当应用核心(M4)向协议栈核心(M0+)发送数据的时候,先把数据放到指定的RAM通用区域并且设置对应的通道使能,然后状态CHnF变为1,此时M0+核心收到中断,取走数据并且清对应的CHnF为0,M4收到对应通道空闲中断,知道数据已经发送完成。至此完成了一次M4到M0+的同步调用。
以M4发送系统HCI命令为例:
send过程:
void shci_send( uint16_t cmd_code, uint8_t len_cmd_payload,
uint8_t * p_cmd_payload, TL_EvtPacket_t * p_rsp )
{
Cmd_SetStatus(SHCI_TL_CmdBusy);//加锁
//填充通用区域,相当于共享内存通讯
pCmdBuffer->cmdserial.cmd.cmdcode = cmd_code;
pCmdBuffer->cmdserial.cmd.plen = len_cmd_payload;
memcpy(pCmdBuffer->cmdserial.cmd.payload,
p_cmd_payload, len_cmd_payload );
//实际调用HW_IPCC_SYS_SendCmd函数,会设置对应的通道标志,通知M0+取数
shciContext.io.Send(0,0);
//调用osSemaphoreAcquire(SemShciId, osWaitForever)等待对应的通道空闲中断
//IPCC_C1_TX_IRQHandler会处理该中断,具体看response过程
shci_cmd_resp_wait(SHCI_TL_DEFAULT_TIMEOUT);
/**
* The command complete of a system command does not have the header
* It starts immediately with the evtserial field
*/
memcpy( &(p_rsp->evtserial), pCmdBuffer,
((TL_EvtSerial_t*)pCmdBuffer)->evt.plen + TL_EVT_HDR_SIZE );
Cmd_SetStatus(SHCI_TL_CmdAvailable);//释放锁
return;
}
int32_t TL_SYS_SendCmd( uint8_t* buffer, uint16_t size )
{
(void)(buffer); (void)(size);//两个参数实际没用到
((TL_CmdPacket_t *)(TL_RefTable.p_sys_table->pcmd_buffer))->cmdserial.type = TL_SYSCMD_PKT_TYPE;
OutputDbgTrace(TL_MB_SYS_CMD, TL_RefTable.p_sys_table->pcmd_buffer);
HW_IPCC_SYS_SendCmd();//数据都填充完了就可以设置对应通道状态来通知协议栈处理器
return 0;
}
//IPCC->C1SCR中发送通道HW_IPCC_SYSTEM_CMD_RSP_CHANNEL 置位,
//并且使能HW_IPCC_SYSTEM_CMD_RSP_CHANNEL通道中断
void HW_IPCC_SYS_SendCmd( void ) {
LL_C1_IPCC_SetFlag_CHx( IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL );
LL_C1_IPCC_EnableTransmitChannel( IPCC, HW_IPCC_SYSTEM_CMD_RSP_CHANNEL );
return;
}
response过程:
//当M0+收到系统指令后会清对应通道为空闲,触发M4的IPCC_C1_TX_IRQHandler中断,
//调用过程为IPCC_C1_TX_IRQHandler->HW_IPCC_Tx_Handler
void HW_IPCC_Tx_Handler( void )
{
/*if条件中展开为( !(LL_C1_IPCC_IsActiveFlag_CHx( IPCC, channel )) ) && (((~(IPCC->C1MR)) & (channel << 16U)))
其中!(LL_C1_IPCC_IsActiveFlag_CHx( IPCC, channel ))为1代表CH2F清零,也就
是HW_IPCC_SYSTEM_CMD_RSP_CHANNEL通道空闲了,说明M0+已经把命令数据取走,
(((~(IPCC->C1MR)) & (channel << 16U)))用来判断该通道是否已经使能,在send过
程中的HW_IPCC_SYS_SendCmd函数中使能了。
*/
if (HW_IPCC_TX_PENDING( HW_IPCC_SYSTEM_CMD_RSP_CHANNEL ))
{
HW_IPCC_SYS_CmdEvtHandler();//下面展开讲
}
//省略其他通道判断...
}
static void HW_IPCC_SYS_CmdEvtHandler( void )
{
//屏蔽HW_IPCC_SYSTEM_CMD_RSP_CHANNEL通道发送空闲中断
LL_C1_IPCC_DisableTransmitChannel( IPCC,
HW_IPCC_SYSTEM_CMD_RSP_CHANNEL );
HW_IPCC_SYS_CmdEvtNot();
return;
}
void HW_IPCC_SYS_CmdEvtNot(void)
{
//实际调用TlCmdEvtReceived函数,该函数调用shci_cmd_resp_release,最终
//osSemaphoreRelease(SemShciId)让send过程的shci_cmd_resp_wait函数返回。
SYS_CMD_IoBusCallBackFunction( (TL_EvtPacket_t*)
(TL_RefTable.p_sys_table->pcmd_buffer) );
return;
}
其他通道同步调用也是类似的,在此不再赘述。
版权声明:本文为weixin_39676041原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。