]> rtime.felk.cvut.cz Git - arc.git/blob - arch/arm/arm_cm3/drivers/Mcu.c
Adc updated for 5668
[arc.git] / arch / arm / arm_cm3 / drivers / Mcu.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 #include "Std_Types.h"\r
18 #include "Mcu.h"\r
19 #include "Det.h"\r
20 #if defined(USE_DEM)\r
21 #include "Dem.h"\r
22 #endif\r
23 #include <assert.h>\r
24 #include "Cpu.h"\r
25 #include <string.h>\r
26 #include "Ramlog.h"\r
27 \r
28 //#define USE_LDEBUG_PRINTF 1\r
29 #include "debug.h"\r
30 \r
31 \r
32 #ifndef ARRAY_SIZE\r
33 #define ARRAY_SIZE(_x)  (sizeof(_x)/sizeof((_x)[0]))\r
34 #endif\r
35 \r
36 /* Development error macros. */\r
37 #if ( MCU_DEV_ERROR_DETECT == STD_ON )\r
38 #define VALIDATE(_exp,_api,_err ) \\r
39         if( !(_exp) ) { \\r
40           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
41           return; \\r
42         }\r
43 \r
44 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
45         if( !(_exp) ) { \\r
46           Det_ReportError(MODULE_ID_MCU,0,_api,_err); \\r
47           return (_rv); \\r
48         }\r
49 #else\r
50 #define VALIDATE(_exp,_api,_err )\r
51 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
52 #endif\r
53 \r
54 \r
55 #define CORE_CPUID_CORTEX_M3    0x411FC231UL\r
56 \r
57 \r
58 \r
59 typedef struct {\r
60         uint32 lossOfLockCnt;\r
61         uint32 lossOfClockCnt;\r
62 } Mcu_Stats;\r
63 \r
64 /**\r
65  * Type that holds all global data for Mcu\r
66  */\r
67 typedef struct\r
68 {\r
69   // Set if Mcu_Init() have been called\r
70   boolean initRun;\r
71 \r
72   // Our config\r
73   const Mcu_ConfigType *config;\r
74 \r
75   Mcu_ClockType clockSetting;\r
76 \r
77   Mcu_Stats stats;\r
78 \r
79 } Mcu_GlobalType;\r
80 \r
81 \r
82 // Global config\r
83 Mcu_GlobalType Mcu_Global =\r
84 {\r
85                 .initRun = 0,\r
86                 .config = &McuConfigData[0],\r
87 };\r
88 \r
89 //-------------------------------------------------------------------\r
90 \r
91 typedef struct {\r
92   char *name;\r
93   uint32 pvr;\r
94 } core_info_t;\r
95 \r
96 typedef struct {\r
97   char *name;\r
98   uint32 pvr;\r
99 } cpu_info_t;\r
100 \r
101 \r
102 void Mcu_ConfigureFlash(void);\r
103 \r
104 \r
105 \r
106 /* Haven't found any ID accessable from memory.\r
107  * There is the DBGMCU_IDCODE (0xe0042000) found in RM0041 but it\r
108  * you can't read from that address..\r
109  */\r
110 #if 0\r
111 cpu_info_t cpu_info_list[] = {\r
112     {\r
113     .name = "????",\r
114     .pvr = 0,\r
115     },\r
116 };\r
117 #endif\r
118 \r
119 /* The supported cores\r
120  */\r
121 core_info_t core_info_list[] = {\r
122     {\r
123     .name = "CORE_ARM_CORTEX_M3",\r
124     .pvr = CORE_CPUID_CORTEX_M3,\r
125     },\r
126 };\r
127 \r
128 #if 0\r
129 static cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)\r
130 {\r
131   int i;\r
132   for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {\r
133     if (cpu_info_list[i].pvr == pvr) {\r
134       return &cpu_info_list[i];\r
135     }\r
136   }\r
137 \r
138   return NULL;\r
139 }\r
140 #endif\r
141 \r
142 \r
143 static core_info_t *Mcu_IdentifyCore(uint32 pvr)\r
144 {\r
145   int i;\r
146   for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {\r
147     if (core_info_list[i].pvr == pvr) {\r
148       return &core_info_list[i];\r
149     }\r
150   }\r
151 \r
152   return NULL;\r
153 }\r
154 \r
155 /**\r
156  * Identify the core, just to check that we have support for it.\r
157  *\r
158  * @return\r
159  */\r
160 static uint32 Mcu_CheckCpu( void ) {\r
161 \r
162   uint32 pvr = SCB->CPUID;\r
163   //uint32 pir;\r
164   //cpu_info_t *cpuType;\r
165   core_info_t *coreType;\r
166 \r
167   //cpuType = Mcu_IdentifyCpu(pvr);\r
168   coreType = Mcu_IdentifyCore(pvr);\r
169 \r
170   if( (coreType == NULL) ) {\r
171     // Just hang\r
172     while(1) ;\r
173   }\r
174 \r
175   return 0;\r
176 }\r
177 \r
178 static uint32_t GetPllValueFromMult(uint8_t pll)\r
179 {\r
180         return (((uint32_t)pll - 2) << 18);\r
181 }\r
182 \r
183 #ifdef STM32F10X_CL\r
184 static uint32_t GetPll2ValueFromMult(uint8_t pll)\r
185 {\r
186         return (((uint32_t)pll - 2) << 8);\r
187 }\r
188 #endif\r
189 \r
190 /**\r
191   * Set bus clocks. SysClk,AHBClk,APB1Clk,APB2Clk\r
192   */\r
193 static void SetClocks(Mcu_ClockSettingConfigType *clockSettingsPtr)\r
194 {\r
195   volatile uint32 StartUpCounter = 0, HSEStatus = 0;\r
196 \r
197   /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/\r
198   /* Enable HSE */\r
199   RCC->CR |= ((uint32_t)RCC_CR_HSEON);\r
200 \r
201   /* Wait till HSE is ready and if Time out is reached exit */\r
202   do\r
203   {\r
204     HSEStatus = RCC->CR & RCC_CR_HSERDY;\r
205     StartUpCounter++;\r
206   } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));\r
207 \r
208   if ((RCC->CR & RCC_CR_HSERDY) != RESET)\r
209   {\r
210     HSEStatus = (uint32_t)0x01;\r
211   }\r
212   else\r
213   {\r
214     HSEStatus = (uint32_t)0x00;\r
215   }\r
216 \r
217   if (HSEStatus == (uint32_t)0x01)\r
218   {\r
219     /* Enable Prefetch Buffer */\r
220     FLASH->ACR |= FLASH_ACR_PRFTBE;\r
221 \r
222     /* Flash 2 wait state */\r
223     FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);\r
224     FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;\r
225 \r
226 \r
227     /* HCLK = SYSCLK */\r
228     RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;\r
229 \r
230     /* PCLK2 = HCLK */\r
231     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;\r
232 \r
233     /* PCLK1 = HCLK */\r
234     RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;\r
235 \r
236 #ifdef STM32F10X_CL\r
237     /* Configure PLLs ------------------------------------------------------*/\r
238     /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */\r
239     /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */\r
240 \r
241     RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |\r
242                               RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);\r
243     RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | GetPll2ValueFromMult(clockSettingsPtr->Pll2) |\r
244                              RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);\r
245 \r
246     /* Enable PLL2 */\r
247     RCC->CR |= RCC_CR_PLL2ON;\r
248     /* Wait till PLL2 is ready */\r
249     while((RCC->CR & RCC_CR_PLL2RDY) == 0)\r
250     {\r
251     }\r
252 \r
253     /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */\r
254     RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);\r
255     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |\r
256                                 GetPllValueFromMult(clockSettingsPtr->Pll1));\r
257 #else\r
258     /*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */\r
259     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |\r
260                                         RCC_CFGR_PLLMULL));\r
261     RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | GetPllValueFromMult(clockSettingsPtr->Pll1));\r
262 #endif /* STM32F10X_CL */\r
263 \r
264     /* Enable PLL */\r
265     RCC->CR |= RCC_CR_PLLON;\r
266 \r
267     /* Wait till PLL is ready */\r
268     while((RCC->CR & RCC_CR_PLLRDY) == 0)\r
269     {\r
270     }\r
271 \r
272     /* Select PLL as system clock source */\r
273     RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));\r
274     RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;\r
275 \r
276     /* Wait till PLL is used as system clock source */\r
277     while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)\r
278     {\r
279     }\r
280   }\r
281   else\r
282   { /* HSE fails to start-up, the application will have wrong clock */\r
283           NVIC_SystemReset();\r
284   }\r
285 }\r
286 \r
287 /**\r
288   * Initialize Peripherals clocks\r
289   */\r
290 static void InitPerClocks()\r
291 {\r
292         RCC->AHBENR |= McuPerClockConfigData.AHBClocksEnable;\r
293         RCC->APB1ENR |= McuPerClockConfigData.APB1ClocksEnable;\r
294         RCC->APB2ENR |= McuPerClockConfigData.APB2ClocksEnable;\r
295 }\r
296 \r
297 /**\r
298   * Initialize Flash, PLL and clocks.\r
299   */\r
300 static void InitMcuClocks(Mcu_ClockSettingConfigType *clockSettingsPtr)\r
301 {\r
302   /* Reset the RCC clock configuration to the default reset state(for debug purpose) */\r
303   /* Set HSION bit */\r
304   RCC->CR |= (uint32_t)0x00000001;\r
305 \r
306   /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */\r
307 #ifndef STM32F10X_CL\r
308   RCC->CFGR &= (uint32_t)0xF8FF0000;\r
309 #else\r
310   RCC->CFGR &= (uint32_t)0xF0FF0000;\r
311 #endif /* STM32F10X_CL */\r
312 \r
313   /* Reset HSEON, CSSON and PLLON bits */\r
314   RCC->CR &= (uint32_t)0xFEF6FFFF;\r
315 \r
316   /* Reset HSEBYP bit */\r
317   RCC->CR &= (uint32_t)0xFFFBFFFF;\r
318 \r
319   /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */\r
320   RCC->CFGR &= (uint32_t)0xFF80FFFF;\r
321 \r
322 #ifndef STM32F10X_CL\r
323   /* Disable all interrupts and clear pending bits  */\r
324   RCC->CIR = 0x009F0000;\r
325 #else\r
326   /* Reset PLL2ON and PLL3ON bits */\r
327   RCC->CR &= (uint32_t)0xEBFFFFFF;\r
328 \r
329   /* Disable all interrupts and clear pending bits  */\r
330   RCC->CIR = 0x00FF0000;\r
331 \r
332   /* Reset CFGR2 register */\r
333   RCC->CFGR2 = 0x00000000;\r
334 #endif /* STM32F10X_CL */\r
335 \r
336   /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */\r
337   /* Configure the Flash Latency cycles and enable prefetch buffer */\r
338   SetClocks(clockSettingsPtr);\r
339 }\r
340 \r
341 //-------------------------------------------------------------------\r
342 \r
343 void Mcu_Init(const Mcu_ConfigType *configPtr)\r
344 {\r
345   VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );\r
346 \r
347 #if !defined(USE_SIMULATOR)\r
348   Mcu_CheckCpu();\r
349 #endif\r
350 \r
351   memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));\r
352 \r
353   Irq_Enable();\r
354 \r
355   Mcu_Global.config = configPtr;\r
356   Mcu_Global.initRun = 1;\r
357 }\r
358 //-------------------------------------------------------------------\r
359 \r
360 void Mcu_DeInit()\r
361 {\r
362   Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?\r
363 }\r
364 \r
365 //-------------------------------------------------------------------\r
366 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)\r
367 {\r
368   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
369   VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );\r
370 \r
371   /* NOT SUPPORTED, reason: no support for external RAM */\r
372 \r
373   return E_OK;\r
374 }\r
375 \r
376 \r
377 \r
378 //-------------------------------------------------------------------\r
379 \r
380 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)\r
381 {\r
382   Mcu_ClockSettingConfigType *clockSettingsPtr;\r
383   VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );\r
384   VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );\r
385 \r
386   Mcu_Global.clockSetting = ClockSetting;\r
387   clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];\r
388 \r
389   InitMcuClocks(clockSettingsPtr);\r
390 \r
391   InitPerClocks(clockSettingsPtr);\r
392 \r
393   return E_OK;\r
394 }\r
395 \r
396 //-------------------------------------------------------------------\r
397 \r
398 void Mcu_DistributePllClock(void)\r
399 {\r
400   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );\r
401 //  VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );\r
402 \r
403   /* NOT IMPLEMENTED due to pointless function on this hardware */\r
404 \r
405 }\r
406 \r
407 //-------------------------------------------------------------------\r
408 \r
409 \r
410 Mcu_PllStatusType Mcu_GetPllStatus(void) {\r
411         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );\r
412         Mcu_PllStatusType rv;\r
413 \r
414 #if !defined(USE_SIMULATOR)\r
415         if (RCC->CR & RCC_CR_PLLRDY) {\r
416                 rv = MCU_PLL_LOCKED;\r
417         } else {\r
418                 rv = MCU_PLL_UNLOCKED;\r
419         }\r
420 #else\r
421         /* We are running on instruction set simulator. PLL is then always in sync... */\r
422         rv = MCU_PLL_LOCKED;\r
423 #endif\r
424         return rv;\r
425 }\r
426 \r
427 //-------------------------------------------------------------------\r
428 \r
429 /**\r
430  *\r
431  * @return\r
432  */\r
433 Mcu_ResetType Mcu_GetResetReason(void) {\r
434         Mcu_ResetType rv;\r
435         uint32_t csr;\r
436 \r
437         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );\r
438 \r
439         csr = RCC->CSR;\r
440 \r
441         if (csr & RCC_CSR_SFTRSTF) {\r
442                 rv = MCU_SW_RESET;\r
443         } else if (csr & (RCC_CSR_IWDGRSTF|RCC_CSR_WWDGRSTF) ) {\r
444                 rv = MCU_WATCHDOG_RESET;\r
445         } else if ( csr & RCC_CSR_PORRSTF ) {\r
446                 rv = MCU_POWER_ON_RESET;\r
447         } else {\r
448                 rv = MCU_RESET_UNDEFINED;\r
449         }\r
450 \r
451         return rv;\r
452 }\r
453 \r
454 //-------------------------------------------------------------------\r
455 \r
456 /**\r
457  * Shall read the raw reset value from hardware register if the hardware\r
458  * supports this.\r
459  *\r
460  * @return\r
461  */\r
462 \r
463 Mcu_RawResetType Mcu_GetResetRawValue(void) {\r
464         VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );\r
465 \r
466         if (!Mcu_Global.initRun) {\r
467                 return MCU_GETRESETRAWVALUE_UNINIT_RV;\r
468         } else {\r
469                 return (RCC->CSR) & (RCC_CSR_RMVF | RCC_CSR_PINRSTF | RCC_CSR_PORRSTF\r
470                                 | RCC_CSR_SFTRSTF | RCC_CSR_IWDGRSTF | RCC_CSR_WWDGRSTF\r
471                                 | RCC_CSR_LPWRRSTF);\r
472         }\r
473         return 0;\r
474 }\r
475 \r
476 //-------------------------------------------------------------------\r
477 \r
478 #if ( MCU_PERFORM_RESET_API == STD_ON )\r
479 /**\r
480  * Shell perform a microcontroller reset by using the hardware feature\r
481  * of the micro controller.\r
482  */\r
483 void Mcu_PerformReset(void)\r
484 {\r
485   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );\r
486 \r
487   NVIC_SystemReset();\r
488 }\r
489 #endif\r
490 \r
491 //-------------------------------------------------------------------\r
492 \r
493 void Mcu_SetMode(const Mcu_ModeType McuMode)\r
494 {\r
495   VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );\r
496   VALIDATE( (0), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
497   //VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );\r
498   (void) McuMode;\r
499 \r
500   /* NOT SUPPORTED */\r
501 }\r
502 \r
503 //-------------------------------------------------------------------\r
504 \r
505 /**\r
506  * Get the system clock in Hz. It calculates the clock from the\r
507  * different register settings in HW.\r
508  */\r
509 uint32_t McuE_GetSystemClock(void)\r
510 {\r
511   uint32_t f_sys;\r
512 \r
513   uint32  extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;\r
514   uint32 pll1 = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].Pll1;\r
515 \r
516 #ifdef STM32F10X_CL\r
517   uint32 pll2 = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].Pll2;\r
518   /* PLL2 configuration: PLL2CLK = (HSE / 5) * PLL2 */\r
519   /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 */\r
520   /* PLL configuration: PLLCLK = PREDIV1 * PLL1 */\r
521   f_sys = (extal / 5 * pll2) / 5 * pll1;\r
522 #else\r
523   /* PLL configuration: PLLCLK = HSE * PLL1 */\r
524   f_sys = extal * pll1;\r
525 #endif\r
526 \r
527   return f_sys;\r
528 }\r
529 \r
530 /**\r
531  * Get the peripheral clock in Hz for a specific device\r
532  */\r
533 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)\r
534 {\r
535         uint32_t res = 0;\r
536 \r
537         switch(type)\r
538         {\r
539         case PERIPHERAL_CLOCK_AHB:\r
540                 res = McuE_GetSystemClock();\r
541                 break;\r
542         case PERIPHERAL_CLOCK_APB1:\r
543                 res = McuE_GetSystemClock() / 2;\r
544                 break;\r
545         case PERIPHERAL_CLOCK_APB2:\r
546                 res = McuE_GetSystemClock();\r
547                 break;\r
548         default:\r
549                 break;\r
550         }\r
551 \r
552         return res;\r
553 }\r
554 \r
555 \r
556 /**\r
557  * Function to setup the internal flash for optimal performance\r
558  */\r
559 \r
560 void Mcu_ConfigureFlash(void)\r
561 {\r
562 \r
563 }\r