Skip to main content
Explorer
September 19, 2025
Question

STM32H755: HSEM HAL_HSEM_Take() Not Blocking in FreeRTOS Task

  • September 19, 2025
  • 1 reply
  • 580 views

Hello everyone,

I'm developing a dual-core FreeRTOS application on an STM32H755ZIT6 using STM32CubeIDE, and I'm facing an issue where the HSEM handshake is not working as expected.

My goal is to have a FreeRTOS task on the Cortex-M7 block and wait for a signal from the Cortex-M4.

Expected Behavior: The M7 task calls HAL_HSEM_Take() and should be blocked by the FreeRTOS scheduler until the M4 calls HAL_HSEM_Release() on the same semaphore.

Actual Behavior: The M7 task calls HAL_HSEM_Take() and it returns immediately, without blocking. This happens even when the corresponding HAL_HSEM_Release() call on the M4 is commented out for testing, causing the M7 task to loop continuously.

 

Debugging Steps I Have Already Taken

  1. Verified Core IDs: I have confirmed in the project properties that the M4 project has the CORE_CM4 define and the M7 project has the CORE_CM7 define.

  2. Implemented Handshake Logic: I have implemented the standard handshake where the M7 "primes" the lock by taking the semaphore once before the RTOS scheduler starts, and the task then calls HAL_HSEM_Take() in its main loop.

  3. Isolated the Issue: The problem persists even when all other tasks and logic are simplified. The HAL_HSEM_Take() call simply does not block.


Application Code

 

Here is the relevant code from my project.

shared_data.h (common to both cores)

#ifndef INC_SHARED_DATA_H_
#define INC_SHARED_DATA_H_

#include <stdint.h>

#define SHARED_MEM_ADDR 0x38000000

#define HSEM_ID_TOF_LOCK 1U
#define HSEM_ID_M7_NOTIFICATION 2U

typedef struct {
volatile uint32_t frame_count;
// ... other data members
} SharedTofData_t;

#define SHARED_TOF_DATA ((SharedTofData_t *)SHARED_MEM_ADDR)

#endif /* INC_SHARED_DATA_H_ */

 

Cortex-M4 main.c (Sender)

#include "main.h"
#include "shared_data.h"

// This function is called from the main while(1) loop when new sensor data is ready.
static void SEND_CMD_TOF_M7(void)
{
if (HAL_HSEM_FastTake(HSEM_ID_TOF_LOCK) == HAL_OK)
{
SHARED_TOF_DATA->frame_count++;

// Release the data lock
HAL_HSEM_Release(HSEM_ID_TOF_LOCK, 0);

// Send the notification signal to the CM7.
// NOTE: The M7 fails to block even when this line is commented out.
HAL_HSEM_Release(HSEM_ID_M7_NOTIFICATION, 0);

printf("-> Full dataset sent. Frame: %lu\r\n", SHARED_TOF_DATA->frame_count);
}
}

int main(void)
{
// ... Initialization ...

while (1)
{
// ... Logic to check for new sensor data ...
if (new_data_found)
{
SEND_CMD_TOF_M7();
}
}
}

 

Cortex-M7 main.c (Receiver)

#include "main.h"
#include "cmsis_os.h"
#include "shared_data.h"

// ... RTOS Task definitions ...

void StartHsemRxTask(void *argument)
{
for(;;)
{
// This call SHOULD block the task, but it returns immediately.
while (HAL_HSEM_FastTake(HSEM_ID_M7_NOTIFICATION) != HAL_OK) { osDelay(1); }
// This code is reached continuously, causing a stream of prints.
printf("Code shound't be reached until M4 notifies\r\n"); 

if (HAL_HSEM_FastTake(HSEM_ID_TOF_LOCK) == HAL_OK)
{
printf("--- [Direct Rx] Fetched Frame: %lu ---\r\n", SHARED_TOF_DATA->frame_count);
HAL_HSEM_Release(HSEM_ID_TOF_LOCK, 0);
}
}
}

int main(void)
{
// ... MCU and Peripheral Initialization ...

// Prime the notification semaphore by taking it once before the scheduler starts.
HAL_HSEM_FastTake(HSEM_ID_M7_NOTIFICATION);

/* Init scheduler */
osKernelInitialize();

// ... Create RTOS tasks (including HsemRxTask) ...

/* Start scheduler */
osKernelStart();

while (1) {}
}

 

My Question

Given that the issue occurs with this standard handshake logic and with confirmed Core ID settings, what could be the potential cause? Could this be a known issue with a specific HAL/CubeMX version, a toolchain problem, or is there another hardware configuration step I am missing for the HSEM to work correctly with FreeRTOS?

Thank you for your time and assistance.

 

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    September 19, 2025

    Hello @Daniel_Ismail 

    Your current implementation does not use the HSEM APIs correctly, as there is no waiting loop in the HAL_HSEM_Take() call. The HAL_HSEM_Take() function simply returns HAL_OK if it successfully acquires the semaphore, or HAL_ERROR otherwise, without blocking or waiting. Therefore, it is essential at the application level to systematically check the return value and implement a loop to wait until the semaphore is actually taken.

    Explorer
    September 19, 2025

    I need the CM7 task executes once per new frame from CM4 and never runs unless CM4 explicitly notifies via HSEM. From your note I understand HAL_HSEM_Take()/HAL_HSEM_FastTake() are non-blocking and must be wrapped in a wait loop. Could you please confirm the correct HAL pattern for this use case?

    Technical Moderator
    September 23, 2025

    Hello @Daniel_Ismail 

    Please find below the HAL pattern for this use case. 

    while (HAL_HSEM_Take(SEMAPHORE_ID, 0) != HAL_OK) 
    {
     
    }