]> rtime.felk.cvut.cz Git - arc.git/blob - system/EcuM/EcuM.c
04d1cf8fff0edb2d3d37a84e55c4c6c4a6c33f60
[arc.git] / system / EcuM / EcuM.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 \r
17 /** @reqSettings DEFAULT_SPECIFICATION_REVISION=3.1.5 */\r
18 \r
19 /* ----------------------------[information]----------------------------------*/\r
20 /*\r
21  * Author: ?+mahi\r
22  *\r
23  * Part of Release:\r
24  *   3.1.5\r
25  *\r
26  * Description:\r
27  *   Implements the Can Driver module\r
28  *\r
29  * Support:\r
30  *   General                  Have Support\r
31  *   -------------------------------------------\r
32  *   ECUM_TTII_ENABLED                          N\r
33  *   ECUM_DEV_ERROR_DETECT                              Y\r
34  *   ECUM_VERSION_INFO_API                              Y\r
35  *   ECUM_INCLUDE_DEM                                   N (controlled by USE_x macro's instead)\r
36  *   ECUM_INCLUDE_NVRAM_MGR                             N (controlled by USE_x macro's instead)\r
37  *   ECUM_INLCUDE_DET                                   N (controlled by USE_x macro's instead)\r
38  *   ECUM_MAIN_FUNCTION_PERDIOD                 Y\r
39  *   ECUM_TTII_WKSOURCE                                 N\r
40  *\r
41  *   Configuration            Have Support\r
42  *   -------------------------------------------\r
43  *   ECUM_SLEEP_ACTIVITY_PERIOD                 ?\r
44  *   ECUM_CONFIGCONSISTENCY_HASH                N\r
45  *   ECUM_RUN_SELF_REQUEST_PERIOD               ?\r
46  *   ECUM_NVRAM_WRITEALL_TIMEOUT                Y\r
47  *   ECUM_DEFAULT_APP_MODE                              ?\r
48  *\r
49  *\r
50  *   DefaultShutdownTarget\r
51  *   -------------------------------------------\r
52  *   ECUM_DEFAULT_SHUTDOWN_TARGET               N\r
53  *\r
54  *\r
55  * Things to start with:\r
56  * - EcuM2181\r
57  * - EcuM2861 , Watchdog\r
58  * - ComM_EcuM_RunModeIndication()  not called, See Figure 8 (Seems that the ComM does not do much either)\r
59  *\r
60  *\r
61  *\r
62  */\r
63 \r
64 //lint -emacro(904,VALIDATE,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
65 \r
66 \r
67 /* ----------------------------[includes]------------------------------------*/\r
68 \r
69 #include "Std_Types.h"\r
70 #include "EcuM.h"\r
71 #include "Modules.h"\r
72 #include <string.h>\r
73 #include <Os.h>\r
74 #include "EcuM_Generated_Types.h"\r
75 #include "EcuM_Internals.h"\r
76 #include "EcuM_Cbk.h"\r
77 #include "SchM_EcuM.h"\r
78 #include "MemMap.h"\r
79 #include "Mcu.h"\r
80 #include "ComStack_Types.h"\r
81 #if defined(USE_DET)\r
82 #include "Det.h"\r
83 #endif\r
84 #include "isr.h"\r
85 #if defined(USE_NVM)\r
86 #include "NvM.h"\r
87 #endif\r
88 #if defined(USE_RTE)\r
89 #include "Rte_Main.h"\r
90 #endif\r
91 #if defined(USE_SCHM)\r
92 #include "SchM.h"\r
93 #endif\r
94 \r
95 \r
96 /* ----------------------------[private define]------------------------------*/\r
97 /* ----------------------------[private macro]-------------------------------*/\r
98 /* ----------------------------[private typedef]-----------------------------*/\r
99 /* ----------------------------[private function prototypes]-----------------*/\r
100 /* ----------------------------[private variables]---------------------------*/\r
101 \r
102 EcuM_GlobalType internal_data;\r
103 \r
104 /* ----------------------------[private functions]---------------------------*/\r
105 \r
106 \r
107 /* ----------------------------[public functions]----------------------------*/\r
108 \r
109 #if !defined(USE_DET) && defined(ECUM_DEV_ERROR_DETECT)\r
110 #error EcuM configuration error. DET is not enabled when ECUM_DEV_ERROR_DETECT is set\r
111 #endif\r
112 \r
113 void EcuM_Init( void )\r
114 {\r
115         Std_ReturnType status;\r
116         set_current_state(ECUM_STATE_STARTUP_ONE);\r
117 \r
118         // Initialize drivers that are needed to determine PostBuild configuration\r
119         EcuM_AL_DriverInitZero();\r
120 \r
121         // Initialize the OS\r
122         InitOS();\r
123 \r
124         // Setup interrupts\r
125         Os_IsrInit();\r
126 \r
127         // Determine PostBuild configuration\r
128         internal_data.config = EcuM_DeterminePbConfiguration();\r
129 \r
130 \r
131         // TODO: Check consistency of PB configuration\r
132 \r
133         // Initialize drivers needed before the OS-starts\r
134         EcuM_AL_DriverInitOne(internal_data.config);\r
135 \r
136         // Determine the reset/wakeup reason\r
137         // TODO Mcu_ResetType type = Mcu_GetResetReason();\r
138 \r
139         // Moved this here because EcuM_SelectShutdownTarget needs us to be initilized.\r
140         internal_data.initiated = TRUE;\r
141 \r
142         // Set default shutdown target\r
143         status = EcuM_SelectShutdownTarget(internal_data.config->EcuMDefaultShutdownTarget,internal_data.config->EcuMDefaultSleepMode);/** @req EcuM2181 */\r
144         if(status!=E_OK){\r
145                 //TODO: Report error.\r
146         }\r
147 \r
148 \r
149         // Set default application mode\r
150         status =  EcuM_SelectApplicationMode(internal_data.config->EcuMDefaultAppMode);\r
151         if(status!=E_OK){\r
152                 //TODO: Report error.\r
153         }\r
154 \r
155 #if defined(USE_COMM) || defined(USE_ECUM_COMM)\r
156         internal_data.run_comm_requests = 0;\r
157 #endif\r
158         internal_data.run_requests = 0;\r
159         internal_data.postrun_requests = 0;\r
160 \r
161         // Start this baby up\r
162         AppModeType appMode;\r
163         status = EcuM_GetApplicationMode(&appMode);\r
164         if(status!=E_OK){\r
165                 //TODO: Report error.\r
166         }\r
167         StartOS(appMode); /** @req EcuM2141 */\r
168 }\r
169 \r
170 /*\r
171  * The order defined here is found in 3.1.5/EcuM2411\r
172  */\r
173 void EcuM_StartupTwo(void)\r
174 {\r
175         //TODO:  Validate that we are in state STARTUP_ONE.\r
176 #if defined(USE_NVM)\r
177         extern CounterType Os_Arc_OsTickCounter;\r
178         TickType tickTimerStart, tickTimerElapsed;\r
179         static NvM_RequestResultType readAllResult;\r
180         TickType tickTimer;\r
181         StatusType tickTimerStatus;\r
182 #endif\r
183 \r
184         // Initialize the BSW scheduler\r
185 #if defined(USE_SCHM)\r
186         SchM_Init();\r
187 #endif\r
188 \r
189         // Initialize drivers that don't need NVRAM data\r
190         EcuM_AL_DriverInitTwo(internal_data.config);\r
191 \r
192 #if defined(USE_NVM)\r
193         // Start timer to wait for NVM job to complete\r
194         tickTimerStart = GetOsTick();\r
195 #endif\r
196 \r
197         // Prepare the system to startup RTE\r
198         // TODO EcuM_OnRTEStartup();\r
199 #if defined(USE_RTE)\r
200         Rte_Start();\r
201 #endif\r
202 \r
203         set_current_state(ECUM_STATE_STARTUP_TWO);\r
204 \r
205 #if defined(USE_NVM)\r
206 \r
207 #if 0\r
208         /* Wait for the NVM job (NvmReadAll) to terminate. This assumes that:\r
209          * - A task runs the memory MainFunctions, e.g. Ea_MainFunction(), Eep_MainFunction()\r
210          *    Prio: HIGH\r
211          * - A task runs the service functions for EcuM, Nvm.\r
212          *    Prio: MIDDLE\r
213          * - This task:\r
214          *    Prio: LOW  (So that the service functions for the other may run)\r
215          */\r
216         do {\r
217                 /* Read the multiblock status */\r
218                 NvM_GetErrorStatus(0, &readAllResult);\r
219                 tickTimerElapsed = OS_TICKS2MS_OsTick(GetOsTick() - tickTimerStart);\r
220                 /* The timeout EcuMNvramReadAllTimeout is in ms */\r
221         } while( (readAllResult == NVM_REQ_PENDING) && (tickTimerElapsed < internal_data.config->EcuMNvramReadAllTimeout) );\r
222 #else\r
223         // Wait for the NVM job (NvmReadAll) to terminate\r
224                 do {\r
225                         NvM_GetErrorStatus(0, &readAllResult);  // Read the multiblock status\r
226                         tickTimer = tickTimerStart;     // Save this because the GetElapsedCounterValue() will destroy it.\r
227                         tickTimerStatus =  GetElapsedCounterValue(Os_Arc_OsTickCounter, &tickTimer, &tickTimerElapsed);\r
228                         if (tickTimerStatus != E_OK) {\r
229                                 DET_REPORTERROR(MODULE_ID_ECUM, 0, ECUM_ARC_STARTUPTWO_ID, ECUM_E_ARC_TIMERERROR);\r
230                         }\r
231                 } while( (readAllResult == NVM_REQ_PENDING) && (tickTimerElapsed < internal_data.config->EcuMNvramReadAllTimeout) );\r
232 #endif\r
233 #endif\r
234 \r
235         // Initialize drivers that need NVRAM data\r
236         EcuM_AL_DriverInitThree(internal_data.config);\r
237 \r
238         // TODO: Indicate mode change to RTE\r
239 \r
240         // If coming from startup sequence, enter Run mode\r
241 //      if (internal_data.current_state == ECUM_STATE_STARTUP_TWO)\r
242                 EcuM_enter_run_mode();\r
243 \r
244 }\r
245 \r
246 // Typically called from OS shutdown hook\r
247 void EcuM_Shutdown(void)\r
248 {\r
249         set_current_state(ECUM_STATE_GO_OFF_TWO);\r
250 \r
251         // Let the last drivers do a nice shutdown\r
252         EcuM_OnGoOffTwo();\r
253 \r
254         if (internal_data.shutdown_target == ECUM_STATE_OFF)\r
255         {\r
256                 EcuM_AL_SwitchOff();\r
257         }\r
258         else\r
259         {\r
260 #if (MCU_PERFORM_RESET_API == STD_ON)\r
261                 Mcu_PerformReset();\r
262 #else\r
263                 for(;;)\r
264                 {\r
265                   ;\r
266                 }\r
267 #endif\r
268         }\r
269 }\r
270 \r
271 Std_ReturnType EcuM_GetState(EcuM_StateType* state)\r
272 {\r
273         VALIDATE_RV(internal_data.initiated, ECUM_GETSTATE_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
274         VALIDATE_RV(state != NULL, ECUM_GETSTATE_ID, ECUM_E_NULL_POINTER, E_NOT_OK);\r
275 \r
276         *state = internal_data.current_state;\r
277 \r
278         return E_OK;\r
279 }\r
280 \r
281 Std_ReturnType EcuM_SelectApplicationMode(AppModeType appMode)\r
282 {\r
283         VALIDATE_RV(internal_data.initiated, ECUM_SELECTAPPMODE_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
284 \r
285         internal_data.app_mode = appMode;\r
286 \r
287         return E_OK;\r
288 }\r
289 \r
290 Std_ReturnType EcuM_GetApplicationMode(AppModeType* appMode)\r
291 {\r
292         VALIDATE_RV(internal_data.initiated, ECUM_GETAPPMODE_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
293         VALIDATE_RV(appMode != NULL, ECUM_GETAPPMODE_ID, ECUM_E_NULL_POINTER, E_NOT_OK);\r
294 \r
295         *appMode = internal_data.app_mode;\r
296 \r
297         return E_OK;\r
298 }\r
299 \r
300 Std_ReturnType EcuM_SelectBootTarget(EcuM_BootTargetType target)\r
301 {\r
302         VALIDATE_RV(internal_data.initiated, ECUM_SELECT_BOOTARGET_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
303 \r
304         // TODO Do something great here\r
305         (void) target;\r
306 \r
307         return E_NOT_OK;\r
308 }\r
309 \r
310 Std_ReturnType EcuM_GetBootTarget(EcuM_BootTargetType* target)\r
311 {\r
312         VALIDATE_RV(internal_data.initiated, ECUM_GET_BOOTARGET_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
313         VALIDATE_RV(target != NULL, ECUM_GET_BOOTARGET_ID, ECUM_E_NULL_POINTER, E_NOT_OK);\r
314 \r
315         // TODO Return selected boot target here\r
316         (void) target;\r
317 \r
318         return E_NOT_OK;\r
319 }\r
320 \r
321 \r
322 Std_ReturnType EcuM_SelectShutdownTarget(EcuM_StateType shutdownTarget, uint8 sleepMode)\r
323 {\r
324         VALIDATE_RV(internal_data.initiated, ECUM_SELECTSHUTDOWNTARGET_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
325         VALIDATE_RV((shutdownTarget == ECUM_STATE_OFF) || (shutdownTarget == ECUM_STATE_RESET) || (shutdownTarget == ECUM_STATE_SLEEP), ECUM_SELECTSHUTDOWNTARGET_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
326 \r
327         internal_data.shutdown_target = shutdownTarget;\r
328         internal_data.sleep_mode = sleepMode;\r
329 \r
330         return E_OK;\r
331 }\r
332 \r
333 \r
334 Std_ReturnType EcuM_GetShutdownTarget(EcuM_StateType* shutdownTarget, uint8* sleepMode) /** @req EcuM2824 */\r
335 {\r
336         VALIDATE_RV(internal_data.initiated, ECUM_GETSHUTDOWNTARGET_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
337         VALIDATE_RV(shutdownTarget != NULL, ECUM_GETSHUTDOWNTARGET_ID, ECUM_E_NULL_POINTER, E_NOT_OK);\r
338         VALIDATE_RV(sleepMode != NULL, ECUM_GETSHUTDOWNTARGET_ID, ECUM_E_NULL_POINTER, E_NOT_OK);\r
339 \r
340         *shutdownTarget = internal_data.shutdown_target;\r
341         *sleepMode = internal_data.sleep_mode;\r
342 \r
343         return E_OK;\r
344 }\r
345 \r
346 \r
347 Std_ReturnType EcuM_RequestRUN(EcuM_UserType user)\r
348 {\r
349         VALIDATE_RV(internal_data.initiated, ECUM_REQUESTRUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
350         VALIDATE_RV(user < ECUM_USER_ENDMARK, ECUM_REQUESTRUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
351 \r
352         internal_data.run_requests |= (uint32)1 << user;\r
353 \r
354         return E_OK;\r
355 }\r
356 \r
357 Std_ReturnType EcuM_ReleaseRUN(EcuM_UserType user)\r
358 {\r
359         VALIDATE_RV(internal_data.initiated, ECUM_RELEASERUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
360         VALIDATE_RV(user < ECUM_USER_ENDMARK, ECUM_RELEASERUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
361 \r
362         internal_data.run_requests &= ~((uint32)1 << user);\r
363 \r
364         return E_OK;\r
365 }\r
366 \r
367 /**\r
368  *\r
369  */\r
370 void EcuM_KillAllRUNRequests( void ) {\r
371         /* NOT IMPLEMENTED */\r
372 }\r
373 \r
374 \r
375 /**\r
376  *\r
377  * @param sources\r
378  */\r
379 void EcuM_SetWakeupEvent(EcuM_WakeupSourceType sources) {\r
380         /* @req 3.1.5/EcuM2826 The function exists */\r
381         /* @req 3.1.5/EcuM2171 */\r
382 \r
383         /* @req 3.1.5/EcuM2867 */\r
384 #if  ( ECUM_DEV_ERROR_DETECT == STD_ON )\r
385         {\r
386                 EcuM_WakeupSourceType wkSource;\r
387                 const EcuM_SleepModeType *sleepModePtr;\r
388 \r
389                 sleepModePtr = &internal_data.config->EcuMSleepModeConfig[internal_data.sleep_mode];\r
390                 wkSource =  sleepModePtr->EcuMWakeupSourceMask;\r
391 \r
392                 if( !((sources | wkSource) ==  wkSource)) {\r
393                         Det_ReportError(MODULE_ID_ECUM, 0, ECUM_VALIDATE_WAKEUP_EVENT_ID, ECUM_E_UNKNOWN_WAKEUP_SOURCE );\r
394                         return;\r
395                 }\r
396         }\r
397 #endif\r
398 \r
399 \r
400         /* @req 3.1.5/EcuM1117 */\r
401         internal_data.wakeupEvents |= sources;\r
402 \r
403         /* @req 3.1.5/EcuM2707 @req 3.1.5/EcuM2709*/\r
404         internal_data.wakeupTimer = ECUM_VALIDATION_TIMEOUT;\r
405 \r
406 }\r
407 \r
408 #if defined(USE_COMM) || defined(USE_ECUM_COMM)\r
409 Std_ReturnType EcuM_ComM_RequestRUN(NetworkHandleType channel)\r
410 {\r
411         VALIDATE_RV(internal_data.initiated, ECUM_COMM_REQUESTRUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
412         VALIDATE_RV(channel < 32, ECUM_COMM_REQUESTRUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
413 \r
414         internal_data.run_comm_requests |= (uint32)1 << channel;\r
415 \r
416         return E_OK;\r
417 }\r
418 \r
419 Std_ReturnType EcuM_ComM_ReleaseRUN(NetworkHandleType channel)\r
420 {\r
421         VALIDATE_RV(internal_data.initiated, ECUM_COMM_RELEASERUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
422         VALIDATE_RV(channel < 32, ECUM_COMM_RELEASERUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
423 \r
424         internal_data.run_comm_requests &= ~((uint32)1 << channel);\r
425 \r
426         return E_OK;\r
427 }\r
428 \r
429 boolean EcuM_ComM_HasRequestedRUN(NetworkHandleType channel)\r
430 {\r
431         VALIDATE_RV(internal_data.initiated, ECUM_COMM_HASREQUESTEDRUN_ID, ECUM_E_NOT_INITIATED, FALSE);\r
432         VALIDATE_RV(channel < 32, ECUM_COMM_HASREQUESTEDRUN_ID, ECUM_E_INVALID_PAR, FALSE);\r
433 \r
434         return (internal_data.run_comm_requests &((uint32)1 << channel)) != 0;\r
435 }\r
436 #endif\r
437 \r
438 Std_ReturnType EcuM_RequestPOST_RUN(EcuM_UserType user)\r
439 {\r
440         VALIDATE_RV(internal_data.initiated, ECUM_REQUESTPOSTRUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
441         VALIDATE_RV(user < ECUM_USER_ENDMARK, ECUM_REQUESTPOSTRUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
442 \r
443         internal_data.postrun_requests |= (uint32)1 << user;\r
444 \r
445         return E_OK;\r
446 }\r
447 \r
448 Std_ReturnType EcuM_ReleasePOST_RUN(EcuM_UserType user)\r
449 {\r
450         VALIDATE_RV(internal_data.initiated, ECUM_RELEASEPOSTRUN_ID, ECUM_E_NOT_INITIATED, E_NOT_OK);\r
451         VALIDATE_RV(user < ECUM_USER_ENDMARK, ECUM_RELEASEPOSTRUN_ID, ECUM_E_INVALID_PAR, E_NOT_OK);\r
452 \r
453         internal_data.postrun_requests &= ~((uint32)1 << user);\r
454 \r
455         return E_OK;\r
456 }\r
457 \r
458 /*\r
459  * TODO: Don't yet understand the use\r
460  */\r
461 void EcuM_ClearWakeupEvent( EcuM_WakeupSourceType source )\r
462 {\r
463         switch(source) {\r
464         case ECUM_WKSTATUS_NONE:\r
465                 /* Seems quite pointless */\r
466                 break;\r
467         case ECUM_WKSTATUS_PENDING:\r
468                 break;\r
469         case ECUM_WKSTATUS_VALIDATED:\r
470                 break;\r
471         case ECUM_WKSTATUS_EXPIRED:\r
472                 break;\r
473         default:\r
474                 break;\r
475         }\r
476 }\r
477 \r
478 /**\r
479  * Get the pending wakeup events.\r
480  *\r
481  * @return\r
482  */\r
483 EcuM_WakeupSourceType EcuM_GetPendingWakeupEvents( void ) {\r
484         /* @req 3.1.5/EcuM2827 API\r
485          * @req 3.1.5/EcuM2172 Callable from interrupt context\r
486          * */\r
487 \r
488         /* @req 3.1.5/EcuM1156 */\r
489         return internal_data.wakeupEvents;\r
490 \r
491 }\r
492 \r
493 \r
494 void EcuM_CheckValidation(EcuM_WakeupSourceType wakeupSource) {\r
495         /* Used only if CanIf is used ? CanIf_Checkvalidation(wakeupSource) */\r
496 }\r
497 \r
498 \r
499 EcuM_WakeupSourceType EcuM_GetValidatedWakeupEvents( void ) {\r
500         // TODO:\r
501 }\r
502 \r
503 EcuM_WakeupStatusType EcuM_GetStatusOfWakeupSource( EcuM_WakeupSourceType sources ) {\r
504 \r
505 }\r
506 \r
507 \r