cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H755: HSEM HAL_HSEM_Take() Not Blocking in FreeRTOS Task

Daniel_Ismail
Associate III

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.

 

3 REPLIES 3
Saket_Om
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

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?

Hello @Daniel_Ismail 

Please find below the HAL pattern for this use case. 

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

 

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om