@@ -98,15 +98,15 @@ typedef struct _machine_hard_uart_buf_t {
98
98
typedef struct _machine_hard_uart_obj_t {
99
99
mp_obj_base_t base ;
100
100
const nrfx_uart_t * p_uart ; // Driver instance
101
- machine_hard_uart_buf_t * buf ;
101
+ machine_hard_uart_buf_t buf ;
102
+ uint16_t timeout ; // timeout waiting for first char (in ms)
103
+ uint16_t timeout_char ; // timeout waiting between chars (in ms)
102
104
} machine_hard_uart_obj_t ;
103
105
104
106
static const nrfx_uart_t instance0 = NRFX_UART_INSTANCE (0 );
105
107
106
- STATIC machine_hard_uart_buf_t machine_hard_uart_buf [1 ];
107
-
108
- STATIC const machine_hard_uart_obj_t machine_hard_uart_obj [] = {
109
- {{& machine_uart_type }, .p_uart = & instance0 , .buf = & machine_hard_uart_buf [0 ]},
108
+ STATIC machine_hard_uart_obj_t machine_hard_uart_obj [] = {
109
+ {{& machine_uart_type }, .p_uart = & instance0 }
110
110
};
111
111
112
112
void uart_init0 (void ) {
@@ -124,45 +124,45 @@ STATIC int uart_find(mp_obj_t id) {
124
124
STATIC void uart_event_handler (nrfx_uart_event_t const * p_event , void * p_context ) {
125
125
machine_hard_uart_obj_t * self = p_context ;
126
126
if (p_event -> type == NRFX_UART_EVT_RX_DONE ) {
127
- int chr = self -> buf -> rx_buf [0 ];
128
- nrfx_uart_rx ( self -> p_uart , & self -> buf -> rx_buf [0 ], 1 ) ;
127
+ nrfx_uart_rx ( self -> p_uart , & self -> buf . rx_buf [0 ], 1 ) ;
128
+ int chr = self -> buf . rx_buf [0 ];
129
129
#if !MICROPY_PY_BLE_NUS && MICROPY_KBD_EXCEPTION
130
130
if (chr == mp_interrupt_char ) {
131
- self -> buf -> rx_ringbuf .iget = 0 ;
132
- self -> buf -> rx_ringbuf .iput = 0 ;
131
+ self -> buf . rx_ringbuf .iget = 0 ;
132
+ self -> buf . rx_ringbuf .iput = 0 ;
133
133
mp_sched_keyboard_interrupt ();
134
134
} else
135
135
#endif
136
136
{
137
- ringbuf_put ((ringbuf_t * )& self -> buf -> rx_ringbuf , chr );
137
+ ringbuf_put ((ringbuf_t * )& self -> buf . rx_ringbuf , chr );
138
138
}
139
139
}
140
140
}
141
141
142
- bool uart_rx_any (const machine_hard_uart_obj_t * self ) {
143
- return self -> buf -> rx_ringbuf .iput != self -> buf -> rx_ringbuf .iget ;
142
+ bool uart_rx_any (machine_hard_uart_obj_t * self ) {
143
+ return self -> buf . rx_ringbuf .iput != self -> buf . rx_ringbuf .iget ;
144
144
}
145
145
146
- int uart_rx_char (const machine_hard_uart_obj_t * self ) {
147
- return ringbuf_get ((ringbuf_t * )& self -> buf -> rx_ringbuf );
146
+ int uart_rx_char (machine_hard_uart_obj_t * self ) {
147
+ return ringbuf_get ((ringbuf_t * )& self -> buf . rx_ringbuf );
148
148
}
149
149
150
- STATIC nrfx_err_t uart_tx_char (const machine_hard_uart_obj_t * self , int c ) {
150
+ STATIC nrfx_err_t uart_tx_char (machine_hard_uart_obj_t * self , int c ) {
151
151
while (nrfx_uart_tx_in_progress (self -> p_uart )) {
152
152
;
153
153
}
154
- self -> buf -> tx_buf [0 ] = c ;
155
- return nrfx_uart_tx (self -> p_uart , & self -> buf -> tx_buf [0 ], 1 );
154
+ self -> buf . tx_buf [0 ] = c ;
155
+ return nrfx_uart_tx (self -> p_uart , & self -> buf . tx_buf [0 ], 1 );
156
156
}
157
157
158
158
159
- void uart_tx_strn (const machine_hard_uart_obj_t * uart_obj , const char * str , uint len ) {
159
+ void uart_tx_strn (machine_hard_uart_obj_t * uart_obj , const char * str , uint len ) {
160
160
for (const char * top = str + len ; str < top ; str ++ ) {
161
161
uart_tx_char (uart_obj , * str );
162
162
}
163
163
}
164
164
165
- void uart_tx_strn_cooked (const machine_hard_uart_obj_t * uart_obj , const char * str , uint len ) {
165
+ void uart_tx_strn_cooked (machine_hard_uart_obj_t * uart_obj , const char * str , uint len ) {
166
166
for (const char * top = str + len ; str < top ; str ++ ) {
167
167
if (* str == '\n' ) {
168
168
uart_tx_char (uart_obj , '\r' );
@@ -184,10 +184,12 @@ STATIC void machine_hard_uart_print(const mp_print_t *print, mp_obj_t self_in, m
184
184
/// - `id`is bus id.
185
185
/// - `baudrate` is the clock rate.
186
186
STATIC mp_obj_t machine_hard_uart_make_new (const mp_obj_type_t * type , size_t n_args , size_t n_kw , const mp_obj_t * all_args ) {
187
- enum { ARG_id , ARG_baudrate };
187
+ enum { ARG_id , ARG_baudrate , ARG_timeout , ARG_timeout_char };
188
188
static const mp_arg_t allowed_args [] = {
189
189
{ MP_QSTR_id , MP_ARG_REQUIRED | MP_ARG_OBJ },
190
190
{ MP_QSTR_baudrate , MP_ARG_REQUIRED | MP_ARG_INT , {.u_int = 9600 } },
191
+ { MP_QSTR_timeout , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 1 } },
192
+ { MP_QSTR_timeout_char , MP_ARG_KW_ONLY | MP_ARG_INT , {.u_int = 1 } },
191
193
};
192
194
193
195
// parse args
@@ -196,7 +198,7 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a
196
198
197
199
// get static peripheral object
198
200
int uart_id = uart_find (args [ARG_id ].u_obj );
199
- const machine_hard_uart_obj_t * self = & machine_hard_uart_obj [uart_id ];
201
+ machine_hard_uart_obj_t * self = & machine_hard_uart_obj [uart_id ];
200
202
201
203
nrfx_uart_config_t config ;
202
204
@@ -238,19 +240,21 @@ STATIC mp_obj_t machine_hard_uart_make_new(const mp_obj_type_t *type, size_t n_a
238
240
config .pselrts = MICROPY_HW_UART1_RTS ;
239
241
config .pselcts = MICROPY_HW_UART1_CTS ;
240
242
#endif
243
+ self -> timeout = args [ARG_timeout ].u_int ;
244
+ self -> timeout_char = args [ARG_timeout_char ].u_int ;
241
245
242
246
// Set context to this instance of UART
243
247
config .p_context = (void * )self ;
244
248
245
249
// Initialise ring buffer
246
- self -> buf -> rx_ringbuf .buf = self -> buf -> rx_ringbuf_array ;
247
- self -> buf -> rx_ringbuf .size = sizeof (self -> buf -> rx_ringbuf_array );
248
- self -> buf -> rx_ringbuf .iget = 0 ;
249
- self -> buf -> rx_ringbuf .iput = 0 ;
250
+ self -> buf . rx_ringbuf .buf = self -> buf . rx_ringbuf_array ;
251
+ self -> buf . rx_ringbuf .size = sizeof (self -> buf . rx_ringbuf_array );
252
+ self -> buf . rx_ringbuf .iget = 0 ;
253
+ self -> buf . rx_ringbuf .iput = 0 ;
250
254
251
255
// Enable event callback and start asynchronous receive
252
256
nrfx_uart_init (self -> p_uart , & config , uart_event_handler );
253
- nrfx_uart_rx (self -> p_uart , & self -> buf -> rx_buf [0 ], 1 );
257
+ nrfx_uart_rx (self -> p_uart , & self -> buf . rx_buf [0 ], 1 );
254
258
255
259
#if NRFX_UART_ENABLED
256
260
nrfx_uart_rx_enable (self -> p_uart );
@@ -286,20 +290,29 @@ STATIC mp_obj_t machine_hard_uart_readchar(mp_obj_t self_in) {
286
290
}
287
291
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_hard_uart_readchar_obj , machine_hard_uart_readchar );
288
292
293
+ // uart.any()
294
+ STATIC mp_obj_t machine_uart_any (mp_obj_t self_in ) {
295
+ machine_hard_uart_obj_t * self = self_in ;
296
+ return MP_OBJ_NEW_SMALL_INT (ringbuf_avail ((ringbuf_t * )& self -> buf .rx_ringbuf ));
297
+ }
298
+ STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_uart_any_obj , machine_uart_any );
299
+
289
300
// uart.sendbreak()
290
301
STATIC mp_obj_t machine_hard_uart_sendbreak (mp_obj_t self_in ) {
291
302
return mp_const_none ;
292
303
}
293
304
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_hard_uart_sendbreak_obj , machine_hard_uart_sendbreak );
294
305
295
- // Since uart.write() waits up to the last byte, uart. txdone() always returns True.
306
+ // uart.txdone()
296
307
STATIC mp_obj_t machine_uart_txdone (mp_obj_t self_in ) {
297
- return mp_const_true ;
308
+ machine_hard_uart_obj_t * self = self_in ;
309
+ return mp_obj_new_bool (!nrfx_uart_tx_in_progress (self -> p_uart ));
298
310
}
299
311
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (machine_uart_txdone_obj , machine_uart_txdone );
300
312
301
313
STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table [] = {
302
314
// instance methods
315
+ { MP_ROM_QSTR (MP_QSTR_any ), MP_ROM_PTR (& machine_uart_any_obj ) },
303
316
{ MP_ROM_QSTR (MP_QSTR_read ), MP_ROM_PTR (& mp_stream_read_obj ) },
304
317
{ MP_ROM_QSTR (MP_QSTR_readline ), MP_ROM_PTR (& mp_stream_unbuffered_readline_obj ) },
305
318
{ MP_ROM_QSTR (MP_QSTR_readinto ), MP_ROM_PTR (& mp_stream_readinto_obj ) },
@@ -321,29 +334,38 @@ STATIC const mp_rom_map_elem_t machine_hard_uart_locals_dict_table[] = {
321
334
STATIC MP_DEFINE_CONST_DICT (machine_hard_uart_locals_dict , machine_hard_uart_locals_dict_table );
322
335
323
336
STATIC mp_uint_t machine_hard_uart_read (mp_obj_t self_in , void * buf_in , mp_uint_t size , int * errcode ) {
324
- const machine_hard_uart_obj_t * self = self_in ;
337
+ machine_hard_uart_obj_t * self = self_in ;
325
338
byte * buf = buf_in ;
339
+ uint32_t t = self -> timeout + mp_hal_ticks_ms ();
326
340
327
341
// read the data
328
342
for (size_t i = 0 ; i < size ; i ++ ) {
329
343
while (!uart_rx_any (self )) {
344
+ if ((int32_t )(mp_hal_ticks_ms () - t ) >= 0 ) { // timed out
345
+ if (i == 0 ) {
346
+ * errcode = MP_EAGAIN ;
347
+ return MP_STREAM_ERROR ;
348
+ } else {
349
+ return i ;
350
+ }
351
+ }
352
+ MICROPY_EVENT_POLL_HOOK ;
330
353
}
331
354
buf [i ] = uart_rx_char (self );
355
+ t = self -> timeout_char + mp_hal_ticks_ms ();
332
356
}
333
357
334
358
return size ;
335
359
}
336
360
337
361
STATIC mp_uint_t machine_hard_uart_write (mp_obj_t self_in , const void * buf_in , mp_uint_t size , int * errcode ) {
338
362
machine_hard_uart_obj_t * self = self_in ;
339
- const byte * buf = buf_in ;
340
-
341
- nrfx_err_t err = NRFX_SUCCESS ;
342
- for (int i = 0 ; i < size ; i ++ ) {
343
- err = uart_tx_char (self , (int )((uint8_t * )buf )[i ]);
344
- }
345
363
364
+ nrfx_err_t err = nrfx_uart_tx (self -> p_uart , buf_in , size );
346
365
if (err == NRFX_SUCCESS ) {
366
+ while (nrfx_uart_tx_in_progress (self -> p_uart )) {
367
+ MICROPY_EVENT_POLL_HOOK ;
368
+ }
347
369
// return number of bytes written
348
370
return size ;
349
371
} else {
@@ -355,9 +377,20 @@ STATIC mp_uint_t machine_hard_uart_write(mp_obj_t self_in, const void *buf_in, m
355
377
STATIC mp_uint_t machine_hard_uart_ioctl (mp_obj_t self_in , mp_uint_t request , uintptr_t arg , int * errcode ) {
356
378
machine_hard_uart_obj_t * self = self_in ;
357
379
(void )self ;
380
+ mp_uint_t ret = 0 ;
358
381
359
- if (request == MP_STREAM_FLUSH ) {
360
- // Since uart.write() waits up to the last byte, uart.flush() always succeds.
382
+ if (request == MP_STREAM_POLL ) {
383
+ uintptr_t flags = arg ;
384
+ if ((flags & MP_STREAM_POLL_RD ) && uart_rx_any (self ) != 0 ) {
385
+ ret |= MP_STREAM_POLL_RD ;
386
+ }
387
+ if ((flags & MP_STREAM_POLL_WR ) && !nrfx_uart_tx_in_progress (self -> p_uart )) {
388
+ ret |= MP_STREAM_POLL_WR ;
389
+ }
390
+ } else if (request == MP_STREAM_FLUSH ) {
391
+ while (nrfx_uart_tx_in_progress (self -> p_uart )) {
392
+ MICROPY_EVENT_POLL_HOOK ;
393
+ }
361
394
return 0 ;
362
395
}
363
396
return MP_STREAM_ERROR ;
0 commit comments