29
29
30
30
#include "driver/uart.h"
31
31
#include "freertos/FreeRTOS.h"
32
+ #include "freertos/task.h"
33
+ #include "freertos/queue.h"
34
+ #include "esp_task.h"
35
+ #include "shared/runtime/mpirq.h"
32
36
33
37
#include "py/runtime.h"
34
38
#include "py/stream.h"
49
53
#define UART_INV_CTS UART_SIGNAL_CTS_INV
50
54
51
55
#define UART_INV_MASK (UART_INV_TX | UART_INV_RX | UART_INV_RTS | UART_INV_CTS)
56
+ #define UART_IRQ_RX (1 << UART_DATA)
57
+ #define UART_IRQ_BREAK (1 << UART_BREAK)
58
+ #define MP_UART_ALLOWED_FLAGS (UART_IRQ_RX | UART_IRQ_BREAK)
52
59
53
60
typedef struct _machine_uart_obj_t {
54
61
mp_obj_base_t base ;
@@ -66,6 +73,11 @@ typedef struct _machine_uart_obj_t {
66
73
uint16_t timeout ; // timeout waiting for first char (in ms)
67
74
uint16_t timeout_char ; // timeout waiting between chars (in ms)
68
75
uint32_t invert ; // lines to invert
76
+ TaskHandle_t uart_event_task ;
77
+ QueueHandle_t uart_queue ;
78
+ uint16_t mp_irq_trigger ; // user IRQ trigger mask
79
+ uint16_t mp_irq_flags ; // user IRQ active IRQ flags
80
+ mp_irq_obj_t * mp_irq_obj ; // user IRQ object
69
81
} machine_uart_obj_t ;
70
82
71
83
static const char * _parity_name [] = {"None" , "1" , "0" };
@@ -80,14 +92,43 @@ static const char *_parity_name[] = {"None", "1", "0"};
80
92
{ MP_ROM_QSTR(MP_QSTR_INV_CTS), MP_ROM_INT(UART_INV_CTS) }, \
81
93
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HW_FLOWCTRL_RTS) }, \
82
94
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HW_FLOWCTRL_CTS) }, \
95
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RX), MP_ROM_INT(UART_IRQ_RX) }, \
96
+ { MP_ROM_QSTR(MP_QSTR_IRQ_BREAK), MP_ROM_INT(UART_IRQ_BREAK) }, \
97
+
98
+ static void uart_event_task (void * self_in ) {
99
+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
100
+ uart_event_t event ;
101
+ for (;;) {
102
+ // Waiting for an UART event.
103
+ if (xQueueReceive (self -> uart_queue , (void * )& event , (TickType_t )portMAX_DELAY )) {
104
+ self -> mp_irq_flags = 0 ;
105
+ switch (event .type ) {
106
+ // Event of UART receiving data
107
+ case UART_DATA :
108
+ self -> mp_irq_flags |= UART_IRQ_RX ;
109
+ break ;
110
+ case UART_BREAK :
111
+ self -> mp_irq_flags |= UART_IRQ_BREAK ;
112
+ break ;
113
+ default :
114
+ break ;
115
+ }
116
+ // Check the flags to see if the user handler should be called
117
+ if (self -> mp_irq_trigger & self -> mp_irq_flags ) {
118
+ mp_irq_handler (self -> mp_irq_obj );
119
+ mp_hal_wake_main_task_from_isr ();
120
+ }
121
+ }
122
+ }
123
+ }
83
124
84
125
static void mp_machine_uart_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
85
126
machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
86
127
uint32_t baudrate ;
87
128
check_esp_err (uart_get_baudrate (self -> uart_num , & baudrate ));
88
- mp_printf (print , "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, txbuf=%u, rxbuf=%u, timeout=%u, timeout_char=%u" ,
129
+ mp_printf (print , "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, rts=%d, cts=%d, txbuf=%u, rxbuf=%u, timeout=%u, timeout_char=%u, irq=%d " ,
89
130
self -> uart_num , baudrate , self -> bits , _parity_name [self -> parity ],
90
- self -> stop , self -> tx , self -> rx , self -> rts , self -> cts , self -> txbuf , self -> rxbuf , self -> timeout , self -> timeout_char );
131
+ self -> stop , self -> tx , self -> rx , self -> rts , self -> cts , self -> txbuf , self -> rxbuf , self -> timeout , self -> timeout_char , self -> mp_irq_trigger );
91
132
if (self -> invert ) {
92
133
mp_printf (print , ", invert=" );
93
134
uint32_t invert_mask = self -> invert ;
@@ -348,6 +389,7 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
348
389
self -> timeout_char = 0 ;
349
390
self -> invert = 0 ;
350
391
self -> flowcontrol = 0 ;
392
+ self -> uart_event_task = 0 ;
351
393
352
394
switch (uart_num ) {
353
395
case UART_NUM_0 :
@@ -378,7 +420,7 @@ static mp_obj_t mp_machine_uart_make_new(const mp_obj_type_t *type, size_t n_arg
378
420
// Setup
379
421
check_esp_err (uart_param_config (self -> uart_num , & uartcfg ));
380
422
381
- check_esp_err (uart_driver_install (uart_num , self -> rxbuf , self -> txbuf , 0 , NULL , 0 ));
423
+ check_esp_err (uart_driver_install (uart_num , self -> rxbuf , self -> txbuf , 3 , & self -> uart_queue , 0 ));
382
424
}
383
425
384
426
mp_map_t kw_args ;
@@ -422,6 +464,66 @@ static void mp_machine_uart_sendbreak(machine_uart_obj_t *self) {
422
464
check_esp_err (uart_set_baudrate (self -> uart_num , baudrate ));
423
465
}
424
466
467
+ static mp_uint_t uart_irq_trigger (mp_obj_t self_in , mp_uint_t new_trigger ) {
468
+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
469
+ self -> mp_irq_trigger = new_trigger ;
470
+ return 0 ;
471
+ }
472
+
473
+ static mp_uint_t uart_irq_info (mp_obj_t self_in , mp_uint_t info_type ) {
474
+ machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
475
+ if (info_type == MP_IRQ_INFO_FLAGS ) {
476
+ return self -> mp_irq_flags ;
477
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS ) {
478
+ return self -> mp_irq_trigger ;
479
+ }
480
+ return 0 ;
481
+ }
482
+
483
+ static const mp_irq_methods_t uart_irq_methods = {
484
+ .trigger = uart_irq_trigger ,
485
+ .info = uart_irq_info ,
486
+ };
487
+
488
+ static mp_irq_obj_t * mp_machine_uart_irq (machine_uart_obj_t * self , bool any_args , mp_arg_val_t * args ) {
489
+ if (self -> mp_irq_obj == NULL ) {
490
+ self -> mp_irq_trigger = 0 ;
491
+ self -> mp_irq_obj = mp_irq_new (& uart_irq_methods , MP_OBJ_FROM_PTR (self ));
492
+ }
493
+
494
+ if (any_args ) {
495
+ // Check the handler
496
+ mp_obj_t handler = args [MP_IRQ_ARG_INIT_handler ].u_obj ;
497
+ if (handler != mp_const_none && !mp_obj_is_callable (handler )) {
498
+ mp_raise_ValueError (MP_ERROR_TEXT ("handler must be None or callable" ));
499
+ }
500
+
501
+ // Check the trigger
502
+ mp_uint_t trigger = args [MP_IRQ_ARG_INIT_trigger ].u_int ;
503
+ mp_uint_t not_supported = trigger & ~MP_UART_ALLOWED_FLAGS ;
504
+ if (trigger != 0 && not_supported ) {
505
+ mp_raise_msg_varg (& mp_type_ValueError , MP_ERROR_TEXT ("trigger 0x%04x unsupported" ), not_supported );
506
+ }
507
+
508
+ self -> mp_irq_obj -> handler = handler ;
509
+ if (args [MP_IRQ_ARG_INIT_hard ].u_bool ) {
510
+ mp_raise_ValueError (MP_ERROR_TEXT ("hard IRQ is not supported" ));
511
+ }
512
+ self -> mp_irq_obj -> ishard = false;
513
+ self -> mp_irq_trigger = trigger ;
514
+ // Start a task for handling events
515
+ if (handler != mp_const_none && self -> uart_event_task == NULL ) {
516
+ xTaskCreatePinnedToCore (uart_event_task , "uart_event_task" , 2048 , self ,
517
+ ESP_TASKD_EVENT_PRIO , (TaskHandle_t * )& self -> uart_event_task , MP_TASK_COREID );
518
+ } else if (handler == mp_const_none && self -> uart_event_task != NULL ) {
519
+ vTaskDelete (self -> uart_event_task );
520
+ self -> uart_event_task = NULL ;
521
+ }
522
+ }
523
+
524
+ return self -> mp_irq_obj ;
525
+ }
526
+
425
527
static mp_uint_t mp_machine_uart_read (mp_obj_t self_in , void * buf_in , mp_uint_t size , int * errcode ) {
426
528
machine_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
427
529
0 commit comments