1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
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>.
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
14 * -------------------------------- Arctic Core ------------------------------*/
25 #include "Std_Types.h"
\r
31 #include "mpc55xx.h"
\r
35 #include "int_ctrl.h"
\r
37 //#define USE_TRACE 1
\r
38 //#define USE_DEBUG 1
\r
41 #define SYSCLOCK_SELECT_PLL 0x2
\r
43 #if defined(CFG_MPC5567)
\r
44 #define CALC_SYSTEM_CLOCK(_extal,_emfd,_eprediv,_erfd) \
\r
45 ( (_extal) * ((_emfd)+4) / (((_eprediv)+1)*(1<<(_erfd))) )
\r
47 #define CALC_SYSTEM_CLOCK(_extal,_emfd,_eprediv,_erfd) \
\r
48 ( (_extal) * ((_emfd)+16) / (((_eprediv)+1)*((_erfd)+1)) )
\r
51 typedef void (*vfunc_t)();
\r
53 /* Function declarations. */
\r
54 static void Mcu_ConfigureFlash(void);
\r
58 uint32 lossOfLockCnt;
\r
59 uint32 lossOfClockCnt;
\r
63 * Type that holds all global data for Mcu
\r
67 // Set if Mcu_Init() have been called
\r
71 const Mcu_ConfigType *config;
\r
73 Mcu_ClockType clockSetting;
\r
79 /* Development error macros. */
\r
80 #if ( MCU_DEV_ERROR_DETECT == STD_ON )
\r
81 #define VALIDATE(_exp,_api,_err ) \
\r
83 Det_ReportError(MODULE_ID_MCU,0,_api,_err); \
\r
87 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
89 Det_ReportError(MODULE_ID_MCU,0,_api,_err); \
\r
93 #define VALIDATE(_exp,_api,_err )
\r
94 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
98 Mcu_GlobalType Mcu_Global =
\r
101 .config = &McuConfigData[0],
\r
104 //-------------------------------------------------------------------
\r
106 static void Mcu_LossOfLock( void ) {
\r
108 Dem_ReportErrorStatus(MCU_E_CLOCK_FAILURE, DEM_EVENT_STATUS_FAILED);
111 Mcu_Global.stats.lossOfLockCnt++;
\r
113 FMPLL.SYNSR.B.LOLF = 1;
\r
117 //-------------------------------------------------------------------
\r
118 static void Mcu_LossOfCLock( void ) {
\r
120 /* Should report MCU_E_CLOCK_FAILURE with DEM here */
\r
122 Mcu_Global.stats.lossOfClockCnt++;
\r
124 FMPLL.SYNSR.B.LOCF = 1;
\r
128 #define SPR_PIR 286
\r
129 #define SPR_PVR 287
\r
131 #define CORE_PVR_E200Z1 0x81440000UL
\r
132 #define CORE_PVR_E200Z0 0x81710000UL
133 #define CORE_PVR_E200Z3 0x81120000UL
\r
134 #define CORE_PVR_E200Z6 0x81170000UL
\r
147 cpu_info_t cpu_info_list[] =
\r
149 #if defined(CFG_MPC5516)
\r
152 .pvr = CORE_PVR_E200Z1,
\r
156 .pvr = CORE_PVR_E200Z0,
\r
158 #elif defined(CFG_MPC5567)
\r
161 .pvr = CORE_PVR_E200Z6,
\r
163 #elif defined(CFG_MPC5633)
166 .pvr = CORE_PVR_E200Z3,
171 core_info_t core_info_list[] = {
\r
172 #if defined(CFG_MPC5516)
\r
174 .name = "CORE_E200Z1",
\r
175 .pvr = CORE_PVR_E200Z1,
\r
178 .name = "CORE_E200Z1",
\r
179 .pvr = CORE_PVR_E200Z1,
\r
181 #elif defined(CFG_MPC5567)
\r
183 .name = "CORE_E200Z6",
\r
184 .pvr = CORE_PVR_E200Z6,
\r
186 #elif defined(CFG_MPC5633)
188 .name = "CORE_E200Z3",
189 .pvr = CORE_PVR_E200Z3,
195 #if !defined(ARRAY_SIZE)
\r
196 #define ARRAY_SIZE(_x) (sizeof(_x)/sizeof((_x)[0]))
\r
199 static cpu_info_t *Mcu_IdentifyCpu(uint32 pvr)
\r
202 for (i = 0; i < ARRAY_SIZE(cpu_info_list); i++) {
\r
203 if (cpu_info_list[i].pvr == pvr) {
\r
204 return &cpu_info_list[i];
\r
211 static core_info_t *Mcu_IdentifyCore(uint32 pvr)
\r
214 for (i = 0; i < ARRAY_SIZE(core_info_list); i++) {
\r
215 if (core_info_list[i].pvr == pvr) {
\r
216 return &core_info_list[i];
\r
224 static uint32 Mcu_CheckCpu( void ) {
\r
228 cpu_info_t *cpuType;
\r
229 core_info_t *coreType;
\r
231 // We have to registers to read here, PIR and PVR
\r
233 pir = get_spr(SPR_PIR);
\r
234 pvr = get_spr(SPR_PVR);
\r
236 cpuType = Mcu_IdentifyCpu(pvr);
\r
237 coreType = Mcu_IdentifyCore(pvr);
\r
239 if( (cpuType == NULL) || (coreType == NULL) ) {
\r
244 //DEBUG(DEBUG_HIGH,"/drivers/mcu: Cpu: %s( 0x%08x )\n",cpuType->name,pvr);
\r
245 //DEBUG(DEBUG_HIGH,"/drivers/mcu: Core: %s( 0x%08x )\n",coreType->name,pvr);
\r
251 //-------------------------------------------------------------------
\r
253 void Mcu_Init(const Mcu_ConfigType *configPtr)
\r
255 VALIDATE( ( NULL != configPtr ), MCU_INIT_SERVICE_ID, MCU_E_PARAM_CONFIG );
\r
257 if( !SIMULATOR() ) {
\r
261 memset(&Mcu_Global.stats,0,sizeof(Mcu_Global.stats));
\r
267 Mcu_ConfigureFlash();
\r
271 Mcu_Global.config = configPtr;
\r
272 Mcu_Global.initRun = 1;
\r
274 if( Mcu_Global.config->McuClockSrcFailureNotification == TRUE ){
\r
275 // Enable loss of lock interrupt
\r
277 IntCtrl_AttachIsr1(Mcu_LossOfLock, NULL, PLL_SYNSR_LOLF,10 );
\r
278 #if defined(CFG_MPC5516)
\r
279 // FMPLL.SYNCR.B.LOCIRQ = 1; TODO: Kolla denna bortkommentering med Mårten.
\r
280 FMPLL.ESYNCR2.B.LOLIRQ = 1;
\r
281 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)
\r
282 FMPLL.SYNCR.B.LOLIRQ = 1;
\r
284 IntCtrl_AttachIsr1(Mcu_LossOfCLock, NULL, PLL_SYNSR_LOCF,10 );
\r
285 #if defined(CFG_MPC5516)
\r
286 // FMPLL.SYNCR.B.LOCIRQ = 1; TODO: Kolla denna bortkommentering med Mårten.
\r
287 FMPLL.ESYNCR2.B.LOCIRQ = 1;
\r
288 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)
\r
289 FMPLL.SYNCR.B.LOCIRQ = 1;
\r
293 //-------------------------------------------------------------------
\r
297 Mcu_Global.initRun = FALSE; // Very simple Deinit. Should we do more?
\r
300 //-------------------------------------------------------------------
\r
301 Std_ReturnType Mcu_InitRamSection(const Mcu_RamSectionType RamSection)
\r
303 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );
\r
304 VALIDATE_W_RV( ( RamSection <= Mcu_Global.config->McuRamSectors ), MCU_INITRAMSECTION_SERVICE_ID, MCU_E_PARAM_RAMSECTION, E_NOT_OK );
\r
306 /* NOT SUPPORTED, reason: no support for external RAM */
\r
313 //-------------------------------------------------------------------
\r
315 Std_ReturnType Mcu_InitClock(const Mcu_ClockType ClockSetting)
\r
317 Mcu_ClockSettingConfigType *clockSettingsPtr;
\r
318 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_INITCLOCK_SERVICE_ID, MCU_E_UNINIT, E_NOT_OK );
\r
319 VALIDATE_W_RV( ( ClockSetting < Mcu_Global.config->McuClockSettings ), MCU_INITCLOCK_SERVICE_ID, MCU_E_PARAM_CLOCK, E_NOT_OK );
\r
321 Mcu_Global.clockSetting = ClockSetting;
\r
322 clockSettingsPtr = &Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting];
\r
325 // TODO: find out if the 5554 really works like the 5516 here
\r
326 // All three (16, 54, 67) used to run the same code here though, so i'm sticking it with 5516
\r
327 #if defined(CFG_MPC5516) || defined(CFG_MPC5554)
\r
329 * Fsys - System frequency ( CPU + all periperals? )
\r
331 * Fsys = EXTAL_FREQ *( (emfd+16) / ( (eprediv+1) * ( erfd+1 )) ) )
\r
334 assert((clockSettingsPtr->PllEmfd>=32) && (clockSettingsPtr->PllEmfd<=132));
\r
335 assert( (clockSettingsPtr->PllEprediv!=6) &&
\r
336 (clockSettingsPtr->PllEprediv!=8) &&
\r
337 (clockSettingsPtr->PllEprediv<10) );
\r
338 assert( clockSettingsPtr->PllErfd & 1); // Must be odd
\r
339 #elif defined(CFG_MPC5567)
\r
340 /* 5567 clock info:
\r
341 * Fsys = EXTAL_FREQ *( (emfd+4) / ( (eprediv+1) * ( 2^erfd )) ) )
\r
344 assert(clockSettingsPtr->PllEmfd < 16);
\r
345 assert(clockSettingsPtr->PllEprediv <= 4);
\r
346 assert(clockSettingsPtr->PllErfd < 8);
\r
350 #if defined(USE_DEBUG)
\r
352 uint32 extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;
\r
355 f_sys = CALC_SYSTEM_CLOCK( extal,
\r
356 clockSettingsPtr->PllEmfd,
\r
357 clockSettingsPtr->PllEprediv,
\r
358 clockSettingsPtr->PllErfd );
\r
360 //DEBUG(DEBUG_HIGH,"/drivers/mcu: F_sys will be:%08d Hz\n",f_sys);
\r
364 #if defined(CFG_MPC5516)
\r
365 // External crystal PLL mode.
\r
366 FMPLL.ESYNCR1.B.CLKCFG = 7; //TODO: Hur ställa detta för 5567?
\r
368 // Write pll parameters.
\r
369 FMPLL.ESYNCR1.B.EPREDIV = clockSettingsPtr->PllEprediv;
\r
370 FMPLL.ESYNCR1.B.EMFD = clockSettingsPtr->PllEmfd;
\r
371 FMPLL.ESYNCR2.B.ERFD = clockSettingsPtr->PllErfd;
\r
373 // Connect SYSCLK to FMPLL
\r
374 SIU.SYSCLK.B.SYSCLKSEL = SYSCLOCK_SELECT_PLL;
\r
375 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)
\r
376 // Partially following the steps in MPC5567 RM..
\r
377 FMPLL.SYNCR.B.DEPTH = 0;
\r
378 FMPLL.SYNCR.B.LOLRE = 0;
\r
379 FMPLL.SYNCR.B.LOLIRQ = 0;
\r
381 FMPLL.SYNCR.B.PREDIV = clockSettingsPtr->PllEprediv;
\r
382 FMPLL.SYNCR.B.MFD = clockSettingsPtr->PllEmfd;
\r
383 FMPLL.SYNCR.B.RFD = clockSettingsPtr->PllErfd;
\r
385 // Wait for PLL to sync.
\r
386 while (Mcu_GetPllStatus() != MCU_PLL_LOCKED)
\r
389 FMPLL.SYNCR.B.LOLIRQ = 1;
\r
395 //-------------------------------------------------------------------
\r
397 void Mcu_DistributePllClock(void)
\r
399 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_UNINIT );
\r
400 VALIDATE( ( FMPLL.SYNSR.B.LOCK == 1 ), MCU_DISTRIBUTEPLLCLOCK_SERVICE_ID, MCU_E_PLL_NOT_LOCKED );
\r
402 /* NOT IMPLEMENTED due to pointless function on this hardware */
\r
406 //-------------------------------------------------------------------
\r
408 Mcu_PllStatusType Mcu_GetPllStatus(void)
\r
410 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETPLLSTATUS_SERVICE_ID, MCU_E_UNINIT, MCU_PLL_STATUS_UNDEFINED );
\r
411 Mcu_PllStatusType rv;
\r
415 if ( !FMPLL.SYNSR.B.LOCK )
\r
417 rv = MCU_PLL_UNLOCKED;
\r
420 rv = MCU_PLL_LOCKED;
\r
425 /* We are running on instruction set simulator. PLL is then always in sync... */
\r
426 rv = MCU_PLL_LOCKED;
\r
432 //-------------------------------------------------------------------
\r
434 Mcu_ResetType Mcu_GetResetReason(void)
\r
438 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_RESET_UNDEFINED );
\r
440 if( SIU.RSR.B.SSRS ) {
\r
442 } else if( SIU.RSR.B.WDRS ) {
\r
443 rv = MCU_WATCHDOG_RESET;
\r
444 } else if( SIU.RSR.B.PORS || SIU.RSR.B.ERS ) {
\r
445 rv = MCU_POWER_ON_RESET;
\r
447 rv = MCU_RESET_UNDEFINED;
\r
453 //-------------------------------------------------------------------
\r
455 Mcu_RawResetType Mcu_GetResetRawValue(void)
\r
457 VALIDATE_W_RV( ( 1 == Mcu_Global.initRun ), MCU_GETRESETREASON_SERVICE_ID, MCU_E_UNINIT, MCU_GETRESETRAWVALUE_UNINIT_RV );
\r
459 if( !Mcu_Global.initRun ) {
\r
460 return MCU_GETRESETRAWVALUE_UNINIT_RV;
\r
466 //-------------------------------------------------------------------
\r
468 #if ( MCU_PERFORM_RESET_API == STD_ON )
\r
469 void Mcu_PerformReset(void)
\r
471 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_PERFORMRESET_SERVICE_ID, MCU_E_UNINIT );
\r
474 SIU.SRCR.B.SSR = 1;
\r
479 //-------------------------------------------------------------------
\r
481 void Mcu_SetMode(const Mcu_ModeType McuMode)
\r
483 VALIDATE( ( 1 == Mcu_Global.initRun ), MCU_SETMODE_SERVICE_ID, MCU_E_UNINIT );
\r
484 VALIDATE( ( McuMode <= Mcu_Global.config->McuNumberOfMcuModes ), MCU_SETMODE_SERVICE_ID, MCU_E_PARAM_MODE );
\r
487 /* NOT SUPPORTED */
\r
490 //-------------------------------------------------------------------
\r
493 * Get the system clock in Hz. It calculates the clock from the
\r
494 * different register settings in HW.
\r
496 uint32_t McuE_GetSystemClock(void)
\r
499 * System clock calculation
\r
501 * 5516 - f_sys = extal * (emfd+16) / ( (eprediv+1) * ( erfd+1 ));
\r
502 * 5567 - f_sys = extal * (emfd+4) / ( (eprediv+1) * ( 2^erfd ));
503 * 563x - We run in legacy mode = 5567
505 #if defined(CFG_MPC5516)
\r
506 uint32_t eprediv = FMPLL.ESYNCR1.B.EPREDIV;
\r
507 uint32_t emfd = FMPLL.ESYNCR1.B.EMFD;
\r
508 uint32_t erfd = FMPLL.ESYNCR2.B.ERFD;
\r
509 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567) || defined(CFG_MPC5633)
\r
510 uint32_t eprediv = FMPLL.SYNCR.B.PREDIV;
\r
511 uint32_t emfd = FMPLL.SYNCR.B.MFD;
\r
512 uint32_t erfd = FMPLL.SYNCR.B.RFD;
\r
515 uint32 extal = Mcu_Global.config->McuClockSettingConfig[Mcu_Global.clockSetting].McuClockReferencePoint;
\r
517 f_sys = CALC_SYSTEM_CLOCK(extal,emfd,eprediv,erfd);
522 imask_t McuE_EnterCriticalSection()
\r
524 uint32_t msr = get_msr();
\r
529 void McuE_ExitCriticalSection(uint32_t old_state)
\r
531 set_msr(old_state);
\r
535 * Get the peripheral clock in Hz for a specific device
\r
538 uint32_t McuE_GetPeripheralClock(McuE_PeriperalClock_t type)
\r
540 #if defined(CFG_MPC5567)
\r
541 // No peripheral dividers on 5567.
\r
542 return McuE_GetSystemClock();
\r
544 uint32_t sysClock = McuE_GetSystemClock();
\r
545 vuint32_t prescaler;
\r
548 // See table 3.1, section 3.4.5 Peripheral Clock dividers
\r
551 case PERIPHERAL_CLOCK_FLEXCAN_A:
\r
552 case PERIPHERAL_CLOCK_DSPI_A:
\r
553 #if defined(CFG_MPC5516)
\r
554 prescaler = SIU.SYSCLK.B.LPCLKDIV0;
\r
558 case PERIPHERAL_CLOCK_PIT:
\r
559 case PERIPHERAL_CLOCK_ESCI_A:
\r
560 case PERIPHERAL_CLOCK_IIC_A:
\r
561 #if defined(CFG_MPC5516)
\r
562 prescaler = SIU.SYSCLK.B.LPCLKDIV1;
\r
566 case PERIPHERAL_CLOCK_FLEXCAN_B:
\r
567 case PERIPHERAL_CLOCK_FLEXCAN_C:
\r
568 case PERIPHERAL_CLOCK_FLEXCAN_D:
\r
569 case PERIPHERAL_CLOCK_FLEXCAN_E:
\r
570 case PERIPHERAL_CLOCK_FLEXCAN_F:
\r
571 #if defined(CFG_MPC5516)
\r
572 prescaler = SIU.SYSCLK.B.LPCLKDIV2;
\r
576 case PERIPHERAL_CLOCK_DSPI_B:
\r
577 case PERIPHERAL_CLOCK_DSPI_C:
\r
578 case PERIPHERAL_CLOCK_DSPI_D:
\r
579 #if defined(CFG_MPC5516)
\r
580 prescaler = SIU.SYSCLK.B.LPCLKDIV3;
\r
584 case PERIPHERAL_CLOCK_ESCI_B:
\r
585 case PERIPHERAL_CLOCK_ESCI_C:
\r
586 case PERIPHERAL_CLOCK_ESCI_D:
\r
587 case PERIPHERAL_CLOCK_ESCI_E:
\r
588 case PERIPHERAL_CLOCK_ESCI_F:
\r
589 case PERIPHERAL_CLOCK_ESCI_G:
\r
590 case PERIPHERAL_CLOCK_ESCI_H:
\r
591 #if defined(CFG_MPC5516)
\r
592 prescaler = SIU.SYSCLK.B.LPCLKDIV4;
\r
596 case PERIPHERAL_CLOCK_EMIOS:
\r
597 #if defined(CFG_MPC5516)
\r
598 prescaler = SIU.SYSCLK.B.LPCLKDIV5;
\r
602 case PERIPHERAL_CLOCK_MLB:
\r
603 #if defined(CFG_MPC5516)
\r
604 prescaler = SIU.SYSCLK.B.LPCLKDIV6;
\r
613 return sysClock/(1<<prescaler);
\r
619 * Function to setup the internal flash for optimal performance
\r
622 static void Mcu_ConfigureFlash(void)
\r
624 /* These flash settings increases the CPU performance of 7 times compared
\r
625 to reset default settings!! */
\r
627 #if defined(CFG_MPC5516)
\r
628 /* Disable pipelined reads when flash options are changed. */
\r
629 FLASH.MCR.B.PRD = 1;
\r
631 /* Enable master prefetch for e200z1 and eDMA. */
\r
632 FLASH.PFCRP0.B.M0PFE = 1;
\r
633 FLASH.PFCRP0.B.M2PFE = 1;
\r
635 /* Address pipelining control. Must be set to the same value as RWSC. */
\r
636 FLASH.PFCRP0.B.APC = 2;
\r
637 FLASH.PFCRP0.B.RWSC = 2;
\r
639 /* Write wait states. */
\r
640 FLASH.PFCRP0.B.WWSC = 1;
\r
642 /* Enable data prefetch. */
\r
643 FLASH.PFCRP0.B.DPFEN = 1;
\r
645 /* Enable instruction prefetch. */
\r
646 FLASH.PFCRP0.B.IPFEN = 1;
\r
648 /* Prefetch algorithm. */
\r
649 /* TODO: Ask Freescale about this option. */
\r
650 FLASH.PFCRP0.B.PFLIM = 2;
\r
652 /* Enable line read buffers. */
\r
653 FLASH.PFCRP0.B.BFEN = 1;
\r
655 /* Enable pipelined reads again. */
\r
656 FLASH.MCR.B.PRD = 0;
\r
657 #elif defined(CFG_MPC5554) || defined(CFG_MPC5567)
\r
658 //TODO: Lägg till flash för mpc5554 &67
\r
662 void McuE_EnableInterrupts(void)
\r
667 void McuE_DisableInterrupts(void)
\r