80
80
81
81
#define UART_HWCONTROL_CTS (1)
82
82
#define UART_HWCONTROL_RTS (2)
83
+ // OR-ed IRQ flags which are allowed to be used by the user
84
+ #define MP_UART_ALLOWED_FLAGS (UART_UARTMIS_RTMIS_BITS | UART_UARTMIS_TXMIS_BITS | UART_UARTMIS_BEMIS_BITS)
85
+ #define UART_FIFO_SIZE_RX (32)
86
+ #define UART_FIFO_TRIGGER_LEVEL_RX (24)
83
87
84
88
static mutex_t write_mutex_0 ;
85
89
static mutex_t write_mutex_1 ;
@@ -111,12 +115,15 @@ typedef struct _machine_uart_obj_t {
111
115
mutex_t * read_mutex ;
112
116
ringbuf_t write_buffer ;
113
117
mutex_t * write_mutex ;
118
+ uint16_t mp_irq_trigger ; // user IRQ trigger mask
119
+ uint16_t mp_irq_flags ; // user IRQ active IRQ flags
120
+ mp_irq_obj_t * mp_irq_obj ; // user IRQ object
114
121
} machine_uart_obj_t ;
115
122
116
123
static machine_uart_obj_t machine_uart_obj [] = {
117
124
{{& machine_uart_type }, uart0 , 0 , 0 , DEFAULT_UART_BITS , UART_PARITY_NONE , DEFAULT_UART_STOP ,
118
125
MICROPY_HW_UART0_TX , MICROPY_HW_UART0_RX , MICROPY_HW_UART0_CTS , MICROPY_HW_UART0_RTS ,
119
- 0 , 0 , 0 , 0 , {NULL , 1 , 0 , 0 }, & read_mutex_0 , {NULL , 1 , 0 , 0 }, & write_mutex_0 },
126
+ 0 , 0 , 0 , 0 , {NULL , 1 , 0 , 0 }, & read_mutex_0 , {NULL , 1 , 0 , 0 }, & write_mutex_0 , 0 , 0 , NULL },
120
127
{{& machine_uart_type }, uart1 , 1 , 0 , DEFAULT_UART_BITS , UART_PARITY_NONE , DEFAULT_UART_STOP ,
121
128
MICROPY_HW_UART1_TX , MICROPY_HW_UART1_RX , MICROPY_HW_UART1_CTS , MICROPY_HW_UART1_RTS ,
122
129
0 , 0 , 0 , 0 , {NULL , 1 , 0 , 0 }, & read_mutex_1 , {NULL , 1 , 0 , 0 }, & write_mutex_1 },
@@ -144,14 +151,15 @@ static inline void read_mutex_unlock(machine_uart_obj_t *u) {
144
151
mutex_exit (u -> read_mutex );
145
152
}
146
153
147
- // take all bytes from the fifo and store them in the buffer
148
- static void uart_drain_rx_fifo (machine_uart_obj_t * self ) {
154
+ // take at most max_items bytes from the fifo and store them in the buffer
155
+ static void uart_drain_rx_fifo (machine_uart_obj_t * self , uint32_t max_items ) {
149
156
if (read_mutex_try_lock (self )) {
150
- while (uart_is_readable (self -> uart ) && ringbuf_free (& self -> read_buffer ) > 0 ) {
157
+ while (uart_is_readable (self -> uart ) && ringbuf_free (& self -> read_buffer ) > 0 && max_items > 0 ) {
151
158
// Get a byte from uart and put into the buffer. Every entry from
152
159
// the FIFO is accompanied by 4 error bits, that may be used for
153
160
// error handling.
154
161
uint16_t c = uart_get_hw (self -> uart )-> dr ;
8000
162
+ max_items -= 1 ;
155
163
if (c & UART_UARTDR_OE_BITS ) {
156
164
// Overrun Error: We missed at least one byte. Not much we can do here.
157
165
}
@@ -187,15 +195,30 @@ static void uart_fill_tx_fifo(machine_uart_obj_t *self) {
187
195
}
188
196
189
197
static inline void uart_service_interrupt (machine_uart_obj_t * self ) {
190
- if (uart_get_hw (self -> uart )-> mis & (UART_UARTMIS_RXMIS_BITS | UART_UARTMIS_RTMIS_BITS )) { // rx interrupt?
191
- // clear all interrupt bits but tx
192
- uart_get_hw (self -> uart )-> icr = UART_UARTICR_BITS & (~UART_UARTICR_TXIC_BITS );
193
- uart_drain_rx_fifo (self );
198
+ uint16_t mp_irq_flags = uart_get_hw (self -> uart )-> mis & (UART_UARTMIS_RXMIS_BITS | UART_UARTMIS_RTMIS_BITS );
199
+ if (mp_irq_flags ) { // rx interrupt?
200
+ // clear all interrupt bits but tx and break
201
+ uart_get_hw (self -> uart )-> icr = UART_UARTICR_BITS & ~(UART_UARTICR_TXIC_BITS | UART_UARTICR_BEIC_BITS );
202
+ uart_drain_rx_fifo (self , UART_FIFO_TRIGGER_LEVEL_RX - 1 );
194
203
}
195
204
if (uart_get_hw (self -> uart )-> mis & UART_UARTMIS_TXMIS_BITS ) { // tx interrupt?
196
- // clear all interrupt bits but rx
197
- uart_get_hw (self -> uart )-> icr = UART_UARTICR_BITS & ~(UART_UARTICR_RXIC_BITS | UART_UARTICR_RTIC_BITS );
198
- uart_fill_tx_fifo (self );
205
+ // clear all interrupt bits but rx and break
206
+ uart_get_hw (self -> uart )-> icr = UART_UARTICR_BITS & ~(UART_UARTICR_RXIC_BITS | UART_UARTICR_RTIC_BITS | UART_UARTICR_BEIC_BITS );
207
+ if (ringbuf_avail (& self -> write_buffer ) == 0 ) {
208
+ mp_irq_flags |= UART_UARTMIS_TXMIS_BITS ;
209
+ } else {
210
+ uart_fill_tx_fifo (self );
211
+ }
212
+ }
213
+ if (uart_get_hw (self -> uart )-> mis & UART_UARTMIS_BEMIS_BITS ) { // break interrupt?
214
+ // CLear the event
215
+ hw_set_bits (& uart_get_hw (self -> uart )-> icr , UART_UARTICR_BEIC_BITS );
216
+ mp_irq_flags |= UART_UARTMIS_BEMIS_BITS ;
217
+ }
218
+ // Check the flags to see if the user handler should be called
219
+ if (self -> mp_irq_trigger & mp_irq_flags ) {
220
+ self -> mp_irq_flags = mp_irq_flags ;
221
+ mp_irq_handler (self -> mp_irq_obj );
199
222
}
200
223
}
201
224
@@ -215,14 +238,17 @@ static void uart1_irq_handler(void) {
215
238
{ MP_ROM_QSTR(MP_QSTR_INV_RX), MP_ROM_INT(UART_INVERT_RX) }, \
216
239
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) }, \
217
240
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) }, \
241
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RXIDLE), MP_ROM_INT(UART_UARTMIS_RTMIS_BITS) }, \
242
+ { MP_ROM_QSTR(MP_QSTR_IRQ_TXIDLE), MP_ROM_INT(UART_UARTMIS_TXMIS_BITS) }, \
243
+ { MP_ROM_QSTR(MP_QSTR_IRQ_BREAK), MP_ROM_INT(UART_UARTMIS_BEMIS_BITS) }, \
218
244
219
245
static void mp_machine_uart_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
220
246
machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
221
247
mp_printf (print , "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, "
222
- "txbuf=%d, rxbuf=%d, timeout=%u, timeout_char=%u, invert=%s)" ,
248
+ "txbuf=%d, rxbuf=%d, timeout=%u, timeout_char=%u, invert=%s, irq=%d )" ,
223
249
self -> uart_id , self -> baudrate , self -> bits , _parity_name [self -> parity ],
224
250
self -> stop , self -> tx , self -> rx , self -> write_buffer .size - 1 , self -> read_buffer .size - 1 ,
225
- self -> timeout , self -> timeout_char , _invert_name [self -> invert ]);
251
+ self -> timeout , self -> timeout_char , _invert_name [self -> invert ], self -> mp_irq_trigger );
226
252
}
227
253
228
254
static void mp_machine_uart_init_helper (machine_uart_obj_t * self , size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
@@ -441,11 +467,19 @@ static void mp_machine_uart_deinit(machine_uart_obj_t *self) {
441
467
self -> baudrate = 0 ;
442
468
MP_STATE_PORT (rp2_uart_rx_buffer [self -> uart_id ]) = NULL ;
443
469
MP_STATE_PORT (rp2_uart_tx_buffer [self -> uart_id ]) = NULL ;
470
+ MP_STATE_PORT (rp2_uart_irq_obj )[self -> uart_id ] = NULL ;
471
+ self -> mp_irq_obj = NULL ;
472
+ self -> mp_irq_trigger = 0 ;
473
+ }
474
+
475
+ void machine_uart_deinit_all () {
476
+ mp_machine_uart_deinit ((machine_uart_obj_t * )& machine_uart_obj [0 ]);
477
+ mp_machine_uart_deinit ((machine_uart_obj_t * )& machine_uart_obj [1 ]);
444
478
}
445
479
446
480
static mp_int_t mp_machine_uart_any (machine_uart_obj_t * self ) {
447
481
// get all bytes from the fifo first
448
- uart_drain_rx_fifo (self );
482
+ uart_drain_rx_fifo (self , UART_FIFO_SIZE_RX + 1 );
449
483
return ringbuf_avail (& self -> read_buffer );
450
484
}
451
485
@@ -460,6 +494,77 @@ static void mp_machine_uart_sendbreak(machine_uart_obj_t *self) {
460
494
uart_set_break (self -> uart , false);
461
495
}
462
496
497
+ static void uart_set_irq_level (machine_uart_obj_t * self , uint16_t trigger ) {
498
+ if (trigger & UART_UARTMIS_BEMIS_BITS ) {
499
+ // Enable the break Interrupt
500
+ hw_set_bits (& uart_get_hw (self -> uart )-> imsc , UART_UARTIMSC_BEIM_BITS );
501
+ } else {
502
+ // Disable the break Interrupt
503
+ hw_clear_bits (& uart_get_hw (self -> uart )-> imsc , UART_UARTIMSC_BEIM_BITS );
504
+ }
505
+ if (trigger & UART_UARTMIS_RTMIS_BITS ) {
506
+ // Set the RX trigger level to 3/4 FIFO_size
507
+ hw_write_masked (& uart_get_hw (self -> uart )-> ifls , 0b011 << UART_UARTIFLS_RXIFLSEL_LSB ,
508
+ UART_UARTIFLS_RXIFLSEL_BITS );
509
+ } else {
510
+ // Set the RX trigger level to 1/8 FIFO_size
511
+ hw_write_masked (& uart_get_hw (self -> uart )-> ifls , 0 << UART_UARTIFLS_RXIFLSEL_LSB ,
512
+ UART_UARTIFLS_RXIFLSEL_BITS );
513
+ }
514
+ }
515
+
516
+ static mp_uint_t uart_irq_trigger (mp_obj_t self_in , mp_uint_t new_trigger ) {
517
+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
518
+ self -> mp_irq_trigger = new_trigger ;
519
+ uart_set_irq_level (self , new_trigger );
520
+ return 0 ;
521
+ }
522
+
523
+ static mp_uint_t uart_irq_info (mp_obj_t self_in , mp_uint_t info_type ) {
524
+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
525
+ if (info_type == MP_IRQ_INFO_FLAGS ) {
526
+ return self -> mp_irq_flags ;
527
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS ) {
528
+ return self -> mp_irq_trigger ;
529
+ }
530
+ return 0 ;
531
+ }
532
+
533
+ static const mp_irq_methods_t uart_irq_methods = {
534
+ .trigger = uart_irq_trigger ,
535
+ .info = uart_irq_info ,
536
+ };
537
+
538
+ static mp_irq_obj_t * mp_machine_uart_irq (machine_uart_obj_t * self , bool any_args , mp_arg_val_t * args ) {
539
+ if (self -> mp_irq_obj == NULL ) {
540
+ self -> mp_irq_trigger = 0 ;
541
+ self -> mp_irq_obj = mp_irq_new (& uart_irq_methods , MP_OBJ_FROM_PTR (self ));
542
+ MP_STATE_PORT (rp2_uart_irq_obj )[self -> uart_id ] = self -> mp_irq_obj ;
543
+ }
544
+
545
+ if (any_args ) {
546
+ // Check the handler
547
+ mp_obj_t handler = args [MP_IRQ_ARG_INIT_handler ].u_obj ;
548
+ if (handler != mp_const_none && !mp_obj_is_callable (handler )) {
549
+ mp_raise_ValueError (MP_ERROR_TEXT ("handler must be None or callable" ));
550
+ }
551
+
552
+ // Check the trigger
553
+ mp_uint_t trigger = args [MP_IRQ_ARG_INIT_trigger ].u_int ;
554
+ mp_uint_t not_supported = trigger & ~MP_UART_ALLOWED_FLAGS ;
555
+ if (trigger != 0 && not_supported ) {
556
+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("trigger 0x%04x unsupported" ), not_supported );
557
+ }
558
+
559
+ self -> mp_irq_obj -> handler = handler ;
560
+ self -> mp_irq_obj -> ishard = args [MP_IRQ_ARG_INIT_hard ].u_bool ;
561
+ self -> mp_irq_trigger = trigger ;
562
+ uart_set_irq_level (self , trigger );
563
+ }
564
+
565
+ return self -> mp_irq_obj ;
566
+ }
567
+
463
568
static mp_uint_t mp_machine_uart_read (mp_obj_t self_in , void * buf_in , mp_uint_t size , int * errcode ) {
464
569
machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
465
570
mp_uint_t start = mp_hal_ticks_ms ();
@@ -471,7 +576,7 @@ static mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
471
576
while (ringbuf_avail (& self -> read_buffer ) == 0 ) {
472
577
if (uart_is_readable (self -> uart )) {
473
578
// Force a few incoming bytes to the buffer
474
- uart_drain_rx_fifo (self );
579
+ uart_drain_rx_fifo (self , UART_FIFO_SIZE_RX + 1 );
475
580
break ;
476
581
}
477
582
mp_uint_t elapsed = mp_hal_ticks_ms () - start ;
@@ -572,3 +677,4 @@ static mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uint
572
677
573
678
MP_REGISTER_ROOT_POINTER (void * rp2_uart_rx_buffer [2 ]);
574
679
MP_REGISTER_ROOT_POINTER (void * rp2_uart_tx_buffer [2 ]);
680
+ MP_REGISTER_ROOT_POINTER (void * rp2_uart_irq_obj [2 ]);
0 commit comments