LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 
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  }
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 
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 
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 
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 
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 */
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 */
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) {
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 */
289  OSSched();
290  done = DEF_TRUE; /* No more entries in the queue, we are done */
291  } else {
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  }
300  OSIntQOutPtr = OSIntQOutPtr->NextPtr; /* Point to next item in the ISR queue */
301  OSIntQNbrEntries--;
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 
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) */
401  (OS_MSG_QTY )0u,
402  (OS_TICK )0u,
403  (void *)0,
405  (OS_ERR *)p_err);
406 }
407 
408 #endif