]> rtime.felk.cvut.cz Git - arc.git/blob - system/EcuM/EcuM_Main.c
EcuM_Main, reverted fix for non-ppc. Problem was already fixed..
[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 \r
31 static uint32 internal_data_run_state_timeout = 0;\r
32 #if defined(USE_NVM)\r
33 static uint32 internal_data_go_off_one_state_timeout = 0;\r
34 static NvM_RequestResultType writeAllResult;\r
35 #endif\r
36 \r
37 static uint32 internal_data_go_sleep_state_timeout = 0;\r
38 \r
39 #ifdef CFG_ECUM_USE_SERVICE_COMPONENT\r
40 /** @req EcuM2749 */\r
41 static Rte_ModeType_EcuM_Mode currentMode;\r
42 \r
43 void set_current_state(EcuM_StateType state) {\r
44         /* Update the state */\r
45         internal_data.current_state = state;\r
46 \r
47         Rte_ModeType_EcuM_Mode newMode = currentMode;\r
48         switch( state ) {\r
49         case ECUM_STATE_WAKEUP:\r
50         case ECUM_STATE_WAKEUP_ONE:\r
51         case ECUM_STATE_WAKEUP_VALIDATION:\r
52         case ECUM_STATE_WAKEUP_REACTION:\r
53         case ECUM_STATE_WAKEUP_TWO:\r
54         case ECUM_STATE_SLEEP:\r
55         case ECUM_STATE_SHUTDOWN:\r
56                 newMode = RTE_MODE_EcuM_Mode_SLEEP;\r
57                 break;\r
58         case ECUM_STATE_GO_SLEEP:\r
59                 if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
60                         newMode = RTE_MODE_EcuM_Mode_SLEEP; /** @req EcuM2752 */\r
61                 }\r
62                 break;\r
63         case ECUM_STATE_GO_OFF_ONE:\r
64         case ECUM_STATE_GO_OFF_TWO:\r
65                 newMode = RTE_MODE_EcuM_Mode_SHUTDOWN;\r
66                 break;\r
67         case ECUM_STATE_WAKEUP_TTII:\r
68                 if( internal_data.shutdown_target == ECUM_STATE_SLEEP ) {\r
69                         newMode = RTE_MODE_EcuM_Mode_WAKE_SLEEP; /** @req EcuM2752 */\r
70                 }\r
71                 break;\r
72         case ECUM_STATE_PREP_SHUTDOWN:\r
73         case ECUM_STATE_APP_POST_RUN: /* Assuming this is same as RUN_III */\r
74                 newMode = RTE_MODE_EcuM_Mode_POST_RUN;\r
75                 break;\r
76         case ECUM_STATE_APP_RUN: /* Assuming this is same as RUN_II */\r
77                 newMode = RTE_MODE_EcuM_Mode_RUN;\r
78                 break;\r
79         case ECUM_STATE_STARTUP_TWO:\r
80                 newMode = RTE_MODE_EcuM_Mode_STARTUP;\r
81                 break;\r
82         default:\r
83                 /* Do nothing */\r
84                 break;\r
85         }\r
86 \r
87         if( newMode != currentMode ) {\r
88                 currentMode = newMode;\r
89                 Rte_Switch_EcuM_CurrentMode_currentMode(currentMode); /** @req EcuM2750 */\r
90         }\r
91 }\r
92 #endif\r
93 \r
94 \r
95 /**\r
96  * RUN II entry\r
97  * - Called from EcuM_StartupTwo()\r
98  * - Called from\r
99  *\r
100  *\r
101  */\r
102 void EcuM_enter_run_mode(void){\r
103         set_current_state(ECUM_STATE_APP_RUN);\r
104         EcuM_OnEnterRun(); /** @req EcuM2308 */\r
105 \r
106 #if defined(USE_WDGM)\r
107         /* This seems strange, should be in FW instead */\r
108         WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMRunMode);\r
109 #endif\r
110 \r
111 #if defined(USE_COMM)\r
112         /*\r
113          * Loop over all channels that have requested run,\r
114          * ie EcuM_ComM_RequestRUN()\r
115          */\r
116         {\r
117                 uint32 cMask = internal_data.run_comm_requests;\r
118                 uint8  channel;\r
119 \r
120                 for (; cMask; cMask &= ~(1ul << channel)) {\r
121                         channel = ilog2(cMask);\r
122                         ComM_EcuM_RunModeIndication(channel);\r
123                 }\r
124         }\r
125 #endif\r
126 \r
127         /* We have a configurable minimum time (EcuMRunMinimumDuration)\r
128          * we have to stay in RUN state  */\r
129         internal_data_run_state_timeout = internal_data.config->EcuMRunMinimumDuration / ECUM_MAIN_FUNCTION_PERIOD; /** @req EcuM2310 */\r
130 }\r
131 \r
132 \r
133 //--------- Local functions ------------------------------------------------------------------------------------------------\r
134 \r
135 \r
136 \r
137 /**\r
138  * Enter GO SLEEP state ( soon in state ECUM_STATE_GO_SLEEP)\r
139  */\r
140 static inline void enter_go_sleep_mode(void){\r
141         EcuM_WakeupSourceType wakeupSource;\r
142         set_current_state(ECUM_STATE_GO_SLEEP);\r
143 \r
144         EcuM_OnGoSleep();\r
145 \r
146 #if defined(USE_NVM)\r
147         NvM_WriteAll();\r
148 \r
149         /* Start timer */\r
150         internal_data_go_sleep_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
151 \r
152         wakeupSource = EcuM_GetPendingWakeupEvents();\r
153 #else\r
154         wakeupSource = EcuM_GetPendingWakeupEvents();\r
155 #endif\r
156 }\r
157 \r
158 /**\r
159   In GO SLEEP state (in state ECUM_STATE_GO_SLEEP)\r
160  */\r
161 static void in_state_goSleep( void ) {\r
162 \r
163         /* We only wait for NvM_WriteAll() for so long */\r
164         if (internal_data_go_sleep_state_timeout){\r
165                 internal_data_go_sleep_state_timeout--;\r
166         }\r
167 \r
168         if( (internal_data_go_sleep_state_timeout == 0) ) {\r
169                 /*\r
170                  * We should go to sleep , enable source that should wake us\r
171                  * */\r
172                 uint32 cMask;\r
173                 uint8  source;\r
174                 const EcuM_SleepModeType *sleepModePtr;\r
175 \r
176                 /* Get the current sleep mode */\r
177 \r
178                 sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
179 \r
180                 cMask = sleepModePtr->EcuMWakeupSourceMask;\r
181 \r
182                 /* Loop over the WKSOURCE for this sleep mode */\r
183                 for (; cMask; cMask &= ~(1ul << source)) {\r
184                         source = ilog2(cMask);\r
185                         /* @req 3.1.5/ECUM2389 */\r
186                         EcuM_EnableWakeupSources( 1<< source );\r
187 \r
188 #if defined(WDGM)\r
189                         WdgM_SetMode(sleepModePtr->EcuMSleepModeWdgMMode);\r
190 #endif\r
191 \r
192                         /* Let no one else run */\r
193                         GetResource(RES_SCHEDULER);\r
194                 }\r
195 \r
196         } else if( EcuM_GetPendingWakeupEvents() != 0 ) {\r
197                 /* We have pending wakeup events, need to startup again */\r
198 #if defined(USE_NVM)\r
199                 NvM_CancelWriteAll();\r
200 #endif\r
201         }\r
202 }\r
203 \r
204 \r
205 /**\r
206  * In "Sleep Sequence I"  (in state ECUM_STATE_SLEEP)\r
207  */\r
208 static void in_state_sleep ( void ) {\r
209         const EcuM_SleepModeType *sleepModePtr;\r
210         sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
211 \r
212         EcuM_GenerateRamHash();\r
213 \r
214         Mcu_SetMode(sleepModePtr->EcuMSleepModeMcuMode);\r
215 \r
216         /* @req 3.1.5/ECUM2863 */\r
217         if( EcuM_CheckRamHash() == 0) {\r
218 #if defined(USE_DEM)\r
219                 //\r
220                 EcuM_ErrorHook(ECUM_E_RAM_CHECK_FAILED);\r
221 #endif\r
222         }\r
223 \r
224         set_current_state(ECUM_STATE_WAKEUP_ONE);\r
225 }\r
226 \r
227 static inline void enter_go_off_one_mode(void){\r
228         set_current_state(ECUM_STATE_GO_OFF_ONE);\r
229         EcuM_OnGoOffOne();\r
230 \r
231 #if defined(USE_COMM)\r
232         ComM_DeInit();\r
233 #endif\r
234 \r
235 #if defined(USE_NVM)\r
236 \r
237         // Start NvM_WriteAll and timeout timer\r
238         NvM_WriteAll();\r
239 \r
240         internal_data_go_off_one_state_timeout = internal_data.config->EcuMNvramWriteAllTimeout / ECUM_MAIN_FUNCTION_PERIOD;\r
241 #endif\r
242 }\r
243 \r
244 \r
245 static inline boolean hasRunRequests(void){\r
246         uint32 result = internal_data.run_requests;\r
247 \r
248 #if defined(USE_COMM)\r
249         result |= internal_data.run_comm_requests;\r
250 #endif\r
251 \r
252         return (result != 0);\r
253 }\r
254 \r
255 static inline boolean hasPostRunRequests(void){\r
256         return (internal_data.postrun_requests != 0);\r
257 }\r
258 \r
259 \r
260 /**\r
261  * RUN II Loop (in state ECUM_STATE_APP_RUN)\r
262  * - The entry to RUN II is done in\r
263  */\r
264 static inline void in_state_appRun(void){\r
265         if (internal_data_run_state_timeout){\r
266                 internal_data_run_state_timeout--;\r
267         }\r
268 \r
269         if ((!hasRunRequests()) && (internal_data_run_state_timeout == 0)){\r
270                 EcuM_OnExitRun();       /** @req EcuM2865 */\r
271 \r
272 #if defined(USE_WDGM)\r
273                 WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMPostRunMode);\r
274 #endif\r
275 \r
276 #if defined(USE_RTE) && defined(CFG_ECUM_USE_SERVICE_COMPONENT)\r
277                 Rte_Switch_currentMode_currentMode(RTE_MODE_EcuM_Mode_POSTRUN);\r
278 #endif\r
279 \r
280                 set_current_state(ECUM_STATE_APP_POST_RUN);/** @req EcuM2865 */\r
281         }\r
282 }\r
283 \r
284 \r
285 /**\r
286  * RUN III states (in state ECUM_STATE_APP_POST_RUN)\r
287  */\r
288 static inline void in_state_appPostRun(void){\r
289 \r
290         /* @req 3.1.5/ECUM2866 */\r
291         if (hasRunRequests()){\r
292                 /* We have run requests, return to RUN II */\r
293                 EcuM_enter_run_mode();\r
294 \r
295         } else if (!hasPostRunRequests()){\r
296                 EcuM_OnExitPostRun(); /** @req EcuM2761 */\r
297                 set_current_state(ECUM_STATE_PREP_SHUTDOWN);/** @req EcuM2761 */\r
298         } else {\r
299                 /* TODO: We have postrun requests */\r
300         }\r
301 }\r
302 \r
303 \r
304 /**\r
305  * PREP SHUTDOWN state (in state ECUM_STATE_PREP_SHUTDOWN)\r
306  */\r
307 static inline void in_state_prepShutdown(void){\r
308 \r
309         // TODO: The specification does not state what events to clear\r
310         EcuM_ClearWakeupEvent(ECUM_WKSTATUS_NONE);\r
311 \r
312         EcuM_OnPrepShutdown();\r
313 \r
314 #if defined(USE_DEM)\r
315         // DEM shutdown\r
316         Dem_Shutdown();\r
317 #endif\r
318 \r
319         // Switch shutdown mode\r
320         switch(internal_data.shutdown_target){\r
321                 //If in state Off or Reset go into Go_Off_One:\r
322                 case ECUM_STATE_OFF:\r
323                 case ECUM_STATE_RESET:\r
324                         enter_go_off_one_mode();\r
325                         break;\r
326                 case ECUM_STATE_SLEEP:\r
327                         enter_go_sleep_mode();\r
328                         break;\r
329                 default:\r
330                         //TODO: Report error.\r
331                         break;\r
332         }\r
333 }\r
334 \r
335 static inline void in_state_goOffOne(void){\r
336 #if defined(USE_NVM)\r
337                 if (internal_data_go_off_one_state_timeout){\r
338                         internal_data_go_off_one_state_timeout--;\r
339                 }\r
340                 // Wait for the NVM job (NvmWriteAll) to terminate\r
341                 NvM_GetErrorStatus(0, &writeAllResult);\r
342                 if ((writeAllResult != NVM_REQ_PENDING) || (internal_data_go_off_one_state_timeout == 0)){\r
343 \r
344 #if defined(USE_WDGM)\r
345                         WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMShutdownMode);\r
346 #endif\r
347                         ShutdownOS(E_OK);\r
348                 }\r
349 #else\r
350 \r
351 #if defined(USE_WDGM)\r
352                 WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMShutdownMode);\r
353 #endif\r
354                 ShutdownOS(E_OK);\r
355 #endif\r
356 }\r
357 \r
358 \r
359 //----- MAIN -----------------------------------------------------------------------------------------------------------------\r
360 void EcuM_MainFunction(void){\r
361         EcuM_WakeupSourceType wMask;\r
362 \r
363         VALIDATE_NO_RV(internal_data.initiated, ECUM_MAINFUNCTION_ID, ECUM_E_NOT_INITIATED);\r
364 \r
365         switch(internal_data.current_state){\r
366 \r
367                 case ECUM_STATE_APP_RUN:\r
368                         /* RUN II state */\r
369                         in_state_appRun();\r
370                         break;\r
371                 case ECUM_STATE_APP_POST_RUN:\r
372                         /* RUN III state */\r
373                         in_state_appPostRun();\r
374                         break;\r
375                 case ECUM_STATE_PREP_SHUTDOWN:\r
376                         in_state_prepShutdown();\r
377                         break;\r
378                 case ECUM_STATE_GO_OFF_ONE:\r
379                         in_state_goOffOne();\r
380                         break;\r
381                 case ECUM_STATE_GO_SLEEP:\r
382                         in_state_goSleep();\r
383                         break;\r
384                 case ECUM_STATE_SLEEP:\r
385                         in_state_sleep();\r
386                         break;\r
387                 case ECUM_STATE_WAKEUP_ONE:\r
388                 {\r
389                         /* TODO: we must have a normal RUN mode.. can't find any\r
390                          * in the A3.1.5 spec. */\r
391                         Mcu_SetMode(MCU_MODE_NORMAL);\r
392 \r
393 #if defined(USE_WDGM)\r
394                         WdgM_SetMode(internal_data.config->EcuMWdgMConfig->EcuMWdgMWakeupMode);\r
395 #endif\r
396 \r
397                         wMask = EcuM_GetPendingWakeupEvents();\r
398 \r
399                         EcuM_DisableWakeupSources(wMask);\r
400 \r
401                         EcuM_AL_DriverRestart();\r
402 \r
403                         ReleaseResource(RES_SCHEDULER);\r
404 \r
405                         set_current_state(ECUM_STATE_WAKEUP_VALIDATION);\r
406 \r
407                         break;\r
408                 }\r
409 \r
410                 case ECUM_STATE_WAKEUP_VALIDATION:\r
411                 {\r
412                         wMask = EcuM_GetPendingWakeupEvents();\r
413 \r
414                         EcuM_StartWakeupSources(wMask);\r
415 \r
416                         EcuM_CheckValidation( wMask );\r
417 \r
418                         // TODO:\r
419                         // ComM_EcuM_WakeupIndication( network handle )\r
420 \r
421                         set_current_state(ECUM_STATE_WAKEUP_REACTION);\r
422                         break;\r
423                 }\r
424 \r
425                 case ECUM_STATE_WAKEUP_REACTION:\r
426                 {\r
427                         /*\r
428                          * At this stage we want to know how to react to the wakeup, e.g. go\r
429                          * back to RUN or SHUTDOWN, etc.\r
430                          */\r
431                         EcuM_WakeupReactionType wReaction;\r
432 \r
433                         wMask = EcuM_GetValidatedWakeupEvents();\r
434 \r
435                         /* TODO: We have skipped the TTII timer here */\r
436 \r
437                         /* If the wakeup mask here is != 0 we have a validated wakeup event ->\r
438                          * go back to RUN */\r
439                         wReaction = ( 0 == wMask ) ? ECUM_WKACT_SHUTDOWN : ECUM_WKACT_RUN;\r
440                         wReaction = EcuM_OnWakeupReaction(wReaction);\r
441 \r
442                         if( wReaction == ECUM_WKACT_RUN) {\r
443                                 set_current_state(ECUM_STATE_WAKEUP_TWO);\r
444                         } else {\r
445                                 /* From figure 28 it seems that we should go to SHUTDOWN/GO SLEEP) again from wakeup\r
446                                  * not going up to RUN/RUN II state again. */\r
447                                 set_current_state(ECUM_STATE_GO_SLEEP);\r
448                         }\r
449                         break;\r
450                 }\r
451 \r
452                 case ECUM_STATE_WAKEUP_TWO:\r
453 #if defined(USE_DEM)\r
454                         Dem_Init();\r
455 #endif\r
456                         set_current_state(ECUM_STATE_RUN);\r
457                         break;\r
458 \r
459                 default:\r
460                         //TODO: Report error.\r
461                         break;\r
462         }\r
463 }\r