OSAL的消息机制触发事件流程
0赞定时器触发事件一般为程序内部触发,若外部触发事件,可以用系统消息触发,以按键触发为例。
在初始化时候,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 );向目标任务发送一个系统消息事件,在主循环中调用目标任务的回调函数,进入系统消息处理分支接收并解析处理消息。

