Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2011-2012, 2014-2015 Wind River Systems, Inc. |
| 3 | * |
Javier B Perez Hernandez | f7fffae | 2015-10-06 11:00:37 -0500 | [diff] [blame] | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 7 | * |
Javier B Perez Hernandez | f7fffae | 2015-10-06 11:00:37 -0500 | [diff] [blame] | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 9 | * |
Javier B Perez Hernandez | f7fffae | 2015-10-06 11:00:37 -0500 | [diff] [blame] | 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
Anas Nashif | 275ca60 | 2015-12-04 10:09:39 -0500 | [diff] [blame] | 17 | /** |
| 18 | * @file |
| 19 | * @brief UART-driven console |
| 20 | * |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 21 | * |
| 22 | * Serial console driver. |
| 23 | * Hooks into the printk and fputc (for printf) modules. Poll driven. |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 24 | */ |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 25 | |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 26 | #include <nanokernel.h> |
Dan Kalowsky | c02dd34 | 2015-05-28 10:56:47 -0700 | [diff] [blame] | 27 | #include <arch/cpu.h> |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 28 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 29 | #include <stdio.h> |
| 30 | #include <stdint.h> |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 31 | #include <errno.h> |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 32 | #include <ctype.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 33 | |
Daniel Leung | ad2d296 | 2015-08-12 10:17:35 -0700 | [diff] [blame] | 34 | #include <device.h> |
| 35 | #include <init.h> |
| 36 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 37 | #include <board.h> |
Tomasz Bursztyka | 17e06fb | 2015-10-15 09:48:03 +0300 | [diff] [blame] | 38 | #include <uart.h> |
Tomasz Bursztyka | ae09a48 | 2015-04-23 13:12:51 +0300 | [diff] [blame] | 39 | #include <console/uart_console.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 40 | #include <toolchain.h> |
| 41 | #include <sections.h> |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 42 | #include <atomic.h> |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 43 | #include <misc/printk.h> |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 44 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 45 | static struct device *uart_console_dev; |
| 46 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 47 | #if 0 /* NOTUSED */ |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 48 | /** |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 49 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 50 | * @brief Get a character from UART |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 51 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 52 | * @return the character or EOF if nothing present |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 53 | */ |
| 54 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 55 | static int console_in(void) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 56 | { |
| 57 | unsigned char c; |
Dan Kalowsky | da67b29 | 2015-10-20 09:42:33 -0700 | [diff] [blame] | 58 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 59 | if (uart_poll_in(uart_console_dev, &c) < 0) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 60 | return EOF; |
| 61 | else |
| 62 | return (int)c; |
| 63 | } |
| 64 | #endif |
| 65 | |
| 66 | #if defined(CONFIG_PRINTK) || defined(CONFIG_STDOUT_CONSOLE) |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 67 | /** |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 68 | * |
Anas Nashif | f367f07 | 2015-07-01 17:51:40 -0400 | [diff] [blame] | 69 | * @brief Output one character to UART |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 70 | * |
| 71 | * Outputs both line feed and carriage return in the case of a '\n'. |
| 72 | * |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 73 | * @param c Character to output |
| 74 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 75 | * @return The character passed as input. |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 76 | */ |
| 77 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 78 | static int console_out(int c) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 79 | { |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 80 | uart_poll_out(uart_console_dev, (unsigned char)c); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 81 | if ('\n' == c) { |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 82 | uart_poll_out(uart_console_dev, (unsigned char)'\r'); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 83 | } |
| 84 | return c; |
| 85 | } |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 86 | |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 87 | #endif |
| 88 | |
| 89 | #if defined(CONFIG_STDOUT_CONSOLE) |
| 90 | extern void __stdout_hook_install(int (*hook)(int)); |
| 91 | #else |
| 92 | #define __stdout_hook_install(x) \ |
| 93 | do {/* nothing */ \ |
| 94 | } while ((0)) |
| 95 | #endif |
| 96 | |
| 97 | #if defined(CONFIG_PRINTK) |
| 98 | extern void __printk_hook_install(int (*fn)(int)); |
| 99 | #else |
| 100 | #define __printk_hook_install(x) \ |
| 101 | do {/* nothing */ \ |
| 102 | } while ((0)) |
| 103 | #endif |
| 104 | |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 105 | #if defined(CONFIG_CONSOLE_HANDLER) |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 106 | static struct nano_fifo *avail_queue; |
| 107 | static struct nano_fifo *lines_queue; |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 108 | |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 109 | /* Control characters */ |
| 110 | #define ESC 0x1b |
| 111 | #define DEL 0x7f |
| 112 | |
| 113 | /* ANSI escape sequences */ |
| 114 | #define ANSI_ESC '[' |
| 115 | #define ANSI_UP 'A' |
| 116 | #define ANSI_DOWN 'B' |
| 117 | #define ANSI_FORWARD 'C' |
| 118 | #define ANSI_BACKWARD 'D' |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 119 | |
Daniel Leung | 1ad2a56 | 2015-08-05 12:13:36 -0700 | [diff] [blame] | 120 | static int read_uart(struct device *uart, uint8_t *buf, unsigned int size) |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 121 | { |
| 122 | int rx; |
| 123 | |
| 124 | rx = uart_fifo_read(uart, buf, size); |
| 125 | if (rx < 0) { |
| 126 | /* Overrun issue. Stop the UART */ |
| 127 | uart_irq_rx_disable(uart); |
| 128 | |
| 129 | return -EIO; |
| 130 | } |
| 131 | |
| 132 | return rx; |
| 133 | } |
| 134 | |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 135 | static inline void cursor_forward(unsigned int count) |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 136 | { |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 137 | printk("\x1b[%uC", count); |
| 138 | } |
| 139 | |
| 140 | static inline void cursor_backward(unsigned int count) |
| 141 | { |
| 142 | printk("\x1b[%uD", count); |
| 143 | } |
| 144 | |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 145 | static inline void cursor_save(void) |
| 146 | { |
| 147 | printk("\x1b[s"); |
| 148 | } |
| 149 | |
| 150 | static inline void cursor_restore(void) |
| 151 | { |
| 152 | printk("\x1b[u"); |
| 153 | } |
| 154 | |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 155 | static void insert_char(char *pos, char c, uint8_t end) |
| 156 | { |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 157 | char tmp; |
| 158 | |
| 159 | /* Echo back to console */ |
| 160 | uart_poll_out(uart_console_dev, c); |
| 161 | |
| 162 | if (end == 0) { |
| 163 | *pos = c; |
| 164 | return; |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 165 | } |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 166 | |
| 167 | tmp = *pos; |
| 168 | *(pos++) = c; |
| 169 | |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 170 | cursor_save(); |
| 171 | |
| 172 | while (end-- > 0) { |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 173 | uart_poll_out(uart_console_dev, tmp); |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 174 | c = *pos; |
| 175 | *(pos++) = tmp; |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 176 | tmp = c; |
| 177 | } |
| 178 | |
| 179 | /* Move cursor back to right place */ |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 180 | cursor_restore(); |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 181 | } |
| 182 | |
| 183 | static void del_char(char *pos, uint8_t end) |
| 184 | { |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 185 | uart_poll_out(uart_console_dev, '\b'); |
| 186 | |
| 187 | if (end == 0) { |
| 188 | uart_poll_out(uart_console_dev, ' '); |
| 189 | uart_poll_out(uart_console_dev, '\b'); |
| 190 | return; |
| 191 | } |
| 192 | |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 193 | cursor_save(); |
| 194 | |
| 195 | while (end-- > 0) { |
| 196 | *pos = *(pos + 1); |
| 197 | uart_poll_out(uart_console_dev, *(pos++)); |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | uart_poll_out(uart_console_dev, ' '); |
| 201 | |
| 202 | /* Move cursor back to right place */ |
Johan Hedberg | ceba31a | 2015-12-09 12:40:29 +0200 | [diff] [blame] | 203 | cursor_restore(); |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 204 | } |
| 205 | |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 206 | enum { |
| 207 | ESC_ESC, |
| 208 | ESC_ANSI, |
| 209 | ESC_ANSI_FIRST, |
| 210 | ESC_ANSI_VAL, |
| 211 | ESC_ANSI_VAL_2 |
| 212 | }; |
| 213 | |
| 214 | static atomic_t esc_state; |
| 215 | static unsigned int ansi_val, ansi_val_2; |
| 216 | static uint8_t cur, end; |
| 217 | |
| 218 | static void handle_ansi(uint8_t byte) |
| 219 | { |
| 220 | if (atomic_test_and_clear_bit(&esc_state, ESC_ANSI_FIRST)) { |
| 221 | if (!isdigit(byte)) { |
| 222 | ansi_val = 1; |
| 223 | goto ansi_cmd; |
| 224 | } |
| 225 | |
| 226 | atomic_set_bit(&esc_state, ESC_ANSI_VAL); |
| 227 | ansi_val = byte - '0'; |
| 228 | ansi_val_2 = 0; |
| 229 | return; |
| 230 | } |
| 231 | |
| 232 | if (atomic_test_bit(&esc_state, ESC_ANSI_VAL)) { |
| 233 | if (isdigit(byte)) { |
| 234 | if (atomic_test_bit(&esc_state, ESC_ANSI_VAL_2)) { |
| 235 | ansi_val_2 *= 10; |
| 236 | ansi_val_2 += byte - '0'; |
| 237 | } else { |
| 238 | ansi_val *= 10; |
| 239 | ansi_val += byte - '0'; |
| 240 | } |
| 241 | return; |
| 242 | } |
| 243 | |
| 244 | /* Multi value sequence, e.g. Esc[Line;ColumnH */ |
| 245 | if (byte == ';' && |
| 246 | !atomic_test_and_set_bit(&esc_state, ESC_ANSI_VAL_2)) { |
| 247 | return; |
| 248 | } |
| 249 | |
| 250 | atomic_clear_bit(&esc_state, ESC_ANSI_VAL); |
| 251 | atomic_clear_bit(&esc_state, ESC_ANSI_VAL_2); |
| 252 | } |
| 253 | |
| 254 | ansi_cmd: |
| 255 | switch (byte) { |
| 256 | case ANSI_BACKWARD: |
| 257 | if (ansi_val > cur) { |
| 258 | break; |
| 259 | } |
| 260 | |
| 261 | end += ansi_val; |
| 262 | cur -= ansi_val; |
| 263 | cursor_backward(ansi_val); |
| 264 | break; |
| 265 | case ANSI_FORWARD: |
| 266 | if (ansi_val > end) { |
| 267 | break; |
| 268 | } |
| 269 | |
| 270 | end -= ansi_val; |
| 271 | cur += ansi_val; |
| 272 | cursor_forward(ansi_val); |
| 273 | break; |
| 274 | default: |
| 275 | break; |
| 276 | } |
| 277 | |
| 278 | atomic_clear_bit(&esc_state, ESC_ANSI); |
| 279 | } |
| 280 | |
Andrei Emeltchenko | dfa5f23 | 2015-04-23 10:20:32 +0300 | [diff] [blame] | 281 | void uart_console_isr(void *unused) |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 282 | { |
| 283 | ARG_UNUSED(unused); |
| 284 | |
Johan Hedberg | 5ad7803 | 2015-12-07 15:03:20 +0200 | [diff] [blame] | 285 | while (uart_irq_update(uart_console_dev) && |
| 286 | uart_irq_is_pending(uart_console_dev)) { |
| 287 | static struct uart_console_input *cmd; |
| 288 | uint8_t byte; |
| 289 | int rx; |
| 290 | |
| 291 | if (!uart_irq_rx_ready(uart_console_dev)) { |
| 292 | continue; |
| 293 | } |
| 294 | |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 295 | /* Character(s) have been received */ |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 296 | |
Johan Hedberg | 5ad7803 | 2015-12-07 15:03:20 +0200 | [diff] [blame] | 297 | rx = read_uart(uart_console_dev, &byte, 1); |
| 298 | if (rx < 0) { |
| 299 | return; |
| 300 | } |
| 301 | |
| 302 | if (uart_irq_input_hook(uart_console_dev, byte) != 0) { |
| 303 | /* |
| 304 | * The input hook indicates that no further processing |
| 305 | * should be done by this handler. |
| 306 | */ |
| 307 | return; |
| 308 | } |
| 309 | |
| 310 | if (!cmd) { |
| 311 | cmd = nano_isr_fifo_get(avail_queue); |
| 312 | if (!cmd) |
Peter Mitsis | b1c1020 | 2015-09-17 13:22:00 -0400 | [diff] [blame] | 313 | return; |
Johan Hedberg | 5ad7803 | 2015-12-07 15:03:20 +0200 | [diff] [blame] | 314 | } |
Peter Mitsis | b1c1020 | 2015-09-17 13:22:00 -0400 | [diff] [blame] | 315 | |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 316 | /* Handle ANSI escape mode */ |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 317 | if (atomic_test_bit(&esc_state, ESC_ANSI)) { |
| 318 | handle_ansi(byte); |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 319 | continue; |
| 320 | } |
| 321 | |
| 322 | /* Handle escape mode */ |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 323 | if (atomic_test_and_clear_bit(&esc_state, ESC_ESC)) { |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 324 | switch (byte) { |
| 325 | case ANSI_ESC: |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 326 | atomic_set_bit(&esc_state, ESC_ANSI); |
| 327 | atomic_set_bit(&esc_state, ESC_ANSI_FIRST); |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 328 | break; |
| 329 | default: |
| 330 | break; |
| 331 | } |
| 332 | |
| 333 | continue; |
| 334 | } |
| 335 | |
| 336 | /* Handle special control characters */ |
| 337 | if (!isprint(byte)) { |
| 338 | switch (byte) { |
| 339 | case DEL: |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 340 | if (cur > 0) { |
| 341 | del_char(&cmd->line[--cur], end); |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 342 | } |
| 343 | break; |
| 344 | case ESC: |
Johan Hedberg | 8683dc4 | 2015-12-09 11:36:25 +0200 | [diff] [blame^] | 345 | atomic_set_bit(&esc_state, ESC_ESC); |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 346 | break; |
| 347 | case '\r': |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 348 | cmd->line[cur + end] = '\0'; |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 349 | uart_poll_out(uart_console_dev, '\n'); |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 350 | cur = 0; |
| 351 | end = 0; |
Johan Hedberg | f88cccd | 2015-12-08 10:35:04 +0200 | [diff] [blame] | 352 | nano_isr_fifo_put(lines_queue, cmd); |
| 353 | cmd = NULL; |
| 354 | break; |
| 355 | default: |
| 356 | break; |
| 357 | } |
| 358 | |
| 359 | continue; |
| 360 | } |
| 361 | |
Johan Hedberg | 6147fc6 | 2015-12-08 09:26:31 +0200 | [diff] [blame] | 362 | /* Ignore characters if there's no more buffer space */ |
Johan Hedberg | a9f6f89 | 2015-12-08 22:45:12 +0200 | [diff] [blame] | 363 | if (cur + end < sizeof(cmd->line) - 1) { |
| 364 | insert_char(&cmd->line[cur++], byte, end); |
Johan Hedberg | 6147fc6 | 2015-12-08 09:26:31 +0200 | [diff] [blame] | 365 | } |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 366 | } |
| 367 | } |
| 368 | |
Dmitriy Korovkin | 8d06534 | 2015-06-04 11:42:35 -0400 | [diff] [blame] | 369 | IRQ_CONNECT_STATIC(console, CONFIG_UART_CONSOLE_IRQ, |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 370 | CONFIG_UART_CONSOLE_IRQ_PRI, uart_console_isr, 0, |
Dmitriy Korovkin | f142051 | 2015-11-02 18:06:08 -0500 | [diff] [blame] | 371 | UART_IRQ_FLAGS); |
Dmitriy Korovkin | 8d06534 | 2015-06-04 11:42:35 -0400 | [diff] [blame] | 372 | |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 373 | static void console_input_init(void) |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 374 | { |
| 375 | uint8_t c; |
| 376 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 377 | uart_irq_rx_disable(uart_console_dev); |
| 378 | uart_irq_tx_disable(uart_console_dev); |
Juan Manuel Cruz | bc1a79c | 2015-11-30 11:21:13 -0600 | [diff] [blame] | 379 | IRQ_CONFIG(console, uart_irq_get(uart_console_dev)); |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 380 | irq_enable(uart_irq_get(uart_console_dev)); |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 381 | |
| 382 | /* Drain the fifo */ |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 383 | while (uart_irq_rx_ready(uart_console_dev)) { |
| 384 | uart_fifo_read(uart_console_dev, &c, 1); |
Daniel Leung | 1ad2a56 | 2015-08-05 12:13:36 -0700 | [diff] [blame] | 385 | } |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 386 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 387 | uart_irq_rx_enable(uart_console_dev); |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 388 | } |
| 389 | |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 390 | void uart_register_input(struct nano_fifo *avail, struct nano_fifo *lines) |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 391 | { |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 392 | avail_queue = avail; |
| 393 | lines_queue = lines; |
| 394 | |
| 395 | console_input_init(); |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 396 | } |
| 397 | #else |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 398 | #define console_input_init(x) \ |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 399 | do {/* nothing */ \ |
| 400 | } while ((0)) |
Andrei Emeltchenko | 879541a | 2015-05-04 14:43:36 +0300 | [diff] [blame] | 401 | #define uart_register_input(x) \ |
Andrei Emeltchenko | 139c856 | 2015-04-20 11:04:22 +0300 | [diff] [blame] | 402 | do {/* nothing */ \ |
| 403 | } while ((0)) |
| 404 | #endif |
| 405 | |
Anas Nashif | ea0d0b2 | 2015-07-01 17:22:39 -0400 | [diff] [blame] | 406 | /** |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 407 | * |
Daniel Leung | ad2d296 | 2015-08-12 10:17:35 -0700 | [diff] [blame] | 408 | * @brief Install printk/stdout hook for UART console output |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 409 | * |
Anas Nashif | 1362e3c | 2015-07-01 17:29:04 -0400 | [diff] [blame] | 410 | * @return N/A |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 411 | */ |
| 412 | |
Daniel Leung | ad2d296 | 2015-08-12 10:17:35 -0700 | [diff] [blame] | 413 | void uart_console_hook_install(void) |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 414 | { |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 415 | __stdout_hook_install(console_out); |
| 416 | __printk_hook_install(console_out); |
Inaky Perez-Gonzalez | 8ddf82c | 2015-04-10 16:44:37 -0700 | [diff] [blame] | 417 | } |
Daniel Leung | ad2d296 | 2015-08-12 10:17:35 -0700 | [diff] [blame] | 418 | |
| 419 | /** |
| 420 | * |
| 421 | * @brief Initialize one UART as the console/debug port |
| 422 | * |
| 423 | * @return DEV_OK if successful, otherwise failed. |
| 424 | */ |
| 425 | static int uart_console_init(struct device *arg) |
| 426 | { |
| 427 | ARG_UNUSED(arg); |
| 428 | |
Daniel Leung | 08b4fd4 | 2015-12-01 08:42:20 -0800 | [diff] [blame] | 429 | uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME); |
| 430 | |
Daniel Leung | ad2d296 | 2015-08-12 10:17:35 -0700 | [diff] [blame] | 431 | uart_console_hook_install(); |
| 432 | |
| 433 | return DEV_OK; |
| 434 | } |
| 435 | DECLARE_DEVICE_INIT_CONFIG(uart_console, "", uart_console_init, NULL); |
Dmitriy Korovkin | 57f2741 | 2015-10-26 15:56:02 -0400 | [diff] [blame] | 436 | |
| 437 | /* UART consloe initializes after the UART device itself */ |
| 438 | #if defined(CONFIG_EARLY_CONSOLE) |
| 439 | SYS_DEFINE_DEVICE(uart_console, NULL, PRIMARY, CONFIG_UART_CONSOLE_PRIORITY); |
| 440 | #else |
| 441 | SYS_DEFINE_DEVICE(uart_console, NULL, SECONDARY, CONFIG_UART_CONSOLE_PRIORITY); |
| 442 | #endif |