mirror of
https://gitea.osmocom.org/sim-card/simtrace2.git
synced 2026-03-16 21:28:33 +03:00
185 lines
6.3 KiB
C
185 lines
6.3 KiB
C
/* ----------------------------------------------------------------------------
|
|
* ATMEL Microcontroller Software Support
|
|
* ----------------------------------------------------------------------------
|
|
* Copyright (c) 2009, 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.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
* 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[] = {
|
|
|
|
/* PCK = 24 MHz, MCK = 24 MHz
|
|
* PCK = 12000000 * (7+1) / 2 / 2 = 24 MHz
|
|
*/
|
|
{24, 24, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
|
|
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
|
|
| (2 << CKGR_DIV_SHIFT)),
|
|
( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
|
|
/* PCK = 48 MHz, MCK = 48 MHz
|
|
* PCK = 12000000 * (7+1) / 1 / 2 = 48 MHz
|
|
*/
|
|
{48, 48, (CKGR_PLLAR_STUCKTO1 | (7 << CKGR_MUL_SHIFT) \
|
|
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
|
|
| (1 << CKGR_DIV_SHIFT)),
|
|
( PMC_MCKR_PRES_CLK_2 | PMC_MCKR_CSS_PLLA_CLK)},
|
|
/* PCK = 64 MHz, MCK = 64 MHz
|
|
* PCK = 12000000 * (15+1) / 3 / 1 = 64 MHz
|
|
*/
|
|
{64, 64, (CKGR_PLLAR_STUCKTO1 | (15 << CKGR_MUL_SHIFT) \
|
|
| (0x3f << CKGR_PLLCOUNT_SHIFT) \
|
|
| (3 << CKGR_DIV_SHIFT)),
|
|
( PMC_MCKR_PRES_CLK | 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 */
|
|
PMC->PMC_MCKR = (PMC->PMC_MCKR & (uint32_t)~PMC_MCKR_CSS_Msk) | 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 */
|
|
PMC->PMC_MCKR = (clockConfigurations[configuration].mckr & (uint32_t)~PMC_MCKR_CSS_Msk) | 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 */
|
|
UART_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 = UART_GetChar();
|
|
|
|
if ((key >= '0') && (key <= ('0' + NB_CLOCK_CONFIGURATION - 1)))
|
|
{
|
|
CLOCK_SetConfig(key - '0');
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|