【CC 2541】CC 2541のHAL層KEY分析

18147 ワード

CC 2541のHAL層KEY分析
CC 2541 BLEプロトコルスタックでは、KEYテストはHALレイヤによって抽象化され、管理される.キーのテストコードと構成については主にhal_に集中しています.drivers.c 、hal_drivers.h 、hal_key.c、hal_key.h、hal_board_cfg.h、Onboard.cいくつかのファイルにあります.初期化:main関数HALレイヤのKEY初期化は主にHalDriverInit();InitBoard( OB_READY );を呼び出し、コードは以下の通りである.
int main(void)
{
    /* Initialize hardware */
    HAL_BOARD_INIT();

    // Initialize board I/O
    InitBoard( OB_COLD );

    /* Initialze the HAL driver */
    HalDriverInit(); 

    // Final board initialization
    InitBoard( OB_READY );

    /* Initialize NV system */
    osal_snv_init();

    /*Initialize LL*/
    /* Initialize the operating system x*/
    osal_init_system();

    /* Enable interrupts */
    HAL_ENABLE_INTERRUPTS();

    // Final board initialization
    InitBoard( OB_READY );

    #if defined ( POWER_SAVING )
    osal_pwrmgr_device( PWRMGR_BATTERY );

    #if defined (WDT_USED)
    WD_INIT();
    #endif

    /* Start OSAL */  
    osal_start_system(); // No Return from here

    return 0;
}

hal_drivers.cにおけるHalDriverInit()は、ボタンの初期化処理のためにHalKeyInit();が呼び出され、コードは以下のように定義される.
void HalDriverInit (void)
{
  /* TIMER */
#if (defined HAL_TIMER) && (HAL_TIMER == TRUE)
#endif

  /* ADC */
#if (defined HAL_ADC) && (HAL_ADC == TRUE)
  HalAdcInit();
#endif

  /* DMA */
#if (defined HAL_DMA) && (HAL_DMA == TRUE)
  // Must be called before the init call to any module that uses DMA.
  HalDmaInit();
#endif

  /* AES */
#if (defined HAL_AES) && (HAL_AES == TRUE)
  HalAesInit();
#endif

  /* LCD */
#if (defined HAL_LCD) && (HAL_LCD == TRUE)
  HalLcdInit();
#endif

  /* LED */
#if (defined HAL_LED) && (HAL_LED == TRUE)
  HalLedInit();
#endif

  /* UART */
#if (defined HAL_UART) && (HAL_UART == TRUE)
  HalUARTInit();
#endif

  /* KEY */
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
  HalKeyInit();
#endif

  /* HID */
#if (defined HAL_HID) && (HAL_HID == TRUE)
  usbHidInit();
#endif

#if (defined HAL_BAT) && (HAL_BAT == TRUE)
  //HalBatteryInit();
#endif
}

hal_key.cのHalKeyInit( void )は、以下のように定義される.
変数の説明:
  • halKeySavedKeys:前回のボタンの状態をローテーションモードで保存するために使用される.
  • pHalKeyProcessFunction:コールバック処理のための関数ポインタ.初期化時、指向はNULLで、その構造は以下の通りである.
  • 定義:static halKeyCBack_t pHalKeyProcessFunction;
  • タイプ:typedef void (*halKeyCBack_t) (uint8 keys, uint8 state);
  • HalKeyConfigured:ボタン構成パラメータ、FALSEに初期化されます.
  • void HalKeyInit( void )
    {
      halKeySavedKeys = 0;  // Initialize previous key to 0.
    
      #if defined ( CC2540_MINIDK )
      HAL_KEY_SW_1_SEL &= ~(HAL_KEY_SW_1_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_1_DIR &= ~(HAL_KEY_SW_1_BIT);    /* Set pin direction to Input */
      HAL_KEY_SW_2_SEL &= ~(HAL_KEY_SW_2_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_2_DIR &= ~(HAL_KEY_SW_2_BIT);    /* Set pin direction to Input */
      #else
      HAL_KEY_SW_6_SEL &= ~(HAL_KEY_SW_6_BIT);    /* Set pin function to GPIO */
      HAL_KEY_SW_6_DIR &= ~(HAL_KEY_SW_6_BIT);    /* Set pin direction to Input */
      HAL_KEY_SW_7_SEL &= ~(HAL_KEY_SW_7_BIT);    /* Set pin function to GPIO*/
      HAL_KEY_SW_7_DIR &= ~(HAL_KEY_SW_7_BIT);    /* Set pin direction to Input*/
      #endif
      #endif
    
      /* Initialize callback function */
      pHalKeyProcessFunction  = NULL;
    
      /* Start with key is not configured */
      HalKeyConfigured = FALSE;
    }
    

    オンボードでc中:InitBoard(uint8 level)関数でボタンのトリガ方式(割り込み方式、非割り込み方式)が選択されている.HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);は、割り込み可能なパラメータおよびコールバック関数を含むキーサービスを構成する.コードは以下の通り:変数説明:OnboardKeyIntEnable:ボタンが中断する方式のイネーブルスイッチ.賦値HAL_KEY_INTERRUPT_DISABLE非中断方式(すなわち輪訓方式)、賦値HAL_KEY_INTERRUPT_ENABLE中断方式.
    void InitBoard( uint8 level )
    {
      if ( level == OB_COLD )
      {
        osal_int_disable( INTS_ALL );
        HalLedSet( HAL_LED_ALL, HAL_LED_MODE_OFF );
      }
      else//!OB_COLD
      {
          OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;
          HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
      }
    }

    hal_key.cのHalKeyConfig (bool interruptEnable, halKeyCBack_t cback)は、入力キー方式パラメータ(割り込み方式または非割り込み方式)および入力コールバック関数に用いられる.変数説明:Hal_KeyIntEnable:キーを記録する方法(割り込み方式と非割り込み方式).pHalKeyProcessFunction:コールバック関数を指し、上述した.
    void HalKeyConfig (bool interruptEnable, halKeyCBack_t cback)
    {
      /* Enable/Disable Interrupt or */
      Hal_KeyIntEnable = interruptEnable;
    
      /* Register the callback fucntion */
      pHalKeyProcessFunction = cback;
    
      /* Determine if interrupt is enable or not */
      if (Hal_KeyIntEnable)
      {
           #if defined ( CC2540_MINIDK )
               /* Rising/Falling edge configuratinn */
               PICTL |= HAL_KEY_SW_1_EDGEBIT;   /* Set the edge bit to set falling edge to give int */
               HAL_KEY_SW_1_ICTL |= HAL_KEY_SW_1_ICTLBIT; /* enable interrupt generation at port */
               HAL_KEY_SW_1_IEN |= HAL_KEY_SW_1_IENBIT;   /* enable CPU interrupt */
               HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear any pending interrupt */
               HAL_KEY_SW_2_ICTL |= HAL_KEY_SW_2_ICTLBIT; /* enable interrupt generation at port */
               HAL_KEY_SW_2_IEN |= HAL_KEY_SW_2_IENBIT;   /* enable CPU interrupt */
               HAL_KEY_SW_2_PXIFG = ~(HAL_KEY_SW_2_BIT); /* Clear any pending interrupt */
           #else
                /* *************************
                *   Interrupt configuration:
                * - Enable interrupt generation at the port
                * - Enable CPU interrupt
                * - Clear any pending interrupt
                ***************************/
               HAL_KEY_SW_6_ICTL |= HAL_KEY_SW_6_ICTLBIT;//Port0_1
               HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); //flag  BV(1)
               HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT;//Port1_0
               HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); //flag  BV(0);
           #endif // !CC2540_MINIDK
    
          /* Do this only after the hal_key is configured - to work with sleep stuff */
          if (HalKeyConfigured == TRUE)
          {
              osal_stop_timerEx(Hal_TaskID, HAL_KEY_EVENT);  /* Cancel polling if active */
          }
      }
      else    /* Interrupts NOT enabled */
      {
         #if defined ( CC2540_MINIDK )
             HAL_KEY_SW_1_ICTL &= ~(HAL_KEY_SW_1_ICTLBIT); /* don't generate interrupt */
             HAL_KEY_SW_1_IEN &= ~(HAL_KEY_SW_1_IENBIT);   /* Clear interrupt enable bit */
             HAL_KEY_SW_2_ICTL &= ~(HAL_KEY_SW_2_ICTLBIT); /* don't generate interrupt */
             HAL_KEY_SW_2_IEN &= ~(HAL_KEY_SW_2_IENBIT);   /* Clear interrupt enable bit */
         #else
             //HAL_KEY_SW_6_ICTL &= ~(HAL_KEY_SW_6_ICTLBIT); /* don't generate interrupt */
             //HAL_KEY_SW_6_IEN &= ~(HAL_KEY_SW_6_IENBIT);   /* Clear interrupt enable bit */
             //HAL_KEY_SW_BIT_ICTL &= ~HAL_KEY_SW_ICTLBIT;
         #endif  // !CC2540_MINIDK
          osal_set_event(Hal_TaskID, HAL_KEY_EVENT);
      }
    
      /* Key now is configured */
      HalKeyConfigured = TRUE;
    }
    

    キートリガの処理:hal_key.c処理関数halProcessKeyInterrupt (void)を中断し、ボタンが関数の中でHAL_KEY_EVENTのタスクの処理をトリガした場合:
    void halProcessKeyInterrupt (void)
    {
      bool valid=FALSE;
    
    #if defined ( CC2540_MINIDK )
          if( HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT) /* Interrupt Flag has been set by SW1 */
          {
            HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear Interrupt Flag */
            valid = TRUE;
          }
          if (HAL_KEY_SW_2_PXIFG & HAL_KEY_SW_2_BIT)  /* Interrupt Flag has been set by SW2 */
          {
            HAL_KEY_SW_2_PXIFG = ~(HAL_KEY_SW_2_BIT); /* Clear Interrupt Flag */
            valid = TRUE;
          }
    #else
          if(HAL_KEY_SW_6_PXIFG&HAL_KEY_SW_6_BIT)
          {
            HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /*Clear Interrupt Flag */
            valid = TRUE;
          }
          if(HAL_KEY_SW_7_PXIFG&HAL_KEY_SW_7_BIT) 
          { 
               HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); /*Clear Interrupt Flag*/
            valid = TRUE;
          }
    #endif
      //ev_queue_event(EV_KEY_1_PRESS);//this section is removed by tony 20160617
      if (valid)
      {
        osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);//25ms
      }
    }
    

    hal_drivers.cにおけるHAL_KEY_EVENTタスクの処理:
      if (events & HAL_KEY_EVENT)
      {
        #if (defined HAL_KEY) && (HAL_KEY == TRUE)
        /* Check for keys */
        HalKeyPoll();
        /* if interrupt disabled, do next polling */
        #if 1
        if (!Hal_KeyIntEnable)
        {
            // if(lcd_sleep_flag == 1)
            {
               osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 200);
            }       
        }
        #endif
        #endif
        return events ^ HAL_KEY_EVENT;
      }
    

    hal_key.c
    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;
      }
    #else
      if(!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)){
         keys |= HAL_KEY_1;
      }
      if(!(HAL_KEY_SW_7_PORT&HAL_KEY_SW_7_BIT)){
         keys |= HAL_KEY_2;
      } 
      //keys = read_adc_key_value();
    #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);
      }
    }