@@ -107,10 +107,17 @@ static const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0,
107
107
108
108
// take all bytes from the fifo and store them in the buffer
109
109
static void uart_drain_rx_fifo (machine_uart_obj_t * self , Sercom * uart ) {
110
+ uint8_t bits = self -> bits ;
110
111
while (uart -> USART .INTFLAG .bit .RXC != 0 ) {
111
- if (ringbuf_free (& self -> read_buffer ) > 0 ) {
112
- // get a byte from uart and put into the buffer
113
- ringbuf_put (& (self -> read_buffer ), uart -> USART .DATA .bit .DATA );
112
+ if (ringbuf_free (& self -> read_buffer ) >= (bits <= 8 ? 1 : 2 )) {
113
+ // get a word from uart and put into the buffer
114
+ if (bits <= 8 ) {
115
+ ringbuf_put (& (self -> read_buffer ), uart -> USART .DATA .bit .DATA );
116
+ } else {
117
+ uint16_t data = uart -> USART .DATA .bit .DATA ;
118
+ ringbuf_put (& (self -> read_buffer ), data );
119
+ ringbuf_put (& (self -> read_buffer ), data >> 8 );
120
+ }
114
121
} else {
115
122
// if the buffer is full, disable the RX interrupt
116
123
// allowing RTS to come up. It will be re-enabled by the next read
@@ -150,7 +157,12 @@ void common_uart_irq_handler(int uart_id) {
150
157
#if MICROPY_HW_UART_TXBUF
151
158
// handle the outgoing data
152
159
if (ringbuf_avail (& self -> write_buffer ) > 0 ) {
153
- uart -> USART .DATA .bit .DATA = ringbuf_get (& self -> write_buffer );
160
+ if (self -> bits <= 8 ) {
161
+ uart -> USART .DATA .bit .DATA = ringbuf_get (& self -> write_buffer );
162
+ } else {
163
+ uart -> USART .DATA .bit .DATA =
164
+ ringbuf_get (& self -> write_buffer ) | (ringbuf_get (& self -> write_buffer ) << 8 );
165
+ }
154
166
} else {
155
167
#if MICROPY_PY_MACHINE_UART_IRQ
156
168
// Set the TXIDLE flag
@@ -274,6 +286,17 @@ void machine_uart_set_baudrate(mp_obj_t self_in, uint32_t baudrate) {
274
286
275
287
static void mp_machine_uart_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
276
288
machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
289
+ size_t rxbuf_len = self -> read_buffer .size - 1 ;
290
+ #if MICROPY_HW_UART_TXBUF
291
+ size_t txbuf_len = self -> write_buffer .size - 1 ;
292
+ #endif
293
+ if (self -> bits > 8 ) {
294
+ rxbuf_len /= 2 ;
295
+ #if MICROPY_HW_UART_TXBUF
296
+ txbuf_len /= 2 ;
297
+ #endif
298
+ }
299
+
277
300
mp_printf (print , "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, "
278
301
"timeout=%u, timeout_char=%u, rxbuf=%d"
279
302
#if MICROPY_HW_UART_TXBUF
@@ -287,9 +310,9 @@ static void mp_machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_
287
310
#endif
288
311
")" ,
289
312
self -> id , self -> baudrate , self -> bits , _parity_name [self -> parity ],
290
- self -> stop + 1 , self -> timeout , self -> timeout_char , self -> read_buffer . size - 1
313
+ self -> stop + 1 , self -> timeout , self -> timeout_char , rxbuf_len
291
314
#if MICROPY_HW_UART_TXBUF
292
- , self -> write_buffer . size - 1
315
+ , txbuf_len
293
316
#endif
294
317
#if MICROPY_HW_UART_RTSCTS
295
318
, self -> rts != 0xff ? pin_find_by_id (self -> rts )-> name : MP_QSTR_None
@@ -411,6 +434,14 @@ static void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args,
411
434
}
412
435
}
413
436
#endif
437
+
438
+ // Double the buffer lengths for 9 bit transfer
439
+ if (self -> bits > 8 ) {
440
+ rxbuf_len *= 2 ;
441
+ #if MICROPY_HW_UART_TXBUF
442
+ txbuf_len *= 2 ;
443
+ #endif
444
+ }
414
445
// Initialise the UART peripheral if any arguments given, or it was not initialised previously.
415
446
if (n_args > 0 || kw_args -> used > 0 || self -> new ) {
416
447
self -> new = false;
@@ -619,7 +650,12 @@ static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
619
650
uint64_t timeout_char = self -> timeout_char ;
620
651
uint8_t * dest = buf_in ;
621
652
622
- for (size_t i = 0 ; i < size ; i ++ ) {
653
+ // Check that size is even for 9 bit transfers.
654
+ if ((self -> bits >= 9 ) && (size & 1 )) {
655
+ * errcode = MP_EIO ;
656
+ return MP_STREAM_ERROR ;
657
+ }
658
+ for (size_t i = 0 ; i < size ;) {
623
659
// Wait for the first/next character
624
660
while (ringbuf_avail (& self -> read_buffer ) == 0 ) {
625
661
if (mp_hal_ticks_ms_64 () > t ) { // timed out
@@ -633,6 +669,11 @@ static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
633
669
MICROPY_EVENT_POLL_HOOK
634
670
}
635
671
* dest ++ = ringbuf_get (& (self -> read_buffer ));
672
+ i ++ ;
673
+ if (self -> bits >= 9 && i < size ) {
674
+ * dest ++ = ringbuf_get (& (self -> read_buffer ));
675
+ i ++ ;
676
+ }
636
677
t = mp_hal_ticks_ms_64 () + timeout_char ;
637
678
// (Re-)Enable RXC interrupt
638
679
if ((uart -> USART .INTENSET .reg & SERCOM_USART_INTENSET_RXC ) == 0 ) {
@@ -647,12 +688,19 @@ static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
647
688
size_t i = 0 ;
648
689
const uint8_t * src = buf_in ;
649
690
Sercom * uart = sercom_instance [self -> id ];
650
-
651
691
uint64_t t = mp_hal_ticks_ms_64 () + self -> timeout ;
692
+ uint8_t bits = self -> bits ;
693
+ // Check that size is even for 9 bit transfers.
694
+ if ((bits >= 9 ) && (size & 1 )) {
695
+ * errcode = MP_EIO ;
696
+ return MP_STREAM_ERROR ;
697
+ }
698
+
652
699
#if MICROPY_HW_UART_TXBUF
653
700
654
701
#if MICROPY_PY_MACHINE_UART_IRQ
655
702
// Prefill the FIFO to get rid of the initial IRQ_TXIDLE event
703
+ // Do not care for 9 Bit transfer here since the UART is not yet started.
656
704
while (i < size && ringbuf_free (& (self -> write_buffer )) > 0 ) {
657
705
ringbuf_put (& (self -> write_buffer ), * src ++ );
658
706
i ++ ;
@@ -672,8 +720,16 @@ static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
672
720
}
673
721
MICROPY_EVENT_POLL_HOOK
674
722
}
675
- ringbuf_put (& (self -> write_buffer ), * src ++ );
676
- i ++ ;
723
+ if (bits >= 9 ) {
724
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION ();
725
+ ringbuf_put (& (self -> write_buffer ), * src ++ );
726
+ ringbuf_put (& (self -> write_buffer ), * src ++ );
727
+ i += 2 ;
728
+ MICROPY_END_ATOMIC_SECTION (atomic_state );
729
+ } else {
730
+ ringbuf_put (& (self -> write_buffer ), * src ++ );
731
+ i += 1 ;
732
+ }
677
733
uart -> USART .INTENSET .reg = SERCOM_USART_INTENSET_DRE ; // kick off the IRQ
678
734
}
679
735
@@ -691,7 +747,13 @@ static mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
691
747
}
692
748
MICROPY_EVENT_POLL_HOOK
693
749
}
694
- uart -> USART .DATA .bit .DATA = * src ++ ;
750
+ if (self -> bits > 8 && i < (size - 1 )) {
751
+ uart -> USART .DATA .bit .DATA = * (uint16_t * )src ;
752
+ i ++ ;
753
+ src += 2 ;
754
+ } else {
755
+ uart -> USART .DATA .bit .DATA = * src ++ ;
756
+ }
695
757
i ++ ;
696
758
}
697
759
#endif
0 commit comments