]> rtime.felk.cvut.cz Git - arc.git/blob - system/EcuM/EcuM_Main.c
a96cabeff1e763c82bf6b569ae961f3db9afc3b4
[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         /* @req 3.1.5/ECUM2863 */\r
214         if( EcuM_CheckRamHash() == 0) {\r
215 #if defined(USE_DEM)\r
216                 //\r
217                 EcuM_ErrorHook(ECUM_E_RAM_CHECK_FAILED);\r
218 #endif\r
219         }\r
220 \r
221         set_current_state(ECUM_STATE_WAKEUP_ONE);\r
222 }\r
223 \r
224 static inline void enter_go_off_one_mode(void){\r
225         set_current_state(ECUM_STATE_GO_OFF_ONE);\r
226         EcuM_OnGoOffOne();\r
227 \r
228 #if defined(USE_COMM)\r
229         ComM_DeInit();\r
230 #endif\r
231 \r
232 #if defined(USE_NVM)\r
233 \r
234         // Start NvM_WriteAll and timeout timer\r
235         NvM_WriteAll();\r
236 \r
237         internal_data_go_off_one_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
238 #endif\r
239 }\r
240 \r
241 \r
242 static inline boolean hasRunRequests(void){\r
243         uint32 result = internal_data.run_requests;\r
244 \r
245 #if defined(USE_COMM)\r
246         result |= internal_data.run_comm_requests;\r
247 #endif\r
248 \r
249         return (result != 0);\r
250 }\r
251 \r
252 static inline boolean hasPostRunRequests(void){\r
253         return (internal_data.postrun_requests != 0);\r
254 }\r
255 \r
256 \r
257 /**\r
258  * RUN II Loop (in state ECUM_STATE_APP_RUN)\r
259  * - The entry to RUN II is done in\r
260  */\r
261 static inline void in_state_appRun(void){\r
262         if (internal_data_run_state_timeout){\r
263                 internal_data_run_state_timeout--;\r
264         }\r
265 \r
266         if ((!hasRunRequests()) && (internal_data_run_state_timeout == 0)){\r
267                 EcuM_OnExitRun();       /** @req EcuM2865 */\r
268 \r
269 #if defined(USE_WDGM)\r
270                 WdgM_SetMode(FIXME_MODE);\r
271 #endif\r
272 \r
273 #if defined(USE_RTE) && defined(CFG_ECUM_USE_SERVICE_COMPONENT)\r
274                 Rte_Switch_currentMode_currentMode(RTE_MODE_EcuM_Mode_POSTRUN);\r
275 #endif\r
276 \r
277                 set_current_state(ECUM_STATE_APP_POST_RUN);/** @req EcuM2865 */\r
278         }\r
279 }\r
280 \r
281 \r
282 /**\r
283  * RUN III states (in state ECUM_STATE_APP_POST_RUN)\r
284  */\r
285 static inline void in_state_appPostRun(void){\r
286 \r
287         /* @req 3.1.5/ECUM2866 */\r
288         if (hasRunRequests()){\r
289                 /* We have run requests, return to RUN II */\r
290                 EcuM_enter_run_mode();\r
291 \r
292         } else if (!hasPostRunRequests()){\r
293                 EcuM_OnExitPostRun(); /** @req EcuM2761 */\r
294                 set_current_state(ECUM_STATE_PREP_SHUTDOWN);/** @req EcuM2761 */\r
295         } else {\r
296                 /* TODO: We have postrun requests */\r
297         }\r
298 }\r
299 \r
300 \r
301 /**\r
302  * PREP SHUTDOWN state (in state ECUM_STATE_PREP_SHUTDOWN)\r
303  */\r
304 static inline void in_state_prepShutdown(void){\r
305 \r
306         // TODO: The specification does not state what events to clear\r
307         EcuM_ClearWakeupEvent(ECUM_WKSTATUS_NONE);\r
308 \r
309         EcuM_OnPrepShutdown();\r
310 \r
311 #if defined(USE_DEM)\r
312         // DEM shutdown\r
313         Dem_Shutdown();\r
314 #endif\r
315 \r
316         // Switch shutdown mode\r
317         switch(internal_data.shutdown_target){\r
318                 //If in state Off or Reset go into Go_Off_One:\r
319                 case ECUM_STATE_OFF:\r
320                 case ECUM_STATE_RESET:\r
321                         enter_go_off_one_mode();\r
322                         break;\r
323                 case ECUM_STATE_SLEEP:\r
324                         enter_go_sleep_mode();\r
325                         break;\r
326                 default:\r
327                         //TODO: Report error.\r
328                         break;\r
329         }\r
330 }\r
331 \r
332 static inline void in_state_goOffOne(void){\r
333 #if defined(USE_NVM)\r
334                 if (internal_data_go_off_one_state_timeout){\r
335                         internal_data_go_off_one_state_timeout--;\r
336                 }\r
337                 // Wait for the NVM job (NvmWriteAll) to terminate\r
338                 NvM_GetErrorStatus(0, &writeAllResult);\r
339                 if ((writeAllResult != NVM_REQ_PENDING) || (internal_data_go_off_one_state_timeout == 0)){\r
340                         ShutdownOS(E_OK);\r
341                 }\r
342 #else\r
343                 ShutdownOS(E_OK);\r
344 #endif\r
345 }\r
346 \r
347 \r
348 //----- MAIN -----------------------------------------------------------------------------------------------------------------\r
349 void EcuM_MainFunction(void){\r
350         EcuM_WakeupSourceType wMask;\r
351 \r
352         VALIDATE_NO_RV(internal_data.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_NOT_INITIATED);\r
353 \r
354         switch(internal_data.current_state){\r
355 \r
356                 case ECUM_STATE_APP_RUN:\r
357                         /* RUN II state */\r
358                         in_state_appRun();\r
359                         break;\r
360                 case ECUM_STATE_APP_POST_RUN:\r
361                         /* RUN III state */\r
362                         in_state_appPostRun();\r
363                         break;\r
364                 case ECUM_STATE_PREP_SHUTDOWN:\r
365                         in_state_prepShutdown();\r
366                         break;\r
367                 case ECUM_STATE_GO_OFF_ONE:\r
368                         in_state_goOffOne();\r
369                         break;\r
370                 case ECUM_STATE_GO_SLEEP:\r
371                         in_state_goSleep();\r
372                         break;\r
373                 case ECUM_STATE_SLEEP:\r
374                         in_state_sleep();\r
375                         break;\r
376                 case ECUM_STATE_WAKEUP_ONE:\r
377                 {\r
378                         /* TODO: we must have a normal RUN mode.. can't find any\r
379                          * in the A3.1.5 spec. */\r
380                         Mcu_SetMode(MCU_MODE_NORMAL);\r
381 \r
382 #if defined(USE_WDGM)\r
383                         WdgM_SetMode(FIXME_MODE);\r
384 #endif\r
385 \r
386                         wMask = EcuM_GetPendingWakeupEvents();\r
387 \r
388                         EcuM_DisableWakeupSources(wMask);\r
389 \r
390                         EcuM_AL_DriverRestart();\r
391 \r
392                         ReleaseResource(RES_SCHEDULER);\r
393 \r
394                         set_current_state(ECUM_STATE_WAKEUP_VALIDATION);\r
395 \r
396                         break;\r
397                 }\r
398 \r
399                 case ECUM_STATE_WAKEUP_VALIDATION:\r
400                 {\r
401                         wMask = EcuM_GetPendingWakeupEvents();\r
402 \r
403                         EcuM_StartWakeupSources(wMask);\r
404 \r
405                         EcuM_CheckValidation( wMask );\r
406 \r
407                         // TODO:\r
408                         // ComM_EcuM_WakeupIndication( network handle )\r
409 \r
410                         set_current_state(ECUM_STATE_WAKEUP_REACTION);\r
411                         break;\r
412                 }\r
413 \r
414                 case ECUM_STATE_WAKEUP_REACTION:\r
415                 {\r
416                         /*\r
417                          * At this stage we want to know how to react to the wakeup, e.g. go\r
418                          * back to RUN or SHUTDOWN, etc.\r
419                          */\r
420                         EcuM_WakeupReactionType wReaction;\r
421 \r
422                         wMask = EcuM_GetValidatedWakeupEvents();\r
423 \r
424                         /* TODO: We have skipped the TTII timer here */\r
425                         wReaction = ( 0 == wMask ) ? ECUM_WKACT_SHUTDOWN : ECUM_WKACT_RUN\r
426                         wReaction = EcuM_OnWakeupReaction(wReaction);\r
427 \r
428                         if( wReaction == ECUM_WKACT_RUN) {\r
429 \r
430                                 set_current_state(ECUM_STATE_WAKEUP_TWO);\r
431                         } else {\r
432                                 /* Shutdown, again */\r
433                                 /* TODO:\r
434                                 set_current_state(ECUM_STATE_WAKEUP_TWO);\r
435                         }\r
436                         break;\r
437                 }\r
438 \r
439                 case ECUM_STATE_WAKEUP_TWO:\r
440                         Dem_Init();\r
441 \r
442                         break;\r
443 \r
444                 default:\r
445                         //TODO: Report error.\r
446                         break;\r
447         }\r
448 }\r