Skip to content

Commit 4c29c3a

Browse files
authored
Merge pull request #502 from fpistm/PR-496-rework
[PR 496 rework] Disable USART IRQ in uart_write and uart_debug_write
2 parents f9f4340 + 9dc4505 commit 4c29c3a

File tree

4 files changed

+108
-88
lines changed

4 files changed

+108
-88
lines changed

cores/arduino/HardwareSerial.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ void HardwareSerial::configForLowPower(void)
244244
// Reconfigure properly Serial instance to use HSI as clock source
245245
end();
246246
uart_config_lowpower(&_serial);
247-
begin(_serial.baudrate, _config);
247+
begin(_baud, _config);
248248
#endif
249249
}
250250

@@ -290,8 +290,10 @@ int HardwareSerial::_tx_complete_irq(serial_t *obj)
290290
void HardwareSerial::begin(unsigned long baud, byte config)
291291
{
292292
uint32_t databits = 0;
293+
uint32_t stopbits = 0;
294+
uint32_t parity = 0;
293295

294-
_serial.baudrate = (uint32_t)baud;
296+
_baud = baud;
295297
_config = config;
296298

297299
// Manage databits
@@ -311,40 +313,40 @@ void HardwareSerial::begin(unsigned long baud, byte config)
311313
}
312314

313315
if ((config & 0x30) == 0x30) {
314-
_serial.parity = UART_PARITY_ODD;
316+
parity = UART_PARITY_ODD;
315317
databits++;
316318
} else if ((config & 0x20) == 0x20) {
317-
_serial.parity = UART_PARITY_EVEN;
319+
parity = UART_PARITY_EVEN;
318320
databits++;
319321
} else {
320-
_serial.parity = UART_PARITY_NONE;
322+
parity = UART_PARITY_NONE;
321323
}
322324

323325
if ((config & 0x08) == 0x08) {
324-
_serial.stopbits = UART_STOPBITS_2;
326+
stopbits = UART_STOPBITS_2;
325327
} else {
326-
_serial.stopbits = UART_STOPBITS_1;
328+
stopbits = UART_STOPBITS_1;
327329
}
328330

329331
switch (databits) {
330332
#ifdef UART_WORDLENGTH_7B
331333
case 7:
332-
_serial.databits = UART_WORDLENGTH_7B;
334+
databits = UART_WORDLENGTH_7B;
333335
break;
334336
#endif
335337
case 8:
336-
_serial.databits = UART_WORDLENGTH_8B;
338+
databits = UART_WORDLENGTH_8B;
337339
break;
338340
case 9:
339-
_serial.databits = UART_WORDLENGTH_9B;
341+
databits = UART_WORDLENGTH_9B;
340342
break;
341343
default:
342344
case 0:
343345
Error_Handler();
344346
break;
345347
}
346348

347-
uart_init(&_serial);
349+
uart_init(&_serial, (uint32_t)baud, databits, parity, stopbits);
348350
uart_attach_rx_callback(&_serial, _rx_complete_irq);
349351
}
350352

cores/arduino/HardwareSerial.h

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class HardwareSerial : public Stream {
150150
static int _tx_complete_irq(serial_t *obj);
151151
private:
152152
uint8_t _config;
153+
unsigned long _baud;
153154
void init(void);
154155
void configForLowPower(void);
155156
};

cores/arduino/stm32/uart.c

+82-68
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,28 @@ typedef enum {
9797
} uart_index_t;
9898

9999
static UART_HandleTypeDef *uart_handlers[UART_NUM] = {NULL};
100-
static void (*rx_callback[UART_NUM])(serial_t *);
101-
static serial_t *rx_callback_obj[UART_NUM];
102-
static int (*tx_callback[UART_NUM])(serial_t *);
103-
static serial_t *tx_callback_obj[UART_NUM];
104100

105101
static serial_t serial_debug = { .uart = NP, .index = UART_NUM };
106102

103+
/* Aim of the function is to get serial_s pointer using huart pointer */
104+
/* Highly inspired from magical linux kernel's "container_of" */
105+
serial_t *get_serial_obj(UART_HandleTypeDef *huart)
106+
{
107+
struct serial_s *obj_s;
108+
serial_t *obj;
109+
110+
obj_s = (struct serial_s *)((char *)huart - offsetof(struct serial_s, handle));
111+
obj = (serial_t *)((char *)obj_s - offsetof(serial_t, uart));
112+
113+
return (obj);
114+
}
115+
107116
/**
108117
* @brief Function called to initialize the uart interface
109118
* @param obj : pointer to serial_t structure
110119
* @retval None
111120
*/
112-
void uart_init(serial_t *obj)
121+
void uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t parity, uint32_t stopbits)
113122
{
114123
if (obj == NULL) {
115124
return;
@@ -284,10 +293,10 @@ void uart_init(serial_t *obj)
284293
/* Configure uart */
285294
uart_handlers[obj->index] = huart;
286295
huart->Instance = (USART_TypeDef *)(obj->uart);
287-
huart->Init.BaudRate = obj->baudrate;
288-
huart->Init.WordLength = obj->databits;
289-
huart->Init.StopBits = obj->stopbits;
290-
huart->Init.Parity = obj->parity;
296+
huart->Init.BaudRate = baudrate;
297+
huart->Init.WordLength = databits;
298+
huart->Init.StopBits = stopbits;
299+
huart->Init.Parity = parity;
291300
huart->Init.Mode = UART_MODE_TX_RX;
292301
huart->Init.HwFlowCtl = UART_HWCONTROL_NONE;
293302
huart->Init.OverSampling = UART_OVERSAMPLING_16;
@@ -306,7 +315,7 @@ void uart_init(serial_t *obj)
306315
* check Reference Manual
307316
*/
308317
if (obj->uart == LPUART1) {
309-
if (obj->baudrate <= 9600) {
318+
if (baudrate <= 9600) {
310319
#if defined(USART_CR3_UCESM)
311320
HAL_UARTEx_EnableClockStopMode(huart);
312321
#endif
@@ -323,7 +332,7 @@ void uart_init(serial_t *obj)
323332
}
324333
/* Trying to change LPUART clock source */
325334
/* If baudrate is lower than or equal to 9600 try to change to LSE */
326-
if (obj->baudrate <= 9600) {
335+
if (baudrate <= 9600) {
327336
/* Enable the clock if not already set by user */
328337
enableClock(LSE_CLOCK);
329338

@@ -468,6 +477,11 @@ void uart_deinit(serial_t *obj)
468477
}
469478

470479
HAL_UART_DeInit(uart_handlers[obj->index]);
480+
481+
/* Release uart debug to ensure init */
482+
if (serial_debug.index == obj->index) {
483+
serial_debug.index = UART_NUM;
484+
}
471485
}
472486

473487
#if defined(HAL_PWR_MODULE_ENABLED) && defined(UART_IT_WUF)
@@ -564,12 +578,8 @@ void uart_debug_init(void)
564578
#else
565579
serial_debug.pin_tx = pinmap_pin(DEBUG_UART, PinMap_UART_TX);
566580
#endif
567-
serial_debug.baudrate = DEBUG_UART_BAUDRATE;
568-
serial_debug.parity = UART_PARITY_NONE;
569-
serial_debug.databits = UART_WORDLENGTH_8B;
570-
serial_debug.stopbits = UART_STOPBITS_1;
571581

572-
uart_init(&serial_debug);
582+
uart_init(&serial_debug, DEBUG_UART_BAUDRATE, UART_WORDLENGTH_8B, UART_PARITY_NONE, UART_STOPBITS_1);
573583
}
574584
}
575585

@@ -581,38 +591,46 @@ void uart_debug_init(void)
581591
*/
582592
size_t uart_debug_write(uint8_t *data, uint32_t size)
583593
{
584-
uint8_t index = 0;
585594
uint32_t tickstart = HAL_GetTick();
586595

587596
if (DEBUG_UART == NP) {
588597
return 0;
589598
}
590-
/* Search if DEBUG_UART already initialized */
591-
for (index = 0; index < UART_NUM; index++) {
592-
if (uart_handlers[index] != NULL) {
593-
if (DEBUG_UART == uart_handlers[index]->Instance) {
594-
break;
599+
if (serial_debug.index >= UART_NUM) {
600+
/* Search if DEBUG_UART already initialized */
601+
for (serial_debug.index = 0; serial_debug.index < UART_NUM; serial_debug.index++) {
602+
if (uart_handlers[serial_debug.index] != NULL) {
603+
if (DEBUG_UART == uart_handlers[serial_debug.index]->Instance) {
604+
break;
605+
}
595606
}
596607
}
597-
}
598608

599-
if (index >= UART_NUM) {
600-
/* DEBUG_UART not initialized */
601609
if (serial_debug.index >= UART_NUM) {
610+
/* DEBUG_UART not initialized */
602611
uart_debug_init();
603612
if (serial_debug.index >= UART_NUM) {
604613
return 0;
605614
}
615+
} else {
616+
serial_t *obj = get_serial_obj(uart_handlers[serial_debug.index]);
617+
if (obj) {
618+
serial_debug.irq = obj->irq;
619+
}
606620
}
607-
index = serial_debug.index;
608621
}
609622

610-
while (HAL_UART_Transmit(uart_handlers[index], data, size, TX_TIMEOUT) != HAL_OK) {
623+
HAL_NVIC_DisableIRQ(serial_debug.irq);
624+
625+
while (HAL_UART_Transmit(uart_handlers[serial_debug.index], data, size, TX_TIMEOUT) != HAL_OK) {
611626
if ((HAL_GetTick() - tickstart) >= TX_TIMEOUT) {
612-
return 0;
627+
size = 0;
628+
break;
613629
}
614630
}
615631

632+
HAL_NVIC_EnableIRQ(serial_debug.irq);
633+
616634
return size;
617635
}
618636

@@ -655,8 +673,7 @@ int uart_getc(serial_t *obj, unsigned char *c)
655673

656674
*c = (unsigned char)(obj->recv);
657675
/* Restart RX irq */
658-
UART_HandleTypeDef *huart = uart_handlers[obj->index];
659-
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
676+
HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1);
660677

661678
return 0;
662679
}
@@ -678,16 +695,16 @@ void uart_attach_rx_callback(serial_t *obj, void (*callback)(serial_t *))
678695
if (serial_rx_active(obj)) {
679696
return;
680697
}
698+
obj->rx_callback = callback;
699+
700+
/* Must disable interrupt to prevent handle lock contention */
701+
HAL_NVIC_DisableIRQ(obj->irq);
681702

682-
rx_callback[obj->index] = callback;
683-
rx_callback_obj[obj->index] = obj;
703+
HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1);
684704

705+
/* Enable interrupt */
685706
HAL_NVIC_SetPriority(obj->irq, 0, 1);
686707
HAL_NVIC_EnableIRQ(obj->irq);
687-
688-
if (HAL_UART_Receive_IT(uart_handlers[obj->index], &(obj->recv), 1) != HAL_OK) {
689-
return;
690-
}
691708
}
692709

693710
/**
@@ -702,25 +719,25 @@ void uart_attach_tx_callback(serial_t *obj, int (*callback)(serial_t *))
702719
if (obj == NULL) {
703720
return;
704721
}
722+
obj->tx_callback = callback;
705723

706-
tx_callback[obj->index] = callback;
707-
tx_callback_obj[obj->index] = obj;
724+
/* Must disable interrupt to prevent handle lock contention */
725+
HAL_NVIC_DisableIRQ(obj->irq);
726+
727+
/* The following function will enable UART_IT_TXE and error interrupts */
728+
HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1);
708729

709730
/* Enable interrupt */
710731
HAL_NVIC_SetPriority(obj->irq, 0, 2);
711732
HAL_NVIC_EnableIRQ(obj->irq);
712-
713-
/* The following function will enable UART_IT_TXE and error interrupts */
714-
if (HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1) != HAL_OK) {
715-
return;
716-
}
717733
}
718734

719735
/**
720736
* @brief Return index of the serial handler
721737
* @param UartHandle pointer on the uart reference
722738
* @retval index
723739
*/
740+
/*
724741
uint8_t uart_index(UART_HandleTypeDef *huart)
725742
{
726743
uint8_t i = 0;
@@ -736,6 +753,7 @@ uint8_t uart_index(UART_HandleTypeDef *huart)
736753
737754
return i;
738755
}
756+
*/
739757

740758
/**
741759
* @brief Rx Transfer completed callback
@@ -744,10 +762,9 @@ uint8_t uart_index(UART_HandleTypeDef *huart)
744762
*/
745763
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
746764
{
747-
uint8_t index = uart_index(huart);
748-
749-
if (index < UART_NUM) {
750-
rx_callback[index](rx_callback_obj[index]);
765+
serial_t *obj = get_serial_obj(huart);
766+
if (obj) {
767+
obj->rx_callback(obj);
751768
}
752769
}
753770

@@ -758,14 +775,11 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
758775
*/
759776
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
760777
{
761-
uint8_t index = uart_index(huart);
762-
serial_t *obj = tx_callback_obj[index];
778+
serial_t *obj = get_serial_obj(huart);
763779

764-
if (index < UART_NUM) {
765-
if (tx_callback[index](obj) != -1) {
766-
if (HAL_UART_Transmit_IT(uart_handlers[obj->index], &obj->tx_buff[obj->tx_tail], 1) != HAL_OK) {
767-
return;
768-
}
780+
if (obj && obj->tx_callback(obj) != -1) {
781+
if (HAL_UART_Transmit_IT(huart, &obj->tx_buff[obj->tx_tail], 1) != HAL_OK) {
782+
return;
769783
}
770784
}
771785
}
@@ -777,30 +791,32 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
777791
*/
778792
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
779793
{
780-
volatile uint32_t tmpval;
781794
#if defined(STM32F1xx) || defined(STM32F2xx) || defined(STM32F4xx) || defined(STM32L1xx)
782795
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) {
783-
tmpval = huart->Instance->DR; /* Clear PE flag */
796+
__HAL_UART_CLEAR_PEFLAG(huart); /* Clear PE flag */
784797
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) {
785-
tmpval = huart->Instance->DR; /* Clear FE flag */
798+
__HAL_UART_CLEAR_FEFLAG(huart); /* Clear FE flag */
786799
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_NE) != RESET) {
787-
tmpval = huart->Instance->DR; /* Clear NE flag */
800+
__HAL_UART_CLEAR_NEFLAG(huart); /* Clear NE flag */
788801
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
789-
tmpval = huart->Instance->DR; /* Clear ORE flag */
802+
__HAL_UART_CLEAR_OREFLAG(huart); /* Clear ORE flag */
790803
}
791804
#else
792805
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_PE) != RESET) {
793-
tmpval = huart->Instance->RDR; /* Clear PE flag */
806+
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_PEF); /* Clear PE flag */
794807
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_FE) != RESET) {
795-
tmpval = huart->Instance->RDR; /* Clear FE flag */
808+
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_FEF); /* Clear FE flag */
796809
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_NE) != RESET) {
797-
tmpval = huart->Instance->RDR; /* Clear NE flag */
810+
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_NEF); /* Clear NE flag */
798811
} else if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) != RESET) {
799-
tmpval = huart->Instance->RDR; /* Clear ORE flag */
812+
__HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); /* Clear ORE flag */
800813
}
801814
#endif
802-
803-
UNUSED(tmpval);
815+
/* Restart receive interrupt after any error */
816+
serial_t *obj = get_serial_obj(huart);
817+
if (obj && !serial_rx_active(obj)) {
818+
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
819+
}
804820
}
805821

806822
/**
@@ -1010,9 +1026,7 @@ void UART10_IRQHandler(void)
10101026
*/
10111027
void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
10121028
{
1013-
uint8_t index = uart_index(huart);
1014-
serial_t *obj = rx_callback_obj[index];
1015-
1029+
serial_t *obj = get_serial_obj(huart);
10161030
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
10171031
}
10181032
#endif /* HAL_UART_MODULE_ENABLED */

0 commit comments

Comments
 (0)