I am working on a simple app that periodically sends a string over the usart2 and it immediately sends another string when the builtin button is pressed.
The callback associated to the push-button ISR defer wake up task that should preempt the current running task, as per book.
However, when I use snprintf
the board gets stuck in attempting to take the (already taken) semaphore in the deferred task. It follows some (pseudo) code to show what I am doing:
void periodic_task_1sec{
// ...
for(;;){
// ...
usart2_step(PERIODIC_TASK);
// ...
}
}
//...
void usart2_step(enum WhoIsCalling caller) {
char msg[MSG_LENGTH_MAX];
char a[] = "Button Pressed!";
switch (caller) {
case PERIODIC_TASK:
(void)snprintf(msg, MSG_LENGTH_MAX, "pippo: %s \n", "pluto");
transmit(msg);
break;
case IRQ_BUILTIN_BUTTON:
// If I use the following two lines everything works!
/* strncpy(msg, "Button pressed!\r\n", MSG_LENGTH_MAX - 1); */
/* msg[MSG_LENGTH_MAX - 1] = '\0'; */
// If I use this line everything gets stuck
(void)snprintf(msg, MSG_LENGTH_MAX, "pippo: %s \n", a);
transmit(msg);
break;
}
void transmit(char *pMsg) {
if (xSemaphoreTake(mutex_tx_process, pdMS_TO_TICKS(5)) == pdTRUE) {
HAL_UART_Transmit(&huart2, (uint8_t *)pMsg, strlen(pMsg), portMAX_DELAY);
xSemaphoreGive(mutex_tx_process);
}
}
// Interrupt handling
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
if (GPIO_Pin == B1_Pin) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xSemaphoreGiveFromISR(xSemaphoreBuiltinButton, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
// Handle EXTI line 13 interrupt
// This code will be executed when an interrupt occurs on GPIO pin 13
}
}
// Functions associated to deferred task woken by the callback function
void BuiltinButtonDeferred(void *pVParameters) {
(void)pVParameters;
for (;;) {
xSemaphoreTake(xSemaphoreBuiltinButton, portMAX_DELAY);
usart2_step(IRQ_BUILTIN_BUTTON);
}
}
I attached a debugger and after the call to transmit(msg)
in the case IRQ_BUILTIN_BUTTON:
the system gets stuck in the line xSemaphoreTake(xSemaphoreBuiltinButton, portMAX_DELAY);
of the BuiltinButtonDeferred
. If I stop the debugger, I end up in this line configASSERT( pxQueue->uxItemSize == 0 );
.
I am not sure, but it seems that after having taken the xSemaphoreBuiltinButton
, the program seems to try to take it again. But if I push again the builtin button in reality nothing happens.
Surprisingly, if instead I use the following:
case IRQ_BUILTIN_BUTTON:
// If I use the following two lines everything works!
strncpy(msg, "Button pressed!\r\n", MSG_LENGTH_MAX - 1);
msg[MSG_LENGTH_MAX - 1] = '\0';
// If I use this line everything gets stuck
// (void)snprintf(msg, MSG_LENGTH_MAX, "pippo: %s \n", a);
transmit(msg);
break;
where snprintf
is not used, then everything works smoothly.
The priority of the perodic task is 2, whereas the priority of the deferred task is configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
.