1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
17 #include "Std_Types.h"
\r
20 #if defined(USE_DEM)
\r
28 //#define USE_TRACE 1
\r
29 //#define USE_LDEBUG_PRINTF 1
\r
34 #define ARRAY_SIZE(_x) (sizeof(_x)/sizeof((_x)[0]))
\r
37 /* Development error macros. */
\r
38 #if ( MCU_DEV_ERROR_DETECT == STD_ON )
\r
39 #define VALIDATE(_exp,_api,_err ) \
\r
41 Det_ReportError(MODULE_ID_MCU,0,_api,_err); \
\r
45 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
47 Det_ReportError(MODULE_ID_MCU,0,_api,_err); \
\r
51 #define VALIDATE(_exp,_api,_err )
\r
52 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
56 #define CORE_CPUID_CORTEX_M3 0x411FC231UL
\r
61 uint32 lossOfLockCnt;
\r
62 uint32 lossOfClockCnt;
\r
66 * Type that holds all global data for Mcu
\r
70 // Set if Mcu_Init() have been called
\r
74 const Mcu_ConfigType *config;
\r
76 Mcu_ClockType clockSetting;
\r
84 Mcu_GlobalType Mcu_Global =
\r
87 .config = &McuConfigData[0],
\r
90 //-------------------------------------------------------------------
\r
103 void Mcu_ConfigureFlash(void);
\r
107 /* Haven't found any ID accessable from memory.
\r
108 * There is the DBGMCU_IDCODE (0xe0042000) found in RM0041 but it
\r
109 * you can't read from that address..
\r
112 cpu_info_t cpu_info_list[] = {
\r
120 /* The supported cores
\r
122 core_info_t core_info_list[] = {
\r
124 .name = "CORE_ARM_CORTEX_M3",
\r
125 .pvr = CORE_CPUID_CORTEX_M3,
\r
130 static cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)
\r
133 for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {
\r
134 if (cpu_info_list[i].pvr == pvr) {
\r
135 return &cpu_info_list[i];
\r
144 static core_info_t *Mcu_IdentifyCore(uint32 pvr)
\r
147 for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {
\r
148 if (core_info_list[i].pvr == pvr) {
\r
149 return &core_info_list[i];
\r
157 * Identify the core, just to check that we have support for it.
\r
161 static uint32 Mcu_CheckCpu( void ) {
\r
163 uint32 pvr = SCB->CPUID;
\r
165 //cpu_info_t *cpuType;
\r
166 core_info_t *coreType;
\r
168 //cpuType = Mcu_IdentifyCpu(pvr);
\r
169 coreType = Mcu_IdentifyCore(pvr);
\r
171 if( (coreType == NULL) ) {
\r
179 static uint32_t GetPllValueFromMult(uint8_t pll)
\r
181 return (((uint32_t)pll - 2) << 18);
\r
183 static uint32_t GetPll2ValueFromMult(uint8_t pll)
\r
185 return (((uint32_t)pll - 2) << 8);
\r
189 * Set bus clocks. SysClk,AHBClk,APB1Clk,APB2Clk
\r
191 static void SetClocks(Mcu_ClockSettingConfigType *clockSettingsPtr)
\r
193 volatile uint32 StartUpCounter = 0, HSEStatus = 0;
\r
195 /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
\r
197 RCC->CR |= ((uint32_t)RCC_CR_HSEON);
\r
199 /* Wait till HSE is ready and if Time out is reached exit */
\r
202 HSEStatus = RCC->CR & RCC_CR_HSERDY;
\r
204 } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));
\r
206 if ((RCC->CR & RCC_CR_HSERDY) != RESET)
\r
208 HSEStatus = (uint32_t)0x01;
\r
212 HSEStatus = (uint32_t)0x00;
\r
215 if (HSEStatus == (uint32_t)0x01)
\r
217 /* Enable Prefetch Buffer */
\r
218 FLASH->ACR |= FLASH_ACR_PRFTBE;
\r
220 /* Flash 2 wait state */
\r
221 FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
\r
222 FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
\r
225 /* HCLK = SYSCLK */
\r
226 RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
\r
229 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
\r
232 RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
\r
234 #ifdef STM32F10X_CL
\r
235 /* Configure PLLs ------------------------------------------------------*/
\r
236 /* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
\r
237 /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
\r
239 RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
\r
240 RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
\r
241 RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | GetPll2ValueFromMult(clockSettingsPtr->Pll2) |
\r
242 RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
\r
245 RCC->CR |= RCC_CR_PLL2ON;
\r
246 /* Wait till PLL2 is ready */
\r
247 while((RCC->CR & RCC_CR_PLL2RDY) == 0)
\r
251 /* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
\r
252 RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
\r
253 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
\r
254 GetPllValueFromMult(clockSettingsPtr->Pll1));
\r
256 /* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
\r
257 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
\r
258 RCC_CFGR_PLLMULL));
\r
259 RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | GetPllValueFromMult(clockSettingsPtr->Pll1));
\r
260 #endif /* STM32F10X_CL */
\r
263 RCC->CR |= RCC_CR_PLLON;
\r
265 /* Wait till PLL is ready */
\r
266 while((RCC->CR & RCC_CR_PLLRDY) == 0)
\r
270 /* Select PLL as system clock source */
\r
271 RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
\r
272 RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
\r
274 /* Wait till PLL is used as system clock source */
\r
275 while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
\r
280 { /* HSE fails to start-up, the application will have wrong clock */
\r
281 NVIC_SystemReset();
\r
286 * Initialize Peripherals clocks
\r
288 static void InitPerClocks()
\r
290 RCC->AHBENR |= McuPerClockConfigData.AHBClocksEnable;
\r
291 RCC->APB1ENR |= McuPerClockConfigData.APB1ClocksEnable;
\r
292 RCC->APB2ENR |= McuPerClockConfigData.APB2ClocksEnable;
\r
296 * Initialize Flash, PLL and clocks.
\r
298 static void InitMcuClocks(Mcu_ClockSettingConfigType *clockSettingsPtr)
\r
300 /* Reset the RCC clock configuration to the default reset state(for debug purpose) */
\r
301 /* Set HSION bit */
\r
302 RCC->CR |= (uint32_t)0x00000001;
\r
304 /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
\r
305 #ifndef STM32F10X_CL
\r
306 RCC->CFGR &= (uint32_t)0xF8FF0000;
\r
308 RCC->CFGR &= (uint32_t)0xF0FF0000;
\r
309 #endif /* STM32F10X_CL */
\r
311 /* Reset HSEON, CSSON and PLLON bits */
\r
312 RCC->CR &= (uint32_t)0xFEF6FFFF;
\r
314 /* Reset HSEBYP bit */
\r
315 RCC->CR &= (uint32_t)0xFFFBFFFF;
\r
317 /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
\r
318 RCC->CFGR &= (uint32_t)0xFF80FFFF;
\r
320 #ifndef STM32F10X_CL
\r
321 /* Disable all interrupts and clear pending bits */
\r
322 RCC->CIR = 0x009F0000;
\r
324 /* Reset PLL2ON and PLL3ON bits */
\r
325 RCC->CR &= (uint32_t)0xEBFFFFFF;
\r
327 /* Disable all interrupts and clear pending bits */
\r
328 RCC->CIR = 0x00FF0000;
\r
330 /* Reset CFGR2 register */
\r
331 RCC->CFGR2 = 0x00000000;
\r
332 #endif /* STM32F10X_CL */
\r
334 /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
\r
335 /* Configure the Flash Latency cycles and enable prefetch buffer */
\r
336 SetClocks(clockSettingsPtr);
\r
339 //-------------------------------------------------------------------
\r
341 void Mcu_Init(const Mcu_ConfigType *configPtr)
\r
343 VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );
\r
345 #if !defined(USE_SIMULATOR)
\r
349 memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));
\r
353 Mcu_Global.config = configPtr;
\r
354 Mcu_Global.initRun = 1;
\r
356 //-------------------------------------------------------------------
\r
360 Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?
\r
363 //-------------------------------------------------------------------
\r
364 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)
\r
366 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );
\r
367 VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );
\r
369 /* NOT SUPPORTED, reason: no support for external RAM */
\r
376 //-------------------------------------------------------------------
\r
378 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)
\r
380 Mcu_ClockSettingConfigType *clockSettingsPtr;
\r
381 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );
\r
382 VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );
\r
384 Mcu_Global.clockSetting = ClockSetting;
\r
385 clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];
\r
387 InitMcuClocks(clockSettingsPtr);
\r
389 InitPerClocks(clockSettingsPtr);
\r
394 //-------------------------------------------------------------------
\r
396 void Mcu_DistributePllClock(void)
\r
398 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );
\r
399 // VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );
\r
401 /* NOT IMPLEMENTED due to pointless function on this hardware */
\r
405 //-------------------------------------------------------------------
\r
408 Mcu_PllStatusType Mcu_GetPllStatus(void) {
\r
409 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );
\r
410 Mcu_PllStatusType rv;
\r
412 #if !defined(USE_SIMULATOR)
\r
413 if (RCC->CR & RCC_CR_PLLRDY) {
\r
414 rv = MCU_PLL_LOCKED;
\r
416 rv = MCU_PLL_UNLOCKED;
\r
419 /* We are running on instruction set simulator. PLL is then always in sync... */
\r
420 rv = MCU_PLL_LOCKED;
\r
425 //-------------------------------------------------------------------
\r
431 Mcu_ResetType Mcu_GetResetReason(void) {
\r
435 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );
\r
439 if (csr & RCC_CSR_SFTRSTF) {
\r
441 } else if (csr & (RCC_CSR_IWDGRSTF|RCC_CSR_WWDGRSTF) ) {
\r
442 rv = MCU_WATCHDOG_RESET;
\r
443 } else if ( csr & RCC_CSR_PORRSTF ) {
\r
444 rv = MCU_POWER_ON_RESET;
\r
446 rv = MCU_RESET_UNDEFINED;
\r
452 //-------------------------------------------------------------------
\r
455 * Shall read the raw reset value from hardware register if the hardware
\r
461 Mcu_RawResetType Mcu_GetResetRawValue(void) {
\r
462 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );
\r
464 if (!Mcu_Global.initRun) {
\r
465 return MCU_GETRESETRAWVALUE_UNINIT_RV;
\r
467 return (RCC->CSR) & (RCC_CSR_RMVF | RCC_CSR_PINRSTF | RCC_CSR_PORRSTF
\r
468 | RCC_CSR_SFTRSTF | RCC_CSR_IWDGRSTF | RCC_CSR_WWDGRSTF
\r
469 | RCC_CSR_LPWRRSTF);
\r
474 //-------------------------------------------------------------------
\r
476 #if ( MCU_PERFORM_RESET_API == STD_ON )
\r
478 * Shell perform a microcontroller reset by using the hardware feature
\r
479 * of the micro controller.
\r
481 void Mcu_PerformReset(void)
\r
483 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );
\r
485 NVIC_SystemReset();
\r
489 //-------------------------------------------------------------------
\r
491 void Mcu_SetMode(const Mcu_ModeType McuMode)
\r
493 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );
\r
494 VALIDATE( (0), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );
\r
495 //VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );
\r
498 /* NOT SUPPORTED */
\r
501 //-------------------------------------------------------------------
\r
504 * Get the system clock in Hz. It calculates the clock from the
\r
505 * different register settings in HW.
\r
507 uint32_t McuE_GetSystemClock(void)
\r
511 uint32 extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePointFrequency;
\r
512 uint32 pll1 = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].Pll1;
\r
514 #ifdef STM32F10X_CL
\r
515 uint32 pll2 = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].Pll2;
\r
516 /* PLL2 configuration: PLL2CLK = (HSE / 5) * PLL2 */
\r
517 /* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 */
\r
518 /* PLL configuration: PLLCLK = PREDIV1 * PLL1 */
\r
519 f_sys = (extal / 5 * pll2) / 5 * pll1;
\r
521 /* PLL configuration: PLLCLK = HSE * PLL1 */
\r
522 f_sys = extal * pll1;
\r
528 imask_t McuE_EnterCriticalSection()
\r
535 void McuE_ExitCriticalSection(uint32_t old_state)
\r
537 Irq_Restore(old_state);
\r
541 * Get the peripheral clock in Hz for a specific device
\r
543 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)
\r
549 case PERIPHERAL_CLOCK_AHB:
\r
550 res = McuE_GetSystemClock();
\r
552 case PERIPHERAL_CLOCK_APB1:
\r
553 res = McuE_GetSystemClock() / 2;
\r
555 case PERIPHERAL_CLOCK_APB2:
\r
556 res = McuE_GetSystemClock();
\r
567 * Function to setup the internal flash for optimal performance
\r
570 void Mcu_ConfigureFlash(void)
\r
575 void McuE_EnableInterrupts(void)
\r
580 void McuE_DisableInterrupts(void)
\r