TI 的OSAL做的很不错,不过看起来也挺费劲可能自己水平太差吧,网上买的谷雨的开发板觉得确实挺不错的。
做点学习笔记,首先是记录OSAL里执行的顺序流程,主要是task ,event,message
1,
APP_Main.c:
/* Initialize the operating system */
osal_init_system();
其中初始化了
// Initialize the system tasks.
osalInitTasks();
1 /********************************************************************* 2 * @fn osalInitTasks 3 * 4 * @brief This function invokes the initialization function for each task. 5 * 6 * @param void 7 * 8 * @return none 9 */ 10 void osalInitTasks( void ) 11 { 12 uint8 taskID = 0; 13 14 tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); 15 osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt)); 16 17 /* LL Task */ 18 LL_Init( taskID++ ); 19 20 /* Hal Task */ 21 Hal_Init( taskID++ ); 22 23 /* HCI Task */ 24 HCI_Init( taskID++ ); 25 26 #if defined ( OSAL_CBTIMER_NUM_TASKS ) 27 /* Callback Timer Tasks */ 28 osal_CbTimerInit( taskID ); 29 taskID += OSAL_CBTIMER_NUM_TASKS; 30 #endif 31 32 /* L2CAP Task */ 33 L2CAP_Init( taskID++ ); 34 35 /* GAP Task */ 36 GAP_Init( taskID++ ); 37 38 /* GATT Task */ 39 GATT_Init( taskID++ ); 40 41 /* SM Task */ 42 SM_Init( taskID++ ); 43 44 /* Profiles */ 45 GAPRole_Init( taskID++ ); 46 GAPBondMgr_Init( taskID++ ); 47 48 GATTServApp_Init( taskID++ ); 49 50 /* Application */ 51 SimpleBLEPeripheral_Init( taskID ); 52 }
这个很关键,这个函数在OSAL_APP.c,初始化了所有的task以及tasksEvents,用来存储每个task中的事件表。
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
2,task存放:
1 // The order in this table must be identical to the task initialization calls below in osalInitTask. 2 const pTaskEventHandlerFn tasksArr[] = 3 { 4 LL_ProcessEvent, // task 0 5 Hal_ProcessEvent, // task 1 6 HCI_ProcessEvent, // task 2 7 #if defined ( OSAL_CBTIMER_NUM_TASKS ) 8 OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), // task 3 9 #endif 10 L2CAP_ProcessEvent, // task 4 11 GAP_ProcessEvent, // task 5 12 GATT_ProcessEvent, // task 6 13 SM_ProcessEvent, // task 7 14 GAPRole_ProcessEvent, // task 8 15 GAPBondMgr_ProcessEvent, // task 9 16 GATTServApp_ProcessEvent, // task 10 17 SimpleBLEPeripheral_ProcessEvent // task 11 18 };
OSAL_APP.c 之后程序的各任务函数都在这里。
typedef unsigned short (*pTaskEventHandlerFn)( unsigned char task_id, unsigned short event );
3,task,os启动
APP_Main.c:
/* Start OSAL */
osal_start_system(); // No Return from here
这里进入无限循环:
1 void osal_start_system( void ) 2 { 3 #if !defined ( ZBIT ) && !defined ( UBIT ) 4 for(;;) // Forever Loop 5 #endif 6 { 7 osal_run_system(); 8 } 9 }
主要调用每个task判断在其中的osal_run_system
1 /********************************************************************* 2 * @fn osal_run_system 3 * 4 * @brief 5 * 6 * This function will make one pass through the OSAL taskEvents table 7 * and call the task_event_processor() function for the first task that 8 * is found with at least one event pending. If there are no pending 9 * events (all tasks), this function puts the processor into Sleep. 10 * 11 * @param void 12 * 13 * @return none 14 */ 15 void osal_run_system( void ) 16 { 17 uint8 idx = 0; 18 19 #ifndef HAL_BOARD_CC2538 20 osalTimeUpdate(); 21 #endif 22 23 Hal_ProcessPoll(); 24 25 do { 26 if (tasksEvents[idx]) // Task is highest priority that is ready. 27 { 28 break; 29 } 30 } while (++idx < tasksCnt); 31 32 if (idx < tasksCnt) 33 { 34 uint16 events; 35 halIntState_t intState; 36 37 HAL_ENTER_CRITICAL_SECTION(intState); 38 events = tasksEvents[idx]; 39 tasksEvents[idx] = 0; // Clear the Events for this task. 40 HAL_EXIT_CRITICAL_SECTION(intState); 41 42 activeTaskID = idx; 43 events = (tasksArr[idx])( idx, events ); 44 activeTaskID = TASK_NO_TASK; 45 46 HAL_ENTER_CRITICAL_SECTION(intState); 47 tasksEvents[idx] |= events; // Add back unprocessed events to the current task. 48 HAL_EXIT_CRITICAL_SECTION(intState); 49 } 50 #if defined( POWER_SAVING ) 51 else // Complete pass through all task events with no activity? 52 { 53 osal_pwrmgr_powerconserve(); // Put the processor/system into sleep 54 } 55 #endif 56 57 /* Yield in case cooperative scheduling is being used. */ 58 #if defined (configUSE_PREEMPTION) && (configUSE_PREEMPTION == 0) 59 { 60 osal_task_yield(); 61 } 62 #endif 63 }
先按task id判断优先级在前的task跳出来,然后根据event来执行程序。所谓根据event来执行是在task的主函数中通过if来判断:
比如我现在看的SimpleBLEPeripheral_ProcessEvent()也就是我们的application task
1 /********************************************************************* 2 * @fn SimpleBLEPeripheral_ProcessEvent 3 * 4 * @brief Simple BLE Peripheral Application Task event processor. This function 5 * is called to process all events for the task. Events 6 * include timers, messages and any other user defined events. 7 * 8 * @param task_id - The OSAL assigned task ID. 9 * @param events - events to process. This is a bit map and can 10 * contain more than one event. 11 * 12 * @return events not processed 13 */ 14 uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events ) 15 { 16 17 VOID task_id; // OSAL required parameter that isn't used in this function 18 19 if ( events & SYS_EVENT_MSG ) 20 { 21 uint8 *pMsg; 22 23 if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL ) 24 { 25 simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg ); 26 27 // Release the OSAL message 28 VOID osal_msg_deallocate( pMsg ); 29 } 30 31 // return unprocessed events 32 return (events ^ SYS_EVENT_MSG); 33 } 34 35 if ( events & SBP_START_DEVICE_EVT ) 36 { 37 // Start the Device 38 VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs ); 39 40 // Start Bond Manager 41 VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs ); 42 43 // Set timer for first periodic event 44 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); 45 46 return ( events ^ SBP_START_DEVICE_EVT ); 47 } 48 49 if ( events & SBP_PERIODIC_EVT ) 50 { 51 // Restart timer 52 if ( SBP_PERIODIC_EVT_PERIOD ) 53 { 54 osal_start_timerEx( simpleBLEPeripheral_TaskID, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD ); 55 } 56 57 // Perform periodic application task 58 performPeriodicTask(); 59 60 return (events ^ SBP_PERIODIC_EVT); 61 } 62 63 #if defined ( PLUS_BROADCASTER ) 64 if ( events & SBP_ADV_IN_CONNECTION_EVT ) 65 { 66 uint8 turnOnAdv = TRUE; 67 // Turn on advertising while in a connection 68 GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &turnOnAdv ); 69 70 return (events ^ SBP_ADV_IN_CONNECTION_EVT); 71 } 72 #endif // PLUS_BROADCASTER 73 74 // Discard unknown events 75 return 0; 76 }
看到先执行:SYS_EVENT_MSG然后是SBP_START_DEVICE_EVT
每个EVENT执行完就return保证不过多占用CPU,
// return unprocessed events
return (events ^ SYS_EVENT_MSG);
return之后又会回到osal_run_system循环
4,event插入:
先不说SYS_EVENT_MSG,
刚才的SBP_START_DEVICE_EVT是在初始化时候就插入的
osalInitTasks();中的void SimpleBLEPeripheral_Init( uint8 task_id )
1 /********************************************************************* 2 * @fn SimpleBLEPeripheral_Init 3 * 4 * @brief Initialization function for the Simple BLE Peripheral App Task. 5 * This is called during initialization and should contain 6 * any application specific initialization (ie. hardware 7 * initialization/setup, table initialization, power up 8 * notificaiton ... ). 9 * 10 * @param task_id - the ID assigned by OSAL. This ID should be 11 * used to send messages and set timers. 12 * 13 * @return none 14 */ 15 void SimpleBLEPeripheral_Init( uint8 task_id ) 16 { 17 simpleBLEPeripheral_TaskID = task_id; 18 19 // Setup the GAP 20 VOID GAP_SetParamValue( TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL ); 21 22 // Setup the GAP Peripheral Role Profile 23 { 24 #if defined( CC2540_MINIDK ) 25 // For the CC2540DK-MINI keyfob, device doesn't start advertising until button is pressed 26 uint8 initial_advertising_enable = FALSE; 27 #else 28 // For other hardware platforms, device starts advertising upon initialization 29 uint8 initial_advertising_enable = TRUE; 30 #endif 31 32 // By setting this to zero, the device will go into the waiting state after 33 // being discoverable for 30.72 second, and will not being advertising again 34 // until the enabler is set back to TRUE 35 uint16 gapRole_AdvertOffTime = 0; 36 37 uint8 enable_update_request = DEFAULT_ENABLE_UPDATE_REQUEST; 38 uint16 desired_min_interval = DEFAULT_DESIRED_MIN_CONN_INTERVAL; 39 uint16 desired_max_interval = DEFAULT_DESIRED_MAX_CONN_INTERVAL; 40 uint16 desired_slave_latency = DEFAULT_DESIRED_SLAVE_LATENCY; 41 uint16 desired_conn_timeout = DEFAULT_DESIRED_CONN_TIMEOUT; 42 43 // Set the GAP Role Parameters 44 GAPRole_SetParameter( GAPROLE_ADVERT_ENABLED, sizeof( uint8 ), &initial_advertising_enable ); 45 GAPRole_SetParameter( GAPROLE_ADVERT_OFF_TIME, sizeof( uint16 ), &gapRole_AdvertOffTime ); 46 47 GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( scanRspData ), scanRspData ); 48 GAPRole_SetParameter( GAPROLE_ADVERT_DATA, sizeof( advertData ), advertData ); 49 50 GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, sizeof( uint8 ), &enable_update_request ); 51 GAPRole_SetParameter( GAPROLE_MIN_CONN_INTERVAL, sizeof( uint16 ), &desired_min_interval ); 52 GAPRole_SetParameter( GAPROLE_MAX_CONN_INTERVAL, sizeof( uint16 ), &desired_max_interval ); 53 GAPRole_SetParameter( GAPROLE_SLAVE_LATENCY, sizeof( uint16 ), &desired_slave_latency ); 54 GAPRole_SetParameter( GAPROLE_TIMEOUT_MULTIPLIER, sizeof( uint16 ), &desired_conn_timeout ); 55 } 56 57 // Set the GAP Characteristics 58 GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName ); 59 60 // Set advertising interval 61 { 62 uint16 advInt = DEFAULT_ADVERTISING_INTERVAL; 63 64 GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MIN, advInt ); 65 GAP_SetParamValue( TGAP_LIM_DISC_ADV_INT_MAX, advInt ); 66 GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MIN, advInt ); 67 GAP_SetParamValue( TGAP_GEN_DISC_ADV_INT_MAX, advInt ); 68 } 69 70 // Setup the GAP Bond Manager 71 { 72 uint32 passkey = 0; // passkey "000000" 73 uint8 pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ; 74 uint8 mitm = TRUE; 75 uint8 ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY; 76 uint8 bonding = TRUE; 77 GAPBondMgr_SetParameter( GAPBOND_DEFAULT_PASSCODE, sizeof ( uint32 ), &passkey ); 78 GAPBondMgr_SetParameter( GAPBOND_PAIRING_MODE, sizeof ( uint8 ), &pairMode ); 79 GAPBondMgr_SetParameter( GAPBOND_MITM_PROTECTION, sizeof ( uint8 ), &mitm ); 80 GAPBondMgr_SetParameter( GAPBOND_IO_CAPABILITIES, sizeof ( uint8 ), &ioCap ); 81 GAPBondMgr_SetParameter( GAPBOND_BONDING_ENABLED, sizeof ( uint8 ), &bonding ); 82 } 83 84 // Initialize GATT attributes 85 GGS_AddService( GATT_ALL_SERVICES ); // GAP 86 GATTServApp_AddService( GATT_ALL_SERVICES ); // GATT attributes 87 DevInfo_AddService(); // Device Information Service 88 SimpleProfile_AddService( GATT_ALL_SERVICES ); // Simple GATT Profile 89 #if defined FEATURE_OAD 90 VOID OADTarget_AddService(); // OAD Profile 91 #endif 92 93 // Setup the SimpleProfile Characteristic Values 94 { 95 uint8 charValue1 = 1; 96 uint8 charValue2 = 2; 97 uint8 charValue3 = 3; 98 uint8 charValue4 = 4; 99 uint8 charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 }; 100 SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR1, sizeof ( uint8 ), &charValue1 ); 101 SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR2, sizeof ( uint8 ), &charValue2 ); 102 SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR3, sizeof ( uint8 ), &charValue3 ); 103 SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR4, sizeof ( uint8 ), &charValue4 ); 104 SimpleProfile_SetParameter( SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN, charValue5 ); 105 } 106 107 108 #if defined( CC2540_MINIDK ) 109 110 SK_AddService( GATT_ALL_SERVICES ); // Simple Keys Profile 111 112 // Register for all key events - This app will handle all key events 113 RegisterForKeys( simpleBLEPeripheral_TaskID ); 114 115 // makes sure LEDs are off 116 HalLedSet( (HAL_LED_1 | HAL_LED_2), HAL_LED_MODE_OFF ); 117 118 // For keyfob board set GPIO pins into a power-optimized state 119 // Note that there is still some leakage current from the buzzer, 120 // accelerometer, LEDs, and buttons on the PCB. 121 122 P0SEL = 0; // Configure Port 0 as GPIO 123 P1SEL = 0; // Configure Port 1 as GPIO 124 P2SEL = 0; // Configure Port 2 as GPIO 125 126 P0DIR = 0xFC; // Port 0 pins P0.0 and P0.1 as input (buttons), 127 // all others (P0.2-P0.7) as output 128 P1DIR = 0xFF; // All port 1 pins (P1.0-P1.7) as output 129 P2DIR = 0x1F; // All port 1 pins (P2.0-P2.4) as output 130 131 P0 = 0x03; // All pins on port 0 to low except for P0.0 and P0.1 (buttons) 132 P1 = 0; // All pins on port 1 to low 133 P2 = 0; // All pins on port 2 to low 134 135 #endif // #if defined( CC2540_MINIDK ) 136 137 #if (defined HAL_LCD) && (HAL_LCD == TRUE) 138 139 #if defined FEATURE_OAD 140 #if defined (HAL_IMAGE_A) 141 HalLcdWriteStringValue( "BLE Peri-A", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 ); 142 #else 143 HalLcdWriteStringValue( "BLE Peri-B", OAD_VER_NUM( _imgHdr.ver ), 16, HAL_LCD_LINE_1 ); 144 #endif // HAL_IMAGE_A 145 #else 146 HalLcdWriteString( "BLE Peripheral", HAL_LCD_LINE_1 ); 147 #endif // FEATURE_OAD 148 149 #endif // (defined HAL_LCD) && (HAL_LCD == TRUE) 150 151 // Register callback with SimpleGATTprofile 152 VOID SimpleProfile_RegisterAppCBs( &simpleBLEPeripheral_SimpleProfileCBs ); 153 154 // Enable clock divide on halt 155 // This reduces active current while radio is active and CC254x MCU 156 // is halted 157 HCI_EXT_ClkDivOnHaltCmd( HCI_EXT_ENABLE_CLK_DIVIDE_ON_HALT ); 158 159 #if defined ( DC_DC_P0_7 ) 160 161 // Enable stack to toggle bypass control on TPS62730 (DC/DC converter) 162 HCI_EXT_MapPmIoPortCmd( HCI_EXT_PM_IO_PORT_P0, HCI_EXT_PM_IO_PORT_PIN7 ); 163 164 #endif // defined ( DC_DC_P0_7 ) 165 166 // Setup a delayed profile startup 167 osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); 168 169 }
最后一句:
// Setup a delayed profile startup
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT );
5,message:
只能简单做个笔记不细说它的功能作用,我们在SimpleBLEPeripheral_ProcessEvent的SYS_EVENT_MSG中看到的,一般message在这发送的是key事件,传回key的值这样可以带一些自己的data,不像event只是标志。
至于这个key的来源:
1,之前已经初始化过hal_key,在前面可以找到,
/* Initialize Key stuff */
OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE;
//OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE;
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
SimpleBLEPeripheral_Init中注册,把key和task联系起来,也就是key按了之后通知哪个task
// Register for all key events - This app will handle all key events
RegisterForKeys( simpleBLEPeripheral_TaskID );
2,执行顺序首先是按键引起中断:
hal_key.c中void halProcessKeyInterrupt (void)
1 /************************************************************************************************** 2 * @fn halProcessKeyInterrupt 3 * 4 * @brief Checks to see if it's a valid key interrupt, saves interrupt driven key states for 5 * processing by HalKeyRead(), and debounces keys by scheduling HalKeyRead() 25ms later. 6 * 7 * @param 8 * 9 * @return 10 **************************************************************************************************/ 11 void halProcessKeyInterrupt (void) 12 { 13 bool valid=FALSE; 14 15 #if defined ( CC2540_MINIDK ) 16 if( HAL_KEY_SW_1_PXIFG & HAL_KEY_SW_1_BIT) /* Interrupt Flag has been set by SW1 */ 17 { 18 HAL_KEY_SW_1_PXIFG = ~(HAL_KEY_SW_1_BIT); /* Clear Interrupt Flag */ 19 valid = TRUE; 20 } 21 22 if (HAL_KEY_SW_2_PXIFG & HAL_KEY_SW_2_BIT) /* Interrupt Flag has been set by SW2 */ 23 { 24 HAL_KEY_SW_2_PXIFG = ~(HAL_KEY_SW_2_BIT); /* Clear Interrupt Flag */ 25 valid = TRUE; 26 } 27 #else 28 if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT) /* Interrupt Flag has been set */ 29 { 30 HAL_KEY_SW_6_PXIFG = ~(HAL_KEY_SW_6_BIT); /* Clear Interrupt Flag */ 31 valid = TRUE; 32 } 33 34 if (HAL_KEY_JOY_MOVE_PXIFG & HAL_KEY_JOY_MOVE_BIT) /* Interrupt Flag has been set */ 35 { 36 HAL_KEY_JOY_MOVE_PXIFG = ~(HAL_KEY_JOY_MOVE_BIT); /* Clear Interrupt Flag */ 37 valid = TRUE; 38 } 39 #endif 40 if (valid) 41 { 42 osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE); 43 } 44 }
判断是否中断,中断清楚标志,最后osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);
这是告诉Hal_TaskID 的task,发生了HAL_KEY_EVENT,延时HAL_KEY_DEBOUNCE_VALUE之后执行,这里延时个人认为是去抖动
3,
Hal_TaskID 的task在hal_drive.c中
uint16 Hal_ProcessEvent( uint8 task_id, uint16 events )
if (events & HAL_KEY_EVENT)
{
#if (defined HAL_KEY) && (HAL_KEY == TRUE)
/* Check for keys */
HalKeyPoll();
/* if interrupt disabled, do next polling */
if (!Hal_KeyIntEnable)
{
osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);
}
#endif
return events ^ HAL_KEY_EVENT;
}
执行了HalKeyPoll();函数,注意后面if如果没有中断则100ms后再启动这个event,没有中断就是在这轮询
4,HalKeyPoll()
1 /************************************************************************************************** 2 * @fn HalKeyPoll 3 * 4 * @brief Called by hal_driver to poll the keys 5 * 6 * @param None 7 * 8 * @return None 9 **************************************************************************************************/ 10 void HalKeyPoll (void) 11 { 12 uint8 keys = 0; 13 uint8 notify = 0; 14 #if defined (CC2540_MINIDK) 15 if (!(HAL_KEY_SW_1_PORT & HAL_KEY_SW_1_BIT)) /* Key is active low */ 16 { 17 keys |= HAL_KEY_SW_1; 18 } 19 if (!(HAL_KEY_SW_2_PORT & HAL_KEY_SW_2_BIT)) /* Key is active low */ 20 { 21 keys |= HAL_KEY_SW_2; 22 } 23 #else 24 if (!(HAL_KEY_SW_6_PORT & HAL_KEY_SW_6_BIT)) /* Key is active low */ 25 { 26 keys |= HAL_KEY_SW_6; 27 } 28 29 if ((HAL_KEY_JOY_MOVE_PORT & HAL_KEY_JOY_MOVE_BIT)) /* Key is active HIGH */ 30 { 31 keys = halGetJoyKeyInput(); 32 } 33 #endif 34 35 /* If interrupts are not enabled, previous key status and current key status 36 * are compared to find out if a key has changed status. 37 */ 38 if (!Hal_KeyIntEnable) 39 { 40 if (keys == halKeySavedKeys) 41 { 42 /* Exit - since no keys have changed */ 43 return; 44 } 45 else 46 { 47 notify = 1; 48 } 49 } 50 else 51 { 52 /* Key interrupt handled here */ 53 if (keys) 54 { 55 notify = 1; 56 } 57 } 58 59 /* Store the current keys for comparation next time */ 60 halKeySavedKeys = keys; 61 62 /* Invoke Callback if new keys were depressed */ 63 if (notify && (pHalKeyProcessFunction)) 64 { 65 (pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); 66 67 } 68 }
前面是判断哪个被按下,最后一句很关键:
/* Invoke Callback if new keys were depressed */
if (notify && (pHalKeyProcessFunction))
{
(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL);
}
回调函数这时候启动OnBoard_KeyCallback这在之前的初始化时候和pHalKeyProcessFunction挂钩
5,
1 /********************************************************************* 2 * @fn OnBoard_KeyCallback 3 * 4 * @brief Callback service for keys 5 * 6 * @param keys - keys that were pressed 7 * state - shifted 8 * 9 * @return void 10 *********************************************************************/ 11 void OnBoard_KeyCallback ( uint8 keys, uint8 state ) 12 { 13 uint8 shift; 14 (void)state; 15 16 // shift key (S1) is used to generate key interrupt 17 // applications should not use S1 when key interrupt is enabled 18 shift = (OnboardKeyIntEnable == HAL_KEY_INTERRUPT_ENABLE) ? false : ((keys & HAL_KEY_SW_6) ? true : false); 19 20 if ( OnBoard_SendKeys( keys, shift ) != SUCCESS ) 21 { 22 // Process SW1 here 23 if ( keys & HAL_KEY_SW_1 ) // Switch 1 24 { 25 } 26 // Process SW2 here 27 if ( keys & HAL_KEY_SW_2 ) // Switch 2 28 { 29 } 30 // Process SW3 here 31 if ( keys & HAL_KEY_SW_3 ) // Switch 3 32 { 33 } 34 // Process SW4 here 35 if ( keys & HAL_KEY_SW_4 ) // Switch 4 36 { 37 } 38 // Process SW5 here 39 if ( keys & HAL_KEY_SW_5 ) // Switch 5 40 { 41 } 42 // Process SW6 here 43 if ( keys & HAL_KEY_SW_6 ) // Switch 6 44 { 45 } 46 } 47 48 /* If any key is currently pressed down and interrupt 49 is still enabled, disable interrupt and switch to polling */ 50 if( keys != 0 ) 51 { 52 if( OnboardKeyIntEnable == HAL_KEY_INTERRUPT_ENABLE ) 53 { 54 OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE; 55 HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback); 56 } 57 } 58 /* If no key is currently pressed down and interrupt 59 is disabled, enable interrupt and turn off polling */ 60 else 61 { 62 if( OnboardKeyIntEnable == HAL_KEY_INTERRUPT_DISABLE ) 63 { 64 OnboardKeyIntEnable = HAL_KEY_INTERRUPT_ENABLE; 65 HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback); 66 } 67 } 68 }
在on_board.c中
主要的一句:OnBoard_SendKeys( keys, shift )这里发送给了前台task
1 ********************************************************************* 2 * @fn OnBoard_SendKeys 3 * 4 * @brief Send "Key Pressed" message to application. 5 * 6 * @param keys - keys that were pressed 7 * state - shifted 8 * 9 * @return status 10 *********************************************************************/ 11 uint8 OnBoard_SendKeys( uint8 keys, uint8 state ) 12 { 13 keyChange_t *msgPtr; 14 15 if ( registeredKeysTaskID != NO_TASK_ID ) 16 { 17 // Send the address to the task 18 msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) ); 19 if ( msgPtr ) 20 { 21 msgPtr->hdr.event = KEY_CHANGE; 22 msgPtr->state = state; 23 msgPtr->keys = keys; 24 25 osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr ); 26 } 27 return ( SUCCESS ); 28 } 29 else 30 return ( FAILURE ); 31 }
osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );
registeredKeysTaskID之前初始化注册ID我们的apptask,并且这个函数osal_msg_send会触发一个SYS_EVENT_MSG这样就到了前台
6,msg的各种结构:
1 static void simpleBLEPeripheral_ProcessOSALMsg( osal_event_hdr_t *pMsg ) 2 { 3 switch ( pMsg->event ) 4 { 5 #if defined( CC2540_MINIDK ) 6 case KEY_CHANGE: 7 simpleBLEPeripheral_HandleKeys( ((keyChange_t *)pMsg)->state, ((keyChange_t *)pMsg)->keys ); 8 break; 9 #endif // #if defined( CC2540_MINIDK ) 10 11 default: 12 // do nothing 13 break; 14 } 15 }
typedef struct
{
uint8 event;
uint8 status;
} osal_event_hdr_t;
到了key:
typedef struct
{
osal_event_hdr_t hdr;
uint8 state; // shift
uint8 keys; // keys
} keyChange_t;
最开始时候:
uint8 *pMsg;
if ( (pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )) != NULL )
{
simpleBLEPeripheral_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );
// Release the OSAL message
VOID osal_msg_deallocate( pMsg );
}
注意osal_msg_deallocate释放这样就算走完了一遍key
以及整个工程的流程了,花了两三天时间看完的,感谢谷雨资料