[SOLVED] FreeRTOS mutex issue in ISR with stm32 HAL and UART DMA TX
I tried to make a formatted print function, which would not be interrupted by another call to HAL_UART_Transmit_DMA(). I have two threads which freely calls HAL_UART_Transmit_DMA(). If it's not synchronized, the message would be mixed or lost.
So I adopted FreeRTOS mutex, guSyncUARTTX. to synchronize the printings on the terminal. xSemaphoreTake() are called before printing. The threads which call the formatted print function dbg_printf() has to wait until the mutex is released by HAL_UART_TxCpltCallback() in the DMA ISR context.
I made it sure that guSyncUARTTX is initialized before xSemaphoreTake(), xSemaphoreGiveFromISR() is called. So if the line calling xSemaphoreCreateMutex() is commented out, no mutex related functions will be executed. And I have no big problem in this case. messages are simply mixed or lost if unlucky.
But with the mutex initialization routine xSemaphoreCreateMutex(), it freezes. I found out F7 is looping around in vPortRaiseBASEPRI() by debugging with openocd.
Could someone point out what is wrong with the following code? I'm new to FreeRTOS and not so familar with stm32 HAL libraries either.
static SemaphoreHandle_t guSyncUARTTX = NULL;
void taskA(void *pvParameters)
{
uint32_t reg1, reg2;
guSyncUARTTX = xSemaphoreCreateMutex();
HAL_UART_Receive_DMA(&huart1, rxbuffer, 1);
while(1)
{
vTaskDelay(1000);
reg1 = READ_REG(huart1.Instance->CR1);
reg2 = READ_REG(huart1.Instance->ISR);
dbg_printf("shell running 0x%08x 0x%08x!!!\r\n", reg1, reg2);
}
}
void taskB(void *pvParameters)
{
while(1)
{
vTaskDelay(1000);
dbg_printf("taskB running!!!\r\n");
}
}
void uart_tx_wait(void) {
/* dbg_printf() can be called before guSyncUARTTX is initialized */
if(guSyncUARTTX != NULL)
xSemaphoreTake(guSyncUARTTX, portMAX_DELAY);
}
__attribute__((__aligned__(32))) static char rt_log_buf[CONSOLEBUF_SIZE];
void dbg_printf(const char *fmt, ...)
{
va_list args;
size_t length;
uart_tx_wait();
va_start(args, fmt);
length = vsnprintf(rt_log_buf, sizeof(rt_log_buf) - 1, fmt, args);
va_end(args);
HAL_UART_Transmit_DMA(&huart1, (uint8_t *)rt_log_buf, length);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
static BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
/* ISR can be called before guSyncUARTTX is initialized */
if(guSyncUARTTX != NULL)
xSemaphoreGiveFromISR(guSyncUARTTX, &xHigherPriorityTaskWoken);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
unsigned char c = huart->Instance->RDR;
HAL_UART_Receive_DMA(huart, rxbuffer, 1);
BSP_LED_Toggle(LED_GREEN);
}
