]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/alarm.c
Initial commit of changes to add applications. Nothing works....
[arc.git] / system / kernel / alarm.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 #include <assert.h>\r
17 #include <stdlib.h>\r
18 #include "Os.h"\r
19 #include "internal.h"\r
20 \r
21 \r
22 #define COUNTER_MAX(x)                  (x)->counter->alarm_base.maxallowedvalue\r
23 #define COUNTER_MIN_CYCLE(x)    (x)->counter->alarm_base.mincycle\r
24 #define ALARM_CHECK_ID(x)                               \\r
25         if( (x) > OS_ALARM_CNT) { \\r
26                 rv = E_OS_ID;                                   \\r
27                 goto err;                                               \\r
28         }\r
29 \r
30 \r
31 /**\r
32  * The system service  GetAlarmBase  reads the alarm base\r
33  * characteristics. The return value <Info> is a structure in which\r
34  * the information of data type AlarmBaseType is stored.\r
35  *\r
36  * @param alarm_id  Reference to alarm\r
37  * @param info Reference to structure with constants of the alarm base.\r
38  * @return\r
39  */\r
40 StatusType GetAlarmBase( AlarmType AlarmId, AlarmBaseRefType Info ) {\r
41     StatusType rv = Os_CfgGetAlarmBase(AlarmId,Info);\r
42     if (rv != E_OK) {\r
43         goto err;\r
44     }\r
45     OS_STD_END_2(OSServiceId_GetAlarmBase,AlarmId, Info);\r
46 }\r
47 \r
48 \r
49 /**\r
50  * The system service GetAlarm returns the relative value in ticks\r
51  * before the alarm <AlarmID> expires.\r
52 \r
53  * @param AlarmId       Reference to an alarm\r
54  * @param Tick[out]     Relative value in ticks before the alarm <AlarmID> expires.\r
55  * @return\r
56  */\r
57 StatusType GetAlarm(AlarmType AlarmId, TickRefType Tick) {\r
58     StatusType rv = E_OK;\r
59     OsAlarmType *aPtr;\r
60     long flags;\r
61 \r
62     ALARM_CHECK_ID(AlarmId);\r
63     aPtr = Os_CfgGetAlarmObj(AlarmId);\r
64 \r
65         Irq_Save(flags);\r
66         if( aPtr->active == 0 ) {\r
67                 rv = E_OS_NOFUNC;\r
68                 Irq_Restore(flags);\r
69                 goto err;\r
70         }\r
71 \r
72         *Tick = Os_CounterDiff(         aPtr->expire_val,\r
73                                                                 Os_CounterGetValue(aPtr->counter),\r
74                                                                 Os_CounterGetMaxValue(aPtr->counter) );\r
75 \r
76         Irq_Restore(flags);\r
77 \r
78         OS_STD_END_2(OSServiceId_GetAlarm,AlarmId, Tick);\r
79 }\r
80 \r
81 \r
82 \r
83 \r
84 /**\r
85  * The system service occupies the alarm <AlarmID> element.\r
86  * After <increment> ticks have elapsed, the task assigned to the\r
87  * alarm <AlarmID> is activated or the assigned event (only for\r
88  * extended tasks) is set or the alarm-callback routine is called.\r
89  *\r
90  * @param alarm_id Reference to the alarm element\r
91  * @param increment Relative value in ticks\r
92  * @param cycle Cycle value in case of cyclic alarm. In case of single alarms, cycle shall be zero.\r
93  * @return\r
94  */\r
95 \r
96 StatusType SetRelAlarm(AlarmType AlarmId, TickType Increment, TickType Cycle){\r
97         StatusType rv = E_OK;\r
98         OsAlarmType *aPtr;\r
99 \r
100         ALARM_CHECK_ID(AlarmId);\r
101 \r
102         aPtr = Os_CfgGetAlarmObj(AlarmId);\r
103 \r
104         OS_DEBUG(D_ALARM,"SetRelAlarm id:%d inc:%u cycle:%u\n",\r
105                                         AlarmId,\r
106                                         (unsigned)Increment,\r
107                                         (unsigned)Cycle);\r
108 \r
109 \r
110         if( (Increment == 0) || (Increment > COUNTER_MAX(aPtr)) ) {\r
111                 /** @req OS304 */\r
112                 rv =  E_OS_VALUE;\r
113                 goto err;\r
114         } else {\r
115                 if( Cycle != 0 &&\r
116                         ( (Cycle < COUNTER_MIN_CYCLE(aPtr)) ||\r
117                           (Cycle > COUNTER_MAX(aPtr)) ) ) {\r
118                         /** @req OS304 */\r
119                         rv =  E_OS_VALUE;\r
120                         goto err;\r
121                 }\r
122         }\r
123 \r
124         {\r
125                 Irq_Disable();\r
126                 if( aPtr->active == 1 ) {\r
127                         Irq_Enable();\r
128                         rv = E_OS_STATE;\r
129                         goto err;\r
130                 }\r
131 \r
132                 aPtr->active = 1;\r
133 \r
134                 aPtr->expire_val = Os_CounterAdd(\r
135                                                                 Os_CounterGetValue(aPtr->counter),\r
136                                                                 COUNTER_MAX(aPtr),\r
137                                                                 Increment);\r
138                 aPtr->cycletime = Cycle;\r
139 \r
140                 Irq_Enable();\r
141                 OS_DEBUG(D_ALARM,"  expire:%u cycle:%u\n",\r
142                                 (unsigned)aPtr->expire_val,\r
143                                 (unsigned)aPtr->cycletime);\r
144         }\r
145 \r
146         OS_STD_END_3(OSServiceId_SetRelAlarm,AlarmId, Increment, Cycle);\r
147 }\r
148
149 /**
150  * The  system  service  occupies  the  alarm  <AlarmID>  element.
151  * When <start> ticks are reached, the task assigned to the alarm
152  *
153  * If the absolute value <start> is very close to the current counter
154  * value, the alarm may expire, and the task may become ready or
155  * the  alarm-callback  may  be  called  before  the  system  service
156  * returns to the user.
157  * If  the  absolute  value  <start>  already  was  reached  before  the
158  * system call, the alarm shall only expire when the absolute value
159  * <start>  is  reached  again,  i.e.  after  the  next  overrun  of  the
160  * counter.
161  *
162  * If <cycle> is unequal zero, the alarm element is logged on again
163  * immediately after expiry with the relative value <cycle>.
164  *
165  * The alarm <AlarmID> shall not already be in use.
166  * To  change  values  of  alarms  already  in  use  the  alarm  shall  be
167  * cancelled first.
168  *
169  * If  the  alarm  is  already  in  use,  this  call  will  be  ignored  and  the
170  * error E_OS_STATE is returned.
171  *
172  * Allowed on task level and in ISR, but not in hook routines.
173  *
174  * @param AlarmId
175  * @param Start
176  * @param Cycle
177  * @return
178  */
179 \r
180 StatusType SetAbsAlarm(AlarmType AlarmId, TickType Start, TickType Cycle) {\r
181 \r
182         OsAlarmType *aPtr;\r
183         long flags;\r
184         StatusType rv = E_OK;\r
185 \r
186         ALARM_CHECK_ID(AlarmId);\r
187 \r
188         aPtr = Os_CfgGetAlarmObj(AlarmId);\r
189 \r
190         if( Start > COUNTER_MAX(aPtr) ) {\r
191                 /** @req OS304 */\r
192                 rv =  E_OS_VALUE;\r
193                 goto err;\r
194         }\r
195 \r
196         if( Cycle != 0 &&\r
197                 ( (Cycle < COUNTER_MIN_CYCLE(aPtr)) ||\r
198                   (Cycle > COUNTER_MAX(aPtr)) ) ) {\r
199                 /** @req OS304 */\r
200                 rv =  E_OS_VALUE;\r
201                 goto err;\r
202         }\r
203 \r
204         Irq_Save(flags);\r
205         if( aPtr->active == 1 ) {\r
206                 rv = E_OS_STATE;
207                 Irq_Restore(flags);\r
208                 goto err;\r
209         }\r
210 \r
211         aPtr->active = 1;\r
212 \r
213         aPtr->expire_val = Start;\r
214         aPtr->cycletime = Cycle;\r
215 \r
216         Irq_Restore(flags);\r
217 \r
218         OS_DEBUG(D_ALARM,"  expire:%u cycle:%u\n",\r
219                                         (unsigned)aPtr->expire_val,\r
220                                         (unsigned)aPtr->cycletime);\r
221 \r
222         OS_STD_END_3(OSServiceId_SetAbsAlarm,AlarmId, Start, Cycle);\r
223 }\r
224 \r
225 StatusType CancelAlarm(AlarmType AlarmId) {\r
226         StatusType rv = E_OK;\r
227         OsAlarmType *aPtr;\r
228         long flags;\r
229 \r
230         ALARM_CHECK_ID(AlarmId);\r
231 \r
232         aPtr = Os_CfgGetAlarmObj(AlarmId);\r
233 \r
234         Irq_Save(flags);\r
235         if( aPtr->active == 0 ) {\r
236                 rv = E_OS_NOFUNC;\r
237                 Irq_Restore(flags);\r
238                 goto err;\r
239         }\r
240 \r
241         aPtr->active = 0;\r
242 \r
243         Irq_Restore(flags);\r
244 \r
245         OS_STD_END_1(OSServiceId_CancelAlarm,AlarmId);\r
246 }\r
247 \r
248 \r
249 \r
250 /**\r
251  *\r
252  * @param a_obj\r
253  */\r
254 static void AlarmProcess( OsAlarmType *aPtr ) {\r
255         if( aPtr->cycletime == 0 ) {\r
256                 aPtr->active = 0;\r
257         } else {\r
258                 // Calc new expire value..\r
259                 aPtr->expire_val = Os_CounterAdd( Os_CounterGetValue(aPtr->counter),\r
260                                                                                         Os_CounterGetMaxValue(aPtr->counter),\r
261                                                                                         aPtr->cycletime);\r
262         }\r
263 }\r
264 \r
265 void Os_AlarmCheck( OsCounterType *c_p ) {\r
266         OsAlarmType *a_obj;\r
267         StatusType rv;\r
268 \r
269         SLIST_FOREACH(a_obj,&c_p->alarm_head,alarm_list) {\r
270                 if( a_obj->active && (c_p->val == a_obj->expire_val) ) {\r
271                         /* Check if the alarms have expired */\r
272                         OS_DEBUG(D_ALARM,"expired %s id:%u val:%u\n",\r
273                                                                                         a_obj->name,\r
274                                                                                         (unsigned)a_obj->counter_id,\r
275                                                                                         (unsigned)a_obj->expire_val);\r
276 \r
277                         switch( a_obj->action.type ) {\r
278                         case ALARM_ACTION_ACTIVATETASK:\r
279                                 if( ActivateTask(a_obj->action.task_id) != E_OK ) {\r
280                                         /* We actually do thing here, See 0S321 */\r
281                                 }\r
282                                 AlarmProcess(a_obj);\r
283                                 break;\r
284                         case ALARM_ACTION_SETEVENT:\r
285                                 rv =  SetEvent(a_obj->action.task_id,a_obj->action.event_id);\r
286                                 if( rv != E_OK ) {\r
287                                         ERRORHOOK(rv);\r
288                                 }\r
289                                 AlarmProcess(a_obj);\r
290                                 break;\r
291                         case ALARM_ACTION_ALARMCALLBACK:\r
292                                 /* TODO: not done */\r
293                                 break;\r
294 \r
295                         case ALARM_ACTION_INCREMENTCOUNTER:\r
296                                 /** @req OS301 */\r
297                                 /* Huh,, recursive....*/\r
298                                 IncrementCounter(a_obj->action.counter_id);\r
299                                 break;\r
300                         default:\r
301                                 assert(0);\r
302                         }\r
303                 }\r
304         }\r
305 }\r
306 \r
307 void Os_AlarmAutostart(void) {\r
308         int j;\r
309         for (j = 0; j < OS_ALARM_CNT; j++) {\r
310                 OsAlarmType *alarmPtr;\r
311                 alarmPtr = Os_CfgGetAlarmObj(j);\r
312                 if (alarmPtr->autostartPtr != NULL) {\r
313                         const OsAlarmAutostartType *autoPtr = alarmPtr->autostartPtr;\r
314 \r
315                         if (Os_Sys.appMode & autoPtr->appModeRef) {\r
316                                 if (autoPtr->autostartType == ALARM_AUTOSTART_ABSOLUTE) {\r
317                                         SetAbsAlarm(j, autoPtr->alarmTime, autoPtr->cycleTime);\r
318                                 } else {\r
319                                         SetRelAlarm(j, autoPtr->alarmTime, autoPtr->cycleTime);\r
320                                 }\r
321                         }\r
322                 }\r
323         }\r
324 }\r
325 \r
326 \r
327 \r