33
33
#include "py/mperrno.h"
34
34
#include "py/mphal.h"
35
35
#include "lib/utils/interrupt_char.h"
36
+ #include "lib/utils/mpirq.h"
36
37
#include "uart.h"
37
38
#include "irq.h"
38
39
#include "pendsv.h"
72
73
///
73
74
/// uart.any() # returns True if any characters waiting
74
75
76
+ typedef struct _pyb_uart_irq_map_t {
77
+ uint16_t irq_en ;
78
+ uint16_t flag ;
79
+ } pyb_uart_irq_map_t ;
80
+
81
+ STATIC const pyb_uart_irq_map_t mp_irq_map [] = {
82
+ { USART_CR1_IDLEIE , UART_FLAG_IDLE }, // RX idle
83
+ { USART_CR1_PEIE , UART_FLAG_PE }, // parity error
84
+ { USART_CR1_TXEIE , UART_FLAG_TXE }, // TX register empty
85
+ { USART_CR1_TCIE , UART_FLAG_TC }, // TX complete
86
+ { USART_CR1_RXNEIE , UART_FLAG_RXNE }, // RX register not empty
87
+ #if 0
88
+ // For now only IRQs selected by CR1 are supported
89
+ #if defined(STM32F4 )
90
+ { USART_CR2_LBDIE , UART_FLAG_LBD }, // LIN break detection
91
+ #else
92
+ { USART_CR2_LBDIE , UART_FLAG_LBDF }, // LIN break detection
93
+ #endif
94
+ { USART_CR3_CTSIE , UART_FLAG_CTS }, // CTS
95
+ #endif
96
+ };
97
+
98
+ // OR-ed IRQ flags which should not be touched by the user
99
+ STATIC const uint32_t mp_irq_reserved = UART_FLAG_RXNE ;
100
+
101
+ // OR-ed IRQ flags which are allowed to be used by the user
102
+ STATIC const uint32_t mp_irq_allowed = UART_FLAG_IDLE ;
103
+
104
+ STATIC mp_obj_t pyb_uart_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args );
105
+
106
+ STATIC void pyb_uart_irq_config (pyb_uart_obj_t * self , bool enable ) {
107
+ if (self -> mp_irq_trigger ) {
108
+ for (size_t entry = 0 ; entry < MP_ARRAY_SIZE (mp_irq_map ); ++ entry ) {
109
+ if (mp_irq_map [entry ].flag & mp_irq_reserved ) {
110
+ continue ;
111
+ }
112
+ if (mp_irq_map [entry ].flag & self -> mp_irq_trigger ) {
113
+ if (enable ) {
114
+ self -> uartx -> CR1 |= mp_irq_map [entry ].irq_en ;
115
+ } else {
116
+ self -> uartx -> CR1 &= ~mp_irq_map [entry ].irq_en ;
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ STATIC mp_uint_t pyb_uart_irq_trigger (mp_obj_t self_in , mp_uint_t new_trigger ) {
124
+ pyb_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
125
+ pyb_uart_irq_config (self , false);
126
+ self -> mp_irq_trigger = new_trigger ;
127
+ pyb_uart_irq_config (self , true);
128
+ return 0 ;
129
+ }
130
+
131
+ STATIC mp_uint_t pyb_uart_irq_info (mp_obj_t self_in , mp_uint_t info_type ) {
132
+ pyb_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
133
+ if (info_type == MP_IRQ_INFO_FLAGS ) {
134
+ return self -> mp_irq_flags ;
135
+ } else if (info_type == MP_IRQ_INFO_TRIGGERS ) {
136
+ return self -> mp_irq_trigger ;
137
+ }
138
+ return 0 ;
139
+ }
140
+
141
+ STATIC const mp_irq_methods_t pyb_uart_irq_methods = {
142
+ .init = pyb_uart_irq ,
143
+ .trigger = pyb_uart_irq_trigger ,
144
+ .info = pyb_uart_irq_info ,
145
+ };
146
+
75
147
STATIC void pyb_uart_print (const mp_print_t * print , mp_obj_t self_in , mp_print_kind_t kind ) {
76
148
pyb_uart_obj_t * self = MP_OBJ_TO_PTR (self_in );
77
149
if (!self -> is_enabled ) {
@@ -123,9 +195,13 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
123
195
mp_print_str (print , "CTS" );
124
196
}
125
197
}
126
- mp_printf (print , ", timeout=%u, timeout_char=%u, rxbuf=%u) " ,
198
+ mp_printf (print , ", timeout=%u, timeout_char=%u, rxbuf=%u" ,
127
199
self -> timeout , self -> timeout_char ,
128
200
self -> read_buf_len == 0 ? 0 : self -> read_buf_len - 1 ); // -1 to adjust for usable length of buffer
201
+ if (self -> mp_irq_trigger != 0 ) {
202
+ mp_printf (print , "; irq=0x%x" , self -> mp_irq_trigger );
203
+ }
204
+ mp_print_str (print , ")" );
129
205
}
130
206
}
131
207
@@ -414,6 +490,43 @@ STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
414
490
}
415
491
STATIC MP_DEFINE_CONST_FUN_OBJ_1 (pyb_uart_sendbreak_obj , pyb_uart_sendbreak );
416
492
493
+ // irq(handler, trigger, hard)
494
+ STATIC mp_obj_t pyb_uart_irq (size_t n_args , const mp_obj_t * pos_args , mp_map_t * kw_args ) {
495
+ mp_arg_val_t args [MP_IRQ_ARG_INIT_NUM_ARGS ];
496
+ mp_arg_parse_all (n_args - 1 , pos_args + 1 , kw_args , MP_IRQ_ARG_INIT_NUM_ARGS , mp_irq_init_args , args );
497
+ pyb_uart_obj_t * self = MP_OBJ_TO_PTR (pos_args [0 ]);
498
+
499
+ if (self -> mp_irq_obj == NULL ) {
500
+ self -> mp_irq_trigger = 0 ;
501
+ self -> mp_irq_obj = mp_irq_new (& pyb_uart_irq_methods , MP_OBJ_FROM_PTR (self ));
502
+ }
503
+
504
+ if (n_args > 1 || kw_args -> used != 0 ) {
505
+ // Check the handler
506
+ mp_obj_t handler = args [MP_IRQ_ARG_INIT_handler ].u_obj ;
507
+ if (handler != mp_const_none && !mp_obj_is_callable (handler )) {
508
+ mp_raise_ValueError ("handler must be None or callable" );
509
+ }
510
+
511
+ // Check the trigger
512
+ mp_uint_t trigger = args [MP_IRQ_ARG_INIT_trigger ].u_int ;
513
+ mp_uint_t not_supported = trigger & ~mp_irq_allowed ;
514
+ if (trigger != 0 && not_supported ) {
515
+ nlr_raise (mp_obj_new_exception_msg_varg (& mp_type_ValueError , "trigger 0x%08x unsupported" , not_supported ));
516
+ }
517
+
518
+ // Reconfigure user IRQs
519
+ pyb_uart_irq_config (self , false);
520
+ self -> mp_irq_obj -> handler = handler ;
521
+ self -> mp_irq_obj -> ishard = args [MP_IRQ_ARG_INIT_hard ].u_bool ;
522
+ self -> mp_irq_trigger = trigger ;
523
+ pyb_uart_irq_config (self , true);
524
+ }
525
+
526
+ return MP_OBJ_FROM_PTR (self -> mp_irq_obj );
527
+ }
528
+ STATIC MP_DEFINE_CONST_FUN_OBJ_KW (pyb_uart_irq_obj , 1 , pyb_uart_irq );
529
+
417
530
STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table [] = {
418
531
// instance methods
419
532
@@ -429,6 +542,7 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
429
542
{ MP_ROM_QSTR (MP_QSTR_readinto ), MP_ROM_PTR (& mp_stream_readinto_obj ) },
430
543
/// \method write(buf)
431
544
{ MP_ROM_QSTR (MP_QSTR_write ), MP_ROM_PTR (& mp_stream_write_obj ) },
545
+ { MP_ROM_QSTR (MP_QSTR_irq ), MP_ROM_PTR (& pyb_uart_irq_obj ) },
432
546
433
547
{ MP_ROM_QSTR (MP_QSTR_writechar ), MP_ROM_PTR (& pyb_uart_writechar_obj ) },
434
548
{ MP_ROM_QSTR (MP_QSTR_readchar ), MP_ROM_PTR (& pyb_uart_readchar_obj ) },
@@ -437,6 +551,9 @@ STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
437
551
// class constants
438
552
{ MP_ROM_QSTR (MP_QSTR_RTS ), MP_ROM_INT (UART_HWCONTROL_RTS ) },
439
553
{ MP_ROM_QSTR (MP_QSTR_CTS ), MP_ROM_INT (UART_HWCONTROL_CTS ) },
554
+
555
+ // IRQ flags
556
+ { MP_ROM_QSTR (MP_QSTR_IRQ_RXIDLE ), MP_ROM_INT (UART_FLAG_IDLE ) },
440
557
};
441
558
442
559
STATIC MP_DEFINE_CONST_DICT (pyb_uart_locals_dict , pyb_uart_locals_dict_table );
0 commit comments