@hs2, at this point in my struggle, any brainstorming is helpful.
I just implemented a solution similar to what you suggested, but it is definitely not elegant.
The management task has the following:
struct TASK_SYNC_HELPER
{
xQueueHandle q;
EventGroupHandle_t e;
};
typedef struct TASK_SYNC_HELPER TaskSyncronizer_t;
static TaskSyncronizer_t TSync[2];
static int8_t tSyncIndex = 0;
Every time the management task decides to allow access, it toggles which struct get’s used:
// Swap the task synchronizer structs
int8_t TSyncHandleIndex;
vTaskSuspendAll();
TSyncHandleIndex = tSyncIndex;
tSyncIndex = (tSyncIndex + 1) & 1;
xTaskResumeAll();
// From this point on, all registrations will be on the other queue
// Signal all tasks that have registered
xEventGroupSetBits( TSync[TSyncHandleIndex].e, UAPP_EVT_RAM_STABLE );
// Consume the queue
xSemaphoreHandle s;
int8_t SyncTaskCount = 0;
while ( pdTRUE == xQueueReceive( TSync[TSyncHandleIndex].q, &s, 0))
{
SyncTaskCount++;
// We have the semaphore that the task will use to signal when it's done.
xSemaphoreTake( s, portMAX_DELAY);
}
xEventGroupClearBits( TSync[TSyncHandleIndex].e, UAPP_EVT_RAM_STABLE );
As you might notice, the event no longer get’s Sync-ed, but is Set. This prevents the user tasks from sending to the queue and then missing the event.
As you can see, the management task just depletes the queue. What is in the queue is a semaphore that the user tasks give when they are gone.
Here is what the tasks do when they want to “register” and wait for the common resource:
int8_t CurrIndex;
vTaskSuspendAll();
CurrIndex = tSyncIndex;
xQueueSend(TSync[CurrIndex].q, &DoneSemaphore ,0 );
// Once the above completes, we will get the event because the management task will be waiting on our semaphore before clearing the event.
xTaskResumeAll();
// Wait for the event
EventBits_t RetBits = xEventGroupWaitBits( TSync[CurrIndex].e, EventMask, pdTRUE, pdTRUE, uiMaxWaitTicks);
The above has a bunch of error checking removed for brevity.
When the user task gets the event, it goes to work and when it’s done…
xSemaphoreGive( DoneSemaphore );
As I said, this is quite ugly and all the error-checking that needs to happen is annoying, but I just tried it and it worked once in a row
Anyways, I’d love to hear a better solution. I’m sharing my current one for others that might search the forums. Thank you all, and if anyone has a better idea, by all means, let me know.