你的位置:首页 > 操作系统

[操作系统]OSAL的消息机制触发事件流程


定时器触发事件一般为程序内部触发,若外部触发事件,可以用系统消息触发,以按键触发为例。

在初始化时候,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 pressed12 13  *     state - shifted14 15  *16 17  * @return status18 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 task32 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  else55 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 buffer12 13  *  into which the task will encode the particular message it wishes14 15  *  to send. This common buffer scheme is used to strictly limit the16 17  *  creation of message buffers within the system due to RAM size18 19  *  limitations on the microprocessor.  Note that all message buffers20 21  *  are a fixed size (at least initially). The parameter len is kept22 23  *  in case a message pool with varying fixed message sizes is later24 25  *  created (for example, a pool of message buffers of size LARGE,26 27  *  MEDIUM and SMALL could be maintained and allocated based on request28 29  *  from the tasks).30 31  *32 33  *34 35  * @param  uint8 len - wanted buffer length36 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  else75 76   return ( NULL );77 78 }

 

 

其内存布局如下:

 

 

    申请成功后,返回值为keyChange_t部分的首地址,因此在随后的消息检查,填充等操作中会有结构体指针减一的操作。

 

消息创建完成后,调用osal_msg_send()将消息发送出去,该函数调用osal_msg_enqueue_push(),将消息发送至OSAL消息链表,并调用osal_set_event( destination_task, SYS_EVENT_MSG );向目标任务发送一个系统消息事件,在主循环中调用目标任务的回调函数,进入系统消息处理分支接收并解析处理消息。