matsbygg wrote on Friday, February 02, 2018:
Hi!
MCU: STM32F411VET6 100 MHz
FreeRTOS 9.0.0 (same thing happens in 10.0.0)
I have a problem using xQueueOverwriteFromISR() with a queue set.
xQueueSelectFromSet() tells that an item is available, but when trying to read out the item, xQueueReceive() returns pdFALSE.
If I instead use xQueueSendToBackFromISR(), everything (seems to) work normally. But this is not quite the functionality I want.
Here is a longer description of the problem area in my system:
I have a “timestamp” queue (length = 1) which I write to every ~20 ms using xQueueOverwriteFromISR() from an interrupt handler.
I have a “command” queue (length = 10) which I occationally write commands to using xQueueSendToBack() from a “command” task (task priority 1).
I have a “receiver” task (task priority 4) that waits on both of these queues using a queue set, and reads out data from the corresponding queue.
After a while of successful operation, the queue set indicates that an item in the “timestamp” queue is available, but when calling xQueueReceive(), it returns failure.
I have tried to isolate the problem in a simple standalone test application (below), but not fully succeeded.
In the below test application, I also get wrong behaviour (I think), after about 6 seconds, but at a different location than in my real system. (See comment in code where it fails.)
Because of the task priorities, and the wait time specified in xQueueSendToBack(), the “command” queue should not get full, but it does!
And also in the test application, if I replace xQueueOverwriteFromISR() with xQueueSendToBackFromISR(), everything works normally.
Anyone else have problems with Queue Sets and xQueueOverwriteFromISR() ?
And yes, the system should be properly set-up with HAL_Init() that calls HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4).
#include "ClockTick.h"
#include "HWTimer.h"
#include "SystemCore.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
QueueHandle_t command_queue;
QueueHandle_t timestamp_queue;
QueueSetHandle_t queue_set;
TaskHandle_t command_task_handle;
TaskHandle_t receiver_task_handle;
void hw_timer_callback(unsigned ch, void * user) // IRQ priority 6
{
BaseType_t higher_pri_task_woken = pdFALSE;
int value = 0;
// If I instead use xQueueSendToBackFromISR() here, everything works normally
(void) xQueueOverwriteFromISR(timestamp_queue, &value, &higher_pri_task_woken);
portYIELD_FROM_ISR(higher_pri_task_woken);
}
void command_task(void * param) // task priority 1
{
BaseType_t ret;
int value = 0;
for (;;)
{
vTaskDelay(20);
ret = xQueueSendToBack(command_queue, &value, 5);
// **** This assert fails after a while in this test application *****
configASSERT(ret == pdTRUE);
}
}
void receiver_task(void * param) // task priority 4
{
BaseType_t ret;
int value;
// Start recurring HW-timer (330 us timeout)
StartRecurringHWTimer(0, ClockTicksFrom_us(330), hw_timer_callback, NULL);
for (;;)
{
// Wait for command or timestamp
QueueSetMemberHandle_t handle = xQueueSelectFromSet(queue_set, 200);
if (handle == (QueueSetMemberHandle_t) timestamp_queue)
{
ret = xQueueReceive(timestamp_queue, &value, 0);
// **** This assert fails after a while in my real system *****
configASSERT(ret == pdTRUE);
}
else if (handle == (QueueSetMemberHandle_t) command_queue)
{
ret = xQueueReceive(command_queue, &value, 0);
configASSERT(ret == pdTRUE);
}
else
{
configASSERT(handle == NULL);
}
}
}
int main(void)
{
// Init system: HAL, clocks, etc.
ErrorHandler_Init();
SystemCore_Init();
ClockTick_Init();
HWTimer_Init();
// Create queues
command_queue = xQueueCreate(10, sizeof(int));
timestamp_queue = xQueueCreate(1, sizeof(int));
// Create queue sets
queue_set = xQueueCreateSet(10 + 1);
xQueueAddToSet((QueueSetMemberHandle_t)command_queue, queue_set);
xQueueAddToSet((QueueSetMemberHandle_t)timestamp_queue, queue_set);
// Create command and receiver tasks
xTaskCreate(command_task, "CMD", 3 * configMINIMAL_STACK_SIZE, NULL, 1, &command_task_handle);
xTaskCreate(receiver_task, "RCV", 3 * configMINIMAL_STACK_SIZE, NULL, 4, &receiver_task_handle);
vTaskStartScheduler();
return 0;
}
/*
#define configUSE_PREEMPTION 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configUSE_TICKLESS_IDLE 0
#define configCPU_CLOCK_HZ ( SystemCoreClock )
#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) /* Note! 1000 Hz is MAX, as HAL tick & FreeRTOS shares SysTick_Handler() */
#define configUSE_16_BIT_TICKS 0
#define configMAX_PRIORITIES 5
#define configUSE_TIME_SLICING 1
#define configIDLE_SHOULD_YIELD 1
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 130 )
#define configMAX_TASK_NAME_LEN 10
#define configUSE_TASK_NOTIFICATIONS 0
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_QUEUE_SETS 1
#define configUSE_ALTERNATIVE_API 0
#define configQUEUE_REGISTRY_SIZE 8
#define configUSE_NEWLIB_REENTRANT 1 /* Integrating with Newlib & Newlib-Nano */
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0
#define configUSE_APPLICATION_TASK_TAG 0
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
*/