红叶何时落水
队列结构体
typedef struct QueueDefinition
{int8_t *pcHead; /*< Points to the beginning of the queue storage area. */int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */union /* Use of a union is an exception to the coding standard to ensure two mutually exclusive structure members don't appear simultaneously (wasting RAM). */{int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */} u;List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */#endif#if ( configUSE_QUEUE_SETS == 1 )struct QueueDefinition *pxQueueSetContainer;#endif#if ( configUSE_TRACE_FACILITY == 1 )UBaseType_t uxQueueNumber;uint8_t ucQueueType;#endif} xQUEUE;
pcHead -> 44
pcTail -> 48
pcWriteTo -> 44
pcReadFrom -> 47
xTasksWaitingToSend(入队阻塞列表)
xTasksWaitingToReceive(出队阻塞列表)
uxMessagesWaiting=0
uxLength=4
uxItemSize=32
cRxLock=queueUNLOCKED
cTxLock=queueUNLOCKED
其他成员变量
队列项目一(32字节)
队列项目二(32字节)
队列项目三(32字节)
队列项目四(32字节)
动态创建队列
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
{Queue_t *pxNewQueue;size_t xQueueSizeInBytes;uint8_t *pucQueueStorage;if( uxItemSize == ( UBaseType_t ) 0 )//队列大小为0{xQueueSizeInBytes = ( size_t ) 0;}else{xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*否则队列要分配一块空间lint !e961 MISRA exception as the casts are only redundant for some ports. */}pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );//占用的总空间等于结构体+储存体if( pxNewQueue != NULL ){pucQueueStorage = ( ( uint8_t * ) pxNewQueue ) + sizeof( Queue_t );//让该指针指向分配到的储存体地址以上内容为分配空间,下面的是初始化结构体prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue );//初始化队列}return pxNewQueue;//返回句柄,也就是结构体首地址
}
初始化队列prvInitialiseNewQueue
static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue )
{( void ) ucQueueType;if( uxItemSize == ( UBaseType_t ) 0 ){pxNewQueue->pcHead = ( int8_t * ) pxNewQueue;//pcHead不能为NULL,如果为NULL的话,代表他是一个mutex互斥}else{pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage;//指向储存体首地址}pxNewQueue->uxLength = uxQueueLength;//更新长度和大小pxNewQueue->uxItemSize = uxItemSize;( void ) xQueueGenericReset( pxNewQueue, pdTRUE );traceQUEUE_CREATE( pxNewQueue );
}
xQueueGenericReset
BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
{Queue_t * const pxQueue = ( Queue_t * ) xQueue;taskENTER_CRITICAL();{pxQueue->pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize );//pcTail指向储存体尾部pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U;pxQueue->pcWriteTo = pxQueue->pcHead;//一开始pcWriteTo指向头部pxQueue->u.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - ( UBaseType_t ) 1U ) * pxQueue->uxItemSize );pxQueue->cRxLock = queueUNLOCKED;pxQueue->cTxLock = queueUNLOCKED;if( xNewQueue == pdFALSE ){if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ){if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )//下一次复位该队列,代表着,该队列清空,那么之前因为队列满而阻塞的任务,要被释放{queueYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}else{mtCOVERAGE_TEST_MARKER();}}else{ //初始化时执行这里vListInitialise( &( pxQueue->xTasksWaitingToSend ) );vListInitialise( &( pxQueue->xTasksWaitingToReceive ) );}}taskEXIT_CRITICAL();return pdPASS;
}
xTaskRemoveFromEventList
BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
{TCB_t *pxUnblockedTCB;BaseType_t xReturn;pxUnblockedTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxEventList );//获取下一个要解除的任务的句柄( void ) uxListRemove( &( pxUnblockedTCB->xEventListItem ) );//将该任务的事件列表项移除if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )//如果调度器正常工作{( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );//移除状态列表项prvAddTaskToReadyList( pxUnblockedTCB );//添加到就绪列表中,同时,这意味着,堵塞不能嵌套}else{vListInsertEnd( &( xPendingReadyList ), &( pxUnblockedTCB->xEventListItem ) );//添加到xPendingReadyList,等到调度器开始工作后,再添加到就绪列表中}if( pxUnblockedTCB->uxPriority > pxCurrentTCB->uxPriority )//判断要不要切换任务{xReturn = pdTRUE;xYieldPending = pdTRUE;}else{xReturn = pdFALSE;}return xReturn;
}
发送信息到队列xQueueGenericSend
1.开启一个死循环 关中断
2.判断队列是否可以写入
2.true.1 复制队列中的信息prvCopyDataToQueue
2.true.1.1 获取当前队列uxMessagesWaiting值
2.true.1.2 判断是不是互斥队列 是的话xTaskPriorityDisinherit 优先级操作
不是的话判断是将信息插到哪里,是队头还是队尾
具体操作一致 memcpy-指针移动-判断队列满没满
2.true.1.2 uxMessagesWaiting++;
2.true.2 队列集相关操作
2.true.3 检查有没有任务正在堵塞,等待消息
2.true.3.true xTaskRemoveFromEventList释放该任务
2.false.1 队列满了的话,判断xTicksToWait是否要等待
xTicksToWait = 0; return 退出函数
xTicksToWait != 0
设置堵塞时间 vTaskSetTimeOutState 初始化时间结构体 记录当前的系统时钟节拍计数器的值 xTickCount 和溢出次数 xNumOfOverflows。
void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut )
{
pxTimeOut->xOverflowCount = xNumOfOverflows;
pxTimeOut->xTimeOnEntering = xTickCount;
}
3.挂起调度器 并且队列上锁prvLockQueue 这里主要是防止中断程序对该队列有操作
4.检查有没有任务溢出xTaskCheckForTimeOut
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ){BaseType_t xReturn;taskENTER_CRITICAL();{const TickType_t xConstTickCount = xTickCount;if( ( xNumOfOverflows != pxTimeOut->xOverflowCount ) && ( xConstTickCount >= pxTimeOut->xTimeOnEntering ) ) /*lint !e525 Indentation preferred as is to make code within pre-processor directives clearer. */{/* The tick count is greater than the time at whichvTaskSetTimeout() was called, but has also overflowed sincevTaskSetTimeOut() was called. It must have wrapped all the wayaround and gone past again. This passed since vTaskSetTimeout()was called. */xReturn = pdTRUE;}else if( ( ( TickType_t ) ( xConstTickCount - pxTimeOut->xTimeOnEntering ) ) < *pxTicksToWait ) /*lint !e961 Explicit casting is only redundant with some compilers, whereas others require it to prevent integer conversion errors. */{/* Not a genuine timeout. Adjust parameters for time remaining. */*pxTicksToWait -= ( xConstTickCount - pxTimeOut->xTimeOnEntering );vTaskSetTimeOutState( pxTimeOut );xReturn = pdFALSE;}else{xReturn = pdTRUE;}}taskEXIT_CRITICAL();return xReturn;}