Login
升级VIP 登录 注册 安全退出
当前位置: 首页 > word文档 > 合同模板 > 蓝牙协议栈按键流程分析,蓝牙协议栈详解

蓝牙协议栈按键流程分析,蓝牙协议栈详解

收藏

本作品内容为蓝牙协议栈按键流程分析,格式为 docx ,大小 16944 KB ,页数为 22页

蓝牙协议栈按键流程分析


('在介绍蓝牙按键流程分析之前,我们需要了解一个概念,那就是就是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列表中触发一个messagereadyevent。(请注意最后一句话,这句话点出了为什么按键时间的触发为什么会导致系统事件也接受到了)现在以SimpleBLEPeripheral为例说明按键流程在SimpleBLEPeripheral任务初始化函数中有这样一条代码://Registerforallkeyevents-ThisappwillhandleallkeyeventsRegisterForKeys(simpleBLEPeripheral_TaskID);这个函数来自OnBoard.c源文献中/KeyboardRegisterfunctionThekeyboardhandlerissetuptosendallkeyboardchangestoonetask(ifataskisregistered).Ifataskregisters,itwillgetallthekeys.Youcanchangethistoregisterforindividualkeys./uint8RegisterForKeys(uint8task_id){//Allowonlythefirsttaskif(registeredKeysTaskID==NO_TASK_ID){registeredKeysTaskID=task_id;return(true);}elsereturn(false);}向一个全局变量registeredKeysTaskID中赋值自己的任务ID,调用了这个函数就能成功注册按键服务,那这个全局变量在何时使用呢?分析到这里,感觉有点迷糊了,我们可以从顶到下分析。任何一个程序都是从main函数开始的,这点我们要坚信。所以我们一方面找到这个main函数打开SimpleBLEPeripheral_Main.c文献可以看到/intmain(void){/InitializehardwareHAL_BOARD_INIT();//InitializeboardI/OInitBoard(OB_COLD);/InitialzetheHALdriverHalDriverInit();/InitializeNVsystemosal_snv_init();/InitializeLL/Initializetheoperatingsystemosal_init_system();/EnableinterruptsHAL_ENABLE_INTERRUPTS();//FinalboardinitializationInitBoard(OB_READY);#ifdefined(POWER_SAVING)osal_pwrmgr_device(PWRMGR_BATTERY);#endif/StartOSALosal_start_system();//NoReturnfromherereturn0;}我们打开InitBoard(OB_READY);可以看到如下代码/voidInitBoard(uint8level){if(level==OB_COLD){//Interruptsoffosal_int_disable(INTS_ALL);//TurnallLEDsoffHalLedSet(HAL_LED_ALL,HAL_LED_MODE_OFF);//CheckforBrown-Outreset//ChkReset();}else//!OB_COLD{/InitializeKeystuffOnboardKeyIntEnable=HAL_KEY_INTERRUPT_ENABLE;//OnboardKeyIntEnable=HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);}}看到我上面标注的函数了吧?那个是一个按键回调服务注册函数,注册了一个OnBoard_KeyCallback函数HalKeyConfig函数的实现:将上述的回调函数的地址复制给了函数指针变量。通过跟踪发现该函数的指针变量在按键的轮询函数中调用了,如下图://voidHalKeyPoll(void){uint8keys=0;uint8notify=0;#ifdefined(CC2540_MINIDK)if(!(HAL_KEY_SW_1_PORT&HAL_KEY_SW_1_BIT))/Keyisactivelow{keys=HAL_KEY_SW_1;}if(!(HAL_KEY_SW_2_PORT&HAL_KEY_SW_2_BIT))/Keyisactivelow{keys=HAL_KEY_SW_2;}#elseif(!(HAL_KEY_SW_6_PORT&HAL_KEY_SW_6_BIT))/Keyisactivelow{keys=HAL_KEY_SW_6;}if((HAL_KEY_JOY_MOVE_PORT&HAL_KEY_JOY_MOVE_BIT))/KeyisactiveHIGH{keys=halGetJoyKeyInput();}#endif/Ifinterruptsarenotenabled,previouskeystatusandcurrentkeystatusarecomparedtofindoutifakeyhaschangedstatus.if(!Hal_KeyIntEnable){if(keys==halKeySavedKeys){/Exit-sincenokeyshavechangedreturn;}else{notify=1;}}else{/Keyinterrupthandledhereif(keys){notify=1;}}/StorethecurrentkeysforcomparationnexttimehalKeySavedKeys=keys;/InvokeCallbackifnewkeysweredepressedif(notify&&(pHalKeyProcessFunction)){(pHalKeyProcessFunction)(keys,HAL_KEY_STATE_NORMAL);}}在这里底层的按键查询函数调用一个函数指针,而非具体的函数,这样就将解决按键的接口留给了上层,上层应用中,叧需解析的函数指针传入的参数1:keys就知道是哪个按键被按下了。我们再回到刚才的OnBoard_KeyCallback回调函数处,该回调函数代码如下:/state-shifted/voidOnBoard_KeyCallback(uint8keys,uint8state){uint8shift;(void)state;//shiftkey(S1)isusedtogeneratekeyinterrupt//applicationsshouldnotuseS1whenkeyinterruptisenabledshift=(OnboardKeyIntEnable==HAL_KEY_INTERRUPT_ENABLE)?false:((keys&HAL_KEY_SW_6)?true:false);if(OnBoard_SendKeys(keys,shift)!=SUCCESS)//就是这句话将按键消息上传到应用层去解决的{//ProcessSW1hereif(keys&HAL_KEY_SW_1)//Switch1{}//ProcessSW2hereif(keys&HAL_KEY_SW_2)//Switch2{}//ProcessSW3hereif(keys&HAL_KEY_SW_3)//Switch3{}//ProcessSW4hereif(keys&HAL_KEY_SW_4)//Switch4{}//ProcessSW5hereif(keys&HAL_KEY_SW_5)//Switch5{}//ProcessSW6hereif(keys&HAL_KEY_SW_6)//Switch6{}}/Ifanykeyiscurrentlypresseddownandinterruptisstillenabled,disableinterruptandswitchtopollingif(keys!=0){if(OnboardKeyIntEnable==HAL_KEY_INTERRUPT_ENABLE){OnboardKeyIntEnable=HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);}}/Ifnokeyiscurrentlypresseddownandinterruptisdisabled,enableinterruptandturnoffpollingelse{if(OnboardKeyIntEnable==HAL_KEY_INTERRUPT_DISABLE){OnboardKeyIntEnable=HAL_KEY_INTERRUPT_ENABLE;HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);}}}进入按键消息发送函数中可以看到/state-shifted/uint8OnBoard_SendKeys(uint8keys,uint8state){keyChange_tmsgPtr;if(registeredKeysTaskID!=NO_TASK_ID){//SendtheaddresstothetaskmsgPtr=(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);}elsereturn(FAILURE);}重要是将按键时间,状态和按键值打包到信息中最后通过osal_msg_send(registeredKeysTaskID,(uint8)msgPtr);发送到注册了按键服务的应用层去,最终用户按了哪个按键,如何响应当按键在系统事件SYS_EVENT_MSG中解决。疑问又来了,为什么通过osal_msg_send收发的消息会出现在SYS_EVENT_MSG中呢?这个疑问,就是刚才我说过的osal_msg_send(registeredKeysTaskID,(uint8)msgPtr)会产生一个amessagereadyeventinthedestinationtaskseventlist./Thisfunctioniscalledbyatasktosendacommandmessagetoanothertaskorprocessingelement.Thesending_taskfieldmustrefertoavalidtask,sincethetaskIDwillbeusedfortheresponsemessage.Thisfunctionwillalsosetamessagereadyeventinthedestinationtaskseventlist.uint8osal_msg_send(uint8destination_task,uint8msg_ptr){return(osal_msg_enqueue_push(destination_task,msg_ptr,FALSE));}/staticvoidsimpleBLEPeripheral_ProcessOSALMsg(osal_event_hdr_tpMsg){switch(pMsg->event){#ifdefined(CC2540_MINIDK)caseKEY_CHANGE://按键解决事件,用户产生的按键都是在这里解决simpleBLEPeripheral_HandleKeys(((keyChange_t)pMsg)->state,((keyChange_t)pMsg)->keys);break;#endif//#ifdefined(CC2540_MINIDK)default://donothingbreak;}}在SimpleBLEPeripheral中,对按键的响应如下:joystickright(SW2)收发广播的启动和关闭/HAL_KEY_SW_2HAL_KEY_SW_1staticvoidsimpleBLEPeripheral_HandleKeys(uint8shift,uint8keys){uint8SK_Keys=0;VOIDshift;//Intentionallyunreferencedparameterif(keys&HAL_KEY_SW_1){SK_Keys=SK_KEY_LEFT;}if(keys&HAL_KEY_SW_2){SK_Keys=SK_KEY_RIGHT;//ifdeviceisnotinaconnection,pressingtherightkeyshouldtoggle//advertisingonandoffif(gapProfileState!=GAPROLE_CONNECTED){uint8current_adv_enabled_status;uint8new_adv_enabled_status;//FindthecurrentGAPadvertisementstatusGAPRole_GetParameter(GAPROLE_ADVERT_ENABLED,¤t_adv_enabled_status);//这个函数重要就是获得广播的启动和关闭状态if(current_adv_enabled_status==FALSE){new_adv_enabled_status=TRUE;}else{new_adv_enabled_status=FALSE;}//changetheGAPadvertisementstatustooppositeofcurrentstatusGAPRole_SetParameter(GAPROLE_ADVERT_ENABLED,sizeof(uint8),&new_adv_enabled_status);}}//SetthevalueofthekeysstatetotheSimpleKeysProfile;//ThiswillsendoutanotificationofthekeysstateifenabledSK_SetParameter(SK_KEY_ATTR,sizeof(uint8),&SK_Keys);}#endif//#ifdefined(CC2540_MINIDK)现在按键基本分析完了,其实CC2540学习板子是默认启动广播,但是Keyfob就需要按键手动启动了。接下来我会继续分析协议栈的其他功能,如有局限性之外,望补充~~~~~~~~~',)


  • 编号:1700671682
  • 分类:合同模板
  • 软件: wps,office word
  • 大小:22页
  • 格式:docx
  • 风格:商务
  • PPT页数:16944 KB
  • 标签:

广告位推荐

相关合同模板更多>