]> rtime.felk.cvut.cz Git - arc.git/blob - system/EcuM/EcuM_Main.c
EcuM/MCU: Sleep code there..does not work
[arc.git] / system / EcuM / EcuM_Main.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 //lint -emacro(904,VALIDATE,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
17 \r
18 #include "Std_Types.h"\r
19 #include "EcuM.h"\r
20 #include "EcuM_Generated_Types.h"\r
21 #include "EcuM_Internals.h"\r
22 \r
23 #if defined(USE_DEM)\r
24 #include "Dem.h"\r
25 #endif\r
26 #if defined(USE_NVM)\r
27 #include "NvM.h"\r
28 #endif\r
29 \r
30 static uint32 internal_data_run_state_timeout = 0;\r
31 #if defined(USE_NVM)\r
32 static uint32 internal_data_go_off_one_state_timeout = 0;\r
33 static NvM_RequestResultType writeAllResult;\r
34 #endif\r
35 \r
36 static uint32 internal_data_go_sleep_state_timeout = 0;\r
37 \r
38 #ifdef CFG_ECUM_USE_SERVICE_COMPONENT\r
39 /** @req EcuM2749 */\r
40 static Rte_ModeType_EcuM_Mode currentMode;\r
41 \r
42 void set_current_state(EcuM_StateType state) {\r
43         /* Update the state */\r
44         internal_data.current_state = state;\r
45 \r
46         Rte_ModeType_EcuM_Mode newMode = currentMode;\r
47         switch( state ) {\r
48         case ECUM_STATE_WAKEUP:\r
49         case ECUM_STATE_WAKEUP_ONE:\r
50         case ECUM_STATE_WAKEUP_VALIDATION:\r
51         case ECUM_STATE_WAKEUP_REACTION:\r
52         case ECUM_STATE_WAKEUP_TWO:\r
53         case ECUM_STATE_SLEEP:\r
54         case ECUM_STATE_SHUTDOWN:\r
55                 newMode = RTE_MODE_EcuM_Mode_SLEEP;\r
56                 break;\r
57         case ECUM_STATE_GO_SLEEP:\r
58                 if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
59                         newMode = RTE_MODE_EcuM_Mode_SLEEP; /** @req EcuM2752 */\r
60                 }\r
61                 break;\r
62         case ECUM_STATE_GO_OFF_ONE:\r
63         case ECUM_STATE_GO_OFF_TWO:\r
64                 newMode = RTE_MODE_EcuM_Mode_SHUTDOWN;\r
65                 break;\r
66         case ECUM_STATE_WAKEUP_TTII:\r
67                 if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
68                         newMode = RTE_MODE_EcuM_Mode_WAKE_SLEEP; /** @req EcuM2752 */\r
69                 }\r
70                 break;\r
71         case ECUM_STATE_PREP_SHUTDOWN:\r
72         case ECUM_STATE_APP_POST_RUN: /* Assuming this is same as RUN_III */\r
73                 newMode = RTE_MODE_EcuM_Mode_POST_RUN;\r
74                 break;\r
75         case ECUM_STATE_APP_RUN: /* Assuming this is same as RUN_II */\r
76                 newMode = RTE_MODE_EcuM_Mode_RUN;\r
77                 break;\r
78         case ECUM_STATE_STARTUP_TWO:\r
79                 newMode = RTE_MODE_EcuM_Mode_STARTUP;\r
80                 break;\r
81         default:\r
82                 /* Do nothing */\r
83                 break;\r
84         }\r
85 \r
86         if( newMode != currentMode ) {\r
87                 currentMode = newMode;\r
88                 Rte_Switch_EcuM_CurrentMode_currentMode(currentMode); /** @req EcuM2750 */\r
89         }\r
90 }\r
91 #endif\r
92 \r
93 \r
94 /**\r
95  * RUN II entry\r
96  * - Called from EcuM_StartupTwo()\r
97  * - Called from\r
98  *\r
99  *\r
100  */\r
101 void EcuM_enter_run_mode(void){\r
102         set_current_state(ECUM_STATE_APP_RUN);\r
103         EcuM_OnEnterRun(); /** @req EcuM2308 */\r
104 \r
105 #if defined(USE_WDGM)\r
106         /* This seems strange, should be in FW instead */\r
107         WdgM_SetMode(TODO_MODE);\r
108 #endif\r
109 \r
110 #if defined(USE_COMM)\r
111         /*\r
112          * Loop over all channels that have requested run,\r
113          * ie EcuM_ComM_RequestRUN()\r
114          */\r
115         {\r
116                 uint32 cMask = internal_data.run_comm_requests;\r
117                 uint8  channel;\r
118 \r
119                 for (; cMask; cMask &= ~(1ul << channel)) {\r
120                         channel = ilog2(cMask);\r
121                         ComM_EcuM_RunModeIndication(channel);\r
122                 }\r
123         }\r
124 #endif\r
125 \r
126         /* We have a configurable minimum time (EcuMRunMinimumDuration)\r
127          * we have to stay in RUN state  */\r
128         internal_data_run_state_timeout = internal_data.config->EcuMRunMinimumDuration / ECUM_MAIN_FUNCTION_PERIOD; /** @req EcuM2310 */\r
129 }\r
130 \r
131 \r
132 //--------- Local functions ------------------------------------------------------------------------------------------------\r
133 \r
134 \r
135 \r
136 /**\r
137  * Enter GO SLEEP state ( soon in state ECUM_STATE_GO_SLEEP)\r
138  */\r
139 static inline void enter_go_sleep_mode(void){\r
140         EcuM_WakeupSourceType wakeupSource;\r
141         set_current_state(ECUM_STATE_GO_SLEEP);\r
142 \r
143         EcuM_OnGoSleep();\r
144 \r
145 #if defined(USE_NVM)\r
146         NvM_WriteAll();\r
147 \r
148         /* Start timer */\r
149         internal_data_go_sleep_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
150 \r
151         wakeupSource = EcuM_GetPendingWakeupEvents();\r
152 #else\r
153         wakeupSource = EcuM_GetPendingWakeupEvents();\r
154 #endif\r
155 }\r
156 \r
157 /**\r
158   In GO SLEEP state (in state ECUM_STATE_GO_SLEEP)\r
159  */\r
160 static void in_state_goSleep( void ) {\r
161 \r
162         /* We only wait for NvM_WriteAll() for so long */\r
163         if (internal_data_go_sleep_state_timeout){\r
164                 internal_data_go_sleep_state_timeout--;\r
165         }\r
166 \r
167         if( (internal_data_go_sleep_state_timeout == 0) ) {\r
168                 /*\r
169                  * We should go to sleep , enable source that should wake us\r
170                  * */\r
171                 uint32 cMask;\r
172                 uint8  source;\r
173                 const EcuM_SleepModeType *sleepModePtr;\r
174 \r
175                 /* Get the current sleep mode */\r
176 \r
177                 sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
178 \r
179                 cMask = sleepModePtr->EcuMWakeupSourceMask;\r
180 \r
181                 /* Loop over the WKSOURCE for this sleep mode */\r
182                 for (; cMask; cMask &= ~(1ul << source)) {\r
183                         source = ilog2(cMask);\r
184                         /* @req 3.1.5/ECUM2389 */\r
185                         EcuM_EnableWakeupSources( 1<< source );\r
186 \r
187 #if defined(WDGM)\r
188                         WdgM_SetMode(sleepModePtr->EcuMSleepModeWdgMMode);\r
189 #endif\r
190 \r
191                         /* Let no one else run */\r
192                         GetResource(RES_SCHEDULER);\r
193                 }\r
194 \r
195         } else if( EcuM_GetPendingWakeupEvents() != 0 ) {\r
196                 /* We have pending wakeup events, need to startup again */\r
197 #if defined(USE_NVM)\r
198                 NvM_CancelWriteAll();\r
199 #endif\r
200         }\r
201 }\r
202 \r
203 \r
204 /**\r
205  * In "Sleep Sequence I"  (in state ECUM_STATE_SLEEP)\r
206  */\r
207 static void in_state_sleep ( void ) {\r
208         const EcuM_SleepModeType *sleepModePtr;\r
209         sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
210 \r
211         Mcu_SetMode(sleepModePtr->EcuMSleepModeMcuMode);\r
212 }\r
213 \r
214 static inline void enter_go_off_one_mode(void){\r
215         set_current_state(ECUM_STATE_GO_OFF_ONE);\r
216         EcuM_OnGoOffOne();\r
217 \r
218 #if defined(USE_COMM)\r
219         ComM_DeInit();\r
220 #endif\r
221 \r
222 #if defined(USE_NVM)\r
223 \r
224         // Start NvM_WriteAll and timeout timer\r
225         NvM_WriteAll();\r
226 \r
227         internal_data_go_off_one_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
228 #endif\r
229 }\r
230 \r
231 \r
232 static inline boolean hasRunRequests(void){\r
233         uint32 result = internal_data.run_requests;\r
234 \r
235 #if defined(USE_COMM)\r
236         result |= internal_data.run_comm_requests;\r
237 #endif\r
238 \r
239         return (result != 0);\r
240 }\r
241 \r
242 static inline boolean hasPostRunRequests(void){\r
243         return (internal_data.postrun_requests != 0);\r
244 }\r
245 \r
246 \r
247 /**\r
248  * RUN II Loop (in state ECUM_STATE_APP_RUN)\r
249  * - The entry to RUN II is done in\r
250  */\r
251 static inline void in_state_appRun(void){\r
252         if (internal_data_run_state_timeout){\r
253                 internal_data_run_state_timeout--;\r
254         }\r
255 \r
256         if ((!hasRunRequests()) && (internal_data_run_state_timeout == 0)){\r
257                 EcuM_OnExitRun();       /** @req EcuM2865 */\r
258 \r
259 #if defined(USE_WDGM)\r
260                 WdgM_SetMode(FIXME_MODE);\r
261 #endif\r
262 \r
263 #if defined(USE_RTE) && defined(CFG_ECUM_USE_SERVICE_COMPONENT)\r
264                 Rte_Switch_currentMode_currentMode(RTE_MODE_EcuM_Mode_POSTRUN);\r
265 #endif\r
266 \r
267                 set_current_state(ECUM_STATE_APP_POST_RUN);/** @req EcuM2865 */\r
268         }\r
269 }\r
270 \r
271 \r
272 /**\r
273  * RUN III states (in state ECUM_STATE_APP_POST_RUN)\r
274  */\r
275 static inline void in_state_appPostRun(void){\r
276 \r
277         /* @req 3.1.5/ECUM2866 */\r
278         if (hasRunRequests()){\r
279                 /* We have run requests, return to RUN II */\r
280                 EcuM_enter_run_mode();\r
281 \r
282         } else if (!hasPostRunRequests()){\r
283                 EcuM_OnExitPostRun(); /** @req EcuM2761 */\r
284                 set_current_state(ECUM_STATE_PREP_SHUTDOWN);/** @req EcuM2761 */\r
285         } else {\r
286                 /* TODO: We have postrun requests */\r
287         }\r
288 }\r
289 \r
290 \r
291 /**\r
292  * PREP SHUTDOWN state (in state ECUM_STATE_PREP_SHUTDOWN)\r
293  */\r
294 static inline void in_state_prepShutdown(void){\r
295 \r
296         // TODO: The specification does not state what events to clear\r
297         EcuM_ClearWakeupEvent(ECUM_WKSTATUS_NONE);\r
298 \r
299         EcuM_OnPrepShutdown();\r
300 \r
301 #if defined(USE_DEM)\r
302         // DEM shutdown\r
303         Dem_Shutdown();\r
304 #endif\r
305 \r
306         // Switch shutdown mode\r
307         switch(internal_data.shutdown_target){\r
308                 //If in state Off or Reset go into Go_Off_One:\r
309                 case ECUM_STATE_OFF:\r
310                 case ECUM_STATE_RESET:\r
311                         enter_go_off_one_mode();\r
312                         break;\r
313                 case ECUM_STATE_SLEEP:\r
314                         enter_go_sleep_mode();\r
315                         break;\r
316                 default:\r
317                         //TODO: Report error.\r
318                         break;\r
319         }\r
320 }\r
321 \r
322 static inline void in_state_goOffOne(void){\r
323 #if defined(USE_NVM)\r
324                 if (internal_data_go_off_one_state_timeout){\r
325                         internal_data_go_off_one_state_timeout--;\r
326                 }\r
327                 // Wait for the NVM job (NvmWriteAll) to terminate\r
328                 NvM_GetErrorStatus(0, &writeAllResult);\r
329                 if ((writeAllResult != NVM_REQ_PENDING) || (internal_data_go_off_one_state_timeout == 0)){\r
330                         ShutdownOS(E_OK);\r
331                 }\r
332 #else\r
333                 ShutdownOS(E_OK);\r
334 #endif\r
335 }\r
336 \r
337 \r
338 //----- MAIN -----------------------------------------------------------------------------------------------------------------\r
339 void EcuM_MainFunction(void){\r
340         VALIDATE_NO_RV(internal_data.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_NOT_INITIATED);\r
341 \r
342         switch(internal_data.current_state){\r
343 \r
344                 case ECUM_STATE_APP_RUN:\r
345                         /* RUN II state */\r
346                         in_state_appRun();\r
347                         break;\r
348                 case ECUM_STATE_APP_POST_RUN:\r
349                         /* RUN III state */\r
350                         in_state_appPostRun();\r
351                         break;\r
352                 case ECUM_STATE_PREP_SHUTDOWN:\r
353                         in_state_prepShutdown();\r
354                         break;\r
355                 case ECUM_STATE_GO_OFF_ONE:\r
356                         in_state_goOffOne();\r
357                         break;\r
358                 case ECUM_STATE_GO_SLEEP:\r
359                         in_state_goSleep();\r
360                         break;\r
361                 case ECUM_STATE_SLEEP:\r
362                         in_state_sleep();\r
363                         break;\r
364 \r
365                 default:\r
366                         //TODO: Report error.\r
367                         break;\r
368         }\r
369 }\r