版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、蓝牙4.0协议栈按键流程分析在介绍蓝牙按键流程分析之前,我们需要了解一个概念,那就是就是OSAL。什么是OSAL呢?可能大伙对于OS是比较了解的,学了计算机的搞过 OS的也基本接触过,简单来说就是一个操作系统抽象层,可以理 解为运行在CC2540上的操作系统,说操作系统还不能算,TI的OSAL只实现了任务切换和消息机制。并且把协议栈的代码、硬件处理的代码,用户程序的代码等分别放到了OSAL层的不同任务处理函数中去了,各任务函数之间通过消息机制、同一个任务之间通过事件的的方式来通信。什么是EVENT事件?OSAL为每个任务函数分配了一个 16位的事件变量,每一位代表一个事件,最高位为 0x800
2、0 表示为系统事件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_
3、send()发送一个 msg 的同时会在 EVENT 列表中触发一个message ready event 。(请注意最后一句话,这句话点出了为什么按键时间的触发为何会导致系统事件 也接受到了)现在以SimpleBLEPeripheral为例说明按键流程在SimpleBLEPeripheral任务初始化函数中有这样一条代码:/ Register for all key events - This app will handle all key eventsRegisterForKeys( simpleBLEPeripheral_TasklD );这个函数来自OnBoard.c 源文件中/* *
4、 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 taski
5、f ( registeredKeysTaskID = NO_TASK_ID )registeredKeysTaskID = task_id;return ( true );elsereturn ( false );向一个全局变量registeredKeysTaskID中赋值自己的任务ID,调用了这个函数就能成功注册按键服务,那这个全局变量在何时使用呢?分析到这里,感觉有点迷糊了,我们可以从顶到下分析。任何一个程序都是从main函数开始的,这点我们要坚信。所以我们首先找到这个main函数打开SimpleBLEPeripheral_Main.c文件可以看至/* fnmain* briefStart
6、 of application.* paramnone* 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 */ osalnit_system(
7、);/* Enable interrupts */HAL_ENABLE_INTERRUPTS();/ Final board initializationlnitBoard( 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 Ini
8、tialize 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/* I
9、nitialize Key stuff */OnboardKeylntEnable = HAL_KEY_INTERRUPT_ENABLE; /OnboardKeylntEnable = HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig( OnboardKeylntEnable, OnBoard_KeyCallback);看到我上面标注的函数了吧?那个是一个按键回调服务注册函数,注册了一个OnBoard_KeyCallback 函数HalKeyConfig 函数的实现:将上述的回调函数的地址复制给了函数指针变量。通过跟踪发现该函数的指针变量在按键的轮询函数中调用了,如
10、下图:/* fnHalKeyPoll* 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)/* Key is active low */if (!(HAL_KEY_SW_1_PORT & HAL_KEY_SW_1_BIT)/* Key is active low */#else/* Key is active low */if (!(H
11、AL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)keys |= HAL_KEY_SW_6;if (HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT) /* Key is active HIGH */keys = halGetJoyKeylnput();#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
12、(!Hal_KeyIntEnable)if (keys = halKeySavedKeys)/* Exit - since no keys have changed */return;elsenotify = 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 &
13、 (pHalKeyProcessFunction)(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);在这里底层的按键查询函数调用一个函数指针,而非具体的函数,这样就将处理按键的接口留给了上层,上层应用中, 另需解析的函数指针传入的参数1 : keys就知道是哪个按键被按下了。我们再回到刚才的 OnBoard_KeyCallback回调函数处,该回调函数代码如下:/* fn OnBoard_KeyCallback* brief Callback service for keys* param keys - keys that were p
14、ressed* state - shifted* return void*:void OnBoard_KeyCallback ( uint8 keys, uint8 state )uint8 shift; |(void)state;/ shift key (S1) is used to generate key interrupt/ applications should not use S1 when key interrupt is enabledshift = (OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE) ? false : (keys
15、 & HAL_KEY_SW_6) ? true : false);if ( OnBoard_SendKeys( keys, shift ) != SUCCESS) /就是这句话将按键消息上传到应用层去处理的/ Process SW1 hereif ( keys & HAL_KEY_SW_1 ) / Switch 1/ Process SW2 hereif ( keys & HAL_KEY_SW_2 ) / Switch 2/ Process SW3 hereif ( keys & HAL_KEY_SW_3 ) / Switch 3/ Process SW4 hereif ( keys & HA
16、L_KEY_SW_4 ) / Switch 4/ Process SW5 hereif ( keys & HAL_KEY_SW_5 ) / Switch 5/ Process SW6 hereif ( keys & HAL_KEY_SW_6 ) / Switch 6/* If any key is currently pressed down and interruptis still enabled, disable interrupt and switch to polling */ if( keys != 0 ) |if( OnboardKeylntEnable = HAL_KEY_IN
17、TERRUPT_ENABLE ) OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);/* If no key is currently pressed down and interrupt is disabled, enable interrupt and turn off polling */ elseif( OnboardKeylntEnable = HAL_KEY_INTERRUPT_DISABLE )OnboardKeylntEn
18、able = HAL_KEY_INTERRUPT_ENABLE;HalKeyConfig( OnboardKeylntEnable, OnBoard_KeyCallback);进入按键消息发送函数中可以看到:* fn*OnBoard_SendKeys* briefSend Key Pressed message to application.|* param keys - keys that were pressedstate - shifted* return status*uint8 OnBoard_SendKeys( uint8 keys, uint8 state )keyChange_
19、t *msgPtr;if ( registeredKeysTaskID != NO_TASK_ID )/ Send the address to the taskmsgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t);if ( msgPtr )msgPtr-hdr.event = KEY_CHANGE;msgPtr-state = state;msgPtr-keys = keys;osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );return ( SUCCESS )
20、;elsereturn ( FAILURE );主要是将按键时间,状态和按键值打包到信息中最后通过osal_msg_send( registeredKeysTaskID, (uint8*)msgPtr );发送到注册了按键服务的应用层去,最终用户按了哪个按键,如何响应该按键在系统事件 SYS_EVENT_MSG 中处理。疑问又来了,为什么通过osal_msg_send收发的消息会出现在SYS_EVENT_MSG中呢?这个疑问,就是刚才我说过的osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr )会产生一个amessage ready eve
21、nt in the destination tasks event list./* fn osal_msg_send* brief* This function is called by a task to send a command message to* another task or processing element. The sending_task field must* refer to a valid task, since the task ID will be used* for the response message. This function will also
22、 set a message* ready event in the destination tasks event list.* paramuint8 destination_task - Send msg to Task ID* paramuint8 *msg_ptr - pointer to new message buffer* return SUCCESS, INVALID_TASK, INVALID_MSG_POINTER*/uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr )return ( osal_msg_
23、enqueue_push( destination_task, msg_ptr, FALSE );/* fn simpleBLEPeripheral_ProcessOSALMsg* brief Process an incoming task message.* param pMsg - message to process* return none*/static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg )switch ( pMsg-event )#if defined( CC2540_MINIDK )c
24、ase KEY_CHANGE:/按键处理事件,用户产生的按键都是在这里处理(keyChange_tsimpleBLEPeripheral_HandleKeys(keyChange_t*)pMsg)-state,*)pMsg)-keys );break;#endif / #if defined( CC2540_MINIDK )default:/ do nothing break;在SimpleBLEPeripheral 中,对按键的响应如下:joystick right(SW2)收发广播的开启和关闭/* fn simpleBLEPeripheral_HandleKeys* brief Handl
25、es all key events for this device.* param shift - true if in shift/alt.* param keys - bit field for key events. Valid entries:* HAL_KEY_SW_2* HAL_KEY_SW_1* return none*/static void simpleBLEPeripheral_HandleKeys( uint8 shift, uint8 keys ) uint8 SK_Keys = 0;VOID shift; / Intentionally unreferenced parameterif ( keys & HAL_KEY_SW_1 )SK_Keys |= SK_KEY_LEFT;if ( keys & HAL_KEY_SW_2 )SK_Keys |= SK_KEY_RIGHT;/ if device is not in a connection, pressing t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 幼儿园餐饮供货协议
- 附录一国家行政机关公文处理办法现代应用文书写作(第三版)教学课件电子教案
- 2025年度个人所得税赡养老人专项附加扣除协议执行细则4篇
- 2025年度个人留学担保合同模板
- 2025年度个人收入证明范本及税务合规服务合同
- 2025-2030全球氢混合锅炉行业调研及趋势分析报告
- 2025-2030全球CO2激光冷水机行业调研及趋势分析报告
- 2024年女职工权益保护及性别平等知识有奖知识竞赛题库及答案
- 2024年居民健康素养知识竞赛考试题库含答案
- 2025年个人间技术秘密保护保密合同4篇
- 江苏省无锡市2023-2024学年八年级上学期期末数学试题(原卷版)
- 2024年全国统一高考数学试卷(新高考Ⅱ)含答案
- 消防救援-低温雨雪冰冻恶劣天气条件下灾害防范及救援行动与安全
- 供热管网工程监理大纲
- 国家临床医学研究临床中心五年发展规划
- 移动商务内容运营(吴洪贵)任务四 引起受众传播内容要素的掌控
- 安徽新宸新材料有限公司年产6000吨锂离子电池材料双氟磺酰亚胺锂项目环境影响报告书
- 绘本《汪汪的生日派对》
- 分手的协议书模板(5篇)
- 助产护理毕业论文
- 地震工程学概论课件
评论
0/150
提交评论