在双核系统中,不同的核心(Core)可能会同时尝试访问同一个资源(如LED、外设、共享内存等),这可能导致数据不一致或资源冲突。为了解决这个问题,硬件信号量(HSEM)提供了一种有效的同步手段。
具体该怎么做呢:
1、初始化HSEM:在系统启动时,初始化硬件信号量,设置其初始状态为“空闲”(即未被任何核心占用)。
2、获取HSEM:当某个核心需要访问LED资源时,它首先尝试获取硬件信号量。如果信号量当前处于“空闲”状态,则该核心成功获取信号量,并将其状态设置为“占用”。如果信号量已被其他核心占用,则该核心需要等待,直到信号量被释放。
3、访问LED资源:在成功获取硬件信号量后,核心可以安全地访问LED资源,进行必要的操作(如点亮、熄灭等)。
4、释放HSEM:在完成对LED资源的访问后,核心需要释放硬件信号量,将其状态设置回“空闲”,以便其他核心可以访问该资源。
下面假设CM7、CM4都要控制LED1,用HSEM保证LED资源互斥访问
1、CM4中注释HSEM中断处理函数
//void HAL_HSEM_FreeCallback(uint32_t SemMask)
//{
// notifReceived=1;
// HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
//}
中断用于CM7释放信号量后通知CM4可以操作,适用于两核循环执行的场景。
本例中CM7、CM4谁获得了信号量,谁控制LED。
2、CM7、CM4都要对LED1做初始化
/*Configure GPIO pin : LED1_Pin */
GPIO_InitStruct.Pin = LED1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED1_GPIO_Port, &GPIO_InitStruct);
这样两核都可以控制LED1亮灭。
3、CM7 while(1)中快速亮灭LED1
if(HAL_HSEM_Take(HSEM_ID_0,5)==HAL_OK)
{
for(int i=0;i<6;i++)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_Delay(100);
}
HAL_HSEM_Release(HSEM_ID_0,5);
}
if(HAL_HSEM_Take(HSEM_ID_0,5)==HAL_OK) 获取信号量,5是进程ID,
获取信号量成功,翻转LED1六次。
HAL_HSEM_Release(HSEM_ID_0,5);释放信号量
4、CM4 while(1)中慢速亮灭LED1
if(HAL_HSEM_Take(HSEM_ID_0,5)==HAL_OK)
{
for(int i=0;i<6;i++)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);
HAL_Delay(1000);
}
HAL_HSEM_Release(HSEM_ID_0,5);
}
CM7、CM4都通过HAL_HSEM_Take函数获得信号量,谁获得信号量谁执行LED1翻转。
5、运行效果
CM7获得了信号量快速翻转LED1六次,释放信号量。
CM4获得了信号量慢速翻转LED1六次,释放信号量。
|