]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Mcu.c
Initial commit.
[arc.git] / arch / arm / arm_cm3 / drivers / Mcu.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23 #include "Std_Types.h"\r
24 #include "Mcu.h"\r
25 #include "Det.h"\r
26 #include <assert.h>\r
27 #include "cpu.h"\r
28 #include <string.h>\r
29 #include "Ramlog.h"\r
30 #include "system_stm32f10x.h"
31 \r
32 //#define USE_TRACE 1\r
33 //#define USE_DEBUG 1\r
34 #include "Trace.h"\r
35 \r
36 typedef struct {\r
37         uint32 lossOfLockCnt;\r
38         uint32 lossOfClockCnt;\r
39 } Mcu_Stats;\r
40 \r
41 void Mcu_ConfigureFlash(void);\r
42 /**\r
43  * Type that holds all global data for Mcu\r
44  */\r
45 typedef struct\r
46 {\r
47   // Set if Mcu_Init() have been called\r
48   boolean initRun;\r
49 \r
50   // Our config\r
51   const Mcu_ConfigType *config;\r
52 \r
53   Mcu_ClockType clockSetting;\r
54 \r
55   Mcu_Stats stats;\r
56 \r
57 } Mcu_GlobalType;\r
58 \r
59 /* Development error macros. */\r
60 #if ( MCU_DEV_ERROR_DETECT == STD_ON )\r
61 #define VALIDATE(_exp,_api,_err ) \\r
62         if( !(_exp) ) { \\r
63           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
64           return; \\r
65         }\r
66 \r
67 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
68         if( !(_exp) ) { \\r
69           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
70           return (_rv); \\r
71         }\r
72 #else\r
73 #define VALIDATE(_exp,_api,_err )\r
74 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
75 #endif\r
76 \r
77 // Global config\r
78 Mcu_GlobalType Mcu_Global =\r
79 {\r
80                 .initRun = 0,\r
81                 .config = &McuConfigData[0],\r
82 };\r
83 \r
84 //-------------------------------------------------------------------\r
85 \r
86 static void Mcu_LossOfLock( void  ) {\r
87 #if ( MCU_DEV_ERROR_DETECT == STD_ON )\r
88         /* Should report MCU_E_CLOCK_FAILURE with DEM here.... but\r
89          * we do the next best thing. Report with Det with API = 0\r
90          */\r
91         Det_ReportError(MODULE_ID_MCU,0,0,MCU_E_PLL_NOT_LOCKED);\r
92 #endif\r
93 \r
94         Mcu_Global.stats.lossOfLockCnt++;\r
95         // Clear interrupt\r
96 //      FMPLL.SYNSR.B.LOLF = 1;\r
97 \r
98 }\r
99 \r
100 //-------------------------------------------------------------------\r
101 static void Mcu_LossOfCLock( void  ) {\r
102 \r
103         /* Should report MCU_E_CLOCK_FAILURE with DEM here */\r
104 \r
105         Mcu_Global.stats.lossOfClockCnt++;\r
106         // Clear interrupt\r
107 //      FMPLL.SYNSR.B.LOCF = 1;\r
108 }\r
109 \r
110 \r
111 #define SPR_PIR 286\r
112 #define SPR_PVR 287\r
113 \r
114 #define CORE_PVR_E200Z1   0x81440000UL\r
115 #define CORE_PVR_E200Z0   0x81710000UL\r
116 \r
117 \r
118 typedef struct {\r
119   char *name;\r
120   uint32 pvr;\r
121 } core_info_t;\r
122 \r
123 typedef struct {\r
124   char *name;\r
125   uint32 pvr;\r
126 } cpu_info_t;\r
127 \r
128 cpu_info_t cpu_info_list[] = {\r
129     {\r
130     .name = "MPC5516",\r
131     .pvr = CORE_PVR_E200Z1,\r
132     },\r
133     {\r
134     .name = "MPC5516",\r
135     .pvr = CORE_PVR_E200Z0,\r
136     },\r
137 };\r
138 \r
139 core_info_t core_info_list[] = {\r
140     {\r
141     .name = "CORE_E200Z1",\r
142     .pvr = CORE_PVR_E200Z1,\r
143     },\r
144     {\r
145     .name = "CORE_E200Z1",\r
146     .pvr = CORE_PVR_E200Z1,\r
147     },\r
148 };\r
149 \r
150 // TODO: move\r
151 #define ARRAY_SIZE(_x)  (sizeof(_x)/sizeof((_x)[0]))\r
152 \r
153 static cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)\r
154 {\r
155   int i;\r
156   for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {\r
157     if (cpu_info_list[i].pvr == pvr) {\r
158       return &cpu_info_list[i];\r
159     }\r
160   }\r
161 \r
162   return NULL;\r
163 }\r
164 \r
165 static core_info_t *Mcu_IdentifyCore(uint32 pvr)\r
166 {\r
167   int i;\r
168   for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {\r
169     if (core_info_list[i].pvr == pvr) {\r
170       return &core_info_list[i];\r
171     }\r
172   }\r
173 \r
174   return NULL;\r
175 }\r
176 \r
177 \r
178 static uint32 Mcu_CheckCpu( void ) {\r
179 \r
180   uint32 pvr;\r
181   uint32 pir;\r
182   cpu_info_t *cpuType;\r
183   core_info_t *coreType;\r
184 \r
185   // We have to registers to read here, PIR and PVR\r
186 \r
187 #if 0\r
188   pir = get_spr(SPR_PIR);\r
189   pvr = get_spr(SPR_PVR);\r
190 #endif\r
191 \r
192   cpuType = Mcu_IdentifyCpu(pvr);\r
193   coreType = Mcu_IdentifyCore(pvr);\r
194 \r
195   if( (cpuType == NULL) || (coreType == NULL) ) {\r
196     // Just hang\r
197     while(1);\r
198   }\r
199 \r
200   //DEBUG(DEBUG_HIGH,"/drivers/mcu: Cpu:  %s( 0x%08x )\n",cpuType->name,pvr);\r
201   //DEBUG(DEBUG_HIGH,"/drivers/mcu: Core: %s( 0x%08x )\n",coreType->name,pvr);\r
202 \r
203   return 0;\r
204 }\r
205 \r
206 \r
207 //-------------------------------------------------------------------\r
208 \r
209 void Mcu_Init(const Mcu_ConfigType *configPtr)\r
210 {\r
211   VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );\r
212 \r
213   if( !SIMULATOR() ) {\r
214           Mcu_CheckCpu();\r
215   }\r
216 \r
217   memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));\r
218
219
220   SystemInit();\r
221
222   Irq_Enable();\r
223 \r
224   Mcu_Global.config = configPtr;\r
225   Mcu_Global.initRun = 1;\r
226 }\r
227 //-------------------------------------------------------------------\r
228 \r
229 void Mcu_DeInit()\r
230 {\r
231   Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?\r
232 }\r
233 \r
234 //-------------------------------------------------------------------\r
235 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)\r
236 {\r
237   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
238   VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );\r
239 \r
240   /* NOT SUPPORTED, reason: no support for external RAM */\r
241 \r
242   return E_OK;\r
243 }\r
244 \r
245 \r
246 \r
247 //-------------------------------------------------------------------\r
248 \r
249 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)\r
250 {\r
251   Mcu_ClockSettingConfigType *clockSettingsPtr;\r
252   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
253   VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );\r
254 \r
255   Mcu_Global.clockSetting = ClockSetting;\r
256   clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];\r
257 \r
258 \r
259 \r
260 #if 0\r
261   /* 5516clock info:\r
262    * Fsys - System frequency ( CPU + all periperals? )\r
263    *\r
264    *  Fsys = EXTAL_FREQ *(  (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )\r
265    */\r
266   // Check ranges...\r
267   assert((clockSettingsPtr->PllEmfd>=32) && (clockSettingsPtr->PllEmfd<=132));\r
268   assert( (clockSettingsPtr->PllEprediv!=6) &&\r
269           (clockSettingsPtr->PllEprediv!=8) &&\r
270           (clockSettingsPtr->PllEprediv<10) );\r
271   assert( clockSettingsPtr->PllErfd & 1); // Must be odd\r
272 #endif\r
273 \r
274 \r
275 \r
276 #if defined(USE_DEBUG)\r
277   {\r
278     uint32    extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;\r
279     uint32    f_sys;\r
280 \r
281     f_sys = CALC_SYSTEM_CLOCK( extal,\r
282         clockSettingsPtr->PllEmfd,\r
283         clockSettingsPtr->PllEprediv,\r
284         clockSettingsPtr->PllErfd );\r
285 \r
286     //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);\r
287   }\r
288 #endif\r
289 \r
290 #if defined(CFG_MPC5516)\r
291   // External crystal PLL mode.\r
292   FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?\r
293 \r
294   // Write pll parameters.\r
295   FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->PllEprediv;\r
296   FMPLL.ESYNCR1.B.EMFD    = clockSettingsPtr->PllEmfd;\r
297   FMPLL.ESYNCR2.B.ERFD    = clockSettingsPtr->PllErfd;\r
298 \r
299   // Connect SYSCLK to FMPLL\r
300   SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;\r
301 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)\r
302   FMPLL.SYNCR.B.PREDIV  = clockSettingsPtr->PllEprediv;\r
303   FMPLL.SYNCR.B.MFD             = clockSettingsPtr->PllEmfd;\r
304   FMPLL.SYNCR.B.RFD     = clockSettingsPtr->PllErfd;\r
305 #endif\r
306 \r
307   return E_OK;\r
308 }\r
309 \r
310 //-------------------------------------------------------------------\r
311 \r
312 void Mcu_DistributePllClock(void)\r
313 {\r
314   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
315 //  VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
316 \r
317   /* NOT IMPLEMENTED due to pointless function on this hardware */\r
318 \r
319 }\r
320 \r
321 //-------------------------------------------------------------------\r
322 \r
323 Mcu_PllStatusType Mcu_GetPllStatus(void)\r
324 {\r
325   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
326   Mcu_PllStatusType rv;\r
327 \r
328   if( !SIMULATOR() )\r
329   {\r
330 #if 0\r
331     if ( !FMPLL.SYNSR.B.LOCK )\r
332     {\r
333       rv = MCU_PLL_UNLOCKED;\r
334     } else\r
335     {\r
336       rv = MCU_PLL_LOCKED;\r
337     }\r
338 #endif\r
339   }\r
340   else\r
341   {\r
342     /* We are running on instruction set simulator. PLL is then always in sync... */\r
343     rv = MCU_PLL_LOCKED;\r
344   }\r
345 \r
346   return rv;\r
347 }\r
348 \r
349 //-------------------------------------------------------------------\r
350 \r
351 Mcu_ResetType Mcu_GetResetReason(void)\r
352 {\r
353         Mcu_ResetType rv;\r
354 \r
355   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
356 \r
357 #if 0\r
358   if( SIU.RSR.B.SSRS ) {\r
359         rv = MCU_SW_RESET;\r
360   } else if( SIU.RSR.B.WDRS ) {\r
361         rv = MCU_WATCHDOG_RESET;\r
362   } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {\r
363         rv = MCU_POWER_ON_RESET;\r
364   } else {\r
365         rv = MCU_RESET_UNDEFINED;\r
366   }\r
367 #endif\r
368 \r
369   return rv;\r
370 }\r
371 \r
372 //-------------------------------------------------------------------\r
373 \r
374 Mcu_RawResetType Mcu_GetResetRawValue(void)\r
375 {\r
376   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
377 \r
378   if( !Mcu_Global.initRun ) {\r
379         return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
380   }\r
381 \r
382 #if 0\r
383   return SIU.RSR.R;\r
384 #endif\r
385 \r
386   return 0;\r
387 }\r
388 \r
389 //-------------------------------------------------------------------\r
390 \r
391 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
392 void Mcu_PerformReset(void)\r
393 {\r
394   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
395 \r
396   NVIC_SystemReset();\r
397 }\r
398 #endif\r
399 \r
400 //-------------------------------------------------------------------\r
401 \r
402 void Mcu_SetMode(const Mcu_ModeType McuMode)\r
403 {\r
404   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
405   VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
406   (void) McuMode;\r
407 \r
408   /* NOT SUPPORTED */\r
409 }\r
410 \r
411 //-------------------------------------------------------------------\r
412 \r
413 /**\r
414  * Get the system clock in Hz. It calculates the clock from the\r
415  * different register settings in HW.\r
416  */\r
417 uint32_t McuE_GetSystemClock(void)\r
418 {\r
419   /*\r
420    * System clock calculation\r
421    *\r
422    */\r
423   uint32_t f_sys = 0;\r
424 #if 0\r
425   uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;\r
426 \r
427   f_sys =  CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);\r
428 #endif\r
429 \r
430 //  f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));\r
431   return f_sys;\r
432 }\r
433 \r
434 imask_t McuE_EnterCriticalSection()\r
435 {\r
436 #if 0\r
437   uint32_t msr = get_msr();\r
438   Irq_Disable();\r
439   return msr;\r
440 #endif\r
441   return 0;\r
442 }\r
443 \r
444 void McuE_ExitCriticalSection(uint32_t old_state)\r
445 {\r
446 #if 0\r
447   set_msr(old_state);\r
448 #endif\r
449 }\r
450 \r
451 /**\r
452  * Get the peripheral clock in Hz for a specific device\r
453  */\r
454 \r
455 #if 0\r
456 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
457 {\r
458 \r
459         return 0;\r
460 }\r
461 #endif\r
462 \r
463 \r
464 /**\r
465  * Function to setup the internal flash for optimal performance\r
466  */\r
467 \r
468 void Mcu_ConfigureFlash(void)\r
469 {\r
470 \r
471 }\r
472 \r
473 void McuE_EnableInterrupts(void)\r
474 {\r
475   Irq_Enable();\r
476 }\r
477 \r
478 void McuE_DisableInterrupts(void)\r
479 {\r
480   Irq_Disable();\r
481 }\r