5252
5353static uint32_t get_nrf_baud (uint32_t baudrate );
5454
55+ static uint16_t ringbuf_count (ringbuf_t * r )
56+ {
57+ volatile int count = r -> iput - r -> iget ;
58+ if ( count < 0 ) {
59+ count += r -> size ;
60+ }
61+
62+ return (uint16_t ) count ;
63+ }
64+
65+ static void ringbuf_clear (ringbuf_t * r )
66+ {
67+ r -> iput = r -> iget = 0 ;
68+ }
69+
5570static void uart_callback_irq (const nrfx_uarte_event_t * event , void * context ) {
5671 busio_uart_obj_t * self = (busio_uart_obj_t * ) context ;
5772
5873 switch ( event -> type ) {
5974 case NRFX_UARTE_EVT_RX_DONE :
60- self -> rx_count = event -> data .rxtx .bytes ;
75+ for (uint8_t i = 0 ; i < event -> data .rxtx .bytes ; i ++ ) {
76+ if ( ringbuf_put (& self -> rbuf , event -> data .rxtx .p_data [i ]) < 0 ) {
77+ // if full overwrite old data
78+ (void ) ringbuf_get (& self -> rbuf );
79+ ringbuf_put (& self -> rbuf , event -> data .rxtx .p_data [i ]);
80+ }
81+ }
82+
83+ // keep receiving
84+ _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , & self -> rx_char , 1 ));
6185 break ;
6286
6387 case NRFX_UARTE_EVT_TX_DONE :
88+ // nothing to do
6489 break ;
6590
6691 case NRFX_UARTE_EVT_ERROR :
67- if ( self -> rx_count == -1 ) {
68- self -> rx_count = 0 ;
69- }
92+ // Handle error
7093 break ;
7194
7295 default :
@@ -110,12 +133,15 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
110133
111134 // Init buffer for rx
112135 if ( rx != mp_const_none ) {
113- self -> buffer = (uint8_t * ) gc_alloc (receiver_buffer_size , false, false);
114- if ( !self -> buffer ) {
136+ self -> rbuf .buf = (uint8_t * ) gc_alloc (receiver_buffer_size , false, false);
137+
138+ if ( !self -> rbuf .buf ) {
115139 nrfx_uarte_uninit (& self -> uarte );
116140 mp_raise_msg (& mp_type_MemoryError , translate ("Failed to allocate RX buffer" ));
117141 }
118- self -> bufsize = receiver_buffer_size ;
142+
143+ self -> rbuf .size = receiver_buffer_size ;
144+ self -> rbuf .iget = self -> rbuf .iput = 0 ;
119145
120146 self -> rx_pin_number = rx -> number ;
121147 claim_pin (rx );
@@ -131,9 +157,8 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
131157 self -> baudrate = baudrate ;
132158 self -> timeout_ms = timeout * 1000 ;
133159
134- // queue 1-byte transfer for rx_characters_available()
135- self -> rx_count = -1 ;
136- _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , self -> buffer , 1 ));
160+ // Initial wait for incoming byte
161+ _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , & self -> rx_char , 1 ));
137162}
138163
139164bool common_hal_busio_uart_deinited (busio_uart_obj_t * self ) {
@@ -147,7 +172,10 @@ void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
147172 reset_pin_number (self -> rx_pin_number );
148173 self -> tx_pin_number = NO_PIN ;
149174 self -> rx_pin_number = NO_PIN ;
150- gc_free (self -> buffer );
175+
176+ gc_free (self -> rbuf .buf );
177+ self -> rbuf .size = 0 ;
178+ self -> rbuf .iput = self -> rbuf .iget = 0 ;
151179 }
152180}
153181
@@ -157,48 +185,33 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
157185 mp_raise_ValueError (translate ("No RX pin" ));
158186 }
159187
160- size_t remain = len ;
188+ size_t rx_bytes = 0 ;
161189 uint64_t start_ticks = ticks_ms ;
162190
163- while ( 1 ) {
164- // Wait for on-going transfer to complete
165- while ( (self -> rx_count == -1 ) && (ticks_ms - start_ticks < self -> timeout_ms ) ) {
191+ // Wait for all bytes received or timeout
192+ while ( (ringbuf_count (& self -> rbuf ) < len ) && (ticks_ms - start_ticks < self -> timeout_ms ) ) {
166193#ifdef MICROPY_VM_HOOK_LOOP
167- MICROPY_VM_HOOK_LOOP ;
168- // Allow user to break out of a timeout with a KeyboardInterrupt.
169- if (mp_hal_is_interrupted ()) {
170- return 0 ;
171- }
172- #endif
173- }
174-
175- // copy received data
176- if ( self -> rx_count > 0 ) {
177- memcpy (data , self -> buffer , self -> rx_count );
178- data += self -> rx_count ;
179- remain -= self -> rx_count ;
180-
181- self -> rx_count = 0 ;
194+ MICROPY_VM_HOOK_LOOP ;
195+ // Allow user to break out of a timeout with a KeyboardInterrupt.
196+ if ( mp_hal_is_interrupted () ) {
197+ return 0 ;
182198 }
199+ #endif
200+ }
183201
184- // exit if complete or time up
185- if ( !remain || !(ticks_ms - start_ticks < self -> timeout_ms ) ) {
186- break ;
187- }
202+ // prevent conflict with uart irq
203+ NVIC_DisableIRQ (nrfx_get_irq_number (self -> uarte .p_reg ));
188204
189- // prepare next receiving
190- const size_t cnt = MIN (self -> bufsize , remain );
191- self -> rx_count = -1 ;
192- _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , self -> buffer , cnt ));
205+ // copy received data
206+ rx_bytes = ringbuf_count (& self -> rbuf );
207+ rx_bytes = MIN (rx_bytes , len );
208+ for ( uint16_t i = 0 ; i < rx_bytes ; i ++ ) {
209+ data [i ] = ringbuf_get (& self -> rbuf );
193210 }
194211
195- // queue 1-byte transfer for rx_characters_available()
196- if ( self -> rx_count == 0 ) {
197- self -> rx_count = -1 ;
198- _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , self -> buffer , 1 ));
199- }
212+ NVIC_EnableIRQ (nrfx_get_irq_number (self -> uarte .p_reg ));
200213
201- return len - remain ;
214+ return rx_bytes ;
202215}
203216
204217// Write characters.
@@ -258,15 +271,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat
258271}
259272
260273uint32_t common_hal_busio_uart_rx_characters_available (busio_uart_obj_t * self ) {
261- return ( self -> rx_count > 0 ) ? self -> rx_count : 0 ;
274+ return ringbuf_count ( & self -> rbuf ) ;
262275}
263276
264277void common_hal_busio_uart_clear_rx_buffer (busio_uart_obj_t * self ) {
265- // Discard received byte, and queue 1-byte transfer for rx_characters_available()
266- if ( self -> rx_count > 0 ) {
267- self -> rx_count = -1 ;
268- _VERIFY_ERR (nrfx_uarte_rx (& self -> uarte , self -> buffer , 1 ));
269- }
278+ // prevent conflict with uart irq
279+ NVIC_DisableIRQ (nrfx_get_irq_number (self -> uarte .p_reg ));
280+ ringbuf_clear (& self -> rbuf );
281+ NVIC_EnableIRQ (nrfx_get_irq_number (self -> uarte .p_reg ));
270282}
271283
272284bool common_hal_busio_uart_ready_to_tx (busio_uart_obj_t * self ) {
0 commit comments