blob: cf015450d6ee695c7c963af2927518d65ab59196 [file] [log] [blame]
/* ----------------------------------------------------------------------------
* 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;
}
}
}