当前位置:文档之家› 蓝牙4.0协议栈按键流程分析

蓝牙4.0协议栈按键流程分析

在介绍蓝牙按键流程分析之前,我们需要了解一个概念,那就是就是OSAL。

什么是OSAL呢?可能大伙对于OS是比较了解的,学了计算机的搞过OS的也基本接触过,简单来说就是一个操作系统抽象层,可以理解为运行在CC2540 上的操作系统,说操作系统还不能算,TI的OSAL只实现了任务切换和消息机制。

并且把协议栈的代码、硬件处理的代码,用户程序的代码等分别放到了OSAL 层的不同任务处理函数中去了,各任务函数之间通过消息机制、同一个任务之间通过事件的的方式来通信。

什么是EVENT 事件?OSAL 为每个任务函数分配了一个16 位的事件变量,每一位代表一个事件,最高位为0x8000表示为系统事件SYS_EVENT_MSG。

其余的15 位留给用户自定义需要的事件。

通常事件由定时器启动,比如一秒后我要点亮LED2,这就需要发送一个点亮LED2 的事件,然后等待定时器1s后溢出,于是启动点亮LED2事件,事件会调用相应的hal 层API点亮LED2。

什么是MSG 消息MSG 是比EVENT 事件更具体并且可以携带数据的一种通信方式,MSG 的标记是按数值,而不是按位。

比如0x01 和0x02 是两个不同的消息,但对于事件0x03 则是0x01 事件和0x02 事件的组合。

MSG 收发使用osal_msg_send()和osal_msg_receive();当调用osal_msg_send()发送一个msg 的同时会在EVENT 列表中触发一个message ready event。

(请注意最后一句话,这句话点出了为什么按键时间的触发为何会导致系统事件也接受到了)现在以SimpleBLEPeripheral 为例说明按键流程在SimpleBLEPeripheral 任务初始化函数中有这样一条代码:// Register for all key events - This app will handle all key eventsRegisterForKeys( simpleBLEPeripheral_TaskID );这个函数来自OnBoard.c 源文件中/********************************************************************** Keyboard Register function** The keyboard handler is setup to send all keyboard changes to* one task (if a task is registered).** If a task registers, it will get all the keys. You can change this* to register for individual keys.*********************************************************************/uint8 RegisterForKeys( uint8 task_id ){// Allow only the first taskif ( registeredKeysTaskID == NO_TASK_ID ){registeredKeysTaskID = task_id;return ( true );}elsereturn ( false );}向一个全局变量registeredKeysTaskID中赋值自己的任务ID,调用了这个函数就能成功注册按键服务,那这个全局变量在何时使用呢?分析到这里,感觉有点迷糊了,我们可以从顶到下分析。

任何一个程序都是从main函数开始的,这点我们要坚信。

所以我们首先找到这个main函数打开SimpleBLEPeripheral_Main.c文件可以看到/********************************************************************************************** ***** @fn main** @brief Start of application.** @param none** @return none*********************************************************************************************** ****/int main(void){/* Initialize hardware */HAL_BOARD_INIT();// Initialize board I/OInitBoard( 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 initializationInitBoard( OB_READY );#if defined ( POWER_SAVING )osal_pwrmgr_device( PWRMGR_BATTERY );#endif/* Start OSAL */osal_start_system(); // No Return from herereturn 0;}我们打开InitBoard( OB_READY );可以看到如下代码/********************************************************************** @fn InitBoard()* @brief Initialize the CC2540DB Board Peripherals* @param level: COLD,WARM,READY* @return None*/void InitBoard( uint8 level ){if ( level == OB_COLD ){// Interrupts offosal_int_disable( INTS_ALL );// Turn all LEDs offHalLedSet( HAL_LED_ALL, HAL_LED_MODE_OFF );// Check for Brown-Out reset// ChkReset();}else // !OB_COLD{/* Initialize Key stuff */OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;//OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);}}看到我上面标注的函数了吧?那个是一个按键回调服务注册函数,注册了一个OnBoard_KeyCallback函数HalKeyConfig 函数的实现:将上述的回调函数的地址复制给了函数指针变量。

通过跟踪发现该函数的指针变量在按键的轮询函数中调用了,如下图:/********************************************************************************************** ***** @fn HalKeyPoll** @brief Called by hal_driver to poll the keys** @param None** @return None*********************************************************************************************** ***/void HalKeyPoll (void){uint8 keys = 0;uint8 notify = 0;#if defined (CC2540_MINIDK)if (!(HAL_KEY_SW_1_PORT & HAL_KEY_SW_1_BIT)) /* Key is active low */{keys |= HAL_KEY_SW_1;}if (!(HAL_KEY_SW_2_PORT & HAL_KEY_SW_2_BIT)) /* Key is active low */{keys |= HAL_KEY_SW_2;}#elseif (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */{keys |= HAL_KEY_SW_6;}if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT)) /* Key is active HIGH */{keys = halGetJoyKeyInput();}#endif/* If interrupts are not enabled, previous key status and current key status* are compared to find out if a key has changed status.*/if (!Hal_KeyIntEnable){if (keys == halKeySavedKeys){/* Exit - since no keys have changed */return;}else{notify = 1;}}else{/* Key interrupt handled here */if (keys){notify = 1;}}/* Store the current keys for comparation next time */halKeySavedKeys = keys;/* Invoke Callback if new keys were depressed */if (notify && (pHalKeyProcessFunction)){(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);}}在这里底层的按键查询函数调用一个函数指针,而非具体的函数,这样就将处理按键的接口留给了上层,上层应用中,叧需解析的函数指针传入的参数1:keys 就知道是哪个按键被按下了。

相关主题