TI BLE STACK

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 }
osalInitTasks

这个很关键,这个函数在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 };
tasksArr[]

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 }
osal_start_system

主要调用每个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 }
osal_run_system

先按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 }
SimpleBLEPeripheral_ProcessEvent

看到先执行: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 }
SimpleBLEPeripheral_Init

最后一句:

// 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_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR )
{
  halProcessKeyInterrupt();
 
………
}

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 }
void halProcessKeyInterrupt (void)

判断是否中断,中断清楚标志,最后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 }
HalKeyPoll()

前面是判断哪个被按下,最后一句很关键:

/* 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 }
OnBoard_KeyCallback

在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 }
OnBoard_SendKeys

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 }
simpleBLEPeripheral_ProcessOSALMsg

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

以及整个工程的流程了,花了两三天时间看完的,感谢谷雨资料

原文地址:https://www.cnblogs.com/wwjdwy/p/3625733.html