52
52
53
53
static uint32_t get_nrf_baud (uint32_t baudrate );
54
54
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
+
55
70
static void uart_callback_irq (const nrfx_uarte_event_t * event , void * context ) {
56
71
busio_uart_obj_t * self = (busio_uart_obj_t * ) context ;
57
72
58
73
switch ( event -> type ) {
59
74
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 ));
61
85
break ;
62
86
63
87
case NRFX_UARTE_EVT_TX_DONE :
88
+ // nothing to do
64
89
break ;
65
90
66
91
case NRFX_UARTE_EVT_ERROR :
67
- if ( self -> rx_count == -1 ) {
68
- self -> rx_count = 0 ;
69
- }
92
+ // Handle error
70
93
break ;
71
94
72
95
default :
@@ -110,12 +133,15 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
110
133
111
134
// Init buffer for rx
112
135
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 ) {
115
139
nrfx_uarte_uninit (& self -> uarte );
116
140
mp_raise_msg (& mp_type_MemoryError , translate ("Failed to allocate RX buffer" ));
117
141
}
118
- self -> bufsize = receiver_buffer_size ;
142
+
143
+ self -> rbuf .size = receiver_buffer_size ;
144
+ self -> rbuf .iget = self -> rbuf .iput = 0 ;
119
145
120
146
self -> rx_pin_number = rx -> number ;
121
147
claim_pin (rx );
@@ -131,9 +157,8 @@ void common_hal_busio_uart_construct (busio_uart_obj_t *self,
131
157
self -> baudrate = baudrate ;
132
158
self -> timeout_ms = timeout * 1000 ;
133
159
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 ));
137
162
}
138
163
139
164
bool 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) {
147
172
reset_pin_number (self -> rx_pin_number );
148
173
self -> tx_pin_number = NO_PIN ;
149
174
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 ;
151
179
}
152
180
}
153
181
@@ -157,48 +185,33 @@ size_t common_hal_busio_uart_read
8000
(busio_uart_obj_t *self, uint8_t *data, size_t
157
185
mp_raise_ValueError (translate ("No RX pin" ));
158
186
}
159
187
160
- size_t remain = len ;
188
+ size_t rx_bytes = 0 ;
161
189
uint64_t start_ticks = ticks_ms ;
162
190
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 ) ) {
166
193
#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 ;
182
198
}
199
+ #endif
200
+ }
183
201
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 ));
188
204
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 );
193
210
}
194
211
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 ));
200
213
201
- return len - remain ;
214
+ return rx_bytes ;
202
215
}
203
216
204
217
// Write characters.
@@ -258,15 +271,14 @@ void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrat
258
271
}
259
272
260
273
uint32_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 ) ;
262
275
}
263
276
264
277
void 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 ));
270
282
}
271
283
272
284
bool common_hal_busio_uart_ready_to_tx (busio_uart_obj_t * self ) {
0 commit comments