定時器觸發事件一般為程序內部觸發,若外部觸發事件,可以用系統消息觸發,以按鍵觸發為例。
在初始化時候,InitBoard()中,注冊了按鍵回調函數
HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);
該函數中注冊按鍵回調函數到pHalKeyProcessFunction,並啟動定時器事件,ID為HAL層ID,事件為按鍵事件,調用HalKeyPoll(),啟動按鍵輪詢,等待按鍵觸發。
halProcessKeyInterrupt()通過HAL_ISR_FUNCTION()注冊到OSAL的中斷機制中,此部分代碼沒有公開,可能是底層按鍵觸發中斷,然后調用halProcessKeyInterrupt()上報事件,HalKeyPoll()中調用初始化時候注冊的按鍵回調函數(pHalKeyProcessFunction) ()進行處理;
在回調函數中,調用OnBoard_SendKeys()函數發送系統消息,消息結構如下
typedef struct
{
void *next;
uint16 len;
uint8 dest_id;
} osal_msg_hdr_t;
typedef struct
{
uint8 event;
uint8 status;
} osal_event_hdr_t;
typedef struct
{
osal_event_hdr_t hdr;
uint8 state;
uint8 keys;
} keyChange_t;
回調函數OnBoard_SendKeys()原型如下:
1 /********************************************************************* 2 3 * @fn OnBoard_SendKeys 4 5 * 6 7 * @brief Send "Key Pressed" message to application. 8 9 * 10 11 * @param keys - keys that were pressed 12 13 * state - shifted 14 15 * 16 17 * @return status 18 19 *********************************************************************/ 20 21 uint8 OnBoard_SendKeys( uint8 keys, uint8 state ) 22 23 { 24 25 keyChange_t *msgPtr; 26 27 if ( registeredKeysTaskID != NO_TASK_ID ) 28 29 { 30 31 // Send the address to the task 32 33 msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) ); 34 35 if ( msgPtr ) 36 37 { 38 39 msgPtr->hdr.event = KEY_CHANGE; 40 41 msgPtr->state = state; 42 43 msgPtr->keys = keys; 44 45 46 osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr ); 47 48 } 49 50 return ( SUCCESS ); 51 52 } 53 54 else 55 56 return ( FAILURE ); 57 58 }
在OnBoard_SendKeys()函數中,調用osal_msg_allocate()函數申請一塊內存,
1 /********************************************************************* 2 3 * @fn osal_msg_allocate 4 5 * 6 7 * @brief 8 9 * 10 11 * This function is called by a task to allocate a message buffer 12 13 * into which the task will encode the particular message it wishes 14 15 * to send. This common buffer scheme is used to strictly limit the 16 17 * creation of message buffers within the system due to RAM size 18 19 * limitations on the microprocessor. Note that all message buffers 20 21 * are a fixed size (at least initially). The parameter len is kept 22 23 * in case a message pool with varying fixed message sizes is later 24 25 * created (for example, a pool of message buffers of size LARGE, 26 27 * MEDIUM and SMALL could be maintained and allocated based on request 28 29 * from the tasks). 30 31 * 32 33 * 34 35 * @param uint8 len - wanted buffer length 36 37 * 38 39 * 40 41 * @return pointer to allocated buffer or NULL if allocation failed. 42 43 */ 44 45 uint8 * osal_msg_allocate( uint16 len ) 46 47 { 48 49 osal_msg_hdr_t *hdr; 50 51 52 if ( len == 0 ) 53 54 return ( NULL ); 55 56 57 58 hdr = (osal_msg_hdr_t *) osal_mem_alloc( (short)(len + sizeof( osal_msg_hdr_t )) ); 59 60 if ( hdr ) 61 62 { 63 64 hdr->next = NULL; 65 66 hdr->len = len; 67 68 hdr->dest_id = TASK_NO_TASK; 69 70 return ( (uint8 *) (hdr + 1) ); 71 72 } 73 74 else 75 76 return ( NULL ); 77 78 }
其內存布局如下:
申請成功后,返回值為keyChange_t部分的首地址,因此在隨后的消息檢查,填充等操作中會有結構體指針減一的操作。
消息創建完成后,調用osal_msg_send()將消息發送出去,該函數調用osal_msg_enqueue_push(),將消息發送至OSAL消息鏈表,並調用osal_set_event( destination_task, SYS_EVENT_MSG );向目標任務發送一個系統消息事件,在主循環中調用目標任務的回調函數,進入系統消息處理分支接收並解析處理消息。