]> rtime.felk.cvut.cz Git - arc.git/blobdiff - system/EcuM/EcuM_Main.c
EcuM: Adding more sleep functionility
[arc.git] / system / EcuM / EcuM_Main.c
index e3283a529ca49f35104df3e2183d75f1a7576b89..a96cabeff1e763c82bf6b569ae961f3db9afc3b4 100644 (file)
 \r
 //lint -emacro(904,VALIDATE,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\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 defined(USE_NVM)\r
-#include "Nvm.h"\r
+#include "NvM.h"\r
 #endif\r
 \r
 static uint32 internal_data_run_state_timeout = 0;\r
@@ -31,24 +33,196 @@ static uint32 internal_data_go_off_one_state_timeout = 0;
 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
-       internal_data.current_state = ECUM_STATE_APP_RUN;\r
-       EcuM_OnEnterRUN(); /** @req EcuM2308 */\r
-       //TODO: Call ComM_EcuM_RunModeIndication(NetworkHandleType Channel) for all channels that have requested run.\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(TODO_MODE);\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
+       /* 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
 \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
-       internal_data.current_state = ECUM_STATE_GO_SLEEP;\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
+/**\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
+\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
+       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
-       internal_data.current_state = ECUM_STATE_GO_OFF_ONE;\r
+       set_current_state(ECUM_STATE_GO_OFF_ONE);\r
        EcuM_OnGoOffOne();\r
 \r
 #if defined(USE_COMM)\r
@@ -80,7 +254,10 @@ static inline boolean hasPostRunRequests(void){
 }\r
 \r
 \r
-\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
@@ -88,29 +265,49 @@ static inline void in_state_appRun(void){
 \r
        if ((!hasRunRequests()) && (internal_data_run_state_timeout == 0)){\r
                EcuM_OnExitRun();       /** @req EcuM2865 */\r
-               internal_data.current_state = ECUM_STATE_APP_POST_RUN;/** @req EcuM2865 */\r
+\r
+#if defined(USE_WDGM)\r
+               WdgM_SetMode(FIXME_MODE);\r
+#endif\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
 \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
-               internal_data.current_state = ECUM_STATE_APP_RUN;/** @req EcuM2866 */ /** @req EcuM2308 */\r
-               EcuM_OnEnterRUN(); /** @req EcuM2308 */\r
-               //TODO: Call ComM_EcuM_RunModeIndication(NetworkHandleType Channel) for all channels that have requested run.\r
-               internal_data_run_state_timeout = internal_data.config->EcuMRunMinimumDuration / ECUM_MAIN_FUNCTION_PERIOD; /** @req EcuM2310 */\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
-               internal_data.current_state = ECUM_STATE_PREP_SHUTDOWN;/** @req EcuM2761 */\r
-\r
-               EcuM_OnPrepShutdown();\r
+               set_current_state(ECUM_STATE_PREP_SHUTDOWN);/** @req EcuM2761 */\r
        } else {\r
-               // TODO: Do something?\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 defined(USE_DEM)\r
        // DEM shutdown\r
        Dem_Shutdown();\r
@@ -150,14 +347,18 @@ static inline void in_state_goOffOne(void){
 \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
@@ -167,8 +368,79 @@ void EcuM_MainFunction(void){
                        in_state_goOffOne();\r
                        break;\r
                case ECUM_STATE_GO_SLEEP:\r
-                       // TODO: Fill out\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(FIXME_MODE);\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
+                       wReaction = ( 0 == wMask ) ? ECUM_WKACT_SHUTDOWN : ECUM_WKACT_RUN\r
+                       wReaction = EcuM_OnWakeupReaction(wReaction);\r
+\r
+                       if( wReaction == ECUM_WKACT_RUN) {\r
+\r
+                               set_current_state(ECUM_STATE_WAKEUP_TWO);\r
+                       } else {\r
+                               /* Shutdown, again */\r
+                               /* TODO:\r
+                               set_current_state(ECUM_STATE_WAKEUP_TWO);\r
+                       }\r
+                       break;\r
+               }\r
+\r
+               case ECUM_STATE_WAKEUP_TWO:\r
+                       Dem_Init();\r
+\r
+                       break;\r
+\r
                default:\r
                        //TODO: Report error.\r
                        break;\r