STM32WB5MMG核间通讯IPCC介绍-发送过程分析

  • Post author:
  • Post category:其他


当应用核心(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 版权协议,转载请附上原文出处链接和本声明。