分享

BLE开发(TI CC254x)之协议栈分析

 iamlijin 2019-08-16

TI 系列的蓝牙芯片在协议栈支持上比较完善,最近使用CC254x系列BLE芯片,发现其协议栈的实现挺有意思,这里做点简单分析。

1.协议栈结构

CC2540 集成了增强型的 8051 内核, TI 为 BLE 协议栈搭建了一个简单的操作系统OSAL,即一种任务轮询机制。帮你做好了底层和蓝牙协议深层的内容,将复杂部分屏蔽掉。让用户通过 API 函数就可以轻易用蓝牙 4.0,是开发起来更加方便,开发周期也可以相应缩短。 

安装完 BLE 协议栈之后,会在安装目录下看到以下文件结构:


其中,Accessories存放附件,如:USB驱动和hex文件。Components即为OSAL操作系统的底层实现,里面包括OSAL的各层具体实现。

Documents为协议栈相关说明文档,Projects为官方提供的demos,很多demo都是可以直接修改使用的,其中重点关心四个demo:

SimpleBLEBroadcaster、SimpleBLECentral、SimpleBLEObserver、SimpleBLEPeripheral。 
这四个代码是CC254x开发的基本模板,他们都有自己的特点。 
· Broadcaster 广播员 —— 非连接性的信号装置 
· Observer 观察者    —— 扫描得到,但不能链接 
· Peripheral 从机    —— 可链接,在单个链路层链接中作为从机 
· Central 主机   —— 扫描设备并发起链接,在单链路层或多链路层中作为主机。

2.协议栈OSAL原理分析

协议栈中所谓的OSAL就是一个小型的操作系统,实现了最基本的任务轮询。

直接从main函数开始解剖:

  1. int main(void)
  2. {
  3. /* Initialize hardware */
  4. HAL_BOARD_INIT();
  5. // Initialize board I/O
  6. InitBoard( OB_COLD );
  7. /* Initialze the HAL driver */
  8. HalDriverInit();
  9. /* Initialize NV system */
  10. osal_snv_init();
  11. /* Initialize LL */
  12. /* Initialize the operating system */
  13. osal_init_system();
  14. /* Enable interrupts */
  15. HAL_ENABLE_INTERRUPTS();
  16. // Final board initialization
  17. InitBoard( OB_READY );
  18. #if defined ( POWER_SAVING )
  19. osal_pwrmgr_device( PWRMGR_BATTERY );
  20. #endif
  21. /* Start OSAL */
  22. osal_start_system(); // No Return from here
  23. return 0;
  24. }
主函数一进去就是各种系统初始化:包括硬件、GATT、 GAP 层、任务等的初始化。然后执行 osal_start_system();操作系统。我们重点关心2 个函数:
初始化操作系统 
osal_init_system(); 
运行操作系统 
osal_start_system(); 

        我们先来看 osal_init_system();系统初始化函数,进入函数。发现里面有 6个初始化函数,这里我们只关心osalInitTasks();任务初始化函数。继续由该函数进入,进入后发现终于看到各层任务的添加,taskID 依次递增表示优先级降低,即越底层优先级越高(LL、HAL、HCI、L2CAP、GAP、GATT、SM、Profiles、Application)

  1. void osalInitTasks( void )
  2. {
  3. uint8 taskID = 0;
  4. tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  5. osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
  6. /* LL Task */
  7. LL_Init( taskID++ );
  8. /* Hal Task */
  9. Hal_Init( taskID++ );
  10. /* HCI Task */
  11. HCI_Init( taskID++ );
  12. #if defined ( OSAL_CBTIMER_NUM_TASKS )
  13. /* Callback Timer Tasks */
  14. osal_CbTimerInit( taskID );
  15. taskID += OSAL_CBTIMER_NUM_TASKS;
  16. #endif
  17. /* L2CAP Task */
  18. L2CAP_Init( taskID++ );
  19. /* GAP Task */
  20. GAP_Init( taskID++ );
  21. /* GATT Task */
  22. GATT_Init( taskID++ );
  23. /* SM Task */
  24. SM_Init( taskID++ );
  25. /* Profiles */
  26. GAPCentralRole_Init( taskID++ );
  27. GAPBondMgr_Init( taskID++ );
  28. GATTServApp_Init( taskID++ );
  29. /* Application */
  30. SimpleBLECentral_Init( taskID );
  31. }
最高层即应用层优先级最低,最后执行应用层的任务初始化。

 我们再来看第二个函数 osal_start_system();运行操作系统。同样用 go to definition 的方法进入该函数。再进入 osal_run_system() ,我们欣喜地发现这里就是任务轮询的基本轮廓,源码和分析如下:

  1. void osal_run_system( void )
  2. {
  3. uint8 idx = 0;
  4. #ifndef HAL_BOARD_CC2538
  5. osalTimeUpdate();
  6. #endif
  7. Hal_ProcessPoll();
  8. //这段代码扫描触发的任务
  9. do {
  10. if (tasksEvents[idx]) //优先级高的任务被置位,说明有任务触发
  11. {
  12. break;//跳出任务扫描,得到的idx即为任务ID!
  13. }
  14. } while (++idx < tasksCnt);//idx从0开始递增,先查询高优先级的任务
  15. if (idx < tasksCnt)
  16. {
  17. uint16 events;
  18. halIntState_t intState;
  19. //然后进入临界保护区,提取事件后清清除
  20. HAL_ENTER_CRITICAL_SECTION(intState);
  21. events = tasksEvents[idx];
  22. tasksEvents[idx] = 0; // 清除
  23. HAL_EXIT_CRITICAL_SECTION(intState);
  24. //然后通过函数指针调用对应的任务处理函数
  25. activeTaskID = idx;
  26. events = (tasksArr[idx])( idx, events );
  27. activeTaskID = TASK_NO_TASK;
  28. //taskArr[]即为函数指针数组,存放所有定义好的处理任务函数的入口地址
  29. HAL_ENTER_CRITICAL_SECTION(intState);
  30. tasksEvents[idx] |= events; // 保存未处理的事件
  31. HAL_EXIT_CRITICAL_SECTION(intState);
  32. }
  33. #if defined( POWER_SAVING )//如果定义了节能模式
  34. else
  35. {
  36. osal_pwrmgr_powerconserve(); //进入睡眠
  37. }
  38. #endif
  39. #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
  40. {
  41. osal_task_yield();
  42. }
  43. #endif
  44. }
可见协议栈就是一个被称为OSAL的小型操作系统,基本流程如下:

各种初始化---运行操作系统---有任务触发---执行任务

以上只是对协议栈OSAL系统的简单分析,关于蓝牙通信的API 部分后文再续。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多