queue.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. #include <stdlib.h>
  2. #include <string.h>
  3. /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
  4. all the API functions to use the MPU wrappers. That should only be done when
  5. task.h is included from an application file. */
  6. #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
  7. #include "FreeRTOS.h"
  8. #include "task.h"
  9. #include "queue.h"
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #define MT2625_QUEUE_DEBUG
  13. #ifdef MT2625_QUEUE_DEBUG
  14. #define LOG_TAG "QUEUE"
  15. #define LOG_LVL LOG_LVL_ERROR // LOG_LVL_ERROR | LOG_LVL_DBG
  16. #include <ulog.h>
  17. #else
  18. #define LOG_D(...)
  19. #define LOG_I(...)
  20. #define LOG_W(...)
  21. #define LOG_E(...)
  22. #endif
  23. /* Lint e961 and e750 are suppressed as a MISRA exception justified because the
  24. MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
  25. header files above, but not in this file, in order to generate the correct
  26. privileged Vs unprivileged linkage and placement. */
  27. #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
  28. /* Semaphores do not actually store or copy data, so have an item size of
  29. zero. */
  30. #define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )
  31. #define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U )
  32. static volatile unsigned short mq_index = 0;
  33. static volatile unsigned short ms_index = 0;
  34. static volatile unsigned short mx_index = 0;
  35. static volatile unsigned short mr_index = 0;
  36. extern rt_err_t rt_fmq_delete(rt_mailbox_t mb);
  37. extern rt_err_t rt_fmq_recv(rt_mailbox_t mb, void *value, rt_int32_t peek, rt_int32_t timeout);
  38. extern rt_err_t rt_fmq_send(rt_mailbox_t mb, void *value, rt_int32_t pos, rt_int32_t timeout);
  39. extern rt_mailbox_t rt_fmq_create(const char *name, rt_size_t item, rt_size_t size, rt_uint8_t flag);
  40. /*-----------------------------------------------------------*/
  41. BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue )
  42. {
  43. LOG_E("queue reset, TODO");
  44. return pdPASS;
  45. }
  46. /*-----------------------------------------------------------*/
  47. extern uint32_t get_current_irq();
  48. QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType )
  49. {
  50. char name[10] = {0};
  51. rt_object_t obj = 0;
  52. if (uxItemSize <= 0 || uxQueueLength <= 0)
  53. {
  54. if (ucQueueType == queueQUEUE_TYPE_MUTEX || ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX)
  55. {
  56. if (ucQueueType == queueQUEUE_TYPE_MUTEX)
  57. {
  58. sprintf(name,"mux%02d",((++mx_index)%100));
  59. // obj = (rt_object_t)rt_mutex_create(name,RT_IPC_FLAG_PRIO);
  60. obj = (rt_object_t)rt_sem_create(name, 1, RT_IPC_FLAG_PRIO);
  61. LOG_D("mux:%p, name:%s", obj, name);
  62. }
  63. else
  64. {
  65. sprintf(name,"rmx%02d",((++mr_index)%100));
  66. obj = (rt_object_t)rt_mutex_create(name,RT_IPC_FLAG_PRIO);
  67. }
  68. }
  69. else if (ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE)
  70. {
  71. sprintf(name,"Bsem%02d",((++ms_index)%100));
  72. obj = (rt_object_t)rt_sem_create(name,0,RT_IPC_FLAG_PRIO);
  73. LOG_D("Bsem:%p, name:%s", obj, name);
  74. }
  75. else if (ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE)
  76. {
  77. sprintf(name,"sem%02d",((++ms_index)%100));
  78. obj = (rt_object_t)rt_sem_create(name,0,RT_IPC_FLAG_PRIO);
  79. }
  80. }
  81. else
  82. {
  83. sprintf(name,"fmq%02d",((++mq_index)%100));
  84. obj = (rt_object_t)rt_fmq_create(name,uxItemSize,uxQueueLength,RT_IPC_FLAG_PRIO);
  85. }
  86. return obj;
  87. }
  88. /*-----------------------------------------------------------*/
  89. #if ( configUSE_MUTEXES == 1 )
  90. QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
  91. {
  92. QueueHandle_t obj;
  93. obj = xQueueGenericCreate(1, 0, ucQueueType);
  94. return obj;
  95. }
  96. #endif /* configUSE_MUTEXES */
  97. /*-----------------------------------------------------------*/
  98. #if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) )
  99. void* xQueueGetMutexHolder( QueueHandle_t xSemaphore )
  100. {
  101. LOG_E("Get mutex owner, TODO");
  102. return NULL;
  103. } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */
  104. #endif
  105. /*-----------------------------------------------------------*/
  106. #if ( configUSE_RECURSIVE_MUTEXES == 1 )
  107. BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
  108. {
  109. return xQueueGenericSend(xMutex,0,0,queueSEND_TO_BACK);
  110. }
  111. #endif /* configUSE_RECURSIVE_MUTEXES */
  112. /*-----------------------------------------------------------*/
  113. #if ( configUSE_RECURSIVE_MUTEXES == 1 )
  114. BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait )
  115. {
  116. return xQueueGenericReceive(xMutex,0,xTicksToWait,pdFALSE);
  117. }
  118. #endif /* configUSE_RECURSIVE_MUTEXES */
  119. /*-----------------------------------------------------------*/
  120. #if ( configUSE_COUNTING_SEMAPHORES == 1 )
  121. QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount )
  122. {
  123. return xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE );
  124. }
  125. #endif /* configUSE_COUNTING_SEMAPHORES */
  126. /*-----------------------------------------------------------*/
  127. BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition )
  128. {
  129. rt_object_t obj = xQueue;
  130. rt_err_t err = RT_EOK;
  131. if (!obj)
  132. {
  133. LOG_E("In param (xQueue) is NULL!");
  134. configASSERT(obj);
  135. }
  136. if (obj->type == RT_Object_Class_Semaphore)
  137. {
  138. LOG_D("-> release sem[0x%08x], thread:%s", obj, rt_thread_self()->name);
  139. err = rt_sem_release((rt_sem_t)obj);
  140. }
  141. else if (obj->type == RT_Object_Class_Mutex)
  142. {
  143. LOG_D("-> release mutex, thread:%s", rt_thread_self()->name);
  144. err = rt_mutex_release((rt_mutex_t)obj);
  145. }
  146. else
  147. {
  148. LOG_D("-> send fast mq, thread:%s", rt_thread_self()->name);
  149. err = rt_fmq_send((rt_mailbox_t)obj,(void *)pvItemToQueue,xCopyPosition,xTicksToWait);
  150. }
  151. return (err==RT_EOK)?pdPASS:errQUEUE_FULL;
  152. }
  153. /*-----------------------------------------------------------*/
  154. BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition )
  155. {
  156. rt_object_t obj = xQueue;
  157. rt_err_t err = RT_EOK;
  158. if (!obj)
  159. {
  160. LOG_E("In param (xQueue) is NULL!");
  161. configASSERT(obj);
  162. }
  163. if (obj->type == RT_Object_Class_Semaphore)
  164. {
  165. LOG_D("-> release sem[INT]");
  166. err = rt_sem_release((rt_sem_t)obj);
  167. }
  168. else if (obj->type == RT_Object_Class_Mutex)
  169. {
  170. LOG_E("release mutex in isr");
  171. }
  172. else
  173. {
  174. LOG_D("-> send fast mq[INT]");
  175. err = rt_fmq_send((rt_mailbox_t)obj,(void *)pvItemToQueue, xCopyPosition, 0);
  176. }
  177. if (pxHigherPriorityTaskWoken) *pxHigherPriorityTaskWoken = pdFALSE;
  178. return (err==RT_EOK)?pdPASS:errQUEUE_FULL;
  179. }
  180. /*-----------------------------------------------------------*/
  181. BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken )
  182. {
  183. return xQueueGenericSendFromISR(xQueue,0,pxHigherPriorityTaskWoken,queueSEND_TO_BACK);
  184. }
  185. /*-----------------------------------------------------------*/
  186. BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
  187. {
  188. rt_object_t obj = xQueue;
  189. rt_err_t err = RT_EOK;
  190. rt_int32_t timeout;
  191. if (!obj)
  192. {
  193. LOG_E("In param (xQueue) is NULL!");
  194. configASSERT(obj);
  195. }
  196. if (xTicksToWait == portMAX_DELAY)
  197. timeout = RT_WAITING_FOREVER;
  198. else
  199. timeout = xTicksToWait;
  200. if (obj->type == RT_Object_Class_Semaphore)
  201. {
  202. LOG_D("┌- try to take sem[0x%08x]", obj);
  203. err = rt_sem_take((rt_sem_t)obj, timeout);
  204. LOG_D("└> taken sem[0x%08x], err=%d, thread:%s", obj, err, rt_thread_self()->name);
  205. }
  206. else if (obj->type == RT_Object_Class_Mutex)
  207. {
  208. LOG_D("┌- try to take mutex");
  209. err = rt_mutex_take((rt_mutex_t)obj, timeout);
  210. LOG_D("└> taken mutex, err=%d, thread:%s", err, rt_thread_self()->name);
  211. }
  212. else
  213. {
  214. LOG_D("┌- try to send fast mq");
  215. err = rt_fmq_recv((rt_mailbox_t)obj,(void *)pvBuffer,xJustPeeking,timeout);
  216. LOG_D("└> recved fast mq, err=%d, thread:%s", err, rt_thread_self()->name);
  217. }
  218. return (err==RT_EOK)?pdPASS:errQUEUE_EMPTY;
  219. }
  220. /*-----------------------------------------------------------*/
  221. BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
  222. {
  223. rt_object_t obj = xQueue;
  224. rt_err_t err = RT_EOK;
  225. if (!obj)
  226. {
  227. LOG_E("In param (xQueue) is NULL!");
  228. configASSERT(obj);
  229. }
  230. if (obj->type == RT_Object_Class_Semaphore)
  231. {
  232. LOG_D("┌- try to take sem[INT]");
  233. err = rt_sem_take((rt_sem_t)obj, 0);
  234. LOG_D("└> taken sem, err=%d", err);
  235. }
  236. else if (obj->type == RT_Object_Class_Mutex)
  237. {
  238. LOG_E("take mutex in isr");
  239. }
  240. else
  241. {
  242. LOG_D("┌- try to send fast mq[INT]");
  243. err = rt_fmq_recv((rt_mailbox_t)obj,(void *)pvBuffer, pdFALSE, 0);
  244. LOG_D("└> recved fast mq, err=%d", err);
  245. }
  246. if (pxHigherPriorityTaskWoken) *pxHigherPriorityTaskWoken = pdFALSE;
  247. return (err==RT_EOK)?pdPASS:errQUEUE_EMPTY;
  248. }
  249. /*-----------------------------------------------------------*/
  250. UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
  251. {
  252. rt_object_t obj = xQueue;
  253. unsigned portBASE_TYPE count = 0;
  254. if (!obj)
  255. {
  256. LOG_E("In param (xQueue) is NULL!");
  257. configASSERT(obj);
  258. }
  259. if (obj->type == RT_Object_Class_Semaphore)
  260. count = ((rt_sem_t)obj)->value;
  261. else if (obj->type == RT_Object_Class_Mutex)
  262. count = ((rt_mutex_t)obj)->value;
  263. else
  264. count = ((rt_mailbox_t)obj)->entry;
  265. return count;
  266. } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
  267. /*-----------------------------------------------------------*/
  268. UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
  269. {
  270. UBaseType_t uxReturn = 0;
  271. rt_object_t obj = xQueue;
  272. if (!obj)
  273. {
  274. LOG_E("In param (xQueue) is NULL!");
  275. configASSERT(obj);
  276. }
  277. if (obj->type == RT_Object_Class_MailBox)
  278. {
  279. rt_ubase_t level;
  280. struct rt_mailbox *mb = (struct rt_mailbox *)obj;
  281. rt_enter_critical();
  282. uxReturn = mb->size - mb->entry;
  283. rt_exit_critical();
  284. }
  285. return uxReturn;
  286. } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
  287. /*-----------------------------------------------------------*/
  288. UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue )
  289. {
  290. UBaseType_t uxReturn;
  291. uxReturn = uxQueueMessagesWaiting(xQueue);
  292. return uxReturn;
  293. } /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
  294. /*-----------------------------------------------------------*/
  295. void vQueueDelete( QueueHandle_t xQueue )
  296. {
  297. rt_object_t obj = xQueue;
  298. if (!obj)
  299. {
  300. LOG_E("In param (xQueue) is NULL!");
  301. configASSERT(obj);
  302. }
  303. if (obj->type == RT_Object_Class_Semaphore)
  304. rt_sem_delete((rt_sem_t)obj);
  305. else if (obj->type == RT_Object_Class_Mutex)
  306. rt_mutex_delete((rt_mutex_t)obj);
  307. else
  308. rt_fmq_delete((rt_mailbox_t)obj);
  309. }
  310. /*-----------------------------------------------------------*/
  311. void *uxQueueGetTasksWaitingToReceive(QueueHandle_t xQueue)
  312. {
  313. // LOG_E("F:%s;L:%d; xQueue:%p TODO", __FUNCTION__, __LINE__, xQueue);
  314. rt_object_t obj = xQueue;
  315. rt_list_t *list;
  316. rt_thread_t thread;
  317. if (!obj)
  318. {
  319. LOG_E("In param (xQueue) is NULL!");
  320. configASSERT(obj);
  321. }
  322. if (obj->type == RT_Object_Class_Semaphore)
  323. {
  324. rt_kprintf("type sem\n");
  325. list = &(((rt_sem_t)obj)->parent.suspend_thread);
  326. }
  327. else if (obj->type == RT_Object_Class_Mutex)
  328. {
  329. rt_kprintf("type mutex\n");
  330. list = &(((rt_mutex_t)obj)->parent.suspend_thread);
  331. }
  332. else
  333. {
  334. rt_kprintf("type others\n");
  335. list = &(((rt_mailbox_t)obj)->parent.suspend_thread);
  336. }
  337. rt_enter_critical();
  338. thread = rt_list_entry(list->next, struct rt_thread, tlist);
  339. rt_exit_critical();
  340. return thread;
  341. }