* for more details.\r
* -------------------------------- Arctic Core ------------------------------*/\r
\r
+//lint -emacro(904,VALIDATE,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
\r
-\r
-\r
-\r
-\r
-\r
-\r
+#include "Std_Types.h"\r
#include "EcuM.h"\r
-#include "EcuM_Cbk.h"\r
+#include "EcuM_Generated_Types.h"\r
#include "EcuM_Internals.h"\r
+\r
#if defined(USE_DEM)\r
#include "Dem.h"\r
#endif\r
-#if (ECUM_INCLUDE_NVRAM_MGR == STD_ON)\r
-#include "Nvm.h"\r
+#if defined(USE_NVM)\r
+#include "NvM.h"\r
#endif\r
\r
+\r
static uint32 internal_data_run_state_timeout = 0;\r
-#if (ECUM_INCLUDE_NVRAM_MGR == STD_ON)\r
+#if defined(USE_NVM)\r
static uint32 internal_data_go_off_one_state_timeout = 0;\r
+static NvM_RequestResultType writeAllResult;\r
+#endif\r
+\r
+static uint32 internal_data_go_sleep_state_timeout = 0;\r
+\r
+#ifdef CFG_ECUM_USE_SERVICE_COMPONENT\r
+/** @req EcuM2749 */\r
+static Rte_ModeType_EcuM_Mode currentMode;\r
+\r
+void set_current_state(EcuM_StateType state) {\r
+ /* Update the state */\r
+ internal_data.current_state = state;\r
+\r
+ Rte_ModeType_EcuM_Mode newMode = currentMode;\r
+ switch( state ) {\r
+ case ECUM_STATE_WAKEUP:\r
+ case ECUM_STATE_WAKEUP_ONE:\r
+ case ECUM_STATE_WAKEUP_VALIDATION:\r
+ case ECUM_STATE_WAKEUP_REACTION:\r
+ case ECUM_STATE_WAKEUP_TWO:\r
+ case ECUM_STATE_SLEEP:\r
+ case ECUM_STATE_SHUTDOWN:\r
+ newMode = RTE_MODE_EcuM_Mode_SLEEP;\r
+ break;\r
+ case ECUM_STATE_GO_SLEEP:\r
+ if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
+ newMode = RTE_MODE_EcuM_Mode_SLEEP; /** @req EcuM2752 */\r
+ }\r
+ break;\r
+ case ECUM_STATE_GO_OFF_ONE:\r
+ case ECUM_STATE_GO_OFF_TWO:\r
+ newMode = RTE_MODE_EcuM_Mode_SHUTDOWN;\r
+ break;\r
+ case ECUM_STATE_WAKEUP_TTII:\r
+ if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
+ newMode = RTE_MODE_EcuM_Mode_WAKE_SLEEP; /** @req EcuM2752 */\r
+ }\r
+ break;\r
+ case ECUM_STATE_PREP_SHUTDOWN:\r
+ case ECUM_STATE_APP_POST_RUN: /* Assuming this is same as RUN_III */\r
+ newMode = RTE_MODE_EcuM_Mode_POST_RUN;\r
+ break;\r
+ case ECUM_STATE_APP_RUN: /* Assuming this is same as RUN_II */\r
+ newMode = RTE_MODE_EcuM_Mode_RUN;\r
+ break;\r
+ case ECUM_STATE_STARTUP_TWO:\r
+ newMode = RTE_MODE_EcuM_Mode_STARTUP;\r
+ break;\r
+ default:\r
+ /* Do nothing */\r
+ break;\r
+ }\r
+\r
+ if( newMode != currentMode ) {\r
+ currentMode = newMode;\r
+ Rte_Switch_EcuM_CurrentMode_currentMode(currentMode); /** @req EcuM2750 */\r
+ }\r
+}\r
+#endif\r
+\r
+\r
+/**\r
+ * RUN II entry\r
+ * - Called from EcuM_StartupTwo()\r
+ * - Called from\r
+ *\r
+ *\r
+ */\r
+void EcuM_enter_run_mode(void){\r
+ set_current_state(ECUM_STATE_APP_RUN);\r
+ EcuM_OnEnterRun(); /** @req EcuM2308 */\r
+\r
+#if defined(USE_WDGM)\r
+ /* This seems strange, should be in FW instead */\r
+ WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMRunMode);\r
#endif\r
\r
+#if defined(USE_COMM)\r
+ /*\r
+ * Loop over all channels that have requested run,\r
+ * ie EcuM_ComM_RequestRUN()\r
+ */\r
+ {\r
+ uint32 cMask = internal_data.run_comm_requests;\r
+ uint8 channel;\r
\r
+ for (; cMask; cMask &= ~(1ul << channel)) {\r
+ channel = ilog2(cMask);\r
+ ComM_EcuM_RunModeIndication(channel);\r
+ }\r
+ }\r
+#endif\r
\r
-static inline void enter_run_mode(void)\r
-{\r
- internal_data.current_state = ECUM_STATE_APP_RUN;\r
- EcuM_OnEnterRUN();\r
- internal_data_run_state_timeout = internal_data.config->EcuMRunSelfRequestPeriod / ECUM_MAIN_FUNCTION_PERIOD;\r
+ /* We have a configurable minimum time (EcuMRunMinimumDuration)\r
+ * we have to stay in RUN state */\r
+ internal_data_run_state_timeout = internal_data.config->EcuMRunMinimumDuration / ECUM_MAIN_FUNCTION_PERIOD; /** @req EcuM2310 */\r
}\r
\r
-static inline void enter_post_run_mode(void)\r
-{\r
- internal_data.current_state = ECUM_STATE_APP_POST_RUN;\r
+\r
+//--------- Local functions ------------------------------------------------------------------------------------------------\r
+\r
+\r
+\r
+/**\r
+ * Enter GO SLEEP state ( soon in state ECUM_STATE_GO_SLEEP)\r
+ */\r
+static inline void enter_go_sleep_mode(void){\r
+ EcuM_WakeupSourceType wakeupSource;\r
+ set_current_state(ECUM_STATE_GO_SLEEP);\r
+\r
+ EcuM_OnGoSleep();\r
+\r
+#if defined(USE_NVM)\r
+ NvM_WriteAll();\r
+\r
+ /* Start timer */\r
+ internal_data_go_sleep_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
+\r
+ wakeupSource = EcuM_GetPendingWakeupEvents();\r
+#else\r
+ wakeupSource = EcuM_GetPendingWakeupEvents();\r
+#endif\r
}\r
\r
-static inline void enter_prep_shutdown_mode(void)\r
-{\r
- internal_data.current_state = ECUM_STATE_PREP_SHUTDOWN;\r
- EcuM_OnPrepShutdown();\r
+/**\r
+ In GO SLEEP state (in state ECUM_STATE_GO_SLEEP)\r
+ */\r
+static void in_state_goSleep( void ) {\r
+\r
+ /* We only wait for NvM_WriteAll() for so long */\r
+ if (internal_data_go_sleep_state_timeout){\r
+ internal_data_go_sleep_state_timeout--;\r
+ }\r
+\r
+ if( (internal_data_go_sleep_state_timeout == 0) ) {\r
+ /*\r
+ * We should go to sleep , enable source that should wake us\r
+ * */\r
+ uint32 cMask;\r
+ uint8 source;\r
+ const EcuM_SleepModeType *sleepModePtr;\r
+\r
+ /* Get the current sleep mode */\r
+\r
+ sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
+\r
+ cMask = sleepModePtr->EcuMWakeupSourceMask;\r
+\r
+ /* Loop over the WKSOURCE for this sleep mode */\r
+ for (; cMask; cMask &= ~(1ul << source)) {\r
+ source = ilog2(cMask);\r
+ /* @req 3.1.5/ECUM2389 */\r
+ EcuM_EnableWakeupSources( 1<< source );\r
+\r
+#if defined(WDGM)\r
+ WdgM_SetMode(sleepModePtr->EcuMSleepModeWdgMMode);\r
+#endif\r
+\r
+ /* Let no one else run */\r
+ GetResource(RES_SCHEDULER);\r
+ }\r
+\r
+ } else if( EcuM_GetPendingWakeupEvents() != 0 ) {\r
+ /* We have pending wakeup events, need to startup again */\r
+#if defined(USE_NVM)\r
+ NvM_CancelWriteAll();\r
+#endif\r
+ }\r
}\r
\r
-static inline void enter_go_sleep_mode(void)\r
-{\r
- internal_data.current_state = ECUM_STATE_GO_SLEEP;\r
- void EcuM_OnGoSleep();\r
+\r
+/**\r
+ * In "Sleep Sequence I" (in state ECUM_STATE_SLEEP)\r
+ */\r
+static void in_state_sleep ( void ) {\r
+ const EcuM_SleepModeType *sleepModePtr;\r
+ sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
+\r
+ EcuM_GenerateRamHash();\r
+\r
+ Mcu_SetMode(sleepModePtr->EcuMSleepModeMcuMode);\r
+\r
+ /* @req 3.1.5/ECUM2863 */\r
+ if( EcuM_CheckRamHash() == 0) {\r
+#if defined(USE_DEM)\r
+ //\r
+ EcuM_ErrorHook(ECUM_E_RAM_CHECK_FAILED);\r
+#endif\r
+ }\r
+\r
+ set_current_state(ECUM_STATE_WAKEUP_ONE);\r
}\r
\r
-static inline void enter_go_off_one_mode(void)\r
-{\r
- internal_data.current_state = ECUM_STATE_GO_OFF_ONE;\r
+static inline void enter_go_off_one_mode(void){\r
+ set_current_state(ECUM_STATE_GO_OFF_ONE);\r
EcuM_OnGoOffOne();\r
\r
#if defined(USE_COMM)\r
ComM_DeInit();\r
#endif\r
\r
-#if (ECUM_INCLUDE_NVRAM_MGR == STD_ON)\r
+#if defined(USE_NVM)\r
\r
// Start NvM_WriteAll and timeout timer\r
NvM_WriteAll();\r
#endif\r
}\r
\r
-static inline boolean hasRunRequests(void)\r
-{\r
- boolean result = internal_data.run_requests;\r
+\r
+static inline boolean hasRunRequests(void){\r
+ uint32 result = internal_data.run_requests;\r
\r
#if defined(USE_COMM)\r
result |= internal_data.run_comm_requests;\r
return (result != 0);\r
}\r
\r
-static inline boolean hasPostRunRequests(void)\r
-{\r
+static inline boolean hasPostRunRequests(void){\r
return (internal_data.postrun_requests != 0);\r
}\r
\r
-void EcuM_MainFunction(void)\r
-{\r
-#if (ECUM_INCLUDE_NVRAM_MGR == STD_ON)\r
-static NvM_RequestResultType writeAllResult;\r
-#endif\r
\r
-VALIDATE_NO_RV(internal_data.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_NOT_INITIATED);\r
+/**\r
+ * RUN II Loop (in state ECUM_STATE_APP_RUN)\r
+ * - The entry to RUN II is done in\r
+ */\r
+static inline void in_state_appRun(void){\r
+ if (internal_data_run_state_timeout){\r
+ internal_data_run_state_timeout--;\r
+ }\r
\r
- // If coming from startup sequence, enter Run mode\r
- if (internal_data.current_state == ECUM_STATE_STARTUP_TWO)\r
- enter_run_mode();\r
+ if ((!hasRunRequests()) && (internal_data_run_state_timeout == 0)){\r
+ EcuM_OnExitRun(); /** @req EcuM2865 */\r
\r
- if (internal_data.current_state == ECUM_STATE_APP_RUN)\r
- {\r
- if (internal_data_run_state_timeout)\r
- internal_data_run_state_timeout--;\r
+#if defined(USE_WDGM)\r
+ WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMPostRunMode);\r
+#endif\r
\r
- if (!hasRunRequests() && (internal_data_run_state_timeout == 0))\r
- {\r
- EcuM_OnExitRun(); // ECUM_2865\r
- enter_post_run_mode();\r
- return;\r
- }\r
+#if defined(USE_RTE) && defined(CFG_ECUM_USE_SERVICE_COMPONENT)\r
+ Rte_Switch_currentMode_currentMode(RTE_MODE_EcuM_Mode_POSTRUN);\r
+#endif\r
+\r
+ set_current_state(ECUM_STATE_APP_POST_RUN);/** @req EcuM2865 */\r
}\r
+}\r
\r
- if (internal_data.current_state == ECUM_STATE_APP_POST_RUN)\r
- {\r
- if (hasRunRequests())\r
- {\r
- enter_run_mode(); // ECUM_2866\r
- return;\r
- }\r
\r
- if (!hasPostRunRequests())\r
- {\r
- EcuM_OnExitPostRun(); // ECUM_2761\r
- enter_prep_shutdown_mode();\r
- return;\r
- }\r
+/**\r
+ * RUN III states (in state ECUM_STATE_APP_POST_RUN)\r
+ */\r
+static inline void in_state_appPostRun(void){\r
+\r
+ /* @req 3.1.5/ECUM2866 */\r
+ if (hasRunRequests()){\r
+ /* We have run requests, return to RUN II */\r
+ EcuM_enter_run_mode();\r
+\r
+ } else if (!hasPostRunRequests()){\r
+ EcuM_OnExitPostRun(); /** @req EcuM2761 */\r
+ set_current_state(ECUM_STATE_PREP_SHUTDOWN);/** @req EcuM2761 */\r
+ } else {\r
+ /* TODO: We have postrun requests */\r
}\r
+}\r
+\r
+\r
+/**\r
+ * PREP SHUTDOWN state (in state ECUM_STATE_PREP_SHUTDOWN)\r
+ */\r
+static inline void in_state_prepShutdown(void){\r
+\r
+ // TODO: The specification does not state what events to clear\r
+ EcuM_ClearWakeupEvent(ECUM_WKSTATUS_NONE);\r
+\r
+ EcuM_OnPrepShutdown();\r
\r
- if (internal_data.current_state == ECUM_STATE_PREP_SHUTDOWN)\r
- {\r
#if defined(USE_DEM)\r
- // DEM shutdown\r
- Dem_Shutdown();\r
+ // DEM shutdown\r
+ Dem_Shutdown();\r
#endif\r
\r
- // Switch shutdown mode\r
- if ((internal_data.shutdown_target == ECUM_STATE_OFF) || (internal_data.shutdown_target == ECUM_STATE_RESET)) {\r
+ // Switch shutdown mode\r
+ switch(internal_data.shutdown_target){\r
+ //If in state Off or Reset go into Go_Off_One:\r
+ case ECUM_STATE_OFF:\r
+ case ECUM_STATE_RESET:\r
enter_go_off_one_mode();\r
- }\r
-\r
- if (internal_data.shutdown_target == ECUM_STATE_SLEEP) {\r
+ break;\r
+ case ECUM_STATE_SLEEP:\r
enter_go_sleep_mode();\r
- }\r
+ break;\r
+ default:\r
+ //TODO: Report error.\r
+ break;\r
}\r
+}\r
\r
- if (internal_data.current_state == ECUM_STATE_GO_OFF_ONE)\r
- {\r
-#if (ECUM_INCLUDE_NVRAM_MGR == STD_ON)\r
- if (internal_data_go_off_one_state_timeout)\r
+static inline void in_state_goOffOne(void){\r
+#if defined(USE_NVM)\r
+ if (internal_data_go_off_one_state_timeout){\r
internal_data_go_off_one_state_timeout--;\r
-\r
+ }\r
// Wait for the NVM job (NvmWriteAll) to terminate\r
NvM_GetErrorStatus(0, &writeAllResult);\r
- if ((writeAllResult != NVM_REQ_PENDING) || (internal_data_go_off_one_state_timeout == 0))\r
- {\r
+ if ((writeAllResult != NVM_REQ_PENDING) || (internal_data_go_off_one_state_timeout == 0)){\r
+\r
+#if defined(USE_WDGM)\r
+ WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMShutdownMode);\r
+#endif\r
ShutdownOS(E_OK);\r
}\r
#else\r
+\r
+#if defined(USE_WDGM)\r
+ WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMShutdownMode);\r
+#endif\r
ShutdownOS(E_OK);\r
#endif\r
- }\r
+}\r
\r
- if (internal_data.current_state == ECUM_STATE_GO_SLEEP)\r
- {\r
- // TODO: Fill out\r
- }\r
\r
+//----- MAIN -----------------------------------------------------------------------------------------------------------------\r
+void EcuM_MainFunction(void){\r
+ EcuM_WakeupSourceType wMask;\r
+\r
+ VALIDATE_NO_RV(internal_data.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_NOT_INITIATED);\r
+\r
+ switch(internal_data.current_state){\r
+\r
+ case ECUM_STATE_APP_RUN:\r
+ /* RUN II state */\r
+ in_state_appRun();\r
+ break;\r
+ case ECUM_STATE_APP_POST_RUN:\r
+ /* RUN III state */\r
+ in_state_appPostRun();\r
+ break;\r
+ case ECUM_STATE_PREP_SHUTDOWN:\r
+ in_state_prepShutdown();\r
+ break;\r
+ case ECUM_STATE_GO_OFF_ONE:\r
+ in_state_goOffOne();\r
+ break;\r
+ case ECUM_STATE_GO_SLEEP:\r
+ in_state_goSleep();\r
+ break;\r
+ case ECUM_STATE_SLEEP:\r
+ in_state_sleep();\r
+ break;\r
+ case ECUM_STATE_WAKEUP_ONE:\r
+ {\r
+ /* TODO: we must have a normal RUN mode.. can't find any\r
+ * in the A3.1.5 spec. */\r
+ Mcu_SetMode(MCU_MODE_NORMAL);\r
+\r
+#if defined(USE_WDGM)\r
+ WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMWakeupMode);\r
+#endif\r
+\r
+ wMask = EcuM_GetPendingWakeupEvents();\r
+\r
+ EcuM_DisableWakeupSources(wMask);\r
+\r
+ EcuM_AL_DriverRestart();\r
+\r
+ ReleaseResource(RES_SCHEDULER);\r
+\r
+ set_current_state(ECUM_STATE_WAKEUP_VALIDATION);\r
+\r
+ break;\r
+ }\r
+\r
+ case ECUM_STATE_WAKEUP_VALIDATION:\r
+ {\r
+ wMask = EcuM_GetPendingWakeupEvents();\r
+\r
+ EcuM_StartWakeupSources(wMask);\r
+\r
+ EcuM_CheckValidation( wMask );\r
+\r
+ // TODO:\r
+ // ComM_EcuM_WakeupIndication( network handle )\r
+\r
+ set_current_state(ECUM_STATE_WAKEUP_REACTION);\r
+ break;\r
+ }\r
+\r
+ case ECUM_STATE_WAKEUP_REACTION:\r
+ {\r
+ /*\r
+ * At this stage we want to know how to react to the wakeup, e.g. go\r
+ * back to RUN or SHUTDOWN, etc.\r
+ */\r
+ EcuM_WakeupReactionType wReaction;\r
+\r
+ wMask = EcuM_GetValidatedWakeupEvents();\r
+\r
+ /* TODO: We have skipped the TTII timer here */\r
+\r
+ /* If the wakeup mask here is != 0 we have a validated wakeup event ->\r
+ * go back to RUN */\r
+ wReaction = ( 0 == wMask ) ? ECUM_WKACT_SHUTDOWN : ECUM_WKACT_RUN;\r
+ wReaction = EcuM_OnWakeupReaction(wReaction);\r
+\r
+ if( wReaction == ECUM_WKACT_RUN) {\r
+ set_current_state(ECUM_STATE_WAKEUP_TWO);\r
+ } else {\r
+ /* From figure 28 it seems that we should go to SHUTDOWN/GO SLEEP) again from wakeup\r
+ * not going up to RUN/RUN II state again. */\r
+ set_current_state(ECUM_STATE_GO_SLEEP);\r
+ }\r
+ break;\r
+ }\r
+\r
+ case ECUM_STATE_WAKEUP_TWO:\r
+#if defined(USE_DEM)\r
+ Dem_Init();\r
+#endif\r
+ set_current_state(ECUM_STATE_RUN);\r
+ break;\r
+\r
+ default:\r
+ //TODO: Report error.\r
+ break;\r
+ }\r
}\r