os_int.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. ************************************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
  7. * All rights reserved. Protected by international copyright laws.
  8. *
  9. * ISR QUEUE MANAGEMENT
  10. *
  11. * File : OS_INT.C
  12. * By : JJL
  13. * Version : V3.02.00
  14. *
  15. * LICENSING TERMS:
  16. * ---------------
  17. * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
  18. * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
  19. * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
  20. * application/product. We provide ALL the source code for your convenience and to help you
  21. * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
  22. * it commercially without paying a licensing fee.
  23. *
  24. * Knowledge of the source code may NOT be used to develop a similar product.
  25. *
  26. * Please help us continue to provide the embedded community with the finest software available.
  27. * Your honesty is greatly appreciated.
  28. *
  29. * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
  30. ************************************************************************************************************************
  31. */
  32. #include <os.h>
  33. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  34. const CPU_CHAR *os_int__c = "$Id: $";
  35. #endif
  36. #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
  37. /*$PAGE*/
  38. /*
  39. ************************************************************************************************************************
  40. * POST TO ISR QUEUE
  41. *
  42. * Description: This function places contents of posts into an intermediate queue to help defer processing of interrupts
  43. * at the task level.
  44. *
  45. * Arguments : type is the type of kernel object the post is destined to:
  46. *
  47. * OS_OBJ_TYPE_SEM
  48. * OS_OBJ_TYPE_Q
  49. * OS_OBJ_TYPE_FLAG
  50. * OS_OBJ_TYPE_TASK_MSG
  51. * OS_OBJ_TYPE_TASK_SIGNAL
  52. *
  53. * p_obj is a pointer to the kernel object to post to. This can be a pointer to a semaphore,
  54. * ----- a message queue or a task control clock.
  55. *
  56. * p_void is a pointer to a message that is being posted. This is used when posting to a message
  57. * queue or directly to a task.
  58. *
  59. * msg_size is the size of the message being posted
  60. *
  61. * flags if the post is done to an event flag group then this corresponds to the flags being
  62. * posted
  63. *
  64. * ts is a timestamp as to when the post was done
  65. *
  66. * opt this corresponds to post options and applies to:
  67. *
  68. * OSFlagPost()
  69. * OSSemPost()
  70. * OSQPost()
  71. * OSTaskQPost()
  72. *
  73. * p_err is a pointer to a variable that will contain an error code returned by this function.
  74. *
  75. * OS_ERR_NONE if the post to the ISR queue was successful
  76. * OS_ERR_INT_Q_FULL if the ISR queue is full and cannot accepts any further posts. This
  77. * generally indicates that you are receiving interrupts faster than you
  78. * can process them or, that you didn't make the ISR queue large enough.
  79. *
  80. * Returns : none
  81. *
  82. * Note(s) : none
  83. ************************************************************************************************************************
  84. */
  85. void OS_IntQPost (OS_OBJ_TYPE type,
  86. void *p_obj,
  87. void *p_void,
  88. OS_MSG_SIZE msg_size,
  89. OS_FLAGS flags,
  90. OS_OPT opt,
  91. CPU_TS ts,
  92. OS_ERR *p_err)
  93. {
  94. CPU_SR_ALLOC();
  95. #ifdef OS_SAFETY_CRITICAL
  96. if (p_err == (OS_ERR *)0) {
  97. OS_SAFETY_CRITICAL_EXCEPTION();
  98. return;
  99. }
  100. #endif
  101. CPU_CRITICAL_ENTER();
  102. if (OSIntQNbrEntries < OSCfg_IntQSize) { /* Make sure we haven't already filled the ISR queue */
  103. OSIntQNbrEntries++;
  104. if (OSIntQMaxNbrEntries < OSIntQNbrEntries) {
  105. OSIntQMaxNbrEntries = OSIntQNbrEntries;
  106. }
  107. OSIntQInPtr->Type = type; /* Save object type being posted */
  108. OSIntQInPtr->ObjPtr = p_obj; /* Save pointer to object being posted */
  109. OSIntQInPtr->MsgPtr = p_void; /* Save pointer to message if posting to a message queue */
  110. OSIntQInPtr->MsgSize = msg_size; /* Save the message size if posting to a message queue */
  111. OSIntQInPtr->Flags = flags; /* Save the flags if posting to an event flag group */
  112. OSIntQInPtr->Opt = opt; /* Save post options */
  113. OSIntQInPtr->TS = ts; /* Save time stamp */
  114. OSIntQInPtr = OSIntQInPtr->NextPtr; /* Point to the next interrupt handler queue entry */
  115. OSRdyList[0].NbrEntries = (OS_OBJ_QTY)1; /* Make the interrupt handler task ready to run */
  116. OSRdyList[0].HeadPtr = &OSIntQTaskTCB;
  117. OSRdyList[0].TailPtr = &OSIntQTaskTCB;
  118. OS_PrioInsert(0u); /* Add task priority 0 in the priority table */
  119. OSPrioSaved = OSPrioCur; /* Save current priority */
  120. *p_err = OS_ERR_NONE;
  121. } else {
  122. OSIntQOvfCtr++; /* Count the number of ISR queue overflows */
  123. *p_err = OS_ERR_INT_Q_FULL;
  124. }
  125. CPU_CRITICAL_EXIT();
  126. }
  127. /*$PAGE*/
  128. /*
  129. ************************************************************************************************************************
  130. * INTERRUPT QUEUE MANAGEMENT TASK
  131. *
  132. * Description: This task is created by OS_IntQTaskInit().
  133. *
  134. * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
  135. * the argument is not used and will be a NULL pointer.
  136. *
  137. * Returns : none
  138. ************************************************************************************************************************
  139. */
  140. void OS_IntQRePost (void)
  141. {
  142. void *p_obj;
  143. void *p_void;
  144. OS_ERR err;
  145. OS_FLAGS flags;
  146. CPU_TS ts;
  147. OS_OBJ_TYPE type;
  148. OS_OPT opt;
  149. OS_MSG_SIZE msg_size;
  150. CPU_SR_ALLOC();
  151. CPU_CRITICAL_ENTER();
  152. type = OSIntQOutPtr->Type; /* Get local copy of queue item contents */
  153. p_obj = OSIntQOutPtr->ObjPtr;
  154. p_void = OSIntQOutPtr->MsgPtr;
  155. msg_size = OSIntQOutPtr->MsgSize;
  156. flags = OSIntQOutPtr->Flags;
  157. opt = OSIntQOutPtr->Opt;
  158. ts = OSIntQOutPtr->TS;
  159. OSIntQOutPtr = OSIntQOutPtr->NextPtr; /* Point to next item in the ISR queue */
  160. CPU_CRITICAL_EXIT();
  161. switch (type) { /* Re-post to task */
  162. case OS_OBJ_TYPE_FLAG:
  163. #if OS_CFG_FLAG_EN > 0u
  164. (void)OS_FlagPost((OS_FLAG_GRP *)p_obj,
  165. (OS_FLAGS )flags,
  166. (OS_OPT )opt,
  167. (CPU_TS )ts,
  168. (OS_ERR *)&err);
  169. #endif
  170. break;
  171. case OS_OBJ_TYPE_Q:
  172. #if OS_CFG_Q_EN > 0u
  173. OS_QPost((OS_Q *)p_obj,
  174. (void *)p_void,
  175. (OS_MSG_SIZE)msg_size,
  176. (OS_OPT )opt,
  177. (CPU_TS )ts,
  178. (OS_ERR *)&err);
  179. #endif
  180. break;
  181. case OS_OBJ_TYPE_SEM:
  182. #if OS_CFG_SEM_EN > 0u
  183. (void)OS_SemPost((OS_SEM *)p_obj,
  184. (OS_OPT )opt,
  185. (CPU_TS )ts,
  186. (OS_ERR *)&err);
  187. #endif
  188. break;
  189. case OS_OBJ_TYPE_TASK_MSG:
  190. #if OS_CFG_TASK_Q_EN > 0u
  191. OS_TaskQPost((OS_TCB *)p_obj,
  192. (void *)p_void,
  193. (OS_MSG_SIZE)msg_size,
  194. (OS_OPT )opt,
  195. (CPU_TS )ts,
  196. (OS_ERR *)&err);
  197. #endif
  198. break;
  199. case OS_OBJ_TYPE_TASK_SIGNAL:
  200. (void)OS_TaskSemPost((OS_TCB *)p_obj,
  201. (OS_OPT )opt,
  202. (CPU_TS )ts,
  203. (OS_ERR *)&err);
  204. break;
  205. case OS_OBJ_TYPE_TICK:
  206. #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
  207. OS_SchedRoundRobin(&OSRdyList[OSPrioSaved]);
  208. #endif
  209. (void)OS_TaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
  210. (OS_OPT )OS_OPT_POST_NONE,
  211. (CPU_TS )ts,
  212. (OS_ERR *)&err);
  213. #if OS_CFG_TMR_EN > 0u
  214. OSTmrUpdateCtr--;
  215. if (OSTmrUpdateCtr == (OS_CTR)0u) {
  216. OSTmrUpdateCtr = OSTmrUpdateCnt;
  217. ts = OS_TS_GET(); /* Get timestamp */
  218. (void)OS_TaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
  219. (OS_OPT )OS_OPT_POST_NONE,
  220. (CPU_TS )ts,
  221. (OS_ERR *)&err);
  222. }
  223. #endif
  224. break;
  225. default:
  226. break;
  227. }
  228. }
  229. /*$PAGE*/
  230. /*
  231. ************************************************************************************************************************
  232. * INTERRUPT QUEUE MANAGEMENT TASK
  233. *
  234. * Description: This task is created by OS_IntQTaskInit().
  235. *
  236. * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
  237. * the argument is not used and will be a NULL pointer.
  238. *
  239. * Returns : none
  240. ************************************************************************************************************************
  241. */
  242. void OS_IntQTask (void *p_arg)
  243. {
  244. CPU_BOOLEAN done;
  245. CPU_TS ts_start;
  246. CPU_TS ts_end;
  247. CPU_SR_ALLOC();
  248. p_arg = p_arg; /* Not using 'p_arg', prevent compiler warning */
  249. while (DEF_ON) {
  250. done = DEF_FALSE;
  251. while (done == DEF_FALSE) {
  252. if (OSIntQNbrEntries == (OS_OBJ_QTY)0u) {
  253. CPU_CRITICAL_ENTER();
  254. OSRdyList[0].NbrEntries = (OS_OBJ_QTY)0u; /* Remove from ready list */
  255. OSRdyList[0].HeadPtr = (OS_TCB *)0;
  256. OSRdyList[0].TailPtr = (OS_TCB *)0;
  257. OS_PrioRemove(0u); /* Remove from the priority table */
  258. CPU_CRITICAL_EXIT();
  259. OSSched();
  260. done = DEF_TRUE; /* No more entries in the queue, we are done */
  261. } else {
  262. ts_start = OS_TS_GET();
  263. OS_IntQRePost();
  264. ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
  265. if (ts_end > OSIntQTaskTimeMax) {
  266. OSIntQTaskTimeMax = ts_end;
  267. }
  268. CPU_CRITICAL_ENTER();
  269. OSIntQNbrEntries--;
  270. CPU_CRITICAL_EXIT();
  271. }
  272. }
  273. }
  274. }
  275. /*$PAGE*/
  276. /*
  277. ************************************************************************************************************************
  278. * INITIALIZE THE ISR QUEUE
  279. *
  280. * Description: This function is called by OSInit() to initialize the ISR queue.
  281. *
  282. * Arguments : p_err is a pointer to a variable that will contain an error code returned by this function.
  283. *
  284. * OS_ERR_INT_Q If you didn't provide an ISR queue in OS_CFG.C
  285. * OS_ERR_INT_Q_SIZE If you didn't specify a large enough ISR queue.
  286. * OS_ERR_STK_INVALID If you specified a NULL pointer for the task of the ISR task
  287. * handler
  288. * OS_ERR_STK_SIZE_INVALID If you didn't specify a stack size greater than the minimum
  289. * specified by OS_CFG_STK_SIZE_MIN
  290. * OS_ERR_??? An error code returned by OSTaskCreate().
  291. *
  292. * Returns : none
  293. *
  294. * Note(s) : none
  295. ************************************************************************************************************************
  296. */
  297. void OS_IntQTaskInit (OS_ERR *p_err)
  298. {
  299. OS_INT_Q *p_int_q;
  300. OS_INT_Q *p_int_q_next;
  301. OS_OBJ_QTY i;
  302. #ifdef OS_SAFETY_CRITICAL
  303. if (p_err == (OS_ERR *)0) {
  304. OS_SAFETY_CRITICAL_EXCEPTION();
  305. return;
  306. }
  307. #endif
  308. OSIntQOvfCtr = (OS_QTY)0u; /* Clear the ISR queue overflow counter */
  309. if (OSCfg_IntQBasePtr == (OS_INT_Q *)0) {
  310. *p_err = OS_ERR_INT_Q;
  311. return;
  312. }
  313. if (OSCfg_IntQSize < (OS_OBJ_QTY)2u) {
  314. *p_err = OS_ERR_INT_Q_SIZE;
  315. return;
  316. }
  317. OSIntQTaskTimeMax = (CPU_TS)0;
  318. p_int_q = OSCfg_IntQBasePtr; /* Initialize the circular ISR queue */
  319. p_int_q_next = p_int_q;
  320. p_int_q_next++;
  321. for (i = 0u; i < OSCfg_IntQSize; i++) {
  322. p_int_q->Type = OS_OBJ_TYPE_NONE;
  323. p_int_q->ObjPtr = (void *)0;
  324. p_int_q->MsgPtr = (void *)0;
  325. p_int_q->MsgSize = (OS_MSG_SIZE)0u;
  326. p_int_q->Flags = (OS_FLAGS )0u;
  327. p_int_q->Opt = (OS_OPT )0u;
  328. p_int_q->NextPtr = p_int_q_next;
  329. p_int_q++;
  330. p_int_q_next++;
  331. }
  332. p_int_q--;
  333. p_int_q_next = OSCfg_IntQBasePtr;
  334. p_int_q->NextPtr = p_int_q_next;
  335. OSIntQInPtr = p_int_q_next;
  336. OSIntQOutPtr = p_int_q_next;
  337. OSIntQNbrEntries = (OS_OBJ_QTY)0u;
  338. OSIntQMaxNbrEntries = (OS_OBJ_QTY)0u;
  339. /* -------------- CREATE THE ISR QUEUE TASK ------------- */
  340. if (OSCfg_IntQTaskStkBasePtr == (CPU_STK *)0) {
  341. *p_err = OS_ERR_STK_INVALID;
  342. return;
  343. }
  344. if (OSCfg_IntQTaskStkSize < OSCfg_StkSizeMin) {
  345. *p_err = OS_ERR_STK_SIZE_INVALID;
  346. return;
  347. }
  348. OSTaskCreate((OS_TCB *)&OSIntQTaskTCB,
  349. (CPU_CHAR *)((void *)"uC/OS-III ISR Queue Task"),
  350. (OS_TASK_PTR )OS_IntQTask,
  351. (void *)0,
  352. (OS_PRIO )0u, /* This task is ALWAYS at priority '0' (i.e. highest) */
  353. (CPU_STK *)OSCfg_IntQTaskStkBasePtr,
  354. (CPU_STK_SIZE)OSCfg_IntQTaskStkLimit,
  355. (CPU_STK_SIZE)OSCfg_IntQTaskStkSize,
  356. (OS_MSG_QTY )0u,
  357. (OS_TICK )0u,
  358. (void *)0,
  359. (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
  360. (OS_ERR *)p_err);
  361. }
  362. #endif