【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 herereturn 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; }

【【CC2541】CC2541之HAL层KEY分析】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); //flagBV(1) HAL_KEY_SW_7_ICTL |= HAL_KEY_SW_7_ICTLBIT; //Port1_0 HAL_KEY_SW_7_PXIFG = ~(HAL_KEY_SW_7_BIT); //flagBV(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); } }

    推荐阅读