26
26
27
27
#include "py/mphal.h"
28
28
#include "py/runtime.h"
29
+ #include "shared/runtime/softtimer.h"
29
30
#include "mpuart.h"
30
-
31
31
#include "sys_ctrl_uart.h"
32
- #include "uart.h"
33
32
34
- #define UART_MAX (8)
33
+ #define mp_container_of (ptr , structure , member ) (void *)((uintptr_t)(ptr) - offsetof(structure, member))
34
+
35
+ #define UART_LSR_TEMT_Pos (6)
35
36
#define SYST_PCLK (100000000)
36
37
38
+ #define CALCULATE_BITS_PER_CHAR (data_bits , parity , stop_bits ) \
39
+ (1 + ((data_bits) + 5) + ((parity) != UART_PARITY_NONE) + ((stop_bits) + 1))
40
+
37
41
typedef struct _uart_state_t {
38
42
UART_TRANSFER_STATUS status ;
43
+ uint32_t baudrate ;
44
+ uint32_t bits_per_char ;
39
45
ringbuf_t * rx_ringbuf ;
40
46
const uint8_t * tx_src ;
41
47
const uint8_t * tx_src_max ;
42
- void (* irq_callback )(void );
48
+ soft_timer_entry_t rx_idle_timer ;
49
+ unsigned int irq_trigger ;
50
+ void (* irq_callback )(unsigned int uart_id , unsigned int trigger );
43
51
} uart_state_t ;
44
52
45
53
static const uint8_t uart_irqn [UART_MAX ] = {
@@ -66,7 +74,19 @@ static UART_Type *const uart_periph[UART_MAX] = {
66
74
67
75
static uart_state_t uart_state [UART_MAX ];
68
76
69
- void mp_uart_init (unsigned int uart_id , uint32_t baudrate , mp_hal_pin_obj_t tx , mp_hal_pin_obj_t rx , ringbuf_t * rx_ringbuf ) {
77
+ // This is called by soft_timer and executes at IRQ_PRI_PENDSV.
78
+ static void rx_idle_timer_callback (soft_timer_entry_t * self ) {
79
+ uart_state_t * state = mp_container_of (self , uart_state_t , rx_idle_timer );
80
+ if (state -> irq_callback != NULL && state -> irq_trigger & MP_UART_IRQ_RXIDLE ) {
81
+ unsigned int uart_id = state - & uart_state [0 ];
82
+ state -> irq_callback (uart_id , MP_UART_IRQ_RXIDLE );
83
+ }
84
+ }
85
+
86
+ void mp_uart_init (unsigned int uart_id , uint32_t baudrate ,
87
+ UART_DATA_BITS data_bits , UART_PARITY parity , UART_STOP_BITS stop_bits ,
88
+ mp_hal_pin_obj_t tx , mp_hal_pin_obj_t rx , ringbuf_t * rx_ringbuf ) {
89
+
70
90
UART_Type * uart = uart_periph [uart_id ];
71
91
uart_state_t * state = & uart_state [uart_id ];
72
92
@@ -82,24 +102,29 @@ void mp_uart_init(unsigned int uart_id, uint32_t baudrate, mp_hal_pin_obj_t tx,
82
102
uart_disable_tx_irq (uart );
83
103
uart_disable_rx_irq (uart );
84
104
uart_set_baudrate (uart , SYST_PCLK , baudrate );
85
- uart_set_data_parity_stop_bits (uart , UART_DATA_BITS_8 , UART_PARITY_NONE , UART_STOP_BITS_1 );
105
+ uart_set_data_parity_stop_bits (uart , data_bits , parity , stop_bits );
86
106
uart_set_flow_control (uart , UART_FLOW_CONTROL_NONE );
87
107
uart -> UART_FCR |= UART_FCR_RCVR_FIFO_RESET ;
88
108
uart_set_tx_trigger (uart , UART_TX_FIFO_EMPTY );
89
- uart_set_rx_trigger (uart , UART_RX_ONE_CHAR_IN_FIFO );
109
+ uart_set_rx_trigger (uart , UART_RX_FIFO_QUARTER_FULL );
90
110
91
111
// Initialise the state.
92
112
state -> status = UART_TRANSFER_STATUS_NONE ;
113
+ state -> baudrate = baudrate ;
114
+ state -> bits_per_char = CALCULATE_BITS_PER_CHAR (data_bits , parity , stop_bits );
93
115
state -> rx_ringbuf = rx_ringbuf ;
94
116
state -> tx_src = NULL ;
95
117
state -> tx_src_max = NULL ;
118
+ state -> irq_trigger = 0 ;
96
119
state -> irq_callback = NULL ;
97
120
98
121
// Enable interrupts.
99
122
NVIC_ClearPendingIRQ (uart_irqn [uart_id ]);
100
123
NVIC_SetPriority (uart_irqn [uart_id ], IRQ_PRI_UART_REPL );
101
124
NVIC_EnableIRQ (uart_irqn [uart_id ]);
102
125
uart_enable_rx_irq (uart );
126
+
127
+ soft_timer_static_init (& state -> rx_idle_timer , SOFT_TIMER_MODE_ONE_SHOT , 0 , rx_idle_timer_callback );
103
128
}
104
129
105
130
void mp_uart_deinit (unsigned int uart_id ) {
@@ -109,9 +134,16 @@ void mp_uart_deinit(unsigned int uart_id) {
109
134
NVIC_DisableIRQ (uart_irqn [uart_id ]);
110
135
}
111
136
112
- void mp_uart_set_irq_callback (unsigned int uart_id , void (* callback )(void )) {
137
+ void mp_uart_set_irq_callback (unsigned int uart_id , unsigned int trigger , void (* callback )(unsigned int uart_id , unsigned int trigger )) {
138
+ UART_Type * uart = uart_periph [uart_id ];
113
139
uart_state_t * state = & uart_state [uart_id ];
140
+ state -> irq_trigger = trigger ;
114
141
state -> irq_callback = callback ;
142
+ if (trigger & MP_UART_IRQ_RX ) {
143
+ uart_set_rx_trigger (uart , UART_RX_ONE_CHAR_IN_FIFO );
144
+ } else {
145
+ uart_set_rx_trigger (uart , UART_RX_FIFO_QUARTER_FULL );
146
+ }
115
147
}
116
148
117
149
void mp_uart_set_flow (unsigned int uart_id , mp_hal_pin_obj_t rts , mp_hal_pin_obj_t cts ) {
@@ -131,10 +163,20 @@ void mp_uart_set_flow(unsigned int uart_id, mp_hal_pin_obj_t rts, mp_hal_pin_obj
131
163
132
164
void mp_uart_set_baudrate (unsigned int uart_id , uint32_t baudrate ) {
133
165
UART_Type * uart = uart_periph [uart_id ];
166
+ uart_state_t * state = & uart_state [uart_id ];
134
167
168
+ state -> baudrate = baudrate ;
135
169
uart_set_baudrate (uart , SYST_PCLK , baudrate );
136
170
}
137
171
172
+ void mp_uart_set_bits_parity_stop (unsigned int uart_id , UART_DATA_BITS data_bits , UART_PARITY parity , UART_STOP_BITS stop_bits ) {
173
+ UART_Type * uart = uart_periph [uart_id ];
174
+ uart_state_t * state = & uart_state [uart_id ];
175
+
176
+ state -> bits_per_char = CALCULATE_BITS_PER_CHAR (data_bits , parity , stop_bits );
177
+ uart_set_data_parity_stop_bits (uart , data_bits , parity , stop_bits );
178
+ }
179
+
138
180
size_t mp_uart_rx_any (unsigned int uart_id ) {
139
181
uart_state_t * state = & uart_state [uart_id ];
140
182
if (state -> rx_ringbuf != NULL ) {
@@ -143,6 +185,11 @@ size_t mp_uart_rx_any(unsigned int uart_id) {
143
185
return 0 ;
144
186
}
145
187
188
+ size_t mp_uart_tx_any (unsigned int uart_id ) {
189
+ UART_Type * uart = uart_periph [uart_id ];
190
+ return uart -> UART_TFL + !((uart -> UART_LSR >> UART_LSR_TEMT_Pos ) & 1 );
191
+ }
192
+
146
193
int mp_uart_rx_char (unsigned int uart_id ) {
147
194
uart_state_t * state = & uart_state [uart_id ];
148
195
if (state -> rx_ringbuf != NULL && ringbuf_avail (state -> rx_ringbuf )) {
@@ -208,9 +255,11 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
208
255
}
209
256
210
257
case UART_IIR_RECEIVED_DATA_AVAILABLE :
211
- case UART_IIR_CHARACTER_TIMEOUT :
258
+ case UART_IIR_CHARACTER_TIMEOUT : {
259
+ bool had_char = false;
212
260
while (uart -> UART_USR & UART_USR_RECEIVE_FIFO_NOT_EMPTY ) {
213
261
for (uint32_t rfl = uart -> UART_RFL ; rfl ; -- rfl ) {
262
+ had_char = true;
214
263
int c = uart -> UART_RBR ;
215
264
#if MICROPY_HW_ENABLE_UART_REPL && MICROPY_KBD_EXCEPTION
216
265
if (uart_id == MICROPY_HW_UART_REPL ) {
@@ -226,13 +275,18 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
226
275
}
227
276
}
228
277
229
- if (iir == UART_IIR_CHARACTER_TIMEOUT ) {
230
- if (state -> irq_callback != NULL ) {
231
- state -> irq_callback ();
278
+ if (had_char ) {
279
+ if (state -> irq_callback != NULL && state -> irq_trigger & MP_UART_IRQ_RX ) {
280
+ state -> irq_callback (uart_id , MP_UART_IRQ_RX );
232
281
}
233
282
}
234
283
284
+ if (state -> irq_trigger & MP_UART_IRQ_RXIDLE ) {
285
+ // Wait for 2 characters worth of time before triggering the RXIDLE event.
286
+ soft_timer_reinsert (& state -> rx_idle_timer , 2000 * state -> bits_per_char / state -> baudrate + 1 );
287
+ }
235
288
break ;
289
+ }
236
290
237
291
case UART_IIR_TRANSMIT_HOLDING_REG_EMPTY :
238
292
while (uart -> UART_USR & UART_USR_TRANSMIT_FIFO_NOT_FULL ) {
@@ -241,6 +295,9 @@ static void mp_uart_irq_handler(unsigned int uart_id) {
241
295
} else {
242
296
uart_disable_tx_irq (uart );
243
297
state -> status = UART_TRANSFER_STATUS_SEND_COMPLETE ;
298
+ if (state -> irq_callback != NULL && state -> irq_trigger & MP_UART_IRQ_TXIDLE ) {
299
+ state -> irq_callback (uart_id , MP_UART_IRQ_TXIDLE );
300
+ }
244
301
break ;
245
302
}
246
303
}
@@ -273,7 +330,9 @@ DEFINE_IRQ_HANDLER(7)
273
330
#define REPL_BAUDRATE (115200)
274
331
275
332
void mp_uart_init_repl (void ) {
276
- mp_uart_init (MICROPY_HW_UART_REPL , REPL_BAUDRATE , pin_REPL_UART_TX , pin_REPL_UART_RX , & stdin_ringbuf );
333
+ mp_uart_init (MICROPY_HW_UART_REPL ,
334
+ REPL_BAUDRATE , UART_DATA_BITS_8 , UART_PARITY_NONE , UART_STOP_BITS_1 ,
335
+ pin_REPL_UART_TX , pin_REPL_UART_RX , & stdin_ringbuf );
277
336
}
278
337
279
338
void mp_uart_write_strn_repl (const char * str , size_t len ) {
0 commit comments