| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_int.c
Go to the documentation of this file.
1 /*
2 ************************************************************************************************************************
3 * uC/OS-III
4 * The Real-Time Kernel
5 *
6 * (c) Copyright 2009-2012; 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.03.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
33 #define MICRIUM_SOURCE
34 #include <os.h>
35
36 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
37 const CPU_CHAR *os_int__c = "$Id: $";
38 #endif
39
40
41 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
42 /*$PAGE*/
43 /*
44 ************************************************************************************************************************
45 * POST TO ISR QUEUE
46 *
47 * Description: This function places contents of posts into an intermediate queue to help defer processing of interrupts
48 * at the task level.
49 *
50 * Arguments : type is the type of kernel object the post is destined to:
51 *
52 * OS_OBJ_TYPE_SEM
53 * OS_OBJ_TYPE_Q
54 * OS_OBJ_TYPE_FLAG
55 * OS_OBJ_TYPE_TASK_MSG
56 * OS_OBJ_TYPE_TASK_SIGNAL
57 *
58 * p_obj is a pointer to the kernel object to post to. This can be a pointer to a semaphore,
59 * ----- a message queue or a task control clock.
60 *
61 * p_void is a pointer to a message that is being posted. This is used when posting to a message
62 * queue or directly to a task.
63 *
64 * msg_size is the size of the message being posted
65 *
66 * flags if the post is done to an event flag group then this corresponds to the flags being
67 * posted
68 *
69 * ts is a timestamp as to when the post was done
70 *
71 * opt this corresponds to post options and applies to:
72 *
73 * OSFlagPost()
74 * OSSemPost()
75 * OSQPost()
76 * OSTaskQPost()
77 *
78 * p_err is a pointer to a variable that will contain an error code returned by this function.
79 *
80 * OS_ERR_NONE if the post to the ISR queue was successful
81 * OS_ERR_INT_Q_FULL if the ISR queue is full and cannot accepts any further posts. This
82 * generally indicates that you are receiving interrupts faster than you
83 * can process them or, that you didn't make the ISR queue large enough.
84 *
85 * Returns : none
86 *
87 * Note(s) : none
88 ************************************************************************************************************************
89 */
90
91 void OS_IntQPost (OS_OBJ_TYPE type,
92 void *p_obj,
93 void *p_void,
94 OS_MSG_SIZE msg_size,
95 OS_FLAGS flags,
96 OS_OPT opt,
97 CPU_TS ts,
98 OS_ERR *p_err)
99 {
100 CPU_SR_ALLOC();
101
102
103
104 #ifdef OS_SAFETY_CRITICAL
105 if (p_err == (OS_ERR *)0) {
106 OS_SAFETY_CRITICAL_EXCEPTION();
107 return;
108 }
109 #endif
110
111 CPU_CRITICAL_ENTER();
112 if (OSIntQNbrEntries < OSCfg_IntQSize) { /* Make sure we haven't already filled the ISR queue */
113 OSIntQNbrEntries++;
114
115 if (OSIntQNbrEntriesMax < OSIntQNbrEntries) {
116 OSIntQNbrEntriesMax = OSIntQNbrEntries;
117 }
118
119 OSIntQInPtr->Type = type; /* Save object type being posted */
120 OSIntQInPtr->ObjPtr = p_obj; /* Save pointer to object being posted */
121 OSIntQInPtr->MsgPtr = p_void; /* Save pointer to message if posting to a message queue */
122 OSIntQInPtr->MsgSize = msg_size; /* Save the message size if posting to a message queue */
123 OSIntQInPtr->Flags = flags; /* Save the flags if posting to an event flag group */
124 OSIntQInPtr->Opt = opt; /* Save post options */
125 OSIntQInPtr->TS = ts; /* Save time stamp */
126
127 OSIntQInPtr = OSIntQInPtr->NextPtr; /* Point to the next interrupt handler queue entry */
128
129 OSRdyList[0].NbrEntries = (OS_OBJ_QTY)1; /* Make the interrupt handler task ready to run */
130 OSRdyList[0].HeadPtr = &OSIntQTaskTCB;
131 OSRdyList[0].TailPtr = &OSIntQTaskTCB;
132 OS_PrioInsert(0u); /* Add task priority 0 in the priority table */
133 if (OSPrioCur != 0) { /* Chk if OSIntQTask is not running */
134 OSPrioSaved = OSPrioCur; /* Save current priority */
135 }
136
137 *p_err = OS_ERR_NONE;
138 } else {
139 OSIntQOvfCtr++; /* Count the number of ISR queue overflows */
140 *p_err = OS_ERR_INT_Q_FULL;
141 }
142 CPU_CRITICAL_EXIT();
143 }
144
145 /*$PAGE*/
146 /*
147 ************************************************************************************************************************
148 * INTERRUPT QUEUE MANAGEMENT TASK
149 *
150 * Description: This task is created by OS_IntQTaskInit().
151 *
152 * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
153 * the argument is not used and will be a NULL pointer.
154 *
155 * Returns : none
156 ************************************************************************************************************************
157 */
158
159 void OS_IntQRePost (void)
160 {
161 CPU_TS ts;
162 OS_ERR err;
163
164
165 switch (OSIntQOutPtr->Type) { /* Re-post to task */
166 case OS_OBJ_TYPE_FLAG:
167 #if OS_CFG_FLAG_EN > 0u
168 (void)OS_FlagPost((OS_FLAG_GRP *) OSIntQOutPtr->ObjPtr,
169 (OS_FLAGS ) OSIntQOutPtr->Flags,
170 (OS_OPT ) OSIntQOutPtr->Opt,
171 (CPU_TS ) OSIntQOutPtr->TS,
172 (OS_ERR *)&err);
173 #endif
174 break;
175
176 case OS_OBJ_TYPE_Q:
177 #if OS_CFG_Q_EN > 0u
178 OS_QPost((OS_Q *) OSIntQOutPtr->ObjPtr,
179 (void *) OSIntQOutPtr->MsgPtr,
180 (OS_MSG_SIZE) OSIntQOutPtr->MsgSize,
181 (OS_OPT ) OSIntQOutPtr->Opt,
182 (CPU_TS ) OSIntQOutPtr->TS,
183 (OS_ERR *)&err);
184 #endif
185 break;
186
187 case OS_OBJ_TYPE_SEM:
188 #if OS_CFG_SEM_EN > 0u
189 (void)OS_SemPost((OS_SEM *) OSIntQOutPtr->ObjPtr,
190 (OS_OPT ) OSIntQOutPtr->Opt,
191 (CPU_TS ) OSIntQOutPtr->TS,
192 (OS_ERR *)&err);
193 #endif
194 break;
195
196 case OS_OBJ_TYPE_TASK_MSG:
197 #if OS_CFG_TASK_Q_EN > 0u
198 OS_TaskQPost((OS_TCB *) OSIntQOutPtr->ObjPtr,
199 (void *) OSIntQOutPtr->MsgPtr,
200 (OS_MSG_SIZE) OSIntQOutPtr->MsgSize,
201 (OS_OPT ) OSIntQOutPtr->Opt,
202 (CPU_TS ) OSIntQOutPtr->TS,
203 (OS_ERR *)&err);
204 #endif
205 break;
206
207 case OS_OBJ_TYPE_TASK_RESUME:
208 #if OS_CFG_TASK_SUSPEND_EN > 0u
209 (void)OS_TaskResume((OS_TCB *) OSIntQOutPtr->ObjPtr,
210 (OS_ERR *)&err);
211 #endif
212 break;
213
214 case OS_OBJ_TYPE_TASK_SIGNAL:
215 (void)OS_TaskSemPost((OS_TCB *) OSIntQOutPtr->ObjPtr,
216 (OS_OPT ) OSIntQOutPtr->Opt,
217 (CPU_TS ) OSIntQOutPtr->TS,
218 (OS_ERR *)&err);
219 break;
220
221 case OS_OBJ_TYPE_TASK_SUSPEND:
222 #if OS_CFG_TASK_SUSPEND_EN > 0u
223 (void)OS_TaskSuspend((OS_TCB *) OSIntQOutPtr->ObjPtr,
224 (OS_ERR *)&err);
225 #endif
226 break;
227
228 case OS_OBJ_TYPE_TICK:
229 #if OS_CFG_SCHED_ROUND_ROBIN_EN > 0u
230 OS_SchedRoundRobin(&OSRdyList[OSPrioSaved]);
231 #endif
232
233 (void)OS_TaskSemPost((OS_TCB *)&OSTickTaskTCB, /* Signal tick task */
234 (OS_OPT ) OS_OPT_POST_NONE,
235 (CPU_TS ) OSIntQOutPtr->TS,
236 (OS_ERR *)&err);
237 #if OS_CFG_TMR_EN > 0u
238 OSTmrUpdateCtr--;
239 if (OSTmrUpdateCtr == (OS_CTR)0u) {
240 OSTmrUpdateCtr = OSTmrUpdateCnt;
241 ts = OS_TS_GET(); /* Get timestamp */
242 (void)OS_TaskSemPost((OS_TCB *)&OSTmrTaskTCB, /* Signal timer task */
243 (OS_OPT ) OS_OPT_POST_NONE,
244 (CPU_TS ) ts,
245 (OS_ERR *)&err);
246 }
247 #endif
248 break;
249
250 default:
251 break;
252 }
253 }
254
255 /*$PAGE*/
256 /*
257 ************************************************************************************************************************
258 * INTERRUPT QUEUE MANAGEMENT TASK
259 *
260 * Description: This task is created by OS_IntQTaskInit().
261 *
262 * Arguments : p_arg is a pointer to an optional argument that is passed during task creation. For this function
263 * the argument is not used and will be a NULL pointer.
264 *
265 * Returns : none
266 ************************************************************************************************************************
267 */
268
269 void OS_IntQTask (void *p_arg)
270 {
271 CPU_BOOLEAN done;
272 CPU_TS ts_start;
273 CPU_TS ts_end;
274 CPU_SR_ALLOC();
275
276
277
278 p_arg = p_arg; /* Not using 'p_arg', prevent compiler warning */
279 while (DEF_ON) {
280 done = DEF_FALSE;
281 while (done == DEF_FALSE) {
282 CPU_CRITICAL_ENTER();
283 if (OSIntQNbrEntries == (OS_OBJ_QTY)0u) {
284 OSRdyList[0].NbrEntries = (OS_OBJ_QTY)0u; /* Remove from ready list */
285 OSRdyList[0].HeadPtr = (OS_TCB *)0;
286 OSRdyList[0].TailPtr = (OS_TCB *)0;
287 OS_PrioRemove(0u); /* Remove from the priority table */
288 CPU_CRITICAL_EXIT();
289 OSSched();
290 done = DEF_TRUE; /* No more entries in the queue, we are done */
291 } else {
292 CPU_CRITICAL_EXIT();
293 ts_start = OS_TS_GET();
294 OS_IntQRePost();
295 ts_end = OS_TS_GET() - ts_start; /* Measure execution time of tick task */
296 if (OSIntQTaskTimeMax < ts_end) {
297 OSIntQTaskTimeMax = ts_end;
298 }
299 CPU_CRITICAL_ENTER();
300 OSIntQOutPtr = OSIntQOutPtr->NextPtr; /* Point to next item in the ISR queue */
301 OSIntQNbrEntries--;
302 CPU_CRITICAL_EXIT();
303 }
304 }
305 }
306 }
307
308 /*$PAGE*/
309 /*
310 ************************************************************************************************************************
311 * INITIALIZE THE ISR QUEUE
312 *
313 * Description: This function is called by OSInit() to initialize the ISR queue.
314 *
315 * Arguments : p_err is a pointer to a variable that will contain an error code returned by this function.
316 *
317 * OS_ERR_INT_Q If you didn't provide an ISR queue in OS_CFG.C
318 * OS_ERR_INT_Q_SIZE If you didn't specify a large enough ISR queue.
319 * OS_ERR_STK_INVALID If you specified a NULL pointer for the task of the ISR task
320 * handler
321 * OS_ERR_STK_SIZE_INVALID If you didn't specify a stack size greater than the minimum
322 * specified by OS_CFG_STK_SIZE_MIN
323 * OS_ERR_??? An error code returned by OSTaskCreate().
324 *
325 * Returns : none
326 *
327 * Note(s) : none
328 ************************************************************************************************************************
329 */
330
331 void OS_IntQTaskInit (OS_ERR *p_err)
332 {
333 OS_INT_Q *p_int_q;
334 OS_INT_Q *p_int_q_next;
335 OS_OBJ_QTY i;
336
337
338
339 #ifdef OS_SAFETY_CRITICAL
340 if (p_err == (OS_ERR *)0) {
341 OS_SAFETY_CRITICAL_EXCEPTION();
342 return;
343 }
344 #endif
345
346 OSIntQOvfCtr = (OS_QTY)0u; /* Clear the ISR queue overflow counter */
347
348 if (OSCfg_IntQBasePtr == (OS_INT_Q *)0) {
349 *p_err = OS_ERR_INT_Q;
350 return;
351 }
352
353 if (OSCfg_IntQSize < (OS_OBJ_QTY)2u) {
354 *p_err = OS_ERR_INT_Q_SIZE;
355 return;
356 }
357
358 OSIntQTaskTimeMax = (CPU_TS)0;
359
360 p_int_q = OSCfg_IntQBasePtr; /* Initialize the circular ISR queue */
361 p_int_q_next = p_int_q;
362 p_int_q_next++;
363 for (i = 0u; i < OSCfg_IntQSize; i++) {
364 p_int_q->Type = OS_OBJ_TYPE_NONE;
365 p_int_q->ObjPtr = (void *)0;
366 p_int_q->MsgPtr = (void *)0;
367 p_int_q->MsgSize = (OS_MSG_SIZE)0u;
368 p_int_q->Flags = (OS_FLAGS )0u;
369 p_int_q->Opt = (OS_OPT )0u;
370 p_int_q->NextPtr = p_int_q_next;
371 p_int_q++;
372 p_int_q_next++;
373 }
374 p_int_q--;
375 p_int_q_next = OSCfg_IntQBasePtr;
376 p_int_q->NextPtr = p_int_q_next;
377 OSIntQInPtr = p_int_q_next;
378 OSIntQOutPtr = p_int_q_next;
379 OSIntQNbrEntries = (OS_OBJ_QTY)0u;
380 OSIntQNbrEntriesMax = (OS_OBJ_QTY)0u;
381
382 /* -------------- CREATE THE ISR QUEUE TASK ------------- */
383 if (OSCfg_IntQTaskStkBasePtr == (CPU_STK *)0) {
384 *p_err = OS_ERR_INT_Q_STK_INVALID;
385 return;
386 }
387
388 if (OSCfg_IntQTaskStkSize < OSCfg_StkSizeMin) {
389 *p_err = OS_ERR_INT_Q_STK_SIZE_INVALID;
390 return;
391 }
392
393 OSTaskCreate((OS_TCB *)&OSIntQTaskTCB,
394 (CPU_CHAR *)((void *)"uC/OS-III ISR Queue Task"),
395 (OS_TASK_PTR )OS_IntQTask,
396 (void *)0,
397 (OS_PRIO )0u, /* This task is ALWAYS at priority '0' (i.e. highest) */
398 (CPU_STK *)OSCfg_IntQTaskStkBasePtr,
399 (CPU_STK_SIZE)OSCfg_IntQTaskStkLimit,
400 (CPU_STK_SIZE)OSCfg_IntQTaskStkSize,
401 (OS_MSG_QTY )0u,
402 (OS_TICK )0u,
403 (void *)0,
404 (OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
405 (OS_ERR *)p_err);
406 }
407
408 #endif