【简介】
S32K3 是一个多核的芯片,在硬件的设计上是存在硬件的锁机制来实现核心之间的互斥访问,对应的 SEMA42 这个IP 继承了硬件的互斥锁锁机制。从以下这张图也可以看出,S32K3 系列芯片多核的MCU芯片都是集成了 SEMA42 这个IP.

SEMA42 的驱动配置可以通过S32DS 的RM 模块来配置。

勾选上SEM后在Sem42 下配置使用的硬件 channel 配置。

配置好后更新代码后 SEMA42 相关的驱动代码已经被加入工程中。

以下是SEMA42 的功能框图,从以下的描述可以知道SEMA42 可以被不同的domain 来持有,对应的通道被lock 状态只有对应的 domain 才可以 unlock,每个核心可以配置DID该部分需要在XRDC中进行配置,对于XDRC的配置可以查看此贴(【S32K3XX】XRDC 功能使用)。

以下是SEMA42 IP 的驱动接口说明,接口的用法说明还是比较简单的。


我们只需要Sema42_Ip_Init,Sema42_Ip_LockGate,Sema42_Ip_UnlockGate 即可以完成核间的互斥访问保护临界资源。
以下是本地 core0(domain id = 0),core1(domain id = 1),对一块共享内存区域进行保护代码。
core0 的测试代码
/* Sema42 init */
Sema42_Ip_Init(SEMA42_INSTANCE0);
while(SEMA42_IP_ERROR == Sema42_Ip_LockGate(SEMA42_INSTANCE0,0,0))
{
vTaskDelay(10);
}
while(RingBuffer_GetDataLength(&pvuart->master_rx_slave_tx))
{
RingBuffer_Read(&pvuart->master_rx_slave_tx,&data,1);
PRINTF("%c",data);
}
if(SEMA42_IP_ERROR == Sema42_Ip_UnlockGate (SEMA42_INSTANCE0,0))
{
PRINTF("Unlock gate failed.\n");
}core1 的测试代码
while(SEMA42_IP_ERROR == Sema42_Ip_LockGate(SEMA42_INSTANCE0,0,1))
{
//vTaskDelay(10);
}
ret = RingBuffer_Read((RingBuffer *)(&pvuart->master_tx_slave_rx),pdata,1);
if(SEMA42_IP_ERROR == Sema42_Ip_UnlockGate (SEMA42_INSTANCE0,0))
{
PRINTF("Unlock gate failed.\n");
}验证了SEMA42 的lock/unlock 功能我们继续验证获取channel 的状态信息,我们早CORE1 上lock 住channel2,然后在CORE0上获取channel2 的状态,分别在CORE0/CORE1上添加如下的测试代码来操作 lock/unlock/getlocker。
unsigned int sema42(char argc, char **argv)
{
if(argc == 3 && strcmp(argv[1],"lock") == 0)
{
uint8_t gate = (uint8_t)atoi(argv[2]);
if(SEMA42_IP_ERROR == Sema42_Ip_LockGate(SEMA42_INSTANCE0,gate,CFG_XRDC_DID))
{
PRINTF("Lock gate failed.\n");
}
else
{
PRINTF("Lock gate success.\n");
}
}
else if(argc == 3 && strcmp(argv[1],"unlock") == 0)
{
uint8_t gate = (uint8_t)atoi(argv[2]);
if(SEMA42_IP_ERROR == Sema42_Ip_UnlockGate (SEMA42_INSTANCE0,gate))
{
PRINTF("Unlock gate failed.\n");
}
else
{
PRINTF("Unlock gate success.\n");
}
}
else if(argc == 3 && strcmp(argv[1],"locker") == 0)
{
uint8_t gate = (uint8_t)atoi(argv[2]);
PRINTF("Gate locker: %d\n", Sema42_Ip_GetGateLocker(SEMA42_INSTANCE0,gate));
}
else
{
PRINTF("Usage:\n");
PRINTF(" sema42 lock <gate_index>\n");
PRINTF(" sema42 unlock <gate_index>\n");
PRINTF(" sema42 locker <gate_index>\n");
}
return 0;
}本地如下测试:
step1: core1 lock gate2
step2:core0 lock gate2
step3:core0 get locker
运行结果和预期的一致,core0 获取锁失败,查询锁状态为core1 持有。

我要赚赏金
