我是靠谱客的博主 内向书包,最近开发中收集的这篇文章主要介绍osal_msg_send,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述




uint8 osal_msg_send( uint8 destination_task, uint8 *msg_ptr )
{
  if ( msg_ptr == NULL )
    return ( INVALID_MSG_POINTER );

  if ( destination_task >= tasksCnt )
  {
    osal_msg_deallocate( msg_ptr );
    return ( INVALID_TASK );
  }

  // Check the message header
  if ( OSAL_MSG_NEXT( msg_ptr ) != NULL ||
       OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK )
  {
    osal_msg_deallocate( msg_ptr );
    return ( INVALID_MSG_POINTER );
  }

  OSAL_MSG_ID( msg_ptr ) = destination_task;给消息加上一个消息头

  // queue message
  osal_msg_enqueue( &osal_qHead, msg_ptr );消息加入消息队列

  // Signal the task that a message is waiting
  osal_set_event( destination_task, SYS_EVENT_MSG );给task任务发送一个系统消息SYS_EVENT_MSG ,通过osal_msg_receive接收SYS_EVENT_MSG ,在任务处理函数中再进行对应消息事件的任务处理

  return ( SUCCESS );
}


#define OSAL_MSG_ID(msg_ptr)      ((osal_msg_hdr_t *) (msg_ptr) - 1)->dest_id  减1的意思是向后移动一个消息头的长度

#define OSAL_MSG_NEXT(msg_ptr)      ((osal_msg_hdr_t *) (msg_ptr) - 1)->next


void osal_msg_enqueue( osal_msg_q_t *q_ptr, void *msg_ptr )
{
  void *list;
  halIntState_t intState;

  // Hold off interrupts
  HAL_ENTER_CRITICAL_SECTION(intState);

  OSAL_MSG_NEXT( msg_ptr ) = NULL;
  // If first message in queue
  if ( *q_ptr == NULL )如果消息队列是空的则直接添加消息
  {
    *q_ptr = msg_ptr;
  }
  else
  {
    // Find end of queue
    for ( list = *q_ptr; OSAL_MSG_NEXT( list ) != NULL; list = OSAL_MSG_NEXT( list ) );如果消息队列不是空的

      则将消息添加到消息尾部

    // Add message to end of queue
    OSAL_MSG_NEXT( list ) = msg_ptr;
  }

  // Re-enable interrupts
  HAL_EXIT_CRITICAL_SECTION(intState);使能中断
}


uint8 osal_set_event( uint8 task_id, uint16 event_flag )
{
  if ( task_id < tasksCnt )
  {
    halIntState_t   intState;
    HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts
    tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)设置任务对应的标志位
    HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts
    return ( SUCCESS );
  }
   else
  {
    return ( INVALID_TASK );
  }
}


发送Message,此OS做了两件事:

1,将此Message加入“消息队列”  :osal_msg_enqueue( &osal_qHead, msg_ptr );

2,设置系统消息事件,等待目标任务响应:osal_set_event( destination_task, SYS_EVENT_MSG );

但是为了了代码的可靠性,在此之前加入了判断目标任务ID以及Message的合法性的语句。

 

二,如何向SampleApp_ProcessEvent发送与接收消息?

简单示例:通过按键事件(即在处理所有按键事件的case下面),向SampleApp_ProcessEvent中发送自定义的LED闪烁的Message。

准备工作与步骤如下:

Message定义。

在ZComDef.h中定义了系统用到的Message的宏定义,如

#define  ZDO_STATE_CHANGE  0xD1

#define AF_INCOMING_MSG_CMD       0x1A

注意下面一条注释:

// OSAL System Message IDs/Events Reserved for applications (user applications)

// 0xE0 – 0xFC

所以应用程序定义的Message只能从0xE0 – 0xFC

因此:

1、在注释下面定一条Message 宏定义偏移量:

#define __MSG_OFFSET  0xE0        //避免自定的Marco与系统重复,所以加两条下划线。

2、如果自定的Message中只在SampleApp中使用,则在SampleApp.h中定义,否则应在ZComDef.h中

2.1在SampleApp.h中定义

#define MYMSG_LED_BLIND  __MSG_OFFSET+0x00

2.2自定义消息的格式结构体,用于消息的发送,以及携带数据,在定义的头文件在2.1节中

typedef struct{  osal_event_hdr_t hdr;  //事件头  uint8 state;    //闪烁次数} LedBlind_t;

3、在SampleApp_ProcessEvent函数中的switch ( MSGpkt->hdr.event )下添加一条case-break语句

switch ( MSGpkt->hdr.event )

...

case MYMSG_LED_BLIND :

  HalLedBlink( HAL_LED_1, ((LedBlind_t *)MSGpkt)->state, 50,1000 );  //LED1,闪烁次数((LedBlind_t *)MSGpkt)->state,每次占空比50%,周期1000ms

  break;

...

然后在case KEY_CHANGE:下添加一条发送MYMSG_LED_BLIND闪烁的Message,在发送消息前要定义一个消息指针,并且使用osal_msg_allocate为指针分配内存

...

case KEY_CHANGE:

   ...

    LedBlind_t *msgPtr;

    msgPtr = (LedBlind_t *)osal_msg_allocate( sizeof(LedBlind_t) );

    if(msgPtr)

    {

       msgPtr->hdr.event=MYMSG_LED_BLIND;//消息

       msgPtr->state=0x04;//闪烁次数 

       osal_msg_send(SampleApp_TaskID, (uint8 *)msgPtr );

    }

   ...

 

 以上代码只是演示消息的发送与接收,没有实用价值,因为可直接在按键部分加入HalLedBlink()函数,不用这么绕一大圈子



最后

以上就是内向书包为你收集整理的osal_msg_send的全部内容,希望文章能够帮你解决osal_msg_send所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(61)

评论列表共有 0 条评论

立即
投稿
返回
顶部