cancel
Showing results for 
Search instead for 
Did you mean: 

Sharing data on STM32H745 using HSEM produces duplicate data

ConfusedContrarian
Associate III

Hello, I've been battling with this issue for a while now and I'm hoping someone has done something similar that can help with my issue.

I have a STM32H745 board with an IMU connected. I'm accquiring the data over the M4 core and then trying to send it to the M7 core using the HSEM (hardware semaphore). I'm basing my work off the examples on the ST project [here](https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Projects/STM32H745I-DISCO/Examples/HSEM/HSEM_ResourceSharing/CM7/Src).

The structure basically goes like this:

In a common header file, I have this which defines the buffer and the SRAM address space.

#define MEM_ALIGN(x)   (((x) + 0x00000003) & ~0x00000003)
  struct acc_data_t
  {
    float imu_acc_x;
    float imu_acc_y;
    float imu_acc_z;
  };
 
  #define SRAM4_ADDR     0x38000000
  #define SRAM4_LENGTH 	  0x0000FFFF
  #define ACC_BUFF_CM4_TO_CM7_ADDR  MEM_ALIGN(SRAM4_ADDR)
  #define ACC_BUFF_CM4_TO_CM7_LEN 	MEM_ALIGN(sizeof(acc_data_t))
  #define ACC_BUFFDATA_CM4_TO_CM7_ADDR MEM_ALIGN(ACC_BUFF_CM4_TO_CM7_ADDR + ACC_BUFF_CM4_TO_CM7_LEN)
  #define BUFF_ACC_LEN    MEM_ALIGN(0x00001000)

  Then on the CM4 side, I define the struct:

volatile struct acc_data_t* acc_values_m4 = (struct acc_data_t*)ACC_BUFF_CM4_TO_CM7_ADDR;

I then fill try to add the data to the address:

if(HAL_HSEM_FastTake(hsem_id) == HAL_OK)
	 {
		 acc_values_m4->imu_acc_x = imu.GetAccelData().x;
		 acc_values_m4->imu_acc_y = imu.GetAccelData().y;
		 acc_values_m4->imu_acc_z = imu.GetAccelData().z;
	 }
	 HAL_HSEM_Release(hsem_id);

This part seems to be fine, I see the data updates as expected on the M4. The problem arises when I try to retreive it on the m7 core. On the M7, I configure my MPU to be on cacheable and non-bufferable to prevent cache coherency issues.  

MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    MPU_InitStruct.BaseAddress = 0x38000000;
    MPU_InitStruct.Size = MPU_REGION_SIZE_64KB;
    MPU_InitStruct.SubRegionDisable = 0x0;
    MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
    MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
    MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
    MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
    MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    HAL_MPU_ConfigRegion(&MPU_InitStruct);
    /* Enables the MPU */
    HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
 

I use the HSEM IRQ Handler to handle the notification

void HSEM1_IRQHandler(void)
  {
  	uint32_t status_reg = HSEM_COMMON->MISR;
  	HSEM_COMMON->ICR = (status_reg);
  	NVIC_ClearPendingIRQ(HSEM1_IRQn);
  	LockUnlockCallback(status_reg); // custom function to change the HSEM for multiple IDs for each sensor
  }

I then do something similar to the m4:

volatile struct acc_data_t* acc_values_m7 = (struct acc_data_t*)ACC_BUFF_CM4_TO_CM7_ADDR;
void SensorData::ReadAcc()
  {
  	while(m7_state == hsem_id)
  	{
  		acc_data.imu_acc_x = acc_values_m7->imu_acc_x;
  		acc_data.imu_acc_y = acc_values_m7->imu_acc_y;
  		acc_data.imu_acc_z = acc_values_m7->imu_acc_z;
 
  // Some things I tried that didn't work // Don't think they are required
    		 //HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(hsem_id));
    		SCB_InvalidateDCache_by_Addr((uint32_t*) &acc_values_m7, BUFF_ACC_LEN);
    	}
  }

Unfortunately, the data on the M7 side seems to repeat ever so often and I'm not sure why. A sample output is shown below.

0693W00000WJ9IeQAL.png 

I'm not sure if I'm making a very obvious mistake here. I've looked around and tried all sorts of tricks. The only one that seems to have worked is Tijen Majerle's [ring buffer implementation] but this doesn't seem to make use of the HSEM. I'm looking for a HSEM solution partly out of curiosity and partly for performance reasons down the line.

0 REPLIES 0