queue.c 90 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433
  1. /*
  2. * FreeRTOS Kernel V10.5.1
  3. * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  4. *
  5. * SPDX-License-Identifier: MIT
  6. *
  7. */
  8. #include <stdlib.h>
  9. #include <string.h>
  10. /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
  11. * all the API functions to use the MPU wrappers. That should only be done when
  12. * task.h is included from an application file. */
  13. #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  14. #include "FreeRTOS.h"
  15. #include "task.h"
  16. #include "queue.h"
  17. /* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified
  18. * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
  19. * for the header files above, but not in this file, in order to generate the
  20. * correct privileged Vs unprivileged linkage and placement. */
  21. #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */
  22. /* Constants used with the cRxLock and cTxLock structure members. */
  23. #define queueUNLOCKED ( ( int8_t ) -1 )
  24. #define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 )
  25. #define queueINT8_MAX ( ( int8_t ) 127 )
  26. /* When the Queue_t structure is used to represent a base queue its pcHead and
  27. * pcTail members are used as pointers into the queue storage area. When the
  28. * Queue_t structure is used to represent a mutex pcHead and pcTail pointers are
  29. * not necessary, and the pcHead pointer is set to NULL to indicate that the
  30. * structure instead holds a pointer to the mutex holder (if any). Map alternative
  31. * names to the pcHead and structure member to ensure the readability of the code
  32. * is maintained. The QueuePointers_t and SemaphoreData_t types are used to form
  33. * a union as their usage is mutually exclusive dependent on what the queue is
  34. * being used for. */
  35. #define uxQueueType pcHead
  36. #define queueQUEUE_IS_MUTEX NULL
  37. typedef struct QueuePointers
  38. {
  39. int8_t * pcTail; /* 指向队列中存放消息的最后位置 */
  40. int8_t * pcReadFrom; /**/
  41. } QueuePointers_t;
  42. typedef struct SemaphoreData
  43. {
  44. TaskHandle_t xMutexHolder; /* 持有互斥锁的任务 */
  45. UBaseType_t uxRecursiveCallCount; /* 递归获取互斥锁的次数 */
  46. } SemaphoreData_t;
  47. /* Semaphores do not actually store or copy data, so have an item size of
  48. * zero. */
  49. #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ((UBaseType_t)0)
  50. #define queueMUTEX_GIVE_BLOCK_TIME ((TickType_t)0U)
  51. #if (configUSE_PREEMPTION == 0)
  52. /* If the cooperative scheduler is being used then a yield should not be
  53. * performed just because a higher priority task has been woken. */
  54. #define queueYIELD_IF_USING_PREEMPTION()
  55. #else
  56. #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
  57. #endif
  58. /*
  59. * Definition of the queue used by the scheduler.
  60. * 队列管理结构
  61. */
  62. typedef struct QueueDefinition
  63. {
  64. int8_t *pcHead; /* 队列中存放消息的位置 */
  65. int8_t *pcWriteTo; /* 下一个可存放消息的位置 */
  66. union
  67. {
  68. QueuePointers_t xQueue; /* 消息队列实现 */
  69. SemaphoreData_t xSemaphore; /* 信号量实现 */
  70. } u;
  71. List_t xTasksWaitingToSend; /* 等待发送任务列表,队列满导致像向消息队列发送的任务,都会阻塞加到该优先级链表上 */
  72. List_t xTasksWaitingToReceive; /* 等待接收任务列表,队列空导致像从消息队列读消息的任务,都会阻塞加到该优先级链表上 */
  73. volatile UBaseType_t uxMessagesWaiting; /* 当前队列中的消息数 */
  74. UBaseType_t uxLength; /* 队列的长度,其实是保存队列元素的个数 */
  75. UBaseType_t uxItemSize; /* 消息的长度 */
  76. volatile int8_t cRxLock; /* 队列接收锁 */
  77. volatile int8_t cTxLock; /* 队列发送锁 */
  78. #if (configUSE_QUEUE_SETS == 1)
  79. struct QueueDefinition *pxQueueSetContainer; /* 该队列所在的队列集合 */
  80. #endif
  81. #if (configUSE_TRACE_FACILITY == 1)
  82. UBaseType_t uxQueueNumber;
  83. uint8_t ucQueueType;
  84. #endif
  85. } xQUEUE;
  86. /**
  87. * The old xQUEUE name is maintained above then typedefed to the new Queue_t
  88. * name below to enable the use of older kernel aware debuggers.
  89. */
  90. typedef xQUEUE Queue_t;
  91. /*-----------------------------------------------------------*/
  92. /*
  93. * The queue registry is just a means for kernel aware debuggers to locate
  94. * queue structures. It has no other purpose so is an optional component.
  95. */
  96. #if (configQUEUE_REGISTRY_SIZE > 0)
  97. /* The type stored within the queue registry array. This allows a name
  98. * to be assigned to each queue making kernel aware debugging a little
  99. * more user friendly. */
  100. typedef struct QUEUE_REGISTRY_ITEM
  101. {
  102. const char * pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
  103. QueueHandle_t xHandle;
  104. } xQueueRegistryItem;
  105. /* The old xQueueRegistryItem name is maintained above then typedefed to the
  106. * new xQueueRegistryItem name below to enable the use of older kernel aware
  107. * debuggers. */
  108. typedef xQueueRegistryItem QueueRegistryItem_t;
  109. /* The queue registry is simply an array of QueueRegistryItem_t structures.
  110. * The pcQueueName member of a structure being NULL is indicative of the
  111. * array position being vacant. */
  112. PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ];
  113. #endif /* configQUEUE_REGISTRY_SIZE */
  114. /*
  115. * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not
  116. * prevent an ISR from adding or removing items to the queue, but does prevent
  117. * an ISR from removing tasks from the queue event lists. If an ISR finds a
  118. * queue is locked it will instead increment the appropriate queue lock count
  119. * to indicate that a task may require unblocking. When the queue in unlocked
  120. * these lock counts are inspected, and the appropriate action taken.
  121. */
  122. static void prvUnlockQueue(Queue_t *const pxQueue) PRIVILEGED_FUNCTION;
  123. /*
  124. * Uses a critical section to determine if there is any data in a queue.
  125. *
  126. * @return pdTRUE if the queue contains no items, otherwise pdFALSE.
  127. */
  128. static BaseType_t prvIsQueueEmpty(const Queue_t *pxQueue) PRIVILEGED_FUNCTION;
  129. /*
  130. * Uses a critical section to determine if there is any space in a queue.
  131. *
  132. * @return pdTRUE if there is no space, otherwise pdFALSE;
  133. */
  134. static BaseType_t prvIsQueueFull(const Queue_t *pxQueue) PRIVILEGED_FUNCTION;
  135. /*
  136. * Copies an item into the queue, either at the front of the queue or the
  137. * back of the queue.
  138. */
  139. static BaseType_t prvCopyDataToQueue(Queue_t *const pxQueue,
  140. const void *pvItemToQueue,
  141. const BaseType_t xPosition) PRIVILEGED_FUNCTION;
  142. /*
  143. * Copies an item out of a queue.
  144. */
  145. static void prvCopyDataFromQueue(Queue_t *const pxQueue,
  146. void *const pvBuffer) PRIVILEGED_FUNCTION;
  147. #if (configUSE_QUEUE_SETS == 1)
  148. /*
  149. * Checks to see if a queue is a member of a queue set, and if so, notifies
  150. * the queue set that the queue contains data.
  151. */
  152. static BaseType_t prvNotifyQueueSetContainer(const Queue_t *const pxQueue) PRIVILEGED_FUNCTION;
  153. #endif
  154. /*
  155. * Called after a Queue_t structure has been allocated either statically or
  156. * dynamically to fill in the structure's members.
  157. */
  158. static void prvInitialiseNewQueue(const UBaseType_t uxQueueLength,
  159. const UBaseType_t uxItemSize,
  160. uint8_t *pucQueueStorage,
  161. const uint8_t ucQueueType,
  162. Queue_t *pxNewQueue) PRIVILEGED_FUNCTION;
  163. /*
  164. * Mutexes are a special type of queue. When a mutex is created, first the
  165. * queue is created, then prvInitialiseMutex() is called to configure the queue
  166. * as a mutex.
  167. */
  168. #if ( configUSE_MUTEXES == 1 )
  169. static void prvInitialiseMutex(Queue_t * pxNewQueue) PRIVILEGED_FUNCTION;
  170. #endif
  171. #if (configUSE_MUTEXES == 1)
  172. /*
  173. * If a task waiting for a mutex causes the mutex holder to inherit a
  174. * priority, but the waiting task times out, then the holder should
  175. * disinherit the priority - but only down to the highest priority of any
  176. * other tasks that are waiting for the same mutex. This function returns
  177. * that priority.
  178. */
  179. static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION;
  180. #endif
  181. /*-----------------------------------------------------------*/
  182. /*
  183. * Macro to mark a queue as locked. Locking a queue prevents an ISR from
  184. * accessing the queue event lists.
  185. */
  186. #define prvLockQueue(pxQueue) \
  187. taskENTER_CRITICAL(); \
  188. { \
  189. if ((pxQueue)->cRxLock == queueUNLOCKED) \
  190. { \
  191. (pxQueue)->cRxLock = queueLOCKED_UNMODIFIED; \
  192. } \
  193. if ((pxQueue)->cTxLock == queueUNLOCKED) \
  194. { \
  195. (pxQueue)->cTxLock = queueLOCKED_UNMODIFIED; \
  196. } \
  197. } \
  198. taskEXIT_CRITICAL()
  199. /*
  200. * Macro to increment cTxLock member of the queue data structure. It is
  201. * capped at the number of tasks in the system as we cannot unblock more
  202. * tasks than the number of tasks in the system.
  203. */
  204. #define prvIncrementQueueTxLock( pxQueue, cTxLock ) \
  205. { \
  206. const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \
  207. if ( ( UBaseType_t ) ( cTxLock ) < uxNumberOfTasks ) \
  208. { \
  209. configASSERT( ( cTxLock ) != queueINT8_MAX ); \
  210. ( pxQueue )->cTxLock = ( int8_t ) ( ( cTxLock ) + ( int8_t ) 1 ); \
  211. } \
  212. }
  213. /*
  214. * Macro to increment cRxLock member of the queue data structure. It is
  215. * capped at the number of tasks in the system as we cannot unblock more
  216. * tasks than the number of tasks in the system.
  217. */
  218. #define prvIncrementQueueRxLock(pxQueue, cRxLock) \
  219. { \
  220. const UBaseType_t uxNumberOfTasks = uxTaskGetNumberOfTasks(); \
  221. if ((UBaseType_t) (cRxLock) < uxNumberOfTasks) \
  222. { \
  223. configASSERT((cRxLock) != queueINT8_MAX); \
  224. (pxQueue)->cRxLock = (int8_t) ((cRxLock) + (int8_t)1); \
  225. } \
  226. }
  227. BaseType_t xQueueGenericReset(QueueHandle_t xQueue, BaseType_t xNewQueue)
  228. {
  229. BaseType_t xReturn = pdPASS;
  230. Queue_t * const pxQueue = xQueue;
  231. configASSERT(pxQueue);
  232. if ((pxQueue != NULL) &&
  233. (pxQueue->uxLength >= 1U) &&
  234. /* Check for multiplication overflow. */
  235. ((SIZE_MAX / pxQueue->uxLength) >= pxQueue->uxItemSize))
  236. {
  237. taskENTER_CRITICAL();
  238. {
  239. pxQueue->u.xQueue.pcTail = pxQueue->pcHead + (pxQueue->uxLength * pxQueue->uxItemSize);
  240. pxQueue->uxMessagesWaiting = (UBaseType_t) 0U;
  241. /* 复位队列的存放消息的写位置和读位置 */
  242. pxQueue->pcWriteTo = pxQueue->pcHead;
  243. pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ((pxQueue->uxLength - 1U ) * pxQueue->uxItemSize);
  244. pxQueue->cRxLock = queueUNLOCKED;
  245. pxQueue->cTxLock = queueUNLOCKED;
  246. /* 是否为创建新队列 */
  247. if (xNewQueue == pdFALSE)
  248. {
  249. /* If there are tasks blocked waiting to read from the queue, then
  250. * the tasks will remain blocked as after this function exits the queue
  251. * will still be empty. If there are tasks blocked waiting to write to
  252. * the queue, then one should be unblocked as after this function exits
  253. * it will be possible to write to it. */
  254. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
  255. {
  256. /* 等待发送消息的任务,取消阻塞 */
  257. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
  258. {
  259. queueYIELD_IF_USING_PREEMPTION();
  260. }
  261. }
  262. }
  263. else
  264. {
  265. /**
  266. * Ensure the event queues start in the correct state.
  267. * 初始化新创建队列等待发送和接收链表
  268. */
  269. vListInitialise(&(pxQueue->xTasksWaitingToSend));
  270. vListInitialise(&(pxQueue->xTasksWaitingToReceive));
  271. }
  272. }
  273. taskEXIT_CRITICAL();
  274. }
  275. else
  276. {
  277. xReturn = pdFAIL;
  278. }
  279. configASSERT(xReturn != pdFAIL);
  280. /* A value is returned for calling semantic consistency with previous
  281. * versions.
  282. */
  283. return xReturn;
  284. }
  285. /**
  286. * xQueueGenericCreate: 创建队列
  287. * @uxQueueLength: 队列元素个数
  288. * @uxItemSize: 队列的元素的长度
  289. * @ucQueueType: 队列类型
  290. */
  291. QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength,
  292. const UBaseType_t uxItemSize,
  293. const uint8_t ucQueueType)
  294. {
  295. Queue_t *pxNewQueue = NULL;
  296. size_t xQueueSizeInBytes;
  297. uint8_t *pucQueueStorage;
  298. if ((uxQueueLength > (UBaseType_t)0) &&
  299. /* Check for multiplication overflow. */
  300. ((SIZE_MAX / uxQueueLength) >= uxItemSize) &&
  301. /* Check for addition overflow. */
  302. ((SIZE_MAX - sizeof(Queue_t)) >= (uxQueueLength * uxItemSize)))
  303. {
  304. /**
  305. * Allocate enough space to hold the maximum number of items that
  306. * can be in the queue at any time. It is valid for uxItemSize to be
  307. * zero in the case the queue is used as a semaphore.
  308. * 计算整个队列队列(管理结构和存放消息)的长度
  309. */
  310. xQueueSizeInBytes = (size_t)(uxQueueLength * uxItemSize);
  311. /**
  312. * Allocate the queue and storage area. Justification for MISRA
  313. * deviation as follows: pvPortMalloc() always ensures returned memory
  314. * blocks are aligned per the requirements of the MCU stack. In this case
  315. * pvPortMalloc() must return a pointer that is guaranteed to meet the
  316. * alignment requirements of the Queue_t structure - which in this case
  317. * is an int8_t *. Therefore, whenever the stack alignment requirements
  318. * are greater than or equal to the pointer to char requirements the cast
  319. * is safe. In other cases alignment requirements are not strict (one or
  320. * two bytes).
  321. */
  322. pxNewQueue = (Queue_t *)pvPortMalloc(sizeof(Queue_t) + xQueueSizeInBytes);
  323. if (pxNewQueue != NULL)
  324. {
  325. /**
  326. * Jump past the queue structure to find the location of the queue
  327. * storage area.
  328. * 队列存放消息的内存紧挨在Queue_t管理结构的后面
  329. */
  330. pucQueueStorage = (uint8_t *)pxNewQueue;
  331. pucQueueStorage += sizeof(Queue_t);
  332. prvInitialiseNewQueue(uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue);
  333. }
  334. else
  335. {
  336. traceQUEUE_CREATE_FAILED(ucQueueType);
  337. }
  338. }
  339. else
  340. {
  341. configASSERT( pxNewQueue );
  342. }
  343. return pxNewQueue;
  344. }
  345. /**
  346. * @uxQueueLength: 队列中元素个数
  347. * @uxItemSize: 队列元素的长度
  348. * @pucQueueStorage: 队列存放消息的起始位置
  349. * @ucQueueType: 队列的类型
  350. * @pxNewQueue: 队列管理结构
  351. */
  352. static void prvInitialiseNewQueue(const UBaseType_t uxQueueLength,
  353. const UBaseType_t uxItemSize,
  354. uint8_t * pucQueueStorage,
  355. const uint8_t ucQueueType,
  356. Queue_t * pxNewQueue)
  357. {
  358. /* Remove compiler warnings about unused parameters should
  359. * configUSE_TRACE_FACILITY not be set to 1. */
  360. (void)ucQueueType;
  361. /**
  362. * 如果队列元素的长度为0,说明队列中不需要存放消息
  363. * 比如二值信号量的队列元素大小就是0
  364. */
  365. if (uxItemSize == (UBaseType_t)0)
  366. {
  367. /**
  368. * No RAM was allocated for the queue storage area, but PC head cannot
  369. * be set to NULL because NULL is used as a key to say the queue is used as
  370. * a mutex. Therefore just set pcHead to point to the queue as a benign
  371. * value that is known to be within the memory map.
  372. */
  373. pxNewQueue->pcHead = (int8_t *)pxNewQueue;
  374. }
  375. else
  376. {
  377. /**
  378. * Set the head to the start of the queue storage area.
  379. * 设置队列中存放消息的位置指针
  380. */
  381. pxNewQueue->pcHead = (int8_t *)pucQueueStorage;
  382. }
  383. /**
  384. * Initialise the queue members as described where the queue type is
  385. * defined.
  386. * 设置队列元素个数和元素长度
  387. */
  388. pxNewQueue->uxLength = uxQueueLength;
  389. pxNewQueue->uxItemSize = uxItemSize;
  390. (void)xQueueGenericReset(pxNewQueue, pdTRUE);
  391. #if (configUSE_TRACE_FACILITY == 1)
  392. {
  393. pxNewQueue->ucQueueType = ucQueueType;
  394. }
  395. #endif /* configUSE_TRACE_FACILITY */
  396. #if (configUSE_QUEUE_SETS == 1)
  397. {
  398. pxNewQueue->pxQueueSetContainer = NULL;
  399. }
  400. #endif /* configUSE_QUEUE_SETS */
  401. traceQUEUE_CREATE(pxNewQueue);
  402. }
  403. #if (configUSE_MUTEXES == 1)
  404. static void prvInitialiseMutex(Queue_t * pxNewQueue)
  405. {
  406. if (pxNewQueue != NULL)
  407. {
  408. /* The queue create function will set all the queue structure members
  409. * correctly for a generic queue, but this function is creating a
  410. * mutex. Overwrite those members that need to be set differently -
  411. * in particular the information required for priority inheritance. */
  412. pxNewQueue->u.xSemaphore.xMutexHolder = NULL;
  413. pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX;
  414. /* In case this is a recursive mutex. */
  415. pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0;
  416. traceCREATE_MUTEX(pxNewQueue);
  417. /**
  418. * Start with the semaphore in the expected state.
  419. * 向互斥量队列发送一个消息,让互斥量处于空闲状态
  420. */
  421. (void)xQueueGenericSend(pxNewQueue, NULL, (TickType_t )0U, queueSEND_TO_BACK);
  422. }
  423. else
  424. {
  425. traceCREATE_MUTEX_FAILED();
  426. }
  427. }
  428. /**
  429. * 创建互斥量队列
  430. * @ucQueueType: 队列类型
  431. */
  432. QueueHandle_t xQueueCreateMutex(const uint8_t ucQueueType)
  433. {
  434. QueueHandle_t xNewQueue;
  435. const UBaseType_t uxMutexLength = (UBaseType_t)1;
  436. const UBaseType_t uxMutexSize = (UBaseType_t)0;
  437. xNewQueue = xQueueGenericCreate(uxMutexLength, uxMutexSize, ucQueueType);
  438. prvInitialiseMutex((Queue_t *)xNewQueue);
  439. return xNewQueue;
  440. }
  441. #endif /* configUSE_MUTEXES */
  442. #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
  443. TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore )
  444. {
  445. TaskHandle_t pxReturn;
  446. Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore;
  447. configASSERT( xSemaphore );
  448. /* This function is called by xSemaphoreGetMutexHolder(), and should not
  449. * be called directly. Note: This is a good way of determining if the
  450. * calling task is the mutex holder, but not a good way of determining the
  451. * identity of the mutex holder, as the holder may change between the
  452. * following critical section exiting and the function returning. */
  453. taskENTER_CRITICAL();
  454. {
  455. if ( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX )
  456. {
  457. pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder;
  458. }
  459. else
  460. {
  461. pxReturn = NULL;
  462. }
  463. }
  464. taskEXIT_CRITICAL();
  465. return pxReturn;
  466. } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
  467. TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore )
  468. {
  469. TaskHandle_t pxReturn;
  470. configASSERT( xSemaphore );
  471. /* Mutexes cannot be used in interrupt service routines, so the mutex
  472. * holder should not change in an ISR, and therefore a critical section is
  473. * not required here. */
  474. if ( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX )
  475. {
  476. pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder;
  477. }
  478. else
  479. {
  480. pxReturn = NULL;
  481. }
  482. return pxReturn;
  483. } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
  484. #endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */
  485. #if ( configUSE_RECURSIVE_MUTEXES == 1 )
  486. BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
  487. {
  488. BaseType_t xReturn;
  489. Queue_t * const pxMutex = ( Queue_t * ) xMutex;
  490. configASSERT( pxMutex );
  491. /* If this is the task that holds the mutex then xMutexHolder will not
  492. * change outside of this task. If this task does not hold the mutex then
  493. * pxMutexHolder can never coincidentally equal the tasks handle, and as
  494. * this is the only condition we are interested in it does not matter if
  495. * pxMutexHolder is accessed simultaneously by another task. Therefore no
  496. * mutual exclusion is required to test the pxMutexHolder variable. */
  497. if ( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
  498. {
  499. traceGIVE_MUTEX_RECURSIVE( pxMutex );
  500. /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to
  501. * the task handle, therefore no underflow check is required. Also,
  502. * uxRecursiveCallCount is only modified by the mutex holder, and as
  503. * there can only be one, no mutual exclusion is required to modify the
  504. * uxRecursiveCallCount member. */
  505. ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--;
  506. /* Has the recursive call count unwound to 0? */
  507. if ( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 )
  508. {
  509. /* Return the mutex. This will automatically unblock any other
  510. * task that might be waiting to access the mutex. */
  511. ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
  512. }
  513. xReturn = pdPASS;
  514. }
  515. else
  516. {
  517. /* The mutex cannot be given because the calling task is not the
  518. * holder. */
  519. xReturn = pdFAIL;
  520. traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
  521. }
  522. return xReturn;
  523. }
  524. BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex,
  525. TickType_t xTicksToWait )
  526. {
  527. BaseType_t xReturn;
  528. Queue_t * const pxMutex = ( Queue_t * ) xMutex;
  529. configASSERT( pxMutex );
  530. /* Comments regarding mutual exclusion as per those within
  531. * xQueueGiveMutexRecursive(). */
  532. traceTAKE_MUTEX_RECURSIVE( pxMutex );
  533. if ( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() )
  534. {
  535. ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
  536. xReturn = pdPASS;
  537. }
  538. else
  539. {
  540. xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait );
  541. /* pdPASS will only be returned if the mutex was successfully
  542. * obtained. The calling task may have entered the Blocked state
  543. * before reaching here. */
  544. if ( xReturn != pdFAIL )
  545. {
  546. ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++;
  547. }
  548. else
  549. {
  550. traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
  551. }
  552. }
  553. return xReturn;
  554. }
  555. #endif /* configUSE_RECURSIVE_MUTEXES */
  556. #if (configUSE_COUNTING_SEMAPHORES == 1)
  557. /**
  558. * @uxMaxCount: 最大计数值
  559. * @uxInitialCount: 初始计数值
  560. */
  561. QueueHandle_t xQueueCreateCountingSemaphore(const UBaseType_t uxMaxCount,
  562. const UBaseType_t uxInitialCount)
  563. {
  564. QueueHandle_t xHandle = NULL;
  565. if ((uxMaxCount != 0) &&
  566. (uxInitialCount <= uxMaxCount))
  567. {
  568. xHandle = xQueueGenericCreate(uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE);
  569. if (xHandle != NULL)
  570. {
  571. /* 初始计数信号量的个数 */
  572. ((Queue_t *)xHandle)->uxMessagesWaiting = uxInitialCount;
  573. traceCREATE_COUNTING_SEMAPHORE();
  574. }
  575. else
  576. {
  577. traceCREATE_COUNTING_SEMAPHORE_FAILED();
  578. }
  579. }
  580. else
  581. {
  582. configASSERT(xHandle);
  583. }
  584. return xHandle;
  585. }
  586. #endif
  587. /**
  588. * @pvItemToQueue: 消息
  589. * @xTicksToWait: 等待发送超时tick
  590. * @xCopyPosition: 消息存放的位置
  591. */
  592. BaseType_t xQueueGenericSend(QueueHandle_t xQueue,
  593. const void * const pvItemToQueue,
  594. TickType_t xTicksToWait,
  595. const BaseType_t xCopyPosition)
  596. {
  597. BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
  598. TimeOut_t xTimeOut;
  599. Queue_t * const pxQueue = xQueue;
  600. configASSERT(pxQueue);
  601. configASSERT(!((pvItemToQueue == NULL) && (pxQueue->uxItemSize != (UBaseType_t )0U)));
  602. configASSERT(!((xCopyPosition == queueOVERWRITE) && (pxQueue->uxLength != 1)));
  603. #if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1))
  604. {
  605. configASSERT(!((xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) && (xTicksToWait != 0)));
  606. }
  607. #endif
  608. for( ; ; )
  609. {
  610. taskENTER_CRITICAL();
  611. {
  612. /**
  613. * Is there room on the queue now? The running task must be the
  614. * highest priority task wanting to access the queue. If the head item
  615. * in the queue is to be overwritten then it does not matter if the
  616. * queue is full.
  617. * 判断队列是否有足够的空间,存放发送的消息
  618. */
  619. if ((pxQueue->uxMessagesWaiting < pxQueue->uxLength) || (xCopyPosition == queueOVERWRITE))
  620. {
  621. traceQUEUE_SEND(pxQueue);
  622. #if (configUSE_QUEUE_SETS == 1)
  623. {
  624. const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
  625. /* 拷贝消息到队列 */
  626. xYieldRequired = prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
  627. if (pxQueue->pxQueueSetContainer != NULL)
  628. {
  629. if ((xCopyPosition == queueOVERWRITE) && (uxPreviousMessagesWaiting != (UBaseType_t)0))
  630. {
  631. /* Do not notify the queue set as an existing item
  632. * was overwritten in the queue so the number of items
  633. * in the queue has not changed. */
  634. mtCOVERAGE_TEST_MARKER();
  635. }
  636. else if (prvNotifyQueueSetContainer(pxQueue) != pdFALSE)
  637. {
  638. /* The queue is a member of a queue set, and posting
  639. * to the queue set caused a higher priority task to
  640. * unblock. A context switch is required. */
  641. queueYIELD_IF_USING_PREEMPTION();
  642. }
  643. }
  644. else
  645. {
  646. /**
  647. * If there was a task waiting for data to arrive on the
  648. * queue then unblock it now.
  649. * 如果在队列上有接收任务阻塞等待消息
  650. */
  651. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  652. {
  653. /* 阻塞任务从队列中删除 */
  654. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  655. {
  656. /**
  657. * The unblocked task has a priority higher than
  658. * our own so yield immediately. Yes it is ok to
  659. * do this from within the critical section - the
  660. * kernel takes care of that.
  661. * 触发任务调度,阻塞等待的任务,将会被唤醒,从队列中读取元素
  662. */
  663. queueYIELD_IF_USING_PREEMPTION();
  664. }
  665. }
  666. else if (xYieldRequired != pdFALSE)
  667. {
  668. /**
  669. * This path is a special case that will only get
  670. * executed if the task was holding multiple mutexes
  671. * and the mutexes were given back in an order that is
  672. * different to that in which they were taken.
  673. * 主动触发抢占
  674. */
  675. queueYIELD_IF_USING_PREEMPTION();
  676. }
  677. }
  678. }
  679. #else /* configUSE_QUEUE_SETS */
  680. {
  681. xYieldRequired = prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
  682. /* If there was a task waiting for data to arrive on the
  683. * queue then unblock it now. */
  684. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  685. {
  686. if ( xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  687. {
  688. /* The unblocked task has a priority higher than
  689. * our own so yield immediately. Yes it is ok to do
  690. * this from within the critical section - the kernel
  691. * takes care of that. */
  692. queueYIELD_IF_USING_PREEMPTION();
  693. }
  694. }
  695. else if (xYieldRequired != pdFALSE)
  696. {
  697. /* This path is a special case that will only get
  698. * executed if the task was holding multiple mutexes and
  699. * the mutexes were given back in an order that is
  700. * different to that in which they were taken. */
  701. queueYIELD_IF_USING_PREEMPTION();
  702. }
  703. }
  704. #endif /* configUSE_QUEUE_SETS */
  705. taskEXIT_CRITICAL();
  706. /* 队列未满,发送消息成功,直接返回 */
  707. return pdPASS;
  708. }
  709. else /* 队列已满 */
  710. {
  711. /* 不阻塞等待 */
  712. if (xTicksToWait == (TickType_t)0)
  713. {
  714. /* The queue was full and no block time is specified (or
  715. * the block time has expired) so leave now. */
  716. taskEXIT_CRITICAL();
  717. /* Return to the original privilege level before exiting
  718. * the function.
  719. */
  720. traceQUEUE_SEND_FAILED(pxQueue);
  721. return errQUEUE_FULL;
  722. }
  723. else if (xEntryTimeSet == pdFALSE)
  724. {
  725. /* The queue was full and a block time was specified so
  726. * configure the timeout structure. */
  727. vTaskInternalSetTimeOutState(&xTimeOut);
  728. xEntryTimeSet = pdTRUE;
  729. }
  730. }
  731. }
  732. taskEXIT_CRITICAL();
  733. /* Interrupts and other tasks can send to and receive from the queue
  734. * now the critical section has been exited.
  735. * 发送失败,挂起调度
  736. */
  737. vTaskSuspendAll();
  738. /* 队列上锁 */
  739. prvLockQueue(pxQueue);
  740. /**
  741. * Update the timeout state to see if it has expired yet.
  742. * 检查是否已经超时等待发送设置的超时值
  743. */
  744. if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE)
  745. {
  746. /* 队列还未满 */
  747. if (prvIsQueueFull(pxQueue) != pdFALSE)
  748. {
  749. traceBLOCKING_ON_QUEUE_SEND(pxQueue);
  750. /* 队列还未满, 加入到等待发送的任务队列 */
  751. vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToSend), xTicksToWait);
  752. /* Unlocking the queue means queue events can effect the
  753. * event list. It is possible that interrupts occurring now
  754. * remove this task from the event list again - but as the
  755. * scheduler is suspended the task will go onto the pending
  756. * ready list instead of the actual ready list.
  757. * 队列解锁
  758. */
  759. prvUnlockQueue(pxQueue);
  760. /* Resuming the scheduler will move tasks from the pending
  761. * ready list into the ready list - so it is feasible that this
  762. * task is already in the ready list before it yields - in which
  763. * case the yield will not cause a context switch unless there
  764. * is also a higher priority task in the pending ready list. */
  765. if (xTaskResumeAll() == pdFALSE)
  766. {
  767. portYIELD_WITHIN_API();
  768. }
  769. }
  770. else
  771. {
  772. /* 队列已满, 但是未超过发送等待超时,继续尝试发送 */
  773. prvUnlockQueue(pxQueue);
  774. (void)xTaskResumeAll();
  775. }
  776. }
  777. else
  778. {
  779. /*
  780. * The timeout has expired.
  781. * 等待发送超时
  782. */
  783. prvUnlockQueue(pxQueue);
  784. (void)xTaskResumeAll();
  785. traceQUEUE_SEND_FAILED(pxQueue);
  786. return errQUEUE_FULL;
  787. }
  788. }
  789. }
  790. BaseType_t xQueueGenericSendFromISR(QueueHandle_t xQueue,
  791. const void * const pvItemToQueue,
  792. BaseType_t * const pxHigherPriorityTaskWoken,
  793. const BaseType_t xCopyPosition)
  794. {
  795. BaseType_t xReturn;
  796. UBaseType_t uxSavedInterruptStatus;
  797. Queue_t * const pxQueue = xQueue;
  798. configASSERT(pxQueue);
  799. configASSERT(!((pvItemToQueue == NULL) && (pxQueue->uxItemSize != (UBaseType_t)0U)));
  800. configASSERT(!((xCopyPosition == queueOVERWRITE) && (pxQueue->uxLength != 1)));
  801. /* RTOS ports that support interrupt nesting have the concept of a maximum
  802. * system call (or maximum API call) interrupt priority. Interrupts that are
  803. * above the maximum system call priority are kept permanently enabled, even
  804. * when the RTOS kernel is in a critical section, but cannot make any calls to
  805. * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
  806. * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
  807. * failure if a FreeRTOS API function is called from an interrupt that has been
  808. * assigned a priority above the configured maximum system call priority.
  809. * Only FreeRTOS functions that end in FromISR can be called from interrupts
  810. * that have been assigned a priority at or (logically) below the maximum
  811. * system call interrupt priority. FreeRTOS maintains a separate interrupt
  812. * safe API to ensure interrupt entry is as fast and as simple as possible.
  813. * More information (albeit Cortex-M specific) is provided on the following
  814. * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
  815. portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
  816. /* Similar to xQueueGenericSend, except without blocking if there is no room
  817. * in the queue. Also don't directly wake a task that was blocked on a queue
  818. * read, instead return a flag to say whether a context switch is required or
  819. * not (i.e. has a task with a higher priority than us been woken by this
  820. * post). */
  821. uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
  822. {
  823. if ((pxQueue->uxMessagesWaiting < pxQueue->uxLength) || (xCopyPosition == queueOVERWRITE))
  824. {
  825. const int8_t cTxLock = pxQueue->cTxLock;
  826. const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting;
  827. traceQUEUE_SEND_FROM_ISR(pxQueue);
  828. /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a
  829. * semaphore or mutex. That means prvCopyDataToQueue() cannot result
  830. * in a task disinheriting a priority and prvCopyDataToQueue() can be
  831. * called here even though the disinherit function does not check if
  832. * the scheduler is suspended before accessing the ready lists. */
  833. (void)prvCopyDataToQueue(pxQueue, pvItemToQueue, xCopyPosition);
  834. /* The event list is not altered if the queue is locked. This will
  835. * be done when the queue is unlocked later. */
  836. if (cTxLock == queueUNLOCKED)
  837. {
  838. #if (configUSE_QUEUE_SETS == 1)
  839. {
  840. if (pxQueue->pxQueueSetContainer != NULL)
  841. {
  842. if ((xCopyPosition == queueOVERWRITE) && (uxPreviousMessagesWaiting != (UBaseType_t)0))
  843. {
  844. /* Do not notify the queue set as an existing item
  845. * was overwritten in the queue so the number of items
  846. * in the queue has not changed. */
  847. mtCOVERAGE_TEST_MARKER();
  848. }
  849. else if (prvNotifyQueueSetContainer(pxQueue) != pdFALSE)
  850. {
  851. /* The queue is a member of a queue set, and posting
  852. * to the queue set caused a higher priority task to
  853. * unblock. A context switch is required. */
  854. if (pxHigherPriorityTaskWoken != NULL)
  855. {
  856. *pxHigherPriorityTaskWoken = pdTRUE;
  857. }
  858. }
  859. }
  860. else
  861. {
  862. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  863. {
  864. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  865. {
  866. /* The task waiting has a higher priority so
  867. * record that a context switch is required. */
  868. if (pxHigherPriorityTaskWoken != NULL)
  869. {
  870. *pxHigherPriorityTaskWoken = pdTRUE;
  871. }
  872. }
  873. }
  874. }
  875. }
  876. #else /* configUSE_QUEUE_SETS */
  877. {
  878. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  879. {
  880. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  881. {
  882. /* The task waiting has a higher priority so record that a
  883. * context switch is required. */
  884. if (pxHigherPriorityTaskWoken != NULL)
  885. {
  886. *pxHigherPriorityTaskWoken = pdTRUE;
  887. }
  888. }
  889. }
  890. /* Not used in this path. */
  891. (void) uxPreviousMessagesWaiting;
  892. }
  893. #endif /* configUSE_QUEUE_SETS */
  894. }
  895. else
  896. {
  897. /* Increment the lock count so the task that unlocks the queue
  898. * knows that data was posted while it was locked. */
  899. prvIncrementQueueTxLock(pxQueue, cTxLock);
  900. }
  901. xReturn = pdPASS;
  902. }
  903. else
  904. {
  905. traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue);
  906. xReturn = errQUEUE_FULL;
  907. }
  908. }
  909. portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
  910. return xReturn;
  911. }
  912. BaseType_t xQueueGiveFromISR(QueueHandle_t xQueue,
  913. BaseType_t * const pxHigherPriorityTaskWoken)
  914. {
  915. BaseType_t xReturn;
  916. UBaseType_t uxSavedInterruptStatus;
  917. Queue_t * const pxQueue = xQueue;
  918. /* Similar to xQueueGenericSendFromISR() but used with semaphores where the
  919. * item size is 0. Don't directly wake a task that was blocked on a queue
  920. * read, instead return a flag to say whether a context switch is required or
  921. * not (i.e. has a task with a higher priority than us been woken by this
  922. * post). */
  923. configASSERT(pxQueue);
  924. /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR()
  925. * if the item size is not 0. */
  926. configASSERT(pxQueue->uxItemSize == 0);
  927. /* Normally a mutex would not be given from an interrupt, especially if
  928. * there is a mutex holder, as priority inheritance makes no sense for an
  929. * interrupts, only tasks. */
  930. configASSERT(!((pxQueue->uxQueueType == queueQUEUE_IS_MUTEX) && (pxQueue->u.xSemaphore.xMutexHolder != NULL)));
  931. /* RTOS ports that support interrupt nesting have the concept of a maximum
  932. * system call (or maximum API call) interrupt priority. Interrupts that are
  933. * above the maximum system call priority are kept permanently enabled, even
  934. * when the RTOS kernel is in a critical section, but cannot make any calls to
  935. * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
  936. * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
  937. * failure if a FreeRTOS API function is called from an interrupt that has been
  938. * assigned a priority above the configured maximum system call priority.
  939. * Only FreeRTOS functions that end in FromISR can be called from interrupts
  940. * that have been assigned a priority at or (logically) below the maximum
  941. * system call interrupt priority. FreeRTOS maintains a separate interrupt
  942. * safe API to ensure interrupt entry is as fast and as simple as possible.
  943. * More information (albeit Cortex-M specific) is provided on the following
  944. * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
  945. portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
  946. uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
  947. {
  948. const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
  949. /* When the queue is used to implement a semaphore no data is ever
  950. * moved through the queue but it is still valid to see if the queue 'has
  951. * space'. */
  952. if (uxMessagesWaiting < pxQueue->uxLength)
  953. {
  954. const int8_t cTxLock = pxQueue->cTxLock;
  955. traceQUEUE_SEND_FROM_ISR(pxQueue);
  956. /* A task can only have an inherited priority if it is a mutex
  957. * holder - and if there is a mutex holder then the mutex cannot be
  958. * given from an ISR. As this is the ISR version of the function it
  959. * can be assumed there is no mutex holder and no need to determine if
  960. * priority disinheritance is needed. Simply increase the count of
  961. * messages (semaphores) available. */
  962. pxQueue->uxMessagesWaiting = uxMessagesWaiting + (UBaseType_t)1;
  963. /* The event list is not altered if the queue is locked. This will
  964. * be done when the queue is unlocked later. */
  965. if (cTxLock == queueUNLOCKED)
  966. {
  967. #if (configUSE_QUEUE_SETS == 1)
  968. {
  969. if (pxQueue->pxQueueSetContainer != NULL)
  970. {
  971. if (prvNotifyQueueSetContainer(pxQueue) != pdFALSE)
  972. {
  973. /* The semaphore is a member of a queue set, and
  974. * posting to the queue set caused a higher priority
  975. * task to unblock. A context switch is required. */
  976. if (pxHigherPriorityTaskWoken != NULL)
  977. {
  978. *pxHigherPriorityTaskWoken = pdTRUE;
  979. }
  980. }
  981. }
  982. else
  983. {
  984. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  985. {
  986. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  987. {
  988. /* The task waiting has a higher priority so
  989. * record that a context switch is required. */
  990. if (pxHigherPriorityTaskWoken != NULL)
  991. {
  992. *pxHigherPriorityTaskWoken = pdTRUE;
  993. }
  994. }
  995. }
  996. }
  997. }
  998. #else /* configUSE_QUEUE_SETS */
  999. {
  1000. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  1001. {
  1002. if (xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  1003. {
  1004. /* The task waiting has a higher priority so record that a
  1005. * context switch is required. */
  1006. if (pxHigherPriorityTaskWoken != NULL)
  1007. {
  1008. *pxHigherPriorityTaskWoken = pdTRUE;
  1009. }
  1010. }
  1011. }
  1012. }
  1013. #endif /* configUSE_QUEUE_SETS */
  1014. }
  1015. else
  1016. {
  1017. /* Increment the lock count so the task that unlocks the queue
  1018. * knows that data was posted while it was locked. */
  1019. prvIncrementQueueTxLock(pxQueue, cTxLock);
  1020. }
  1021. xReturn = pdPASS;
  1022. }
  1023. else
  1024. {
  1025. traceQUEUE_SEND_FROM_ISR_FAILED(pxQueue);
  1026. xReturn = errQUEUE_FULL;
  1027. }
  1028. }
  1029. portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
  1030. return xReturn;
  1031. }
  1032. /**
  1033. * 从队列中读消息
  1034. * @pvBuffer: 存放读到的消息缓存
  1035. */
  1036. BaseType_t xQueueReceive(QueueHandle_t xQueue, void * const pvBuffer,
  1037. TickType_t xTicksToWait)
  1038. {
  1039. BaseType_t xEntryTimeSet = pdFALSE;
  1040. TimeOut_t xTimeOut;
  1041. Queue_t * const pxQueue = xQueue;
  1042. /* Check the pointer is not NULL. */
  1043. configASSERT((pxQueue));
  1044. /* The buffer into which data is received can only be NULL if the data size
  1045. * is zero (so no data is copied into the buffer). */
  1046. configASSERT(!(((pvBuffer) == NULL) && ((pxQueue)->uxItemSize != (UBaseType_t) 0U)));
  1047. /* Cannot block if the scheduler is suspended. */
  1048. #if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1))
  1049. {
  1050. configASSERT(!((xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) && (xTicksToWait != 0)));
  1051. }
  1052. #endif
  1053. for( ; ; )
  1054. {
  1055. taskENTER_CRITICAL();
  1056. {
  1057. const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
  1058. /**
  1059. * Is there data in the queue now? To be running the calling task
  1060. * must be the highest priority task wanting to access the queue.
  1061. * 队列中存在消息
  1062. */
  1063. if (uxMessagesWaiting > (UBaseType_t)0)
  1064. {
  1065. /* Data available, remove one item. */
  1066. prvCopyDataFromQueue(pxQueue, pvBuffer);
  1067. traceQUEUE_RECEIVE(pxQueue);
  1068. /* 队列现存消息数减一 */
  1069. pxQueue->uxMessagesWaiting = uxMessagesWaiting - (UBaseType_t)1;
  1070. /**
  1071. * There is now space in the queue, were any tasks waiting to
  1072. * post to the queue? If so, unblock the highest priority waiting
  1073. * task.
  1074. * 入队等待队列不为空,说明之前的队列是满的,本次的读操作,会腾出来一个位置,将
  1075. * 可以唤醒一个等待入队的任务执行入队
  1076. */
  1077. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
  1078. {
  1079. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
  1080. {
  1081. queueYIELD_IF_USING_PREEMPTION();
  1082. }
  1083. }
  1084. taskEXIT_CRITICAL();
  1085. return pdPASS;
  1086. }
  1087. else
  1088. {
  1089. /* 队列中不存在消息, 任务不等待,直接返回 */
  1090. if (xTicksToWait == (TickType_t)0)
  1091. {
  1092. /* The queue was empty and no block time is specified (or
  1093. * the block time has expired) so leave now. */
  1094. taskEXIT_CRITICAL();
  1095. traceQUEUE_RECEIVE_FAILED(pxQueue);
  1096. return errQUEUE_EMPTY;
  1097. }
  1098. else if (xEntryTimeSet == pdFALSE)
  1099. {
  1100. /**
  1101. * The queue was empty and a block time was specified so
  1102. * configure the timeout structure.
  1103. */
  1104. vTaskInternalSetTimeOutState(&xTimeOut);
  1105. xEntryTimeSet = pdTRUE;
  1106. }
  1107. }
  1108. }
  1109. taskEXIT_CRITICAL();
  1110. /* Interrupts and other tasks can send to and receive from the queue
  1111. * now the critical section has been exited. */
  1112. vTaskSuspendAll();
  1113. prvLockQueue(pxQueue);
  1114. /**
  1115. * Update the timeout state to see if it has expired yet.
  1116. */
  1117. if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE)
  1118. {
  1119. /* The timeout has not expired. If the queue is still empty place
  1120. * the task on the list of tasks waiting to receive from the queue. */
  1121. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1122. {
  1123. traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue);
  1124. /* 当前任务加入到阻塞等待队列 */
  1125. vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToReceive), xTicksToWait);
  1126. prvUnlockQueue(pxQueue);
  1127. if (xTaskResumeAll() == pdFALSE)
  1128. {
  1129. portYIELD_WITHIN_API();
  1130. }
  1131. }
  1132. else
  1133. {
  1134. /**
  1135. * The queue contains data again. Loop back to try and read the
  1136. * data
  1137. */
  1138. prvUnlockQueue(pxQueue);
  1139. (void)xTaskResumeAll();
  1140. }
  1141. }
  1142. else
  1143. {
  1144. /* Timed out. If there is no data in the queue exit, otherwise loop
  1145. * back and attempt to read the data. */
  1146. prvUnlockQueue(pxQueue);
  1147. (void)xTaskResumeAll();
  1148. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1149. {
  1150. traceQUEUE_RECEIVE_FAILED(pxQueue);
  1151. return errQUEUE_EMPTY;
  1152. }
  1153. }
  1154. }
  1155. }
  1156. /**
  1157. * 获取信号量
  1158. * @xQueue: 消息队列
  1159. * @xTicksToWait: 超时时间
  1160. */
  1161. BaseType_t xQueueSemaphoreTake(QueueHandle_t xQueue, TickType_t xTicksToWait)
  1162. {
  1163. BaseType_t xEntryTimeSet = pdFALSE;
  1164. TimeOut_t xTimeOut;
  1165. Queue_t * const pxQueue = xQueue;
  1166. #if (configUSE_MUTEXES == 1)
  1167. BaseType_t xInheritanceOccurred = pdFALSE;
  1168. #endif
  1169. /* Check the queue pointer is not NULL. */
  1170. configASSERT((pxQueue));
  1171. /* Check this really is a semaphore, in which case the item size will be
  1172. * 0. */
  1173. configASSERT(pxQueue->uxItemSize == 0);
  1174. /* Cannot block if the scheduler is suspended. */
  1175. #if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1))
  1176. {
  1177. configASSERT(!((xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) && (xTicksToWait != 0)));
  1178. }
  1179. #endif
  1180. for( ; ; )
  1181. {
  1182. taskENTER_CRITICAL();
  1183. {
  1184. /* Semaphores are queues with an item size of 0, and where the
  1185. * number of messages in the queue is the semaphore's count value. */
  1186. const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting;
  1187. /**
  1188. * Is there data in the queue now? To be running the calling task
  1189. * must be the highest priority task wanting to access the queue.
  1190. * 消息队列存在信号量消息(信号量被释放),直接获取,任务不阻塞
  1191. */
  1192. if (uxSemaphoreCount > (UBaseType_t)0)
  1193. {
  1194. traceQUEUE_RECEIVE(pxQueue);
  1195. /* Semaphores are queues with a data size of zero and where the
  1196. * messages waiting is the semaphore's count. Reduce the count.
  1197. * 获取信号量
  1198. */
  1199. pxQueue->uxMessagesWaiting = uxSemaphoreCount - (UBaseType_t)1;
  1200. #if (configUSE_MUTEXES == 1)
  1201. {
  1202. if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX)
  1203. {
  1204. /**
  1205. * Record the information required to implement
  1206. * priority inheritance should it become necessary.
  1207. * 保存拿到互斥锁的任务结构体
  1208. */
  1209. pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount();
  1210. }
  1211. }
  1212. #endif /* configUSE_MUTEXES */
  1213. /**
  1214. * Check to see if other tasks are blocked waiting to give the
  1215. * semaphore, and if so, unblock the highest priority such task.
  1216. * 有任务在等待发送信号量
  1217. */
  1218. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
  1219. {
  1220. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
  1221. {
  1222. /* 触发任务调度 */
  1223. queueYIELD_IF_USING_PREEMPTION();
  1224. }
  1225. }
  1226. taskEXIT_CRITICAL();
  1227. return pdPASS;
  1228. }
  1229. else /* 消息队列为空,没有信号量消息进入队列 */
  1230. {
  1231. /* 不等待,直接返回 */
  1232. if (xTicksToWait == (TickType_t)0)
  1233. {
  1234. /* The semaphore count was 0 and no block time is specified
  1235. * (or the block time has expired) so exit now. */
  1236. taskEXIT_CRITICAL();
  1237. traceQUEUE_RECEIVE_FAILED(pxQueue);
  1238. return errQUEUE_EMPTY;
  1239. }
  1240. else if (xEntryTimeSet == pdFALSE)
  1241. {
  1242. /*
  1243. * The semaphore count was 0 and a block time was specified
  1244. * so configure the timeout structure ready to block.
  1245. * 保存开始阻塞的时间
  1246. */
  1247. vTaskInternalSetTimeOutState(&xTimeOut);
  1248. xEntryTimeSet = pdTRUE;
  1249. }
  1250. }
  1251. }
  1252. taskEXIT_CRITICAL();
  1253. /* Interrupts and other tasks can give to and take from the semaphore
  1254. * now the critical section has been exited. */
  1255. vTaskSuspendAll();
  1256. prvLockQueue(pxQueue);
  1257. /**
  1258. * Update the timeout state to see if it has expired yet.
  1259. * 检查等待是否超时
  1260. */
  1261. if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE)
  1262. {
  1263. /* A block time is specified and not expired. If the semaphore
  1264. * count is 0 then enter the Blocked state to wait for a semaphore to
  1265. * become available. As semaphores are implemented with queues the
  1266. * queue being empty is equivalent to the semaphore count being 0.
  1267. * 未超时
  1268. */
  1269. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1270. {
  1271. traceBLOCKING_ON_QUEUE_RECEIVE(pxQueue);
  1272. #if (configUSE_MUTEXES == 1)
  1273. {
  1274. if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX)
  1275. {
  1276. taskENTER_CRITICAL();
  1277. {
  1278. xInheritanceOccurred = xTaskPriorityInherit(pxQueue->u.xSemaphore.xMutexHolder);
  1279. }
  1280. taskEXIT_CRITICAL();
  1281. }
  1282. }
  1283. #endif /* if ( configUSE_MUTEXES == 1 ) */
  1284. /* 当前任务被挂到xTasksWaitingToReceive事件队列 */
  1285. vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToReceive), xTicksToWait);
  1286. prvUnlockQueue(pxQueue);
  1287. if (xTaskResumeAll() == pdFALSE)
  1288. {
  1289. /* 触发任务调度 */
  1290. portYIELD_WITHIN_API();
  1291. }
  1292. }
  1293. else
  1294. {
  1295. /* There was no timeout and the semaphore count was not 0, so
  1296. * attempt to take the semaphore again. */
  1297. prvUnlockQueue(pxQueue);
  1298. (void) xTaskResumeAll();
  1299. }
  1300. }
  1301. else
  1302. {
  1303. /* 等待超时 */
  1304. prvUnlockQueue(pxQueue);
  1305. (void) xTaskResumeAll();
  1306. /* If the semaphore count is 0 exit now as the timeout has
  1307. * expired. Otherwise return to attempt to take the semaphore that is
  1308. * known to be available. As semaphores are implemented by queues the
  1309. * queue being empty is equivalent to the semaphore count being 0.
  1310. * 队列为空, 消息队列中没有信号量消息
  1311. */
  1312. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1313. {
  1314. #if (configUSE_MUTEXES == 1)
  1315. {
  1316. /* xInheritanceOccurred could only have be set if
  1317. * pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to
  1318. * test the mutex type again to check it is actually a mutex.
  1319. * 出现优先级继承
  1320. */
  1321. if (xInheritanceOccurred != pdFALSE)
  1322. {
  1323. taskENTER_CRITICAL();
  1324. {
  1325. UBaseType_t uxHighestWaitingPriority;
  1326. /* This task blocking on the mutex caused another
  1327. * task to inherit this task's priority. Now this task
  1328. * has timed out the priority should be disinherited
  1329. * again, but only as low as the next highest priority
  1330. * task that is waiting for the same mutex.
  1331. * 获得等待互斥锁任务中,最高的优先级
  1332. */
  1333. uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout(pxQueue);
  1334. vTaskPriorityDisinheritAfterTimeout(pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority);
  1335. }
  1336. taskEXIT_CRITICAL();
  1337. }
  1338. }
  1339. #endif /* configUSE_MUTEXES */
  1340. traceQUEUE_RECEIVE_FAILED(pxQueue);
  1341. return errQUEUE_EMPTY;
  1342. }
  1343. }
  1344. }
  1345. }
  1346. /**
  1347. * 从队列中拷贝消息,但是消息不会出队
  1348. */
  1349. BaseType_t xQueuePeek(QueueHandle_t xQueue, void * const pvBuffer,
  1350. TickType_t xTicksToWait)
  1351. {
  1352. BaseType_t xEntryTimeSet = pdFALSE;
  1353. TimeOut_t xTimeOut;
  1354. int8_t * pcOriginalReadPosition;
  1355. Queue_t * const pxQueue = xQueue;
  1356. /* Check the pointer is not NULL. */
  1357. configASSERT((pxQueue));
  1358. /* The buffer into which data is received can only be NULL if the data size
  1359. * is zero (so no data is copied into the buffer. */
  1360. configASSERT(!(((pvBuffer) == NULL) && ((pxQueue)->uxItemSize != (UBaseType_t) 0U)));
  1361. /* Cannot block if the scheduler is suspended. */
  1362. #if ((INCLUDE_xTaskGetSchedulerState == 1) || (configUSE_TIMERS == 1))
  1363. {
  1364. configASSERT(!((xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED) && (xTicksToWait != 0)));
  1365. }
  1366. #endif
  1367. /*lint -save -e904 This function relaxes the coding standard somewhat to
  1368. * allow return statements within the function itself. This is done in the
  1369. * interest of execution time efficiency. */
  1370. for( ; ; )
  1371. {
  1372. taskENTER_CRITICAL();
  1373. {
  1374. const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
  1375. /* Is there data in the queue now? To be running the calling task
  1376. * must be the highest priority task wanting to access the queue. */
  1377. if (uxMessagesWaiting > (UBaseType_t)0)
  1378. {
  1379. /* Remember the read position so it can be reset after the data
  1380. * is read from the queue as this function is only peeking the
  1381. * data, not removing it.
  1382. * 找到读数据的位置
  1383. */
  1384. pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
  1385. prvCopyDataFromQueue(pxQueue, pvBuffer);
  1386. traceQUEUE_PEEK(pxQueue);
  1387. /**
  1388. * The data is not being removed, so reset the read pointer.
  1389. * 读完数据后,恢复原来的读位置
  1390. */
  1391. pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
  1392. /* The data is being left in the queue, so see if there are
  1393. * any other tasks waiting for the data. */
  1394. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  1395. {
  1396. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  1397. {
  1398. /* The task waiting has a higher priority than this task. */
  1399. queueYIELD_IF_USING_PREEMPTION();
  1400. }
  1401. }
  1402. taskEXIT_CRITICAL();
  1403. return pdPASS;
  1404. }
  1405. else
  1406. {
  1407. if (xTicksToWait == (TickType_t)0)
  1408. {
  1409. /* The queue was empty and no block time is specified (or
  1410. * the block time has expired) so leave now. */
  1411. taskEXIT_CRITICAL();
  1412. traceQUEUE_PEEK_FAILED(pxQueue);
  1413. return errQUEUE_EMPTY;
  1414. }
  1415. else if (xEntryTimeSet == pdFALSE)
  1416. {
  1417. /* The queue was empty and a block time was specified so
  1418. * configure the timeout structure ready to enter the blocked
  1419. * state. */
  1420. vTaskInternalSetTimeOutState(&xTimeOut);
  1421. xEntryTimeSet = pdTRUE;
  1422. }
  1423. }
  1424. }
  1425. taskEXIT_CRITICAL();
  1426. /* Interrupts and other tasks can send to and receive from the queue
  1427. * now that the critical section has been exited. */
  1428. vTaskSuspendAll();
  1429. prvLockQueue(pxQueue);
  1430. /**
  1431. * Update the timeout state to see if it has expired yet.
  1432. * 等待超时
  1433. */
  1434. if (xTaskCheckForTimeOut(&xTimeOut, &xTicksToWait) == pdFALSE)
  1435. {
  1436. /* Timeout has not expired yet, check to see if there is data in the
  1437. * queue now, and if not enter the Blocked state to wait for data. */
  1438. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1439. {
  1440. traceBLOCKING_ON_QUEUE_PEEK(pxQueue);
  1441. vTaskPlaceOnEventList(&(pxQueue->xTasksWaitingToReceive), xTicksToWait);
  1442. prvUnlockQueue(pxQueue);
  1443. if (xTaskResumeAll() == pdFALSE)
  1444. {
  1445. portYIELD_WITHIN_API();
  1446. }
  1447. }
  1448. else
  1449. {
  1450. /* There is data in the queue now, so don't enter the blocked
  1451. * state, instead return to try and obtain the data. */
  1452. prvUnlockQueue(pxQueue);
  1453. (void) xTaskResumeAll();
  1454. }
  1455. }
  1456. else
  1457. {
  1458. /* The timeout has expired. If there is still no data in the queue
  1459. * exit, otherwise go back and try to read the data again. */
  1460. prvUnlockQueue(pxQueue);
  1461. (void) xTaskResumeAll();
  1462. if (prvIsQueueEmpty(pxQueue) != pdFALSE)
  1463. {
  1464. traceQUEUE_PEEK_FAILED(pxQueue);
  1465. return errQUEUE_EMPTY;
  1466. }
  1467. }
  1468. }
  1469. }
  1470. BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,
  1471. void * const pvBuffer,
  1472. BaseType_t * const pxHigherPriorityTaskWoken)
  1473. {
  1474. BaseType_t xReturn;
  1475. UBaseType_t uxSavedInterruptStatus;
  1476. Queue_t * const pxQueue = xQueue;
  1477. configASSERT(pxQueue);
  1478. configASSERT(!((pvBuffer == NULL) && (pxQueue->uxItemSize != (UBaseType_t)0U)));
  1479. /* RTOS ports that support interrupt nesting have the concept of a maximum
  1480. * system call (or maximum API call) interrupt priority. Interrupts that are
  1481. * above the maximum system call priority are kept permanently enabled, even
  1482. * when the RTOS kernel is in a critical section, but cannot make any calls to
  1483. * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
  1484. * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
  1485. * failure if a FreeRTOS API function is called from an interrupt that has been
  1486. * assigned a priority above the configured maximum system call priority.
  1487. * Only FreeRTOS functions that end in FromISR can be called from interrupts
  1488. * that have been assigned a priority at or (logically) below the maximum
  1489. * system call interrupt priority. FreeRTOS maintains a separate interrupt
  1490. * safe API to ensure interrupt entry is as fast and as simple as possible.
  1491. * More information (albeit Cortex-M specific) is provided on the following
  1492. * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
  1493. portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
  1494. uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
  1495. {
  1496. const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
  1497. /* Cannot block in an ISR, so check there is data available. */
  1498. if (uxMessagesWaiting > (UBaseType_t)0)
  1499. {
  1500. const int8_t cRxLock = pxQueue->cRxLock;
  1501. traceQUEUE_RECEIVE_FROM_ISR(pxQueue);
  1502. prvCopyDataFromQueue(pxQueue, pvBuffer);
  1503. pxQueue->uxMessagesWaiting = uxMessagesWaiting - (UBaseType_t)1;
  1504. /* If the queue is locked the event list will not be modified.
  1505. * Instead update the lock count so the task that unlocks the queue
  1506. * will know that an ISR has removed data while the queue was
  1507. * locked. */
  1508. if (cRxLock == queueUNLOCKED)
  1509. {
  1510. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
  1511. {
  1512. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
  1513. {
  1514. /* The task waiting has a higher priority than us so
  1515. * force a context switch. */
  1516. if (pxHigherPriorityTaskWoken != NULL)
  1517. {
  1518. *pxHigherPriorityTaskWoken = pdTRUE;
  1519. }
  1520. }
  1521. }
  1522. }
  1523. else
  1524. {
  1525. /* Increment the lock count so the task that unlocks the queue
  1526. * knows that data was removed while it was locked. */
  1527. prvIncrementQueueRxLock(pxQueue, cRxLock);
  1528. }
  1529. xReturn = pdPASS;
  1530. }
  1531. else
  1532. {
  1533. xReturn = pdFAIL;
  1534. traceQUEUE_RECEIVE_FROM_ISR_FAILED(pxQueue);
  1535. }
  1536. }
  1537. portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
  1538. return xReturn;
  1539. }
  1540. BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void * const pvBuffer)
  1541. {
  1542. BaseType_t xReturn;
  1543. UBaseType_t uxSavedInterruptStatus;
  1544. int8_t * pcOriginalReadPosition;
  1545. Queue_t * const pxQueue = xQueue;
  1546. configASSERT(pxQueue);
  1547. configASSERT(!((pvBuffer == NULL ) && (pxQueue->uxItemSize != (UBaseType_t) 0U)));
  1548. configASSERT(pxQueue->uxItemSize != 0); /* Can't peek a semaphore. */
  1549. /* RTOS ports that support interrupt nesting have the concept of a maximum
  1550. * system call (or maximum API call) interrupt priority. Interrupts that are
  1551. * above the maximum system call priority are kept permanently enabled, even
  1552. * when the RTOS kernel is in a critical section, but cannot make any calls to
  1553. * FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
  1554. * then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
  1555. * failure if a FreeRTOS API function is called from an interrupt that has been
  1556. * assigned a priority above the configured maximum system call priority.
  1557. * Only FreeRTOS functions that end in FromISR can be called from interrupts
  1558. * that have been assigned a priority at or (logically) below the maximum
  1559. * system call interrupt priority. FreeRTOS maintains a separate interrupt
  1560. * safe API to ensure interrupt entry is as fast and as simple as possible.
  1561. * More information (albeit Cortex-M specific) is provided on the following
  1562. * link: https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
  1563. portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
  1564. uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
  1565. {
  1566. /* Cannot block in an ISR, so check there is data available. */
  1567. if ( pxQueue->uxMessagesWaiting > (UBaseType_t)0)
  1568. {
  1569. traceQUEUE_PEEK_FROM_ISR(pxQueue);
  1570. /* Remember the read position so it can be reset as nothing is
  1571. * actually being removed from the queue. */
  1572. pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom;
  1573. prvCopyDataFromQueue(pxQueue, pvBuffer);
  1574. pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition;
  1575. xReturn = pdPASS;
  1576. }
  1577. else
  1578. {
  1579. xReturn = pdFAIL;
  1580. traceQUEUE_PEEK_FROM_ISR_FAILED(pxQueue);
  1581. }
  1582. }
  1583. portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus);
  1584. return xReturn;
  1585. }
  1586. /* 返回队列中的消息数 */
  1587. UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue)
  1588. {
  1589. UBaseType_t uxReturn;
  1590. configASSERT(xQueue);
  1591. taskENTER_CRITICAL();
  1592. {
  1593. uxReturn = ((Queue_t *)xQueue)->uxMessagesWaiting;
  1594. }
  1595. taskEXIT_CRITICAL();
  1596. return uxReturn;
  1597. }
  1598. /* 返回队列中可以存放消息数 */
  1599. UBaseType_t uxQueueSpacesAvailable(const QueueHandle_t xQueue)
  1600. {
  1601. UBaseType_t uxReturn;
  1602. Queue_t * const pxQueue = xQueue;
  1603. configASSERT(pxQueue);
  1604. taskENTER_CRITICAL();
  1605. {
  1606. uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting;
  1607. }
  1608. taskEXIT_CRITICAL();
  1609. return uxReturn;
  1610. }
  1611. UBaseType_t uxQueueMessagesWaitingFromISR(const QueueHandle_t xQueue)
  1612. {
  1613. UBaseType_t uxReturn;
  1614. Queue_t * const pxQueue = xQueue;
  1615. configASSERT(pxQueue);
  1616. uxReturn = pxQueue->uxMessagesWaiting;
  1617. return uxReturn;
  1618. }
  1619. void vQueueDelete(QueueHandle_t xQueue)
  1620. {
  1621. Queue_t * const pxQueue = xQueue;
  1622. configASSERT(pxQueue);
  1623. traceQUEUE_DELETE(pxQueue);
  1624. #if (configQUEUE_REGISTRY_SIZE > 0)
  1625. {
  1626. vQueueUnregisterQueue(pxQueue);
  1627. }
  1628. #endif
  1629. /* The queue can only have been allocated dynamically - free it
  1630. * again. */
  1631. vPortFree(pxQueue);
  1632. }
  1633. #if (configUSE_TRACE_FACILITY == 1)
  1634. UBaseType_t uxQueueGetQueueNumber(QueueHandle_t xQueue)
  1635. {
  1636. return ((Queue_t *)xQueue)->uxQueueNumber;
  1637. }
  1638. void vQueueSetQueueNumber( QueueHandle_t xQueue,
  1639. UBaseType_t uxQueueNumber )
  1640. {
  1641. ((Queue_t *) xQueue)->uxQueueNumber = uxQueueNumber;
  1642. }
  1643. uint8_t ucQueueGetQueueType( QueueHandle_t xQueue )
  1644. {
  1645. return ((Queue_t * ) xQueue )->ucQueueType;
  1646. }
  1647. #endif /* configUSE_TRACE_FACILITY */
  1648. #if (configUSE_MUTEXES == 1)
  1649. /**
  1650. * 返回队列阻塞任务的最高的优先级
  1651. */
  1652. static UBaseType_t prvGetDisinheritPriorityAfterTimeout(const Queue_t * const pxQueue)
  1653. {
  1654. UBaseType_t uxHighestPriorityOfWaitingTasks;
  1655. UBaseType_t uxHeadItemValue;
  1656. /* If a task waiting for a mutex causes the mutex holder to inherit a
  1657. * priority, but the waiting task times out, then the holder should
  1658. * disinherit the priority - but only down to the highest priority of any
  1659. * other tasks that are waiting for the same mutex. For this purpose,
  1660. * return the priority of the highest priority task that is waiting for the
  1661. * mutex. */
  1662. if (listCURRENT_LIST_LENGTH(&(pxQueue->xTasksWaitingToReceive)) > 0U)
  1663. {
  1664. uxHeadItemValue = (UBaseType_t) listGET_ITEM_VALUE_OF_HEAD_ENTRY(&(pxQueue->xTasksWaitingToReceive));
  1665. uxHighestPriorityOfWaitingTasks = (UBaseType_t)configMAX_PRIORITIES - uxHeadItemValue;
  1666. }
  1667. else
  1668. {
  1669. uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY;
  1670. }
  1671. return uxHighestPriorityOfWaitingTasks;
  1672. }
  1673. #endif /* configUSE_MUTEXES */
  1674. /**
  1675. * 拷贝消息到队列中
  1676. */
  1677. static BaseType_t prvCopyDataToQueue(Queue_t *const pxQueue,
  1678. const void *pvItemToQueue,
  1679. const BaseType_t xPosition)
  1680. {
  1681. BaseType_t xReturn = pdFALSE;
  1682. UBaseType_t uxMessagesWaiting;
  1683. /* This function is called from a critical section. */
  1684. uxMessagesWaiting = pxQueue->uxMessagesWaiting;
  1685. if (pxQueue->uxItemSize == (UBaseType_t)0)
  1686. {
  1687. #if (configUSE_MUTEXES == 1)
  1688. {
  1689. if (pxQueue->uxQueueType == queueQUEUE_IS_MUTEX)
  1690. {
  1691. /* The mutex is no longer being held. */
  1692. xReturn = xTaskPriorityDisinherit(pxQueue->u.xSemaphore.xMutexHolder);
  1693. pxQueue->u.xSemaphore.xMutexHolder = NULL;
  1694. }
  1695. }
  1696. #endif /* configUSE_MUTEXES */
  1697. }
  1698. else if (xPosition == queueSEND_TO_BACK)
  1699. {
  1700. /* 拷贝到队列存储消息区域的尾部 */
  1701. (void) memcpy((void *) pxQueue->pcWriteTo, pvItemToQueue, (size_t)pxQueue->uxItemSize);
  1702. pxQueue->pcWriteTo += pxQueue->uxItemSize;
  1703. /* 检查队列是否为满, 如果满了,从头开始覆盖,类似于循环fifo */
  1704. if (pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail)
  1705. {
  1706. pxQueue->pcWriteTo = pxQueue->pcHead;
  1707. }
  1708. }
  1709. else
  1710. {
  1711. /* 拷贝到队列的头部 */
  1712. (void)memcpy((void *)pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, (size_t)pxQueue->uxItemSize);
  1713. pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize;
  1714. if (pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead)
  1715. {
  1716. pxQueue->u.xQueue.pcReadFrom = (pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize);
  1717. }
  1718. /* 覆盖方式,删除队列中的元素 */
  1719. if (xPosition == queueOVERWRITE)
  1720. {
  1721. if (uxMessagesWaiting > (UBaseType_t)0)
  1722. {
  1723. /**
  1724. * An item is not being added but overwritten, so subtract
  1725. * one from the recorded number of items in the queue so when
  1726. * one is added again below the number of recorded items remains
  1727. * correct.
  1728. */
  1729. --uxMessagesWaiting;
  1730. }
  1731. }
  1732. }
  1733. pxQueue->uxMessagesWaiting = uxMessagesWaiting + (UBaseType_t)1;
  1734. return xReturn;
  1735. }
  1736. /**
  1737. * 队列中的消息拷贝到pvBuffer中
  1738. */
  1739. static void prvCopyDataFromQueue(Queue_t * const pxQueue, void * const pvBuffer)
  1740. {
  1741. if (pxQueue->uxItemSize != (UBaseType_t)0)
  1742. {
  1743. pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize;
  1744. /* 队列为空,复位读位置指针 */
  1745. if (pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail)
  1746. {
  1747. pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
  1748. }
  1749. (void)memcpy((void *)pvBuffer, (void *)pxQueue->u.xQueue.pcReadFrom, (size_t)pxQueue->uxItemSize);
  1750. }
  1751. }
  1752. static void prvUnlockQueue(Queue_t * const pxQueue)
  1753. {
  1754. /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
  1755. /* The lock counts contains the number of extra data items placed or
  1756. * removed from the queue while the queue was locked. When a queue is
  1757. * locked items can be added or removed, but the event lists cannot be
  1758. * updated. */
  1759. taskENTER_CRITICAL();
  1760. {
  1761. int8_t cTxLock = pxQueue->cTxLock;
  1762. /* See if data was added to the queue while it was locked. */
  1763. while(cTxLock > queueLOCKED_UNMODIFIED)
  1764. {
  1765. /* Data was posted while the queue was locked. Are any tasks
  1766. * blocked waiting for data to become available? */
  1767. #if (onfigUSE_QUEUE_SETS == 1)
  1768. {
  1769. if (pxQueue->pxQueueSetContainer != NULL)
  1770. {
  1771. if (prvNotifyQueueSetContainer(pxQueue) != pdFALSE)
  1772. {
  1773. /* The queue is a member of a queue set, and posting to
  1774. * the queue set caused a higher priority task to unblock.
  1775. * A context switch is required. */
  1776. vTaskMissedYield();
  1777. }
  1778. }
  1779. else
  1780. {
  1781. /* Tasks that are removed from the event list will get
  1782. * added to the pending ready list as the scheduler is still
  1783. * suspended. */
  1784. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  1785. {
  1786. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  1787. {
  1788. /* The task waiting has a higher priority so record that a
  1789. * context switch is required. */
  1790. vTaskMissedYield();
  1791. }
  1792. }
  1793. else
  1794. {
  1795. break;
  1796. }
  1797. }
  1798. }
  1799. #else /* configUSE_QUEUE_SETS */
  1800. {
  1801. /* Tasks that are removed from the event list will get added to
  1802. * the pending ready list as the scheduler is still suspended.
  1803. * 等待接收消息的任务阻塞队列不为空
  1804. */
  1805. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToReceive)) == pdFALSE)
  1806. {
  1807. /* 从阻塞队列删除,重新加入就绪队列 */
  1808. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToReceive)) != pdFALSE)
  1809. {
  1810. /* The task waiting has a higher priority so record that
  1811. * a context switch is required. */
  1812. vTaskMissedYield();
  1813. }
  1814. }
  1815. else
  1816. {
  1817. break;
  1818. }
  1819. }
  1820. #endif /* configUSE_QUEUE_SETS */
  1821. --cTxLock;
  1822. }
  1823. pxQueue->cTxLock = queueUNLOCKED;
  1824. }
  1825. taskEXIT_CRITICAL();
  1826. /* Do the same for the Rx lock. */
  1827. taskENTER_CRITICAL();
  1828. {
  1829. int8_t cRxLock = pxQueue->cRxLock;
  1830. while(cRxLock > queueLOCKED_UNMODIFIED)
  1831. {
  1832. if (listLIST_IS_EMPTY(&(pxQueue->xTasksWaitingToSend)) == pdFALSE)
  1833. {
  1834. if (xTaskRemoveFromEventList(&(pxQueue->xTasksWaitingToSend)) != pdFALSE)
  1835. {
  1836. vTaskMissedYield();
  1837. }
  1838. --cRxLock;
  1839. }
  1840. else
  1841. {
  1842. break;
  1843. }
  1844. }
  1845. pxQueue->cRxLock = queueUNLOCKED;
  1846. }
  1847. taskEXIT_CRITICAL();
  1848. }
  1849. /**
  1850. * 判断队列是否为空
  1851. * 返回值:
  1852. * true: 队列空
  1853. * fasle: 队列非空
  1854. */
  1855. static BaseType_t prvIsQueueEmpty(const Queue_t * pxQueue)
  1856. {
  1857. BaseType_t xReturn;
  1858. taskENTER_CRITICAL();
  1859. {
  1860. /* 消息数为0, 消息队列为空 */
  1861. if (pxQueue->uxMessagesWaiting == ( UBaseType_t )0)
  1862. {
  1863. xReturn = pdTRUE;
  1864. }
  1865. else
  1866. {
  1867. xReturn = pdFALSE;
  1868. }
  1869. }
  1870. taskEXIT_CRITICAL();
  1871. return xReturn;
  1872. }
  1873. BaseType_t xQueueIsQueueEmptyFromISR(const QueueHandle_t xQueue)
  1874. {
  1875. BaseType_t xReturn;
  1876. Queue_t * const pxQueue = xQueue;
  1877. configASSERT(pxQueue);
  1878. if (pxQueue->uxMessagesWaiting == (UBaseType_t)0)
  1879. {
  1880. xReturn = pdTRUE;
  1881. }
  1882. else
  1883. {
  1884. xReturn = pdFALSE;
  1885. }
  1886. return xReturn;
  1887. }
  1888. /* 队列是否为满 */
  1889. static BaseType_t prvIsQueueFull(const Queue_t *pxQueue)
  1890. {
  1891. BaseType_t xReturn;
  1892. taskENTER_CRITICAL();
  1893. {
  1894. if (pxQueue->uxMessagesWaiting == pxQueue->uxLength)
  1895. {
  1896. xReturn = pdTRUE;
  1897. }
  1898. else
  1899. {
  1900. xReturn = pdFALSE;
  1901. }
  1902. }
  1903. taskEXIT_CRITICAL();
  1904. return xReturn;
  1905. }
  1906. BaseType_t xQueueIsQueueFullFromISR(const QueueHandle_t xQueue)
  1907. {
  1908. BaseType_t xReturn;
  1909. Queue_t * const pxQueue = xQueue;
  1910. configASSERT(pxQueue);
  1911. if (pxQueue->uxMessagesWaiting == pxQueue->uxLength)
  1912. {
  1913. xReturn = pdTRUE;
  1914. }
  1915. else
  1916. {
  1917. xReturn = pdFALSE;
  1918. }
  1919. return xReturn;
  1920. }
  1921. #if (configQUEUE_REGISTRY_SIZE > 0)
  1922. /**
  1923. * 向xQueueRegistry数组添加队列元素xQueue
  1924. */
  1925. void vQueueAddToRegistry(QueueHandle_t xQueue, const char *pcQueueName)
  1926. {
  1927. UBaseType_t ux;
  1928. QueueRegistryItem_t * pxEntryToWrite = NULL;
  1929. configASSERT(xQueue);
  1930. if (pcQueueName != NULL)
  1931. {
  1932. /* See if there is an empty space in the registry. A NULL name denotes
  1933. * a free slot. */
  1934. for(ux = (UBaseType_t) 0U; ux < (UBaseType_t)configQUEUE_REGISTRY_SIZE; ux++)
  1935. {
  1936. /* Replace an existing entry if the queue is already in the registry. */
  1937. if (xQueue == xQueueRegistry[ux].xHandle)
  1938. {
  1939. pxEntryToWrite = &(xQueueRegistry[ux]);
  1940. break;
  1941. }
  1942. else if ((pxEntryToWrite == NULL) && (xQueueRegistry[ux].pcQueueName == NULL))
  1943. {
  1944. pxEntryToWrite = &(xQueueRegistry[ux]);
  1945. }
  1946. }
  1947. }
  1948. /* 如果已经存在,用新的覆盖旧的元素 */
  1949. if (pxEntryToWrite != NULL)
  1950. {
  1951. /* Store the information on this queue. */
  1952. pxEntryToWrite->pcQueueName = pcQueueName;
  1953. pxEntryToWrite->xHandle = xQueue;
  1954. traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName);
  1955. }
  1956. }
  1957. /**
  1958. * 返回队列的名字
  1959. */
  1960. const char * pcQueueGetName(QueueHandle_t xQueue)
  1961. {
  1962. UBaseType_t ux;
  1963. const char * pcReturn = NULL;
  1964. configASSERT(xQueue);
  1965. /* Note there is nothing here to protect against another task adding or
  1966. * removing entries from the registry while it is being searched. */
  1967. for(ux = (UBaseType_t) 0U; ux < (UBaseType_t) configQUEUE_REGISTRY_SIZE; ux++)
  1968. {
  1969. if (xQueueRegistry[ux].xHandle == xQueue)
  1970. {
  1971. pcReturn = xQueueRegistry[ux].pcQueueName;
  1972. break;
  1973. }
  1974. }
  1975. return pcReturn;
  1976. }
  1977. /**
  1978. * 从xQueueRegistry数组中删除xQueue队列
  1979. */
  1980. void vQueueUnregisterQueue(QueueHandle_t xQueue)
  1981. {
  1982. UBaseType_t ux;
  1983. configASSERT( xQueue );
  1984. /* See if the handle of the queue being unregistered in actually in the
  1985. * registry. */
  1986. for(ux = (UBaseType_t) 0U; ux < (UBaseType_t) configQUEUE_REGISTRY_SIZE; ux++)
  1987. {
  1988. if (xQueueRegistry[ux].xHandle == xQueue)
  1989. {
  1990. /* Set the name to NULL to show that this slot if free again. */
  1991. xQueueRegistry[ux].pcQueueName = NULL;
  1992. /* Set the handle to NULL to ensure the same queue handle cannot
  1993. * appear in the registry twice if it is added, removed, then
  1994. * added again. */
  1995. xQueueRegistry[ux].xHandle = (QueueHandle_t)0;
  1996. break;
  1997. }
  1998. }
  1999. }
  2000. #endif /* configQUEUE_REGISTRY_SIZE */
  2001. #if ( configUSE_TIMERS == 1 )
  2002. void vQueueWaitForMessageRestricted(QueueHandle_t xQueue,
  2003. TickType_t xTicksToWait,
  2004. const BaseType_t xWaitIndefinitely)
  2005. {
  2006. Queue_t * const pxQueue = xQueue;
  2007. /* This function should not be called by application code hence the
  2008. * 'Restricted' in its name. It is not part of the public API. It is
  2009. * designed for use by kernel code, and has special calling requirements.
  2010. * It can result in vListInsert() being called on a list that can only
  2011. * possibly ever have one item in it, so the list will be fast, but even
  2012. * so it should be called with the scheduler locked and not from a critical
  2013. * section. */
  2014. /* Only do anything if there are no messages in the queue. This function
  2015. * will not actually cause the task to block, just place it on a blocked
  2016. * list. It will not block until the scheduler is unlocked - at which
  2017. * time a yield will be performed. If an item is added to the queue while
  2018. * the queue is locked, and the calling task blocks on the queue, then the
  2019. * calling task will be immediately unblocked when the queue is unlocked. */
  2020. prvLockQueue(pxQueue);
  2021. if (pxQueue->uxMessagesWaiting == (UBaseType_t) 0U)
  2022. {
  2023. /* There is nothing in the queue, block for the specified period. */
  2024. vTaskPlaceOnEventListRestricted(&(pxQueue->xTasksWaitingToReceive), xTicksToWait, xWaitIndefinitely);
  2025. }
  2026. prvUnlockQueue(pxQueue);
  2027. }
  2028. #endif /* configUSE_TIMERS */
  2029. #if (configUSE_QUEUE_SETS == 1)
  2030. QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength)
  2031. {
  2032. QueueSetHandle_t pxQueue;
  2033. /* 队列的集合 */
  2034. pxQueue = xQueueGenericCreate(uxEventQueueLength, (UBaseType_t) sizeof(Queue_t *), queueQUEUE_TYPE_SET);
  2035. return pxQueue;
  2036. }
  2037. BaseType_t xQueueAddToSet(QueueSetMemberHandle_t xQueueOrSemaphore,
  2038. QueueSetHandle_t xQueueSet)
  2039. {
  2040. BaseType_t xReturn;
  2041. taskENTER_CRITICAL();
  2042. {
  2043. if (((Queue_t *)xQueueOrSemaphore)->pxQueueSetContainer != NULL)
  2044. {
  2045. /* Cannot add a queue/semaphore to more than one queue set. */
  2046. xReturn = pdFAIL;
  2047. }
  2048. else if (((Queue_t *) xQueueOrSemaphore)->uxMessagesWaiting != (UBaseType_t)0)
  2049. {
  2050. /* Cannot add a queue/semaphore to a queue set if there are already
  2051. * items in the queue/semaphore. */
  2052. xReturn = pdFAIL;
  2053. }
  2054. else
  2055. {
  2056. ((Queue_t *) xQueueOrSemaphore)->pxQueueSetContainer = xQueueSet;
  2057. xReturn = pdPASS;
  2058. }
  2059. }
  2060. taskEXIT_CRITICAL();
  2061. return xReturn;
  2062. }
  2063. BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore,
  2064. QueueSetHandle_t xQueueSet)
  2065. {
  2066. BaseType_t xReturn;
  2067. Queue_t * const pxQueueOrSemaphore = (Queue_t *) xQueueOrSemaphore;
  2068. if (pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet)
  2069. {
  2070. /* The queue was not a member of the set. */
  2071. xReturn = pdFAIL;
  2072. }
  2073. else if (pxQueueOrSemaphore->uxMessagesWaiting != (UBaseType_t)0)
  2074. {
  2075. /* It is dangerous to remove a queue from a set when the queue is
  2076. * not empty because the queue set will still hold pending events for
  2077. * the queue. */
  2078. xReturn = pdFAIL;
  2079. }
  2080. else
  2081. {
  2082. taskENTER_CRITICAL();
  2083. {
  2084. /* The queue is no longer contained in the set. */
  2085. pxQueueOrSemaphore->pxQueueSetContainer = NULL;
  2086. }
  2087. taskEXIT_CRITICAL();
  2088. xReturn = pdPASS;
  2089. }
  2090. return xReturn;
  2091. }
  2092. QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet,
  2093. TickType_t const xTicksToWait)
  2094. {
  2095. QueueSetMemberHandle_t xReturn = NULL;
  2096. (void) xQueueReceive((QueueHandle_t) xQueueSet, &xReturn, xTicksToWait);
  2097. return xReturn;
  2098. }
  2099. QueueSetMemberHandle_t xQueueSelectFromSetFromISR(QueueSetHandle_t xQueueSet)
  2100. {
  2101. QueueSetMemberHandle_t xReturn = NULL;
  2102. (void) xQueueReceiveFromISR((QueueHandle_t) xQueueSet, &xReturn, NULL);
  2103. return xReturn;
  2104. }
  2105. static BaseType_t prvNotifyQueueSetContainer(const Queue_t *const pxQueue)
  2106. {
  2107. Queue_t * pxQueueSetContainer = pxQueue->pxQueueSetContainer;
  2108. BaseType_t xReturn = pdFALSE;
  2109. /* This function must be called form a critical section. */
  2110. /* The following line is not reachable in unit tests because every call
  2111. * to prvNotifyQueueSetContainer is preceded by a check that
  2112. * pxQueueSetContainer != NULL */
  2113. configASSERT(pxQueueSetContainer); /* LCOV_EXCL_BR_LINE */
  2114. configASSERT(pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength);
  2115. if (pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength)
  2116. {
  2117. const int8_t cTxLock = pxQueueSetContainer->cTxLock;
  2118. traceQUEUE_SET_SEND(pxQueueSetContainer);
  2119. /* The data copied is the handle of the queue that contains data. */
  2120. xReturn = prvCopyDataToQueue(pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK);
  2121. if (cTxLock == queueUNLOCKED)
  2122. {
  2123. if (listLIST_IS_EMPTY(&(pxQueueSetContainer->xTasksWaitingToReceive)) == pdFALSE)
  2124. {
  2125. if (xTaskRemoveFromEventList(&(pxQueueSetContainer->xTasksWaitingToReceive)) != pdFALSE)
  2126. {
  2127. /* The task waiting has a higher priority. */
  2128. xReturn = pdTRUE;
  2129. }
  2130. }
  2131. }
  2132. else
  2133. {
  2134. prvIncrementQueueTxLock(pxQueueSetContainer, cTxLock);
  2135. }
  2136. }
  2137. return xReturn;
  2138. }
  2139. #endif /* configUSE_QUEUE_SETS */