【 uC/OS II 】uC/OS II 源代码阅读(os_mbox.c)消息邮箱
前言
关于消息邮箱,是一个消息邮箱里面,只能存储一条消息。核心结构体如下:
#if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u)
typedef struct os_event {INT8U OSEventType; /* Type of event control block (see OS_EVENT_TYPE_xxxx) */void *OSEventPtr; /* Pointer to message or queue structure */INT16U OSEventCnt; /* Semaphore Count (not used if other EVENT type) */OS_PRIO OSEventGrp; /* Group corresponding to tasks waiting for event to occur */OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE]; /* List of tasks waiting for event to occur */#if OS_EVENT_NAME_EN > 0uINT8U *OSEventName;
#endif
} OS_EVENT;
#endif
核心的操作字段有三个:消息(OSEventPtr)、等待组(OSEventGrp)、等待表(OSEventTbl)
/*消息邮箱(已看)
*********************************************************************************************************
* uC/OS-II
* The Real-Time Kernel
* MESSAGE MAILBOX MANAGEMENT
*
* (c) Copyright 1992-2017; Micrium, Inc.; Weston; FL
* All Rights Reserved
*
* File : OS_MBOX.C
* By : Jean J. Labrosse
* Version : V2.92.13
*
* LICENSING TERMS:
* ---------------
* uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
* If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license
* its use in your product. We provide ALL the source code for your convenience and to help you experience
* uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
* licensing fee.
*
* Knowledge of the source code may NOT be used to develop a similar product.
*
* Please help us continue to provide the embedded community with the finest software available.
* Your honesty is greatly appreciated.
*
* You can find our product's user manual, API reference, release notes and
* more information at https://doc.micrium.com.
* You can contact us at www.micrium.com.
*********************************************************************************************************
*/#define MICRIUM_SOURCE#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif//是否允许消息邮箱
#if OS_MBOX_EN > 0u
/*
*********************************************************************************************************
* ACCEPT MESSAGE FROM MAILBOX(无等待请求消息邮箱)
*
* Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(),
* OSMboxAccept() does not suspend the calling task if a message is not available.
*这个函数检查消息邮箱是否有可用消息,不像OSMboxPend(),OSMboxAccept()在消息无效的时候并不会挂起任务
* Arguments : pevent is a pointer to the event control block
*指向ECB的指针
* Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared
* so the next time OSMboxAccept() is called, the mailbox will be empty.
如果消息邮箱内的消息是有效的,消息邮箱就会被清空,这样的话,再次调用OSMboxAccept的时候,消息邮箱就是空的了
* == (void *)0 if the mailbox is empty or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass the proper event pointer.
*********************************************************************************************************
*///是否允许无等待请求消息邮箱
#if OS_MBOX_ACCEPT_EN > 0u
void *OSMboxAccept (OS_EVENT *pevent)
{void *pmsg;
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */return ((void *)0);}
#endif//检查ECB类型是否为OS_EVENT_TYPE_MBOXif (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */return ((void *)0);}OS_ENTER_CRITICAL();//关中断,进入临界区pmsg = pevent->OSEventPtr;//获取ECB中的消息//清空ECB中的消息pevent->OSEventPtr = (void *)0; /* Clear the mailbox */OS_EXIT_CRITICAL();//返回消息,这种操作相当于消费操作return (pmsg); /* Return the message received (or NULL) */
}
#endif/*
*********************************************************************************************************
* CREATE A MESSAGE MAILBOX(创建一个消息邮箱)
*
* Description: This function creates a message mailbox if free event control blocks are available.
*这个函数在ECB资源可用的情况下创建一个消息邮箱
* Arguments : pmsg is a pointer to a message that you wish to deposit in the mailbox. If
* you set this value to the NULL pointer (i.e. (void *)0) then the mailbox
* will be considered empty.
*pmsg是一个指向你希望放在邮箱中的消息的指针。如果你传入了一个空指针,那么这个邮箱将被视为空邮箱
* Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
* created mailbox
如果创建成功了,返回指向ECB邮箱的指针
* == (OS_EVENT *)0 if no event control blocks were available(如果没有ECB可用的情况下)
*********************************************************************************************************
*/OS_EVENT *OSMboxCreate (void *pmsg)
{OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}
#endif//ISR中不允许创建消息邮箱if (OSIntNesting > 0u) { /* See if called from ISR ... */return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */}OS_ENTER_CRITICAL();//关中断,进入临界区//从ECB空闲列表中取出一个空闲的ECBpevent = OSEventFreeList; /* Get next free event control block */if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;}OS_EXIT_CRITICAL();//退出临界区,开中断//对ECB进行初始化操作if (pevent != (OS_EVENT *)0) {pevent->OSEventType = OS_EVENT_TYPE_MBOX;pevent->OSEventCnt = 0u;pevent->OSEventPtr = pmsg; /* Deposit message in event control block */
#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";
#endif//初始化就绪组/表OS_EventWaitListInit(pevent);OS_TRACE_MBOX_CREATE(pevent, pevent->OSEventName);}return (pevent); /* Return pointer to event control block */
}/*
*********************************************************************************************************
* DELETE A MAIBOX(删除消息邮箱)
*
* Description: This function deletes a mailbox and readies all tasks pending on the mailbox.
*这个函数删除一个消息邮箱,并且将所有等待此消息邮箱的任务变为就绪状态
* Arguments : pevent is a pointer to the event control block associated with the desired
* mailbox.
*指向与消息邮箱有关的ECB的指针
* opt determines delete options as follows:
* opt == OS_DEL_NO_PEND Delete the mailbox ONLY if no task pending
* opt == OS_DEL_ALWAYS Deletes the mailbox even if tasks are waiting.
* In this case, all the tasks pending will be readied.
*
* perr is a pointer to an error code that can contain one of the following values:
* OS_ERR_NONE The call was successful and the mailbox was deleted
* OS_ERR_DEL_ISR If you attempted to delete the mailbox from an ISR
* OS_ERR_INVALID_OPT An invalid option was specified
* OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete a mailbox after safety
* critical operation started.
* OS_ERR_TASK_WAITING One or more tasks were waiting on the mailbox
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : pevent upon error(如果发生以上错误,就返回ECB的指针)
* (OS_EVENT *)0 if the mailbox was successfully deleted.(如果邮箱被正确删除,就返回0指针)
*
* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
* the mailbox MUST check the return code of OSMboxPend().
* 2) OSMboxAccept() callers will not know that the intended mailbox has been deleted!
* 3) This call can potentially disable interrupts for a long time. The interrupt disable
* time is directly proportional to the number of tasks waiting on the mailbox.
* 4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in
* applications where the mailbox is used for mutual exclusion because the resource(s)
* will no longer be guarded by the mailbox.
* 5) All tasks that were waiting for the mailbox will be readied and returned an
* OS_ERR_PEND_ABORT if OSMboxDel() was called with OS_DEL_ALWAYS
*********************************************************************************************************
*///是否允许消息邮箱的删除操作
#if OS_MBOX_DEL_EN > 0u
OS_EVENT *OSMboxDel (OS_EVENT *pevent,INT8U opt,INT8U *perr)
{BOOLEAN tasks_waiting;OS_EVENT *pevent_return;
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return ((OS_EVENT *)0);}
#endif#ifdef OS_SAFETY_CRITICAL_IEC61508if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();*perr = OS_ERR_ILLEGAL_DEL_RUN_TIME;return ((OS_EVENT *)0);}
#endif
//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */*perr = OS_ERR_PEVENT_NULL;return (pevent);}
#endifOS_TRACE_MBOX_DEL_ENTER(pevent, opt);//检查ECB的类型是否为消息邮箱if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */*perr = OS_ERR_EVENT_TYPE;OS_TRACE_MBOX_DEL_EXIT(*perr);return (pevent);}//ISR中不能删除消息邮箱if (OSIntNesting > 0u) { /* See if called from ISR ... */*perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */OS_TRACE_MBOX_DEL_EXIT(*perr);return (pevent);}OS_ENTER_CRITICAL();//关中断进入临界区//查看是否有任务在等待消息if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mailbox */tasks_waiting = OS_TRUE; /* Yes */} else {tasks_waiting = OS_FALSE; /* No */}//根据是否有任务在等待,来确定删除的方式switch (opt) {//只有在没有任务等待的情况下才可以删除case OS_DEL_NO_PEND: /* Delete mailbox only if no task waiting */if (tasks_waiting == OS_FALSE) {
#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";
#endifpevent->OSEventType = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */pevent->OSEventCnt = 0u;OSEventFreeList = pevent; /* Get next free event control block */OS_EXIT_CRITICAL();*perr = OS_ERR_NONE;pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */} else {OS_EXIT_CRITICAL();*perr = OS_ERR_TASK_WAITING;pevent_return = pevent;}break;//无论是否有任务等待都删除case OS_DEL_ALWAYS: /* Always delete the mailbox */while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox *///以等待被终止来唤醒任务,使任务变为就绪态(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);}
#if OS_EVENT_NAME_EN > 0upevent->OSEventName = (INT8U *)(void *)"?";
#endifpevent->OSEventType = OS_EVENT_TYPE_UNUSED;pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */pevent->OSEventCnt = 0u;OSEventFreeList = pevent; /* Get next free event control block */OS_EXIT_CRITICAL();//如果有任务在等待,则进行一次调度,if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */OS_Sched(); /* Find highest priority task ready to run */}*perr = OS_ERR_NONE;pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */break;default:OS_EXIT_CRITICAL();*perr = OS_ERR_INVALID_OPT;pevent_return = pevent;break;}OS_TRACE_MBOX_DEL_EXIT(*perr);return (pevent_return);
}
#endif/*
*********************************************************************************************************
* PEND ON MAILBOX FOR A MESSAGE(等待消息邮箱中的消息)
*
* Description: This function waits for a message to be sent to a mailbox
*这个函数实现等待消息邮箱接收一个消息
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*指向消息邮箱的ECB指针
* timeout is an optional timeout period (in clock ticks). If non-zero, your task will
* wait for a message to arrive at the mailbox up to the amount of time
* specified by this argument. If you specify 0, however, your task will wait
* forever at the specified mailbox or, until a message arrives.
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE The call was successful and your task received a
* message.
* OS_ERR_TIMEOUT A message was not received within the specified 'timeout'.
* OS_ERR_PEND_ABORT The wait on the mailbox was aborted.
* OS_ERR_EVENT_TYPE Invalid event type
* OS_ERR_PEND_ISR If you called this function from an ISR and the result
* would lead to a suspension.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
*
* Returns : != (void *)0 is a pointer to the message received
* == (void *)0 if no message was received or,
* if 'pevent' is a NULL pointer or,
* if you didn't pass the proper pointer to the event control block.
*********************************************************************************************************
*/void *OSMboxPend (OS_EVENT *pevent,INT32U timeout,INT8U *perr)
{void *pmsg;
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return ((void *)0);}
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */*perr = OS_ERR_PEVENT_NULL;return ((void *)0);}
#endifOS_TRACE_MBOX_PEND_ENTER(pevent, timeout);//检查ECB类型if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */*perr = OS_ERR_EVENT_TYPE;OS_TRACE_MBOX_PEND_EXIT(*perr);return ((void *)0);}//ISR禁止等待消息if (OSIntNesting > 0u) { /* See if called from ISR ... */*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */OS_TRACE_MBOX_PEND_EXIT(*perr);return ((void *)0);}//调度器上锁的情况下,禁止等待一个信号量,因为可能涉及到调度问题if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */OS_TRACE_MBOX_PEND_EXIT(*perr);return ((void *)0);}OS_ENTER_CRITICAL();//关中断,进入临界区//获取msgpmsg = pevent->OSEventPtr;//如果msg存在,则消耗msgif (pmsg != (void *)0) { /* See if there is already a message */pevent->OSEventPtr = (void *)0; /* Clear the mailbox */OS_EXIT_CRITICAL();*perr = OS_ERR_NONE;OS_TRACE_MBOX_PEND_EXIT(*perr);return (pmsg); /* Return the message received (or NULL) */}//如果msg不存在,则进行等待OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */OS_EXIT_CRITICAL();//任务挂起后,进行一次调度OS_Sched(); /* Find next highest priority task ready to run *///当等待结束,再次回到此函数执行的时候OS_ENTER_CRITICAL();//查看等待状态switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */case OS_STAT_PEND_OK://等待成功pmsg = OSTCBCur->OSTCBMsg;*perr = OS_ERR_NONE;break;case OS_STAT_PEND_ABORT://被迫中止等待pmsg = (void *)0;*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */break;case OS_STAT_PEND_TO://超时等待default:OS_EventTaskRemove(OSTCBCur, pevent);pmsg = (void *)0;*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */break;}//修整TCB信息OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
#if (OS_EVENT_MULTI_EN > 0u)OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
#endif//清空原有信息指针OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */OS_EXIT_CRITICAL();OS_TRACE_MBOX_PEND_EXIT(*perr);return (pmsg); /* Return received message */
}/*
*********************************************************************************************************
* ABORT WAITING ON A MESSAGE MAILBOX(中止等待一个消息邮箱的消息)
*
* Description: This function aborts & readies any tasks currently waiting on a mailbox. This function
* should be used to fault-abort the wait on the mailbox, rather than to normally signal
* the mailbox via OSMboxPost() or OSMboxPostOpt().
*这个函数中止等待所有目前等待此邮箱的任务,将他们变为就绪态,这个函数应该在任务因为故障中止等待邮箱时使用,而不是因为正常的使用OSMboxPost() or OSMboxPostOpt()来给消息邮箱一个消息,从而中止等待
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox.
*指向与消息邮箱相关的ECB的指针
* opt determines the type of ABORT performed:
* OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
* mailbox(只中止等待最高优先级的任务)
* OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
* mailbox(中止等待所有任务)
*
* perr is a pointer to where an error message will be deposited. Possible error
* messages are:
*
* OS_ERR_NONE No tasks were waiting on the mailbox.
* OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied
* and informed of the aborted wait; check return value
* for the number of tasks whose wait on the mailbox
* was aborted.
* OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
*
* Returns : == 0 if no tasks were waiting on the mailbox, or upon error.
* > 0 if one or more tasks waiting on the mailbox are now readied and informed.
*********************************************************************************************************
*///预编译,检查是否允许中止等待任务
#if OS_MBOX_PEND_ABORT_EN > 0u
INT8U OSMboxPendAbort (OS_EVENT *pevent,INT8U opt,INT8U *perr)
{INT8U nbr_tasks;//number of tasks
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif#ifdef OS_SAFETY_CRITICALif (perr == (INT8U *)0) {OS_SAFETY_CRITICAL_EXCEPTION();return (0u);}
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */*perr = OS_ERR_PEVENT_NULL;return (0u);}
#endif//检查ECB类型是否为消息邮箱if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */*perr = OS_ERR_EVENT_TYPE;return (0u);}OS_ENTER_CRITICAL();//关中断,进入临界区if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */nbr_tasks = 0u;//初始化nbr_tasks为0switch (opt) {//中止等待所有ECBcase OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);nbr_tasks++;}break;//中止等待最高优先级的ECBcase OS_PEND_OPT_NONE:default: /* No, ready HPT waiting on mailbox */(void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);nbr_tasks++;break;}OS_EXIT_CRITICAL();//因为有任务被唤醒了,进行一次调度OS_Sched(); /* Find HPT ready to run */*perr = OS_ERR_PEND_ABORT;return (nbr_tasks);}OS_EXIT_CRITICAL();*perr = OS_ERR_NONE;return (0u); /* No tasks waiting on mailbox */
}
#endif/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX(提交一个消息到消息邮箱)
*
* Description: This function sends a message to a mailbox
*这个函数提交一个消息到消息邮箱
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*指向与消息邮箱有关的ECB的指针
* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*指向提交的消息的指针,你不能传递一个空指针
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
* message at a time and thus, the message MUST be consumed before you
* are allowed to send another one.你一次只能提交一条消息,如果消息邮箱已经包含了一条消息,消息邮箱中的消息必须被消耗掉,你才能提交下一条消息
* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*
* Note(s) : 1) HPT means Highest Priority Task(HPT的意思时最高优先级的任务)
*********************************************************************************************************
*///检查是否允许提交消息到消息邮箱
#if OS_MBOX_POST_EN > 0u
INT8U OSMboxPost (OS_EVENT *pevent,void *pmsg)
{
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */return (OS_ERR_PEVENT_NULL);}if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */return (OS_ERR_POST_NULL_PTR);}
#endifOS_TRACE_MBOX_POST_ENTER(pevent);//检查ECB类型是否为消息邮箱if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */OS_TRACE_MBOX_POST_EXIT(OS_ERR_EVENT_TYPE);return (OS_ERR_EVENT_TYPE);}OS_ENTER_CRITICAL();//关中断,进入临界区//如果已经有任务在等待消息,则消息不进入邮箱,直接传递给TCB即可if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox *//* Ready HPT waiting on event */(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);OS_EXIT_CRITICAL();//有任务被唤醒,进行一次调度OS_Sched(); /* Find highest priority task ready to run */OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE);return (OS_ERR_NONE);}//如果没有人在等待消息,并且,消息邮箱是满的if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */OS_EXIT_CRITICAL();OS_TRACE_MBOX_POST_EXIT(OS_ERR_MBOX_FULL);return (OS_ERR_MBOX_FULL);}//如果没有任务在等待消息,并且邮箱是空的pevent->OSEventPtr = pmsg; /* Place message in mailbox */OS_EXIT_CRITICAL();OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE);return (OS_ERR_NONE);
}
#endif/*
*********************************************************************************************************
* POST MESSAGE TO A MAILBOX(提交一个消息到消息邮箱)
*
* Description: This function sends a message to a mailbox
*这个函数用来提交一条消息到消息邮箱
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*指向与消息邮箱有关的ECB的指针
* pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
*
* opt determines the type of POST performed:
* OS_POST_OPT_NONE POST to a single waiting task
* (Identical to OSMboxPost())提交消息到一个单一的等待任务上,(与OSMboxPost函数完全一样)
* OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the mailbox
*
* OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked
* //无调度提交消息
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
* message at a time and thus, the message MUST be consumed before you
* are allowed to send another one.
* OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
*
* Note(s) : 1) HPT means Highest Priority Task
*
* Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the
* interrupt disable time is proportional to the number of tasks waiting on the mailbox.
如果你选择了broadcast,那么中断可能被屏蔽很长一段时间,事实上,中断屏蔽时间与正在等待的任务数量成正比
*********************************************************************************************************
*///检查是否允许带参数的提交一个消息到邮箱
#if OS_MBOX_POST_OPT_EN > 0u
INT8U OSMboxPostOpt (OS_EVENT *pevent,void *pmsg,INT8U opt)//传入的opt是含有两层意思的,1. 唤醒方式 2. 唤醒后是否进行调度 以(INT8U)或的方式传入,以逐位&,获取指定参数
{
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */return (OS_ERR_PEVENT_NULL);}if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */return (OS_ERR_POST_NULL_PTR);}
#endifOS_TRACE_MBOX_POST_OPT_ENTER(pevent, opt);//检查ECB类型if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_EVENT_TYPE);return (OS_ERR_EVENT_TYPE);}OS_ENTER_CRITICAL();//关中断,进入临界区//当有任务在等待的时候if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox *///如果opt中是OS_POST_OPT_BROADCAST,那么就将这个消息发送给所有正在等待此邮箱的任务,并将所有任务就绪if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? *///以一条消息唤醒所有任务while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on mailbox */(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);}} else { /* No, Post to HPT waiting on mbox *///只唤醒目前最高的优先级的ECB(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);}OS_EXIT_CRITICAL();//唤醒后是否进行调度if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */OS_Sched(); /* Find HPT ready to run */}OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE);return (OS_ERR_NONE);}//如果没有任务在等待,并且消息邮箱是满的if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */OS_EXIT_CRITICAL();OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_MBOX_FULL);return (OS_ERR_MBOX_FULL);}//如果没有任务在等待,并且消息邮箱是空的,则将消息提交pevent->OSEventPtr = pmsg; /* Place message in mailbox */OS_EXIT_CRITICAL();OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE);return (OS_ERR_NONE);
}
#endif/*
*********************************************************************************************************
* QUERY A MESSAGE MAILBOX(查询消息邮箱)
*
* Description: This function obtains information about a message mailbox.
*这个函数可以用来获取消息邮箱中的消息
* Arguments : pevent is a pointer to the event control block associated with the desired mailbox
*指向与消息邮箱有关的ECB的指针
* p_mbox_data is a pointer to a structure that will contain information about the message
* mailbox.
*指向保存消息邮箱的内容的结构体的指针
* Returns : OS_ERR_NONE The call was successful and the message was sent
* OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mailbox.
* OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
* OS_ERR_PDATA_NULL If 'p_mbox_data' is a NULL pointer
*********************************************************************************************************
*///是否允许消息邮箱查询
#if OS_MBOX_QUERY_EN > 0u
INT8U OSMboxQuery (OS_EVENT *pevent,OS_MBOX_DATA *p_mbox_data)
{INT8U i;OS_PRIO *psrc;OS_PRIO *pdest;
#if OS_CRITICAL_METHOD == 3u/* Allocate storage for CPU status register */OS_CPU_SR cpu_sr = 0u;
#endif//参数检查
#if OS_ARG_CHK_EN > 0uif (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */return (OS_ERR_PEVENT_NULL);}if (p_mbox_data == (OS_MBOX_DATA *)0) { /* Validate 'p_mbox_data' */return (OS_ERR_PDATA_NULL);}
#endif//检查ECB的类型是否为消息邮箱if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */return (OS_ERR_EVENT_TYPE);}OS_ENTER_CRITICAL();//关中断。进入临界区//获取等待组表内容p_mbox_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */psrc = &pevent->OSEventTbl[0];pdest = &p_mbox_data->OSEventTbl[0];for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {*pdest++ = *psrc++;}//获取邮箱中的消息地址p_mbox_data->OSMsg = pevent->OSEventPtr; /* Get message from mailbox */OS_EXIT_CRITICAL();return (OS_ERR_NONE);
}
#endif /* OS_MBOX_QUERY_EN */
#endif /* OS_MBOX_EN */
【 uC/OS II 】uC/OS II 源代码阅读(os_mbox.c)消息邮箱相关推荐
- UC/OS II 消息邮箱
消息邮箱是uC/OS-II中的另一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量.通常该指针指向一个包含了"消息"的特定数据结构.如果该指针为空,说明 ...
- 主流手机OS与鸿蒙OS
主流手机OS与鸿蒙OS 对于一款手机而言,硬件是外在基础,手机系统才是一个手机的内在核心,是一家手机厂商的个性体现.现在大家熟知的的主流手机系统有iOS.Android以及WindowsPhone,其 ...
- python os.environ windows_python 获取系统环境变量 os.environ and os.putenv
从一段code说起 "if "BATCH_CONFIG_INI" in os.environ:" 判断环境变量的值有没有定义 如果定义的话就去环境变量的值,否则 ...
- Django源代码阅读分析-2:持久层结构分析
声明:本文为转载 Django对持久层的封装得很好,很好地支持Mysql.PostgreSQL.Oracle.SQLite3等流行的关系型数据库.顶层提供统一的模型封装,使用者基本无须关心真实数据库底 ...
- FPGA 之 SOPC 系列(六)Nios II 程序开发 II
FPGA 之 SOPC 系列(六)Nios II 程序开发 II 今天给大侠带来今天带来FPGA 之 SOPC 系列第六篇,Nios II 程序开发 II,希望对各位大侠的学习有参考价值,话不多说,上 ...
- python mkdir覆盖_python os.mkdir与 os.makedirs
1.mkdir( path [,mode] ) 作用:创建一个目录,可以是相对或者绝对路径,mode的默认模式是0777. 如果目录有多级,则创建最后一级.如果最后一级目录的上级目录有不存在的,则会抛 ...
- python os system用法_Python调用系统命令os.system()和os.popen()的实现
作为一门脚本语言,写脚本时执行系统命令可以说很常见了,python提供了相关的模块和方法. os模块提供了访问操作系统服务的功能,由于涉及到操作系统,它包含的内容比较多,这里只说system和pope ...
- XV6源代码阅读-中断与系统调用
XV6源代码阅读-中断与系统调用 Exercise1 源代码阅读 1.启动部分: bootasm.S bootmain.c 和xv6初始化模块:main.c bootasm.S 由16位和32位汇编混 ...
- 非常好!!!Linux源代码阅读——环境准备【转】
Linux源代码阅读--环境准备 转自:http://home.ustc.edu.cn/~boj/courses/linux_kernel/0_prepare.html 目录 Linux 系统环境准备 ...
最新文章
- css调整表格在屏幕上的位置
- Windows驱动开发学习笔记(七)—— 多核同步内核重载
- 人工智能之语音识别技术(二)
- 高等数学上-赵立军-北京大学出版社-题解-练习5.1
- L1-079 天梯赛的善良 (20 分)-PAT 团体程序设计天梯赛 GPLT
- 想要做音乐玩音乐,有这一个软件就够了!
- linux常用命令详解(二)
- 11-11 11:11
- 微电子计算机是信息技术的,信息技术说第三十五说,计算机微电子技术
- UZCMS镜像站群-v5.4旗舰版
- 浪曦_Struts2应用开发系列_第1讲.Struts2入门与配置--出现的问题笔记
- 计算机技术在材料成型工业中的应用,计算机在材料成型应用摘要.ppt
- EasyNVR网页/微信播放RTSP摄像机HLS/RTMP播放时出现起播等待问题的优化过程
- 肉蛋堡记 - 符皓冉
- 全志平台boot框架中增加设备驱动过程分析
- python中模块打补丁
- SKNet: Selective Kernel Networks
- 大数据培训课程哪家靠谱?和盈十五年资历做保证
- LaTeX不能识别eps文件?
- 电学基础知识整理(一)