/* ---------------------------------------------------------------------------- | |
* SAM Software Package License | |
* ---------------------------------------------------------------------------- | |
* Copyright (c) 2011, Atmel Corporation | |
* | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions are met: | |
* | |
* - Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the disclaimer below. | |
* | |
* Atmel's name may not be used to endorse or promote products derived from | |
* this software without specific prior written permission. | |
* | |
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR | |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE | |
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, | |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | |
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
* ---------------------------------------------------------------------------- | |
*/ | |
/** \file */ | |
/*---------------------------------------------------------------------------- | |
* Headers | |
*----------------------------------------------------------------------------*/ | |
#include "board.h" | |
/*---------------------------------------------------------------------------- | |
* Types | |
*----------------------------------------------------------------------------*/ | |
/* | |
* \brief Describes a possible clock configuration (processor clock & master clock), | |
* including the necessary register values. | |
*/ | |
typedef struct _ClockConfiguration | |
{ | |
/** Processor clock frequency (in MHz). */ | |
uint16_t pck; | |
/** Master clock frequency (in MHz). */ | |
uint16_t mck; | |
/** CKGR_PLL reqister value. */ | |
uint32_t pllr; | |
/** PMC_MCKR register value. */ | |
uint32_t mckr; | |
} ClockConfiguration ; | |
/*---------------------------------------------------------------------------- | |
* Local variables | |
*----------------------------------------------------------------------------*/ | |
/* Clock configurations for the AT91SAM3S4-EK */ | |
#define CKGR_MUL_SHIFT 16 | |
#define CKGR_PLLCOUNT_SHIFT 8 | |
#define CKGR_DIV_SHIFT 0 | |
/* Clock configuration for the AT91SAM3S */ | |
static const ClockConfiguration clockConfigurations[] = { | |
{133, 133, CKGR_PLLAR_STUCKTO1 | CKGR_PLLAR_MULA(199) | |
| CKGR_PLLAR_OUTA(0) | CKGR_PLLAR_PLLACOUNT(64) | CKGR_PLLAR_DIVA(3), | |
PMC_MCKR_CSS_SLOW_CLK | PMC_MCKR_PRES_CLOCK | PMC_MCKR_MDIV_PCK_DIV3 | |
| PMC_MCKR_PLLADIV2_DIV2 | PMC_MCKR_CSS_PLLA_CLK} | |
}; | |
/* Number of available clock configurations */ | |
#define NB_CLOCK_CONFIGURATION (sizeof(clockConfigurations)/sizeof(clockConfigurations[0])) | |
/* Current clock configuration */ | |
uint32_t currentConfig = 0; /* 0 have to be the default configuration */ | |
/*---------------------------------------------------------------------------- | |
* Exported functions | |
*----------------------------------------------------------------------------*/ | |
/** | |
* \brief Sets the specified clock configuration. | |
* | |
* \param configuration Index of the configuration to set. | |
*/ | |
void CLOCK_SetConfig(uint8_t configuration) | |
{ | |
TRACE_DEBUG("Setting clock configuration #%d ... ", configuration); | |
currentConfig = configuration; | |
/* Switch to main oscillator in two operations */ | |
//C->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS) | PMC_MCKR_CSS_MAIN_CLK; | |
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); | |
/* Configure PLL */ | |
PMC->CKGR_PLLAR = clockConfigurations[configuration].pllr; | |
while ((PMC->PMC_SR & PMC_SR_LOCKA) == 0); | |
/* Configure master clock in two operations */ | |
//C->PMC_MCKR = (clockConfigurations[configuration].mckr & (uint32_t)~PMC_MCKR_CSS) | PMC_MCKR_CSS_MAIN_CLK; | |
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); | |
PMC->PMC_MCKR = clockConfigurations[configuration].mckr; | |
while ((PMC->PMC_SR & PMC_SR_MCKRDY) == 0); | |
/* DBGU reconfiguration */ | |
DBGU_Configure(115200, clockConfigurations[configuration].mck*1000000); | |
TRACE_DEBUG("done.\n\r"); | |
} | |
/** | |
* \brief Display the user menu on the DBGU. | |
*/ | |
void CLOCK_DisplayMenu(void) | |
{ | |
uint32_t i; | |
printf("\n\rMenu Clock configuration:\n\r"); | |
for (i = 0; i < NB_CLOCK_CONFIGURATION; i++) { | |
printf(" %u: Set PCK = %3u MHz, MCK = %3u MHz %s\n\r", | |
(unsigned int)i, | |
(unsigned int)clockConfigurations[i].pck, | |
(unsigned int)clockConfigurations[i].mck, | |
(currentConfig==i)?"(curr)":""); | |
} | |
} | |
/** | |
* \brief Get the current MCK | |
*/ | |
uint16_t CLOCK_GetCurrMCK(void) | |
{ | |
return clockConfigurations[currentConfig].mck; | |
} | |
/** | |
* \brief Get the current PCK | |
*/ | |
uint16_t CLOCK_GetCurrPCK(void) | |
{ | |
return clockConfigurations[currentConfig].pck; | |
} | |
/** | |
* \brief Change clock configuration. | |
*/ | |
void CLOCK_UserChangeConfig(void) | |
{ | |
uint8_t key = 0; | |
while (1) | |
{ | |
CLOCK_DisplayMenu(); | |
key = DBGU_GetChar(); | |
if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1))) | |
{ | |
CLOCK_SetConfig(key - '0'); | |
break; | |
} | |
} | |
} | |