STM32WB5MMG启动代码流程分析

1.HAL_Init();

HAL_StatusTypeDef HAL_Init(void)
{
  HAL_StatusTypeDef status = HAL_OK;
  /* Configure Flash prefetch, Instruction cache, Data cache */
  /* Default configuration at reset is: */
  /* - Prefetch disabled */
  /* - Instruction cache enabled */
  /* - Data cache enabled */
  __HAL_FLASH_PREFETCH_BUFFER_ENABLE();//使能CPU1指令预取
   
  /* Set Interrupt Group Priority */
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//4位全部用来做抢占优先级,也就是最多16级中断优先级
   
  /* Use SysTick as time base source and configure 1ms tick (default clock after Reset is MSI) */
  if (HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
  {
    status = HAL_ERROR;
  }
  else
  {
    /* Init the low level hardware */
    HAL_MspInit();//具体到函数内部初始化了HSEM以及它的中断, PendSV中断优先级设置为最低
  }
   
  /* Return function status */
  return status;
}

2.MX_APPE_Config();

void MX_APPE_Config( void )
{
  /**
  * The OPTVERR flag is wrongly set at power on
  * It shall be cleared before using any HAL_FLASH_xxx() api
  */
  __HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_OPTVERR );
   
  /**
  * Reset some configurations so that the system behave in the same way
  * when either out of nReset or Power On
  */
  Reset_Device( );//1.根据复位原因决定是否重置备份域,例如软复位不需要重置,还会保持上一次的配置。
  //2.使能IPCC时钟,并且关闭CPU1和CPU2 IPCC所有的发送和接收中断
   
  /* Configure HSE Tuning */
  Config_HSE();//根据OTP存储的值,调节HSE的电容。采用官方模块的优势!
   
  return;
}

3.时钟和外设配置
SystemClock_Config();//按照cube配置的时钟树进行时钟配置,详见对应的.ioc文件
PeriphCommonClock_Config();//配置SMPS 以及 配置RF 唤醒时钟源为LSE
MX_IPCC_Init();//配置IPCC时钟,使能cpu1 NVIC中IPCC发送和接收中断,但是屏蔽了IPCC外设的发送接收中断。
MX_GPIO_Init();
MX_RF_Init();//目前是个空函数!
UserRTCInit();//cube中设置不要自动生成MX_RTC_Init();否则会提前打开wakeup中断

4.MX_APPE_Init();

void MX_APPE_Init( void )
{
  //里面的SMPS函数为空,Init_Exti使能了EXTI_LINE_36(IPCC用)和
  //EXTI_LINE_38(HSEM用),Init_Rtc选择RTC唤醒时钟源
  System_Init( );
   
  //选择HSI作为stop唤醒后的系统时钟,LPM配置只是把两个标志位设置了下,
  //CPU2进入深度睡眠的时候进入shutdown模式。
  SystemPower_Config(); 
   
  HW_TS_Init(hw_ts_InitMode_Full, &hrtc); //RTC做软定时器配置
   
  /* USER CODE BEGIN APPE_Init_1 */
  
  /**
  * The Standby mode should not be entered before the initialization is over
  * The default state of the Low Power Manager is to allow the Standby Mode so an request is needed here
  */
  UTIL_LPM_SetOffMode(1 << CFG_LPM_APP, UTIL_LPM_DISABLE);
  
  /* USER CODE END APPE_Init_1 */
  appe_Tl_Init(); //传输层初始化,后面展开讲
   
  /**
  * From now, the application is waiting for the ready event ( VS_HCI_C2_Ready )
  * received on the system channel before starting the Stack
  * This system event is received with APPE_SysUserEvtRx()
  */
  /* USER CODE BEGIN APPE_Init_2 */
   
  /* USER CODE END APPE_Init_2 */
  return;
}
static void appe_Tl_Init( void )
{
  TL_MM_Config_t tl_mm_config;
  SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf;
  /**< Reference table initialization */
  TL_Init();//TL_RefTable管理结构体赋值,CPU1 IPCC发送接收中断使能
   
  //用来锁M4向M0+发起系统命令的调用
  MtxShciId = osMutexNew( NULL );
  
  /*当向M0+发起system hci调用,M0+接收后会产生一个IPCC通道空中断,
    中断中释放该信号量通知应用程序发送完成。*/
  SemShciId = osSemaphoreNew( 1, 0, NULL );
   
  /** M0+协议栈核心准备完成后会通过IPCC_RX通道通知M4,M4会唤醒该任务进行处理 */
  ShciUserEvtProcessId = osThreadNew(ShciUserEvtProcess, NULL, &ShciUserEvtProcess_attr);
   
  /**< System channel initialization */
  SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&SystemCmdBuffer;
  SHci_Tl_Init_Conf.StatusNotCallBack = APPE_SysStatusNot;
  //赋值一些指针变量,IPCC通道2作为system event接收通道,后面展开讲
  shci_init(APPE_SysUserEvtRx, (void*) &SHci_Tl_Init_Conf);
   
  /**< Memory Manager channel initialization */
  tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer;
  tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer;
  tl_mm_config.p_AsynchEvtPool = EvtPool;
  tl_mm_config.AsynchEvtPoolSize = POOL_SIZE;
  /*初始化各种buf,主要用来接收缓存,调用该函数后
    *TL_RefTable.p_mem_manager_table = {
        .blepool = EvtPool,//[1340]
        .blepoolsize = POOL_SIZE,//1340当CFG_TLBLE_EVT_QUEUE_LENGTH = 5
        .pevt_free_buffer_queue = (uint8_t*)&FreeBufQueue,
        .spare_ble_buffer = BleSpareEvtBuffer,//[266] = sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255
        .p_mem_manager_table->spare_sys_buffer = SystemSpareEvtBuffer,//[266]
        .traces_evt_pool = ?,//初始化后这个是个野值!
        .tracespoolsize = ?,//初始化后这个是个野值!
    }
  */
  TL_MM_Init( &tl_mm_config );
  
  //该函数调用HW_IPCC_Enable,使能CPU2的IPCC时钟以及相关中断,
  //用__SEV通知cpu2,然后cpu1用__WFE等待掉这个事件,相当于清理该事件,
  //最后启动无线处理器CPU2.
  //__SEV解释:多处理器环境中向所有的处理器发送事件(包括自身)。在符合CMSIS的设备驱动库中,可以使用“__SEV()”实现该操作.
  TL_Enable();
   
  return;
}
void shci_init(void(* UserEvtRx)(void* pData), void* pConf)
{
  //StatusNotCallBackFunction赋值为APPE_SysStatusNot,
  //该函数利用MtxShciId互斥锁,来保证多线程system hci cmd调用互斥。
  StatusNotCallBackFunction = ((SHCI_TL_HciInitConf_t *)pConf)->StatusNotCallBack;
  
  //shciContext.UserEvtRx=APPE_SysUserEvtRx,
  //当M0+准备完成后会通过IPCC RX通道通知M4调用该函数
  shciContext.UserEvtRx = UserEvtRx;
   
  //该函数会赋值shciContext.io.Init = TL_SYS_Init以及
  //shciContext.io.Send = TL_SYS_SendCmd;
  shci_register_io_bus (&shciContext.io);
   
  //后面展开讲
  TlInit((TL_CmdPacket_t *)(((SHCI_TL_HciInitConf_t *)pConf)->p_cmdbuffer));
   
  return;
}
static void TlInit( TL_CmdPacket_t * p_cmdbuffer )
{
  TL_SYS_InitConf_t Conf;
   
  pCmdBuffer = p_cmdbuffer;//=SystemCmdBuffer
   
  LST_init_head (&SHciAsynchEventQueue);
   
  Cmd_SetStatus(SHCI_TL_CmdAvailable);//SHCICmdStatus = SHCI_TL_CmdAvailable;
   
  SHCI_TL_UserEventFlow = SHCI_TL_UserEventFlow_Enable;
   
  /* Initialize low level driver */
  if (shciContext.io.Init)
  {
    Conf.p_cmdbuffer = (uint8_t *)p_cmdbuffer;//=SystemCmdBuffer
    Conf.IoBusCallBackCmdEvt = TlCmdEvtReceived;
    Conf.IoBusCallBackUserEvt = TlUserEvtReceived;
    shciContext.io.Init(&Conf);//调用TL_SYS_Init
  }
   
  return;
}
int32_t TL_SYS_Init( void* pConf )
{
  MB_SysTable_t * p_systable;
   
  TL_SYS_InitConf_t *pInitHciConf = (TL_SYS_InitConf_t *) pConf;
   
  LST_init_head (&SystemEvtQueue);
  p_systable = TL_RefTable.p_sys_table;
  
  //TL_RefTable.p_sys_table->pcmd_buffer = SystemCmdBuffer;
  //M4利用该buffer发起系统HCI同步调用。
  p_systable->pcmd_buffer = pInitHciConf->p_cmdbuffer;
  
  //TL_RefTable.p_sys_table->sys_queue = (uint8_t*)&SystemEvtQueue;
  //M0+利用该queue给M4发送异步事件
  p_systable->sys_queue = (uint8_t*)&SystemEvtQueue;
   
  HW_IPCC_SYS_Init();//使能system event 接收通道
   
  //SYS_CMD_IoBusCallBackFunction=TlCmdEvtReceived
  //该函数会在M4发送完系统HCI命令后,发送通道空中断中调用,通知M4命令已经发送完成
  SYS_CMD_IoBusCallBackFunction = pInitHciConf->IoBusCallBackCmdEvt;
  
  //SYS_EVT_IoBusCallBackFunction =TlUserEvtReceived
  //该函数会在M0+发送了系统异步事件后,由IPCC接收中断函数调用
  SYS_EVT_IoBusCallBackFunction = pInitHciConf->IoBusCallBackUserEvt;
   
  return 0;
}

5.CPU2准备完成后
经过以上配置后,CPU2协议栈准备完成,CPU1会通过IPCC RX通道接收到事件,函数调用路径HW_IPCC_Rx_Handler->HW_IPCC_SYS_EvtHandler->HW_IPCC_SYS_EvtNot, HW_IPCC_SYS_EvtNot函数从SystemEvtQueue中取出事件,并且通过SYS_EVT_IoBusCallBackFunction(指向TlUserEvtReceived)函数将事件压入SHciAsynchEventQueue, 接着调用shci_notify_asynch_evt(虽然入参是SHciAsynchEventQueue的地址,但是并没有使用),该函数调用osThreadFlagsSet( ShciUserEvtProcessId, 1 ),触发ShciUserEvtProcess任务启动。
shci_user_evt_proc函数 发现SHciAsynchEventQueue不为空,则取出开头的事件进行处理,调用shciContext.UserEvtRx(指向APPE_SysUserEvtRx)函数,该函数首先获取无线协议栈版本号,然后根据subevtcode判断进入哪个处理分支,首次上电后,第一条一般是SHCI_SUB_EVT_CODE_READY,所以这里调用APPE_SysEvtReadyProcessing函数,正常情况下该ready指示的是WIRELESS_FW_RUNNING,所以进入该分支,配置CPU2 debug相关的功能后,调用APP_BLE_Init()。
BLE的事件接收通道HW_IPCC_BLE_EVENT_CHANNEL 为 1

void APP_BLE_Init( void )
{
  SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet =
  {
    {{0,0,0}}, /**< Header unused */
    { 0, /** pBleBufferAddress not used */
      0, /** BleBufferSize not used */
      CFG_BLE_NUM_GATT_ATTRIBUTES,
      CFG_BLE_NUM_GATT_SERVICES,
      CFG_BLE_ATT_VALUE_ARRAY_SIZE,
      CFG_BLE_NUM_LINK,
      CFG_BLE_DATA_LENGTH_EXTENSION,
      CFG_BLE_PREPARE_WRITE_LIST_SIZE,
      CFG_BLE_MBLOCK_COUNT,
      CFG_BLE_MAX_ATT_MTU,
      CFG_BLE_SLAVE_SCA,
      CFG_BLE_MASTER_SCA,
      CFG_BLE_LSE_SOURCE,
      CFG_BLE_MAX_CONN_EVENT_LENGTH,
      CFG_BLE_HSE_STARTUP_TIME,
      CFG_BLE_VITERBI_MODE,
      CFG_BLE_OPTIONS,
      0,
      CFG_BLE_MAX_COC_INITIATOR_NBR,
      CFG_BLE_MIN_TX_POWER,
      CFG_BLE_MAX_TX_POWER,
      CFG_BLE_RX_MODEL_CONFIG,
      CFG_BLE_MAX_ADV_SET_NBR,
      CFG_BLE_MAX_ADV_DATA_LEN,
      CFG_BLE_TX_PATH_COMPENS,
      CFG_BLE_RX_PATH_COMPENS}
    }
  };
 
  /**
  * Initialize Ble Transport Layer
  */
  Ble_Tl_Init( );//和appe_Tl_Init的前半部分很像,这个初始化的是HCI相关
 
  /**
  * Do not allow standby in the application
  */
  UTIL_LPM_SetOffMode(1 << CFG_LPM_APP_BLE, UTIL_LPM_DISABLE);
 
  /**
  * Register the hci transport layer to handle BLE User Asynchronous Events
  */
  HciUserEvtProcessId = osThreadNew(HciUserEvtProcess, NULL, &HciUserEvtProcess_attr);
   
/**
* Starts the BLE Stack on CPU2
*/
if (SHCI_C2_BLE_Init( &ble_init_cmd_packet ) != SHCI_Success)//用ble_init_cmd_packet中的参数配置BLE
{
Error_Handler();
}
 
/**
* Initialization of HCI & GATT & GAP layer
*/
Ble_Hci_Gap_Gatt_Init();//配置各种秘钥,BLE角色设置,广播名,目前暂定“218A”,
 
/**
* Initialization of the BLE Services
*/
SVCCTL_Init();//主要调用SVCCTL_SvcInit函数,该函数调用如下函数
//BAS_Init(); BLS_Init(); CRS_STM_Init();//这三个直接为空
//DIS_Init();//初始化DIS(Device Information Service), 其中的2A29是厂商名称字符串UUID。
//EDS_STM_Init(); HIDS_Init(); //这两个直接为空
//HRS_Init();//初始化heart rate服务(180D),包含三个特性 NOTIFY(2A37)、read(2A38)、write(2A39)
//HTS_Init(); IAS_Init(); LLS_Init(); TPS_Init(); MOTENV_STM_Init(); P2PS_STM_Init(); ZDD_STM_Init(); OTAS_STM_Init(); BVOPUS_STM_Init(); 空
//MESH_Init(); SVCCTL_InitCustomSvc(); 空
 
/**
* Initialization of the BLE App Context
*/
BleApplicationContext.Device_Connection_Status = APP_BLE_IDLE;
BleApplicationContext.BleApplicationContext_legacy.connectionHandle = 0xFFFF;
/**
* From here, all initialization are BLE application specific
*/
AdvUpdateProcessId = osThreadNew(AdvUpdateProcess, NULL, &AdvUpdateProcess_attr);//创建广播任务,该任务非常简单就是等快速
//广播结束后切换到低功耗广播,最终程序需要考虑删掉,只用低功耗广播模式即可
 
/**
* Initialization of ADV - Ad Manufacturer Element - Support OTA Bit Mask
*/
#if(BLE_CFG_OTA_REBOOT_CHAR != 0)
manuf_data[sizeof(manuf_data)-8] = CFG_FEATURE_OTA_REBOOT;
#endif
/**
* Initialize DIS Application
*/
DISAPP_Init();//空
 
/**
* Initialize HRS Application
*/
HRSAPP_Init();//创建HrsProcess任务
 
/* USER CODE BEGIN APP_BLE_Init_3 */
 
/* USER CODE END APP_BLE_Init_3 */
 
/**
* Create timer to handle the connection state machine
*/
 
HW_TS_Create(CFG_TIM_PROC_ID_ISR, &(BleApplicationContext.Advertising_mgr_timer_Id), hw_ts_SingleShot, Adv_Mgr);
 
/**
* Make device discoverable
*/
BleApplicationContext.BleApplicationContext_legacy.advtServUUID[0] = AD_TYPE_16_BIT_SERV_UUID;
BleApplicationContext.BleApplicationContext_legacy.advtServUUIDlen = 1;
Add_Advertisment_Service_UUID(HEART_RATE_SERVICE_UUID);
/* Initialize intervals for reconnexion without intervals update */
AdvIntervalMin = CFG_FAST_CONN_ADV_INTERVAL_MIN;
AdvIntervalMax = CFG_FAST_CONN_ADV_INTERVAL_MAX;
 
/**
* Start to Advertise to be connected by Collector
*/
Adv_Request(APP_BLE_FAST_ADV);//APP_BLE_FAST_ADV 会启动Advertising_mgr_timer_Id定时器,定时60s,然后触发AdvUpdateProcess任务切换到低功耗广播模式
 
/* USER CODE BEGIN APP_BLE_Init_2 */
 
/* USER CODE END APP_BLE_Init_2 */
return;
}
static void Ble_Tl_Init( void ) {
    HCI_TL_HciInitConf_t Hci_Tl_Init_Conf;

    MtxHciId = osMutexNew( NULL );
    SemHciId = osSemaphoreNew( 1, 0, NULL ); /*< Create the semaphore and make it busy at initialization */

    Hci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&BleCmdBuffer;
    Hci_Tl_Init_Conf.StatusNotCallBack = BLE_StatusNot;
    hci_init(BLE_UserEvtRx, (void*) &Hci_Tl_Init_Conf);
}
void hci_init(void(* UserEvtRx)(void* pData), void* pConf)
{
  StatusNotCallBackFunction = ((HCI_TL_HciInitConf_t *)pConf)->StatusNotCallBack;
  hciContext.UserEvtRx = UserEvtRx;

  hci_register_io_bus (&hciContext.io);

  TlInit((TL_CmdPacket_t *)(((HCI_TL_HciInitConf_t *)pConf)->p_cmdbuffer));

  return;
}
学习该芯片时搜集的资料。包括英文手册和部分中文资料。 STM32WB系列为意法近年发售的无线MCU系列芯片。并集成了2.4G相关通信协议栈。 目录: 2.4 GHz low pass filter matched to STM32WB55CxRx.pdf 2.4G低通滤波器.docx Bluetooth ⑧Low Energy and 802.15.4 Nucleo pack.pdf Bluetooth low energy and 802.15.4 Nucleo pack.docx en.flstm32wb.pdf en.MB1293-WB55CGU-C02_ schematic.pdf en.MB1355-WB55RGV-C02. schematic.pdf en.stm32wb. marketing_ pres.pdf en.stm32wb. press-pres.pdf en.stm32wb55_ bluetooth certifiate.pdf en.STM32WB-Closing-Session.pdf en.stm32wb-communication-rf-overview-rf.docx en.STM32WB-Communication-RF-Overview-RF.pdf en.stm32wb-ecosystem-stm32wb-board.docx en.STM32WB-Ecosystem-STM32WB-Boards.pdf en.STM32WB-Introduction-Series-Presentation.pdf en.STM32WB-Introduction-Welcome. session.pdf en.STM32WB-Memory-QuadSPl-interface -QUADSPI.pdf en.stm32wb-peripheral-bluetooth-low-energy-bth.docx en.STM32WB-Peripheral-Bluetooth-Low-Energy-BTH.pdf en.STM32WB-System-ARM-Cortex-M0plus-CM0.pdf en.STM32WB-System-ARM-Cortex-M4-CM4.pdf flstm32wb.docx Getting started with STM32CubeWB for STM32WB Series.pdf Getting started with STM32CubeWB for STM32WBseries.docx p-nucleo-wb55.pdf STM32Cube MCU package examples for STM32WB Series.docx STM32Cube MCU Package examples for STM32WB Series.pdf STM32CubeMonRF release 2.3.0.pdf STM32CuBeMonRF release2.3.0.docx STM32CubeWB.docx STM32CubeWB.pdf STM32WB Nucleo-68 pack for wireless solutions.pdf STM32WB ultra-low-power features overview.pdf Usage of SMPS on STM32WB Series microcontrollers.pdf USAGE OF SMPS ON STM32WB.docx 进程组网.docx 开发板Data brief.docx
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值