微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 硬件工程师文库 > 由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(3)

由浅入深,蓝牙4.0/BLE协议栈开发攻略大全(3)

时间:07-22 来源:本站整理 点击:

始化进程中,这就是说系统启动后不能动态添加功能;

  3. 编写任务处理程序;

  4. 如有需要提供消息服务。

  BLE协议栈的各层都是以OSAL任务方式实现,由于LL控制室的时间要求最为迫切,所以其任务优先级最高。为了实现任务管理,OSAL通过消息处理(messageprocess),存储管理,计时器定时等附加服务实现。

  系统启动流程:

  

  为了使用OSAL,在main函数的最后要启动一个名叫osal_start_system的进程,该进程会调用由特定应用决定的启动函数 osalInitTasks(来启动系统)。osalInitTasks逐个调用BLE协议栈各层的启动进程来初始化协议栈。随后,设置一个任务的 8bit任务ID(task ID),跳入循环等待执行任务,系统启动完成。

  1. 任务优先级决定于任务ID,任务ID越小,优先级越高

  2. BLE协议栈各层的任务优先级比应用程序的高

  3. 初始化协议栈后,越早调入的任务,任务ID越高,优先级越低,即系统倾向于处理新到的任务

  每个事件任务由对应的16bit事件变量来标示,事件状态由旗号(taskflag)来标示。如果事件处理程序已经完成,但其旗号并没有移除,OSAL会认为事情还没有完成而继续在该程序中不返回。比如,在SimpleBLEPeripheral实例工程中,当事件START_DEVICE_EVT发生,其处理函数SimpleBLEPeripheral_ProcessEvent就运行,结束后返回16bit事件变量,并清除旗语 SBP_START_DEVICE_EVT。

  每当OSAL事件检测到了有任务事件,其相应的处理进程将被添加到由处理进程指针构成的事件处理表单中,该表单名叫taskArr(taskarray)。taskArr中各个事件进程的顺序和osalInitTasks初始化函数中任务ID的顺序是对应的。

  有两种,最简单的方法是使用osal_set_event函数(函数原型在OSAL.h文件中),在这个函数中,用户可以像定义函数参数一样设置任务ID 和事件旗语。第二种方法是使用osal_start_timerEx函数(函数原型在OSAL_Timers.h文件中),使用方法同 osal_set_event函数,而第三个以毫秒为单位的参数osal_start_timerEx则指示该事件处理必须要在这个限定时间内,通过定时器来为事件处理计时。

  类似于Linux嵌入式系统内存分配C函数mem_alloc,OSAL利用osal_mem_alloc提供基本的存储管理,但osal_mem_alloc只有一个用于定义byte数的参数。对应的内存释放函数为osal_mem_free。

  不同的子系统通过OSAL的消息机制通信。消息即为数据,数据种类和长度都不限定。消息收发过程描述如下:

  接收信息,调用函数osal_msg_allocate创建消息占用内存空间(已经包含了osal_mem_alloc函数功能),需要为该函数指定空间大小,该函数返回内存空间地址指针,利用该指针就可把所需数据拷贝到该空间。

  发送数据,调用函数osal_msg_send,需为该函数指定发送目标任务,OSAL通过旗语SYS_EVENT_MSG告知目标任务,目标任务的处理函数调用osal_msg_receive来接收发来的数据。建议每个OSAL任务都有一个消息处理函数,每当任务收到一个消息后,通过消息的种类来确定需要本任务做相应处理。消息接收并处理完成,调用函数osal_msg_deallocate来释放内存(已经包含了osal_mem_free函数功能)。

  为了实现更好的移植性,协议栈将硬件层抽象出了一个HAL硬件抽象层,当新的硬件平台做好后,只需修改HAL,而不需修改HAL之上的协议栈的其他组件和应用程序。

  第十五节 BLE蓝牙4.0协议栈启动分析

  TI的这款CC2540/CC2541器件可以单芯片实现BLE蓝牙协议栈结构图的所有组件,包括应用程序。从这章开始我们来剖析协议栈源码,我们选用 SimpleBLEPeripheral工程开刀,这是一个从机的例程,基本的工作是对外广播,等待主机来连接,读写展示的属性。

  

  首先打开工程文件,打开后可以看到整个工程的结构。

  

  我们按照系统的启动顺序来一步一步走,我们都知道在C代码中,一般启动的首个函数为main,这个函数在 SimpleBLEPeripheral_Main.c中,打开文件,可以看到这个文件只有一个main函数和一个函数的申明,我们暂时不理会那个申明的函数,先看main都做了些什么工作:

  Int main(void)

  {

  /* Initialize hardware */

  HAL_BOARD_INIT(); // 硬件初始化

  // Initialize board I/O

  InitBoard( OB_COLD ); // 板级初始化

  /* Initialze the HAL driver */

  HalDriverInit(); // Hal驱动初始化

  /* Initialize NV system */

  osal_snv_init(); // Flash存储SNV初始化

  /* Initialize LL */

  /* Initialize the operating system */

osal_init_system(); // O

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top