/* * The order defined here is found in 3.1.5/EcuM2411 */ void EcuM_StartupTwo(void) { //TODO: Validate that we are in state STARTUP_ONE. #if defined(USE_NVM) extern CounterType Os_Arc_OsTickCounter; TickType tickTimerStart, tickTimerElapsed; static NvM_RequestResultType readAllResult; TickType tickTimer; StatusType tickTimerStatus; #endif set_current_state(ECUM_STATE_STARTUP_TWO); // Initialize the BSW scheduler #if defined(USE_SCHM) SchM_Init(); #endif #if defined(USE_WDGM) if( EcuM_World.config->EcuMWdgMConfig != NULL ) { WdgM_SetMode(EcuM_World.config->EcuMWdgMConfig->EcuMWdgMStartupMode); } #endif // Initialize drivers that don't need NVRAM data EcuM_AL_DriverInitTwo(EcuM_World.config); #if defined(USE_NVM) // Start timer to wait for NVM job to complete tickTimerStart = GetOsTick(); #endif // Prepare the system to startup RTE // TODO EcuM_OnRTEStartup(); #if defined(USE_RTE) Rte_Start(); #endif #if defined(USE_NVM) /* Wait for the NVM job (NvM_ReadAll) to terminate. This assumes that: * - A task runs the memory MainFunctions, e.g. Ea_MainFunction(), Eep_MainFunction() * are run in a higher priority task that the task that executes this code. */ do { /* Read the multiblock status */ NvM_GetErrorStatus(0, &readAllResult); tickTimerElapsed = OS_TICKS2MS_OS_TICK(GetOsTick() - tickTimerStart); /* The timeout EcuMNvramReadAllTimeout is in ms */ } while( (readAllResult == NVM_REQ_PENDING) && (tickTimerElapsed < EcuM_World.config->EcuMNvramReadAllTimeout) ); #endif // Initialize drivers that need NVRAM data EcuM_AL_DriverInitThree(EcuM_World.config); // TODO: Indicate mode change to RTE EcuM_enter_run_mode(); }
/** * RUN III states (in state ECUM_STATE_APP_POST_RUN) */ static inline void in_state_appPostRun(void){ /* @req EcuMf0025 Not enter sleep if we have a run request */ if (hasRunRequests()){ /* We have run requests, return to RUN II */ /* @req EcuMf2866 */ DEBUG_ECUM_CALLOUT( ECUM_STR "EcuM_enter_run_mode"); EcuM_enter_run_mode(); } else if (!hasPostRunRequests()){ DEBUG_ECUM_CALLOUT( ECUM_STR "EcuM_OnExitPostRun"); EcuM_OnExitPostRun(); /** @req EcuMf2761 */ SetCurrentState(ECUM_STATE_PREP_SHUTDOWN); } else { /* NOTE: We have postrun requests */ } }
//----- MAIN ----------------------------------------------------------------------------------------------------------------- void EcuM_MainFunction(void) { EcuM_WakeupSourceType wMask=0; #if defined(USE_LDEBUG_PRINTF) static uint32 validationMask; #endif static uint32 validationMaxTime; static uint32 pendingWkupMask = 0; #if (ECUM_AR_VERSION < 40000) VALIDATE_NO_RV(EcuM_World.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_UNINIT); #else /* @req EcuMf0029 */ if (!EcuM_World.initiated) { return; } #endif #if defined(USE_LDEBUG_PRINTF) { static EcuM_StateType oldEcuMState = 0xff; if( oldEcuMState != EcuM_World.current_state) { DEBUG_ECUM_STATE(EcuM_World.current_state); oldEcuMState = EcuM_World.current_state; } } #endif switch (EcuM_World.current_state) { case ECUM_STATE_APP_RUN: /* RUN II state */ in_state_appRun(); break; case ECUM_STATE_APP_POST_RUN: /* RUN III state */ in_state_appPostRun(); break; case ECUM_STATE_PREP_SHUTDOWN: in_state_prepShutdown(); break; case ECUM_STATE_GO_OFF_ONE: in_state_goOffOne(); break; case ECUM_STATE_GO_SLEEP: /* 4 cases: * 1. Wait for the NvM_WriteAll() - Stay in state * 2. Timeout on NvM_WriteAll() - go to ECUM_STATE_SLEEP (Scheduler is locked) * 3. NvM_WriteAll() is done - go to ECUM_STATE_SLEEP (Scheduler is locked) * 4. Run request - Call NvM_CancelAll() and go to ECUM_STATE_WAKEUP_ONE. */ in_state_goSleep(); if( EcuM_World.current_state != ECUM_STATE_SLEEP ) { break; } /* Flow Through, Scheduler is Locked */ //lint -fallthrough MISRA 2004 Rule 15.2 case ECUM_STATE_SLEEP: in_state_sleep(); /* Flow Through, Scheduler is Locked */ //lint -fallthrough MISRA 2004 Rule 15.2 case ECUM_STATE_WAKEUP_ONE: { DEBUG_ECUM_STATE(EcuM_World.current_state); /*@req EcuMF2975 */ Mcu_SetMode(EcuM_World.config->EcuMNormalMcuMode); wMask = EcuM_GetPendingWakeupEvents(); DEBUG_ECUM_CALLOUT_W_ARG("EcuM_DisableWakeupSources", "0x%lx", (uint32) wMask); EcuM_DisableWakeupSources(wMask); /* @req EcuM2562 */ /* @req EcuMf2562 */ EcuM_AL_DriverRestart(EcuM_World.config); EcuM_World.killAllRequest = false; /* Enable run request again */ (void)ReleaseResource(RES_SCHEDULER); #if defined(USE_LDEBUG_PRINTF) validationMask = 0; #endif validationMaxTime = 0; const EcuM_WakeupSourceConfigType *wkupCfgPtr; SetCurrentState(ECUM_STATE_WAKEUP_VALIDATION); /*-------------- ECUM_STATE_WAKEUP_VALIDATION -------------------- */ DEBUG_ECUM_CALLOUT(ECUM_STR "EcuM_GetPendingWakeupEvents"); pendingWkupMask = EcuM_GetPendingWakeupEvents(); DEBUG_ECUM_CALLOUT_W_ARG("EcuM_StartWakeupSources", "0x%lx",(uint32) pendingWkupMask); EcuM_StartWakeupSources(pendingWkupMask); EcuM_World.validationTimer = 0; /* Calculate the validation timing , if any*/ /* @req EcuMf2494 */ /* @req EcuM2479 */ /* @req EcuMf2479 */ for (int i = 0; i < ECUM_WKSOURCE_USER_CNT; i++) { wkupCfgPtr = &EcuM_World.config->EcuMWakeupSourceConfig[i]; /* Can't validate something that is not pending */ if (wMask & wkupCfgPtr->EcuMWakeupSourceId) { /* No validation timeout == ECUM_VALIDATION_TIMEOUT_ILL */ if ((wkupCfgPtr->EcuMValidationTimeout != ECUM_VALIDATION_TIMEOUT_ILL) && (wMask & wkupCfgPtr->EcuMWakeupSourceId)) { /* Build a mask with the sources that need validation */ #if defined(USE_LDEBUG_PRINTF) validationMask |= wkupCfgPtr->EcuMWakeupSourceId; #endif /* Use one validation timeout, take the longest */ validationMaxTime = MAX( wkupCfgPtr->EcuMValidationTimeout / ECUM_MAIN_FUNCTION_PERIOD, validationMaxTime); EcuM_World.validationTimer = validationMaxTime; } else { LDEBUG_PRINTF(ECUM_STR "No Validation for :0x%lx (EcuM_ValidateWakeupEvent() called)\n", (uint32) wkupCfgPtr->EcuMWakeupSourceId); /* Validate right away */ /* @req EcuM2976 */ /* @req EcuMf2976 */ EcuM_ValidateWakeupEvent(wkupCfgPtr->EcuMWakeupSourceId); } } } break; } case ECUM_STATE_WAKEUP_VALIDATION: { /* !req 3.1.5/EcuM2566 */ boolean done = 0; if (EcuM_World.validationTimer != 0) { /* * Call EcuM_CheckValidation() while all events have not been validated and * timeout have not expired. The call to EcuM_CheckValidation(..) triggers a call * to EcuM_ValidateWakeupEvent(..) from the driver when validated. */ /* Check validation for the events that do not match, ie not yet validated */ DEBUG_ECUM_CALLOUT_W_ARG( "EcuM_CheckValidation", "0x%lx", (uint32)(EcuM_GetValidatedWakeupEvents() ^ pendingWkupMask)); EcuM_CheckValidation( EcuM_GetValidatedWakeupEvents() ^ pendingWkupMask); /* !req EcuMf2495*/ if (0 == (EcuM_GetValidatedWakeupEvents() ^ pendingWkupMask)) { /* All events have been validated */ done = 1; } else { LDEBUG_PRINTF( ECUM_STR " Awaiting validation for mask: pending=%lx, expected=%lx\n", pendingWkupMask, validationMask); LDEBUG_PRINTF(ECUM_STR " Validation Timer : %lu\n", EcuM_World.validationTimer); } } else { uint32 notValidatedMask = EcuM_GetValidatedWakeupEvents() ^ pendingWkupMask; /* Stop wakeupSources that are not validated */ if (notValidatedMask) { DEBUG_ECUM_CALLOUT_W_ARG("EcuM_StopWakeupSources", "0x%lx", (uint32) notValidatedMask); EcuM_StopWakeupSources(notValidatedMask); #if defined(USE_BSWM) BswM_EcuM_CurrentWakeup(notValidatedMask, ECUM_WKSTATUS_EXPIRED); #endif } done = 1; } /* @req 3.1.5/EcuM2710 */ if (EcuM_World.validationTimer) { EcuM_World.validationTimer--; } if (done) { #if defined(USE_COMM) const EcuM_WakeupSourceConfigType *wkupCfgPtr; uint32 validated = EcuM_GetValidatedWakeupEvents(); for(int i=0;i<ECUM_WKSOURCE_USER_CNT;i++) { wkupCfgPtr = &EcuM_World.config->EcuMWakeupSourceConfig[i]; /* Call wakeup indication for all validated events with a channel assigned */ if ( (wkupCfgPtr->EcuMComMChannel != ECUM_COMM_CHANNEL_ILL) && wkupCfgPtr->EcuMWakeupSourceId & validated ) { ComM_EcuM_WakeUpIndication(wkupCfgPtr->EcuMComMChannel); } } #endif SetCurrentState(ECUM_STATE_WAKEUP_REACTION); } break; } case ECUM_STATE_WAKEUP_REACTION: { /* * At this stage we want to know how to react to the wakeup, e.g. go * back to RUN or SHUTDOWN, etc. */ EcuM_WakeupReactionType wReaction; wMask = EcuM_GetValidatedWakeupEvents(); LDEBUG_PRINTF(ECUM_STR "EcuM_GetValidatedWakeupEvents() : %x\n", wMask); /* NOTE: We have skipped the TTII timer here */ /* If the wakeup mask here is != 0 we have a validated wakeup event -> * go back to RUN */ wReaction = (0 == wMask) ? ECUM_WKACT_SHUTDOWN : ECUM_WKACT_RUN; wReaction = EcuM_OnWakeupReaction(wReaction); LDEBUG_PRINTF(ECUM_STR "Wakeup Reaction: %s\n", GetWakeupReactionAsString(wReaction)); if (wReaction == ECUM_WKACT_RUN) { /* @req EcuMf2568 */ SetCurrentState(ECUM_STATE_WAKEUP_TWO); } else { /* From figure 28 it seems that we should go to SHUTDOWN/GO SLEEP) again from wakeup * not going up to RUN/RUN II state again. */ /* @req EcuMf2711 */ /* @req EcuMf2567 */ SetCurrentState(ECUM_STATE_GO_SLEEP); } break; } case ECUM_STATE_WAKEUP_TWO: #if defined(USE_DEM) Dem_Init(); #endif EcuM_enter_run_mode(); // SetCurrentState(ECUM_STATE_APP_RUN); break; default: //IMPROVEMENT: Report error. break; } }