1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
19 #include "application.h"
\r
20 #include "internal.h"
\r
21 #include "alarm_i.h"
\r
24 #if (OS_ALARM_CNT!=0)
\r
25 #define COUNTER_MAX(x) (x)->counter->alarm_base.maxallowedvalue
\r
26 #define COUNTER_MIN_CYCLE(x) (x)->counter->alarm_base.mincycle
\r
27 #define ALARM_CHECK_ID(x) \
\r
28 if( (x) > OS_ALARM_CNT) { \
\r
35 * The system service GetAlarmBase reads the alarm base
\r
36 * characteristics. The return value <Info> is a structure in which
\r
37 * the information of data type AlarmBaseType is stored.
\r
39 * @param alarm_id Reference to alarm
\r
40 * @param info Reference to structure with constants of the alarm base.
\r
43 StatusType GetAlarmBase( AlarmType AlarmId, AlarmBaseRefType Info ) {
\r
44 StatusType rv = Os_AlarmGetBase(AlarmId,Info);
\r
48 OS_STD_END_2(OSServiceId_GetAlarmBase,AlarmId, Info);
\r
53 * The system service GetAlarm returns the relative value in ticks
\r
54 * before the alarm <AlarmID> expires.
\r
56 * @param AlarmId Reference to an alarm
\r
57 * @param Tick[out] Relative value in ticks before the alarm <AlarmID> expires.
\r
60 StatusType GetAlarm(AlarmType AlarmId, TickRefType Tick) {
\r
61 StatusType rv = E_OK;
\r
65 ALARM_CHECK_ID(AlarmId);
\r
66 aPtr = Os_AlarmGet(AlarmId);
\r
69 if( aPtr->active == 0 ) {
\r
75 *Tick = Os_CounterDiff( aPtr->expire_val,
\r
76 Os_CounterGetValue(aPtr->counter),
\r
77 Os_CounterGetMaxValue(aPtr->counter) );
\r
81 OS_STD_END_2(OSServiceId_GetAlarm,AlarmId, Tick);
\r
88 * The system service occupies the alarm <AlarmID> element.
\r
89 * After <increment> ticks have elapsed, the task assigned to the
\r
90 * alarm <AlarmID> is activated or the assigned event (only for
\r
91 * extended tasks) is set or the alarm-callback routine is called.
\r
93 * @param alarm_id Reference to the alarm element
\r
94 * @param increment Relative value in ticks
\r
95 * @param cycle Cycle value in case of cyclic alarm. In case of single alarms, cycle shall be zero.
\r
99 StatusType SetRelAlarm(AlarmType AlarmId, TickType Increment, TickType Cycle){
\r
100 StatusType rv = E_OK;
\r
103 ALARM_CHECK_ID(AlarmId);
\r
105 aPtr = Os_AlarmGet(AlarmId);
\r
107 OS_DEBUG(D_ALARM,"SetRelAlarm id:%d inc:%u cycle:%u\n",
\r
109 (unsigned)Increment,
\r
112 #if (OS_APPLICATION_CNT > 1)
\r
114 rv = Os_ApplHaveAccess( Os_AlarmGet(AlarmId)->accessingApplMask );
\r
121 if( (Increment == 0) || (Increment > COUNTER_MAX(aPtr)) ) {
\r
127 ( (Cycle < COUNTER_MIN_CYCLE(aPtr)) ||
\r
128 (Cycle > COUNTER_MAX(aPtr)) ) ) {
\r
137 if( aPtr->active == 1 ) {
\r
145 aPtr->expire_val = Os_CounterAdd(
\r
146 Os_CounterGetValue(aPtr->counter),
\r
149 aPtr->cycletime = Cycle;
\r
152 OS_DEBUG(D_ALARM," expire:%u cycle:%u\n",
\r
153 (unsigned)aPtr->expire_val,
\r
154 (unsigned)aPtr->cycletime);
\r
157 OS_STD_END_3(OSServiceId_SetRelAlarm,AlarmId, Increment, Cycle);
\r
161 * The system service occupies the alarm <AlarmID> element.
162 * When <start> ticks are reached, the task assigned to the alarm
164 * If the absolute value <start> is very close to the current counter
165 * value, the alarm may expire, and the task may become ready or
166 * the alarm-callback may be called before the system service
167 * returns to the user.
168 * If the absolute value <start> already was reached before the
169 * system call, the alarm shall only expire when the absolute value
170 * <start> is reached again, i.e. after the next overrun of the
173 * If <cycle> is unequal zero, the alarm element is logged on again
174 * immediately after expiry with the relative value <cycle>.
176 * The alarm <AlarmID> shall not already be in use.
177 * To change values of alarms already in use the alarm shall be
180 * If the alarm is already in use, this call will be ignored and the
181 * error E_OS_STATE is returned.
183 * Allowed on task level and in ISR, but not in hook routines.
191 StatusType SetAbsAlarm(AlarmType AlarmId, TickType Start, TickType Cycle) {
\r
195 StatusType rv = E_OK;
\r
197 ALARM_CHECK_ID(AlarmId);
\r
199 aPtr = Os_AlarmGet(AlarmId);
\r
201 #if (OS_APPLICATION_CNT > 1)
\r
203 rv = Os_ApplHaveAccess( aPtr->accessingApplMask );
\r
210 if( Start > COUNTER_MAX(aPtr) ) {
\r
217 ( (Cycle < COUNTER_MIN_CYCLE(aPtr)) ||
\r
218 (Cycle > COUNTER_MAX(aPtr)) ) ) {
\r
225 if( aPtr->active == 1 ) {
\r
227 Irq_Restore(flags);
\r
233 aPtr->expire_val = Start;
\r
234 aPtr->cycletime = Cycle;
\r
236 Irq_Restore(flags);
\r
238 OS_DEBUG(D_ALARM," expire:%u cycle:%u\n",
\r
239 (unsigned)aPtr->expire_val,
\r
240 (unsigned)aPtr->cycletime);
\r
242 OS_STD_END_3(OSServiceId_SetAbsAlarm,AlarmId, Start, Cycle);
\r
245 StatusType CancelAlarm(AlarmType AlarmId) {
\r
246 StatusType rv = E_OK;
\r
250 ALARM_CHECK_ID(AlarmId);
\r
252 aPtr = Os_AlarmGet(AlarmId);
\r
255 if( aPtr->active == 0 ) {
\r
257 Irq_Restore(flags);
\r
263 Irq_Restore(flags);
\r
265 OS_STD_END_1(OSServiceId_CancelAlarm,AlarmId);
\r
274 static void AlarmProcess( OsAlarmType *aPtr ) {
\r
275 if( aPtr->cycletime == 0 ) {
\r
278 // Calc new expire value..
\r
279 aPtr->expire_val = Os_CounterAdd( Os_CounterGetValue(aPtr->counter),
\r
280 Os_CounterGetMaxValue(aPtr->counter),
\r
285 void Os_AlarmCheck( OsCounterType *c_p ) {
\r
286 OsAlarmType *a_obj;
\r
289 SLIST_FOREACH(a_obj,&c_p->alarm_head,alarm_list) {
\r
290 if( a_obj->active && (c_p->val == a_obj->expire_val) ) {
\r
291 /* Check if the alarms have expired */
\r
292 OS_DEBUG(D_ALARM,"expired %s id:%u val:%u\n",
\r
294 (unsigned)a_obj->counter_id,
\r
295 (unsigned)a_obj->expire_val);
\r
297 switch( a_obj->action.type ) {
\r
298 case ALARM_ACTION_ACTIVATETASK:
\r
299 if( ActivateTask(a_obj->action.task_id) != E_OK ) {
\r
300 /* We actually do thing here, See 0S321 */
\r
302 AlarmProcess(a_obj);
\r
304 case ALARM_ACTION_SETEVENT:
\r
305 rv = SetEvent(a_obj->action.task_id,a_obj->action.event_id);
\r
309 AlarmProcess(a_obj);
\r
311 case ALARM_ACTION_ALARMCALLBACK:
\r
312 /* TODO: not done */
\r
315 case ALARM_ACTION_INCREMENTCOUNTER:
\r
317 /* Huh,, recursive....*/
\r
318 IncrementCounter(a_obj->action.counter_id);
\r
327 void Os_AlarmAutostart(void) {
\r
329 for (j = 0; j < OS_ALARM_CNT; j++) {
\r
330 OsAlarmType *alarmPtr;
\r
331 alarmPtr = Os_AlarmGet(j);
\r
332 if (alarmPtr->autostartPtr != NULL) {
\r
333 const OsAlarmAutostartType *autoPtr = alarmPtr->autostartPtr;
\r
335 if (Os_Sys.appMode & autoPtr->appModeRef) {
\r
336 if (autoPtr->autostartType == ALARM_AUTOSTART_ABSOLUTE) {
\r
337 SetAbsAlarm(j, autoPtr->alarmTime, autoPtr->cycleTime);
\r
339 SetRelAlarm(j, autoPtr->alarmTime, autoPtr->cycleTime);
\r