藍(lán)牙4.0協(xié)議棧按鍵流程分析_第1頁
藍(lán)牙4.0協(xié)議棧按鍵流程分析_第2頁
藍(lán)牙4.0協(xié)議棧按鍵流程分析_第3頁
藍(lán)牙4.0協(xié)議棧按鍵流程分析_第4頁
藍(lán)牙4.0協(xié)議棧按鍵流程分析_第5頁
已閱讀5頁,還剩6頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、在介紹藍(lán)牙按鍵流程分析之前,我們需要了解一個(gè)概念,那就是就是OSAL。什么是OSAL呢?可能大伙對(duì)于OS是比較了解的,學(xué)了計(jì)算機(jī)的搞過OS的也基本接觸過,簡單來說就是一個(gè)操作系統(tǒng)抽象層,可以理解為運(yùn)行在 CC2540 上的操作系統(tǒng),說操作系統(tǒng)還不能算,TI的OSAL只實(shí)現(xiàn)了任務(wù)切換和消息機(jī)制。并且把協(xié)議棧的代碼、硬件處理的代碼,用戶程序的代碼等分別放到了 OSAL 層的不同任務(wù)處理函數(shù)中去了,各任務(wù)函數(shù)之間通過消息機(jī)制、同一個(gè)任務(wù)之間通過事件的的方式來通信。什么是 EVENT 事件?OSAL 為每個(gè)任務(wù)函數(shù)分配了一個(gè) 16 位的事件變量,每一位代表一個(gè)事件,最高位為 0x8000表示為系統(tǒng)事件

2、 SYS_EVENT_MSG。其余的15 位留給用戶自定義需要的事件。通常事件由定時(shí)器啟動(dòng),比如一秒后我要點(diǎn)亮 LED2,這就需要發(fā)送一個(gè)點(diǎn)亮 LED2 的事件,然后等待定時(shí)器1s后溢出,于是啟動(dòng)點(diǎn)亮 LED2事件,事件會(huì)調(diào)用相應(yīng)的hal 層API點(diǎn)亮LED2。什么是 MSG 消息MSG 是比 EVENT 事件更具體并且可以攜帶數(shù)據(jù)的一種通信方式,MSG 的標(biāo)記是按數(shù)值,而不是按位。比如 0x01 和 0x02 是兩個(gè)不同的消息,但對(duì)于事件 0x03 則是 0x01 事件和 0x02 事件的組合。MSG 收發(fā)使用 osal_msg_send()和 osal_msg_receive();當(dāng)調(diào)用

3、osal_msg_send()發(fā)送一個(gè) msg 的同時(shí)會(huì)在 EVENT 列表中觸發(fā)一個(gè) message ready event。(請(qǐng)注意最后一句話,這句話點(diǎn)出了為什么按鍵時(shí)間的觸發(fā)為何會(huì)導(dǎo)致系統(tǒng)事件也接受到了)現(xiàn)在以 SimpleBLEPeripheral 為例說明按鍵流程在 SimpleBLEPeripheral 任務(wù)初始化函數(shù)中有這樣一條代碼:  / Register for all key events - This app will handle all key events  RegisterForKeys( simpleBLEPeripher

4、al_TaskID );這個(gè)函數(shù)來自 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_

5、id )  / Allow only the first task  if ( registeredKeysTaskID = NO_TASK_ID )      registeredKeysTaskID = task_id;    return ( true );    else    return ( false );向一個(gè)全局變量 registeredKeysTaskID中賦值自己的任務(wù) ID,調(diào)用了這個(gè)函數(shù)就能成功注冊(cè)按鍵服務(wù),那

6、這個(gè)全局變量在何時(shí)使用呢?分析到這里,感覺有點(diǎn)迷糊了,我們可以從頂?shù)较路治?。任何一個(gè)程序都是從main函數(shù)開始的,這點(diǎn)我們要堅(jiān)信。所以我們首先找到這個(gè)main函數(shù)打開SimpleBLEPeripheral_Main.c文件可以看到/* fn          main* brief       Start of application.* param       none* return      none*/int

7、 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(); &

8、#160;/* Initialize LL */  /* Initialize the operating system */  osal_init_system();  /* Enable interrupts */  HAL_ENABLE_INTERRUPTS();  / Final board initialization  InitBoard( OB_READY );  #if defined ( POWER_SAVING )  

9、0; osal_pwrmgr_device( PWRMGR_BATTERY );  #endif  /* Start OSAL */  osal_start_system(); / No Return from here  return 0;我們打開 InitBoard( OB_READY );可以看到如下代碼/* fn      InitBoard()* brief   Initialize the CC2540DB Board Peripherals*

10、 param   level: COLD,WARM,READY* return  None*/void InitBoard( uint8 level )  if ( level = OB_COLD )      / Interrupts off    osal_int_disable( INTS_ALL );    / Turn all LEDs off    HalLedSet( HAL_LED_ALL, HAL_LED_MODE_O

11、FF );    / Check for Brown-Out reset/    ChkReset();    else  / !OB_COLD      /* Initialize Key stuff */    OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;    /OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;&#

12、160;   HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);  看到我上面標(biāo)注的函數(shù)了吧?那個(gè)是一個(gè)按鍵回調(diào)服務(wù)注冊(cè)函數(shù),注冊(cè)了一個(gè)OnBoard_KeyCallback函數(shù)HalKeyConfig 函數(shù)的實(shí)現(xiàn):將上述的回調(diào)函數(shù)的地址復(fù)制給了函數(shù)指針變量。通過跟蹤發(fā)現(xiàn)該函數(shù)的指針變量在按鍵的輪詢函數(shù)中調(diào)用了,如下圖:/* fn      HalKeyPoll* brief   Called by hal_driver t

13、o 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 |=

14、HAL_KEY_SW_1;    if (!(HAL_KEY_SW_2_PORT & HAL_KEY_SW_2_BIT)    /* Key is active low */      keys |= HAL_KEY_SW_2;  #else  if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)    /* Key is active low */   

15、  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

16、   * are compared to find out if a key has changed status.   */  if (!Hal_KeyIntEnable)      if (keys = halKeySavedKeys)          /* Exit - since no keys have changed */      return;    

17、0;   else          notify = 1;        else      /* Key interrupt handled here */    if (keys)          notify = 1;        /* Store the current ke

18、ys for comparation next time */  halKeySavedKeys = keys;  /* Invoke Callback if new keys were depressed */  if (notify && (pHalKeyProcessFunction)      (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);  在這里底層的按鍵查詢函數(shù)調(diào)用

19、一個(gè)函數(shù)指針,而非具體的函數(shù),這樣就將處理按鍵的接口留給了上層,上層應(yīng)用中,叧需解析的函數(shù)指針傳入的參數(shù) 1:keys 就知道是哪個(gè)按鍵被按下了。我們?cè)倩氐絼偛诺?OnBoard_KeyCallback 回調(diào)函數(shù)處,該回調(diào)函數(shù)代碼如下:/* fn      OnBoard_KeyCallback* brief   Callback service for keys* param   keys  - keys that were pressed*      

20、    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 enabled 

21、60;shift = (OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE) ? false : (keys & HAL_KEY_SW_6) ? true : false);  if ( OnBoard_SendKeys( keys, shift ) != SUCCESS )  /就是這句話將按鍵消息上傳到應(yīng)用層去處理的      / Process SW1 here    if ( keys & HAL_KEY_SW

22、_1 )  / Switch 1            / Process SW2 here    if ( keys & HAL_KEY_SW_2 )  / Switch 2            / Process SW3 here    if ( keys & HAL_KEY_SW_3 )  / Switch 3      &

23、#160;     / Process SW4 here    if ( keys & HAL_KEY_SW_4 )  / Switch 4            / Process SW5 here    if ( keys & HAL_KEY_SW_5 )  / Switch 5            / Process SW6 here  

24、60; if ( keys & HAL_KEY_SW_6 )  / Switch 6            /* If any key is currently pressed down and interrupt     is still enabled, disable interrupt and switch to polling */  if( keys != 0 )      i

25、f( OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE )          OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;      HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);        /* If no key is currently pressed down an

26、d interrupt     is disabled, enable interrupt and turn off polling */  else      if( OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE )          OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;      Hal

27、KeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);      進(jìn)入按鍵消息發(fā)送函數(shù)中可以看到/* fn      OnBoard_SendKeys* brief   Send "Key Pressed" message to application.* param   keys  - keys that were pressed*      

28、    state - shifted* return  status*/uint8 OnBoard_SendKeys( uint8 keys, uint8 state )  keyChange_t *msgPtr;  if ( registeredKeysTaskID != NO_TASK_ID )      / Send the address to the task    msgPtr = (keyChange_t *)osal_msg_alloca

29、te( sizeof(keyChange_t) );    if ( msgPtr )          msgPtr->hdr.event = KEY_CHANGE;      msgPtr->state = state;      msgPtr->keys = keys;      osal_msg_send( registeredKeysTaskID, (uint

30、8 *)msgPtr );        return ( SUCCESS );    else    return ( FAILURE );主要是將按鍵時(shí)間,狀態(tài)和按鍵值打包到信息中最后通過 osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );發(fā)送到注冊(cè)了按鍵服務(wù)的應(yīng)用層去 ,最終用戶按了哪個(gè)按鍵,如何響應(yīng)該按鍵在系統(tǒng)事件 SYS_EVENT_MSG 中處理。疑問又來了,為什么通過 osal_msg_send 收發(fā)的

31、消息會(huì)出現(xiàn)在 SYS_EVENT_MSG 中呢?這個(gè)疑問,就是剛才我說過的osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr )會(huì)產(chǎn)生一個(gè) a message  ready event in the destination tasks event list./* fn      osal_msg_send* brief*    This function is called by a task to send a command message to*

32、    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 set a message*    ready event in the destination tasks eve

33、nt list.* param   uint8 destination_task - Send msg to Task ID* param   uint8 *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_enqueue

34、_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 *p

35、Msg )  switch ( pMsg->event )    #if defined( CC2540_MINIDK )    case KEY_CHANGE:                  /按鍵處理事件,用戶產(chǎn)生的按鍵都是在這里處理          simpleBLEPeripheral_Handle

36、Keys( (keyChange_t *)pMsg)->state, (keyChange_t *)pMsg)->keys );      break;  #endif / #if defined( CC2540_MINIDK )  default:    / do nothing    break;  在 SimpleBLEPeripheral 中,對(duì)按鍵的響應(yīng)如下:joystick right(SW2)收發(fā)廣播的開啟和關(guān)閉/* fn

37、0;     simpleBLEPeripheral_HandleKeys* brief   Handles all key events for this device.* param   shift - true if in shift/alt.* param   keys - bit field for key events. Valid entries:*                &

38、#160;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 para

39、meter  if ( 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 the right key should toggle    / advertising on

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論