1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
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>.
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
14 * -------------------------------- Arctic Core ------------------------------*/
17 #include "internal.h"
\r
21 * Generic requirements this module can handle
31 * How Autosar sees the scheduletable
\r
35 * accessionApplication
\r
38 * |--- absValue (only if type==ABSOLUTE )
\r
39 * |--- relOffset (only if type==RELATIVE )
\r
40 * |--- type (ABSOLUTE, RELATIVE, SYNCHRON )
\r
43 * expiryPoint [1..*]
\r
45 * |--- EventSetting [0..*]
\r
47 * | `--- SetEventTaskRef
\r
49 * |--- TaskActivation [0..*]
\r
52 * |--- AdjustableExpPoint [0..1] (only if syncStrategy!=NONE)
\r
57 * |--- explicitPrecision (only if syncStrategy==EXPLICIT )
\r
58 * |--- syncStrategy (NONE,EXPLICIT,IMPLICIT )
\r
65 #define SCHED_CHECK_ID(x) \
\r
66 if( (x) > Os_CfgGetSchedCnt()) { \
\r
71 #define SCHED_STD_END \
\r
77 extern TickType GetCountValue( OsCounterType *counter );
\r
81 enum OsScheduleTableSyncStrategy getSyncStrategy( OsSchTblType *stblPtr ) {
\r
82 return stblPtr->sync.syncStrategy;
\r
88 * Consistency checks for scheduletables. This should really be checked by
\r
95 static void ScheduleTableConsistenyCheck( OsSchTblType *sTblPtr ) {
\r
97 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
\r
99 if( sTblPtr->sync.syncStrategy == IMPLICIT ) {
\r
100 assert( sTblPtr->duration == (sTblPtr->counter->alarm_base.maxallowedvalue +1) );
\r
104 if( sTblPtr->sync.syncStrategy == EXPLICIT ) {
\r
105 assert( sTblPtr->duration <= (sTblPtr->counter->alarm_base.maxallowedvalue +1) );
\r
110 assert(SA_LIST_CNT(&sTblPtr->expirePointList)>=1);
117 TickType minCycle = Os_CounterGetMinCycle(sTblPtr->counter);
118 TickType maxValue = Os_CounterGetMaxValue(sTblPtr->counter);
120 /* - start at offset=0
121 * - X expiry points = SA_LIST_CNT
126 for(iter=0; iter < SA_LIST_CNT(&sTblPtr->expirePointList) ; iter++) {
127 delta = SA_LIST_GET(&sTblPtr->expirePointList,iter)->offset - delta;
128 assert( delta >= minCycle );
129 assert( delta <= maxValue );
134 delta = sTblPtr->duration - SA_LIST_GET(&sTblPtr->expirePointList,iter-1)->offset;
135 assert( delta >= minCycle );
136 assert( delta <= maxValue );
141 StatusType StartScheduleTableRel(ScheduleTableType sid, TickType offset) {
\r
142 StatusType rv = E_OK;
\r
143 OsSchTblType *sPtr;
\r
147 #if (OS_STATUS_EXTENDED == STD_ON )
\r
152 sPtr = Os_CfgGetSched(sid);
154 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
155 if( sPtr->sync != NULL ) {
156 /* EXPLICIT or IMPLICIT */
159 if( sPtr->sync->syncStrategy == IMPLICIT ) {
166 max_offset = Os_CounterGetMaxValue(sPtr->counter);
167 #if (OS_STATUS_EXTENDED == STD_ON )
170 if( (offset == 0) || ((offset + Os_SchTblGetInitialOffset(sPtr)) > max_offset ) ) {
\r
177 if( sPtr->state != SCHEDULETABLE_STOPPED ) {
\r
183 /* calculate the expire value.. */
185 sPtr->expire_val = Os_CounterAdd(
186 Os_CounterGetValue(sPtr->counter),
188 offset + Os_SchTblGetInitialOffset(sPtr) );
\r
189 sPtr->state = SCHEDULETABLE_RUNNING;
\r
195 StatusType StartScheduleTableAbs(ScheduleTableType sid, TickType start ){
196 StatusType rv = E_OK;
197 OsSchTblType *sTblPtr;
\r
201 sTblPtr = Os_CfgGetSched(sid);
\r
204 if( start > Os_CounterGetMaxValue(sTblPtr->counter) ) {
210 if( sTblPtr->state != SCHEDULETABLE_STOPPED ) {
218 sTblPtr->expire_val = start + Os_SchTblGetInitialOffset(sTblPtr);
219 sTblPtr->state = SCHEDULETABLE_RUNNING;
230 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
232 StatusType StartScheduleTableSynchron(ScheduleTableType sid ){
\r
234 StatusType rv = E_OK;
\r
238 SCHED_CHECK_ID(sid);
\r
241 if( s_p->sync.syncStrategy != EXPLICIT ) {
\r
247 if( s_p->state != SCHEDULETABLE_STOPPED ) {
\r
253 s_p->state = SCHEDULETABLE_WAITING;
\r
264 /* TODO: Implement StopScheduleTable */
\r
265 StatusType StopScheduleTable(ScheduleTableType sid) {
\r
266 StatusType rv = E_OK;
\r
269 SCHED_CHECK_ID(sid);
\r
270 sPtr = Os_CfgGetSched(sid);
273 if(sPtr->state == SCHEDULETABLE_STOPPED ) {
279 sPtr->state = SCHEDULETABLE_STOPPED;
\r
285 StatusType NextScheduleTable( ScheduleTableType sid_curr, ScheduleTableType sid_next) {
\r
286 StatusType rv = E_OK;
\r
290 OsSchTblType *sFromPtr;
\r
291 OsSchTblType *sToPtr;
\r
294 SCHED_CHECK_ID(sid_curr);
\r
295 SCHED_CHECK_ID(sid_next);
\r
297 sFromPtr = Os_CfgGetSched(sid_curr);
\r
298 sToPtr = Os_CfgGetSched(sid_curr);
\r
301 if( sFromPtr->counter != sToPtr->counter) {
\r
307 if( sFromPtr->state == SCHEDULETABLE_STOPPED ||
\r
308 sFromPtr->state == SCHEDULETABLE_NEXT )
\r
315 if( sToPtr->state != SCHEDULETABLE_STOPPED ) {
\r
323 if( sFromPtr->state == SCHEDULETABLE_STOPPED ) {
324 sFromPtr->next->state = SCHEDULETABLE_STOPPED;
327 if( sFromPtr->next != NULL ) {
328 // Stop the schedule-table that was to be next.
329 sFromPtr->next->state = SCHEDULETABLE_STOPPED;
332 sFromPtr->next = sToPtr;
333 sToPtr->state = SCHEDULETABLE_NEXT;
334 sToPtr->expire_curr_index = 0;
350 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
\r
351 StatusType SyncScheduleTable( ScheduleTableType sid, GlobalTimeTickType globalTime ) {
\r
352 StatusType rv = E_OK;
\r
353 OsSchTblType *s_p = Os_CfgGetSched(sid);
\r
355 SCHED_CHECK_ID(sid);
\r
359 if( s_p->sync.syncStrategy != EXPLICIT ) {
\r
365 if( globalTime > s_p->duration ) {
\r
373 if( (s_p->state == SCHEDULETABLE_STOPPED) ||
\r
374 (s_p->state == SCHEDULETABLE_NEXT) ) {
\r
379 switch(s_p->state) {
\r
380 case SCHEDULETABLE_WAITING:
\r
381 // First time we called since started. Set the sync counter to
\r
382 // the value provided.
\r
383 s_p->sync.syncCounter = globalTime;
\r
384 s_p->state = SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS;
\r
387 case SCHEDULETABLE_RUNNING:
\r
388 case SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS:
\r
389 s_p->sync.deviation = s_p->sync.syncCounter - globalTime;
\r
390 if( s_p->sync.deviation != 0 ) {
\r
391 // We are not at sync any more...
\r
392 s_p->state = SCHEDULETABLE_RUNNING;
\r
417 StatusType GetScheduleTableStatus( ScheduleTableType sid, ScheduleTableStatusRefType status ) {
\r
418 StatusType rv = E_OK;
\r
422 SCHED_CHECK_ID(sid);
\r
424 s_p = Os_CfgGetSched(sid);
\r
429 case SCHEDULETABLE_STOPPED:
431 case SCHEDULETABLE_NEXT:
433 case SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS:
435 case SCHEDULETABLE_WAITING:
437 case SCHEDULETABLE_RUNNING:
\r
438 *status = s_p->state;
\r
456 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
\r
457 StatusType SetScheduleTableAsync( ScheduleTableType sid ) {
\r
458 StatusType rv = E_OK;
\r
459 OsSchTblType *s_p = Os_CfgGetSched(sid);
\r
461 SCHED_CHECK_ID(sid);
\r
464 if( s_p->sync.syncStrategy != EXPLICIT ) {
\r
471 /** @req_todo OS362 */
472 /** @req_todo OS323 */
\r
475 s_p->state = SCHEDULETABLE_RUNNING;
\r
486 * Go through the schedule tables connected to this counter
488 * @param c_p Pointer to counter object
490 void Os_SchTblCheck(OsCounterType *c_p) {
494 OsSchTblType *sched_obj;
496 /* Iterate through the schedule tables */
497 SLIST_FOREACH(sched_obj,&c_p->sched_head,sched_list) {
499 if( sched_obj->state == SCHEDULETABLE_STOPPED ) {
503 #if ( OS_SC2 == STD_ON ) || ( OS_SC4 == STD_ON )
504 if( sched_obj->sync.syncStrategy == IMPLICIT ) {
510 if( sched_obj->sync.deviation > 0 ) {
511 // The sync counter was set back ==
512 // we have more time to complete the table
513 adj = MIN(sched_obj->sync.deviation, getAdjExpPoint(sched_obj)->maxAdvance );
514 sched_obj->sync.deviation -= adj;
516 } else if( sched_obj->sync.deviation < 0 ) {
517 // The sync counter was set forward ==
518 // we have less time to complete the table
519 adj = MIN((-sched_obj->sync.deviation), getAdjExpPoint(sched_obj)->maxRetard);
520 sched_obj->sync.deviation -= adj;
524 sched_obj->state = SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS;
529 /* Check if the expire point have been hit */
530 if( (sched_obj->state == SCHEDULETABLE_RUNNING ||
531 sched_obj->state == SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS ) &&
532 (c_p->val == sched_obj->expire_val) )
534 if ( sched_obj->expire_curr_index < SA_LIST_CNT(&sched_obj->expirePointList) ) {
535 OsScheduleTableExpiryPointType * action;
538 action = SA_LIST_GET(&sched_obj->expirePointList,sched_obj->expire_curr_index);
543 /* According to OS412 activate tasks before events */
544 for(i=0; i< action->taskListCnt;i++ ) {
545 ActivateTask(action->taskList[i]);
548 for(i=0; i< action->eventListCnt;i++ ) {
549 SetEvent( action->eventList[i].task, action->eventList[i].event);
552 // Calc new expire val and state
553 Os_SchTblUpdateState(sched_obj);
562 void Os_SchTblInit( void ) {
\r
564 for( int i=0; i < Os_CfgGetSchedCnt();i++ ) {
\r
565 s_p = Os_CfgGetSched(i);
567 ScheduleTableConsistenyCheck(s_p);
\r
571 void Os_SchTblAutostart( void ) {
573 for(int j=0; j < Os_CfgGetSchedCnt(); j++ ) {
575 sPtr = Os_CfgGetSched(j);
577 if( sPtr->autostartPtr != NULL ) {
578 const struct OsSchTblAutostart *autoPtr = sPtr->autostartPtr;
581 if( os_sys.appMode & autoPtr->appMode ) {
583 /* Start the schedule table */
584 switch(autoPtr->type) {
585 case SCHTBL_AUTOSTART_ABSOLUTE:
586 StartScheduleTableAbs(j,autoPtr->offset);
588 case SCHTBL_AUTOSTART_RELATIVE:
589 StartScheduleTableRel(j,autoPtr->offset);
591 #if defined(OS_SC2) || defined(OS_SC4)
592 case SCHTBL_AUTOSTART_SYNCHRONE:
597 assert(0); // Illegal value
607 * Calculates expire value and changes state depending it's state.
610 * We can't cheat with the final + initial expire-point, instead we
611 * must setup trigger after the final delay and set the "previous"
612 * table to SCHEDULETABLE_STOPPED and the new to SCHEDULETABLE_RUNNING.
614 * @param stbl Ptr to a Schedule Table.
616 void Os_SchTblUpdateState( OsSchTblType *stbl ) {
\r
619 TickType initalOffset;
620 TickType finalOffset;
621 OsSchTblType *nextStblPtr;
622 _Bool handleLast = 0;
624 if( (stbl->expire_curr_index) == (SA_LIST_CNT(&stbl->expirePointList) - 1) ) {
625 /* We are at the last expiry point */
626 finalOffset = Os_SchTblGetFinalOffset(stbl);
628 if (finalOffset != 0) {
629 stbl->expire_val = Os_CounterAdd(
630 Os_CounterGetValue(stbl->counter),
631 Os_CounterGetMaxValue(stbl->counter),
634 stbl->expire_curr_index++;
637 /* Only single shot may have an offset of 0 */
638 assert(stbl->repeating == SINGLE_SHOT);
644 ( (stbl->expire_curr_index) == SA_LIST_CNT(&stbl->expirePointList) ) )
646 /* At final offset */
648 if( (stbl->repeating == REPEATING) || (stbl->next != NULL) ) {
649 if( stbl->next != NULL ) {
651 nextStblPtr = stbl->next;
652 /* NextScheduleTable() have been called */
653 assert( nextStblPtr->state==SCHEDULETABLE_NEXT );
655 /* We don't care about REPEATING or SINGLE_SHOT here */
656 initalOffset = Os_SchTblGetInitialOffset(nextStblPtr);
657 stbl->state = SCHEDULETABLE_STOPPED;
658 nextStblPtr->state = SCHEDULETABLE_RUNNING;
663 assert( stbl->repeating == REPEATING );
664 initalOffset = Os_SchTblGetInitialOffset(stbl);
667 stbl->expire_val = Os_CounterAdd(
668 Os_CounterGetValue(stbl->counter),
669 Os_CounterGetMaxValue(stbl->counter),
673 assert( stbl->repeating == SINGLE_SHOT );
675 stbl->state = SCHEDULETABLE_STOPPED;
677 stbl->expire_curr_index = 0;
681 delta = SA_LIST_GET(&stbl->expirePointList,stbl->expire_curr_index+1)->offset -
682 SA_LIST_GET(&stbl->expirePointList,stbl->expire_curr_index)->offset ;
684 stbl->expire_val = Os_CounterAdd(
685 Os_CounterGetValue(stbl->counter),
686 Os_CounterGetMaxValue(stbl->counter),
689 stbl->expire_curr_index++;