Просмотр исходного кода

serial console mostly working, but still losing some bytes when transmitting lots.

Thomas Buck 1 год назад
Родитель
Сommit
46f9c9a5da
13 измененных файлов: 98 добавлений и 32 удалений
  1. 2
    1
      README.md
  2. 5
    2
      debug_swd.sh
  3. 3
    1
      flash_swd.sh
  4. 1
    1
      include/console.h
  5. 1
    1
      include/log.h
  6. 3
    0
      include/ring.h
  7. 1
    0
      include/serial.h
  8. 5
    2
      src/console.c
  9. 3
    1
      src/log.c
  10. 2
    0
      src/main.c
  11. 16
    0
      src/ring.c
  12. 54
    21
      src/serial.c
  13. 2
    2
      src/usb_cdc.c

+ 2
- 1
README.md Просмотреть файл

@@ -101,7 +101,8 @@ And also start a GDB debugging session.
101 101
     continue # start program
102 102
 
103 103
 These commands have also been put in the `flash_swd.sh` and `debug_swd.sh` scripts, respectively.
104
-Call them from the `build_debug` folder where you checked out and built OpenOCD.
104
+They require the `build_debug` folder where you checked out and built OpenOCD.
105
+Here are some [general GDB tips](https://beej.us/guide/bggdb/).
105 106
 
106 107
 ## License
107 108
 

+ 5
- 2
debug_swd.sh Просмотреть файл

@@ -1,8 +1,11 @@
1 1
 #!/bin/bash
2 2
 set -euo pipefail
3 3
 
4
+cd "$(dirname "$0")"
5
+
4 6
 echo Starting OpenOCD in background
5
-./openocd/src/openocd -s openocd/tcl -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "cmsis_dap_vid_pid 0x2e8a 0x000c" &
7
+echo "\n\nstarting new openocd" >> openocd.log
8
+./build_debug/openocd/src/openocd -s build_debug/openocd/tcl -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "cmsis_dap_vid_pid 0x2e8a 0x000c" >> openocd.log 2>&1 &
6 9
 OPENOCD_PID=$!
7 10
 
8 11
 # give OpenOCD some time to output stuff
@@ -19,7 +22,7 @@ arm-none-eabi-gdb \
19 22
 -ex "set history save" \
20 23
 -ex "show print pretty" \
21 24
 -ex "target extended-remote localhost:3333" \
22
--ex "tui new-layout default asm 1 src 2 status 0 cmd 1" \
25
+-ex "tui new-layout default src 1 status 1 cmd 2" \
23 26
 -ex "tui layout default" \
24 27
 -ex "tui enable" \
25 28
 $1

+ 3
- 1
flash_swd.sh Просмотреть файл

@@ -1,4 +1,6 @@
1 1
 #!/bin/bash
2 2
 set -euo pipefail
3 3
 
4
-./openocd/src/openocd -s openocd/tcl -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "cmsis_dap_vid_pid 0x2e8a 0x000c" -c "program $1 verify reset exit"
4
+cd "$(dirname "$0")"
5
+
6
+./build_debug/openocd/src/openocd -s build_debug/openocd/tcl -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000" -c "cmsis_dap_vid_pid 0x2e8a 0x000c" -c "program $1 verify reset exit"

+ 1
- 1
include/console.h Просмотреть файл

@@ -21,6 +21,6 @@
21 21
 
22 22
 void cnsl_init(void);
23 23
 void cnsl_run(void);
24
-void cnsl_handle_input(const char *buf, uint32_t len);
24
+void cnsl_handle_input(const uint8_t *buf, size_t len);
25 25
 
26 26
 #endif // __CONSOLE_H__

+ 1
- 1
include/log.h Просмотреть файл

@@ -43,6 +43,6 @@ void log_dump_to_usb(void);
43 43
 void log_dump_to_uart(void);
44 44
 void log_dump_to_disk(void);
45 45
 
46
-void debug_handle_input(char *buff, uint32_t len);
46
+void debug_handle_input(const uint8_t *buff, size_t len);
47 47
 
48 48
 #endif // __LOG_H__

+ 3
- 0
include/ring.h Просмотреть файл

@@ -32,9 +32,12 @@ struct ring_buffer {
32 32
 #define RB_INIT(b, s) { .buffer = b, .size = s, .head = 0, .tail = 0, .full = false }
33 33
 
34 34
 void rb_add(struct ring_buffer *rb, const uint8_t *data, size_t length);
35
+#define rb_push(rb, v) rb_add(rb, &v, 1)
35 36
 size_t rb_len(struct ring_buffer *rb);
36 37
 #define rb_space(rb) ((rb)->size - rb_len(rb))
37 38
 void rb_dump(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t));
39
+void rb_move(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t));
40
+uint8_t rb_peek(struct ring_buffer *rb);
38 41
 uint8_t rb_pop(struct ring_buffer *rb);
39 42
 
40 43
 #endif // __RING_BUFFER_H__

+ 1
- 0
include/serial.h Просмотреть файл

@@ -26,5 +26,6 @@
26 26
 void serial_init(void);
27 27
 void serial_write(const uint8_t *buf, size_t count);
28 28
 void serial_set_reroute(bool reroute);
29
+void serial_run(void);
29 30
 
30 31
 #endif // __SERIAL_H__

+ 5
- 2
src/console.c Просмотреть файл

@@ -35,6 +35,7 @@
35 35
 #include "lcd.h"
36 36
 #include "image.h"
37 37
 #include "volcano.h"
38
+#include "serial.h"
38 39
 
39 40
 #define CNSL_BUFF_SIZE 1024
40 41
 #define CNSL_REPEAT_MS 500
@@ -303,7 +304,7 @@ void cnsl_run(void) {
303 304
     }
304 305
 }
305 306
 
306
-void cnsl_handle_input(const char *buf, uint32_t len) {
307
+void cnsl_handle_input(const uint8_t *buf, size_t len) {
307 308
     if ((cnsl_buff_pos + len) > CNSL_BUFF_SIZE) {
308 309
         debug("error: console input buffer overflow! %lu > %u", cnsl_buff_pos + len, CNSL_BUFF_SIZE);
309 310
         cnsl_init();
@@ -312,7 +313,7 @@ void cnsl_handle_input(const char *buf, uint32_t len) {
312 313
     memcpy(cnsl_line_buff + cnsl_buff_pos, buf, len);
313 314
     cnsl_buff_pos += len;
314 315
 
315
-    // handle backspace
316
+    // handle backspace and local echo
316 317
     for (ssize_t i = cnsl_buff_pos - len; i < (ssize_t)cnsl_buff_pos; i++) {
317 318
         if ((cnsl_line_buff[i] == '\b') || (cnsl_line_buff[i] == 0x7F)) {
318 319
             if (i > 0) {
@@ -330,11 +331,13 @@ void cnsl_handle_input(const char *buf, uint32_t len) {
330 331
             }
331 332
 
332 333
             usb_cdc_write((const uint8_t *)"\b \b", 3);
334
+            serial_write((const uint8_t *)"\b \b", 3);
333 335
 
334 336
             // check for another backspace in this space
335 337
             i--;
336 338
         } else {
337 339
             usb_cdc_write((const uint8_t *)(cnsl_line_buff + i), 1);
340
+            serial_write((const uint8_t *)(cnsl_line_buff + i), 1);
338 341
         }
339 342
     }
340 343
 

+ 3
- 1
src/log.c Просмотреть файл

@@ -100,6 +100,7 @@ void debug_log_va(bool log, const char *format, va_list args) {
100 100
     }
101 101
     if ((l > 0) && (l <= (int)sizeof(line_buff))) {
102 102
         usb_cdc_write(line_buff, l);
103
+        serial_write(line_buff, l);
103 104
 
104 105
         if (log) {
105 106
             add_to_log(line_buff, l);
@@ -114,7 +115,7 @@ void debug_log(bool log, const char* format, ...) {
114 115
     va_end(args);
115 116
 }
116 117
 
117
-void debug_handle_input(char *buff, uint32_t len) {
118
+void debug_handle_input(const uint8_t *buff, size_t len) {
118 119
     (void)buff;
119 120
 
120 121
     if (len > 0) {
@@ -135,6 +136,7 @@ void debug_wait_input(const char *format, ...) {
135 136
     while (!got_input) {
136 137
         watchdog_update();
137 138
         usb_run();
139
+        serial_run();
138 140
     }
139 141
 
140 142
     usb_cdc_set_reroute(false);

+ 2
- 0
src/main.c Просмотреть файл

@@ -95,7 +95,9 @@ int main(void) {
95 95
 
96 96
         heartbeat_run();
97 97
         buttons_run();
98
+
98 99
         usb_run();
100
+        serial_run();
99 101
         cnsl_run();
100 102
 
101 103
         battery_run();

+ 16
- 0
src/ring.c Просмотреть файл

@@ -62,6 +62,22 @@ void rb_dump(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t)) {
62 62
     }
63 63
 }
64 64
 
65
+void rb_move(struct ring_buffer *rb, void (*write)(const uint8_t *, size_t)) {
66
+    rb_dump(rb, write);
67
+    rb->head = 0;
68
+    rb->tail = 0;
69
+    rb->full = false;
70
+}
71
+
72
+uint8_t rb_peek(struct ring_buffer *rb) {
73
+    if (rb_len(rb) == 0) {
74
+        return 0;
75
+    }
76
+
77
+    uint8_t v = rb->buffer[rb->tail];
78
+    return v;
79
+}
80
+
65 81
 uint8_t rb_pop(struct ring_buffer *rb) {
66 82
     if (rb_len(rb) == 0) {
67 83
         return 0;

+ 54
- 21
src/serial.c Просмотреть файл

@@ -1,6 +1,9 @@
1 1
 /*
2 2
  * serial.c
3 3
  *
4
+ * https://github.com/raspberrypi/pico-examples/blob/master/uart/uart_advanced/uart_advanced.c
5
+ * https://forums.raspberrypi.com/viewtopic.php?t=343110
6
+ *
4 7
  * Copyright (c) 2023 Thomas Buck (thomas@xythobuz.de)
5 8
  *
6 9
  * This program is free software: you can redistribute it and/or modify
@@ -28,7 +31,7 @@
28 31
 #define PARITY UART_PARITY_NONE
29 32
 #define STOP_BITS 1
30 33
 
31
-#define UART_HW_FIFO_LEN 32
34
+#define UART_RX_BUFF_LEN 64
32 35
 #define UART_TX_BUFF_LEN 128
33 36
 
34 37
 #include "hardware/uart.h"
@@ -41,37 +44,33 @@
41 44
 #include "ring.h"
42 45
 #include "serial.h"
43 46
 
47
+static uint8_t rx_buff[UART_RX_BUFF_LEN] = {0};
48
+static struct ring_buffer rx = RB_INIT(rx_buff, sizeof(rx_buff));
49
+
44 50
 static uint8_t tx_buff[UART_TX_BUFF_LEN] = {0};
45 51
 static struct ring_buffer tx = RB_INIT(tx_buff, sizeof(tx_buff));
52
+
46 53
 static bool reroute_serial_debug = false;
54
+static bool tx_irq_state = false;
47 55
 
48 56
 static void serial_irq(void) {
49
-    uint8_t buf[UART_HW_FIFO_LEN];
50
-    uint16_t count = 0;
51
-
52 57
     // Rx - read from UART FIFO to local buffer
53
-    while (uart_is_readable(UART_ID)) {
58
+    while (uart_is_readable(UART_ID) && (rb_space(&rx) > 0)) {
54 59
         uint8_t ch = uart_getc(UART_ID);
55
-        buf[count++] = ch;
60
+        rb_push(&rx, ch);
61
+    }
56 62
 
57
-        if (count >= UART_HW_FIFO_LEN) {
63
+    // Tx - write to UART FIFO if needed
64
+    while (uart_is_writable(UART_ID)) {
65
+        if (rb_len(&tx) > 0) {
66
+            uart_putc_raw(UART_ID, rb_pop(&tx));
67
+        } else {
68
+            uart_set_irq_enables(UART_ID, true, false);
69
+            tx_irq_state = false;
58 70
             break;
59 71
         }
60 72
     }
61 73
 
62
-    // Rx - pass local buffer to further processing
63
-    if ((count >= 1) && (buf[0] == ENTER_BOOTLOADER_MAGIC)) {
64
-        reset_to_bootloader();
65
-    } else if (reroute_serial_debug) {
66
-        debug_handle_input((char *)buf, count);
67
-    } else {
68
-        cnsl_handle_input((char *)buf, count);
69
-    }
70
-
71
-    // Tx - write to UART FIFO if needed
72
-    while (uart_is_writable(UART_ID) && (rb_len(&tx) > 0)) {
73
-        uart_putc_raw(UART_ID, rb_pop(&tx));
74
-    }
75 74
 }
76 75
 
77 76
 void serial_init(void) {
@@ -87,11 +86,22 @@ void serial_init(void) {
87 86
     irq_set_exclusive_handler(UART_IRQ, serial_irq);
88 87
     irq_set_enabled(UART_IRQ, true);
89 88
 
90
-    uart_set_irq_enables(UART_ID, true, true);
89
+    uart_set_irq_enables(UART_ID, true, false);
90
+    tx_irq_state = false;
91 91
 }
92 92
 
93 93
 void serial_write(const uint8_t *buf, size_t count) {
94 94
     uart_set_irq_enables(UART_ID, true, false);
95
+    tx_irq_state = false;
96
+
97
+    while ((rb_len(&tx) == 0) && uart_is_writable(UART_ID) && (count > 0)) {
98
+        uart_putc_raw(UART_ID, *buf++);
99
+        count--;
100
+    }
101
+
102
+    if (count == 0) {
103
+        return;
104
+    }
95 105
 
96 106
     size_t off = 0;
97 107
 
@@ -103,16 +113,39 @@ void serial_write(const uint8_t *buf, size_t count) {
103 113
         off += space;
104 114
 
105 115
         uart_set_irq_enables(UART_ID, true, true);
116
+        tx_irq_state = true;
117
+
106 118
         sleep_ms(1);
119
+
107 120
         uart_set_irq_enables(UART_ID, true, false);
121
+        tx_irq_state = false;
108 122
     }
123
+
109 124
 #endif // SERIAL_WRITES_BLOCK_WHEN_BUFFER_FULL
110 125
 
111 126
     rb_add(&tx, buf + off, count);
112 127
 
113 128
     uart_set_irq_enables(UART_ID, true, true);
129
+    tx_irq_state = true;
114 130
 }
115 131
 
116 132
 void serial_set_reroute(bool reroute) {
117 133
     reroute_serial_debug = reroute;
118 134
 }
135
+
136
+void serial_run(void) {
137
+    uart_set_irq_enables(UART_ID, false, tx_irq_state);
138
+
139
+    // Rx - pass local buffer to further processing
140
+    if (rb_len(&rx) >= 1) {
141
+        if (rb_peek(&rx) == ENTER_BOOTLOADER_MAGIC) {
142
+            reset_to_bootloader();
143
+        } else if (reroute_serial_debug) {
144
+            rb_move(&rx, debug_handle_input);
145
+        } else {
146
+            rb_move(&rx, cnsl_handle_input);
147
+        }
148
+    }
149
+
150
+    uart_set_irq_enables(UART_ID, true, tx_irq_state);
151
+}

+ 2
- 2
src/usb_cdc.c Просмотреть файл

@@ -79,9 +79,9 @@ static void cdc_task(void) {
79 79
         if ((count >= 1) && (buf[0] == ENTER_BOOTLOADER_MAGIC)) {
80 80
             reset_to_bootloader();
81 81
         } else if (reroute_cdc_debug) {
82
-            debug_handle_input(buf, count);
82
+            debug_handle_input((const uint8_t *)buf, count);
83 83
         } else {
84
-            cnsl_handle_input(buf, count);
84
+            cnsl_handle_input((const uint8_t *)buf, count);
85 85
         }
86 86
     }
87 87
 }

Загрузка…
Отмена
Сохранить