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函数开始解剖:
/* Initialize hardware */ /* Initialze the HAL driver */ /* Initialize NV system */ /* Initialize the operating system */ // Final board initialization #if defined ( POWER_SAVING ) osal_pwrmgr_device( PWRMGR_BATTERY ); osal_start_system(); // No Return from here
主函数一进去就是各种系统初始化:包括硬件、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 ) tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); #if defined ( OSAL_CBTIMER_NUM_TASKS ) /* Callback Timer Tasks */ osal_CbTimerInit( taskID ); taskID += OSAL_CBTIMER_NUM_TASKS; GAPCentralRole_Init( taskID++ ); GAPBondMgr_Init( taskID++ ); GATTServApp_Init( taskID++ ); SimpleBLECentral_Init( taskID );
最高层即应用层优先级最低,最后执行应用层的任务初始化。
我们再来看第二个函数 osal_start_system();运行操作系统。同样用 go to definition 的方法进入该函数。再进入 osal_run_system() ,我们欣喜地发现这里就是任务轮询的基本轮廓,源码和分析如下:
void osal_run_system( void ) if (tasksEvents[idx]) //优先级高的任务被置位,说明有任务触发 break;//跳出任务扫描,得到的idx即为任务ID! } while (++idx < tasksCnt);//idx从0开始递增,先查询高优先级的任务 HAL_ENTER_CRITICAL_SECTION(intState); events = tasksEvents[idx]; tasksEvents[idx] = 0; // 清除 HAL_EXIT_CRITICAL_SECTION(intState); 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 )//如果定义了节能模式 osal_pwrmgr_powerconserve(); //进入睡眠 #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0)
可见协议栈就是一个被称为OSAL的小型操作系统,基本流程如下:
各种初始化---运行操作系统---有任务触发---执行任务
以上只是对协议栈OSAL系统的简单分析,关于蓝牙通信的API 部分后文再续。
|