os_rtwrap.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * Copyright (c) 2021, Meco Jianting Man <jiantingman@foxmail.com>
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-07-12 Meco Man the first verion
  9. */
  10. #include "ucos_ii.h"
  11. #include <string.h>
  12. #include <rthw.h>
  13. extern void (*rt_object_put_hook)(struct rt_object *object);
  14. /**
  15. * 让当挂起表第一个任务放弃等待IPC,进入就绪态(由rt_ipc_list_resume函数改编)
  16. *
  17. * @param 挂起表表头指针
  18. *
  19. * @return 错误码
  20. */
  21. rt_err_t rt_ipc_pend_abort_1 (rt_list_t *list)
  22. {
  23. struct rt_thread *thread;
  24. register rt_ubase_t temp;
  25. OS_TCB *p_tcb;
  26. temp = rt_hw_interrupt_disable();
  27. /* get thread entry */
  28. thread = rt_list_entry(list->next, struct rt_thread, tlist);
  29. p_tcb = (OS_TCB*)thread;
  30. /* set error code to RT_ERROR */
  31. thread->error = -RT_ERROR;
  32. /*标记当前任务放弃等待*/
  33. p_tcb->OSTCBStatPend = OS_STAT_PEND_ABORT;
  34. rt_hw_interrupt_enable(temp);
  35. /* resume it */
  36. rt_thread_resume(thread);
  37. return RT_EOK;
  38. }
  39. /**
  40. * 让所有等待该IPC的任务全部放弃等待,进入就绪态(由rt_ipc_list_resume_all函数改编)
  41. *
  42. * @param 挂起表表头指针
  43. *
  44. * @return 放弃了多少个任务
  45. */
  46. rt_uint16_t rt_ipc_pend_abort_all (rt_list_t *list)
  47. {
  48. struct rt_thread *thread;
  49. register rt_ubase_t temp;
  50. OS_TCB *p_tcb;
  51. rt_uint16_t i=0;
  52. /* wakeup all suspend threads */
  53. while (!rt_list_isempty(list))
  54. {
  55. /* disable interrupt */
  56. temp = rt_hw_interrupt_disable();
  57. /* get next suspend thread */
  58. thread = rt_list_entry(list->next, struct rt_thread, tlist);
  59. p_tcb = ((OS_TCB*)thread);
  60. /* set error code to RT_ERROR */
  61. thread->error = -RT_ERROR;
  62. /*标记当前任务放弃等待*/
  63. p_tcb->OSTCBStatPend = OS_STAT_PEND_ABORT;
  64. /*
  65. * resume thread
  66. * In rt_thread_resume function, it will remove current thread from
  67. * suspend list
  68. */
  69. rt_thread_resume(thread);
  70. /* enable interrupt */
  71. rt_hw_interrupt_enable(temp);
  72. i++;
  73. }
  74. return i;
  75. }
  76. /**
  77. * 让所有等待该IPC的任务全部批准进入就绪态(由rt_ipc_list_resume_all函数改编)
  78. *
  79. * @param 挂起表表头指针
  80. *
  81. * @return 错误码
  82. */
  83. static rt_err_t rt_ipc_post_all (rt_list_t *list)
  84. {
  85. struct rt_thread *thread;
  86. register rt_ubase_t temp;
  87. /* wakeup all suspend threads */
  88. while (!rt_list_isempty(list))
  89. {
  90. /* disable interrupt */
  91. temp = rt_hw_interrupt_disable();
  92. /* get next suspend thread */
  93. thread = rt_list_entry(list->next, struct rt_thread, tlist);
  94. /*
  95. * resume thread
  96. * In rt_thread_resume function, it will remove current thread from
  97. * suspend list
  98. */
  99. rt_thread_resume(thread);
  100. /* enable interrupt */
  101. rt_hw_interrupt_enable(temp);
  102. }
  103. return RT_EOK;
  104. }
  105. /**
  106. * This function will wake ALL threads which are WAITTING for message queue (FIFO)
  107. * 改编自rt_mq_send函数
  108. *
  109. * @param mq the message queue object
  110. * @param buffer the message
  111. * @param size the size of buffer
  112. *
  113. * @return the error code
  114. */
  115. rt_err_t rt_mq_send_all(rt_mq_t mq, void *buffer, rt_size_t size)
  116. {
  117. register rt_ubase_t temp;
  118. struct _rt_mq_message *msg;
  119. rt_uint16_t suspend_len;
  120. /* parameter check */
  121. RT_ASSERT(mq != RT_NULL);
  122. RT_ASSERT(rt_object_get_type(&mq->parent.parent) == RT_Object_Class_MessageQueue);
  123. RT_ASSERT(buffer != RT_NULL);
  124. RT_ASSERT(size != 0);
  125. /* greater than one message size */
  126. if (size > mq->msg_size)
  127. return -RT_ERROR;
  128. RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent)));
  129. /* disable interrupt */
  130. temp = rt_hw_interrupt_disable();
  131. /* 获取当前n个线程被当前消息队列挂起 */
  132. suspend_len = rt_list_len(&mq->parent.suspend_thread);
  133. /* 将相同的消息复制n次,一会一起发出去 */
  134. while(suspend_len)
  135. {
  136. /* get a free list, there must be an empty item */
  137. msg = (struct _rt_mq_message *)mq->msg_queue_free;
  138. /* message queue is full */
  139. if (msg == RT_NULL)
  140. {
  141. /* enable interrupt */
  142. rt_hw_interrupt_enable(temp);
  143. return -RT_EFULL;
  144. }
  145. /* move free list pointer */
  146. mq->msg_queue_free = msg->next;
  147. /* enable interrupt */
  148. rt_hw_interrupt_enable(temp);
  149. /* the msg is the new tailer of list, the next shall be NULL */
  150. msg->next = RT_NULL;
  151. /* copy buffer */
  152. rt_memcpy(msg + 1, buffer, size);
  153. /* disable interrupt */
  154. temp = rt_hw_interrupt_disable();
  155. /* link msg to message queue */
  156. if (mq->msg_queue_tail != RT_NULL)
  157. {
  158. /* if the tail exists, */
  159. ((struct _rt_mq_message *)mq->msg_queue_tail)->next = msg;
  160. }
  161. /* set new tail */
  162. mq->msg_queue_tail = msg;
  163. /* if the head is empty, set head */
  164. if (mq->msg_queue_head == RT_NULL)
  165. mq->msg_queue_head = msg;
  166. /* increase message entry */
  167. mq->entry ++;
  168. suspend_len --;
  169. }
  170. /* resume suspended thread */
  171. if (!rt_list_isempty(&mq->parent.suspend_thread))
  172. {
  173. /* 将等待本消息队列的所有线程全部解挂,此时他们将同时获得相同的消息 */
  174. rt_ipc_post_all(&(mq->parent.suspend_thread));
  175. /* enable interrupt */
  176. rt_hw_interrupt_enable(temp);
  177. rt_schedule();
  178. return RT_EOK;
  179. }
  180. /* enable interrupt */
  181. rt_hw_interrupt_enable(temp);
  182. return RT_EOK;
  183. }
  184. /**
  185. * 自动初始化
  186. * uCOS-II兼容层支持按照uCOS-II原版的初始化步骤进行初始化,但是在有些情况,
  187. * 用户不想手动初始化uCOS-II兼容层,想要直接运行应用层任务或模块,则可以使用该
  188. * 宏定义。在rtconfig.h中定义本宏定义后,在RT-Thread初始化完成并进入到main线程之前
  189. * 会自动将uCOS-II兼容层初始化完毕,用户仅需要专注于uCOS-II的应用级任务即可。
  190. * The wrapper supports uCOS-II standard startup procedure. Alternatively,
  191. * if you want to run uCOS-II apps directly and ignore the startup procedure,
  192. * you can choose this option.
  193. */
  194. #ifdef PKG_USING_UCOSII_WRAPPER_AUTOINIT
  195. static int rt_ucosii_autoinit(void)
  196. {
  197. OSInit(); /*uCOS-II操作系统初始化*/
  198. OSStart(); /*开始运行uCOS-II操作系统*/
  199. #if OS_TASK_STAT_EN > 0u
  200. OSStatInit();
  201. #endif
  202. return 0;
  203. }
  204. INIT_PREV_EXPORT(rt_ucosii_autoinit);
  205. #endif