HAL_SPI_TxCpltCallback wont called after creating mutex and before calling osKernelStart

I’m switching from using Keil-RTX to FREERTOS on a project with a lot of peripherals.
The problem is the HAL_SPI_TxCpltCallback not called if I creating mutex osRecursiveMutexCreate(osMutex(osMutex)); or osMutexCreate(osMutex(osMutex));

Before the mutex creation the callback called and it is OK.
It looks like the creating of the mutex disabling the interrupts.
and all of that is befor calling the ‘osKernelStart()’

This is the code I used to check:
extern SPI_HandleTypeDef hspi1;
HAL_SPI_Transmit_DMA(&hspi1,data_to_send, sizeof(data_to_send));

*in HAL_Init the command is exsist HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

Can you assist?

FreeRTOS disables interrupts before the scheduler starts. Do the stuff that needs interrupts after you start the scheduler.

Is there any way to pass it? (On keil it allows me)

Unless the OS is started, there realyy isn’t a point in allowing interrupts, unless these ISRs do not interact with any task or other components that are subject to scheduling. What exactly do you think your ISR can accomplish prior to OS startup? Remember that typically, there are few CPU cycles passed from reset until the OS is up and running. Do you need to servicer anything in that period?

If the scheduler has not been started then FreeRTOS will disable interrupts (or at least, mask interrupts up to configMAX_SYSCALL_INTERRUPT_PRIORITY) each time you call a FreeRTOS API. That is done to prevent interrupt service routines attempting to interact with tasks before the scheduler has started - which was one of the most common sources of support requests in the very early days. You can manually re-enable interrupts in between calls to the FreeRTOS API provided you are sure those interrupt service routines do not call any FreeRTOS API functions or attempt to perform a context switch.

As I mentioned I’m moving from Kyle-RTX to FreeRTOS. RTX seems to be more permissive.

My App works this way:

  1. initialize cube components (like standard).
  2. initialize app components.
    A. Creates various modules and objects.
    B. For each module there is MUTEX
    C. For some there are threads that are created and activated.
    D. There are 2 Timers that are also created and activated
    E. During the initialization of the objects there are a number of initializations calls to SPI and retrieval of data (data reading is required).
  3. osKernelStart()
    Threads begin to run and perform various tasks.

I understand that RTX is more permissive and allows for such work.

The way I think to solve the problem is
Create mutex / Threads / timers while running through active thread. Is it possible? Or do I have to create them before the kernel goes up? How do you propose to resolve this?

It works for me this way, thanks so much for the help, it’s just amazing the speed you respond and aids.

This requirement means that either you need to do it after starting the kernel or manually enable interrupts.

Yes, it should solve your problem.


There is a scheduler startup hook function you could do this from. Can’t provide link as not on my computer, but you could start the scheduler, do your start up stuff in the hook (callback) function, then create all the other tasks when done.

Or you could do the startup comms from the start of a task after the scheduling is running.

Or you could do the comms stuff before creating any FreeRTOS objects.

More details following upon aggarg’s explanation:

This implies that either your SPI driver is not OS aware at all (meaning there are no OS maintained ISR or task dependencies in the SPI driver) or the driver must be aware of the OS startup status and branch to different control paths depending on whether the OS is started or not. For example, you can not use mutex claim or release calls before the scheduler is up and running. Keil - like any other RTOS - must by definition do it that way.

You can mimick that behavior under FreeRTOS, but one of the things you need to be aware of is that this would perform a status check at each and every driver invocation (which would only yield the no-OS answer in a very very small percentage of all invocations). In particular regarding ISRs, that’s a lot of superflous code…