⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_q.c

📁 avr ucos 代码 测试环境:source insight WINAVR 4个进程
💻 C
📖 第 1 页 / 共 4 页
字号:
    BOOLEAN    tasks_waiting;
    OS_Q      *pq;


    if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
        *err = OS_ERR_DEL_ISR;                             /* ... can't DELETE from an ISR             */
        return ((OS_EVENT *)0);
    }//不能在中断服务程序中删除
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {                         /* Validate 'pevent'                        */
        *err = OS_ERR_PEVENT_NULL;
        return (pevent);//pevent不合理
    }
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {          /* Validate event block type                */
        *err = OS_ERR_EVENT_TYPE;
        return (pevent);//非法的事件块模式
    }
#endif
    OS_ENTER_CRITICAL();
    if (pevent->OSEventGrp != 0x00) {                      /* See if any tasks waiting on queue        */
		//如果有任务在队列中等待
        tasks_waiting = TRUE;                              /* Yes                                      */
    } else {
        tasks_waiting = FALSE;                             /* No                                       */
    }
    switch (opt) {
        case OS_DEL_NO_PEND:                               /* Delete queue only if no task waiting     */
			//如果只在无任务等待的情况下删除
             if (tasks_waiting == FALSE) {//无任务等待
                 pq                  = (OS_Q *)pevent->OSEventPtr;  /* Return OS_Q to free list        */
                 pq->OSQPtr          = OSQFreeList;
                 OSQFreeList         = pq;//将它加入了空闲链表
                 pevent->OSEventType = OS_EVENT_TYPE_UNUSED;//标记未用
                 pevent->OSEventPtr  = OSEventFreeList;    /* Return Event Control Block to free list  */
                 OSEventFreeList     = pevent; /* Get next free event control block        *///将事件控制块放入空闲链表中
                 OS_EXIT_CRITICAL();
                 *err = OS_NO_ERR;//无错
                 return ((OS_EVENT *)0);                   /* Queue has been deleted                   */
             } else {//有任务等待
                 OS_EXIT_CRITICAL();
                 *err = OS_ERR_TASK_WAITING;
                 return (pevent);
             }

        case OS_DEL_ALWAYS:                                /* Always delete the queue                  */
			//始终要删除队列
             while (pevent->OSEventGrp != 0x00) {          /* Ready ALL tasks waiting for queue        */
			 	//真有任务等待
                 OS_EventTaskRdy(pevent, (void *)0, OS_STAT_Q);//将挂起的任务就绪
             }
             pq                  = (OS_Q *)pevent->OSEventPtr;      /* Return OS_Q to free list        */
             pq->OSQPtr          = OSQFreeList;
             OSQFreeList         = pq;//同上,将队列控制块放入空闲链表
             pevent->OSEventType = OS_EVENT_TYPE_UNUSED;//标记为未用
             pevent->OSEventPtr  = OSEventFreeList;        /* Return Event Control Block to free list  */
             OSEventFreeList     = pevent;                 /* Get next free event control block        */
			 //将事件控制块放入空闲链表
             OS_EXIT_CRITICAL();
             if (tasks_waiting == TRUE) {                  /* Reschedule only if task(s) were waiting  */
                 OS_Sched();                               /* Find highest priority task ready to run  */
				 //因为新任务就绪,所以要重新调度
             }
             *err = OS_NO_ERR;
             return ((OS_EVENT *)0);                       /* Queue has been deleted                   */

        default://其它异常情况
             OS_EXIT_CRITICAL();
             *err = OS_ERR_INVALID_OPT;
             return (pevent);
    }
}
#endif

/*$PAGE*/
/*
*********************************************************************************************************
*                                           FLUSH QUEUE
*
* Description : This function is used to flush the contents of the message queue.
*
* Arguments   : none
*
* Returns     : OS_NO_ERR           upon success
*               OS_ERR_EVENT_TYPE   If you didn't pass a pointer to a queue
*               OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
                                                   清空消息队列
描述:清空消息队列中内容
参数:无
返回:
                 OS_NO_ERR          成功
*               OS_ERR_EVENT_TYPE   没有传递指针给队列
*               OS_ERR_PEVENT_NULL  如果'pevent' 是一个空指针

*********************************************************************************************************
*/

#if OS_Q_FLUSH_EN > 0
INT8U  OSQFlush (OS_EVENT *pevent)
{
#if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr;
#endif
    OS_Q      *pq;


#if OS_ARG_CHK_EN > 0//允许参数检验
    if (pevent == (OS_EVENT *)0) {                    /* Validate 'pevent'                             */
        return (OS_ERR_PEVENT_NULL);
    }//不合理的参数pevent
    if (pevent->OSEventType != OS_EVENT_TYPE_Q) {     /* Validate event block type                     */
        return (OS_ERR_EVENT_TYPE);
    }//不是事件块类型
#endif
    OS_ENTER_CRITICAL();
    pq             = (OS_Q *)pevent->OSEventPtr;      /* Point to queue storage structure              */
	//保存结构指针
    pq->OSQIn      = pq->OSQStart;
    pq->OSQOut     = pq->OSQStart;//将队列的插入指针IN和取出指针OUT复位
    pq->OSQEntries = 0;//初始化入口为零
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);
}
#endif

/*$PAGE*/
/*
*********************************************************************************************************
*                                     PEND ON A QUEUE FOR A MESSAGE
*
* Description: This function waits for a message to be sent to a queue
*
* Arguments  : pevent        is a pointer to the event control block associated with the desired queue
*
*              timeout       is an optional timeout period (in clock ticks).  If non-zero, your task will
*                            wait for a message to arrive at the queue up to the amount of time
*                            specified by this argument.  If you specify 0, however, your task will wait
*                            forever at the specified queue or, until a message arrives.
*
*              err           is a pointer to where an error message will be deposited.  Possible error
*                            messages are:
*
*                            OS_NO_ERR           The call was successful and your task received a
*                                                message.
*                            OS_TIMEOUT          A message was not received within the specified timeout
*                            OS_ERR_EVENT_TYPE   You didn't pass a pointer to a queue
*                            OS_ERR_PEVENT_NULL  If 'pevent' is a NULL pointer
*                            OS_ERR_PEND_ISR     If you called this function from an ISR and the result
*                                                would lead to a suspension.
*
* 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 a pointer to a queue.
                                                 等待消息队列中的消息
描述:等待消息中的队列
参数:pevent:指向事件控制块结合目标队列的指针
                timeout:超时时间选项(按时钟节拍来),如果非零,任务将按照此
                             参数的定时在队列中等待消息到来,如果设置为零,任务将在目标
                             队列中永远等待,直到消息到来。
                err:指向可能的错误消息的指针,可能为:
*                            OS_NO_ERR        调用成功,任务接收到消息
*                            OS_TIMEOUT         定时时间内消息没有来
*                            OS_ERR_EVENT_TYPE   你没有传递指针到队列
*                            OS_ERR_PEVENT_NULL  如果 'pevent' 是一个空指针
*                            OS_ERR_PEND_ISR    如果从ISR中调用,结果将出现异常              
*********************************************************************************************************
*/

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);//不能在ISR中挂起
    }
#if OS_ARG_CHK_EN > 0
    if (pevent == (OS_EVENT *)0) {               /* Validate 'pevent'                                  */
        *err = OS_ERR_PEVENT_NULL;
        return ((void *)0);//不合理的pevent
    }
    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                   */
//大于零,表示有消息可以用。此时,OSQPend得到事件控制块的.OSQOut域所指
//向的消息,将指向消息的指针复制到msg变量中,并让.OSQOut指针指向
//队列中的下个单元
        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;
        }//消息队列是一个循环缓冲区,如果超出了队列中最末一个单元,发生
        //这种越界时,就要将.OSQOut重新调整到指向队列的起始单元
        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  */
	//设置任务的TCB状态标志,以表明等待消息队列消息的任务被挂起
    OSTCBCur->OSTCBDly   = timeout;              /* Load timeout into TCB                              */
	//装载定时器到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();
    msg = OSTCBCur->OSTCBMsg;//任务调度后,任务会检查此函数是不是将消息放到了

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -