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

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函数开始解剖:

int main(void)
{
  /* Initialize hardware */
  HAL_BOARD_INIT();

  // Initialize board I/O
  InitBoard( OB_COLD );

  /* Initialze the HAL driver */
  HalDriverInit();

  /* Initialize NV system */
  osal_snv_init();
  
  /* Initialize LL */

  /* Initialize the operating system */
  osal_init_system();

  /* Enable interrupts */
  HAL_ENABLE_INTERRUPTS();

  // Final board initialization
  InitBoard( OB_READY );

  #if defined ( POWER_SAVING )
    osal_pwrmgr_device( PWRMGR_BATTERY );
  #endif
    
  /* Start OSAL */
  osal_start_system(); // No Return from here

  return 0;
}
主函数一进去就是各种系统初始化:包括硬件、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)

void osalInitTasks( void )
{
  uint8 taskID = 0;

  tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
  osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));

  /* LL Task */
  LL_Init( taskID++ );

  /* Hal Task */
  Hal_Init( taskID++ );

  /* HCI Task */
  HCI_Init( taskID++ );

#if defined ( OSAL_CBTIMER_NUM_TASKS )
  /* Callback Timer Tasks */
  osal_CbTimerInit( taskID );
  taskID += OSAL_CBTIMER_NUM_TASKS;
#endif

  /* L2CAP Task */
  L2CAP_Init( taskID++ );

  /* GAP Task */
  GAP_Init( taskID++ );

  /* GATT Task */
  GATT_Init( taskID++ );

  /* SM Task */
  SM_Init( taskID++ );

  /* Profiles */
  GAPCentralRole_Init( taskID++ );
  GAPBondMgr_Init( taskID++ );

  GATTServApp_Init( taskID++ );

  /* Application */
  SimpleBLECentral_Init( taskID );
}
最高层即应用层优先级最低,最后执行应用层的任务初始化。

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

void osal_run_system( void )
{
  uint8 idx = 0;

#ifndef HAL_BOARD_CC2538
  osalTimeUpdate();
#endif
  
  Hal_ProcessPoll();
  //这段代码扫描触发的任务
  do {
    if (tasksEvents[idx]) //优先级高的任务被置位,说明有任务触发 
    {
      break;//跳出任务扫描,得到的idx即为任务ID!
    }
  } while (++idx < tasksCnt);//idx从0开始递增,先查询高优先级的任务

  if (idx < tasksCnt)
  {
    uint16 events;
    halIntState_t intState;
    //然后进入临界保护区,提取事件后清清除
    HAL_ENTER_CRITICAL_SECTION(intState);
    events = tasksEvents[idx];
    tasksEvents[idx] = 0;  // 清除
    HAL_EXIT_CRITICAL_SECTION(intState);
    //然后通过函数指针调用对应的任务处理函数
    activeTaskID = idx;
    events = (tasksArr[idx])( idx, events );
    activeTaskID = TASK_NO_TASK;
    //taskArr[]即为函数指针数组,存放所有定义好的处理任务函数的入口地址
    HAL_ENTER_CRITICAL_SECTION(intState);
    tasksEvents[idx] |= events;  // 保存未处理的事件
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
#if defined( POWER_SAVING )//如果定义了节能模式
  else  
  {
    osal_pwrmgr_powerconserve();  //进入睡眠
  }
#endif

#if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
  {
    osal_task_yield();
  }
#endif
}
可见协议栈就是一个被称为OSAL的小型操作系统,基本流程如下:

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

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





  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ctrlturtle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值