Beispiel #1
0
void  *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
    OS_CPU_SR  cpu_sr;
#endif
    void      *msg;
    OS_Q      *pq;


    if (OSIntNesting > 0) {                      /* See if called from ISR ...                         */
        *err = OS_ERR_PEND_ISR;                  /* ... can't PEND from an ISR                         */
        return ((void *)0);
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {/* Validate event block type                          */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
#endif
    OS_ENTER_CRITICAL();
    pq = (OS_Q *)pevent->OSEventPtr;             /* Point at queue control block                       */
    if (pq->OSQEntries > 0) {                    /* See if any messages in the queue                   */
        msg = *pq->OSQOut++;                     /* Yes, extract oldest message from the queue         */
        pq->OSQEntries--;                        /* Update the number of entries in the queue          */
        if (pq->OSQOut == pq->OSQEnd) {          /* Wrap OUT pointer if we are at the end of the queue */
            pq->OSQOut = pq->OSQStart;
        }
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return (msg);                            /* Return message received                            */
    }
    OSTCBCur->OSTCBStat |= OS_STAT_Q;            /* Task will have to pend for a message to be posted  */
    OSTCBCur->OSTCBDly   = timeout;              /* Load timeout into 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();
    if (OSTCBCur->OSTCBStat & OS_STAT_Q) {       /* Was task readied because of a timeout?             */
        OS_EventTO(pevent);                      /* Yes                                                */
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                       /*     Indicate a timeout occured                     */
        return ((void *)0);                      /*     No message received                            */
    }
    msg                     = OSTCBCur->OSTCBMsg;/* No, Extract message from TCB (Put there by QPost)  */
    OSTCBCur->OSTCBMsg      = (void *)0;
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;     /*     No longer waiting for event                    */
    OS_EXIT_CRITICAL();
    *err                    = OS_NO_ERR;
    return (msg);                                /*     Return message received                        */
}
Beispiel #2
0
void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    void      *msg;
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
    if (err == (INT8U *)0) {                          /* Validate 'err'                                */
        return ((void *)0);
    }
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  /* Validate event block type                     */
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
        return ((void *)0);
    }
    OS_ENTER_CRITICAL();
    msg = pevent->OSEventPtr;
    if (msg != (void *)0) {                           /* See if there is already a message             */
        pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return (msg);                                 /* Return the message received (or NULL)         */
    }
    OSTCBCur->OSTCBStat  |= OS_STAT_MBOX;             /* Message not available, task will pend         */
    OSTCBCur->OSTCBPendTO = FALSE;
    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();
    if (OSTCBCur->OSTCBPendTO == TRUE) {              /* See if we were given the message              */
        OS_EventTO(pevent);                           /* Timed out, Make task ready                    */
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                            /* Indicate that a timeout occured               */
        return ((void *)0);                           /* Return a NULL message                         */
    }
    msg                     = OSTCBCur->OSTCBMsg;
    OSTCBCur->OSTCBMsg      = (void *)0;              /* Yes, clear message received                   */
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;          /* No longer waiting for event                   */
    OS_EXIT_CRITICAL();
    *err                    = OS_NO_ERR;
    return (msg);                                     /* Return the message received                   */
}
Beispiel #3
0
void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0;
#endif



#if OS_ARG_CHK_EN > 0
    if (err == (INT8U *)0) {                          /* Validate 'err'                                */
        return;
    }
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        *err = OS_ERR_PEVENT_NULL;
        return;
    }
#endif
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) {   /* Validate event block type                     */
        *err = OS_ERR_EVENT_TYPE;
        return;
    }
    if (OSIntNesting > 0) {                           /* See if called from ISR ...                    */
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
        return;
    }
    if (OSLockNesting > 0) {                          /* See if called with scheduler locked ...       */
        *err = OS_ERR_PEND_LOCKED;                    /* ... can't PEND when locked                    */
        return;
    }
    OS_ENTER_CRITICAL();
    if (pevent->OSEventCnt > 0) {                     /* If sem. is positive, resource available ...   */
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        return;
    }
                                                      /* Otherwise, must wait until event occurs       */
    OSTCBCur->OSTCBStat   |= OS_STAT_SEM;             /* Resource not available, pend on semaphore     */
    OSTCBCur->OSTCBPendTO  = OS_FALSE;
    OSTCBCur->OSTCBDly     = timeout;                 /* Store pend timeout in TCB                     */
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();
    OS_Sched();                                       /* Find next highest priority task ready         */
    OS_ENTER_CRITICAL();
    if (OSTCBCur->OSTCBPendTO == OS_TRUE) {           /* See if we timedout                            */
        OS_EventTO(pevent);
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                            /* Indicate that didn't get event within TO      */
        return;
    }
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
    OS_EXIT_CRITICAL();
    *err = OS_NO_ERR;
}
// 要求获得邮箱的消息
void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
    void      *msg;
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0;
#endif

#if OS_ARG_CHK_EN > 0
    if (err == (INT8U *)0) 							  /* Validate 'err'                                */
    {                          
        return ((void *)0);
    }
    if (pevent == (OS_EVENT *)0) 					  /* Validate 'pevent'                             */
    {                    
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);
    }
#endif
	// 事件类型是邮箱?
    if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) 	  /* Validate event block type                     */
    {  
        *err = OS_ERR_EVENT_TYPE;
        return ((void *)0);
    }
    // 中断处理里不允许挂起
    if (OSIntNesting > 0) 							  /* See if called from ISR ...                    */
    {                           
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
        return ((void *)0);
    }
    // 调度禁止时不允许挂起
    if (OSLockNesting > 0) 							  /* See if called with scheduler locked ...       */
    {                          
        *err = OS_ERR_PEND_LOCKED;                    /* ... can't PEND when locked                    */
        return ((void *)0);
    }
    
    OS_ENTER_CRITICAL();
    msg = pevent->OSEventPtr;
  	// 可获得邮箱消息?
    if (msg != (void *)0) 							  /* See if there is already a message             */
    {    
    	// 清空邮箱
        pevent->OSEventPtr = (void *)0;               /* Clear the mailbox                             */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        // 返回
        return (msg);                                 /* Return the message received (or NULL)         */
    }
    
    // 如果获取不到邮箱信息,任务会挂起
    // 更新任务状态标志
    OSTCBCur->OSTCBStat  |= OS_STAT_MBOX;             /* Message not available, task will pend         */
	// 延时等待最大时间未到
    OSTCBCur->OSTCBPendTO = OS_FALSE;
    // 设置延时等待最大时间
    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  */

    // 当邮箱有效或者等待时间到后,
    // 并且调用OSMboxPend()函数的任务再一次成为最高优先级任务,
    // 就会回到这里继续执行
    OS_ENTER_CRITICAL();
    // 延时等待最大时间到了?
    if (OSTCBCur->OSTCBPendTO == OS_TRUE)  			  /* See if we were given the message              */
    {          
    	// 由于等待超时而将任务置为就绪态。
        OS_EventTO(pevent);                           /* Timed out, Make task ready                    */
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                            /* Indicate that a timeout occured               */
        return ((void *)0);                           /* Return a NULL message                         */
    }
    // 邮箱可被获得:
    // 获得邮箱消息
    msg                     = OSTCBCur->OSTCBMsg;
	// 清空邮箱
    OSTCBCur->OSTCBMsg      = (void *)0;              /* Yes, clear message received                   */
	// 更新任务状态标志
    OSTCBCur->OSTCBStat     = OS_STAT_RDY;
	// 释放TCB里的ECB
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;          /* No longer waiting for event                   */
    OS_EXIT_CRITICAL();
    *err                    = OS_NO_ERR;
    return (msg);                                     /* Return the message received                   */
}
// 要求获得一个信号量
void  OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0;
#endif

#if OS_ARG_CHK_EN > 0
    if (err == (INT8U *)0)							  /* Validate 'err'                                */
    {                          
        return;
    }
    if (pevent == (OS_EVENT *)0)  					  /* Validate 'pevent'                             */
    {                   
        *err = OS_ERR_PEVENT_NULL;
        return;
    }
#endif
	// 确定事件类型是信号量
    if (pevent->OSEventType != OS_EVENT_TYPE_SEM) 	  /* Validate event block type                     */
    {   
        *err = OS_ERR_EVENT_TYPE;
        return;
    }
    // 中断处理里不允许挂起
    if (OSIntNesting > 0) 							  /* See if called from ISR ...                    */
    {                           
        *err = OS_ERR_PEND_ISR;                       /* ... can't PEND from an ISR                    */
        return;
    }
    
    // 调度禁止时不允许挂起
    if (OSLockNesting > 0) 							  /* See if called with scheduler locked ...       */
    {                          
        *err = OS_ERR_PEND_LOCKED;                    /* ... can't PEND when locked                    */
        return;
    }
    
    OS_ENTER_CRITICAL();
    // 如果信号量可用
    if (pevent->OSEventCnt > 0) 					  /* If sem. is positive, resource available ...   */
    {        
    	// 获得信号量,计数器减一,即可用的资源减少一份
        pevent->OSEventCnt--;                         /* ... decrement semaphore only if positive.     */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;
        // 返回
        return;
    }

    // 否则,等待信号量 	                          /* Otherwise, must wait until event occurs       */
    // 更新任务状态标志
    OSTCBCur->OSTCBStat   |= OS_STAT_SEM;             /* Resource not available, pend on semaphore     */
    // 延时等待最大时间未到
    OSTCBCur->OSTCBPendTO  = OS_FALSE;
	// 设置延时等待最大时间
    OSTCBCur->OSTCBDly     = timeout;                 /* Store pend timeout in TCB                     */
    // 将任务添加到事件控制块的等待任务表
    OS_EventTaskWait(pevent);                         /* Suspend task until event or timeout occurs    */
    OS_EXIT_CRITICAL();

	// 找出优先级最高的任务并进行任务切换
    OS_Sched();                                       /* Find next highest priority task ready         */

    // 当信号量有效或者等待时间到后,
    // 并且调用 OSSemPend()函数的任务再一次成为最高优先级任务,
    // 就会回到这里继续执行
    OS_ENTER_CRITICAL();
    // 是否延时等待最大时间到了?
    if (OSTCBCur->OSTCBPendTO == OS_TRUE) 			  /* See if we timedout                            */
    {           
	    // 由于等待超时而将任务置为就绪态。
        OS_EventTO(pevent);
        OS_EXIT_CRITICAL();
        *err = OS_TIMEOUT;                            /* Indicate that didn't get event within TO      */
        return;
    }

    // 释放TCB里的ECB
    OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;
    OS_EXIT_CRITICAL();
    *err = OS_NO_ERR;
}