【CC2541】CC2541之HAL层KEY分析

CC2541之HALKEY分析

CC2541BLE协议栈中,KEY测试是由HAL层来进行抽象和管理的。关于按键的的测试代码和配置主要集中在hal_drivers.chal_drivers.hhal_key.chal_key.hhal_board_cfg.hOnboard.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.cHalDriverInit()定义如下,其中调用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;
}

OnBoard.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);
  }
}

你可能感兴趣的:(CC2541)