42
42
43
43
typedef enum {
44
44
STATUS_FREE = 0 ,
45
- STATUS_IN_USE ,
45
+ STATUS_BUSY ,
46
46
STATUS_NEVER_RESET
47
47
} uart_status_t ;
48
48
49
- static uart_status_t uart_status [2 ];
49
+ static uart_status_t uart_status [NUM_UARTS ];
50
50
51
51
void reset_uart (void ) {
52
- for (uint8_t num = 0 ; num < 2 ; num ++ ) {
53
- if (uart_status [num ] == STATUS_IN_USE ) {
52
+ for (uint8_t num = 0 ; num < NUM_UARTS ; num ++ ) {
53
+ if (uart_status [num ] == STATUS_BUSY ) {
54
54
uart_status [num ] = STATUS_FREE ;
55
55
uart_deinit (UART_INST (num ));
56
56
}
@@ -61,39 +61,30 @@ void never_reset_uart(uint8_t num) {
61
61
uart_status [num ] = STATUS_NEVER_RESET ;
62
62
}
63
63
64
- static uint8_t get_free_uart () {
65
- uint8_t num ;
66
- for (num = 0 ; num < 2 ; num ++ ) {
67
- if (uart_status [num ] == STATUS_FREE ) {
68
- break ;
69
- }
70
- if (num ) {
71
- mp_raise_RuntimeError (translate ("All UART peripherals are in use" ));
72
- }
73
- }
74
- return num ;
75
- }
76
-
77
64
static uint8_t pin_init (const uint8_t uart , const mcu_pin_obj_t * pin , const uint8_t pin_type ) {
78
65
if (pin == NULL ) {
79
66
return NO_PIN ;
80
67
}
81
- if (!(((pin -> number & 3 ) == pin_type ) && ((((pin -> number + 4 ) & 8 ) >> 3 ) == uart ))) {
68
+ if (!(((pin -> number % 4 ) == pin_type ) && ((((pin -> number + 4 ) / 8 ) % NUM_UARTS ) == uart ))) {
82
69
mp_raise_ValueError (translate ("Invalid pins" ));
83
70
}
84
71
claim_pin (pin );
85
72
gpio_set_function (pin -> number , GPIO_FUNC_UART );
86
73
return pin -> number ;
87
74
}
88
75
89
- static ringbuf_t ringbuf [2 ];
76
+ static ringbuf_t ringbuf [NUM_UARTS ];
90
77
91
78
static void uart0_callback (void ) {
92
- while (uart_is_readable (uart0 ) && !ringbuf_put (& ringbuf [0 ], (uint8_t )uart_get_hw (uart0 )-> dr )) {}
79
+ while (uart_is_readable (uart0 ) && ringbuf_num_empty (& ringbuf [0 ]) > 0 ) {
80
+ ringbuf_put (& ringbuf [0 ], (uint8_t )uart_get_hw (uart0 )-> dr );
81
+ }
93
82
}
94
83
95
84
static void uart1_callback (void ) {
96
- while (uart_is_readable (uart1 ) && !ringbuf_put (& ringbuf [1 ], (uint8_t )uart_get_hw (uart1 )-> dr )) {}
85
+ while (uart_is_readable (uart1 ) && ringbuf_num_empty (& ringbuf [1 ]) > 0 ) {
86
+ ringbuf_put (& ringbuf [1 ], (uint8_t )uart_get_hw (uart1 )-> dr );
87
+ }
97
88
}
98
89
99
90
void common_hal_busio_uart_construct (busio_uart_obj_t * self ,
@@ -116,7 +107,13 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
116
107
mp_raise_NotImplementedError (translate ("RS485 Not yet supported on this device" ));
117
108
}
118
109
119
- uint8_t uart_id = get_free_uart ();
110
+ uint8_t uart_id = ((((tx != NULL ) ? tx -> number : rx -> number ) + 4 ) / 8 ) % NUM_UARTS ;
111
+
112
+ if (uart_status [uart_id ] != STATUS_FREE ) {
113
+ mp_raise_RuntimeError (translate ("All UART peripherals are in use" ));
114
+ } else {
115
+ uart_status [uart_id ] = STATUS_BUSY ;
116
+ }
120
117
121
118
self -> tx_pin = pin_init (uart_id , tx , 0 );
122
119
self -> rx_pin = pin_init (uart_id , rx , 1 );
@@ -129,7 +126,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
129
126
self -> timeout_ms = timeout * 1000 ;
130
127
131
128
uart_init (self -> uart , self -> baudrate );
132
- uart_set_fifo_enabled (self -> uart , false );
129
+ uart_set_fifo_enabled (self -> uart , true );
133
130
uart_set_format (self -> uart , bits , stop , parity );
134
131
uart_set_hw_flow (self -> uart , (cts != NULL ), (rts != NULL ));
135
132
@@ -144,7 +141,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
144
141
if (!ringbuf_alloc (& ringbuf [uart_id ], receiver_buffer_size , true)) {
145
142
mp_raise_msg (& mp_type_MemoryError , translate ("Failed to allocate RX buffer" ));
146
143
}
147
- if (uart_id ) {
144
+ if (uart_id == 1 ) {
148
145
self -> uart_irq_id = UART1_IRQ ;
149
146
irq_set_exclusive_handler (self -> uart_irq_id , uart1_callback );
150
147
} else {
@@ -166,6 +163,7 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
166
163
}
167
164
uart_deinit (self -> uart );
168
165
ringbuf_free (& ringbuf [self -> uart_id ]);
166
+ uart_status [self -> uart_id ] = STATUS_FREE ;
169
167
reset_pin_number (self -> tx_pin );
170
168
reset_pin_number (self -> rx_pin );
171
169
reset_pin_number (self -> cts_pin );
@@ -183,7 +181,7 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
183
181
}
184
182
185
183
while (len > 0 ) {
186
- if (uart_is_writable (self -> uart )) {
184
+ while (uart_is_writable (self -> uart ) && len > 0 ) {
187
185
// Write and advance.
188
186
uart_get_hw (self -> uart )-> dr = * data ++ ;
189
187
// Decrease how many chars left to write.
@@ -206,31 +204,40 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
206
204
return 0 ;
207
205
}
208
206
209
- size_t total_read = 0 ;
210
- uint64_t start_ticks = supervisor_ticks_ms64 ();
211
-
212
- // Busy-wait for all bytes received or timeout
213
- while (len > 0 && (supervisor_ticks_ms64 () - start_ticks < self -> timeout_ms )) {
214
- // Reset the timeout on every character read.
215
- if (ringbuf_num_filled (& ringbuf [self -> uart_id ])) {
216
- // Prevent conflict with uart irq.
217
- irq_set_enabled (self -> uart_irq_id , false);
218
- // Copy as much received data as available, up to len bytes.
219
- size_t num_read = ringbuf_get_n (& ringbuf [self -> uart_id ], data , len );
220
- // Re-enable irq.
221
- irq_set_enabled (self -> uart_irq_id , true);
222
- len -= num_read ;
223
- data += num_read ;
224
- total_read += num_read ;
225
- start_ticks = supervisor_ticks_ms64 ();
226
- }
227
- RUN_BACKGROUND_TASKS ;
228
- // Allow user to break out of a timeout with a KeyboardInterrupt.
229
- if (mp_hal_is_interrupted ()) {
230
- return 0 ;
207
+ // Prevent conflict with uart irq.
208
+ irq_set_enabled (self -> uart_irq_id , false);
209
+
210
+ // Copy as much received data as available, up to len bytes.
211
+ size_t total_read = ringbuf_get_n (& ringbuf [self -> uart_id ], data , len );
212
+
213
+ // Check if we still need to read more data.
214
+ if (len > total_read ) {
215
+ len -= total_read ;
216
+ uint64_t start_ticks = supervisor_ticks_ms64 ();
217
+ // Busy-wait until timeout or until we've read enough chars.
218
+ while (len > 0 && (supervisor_ticks_ms64 () - start_ticks < self -> timeout_ms )) {
219
+ if (uart_is_readable (self -> uart )) {
220
+ // Read and advance.
221
+ * data ++ = uart_get_hw (self -> uart )-> dr ;
222
+
223
+ // Adjust the counters.
224
+ len -- ;
225
+ total_read ++ ;
226
+
227
+ // Reset the timeout on every character read.
228
+ start_ticks = supervisor_ticks_ms64 ();
229
+ }
230
+ RUN_BACKGROUND_TASKS ;
231
+ // Allow user to break out of a timeout with a KeyboardInterrupt.
232
+ if (mp_hal_is_interrupted ()) {
233
+ return 0 ;
234
+ }
231
235
}
232
236
}
233
237
238
+ // Re-enable irq.
239
+ irq_set_enabled (self -> uart_irq_id , true);
240
+
234
241
if (total_read == 0 ) {
235
242
* errcode = EAGAIN ;
236
243
return MP_STREAM_ERROR ;
0 commit comments