Failing listTEST_LIST_ITEM_INTEGRITY when taking multiple binary semaphores- Kernel V10.4.5 on Teensy 4.1

I’m using FreeRTOS kernel V10.4.5 on a Teensy 4.1 development board.

In main.cpp, I have defined two semaphores, semaphore_a and semaphore_b. I also have an initialization function ctrl_init(), which is the first function called from main(), and is intended to initialize and take these semaphores.

SemaphoreHandle_t semaphore_a = NULL;
SemaphoreHandle_t semaphore_b = NULL;

static void ctrl_init(void) {
    semaphore_a = xSemaphoreCreateMutex();
    xSemaphoreTake(semaphore_a, portMAX_DELAY);

    semaphore_b = xSemaphoreCreateMutex();
    xSemaphoreTake(semaphore_b, portMAX_DELAY);

This has worked without issue. However, if I attempt to convert these semaphores to binary semaphores instead of mutexes, like so:

static void ctrl_init(void) {
    semaphore_a = xSemaphoreCreateBinary();
    xSemaphoreTake(semaphore_a, portMAX_DELAY);

    semaphore_b = xSemaphoreCreateBinary();
    xSemaphoreTake(semaphore_b, portMAX_DELAY);

then I get the following error message over my serial connection to the Teensy board:

ASSERT in [.pio/libdeps/teensy41/freertos-teensy/src/list.c:127] vListInsert(): ( ( pxNewListItem )->xListItemIntegrityValue1 == 0x5a5a5a5aUL ) && ( ( pxNewListItem )->xListItemIntegrityValue2 == 0x5a5a5a5aUL )

The referenced ASSERT seems to be the macro listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); in vListInsert().

I do not see this behavior (everything behaves as expected) if I comment out either of the xSemaphoreTake lines from my initialization function, or if either or both of the semaphores are created with xSemaphoreCreateMutex.

I do not have a debugger on hand, so unfortunately cannot see the whole stack trace. I also understand that there are other ways to accomplish what I am trying to do here. All the same, I would like to understand, why is this crash happening? What is different between binary semaphores and mutexes which may account for this difference in behavior?

Appreciate any help I can get!

Do I understand correctly that you are calling these functions before the scheduler starts? If so I can see two problems.

The first is the use of portMAX_DELAY - you cannot block if the scheduler is not running - try setting that parameter to 0 (zero) instead.

When you specify a 0 block time I would expect the code to work when you create a binary semaphore, but fail when you create a a mutex. The reason is the priority inheritance mechanism implemented for mutexes associates a mutex with the calling task - but if you haven’t started the scheduler there isn’t a running task.

Stumbled into what seems to be a solution shortly after posting. From the documentation for xSemaphoreCreateBinary():

The semaphore is created in the ‘empty’ state, meaning the semaphore must first be given using the xSemaphoreGive() API function before it can subsequently be taken (obtained) using the xSemaphoreTake() function.

Still not certain why it worked when I only created a single binary semaphore, but adding xSemaphoreGive seemed to solve the issue.