]> rtime.felk.cvut.cz Git - arc.git/blob - system/kernel/counter.c
Again, loads of refactoring and removing and adding files.
[arc.git] / system / kernel / counter.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16 #include <assert.h>
17 #include <stdlib.h>
18 #include "Os.h"
19 #include "internal.h"
20 #include "arc.h"
21 \r
22 #define COUNTER_STD_END         \\r
23                 goto ok;                \\r
24         err:                            \\r
25                 ERRORHOOK(rv);  \\r
26         ok:                                     \\r
27                 return rv;\r
28 \r
29 \r
30 /* Accessor functions */
31 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )\r
32 static inline OsSchTblAdjExpPointType *getAdjExpPoint( OsSchTblType *stblPtr ) {\r
33         return &stblPtr->adjExpPoint;\r
34 }
35 #endif
36 \r
37 \r
38 static inline struct OsSchTblAutostart *getAutoStart( OsSchTblType *stblPtr ) {\r
39         return &stblPtr->autostart;\r
40 }\r
41
42 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )\r
43 static inline struct OsScheduleTableSync *getSync( OsSchTblType *stblPtr ) {\r
44         return &stblPtr->sync;\r
45 }\r
46 #endif\r
47
48 \r
49 /**\r
50  *
51  * @param a_obj
52  */\r
53 static void AlarmProcess( OsAlarmType *a_obj ) {\r
54         if( a_obj->cycletime == 0 ) {\r
55                 a_obj->active = 0;\r
56         } else {\r
57                 // Calc new expire value..\r
58                 a_obj->expire_val = Os_CounterCalcModulo( a_obj->expire_val,\r
59                                                                                         Os_CounterGetMaxValue(a_obj->counter),\r
60                                                                                         a_obj->cycletime);\r
61         }\r
62 }\r
63 \r
64 static void check_alarms( OsCounterType *c_p ) {\r
65         OsAlarmType *a_obj;\r
66 \r
67         SLIST_FOREACH(a_obj,&c_p->alarm_head,alarm_list) {\r
68                 if( a_obj->active && (c_p->val == a_obj->expire_val) ) {\r
69                         /* Check if the alarms have expired */\r
70                         os_isr_printf(D_ALARM,"expired %s id:%d val:%d\n",\r
71                                                                                         a_obj->name,\r
72                                                                                         a_obj->counter_id,\r
73                                                                                         a_obj->expire_val);\r
74 \r
75                         switch( a_obj->action.type ) {\r
76                         case ALARM_ACTION_ACTIVATETASK:\r
77                                 if( ActivateTask(a_obj->action.task_id) != E_OK ) {
78                                         /* We actually do thing here, See 0S321 */\r
79                                 }\r
80                                 AlarmProcess(a_obj);\r
81                                 break;\r
82                         case ALARM_ACTION_SETEVENT:\r
83                                 if( SetEvent(a_obj->action.task_id,a_obj->action.event_id) != E_OK ) {\r
84                                         // TODO: Check what to do here..\r
85                                         assert(0);\r
86                                 }\r
87                                 AlarmProcess(a_obj);\r
88                                 break;\r
89                         case ALARM_ACTION_ALARMCALLBACK:\r
90                                 /* TODO: not done */\r
91                                 break;
92 \r
93                         case ALARM_ACTION_INCREMENTCOUNTER:
94                                 /** @req OS301 */\r
95                                 /* Huh,, recursive....*/\r
96                                 IncrementCounter(a_obj->action.counter_id);\r
97                                 break;\r
98                         default:\r
99                                 assert(0);\r
100                         }\r
101                 }\r
102         }\r
103 }\r
104 \r
105 /**\r
106  * Go through the schedule tables connected to this counter\r
107  *
108  * @param c_p Pointer to counter object
109  */\r
110
111 /** @req OS002 */
112 /** @req OS007 */
113 static void check_stbl(OsCounterType *c_p) {
114         OsSchTblType *sched_obj;\r
115 \r
116         /* Iterate through the schedule tables */\r
117         SLIST_FOREACH(sched_obj,&c_p->sched_head,sched_list) {\r
118 \r
119                 if( sched_obj->state == SCHEDULETABLE_STOPPED ) {\r
120                         continue;\r
121                 }\r
122
123 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )\r
124                 if( sched_obj->sync.syncStrategy == IMPLICIT ) {\r
125                         // ....\r
126 \r
127                 } else {\r
128                         int adj;\r
129                         // Handle EXPLICIT\r
130                         if( sched_obj->sync.deviation > 0 ) {\r
131                                 // The sync counter was set back ==\r
132                                 // we have more time to complete the table\r
133                                 adj = MIN(sched_obj->sync.deviation, getAdjExpPoint(sched_obj)->maxAdvance );\r
134                                 sched_obj->sync.deviation -= adj;\r
135 \r
136                         } else if( sched_obj->sync.deviation < 0 ) {\r
137                                 // The sync counter was set forward ==\r
138                                 // we have less time to complete the table\r
139                                 adj = MIN((-sched_obj->sync.deviation), getAdjExpPoint(sched_obj)->maxRetard);\r
140                                 sched_obj->sync.deviation -= adj;\r
141 \r
142                         } else {\r
143                                 // all is well\r
144                                 sched_obj->state = SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS;\r
145                         }\r
146                 }\r
147 #endif
148 \r
149                 /* Check if the expire point have been hit */\r
150                 if( (sched_obj->state == SCHEDULETABLE_RUNNING ||\r
151                                 SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS ) &&\r
152                                 (c_p->val >= sched_obj->expire_val) )
153                 {\r
154                         OsScheduleTableActionType * action;\r
155 \r
156                         action = SA_LIST_GET(&sched_obj->action_list,sched_obj->expire_curr_index);\r
157 \r
158                         switch( action->type ) {
159                         case SCHEDULE_ACTION_ACTIVATETASK:
160                                 ActivateTask(action->task_id);
161                                 break;
162
163                         case SCHEDULE_ACTION_SETEVENT:
164                                 SetEvent( action->task_id, action->event_id);
165                                 break;
166
167                         default:
168                                 /** @req OS407 */
169                                 assert(0);
170                 }\r
171                         // Calc new expire val\r
172                         Os_SchTblCalcExpire(sched_obj);\r
173                 }\r
174 \r
175         }\r
176 }\r
177 \r
178 \r
179 /**\r
180  * Increment a counter. Checks for wraps.\r
181  *
182  * @param counter Ptr to a counter object
183  */\r
184 static void IncCounter( OsCounterType *counter ) {\r
185         // Check for wrap of type\r
186         if( (counter->val+1) < (counter->val) ) {\r
187                 counter->val = 0;               // This wraps\r
188         } else {\r
189                 if( counter->val > counter->alarm_base.maxallowedvalue ) {\r
190                         counter->val = 0;\r
191                 } else {\r
192                         counter->val++;\r
193                 }\r
194         }\r
195 }\r
196
197
198 #define IsCounterValid(_counterId)   ((_counterId) <= Oil_GetCounterCnt())
199 \r
200 /**\r
201  *
202  * @param counter_id
203  * @return
204  */\r
205
206 /** @req OS399 */\r
207 StatusType IncrementCounter( CounterType counter_id ) {\r
208         StatusType rv = E_OK;\r
209         OsCounterType *counter;\r
210         counter = Oil_GetCounter(counter_id);
211
212         /** @req OS376 */
213         if( !IsCounterValid(counter_id) ) {
214                 rv = E_OS_ID;
215                 goto err;
216         }\r
217 \r
218         /* Check param */\r
219         /** @req OS285 */\r
220         if( ( counter->type != COUNTER_TYPE_SOFT ) ||\r
221                 ( counter_id >= Oil_GetCounterCnt() ) ) {\r
222                 rv =  E_OS_ID;\r
223                 goto err;\r
224         }\r
225
226         /** @req OS286 */\r
227         IncCounter(counter);\r
228 \r
229         check_alarms(counter);\r
230         check_stbl(counter);\r
231
232         /** @req OS321 */\r
233         COUNTER_STD_END;\r
234 }\r
235 \r
236 \r
237 StatusType GetCounterValue( CounterType counter_id , TickRefType tick_ref)\r
238 {
239         StatusType rv = E_OK;\r
240         OsCounterType *cPtr;\r
241         cPtr = Oil_GetCounter(counter_id);
242
243         /** @req OS376 */
244         if( !IsCounterValid(counter_id) ) {
245                 rv = E_OS_ID;
246                 goto err;
247         }
248
249         /** @req OS377 */
250         if( cPtr->type == COUNTER_TYPE_HARD ) {
251                 if( cPtr->driver == NULL ) {
252                         /* It's OSINTERNAL */
253                         *tick_ref = os_sys.tick;
254                 } else {
255 #if 0
256                 /* We support only GPT for now */
257                 *tick_ref  = (TickType)Gpt_GetTimeElapsed(cPtr->driver.OsGptChannelRef);
258 #endif
259
260                 }
261         } else {
262                 *tick_ref = cPtr->val;
263         }
264 \r
265         COUNTER_STD_END;
266 }\r
267 \r
268 StatusType GetElapsedCounterValue( CounterType counter_id, TickRefType val, TickRefType elapsed_val)\r
269 {
270         StatusType rv = E_OK;\r
271         OsCounterType *cPtr;
272         TickType tick;
273
274         cPtr = Oil_GetCounter(counter_id);
275
276         /** @req OS381 */
277         if( !IsCounterValid(counter_id) ) {
278                 rv = E_OS_ID;
279                 goto err;
280         }
281
282         /** @req OS391 */
283         if( *val > Os_CounterGetMaxValue(cPtr) ) {
284                 rv = E_OS_VALUE;
285                 goto err;
286         }
287
288         GetCounterValue(counter_id,&tick);
289
290 #warning missing....OS382
291
292         COUNTER_STD_END;
293 }\r
294 \r
295 /*\r
296  * The OsTick():\r
297  * 1. The Decrementer is setup by Frt_Start(period_ticks)\r
298  * 2. Frt_Init() setup INTC[7] to trigger OsTick\r
299  * 3. OsTick() then increment counter os_tick_counter if used
300  */\r
301 \r
302 /*\r
303  * Non-Autosar stuff\r
304  */\r
305
306 /* The id of the counter driven by the os tick, or -1 if not used.
307  * Using weak linking to set default value -1 if not set by config.
308  */
309 CounterType Os_Arc_OsTickCounter __attribute__((weak)) = -1;
310 \r
311 void OsTick( void ) {
312         // if not used, os_tick_counter < 0
313         if (Os_Arc_OsTickCounter >= 0) {
314
315                 OsCounterType *c_p = Oil_GetCounter(Os_Arc_OsTickCounter);
316
317                 os_sys.tick++;
318
319                 IncCounter(c_p);
320
321         //      os_sys.tick = c_p->val;
322
323                 check_alarms(c_p);
324                 check_stbl(c_p);
325         }
326 }\r
327 \r
328 TickType GetOsTick( void ) {\r
329         return get_os_tick();\r
330 }\r
331 \r