Skip to content

Commit a8070a4

Browse files
committed
Revise IRQ managment, add restart on failure
1 parent 33deb67 commit a8070a4

File tree

2 files changed

+74
-52
lines changed

2 files changed

+74
-52
lines changed

ports/stm32f4/common-hal/busio/UART.c

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -38,44 +38,43 @@
3838
#include "tick.h"
3939
#include "stm32f4xx_hal.h"
4040

41+
bool iflag;
42+
int errflag;
43+
bool rxflag;
44+
bool bsyflag;
45+
4146
STATIC bool reserved_uart[MAX_UART];
4247

4348
void uart_reset(void) {
4449
#ifdef USART1
4550
reserved_uart[0] = false;
4651
MP_STATE_PORT(cpy_uart_obj_all)[0] = NULL;
4752
__HAL_RCC_USART1_CLK_DISABLE();
48-
//HAL_NVIC_DisableIRQ(USART1_IRQn);
4953
#endif
5054
#ifdef USART2
5155
reserved_uart[1] = false;
5256
MP_STATE_PORT(cpy_uart_obj_all)[1] = NULL;
5357
__HAL_RCC_USART2_CLK_DISABLE();
54-
//HAL_NVIC_DisableIRQ(USART2_IRQn);
5558
#endif
5659
#ifdef USART3
5760
reserved_uart[2] = false;
5861
MP_STATE_PORT(cpy_uart_obj_all)[2] = NULL;
5962
__HAL_RCC_USART3_CLK_DISABLE();
60-
//HAL_NVIC_DisableIRQ(USART3_IRQn);
6163
#endif
6264
#ifdef UART4
6365
reserved_uart[3] = false;
6466
MP_STATE_PORT(cpy_uart_obj_all)[3] = NULL;
6567
__HAL_RCC_UART4_CLK_DISABLE();
66-
//HAL_NVIC_DisableIRQ(UART4_IRQn);
6768
#endif
6869
#ifdef UART5
6970
reserved_uart[4] = false;
7071
MP_STATE_PORT(cpy_uart_obj_all)[4] = NULL;
7172
__HAL_RCC_UART5_CLK_DISABLE();
72-
//HAL_NVIC_DisableIRQ(UART5_IRQn);
7373
#endif
7474
#ifdef USART6
7575
reserved_uart[5] = false;
7676
MP_STATE_PORT(cpy_uart_obj_all)[5] = NULL;
7777
__HAL_RCC_USART6_CLK_DISABLE();
78-
//HAL_NVIC_DisableIRQ(USART6_IRQn);
7978
#endif
8079
//TODO: this technically needs to go to 10 to support F413. Any way to condense?
8180
}
@@ -104,10 +103,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
104103
__HAL_RCC_USART1_RELEASE_RESET();
105104
__HAL_RCC_USART1_CLK_ENABLE();
106105
self->irq = USART1_IRQn;
107-
//HAL_NVIC_SetPriority(USART1_IRQn, 2,1);
108-
NVIC_SetPriority(USART1_IRQn, 7);
109-
NVIC_ClearPendingIRQ(USART1_IRQn);
110-
HAL_NVIC_EnableIRQ(USART1_IRQn);
111106
}
112107
#endif
113108
#ifdef USART2
@@ -117,10 +112,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
117112
__HAL_RCC_USART2_RELEASE_RESET();
118113
__HAL_RCC_USART2_CLK_ENABLE();
119114
self->irq = USART2_IRQn;
120-
//HAL_NVIC_SetPriority(USART2_IRQn, 2,1);
121-
NVIC_SetPriority(USART2_IRQn, 7);
122-
NVIC_ClearPendingIRQ(USART2_IRQn);
123-
HAL_NVIC_EnableIRQ(USART2_IRQn);
124115
}
125116
#endif
126117
#ifdef USART3
@@ -130,10 +121,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
130121
__HAL_RCC_USART3_RELEASE_RESET();
131122
__HAL_RCC_USART3_CLK_ENABLE();
132123
self->irq = USART3_IRQn;
133-
//HAL_NVIC_SetPriority(USART3_IRQn, 2,1);
134-
NVIC_SetPriority(USART3_IRQn, 7);
135-
NVIC_ClearPendingIRQ(USART3_IRQn);
136-
HAL_NVIC_EnableIRQ(USART3_IRQn);
137124
}
138125
#endif
139126
#ifdef UART4
@@ -143,10 +130,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
143130
__HAL_RCC_UART4_RELEASE_RESET();
144131
__HAL_RCC_UART4_CLK_ENABLE();
145132
self->irq = UART4_IRQn;
146-
//HAL_NVIC_SetPriority(UART4_IRQn, 2,1);
147-
NVIC_SetPriority(UART4_IRQn, 7);
148-
NVIC_ClearPendingIRQ(UART4_IRQn);
149-
HAL_NVIC_EnableIRQ(UART4_IRQn);
150133
}
151134
#endif
152135
#ifdef UART5
@@ -156,10 +139,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
156139
__HAL_RCC_UART5_RELEASE_RESET();
157140
__HAL_RCC_UART5_CLK_ENABLE();
158141
self->irq = UART5_IRQn;
159-
//NVIC_SetPriority(UART5_IRQn, 7);
160-
NVIC_SetPriority(UART5_IRQn, 7);
161-
NVIC_ClearPendingIRQ(UART5_IRQn);
162-
HAL_NVIC_EnableIRQ(UART5_IRQn);
163142
}
164143
#endif
165144
#ifdef USART6
@@ -169,10 +148,6 @@ STATIC void uart_clk_irq_enable(busio_uart_obj_t *self, USART_TypeDef * USARTx)
169148
__HAL_RCC_USART6_RELEASE_RESET();
170149
__HAL_RCC_USART6_CLK_ENABLE();
171150
self->irq = USART6_IRQn;
172-
//NVIC_SetPriority(USART6_IRQn, 7);
173-
NVIC_SetPriority(USART6_IRQn, 7);
174-
NVIC_ClearPendingIRQ(USART6_IRQn);
175-
HAL_NVIC_EnableIRQ(USART6_IRQn);
176151
}
177152
#endif
178153
}
@@ -308,20 +283,33 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
308283
if (self->tx != NULL) {
309284
claim_pin(tx);
310285
}
311-
312286
self->baudrate = baudrate;
313287
self->timeout_ms = timeout * 1000;
314288

315-
if (HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1) != HAL_OK) {
316-
mp_raise_ValueError(translate("HAL recieve IT start error"));
289+
//start the interrupt series
290+
if ((HAL_UART_GetState(&self->handle) & HAL_UART_STATE_BUSY_RX) == HAL_UART_STATE_BUSY_RX) {
291+
mp_raise_ValueError(translate("Could not start interrupt, RX busy"));
317292
}
293+
HAL_NVIC_DisableIRQ(self->irq); //prevent handle lock contention
294+
295+
HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1);
296+
297+
HAL_NVIC_SetPriority(self->irq, UART_IRQPRI, UART_IRQSUB_PRI);
298+
HAL_NVIC_EnableIRQ(self->irq);
299+
300+
mp_printf(&mp_plat_print, "Started and inited\n");
301+
iflag = 0;
302+
errflag = 0;
303+
rxflag = 0;
304+
bsyflag = 0;
318305
}
319306

320307
bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
321308
return self->tx->pin == mp_const_none;
322309
}
323310

324311
void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
312+
mp_printf(&mp_plat_print, "De-init UART\n");
325313
reset_pin_number(self->tx->pin->port,self->tx->pin->number);
326314
reset_pin_number(self->rx->pin->port,self->rx->pin->number);
327315
self->tx = mp_const_none;
@@ -343,28 +331,34 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
343331
// Wait for all bytes received or timeout, same as nrf
344332
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
345333
RUN_BACKGROUND_TASKS;
334+
//restart if it failed in the callback
335+
if(errflag != HAL_OK) {
336+
errflag = HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1);
337+
}
346338
// Allow user to break out of a timeout with a KeyboardInterrupt.
347339
if ( mp_hal_is_interrupted() ) {
348340
return 0;
349341
}
350342
}
351343

352344
// Halt reception
353-
//HAL_UART_AbortReceive_IT(&self->handle);
354-
NVIC_DisableIRQ(self->irq);
345+
HAL_NVIC_DisableIRQ(self->irq);
355346

356347
// copy received data
357348
rx_bytes = ringbuf_count(&self->rbuf);
349+
//Used for debuggings
350+
//mp_printf(&mp_plat_print, "Read: count:%d, buffer location%p, if:%der:%drx:%dbsy:%d\n", rx_bytes, &self->rbuf,iflag,errflag,rxflag,bsyflag);
351+
iflag = 0;
352+
errflag = 0;
353+
rxflag = 0;
354+
bsyflag = 0;
358355
rx_bytes = MIN(rx_bytes, len);
359356
for ( uint16_t i = 0; i < rx_bytes; i++ ) {
360357
data[i] = ringbuf_get(&self->rbuf);
361358
}
362359

363-
NVIC_EnableIRQ(self->irq);
364-
// if (HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1) != HAL_OK) {
365-
// mp_raise_ValueError(translate("HAL recieve IT re-start error"));
366-
// }
367-
360+
HAL_NVIC_EnableIRQ(self->irq);
361+
368362
if (rx_bytes == 0) {
369363
*errcode = EAGAIN;
370364
return MP_STREAM_ERROR;
@@ -383,28 +377,50 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
383377
} else {
384378
mp_raise_ValueError(translate("UART write error"));
385379
}
380+
mp_printf(&mp_plat_print, "Send\n");
386381
return 0;
387382
}
388383

389384
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *handle)
390385
{
386+
rxflag = 1;
391387
for(int i=0; i<7; i++) {
392388
//get context pointer and cast it as struct pointer
393389
busio_uart_obj_t * context = (busio_uart_obj_t *)MP_STATE_PORT(cpy_uart_obj_all)[i];
394390
if(handle == &context->handle) {
395-
ringbuf_put_n(&context->rbuf, &context->rx_char, 1);
396-
HAL_StatusTypeDef result = HAL_UART_Receive_IT(handle, &context->rx_char, 1);
397-
if(result!=HAL_OK) {
398-
mp_raise_RuntimeError(translate("UART rx restart error"));
391+
//check if transaction is ongoing
392+
if((HAL_UART_GetState(handle) & HAL_UART_STATE_BUSY_RX) == HAL_UART_STATE_BUSY_RX) {
393+
bsyflag = 1;
394+
return;
399395
}
400-
break;
396+
ringbuf_put_n(&context->rbuf, &context->rx_char, 1);
397+
errflag = HAL_UART_Receive_IT(handle, &context->rx_char, 1);
398+
399+
return;
401400
}
402401
}
403402
}
404403

405404
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle)
406405
{
407-
mp_raise_RuntimeError(translate("UART Error Callback hit"));
406+
if (__HAL_UART_GET_FLAG(UartHandle, UART_FLAG_PE) != RESET) {
407+
__HAL_UART_CLEAR_PEFLAG(UartHandle);
408+
} else if (__HAL_UART_GET_FLAG(UartHandle, UART_FLAG_FE) != RESET) {
409+
__HAL_UART_CLEAR_FEFLAG(UartHandle);
410+
} else if (__HAL_UART_GET_FLAG(UartHandle, UART_FLAG_NE) != RESET) {
411+
__HAL_UART_CLEAR_NEFLAG(UartHandle);
412+
} else if (__HAL_UART_GET_FLAG(UartHandle, UART_FLAG_ORE) != RESET) {
413+
__HAL_UART_CLEAR_OREFLAG(UartHandle);
414+
}
415+
//restart serial read after an error
416+
for(int i=0; i<7; i++) {
417+
busio_uart_obj_t * context = (busio_uart_obj_t *)MP_STATE_PORT(cpy_uart_obj_all)[i];
418+
if(UartHandle == &context->handle) {
419+
HAL_UART_Receive_IT(UartHandle, &context->rx_char, 1);
420+
return;
421+
}
422+
}
423+
408424
}
409425

410426
uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
@@ -432,25 +448,24 @@ uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
432448
}
433449

434450
void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
451+
mp_printf(&mp_plat_print, "Clear RX Buffer\n");
435452
// Halt reception
436-
//HAL_UART_AbortReceive_IT(&self->handle);
437-
NVIC_DisableIRQ(self->irq);
453+
HAL_NVIC_DisableIRQ(self->irq);
438454
ringbuf_clear(&self->rbuf);
439-
NVIC_EnableIRQ(self->irq);
440-
//HAL_UART_Receive_IT(&self->handle, &self->rx_char, 1);
455+
HAL_NVIC_EnableIRQ(self->irq);
441456
}
442457

443458
bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
444459
return true;
445460
}
446461

447462
STATIC void call_hal_irq(int uart_num) {
463+
iflag = 1;
448464
//Create casted context pointer
449465
busio_uart_obj_t * context = (busio_uart_obj_t *)MP_STATE_PORT(cpy_uart_obj_all)[uart_num-1];
450466
if(context != NULL) {
467+
HAL_NVIC_ClearPendingIRQ(context->irq);
451468
HAL_UART_IRQHandler(&context->handle);
452-
} else {
453-
mp_raise_ValueError(translate("UART IRQ bad handle supplied"));
454469
}
455470
}
456471

ports/stm32f4/common-hal/busio/UART.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@
3434
#include "py/obj.h"
3535
#include "py/ringbuf.h"
3636

37+
#ifndef UART_IRQPRI
38+
#define UART_IRQPRI 1
39+
#endif
40+
#ifndef UART_IRQSUB_PRI
41+
#define UART_IRQSUB_PRI 0
42+
#endif
43+
3744
typedef struct {
3845
mp_obj_base_t base;
3946
UART_HandleTypeDef handle;

0 commit comments

Comments
 (0)