Example #1
0
/*
 * 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;
	}
}