cc2538: Allow for configuration of processor speed
This commit is contained in:
parent
730bda2001
commit
d8efa8428c
7 changed files with 107 additions and 38 deletions
|
@ -37,12 +37,12 @@
|
||||||
* Implementation of the clock module for the cc2538
|
* Implementation of the clock module for the cc2538
|
||||||
*
|
*
|
||||||
* To implement the clock functionality, we use the SysTick peripheral on the
|
* To implement the clock functionality, we use the SysTick peripheral on the
|
||||||
* cortex-M3. We run the system clock at 16 MHz and we set the SysTick to give
|
* cortex-M3. We run the system clock at a configurable speed and set the
|
||||||
* us 128 interrupts / sec. However, the Sleep Timer counter value is used for
|
* SysTick to give us 128 interrupts / sec. However, the Sleep Timer counter
|
||||||
* the number of elapsed ticks in order to avoid a significant time drift caused
|
* value is used for the number of elapsed ticks in order to avoid a
|
||||||
* by PM1/2. Contrary to the Sleep Timer, the SysTick peripheral is indeed
|
* significant time drift caused by PM1/2. Contrary to the Sleep Timer, the
|
||||||
* frozen during PM1/2, so adjusting upon wake-up a tick counter based on this
|
* SysTick peripheral is indeed frozen during PM1/2, so adjusting upon wake-up
|
||||||
* peripheral would hardly be accurate.
|
* a tick counter based on this peripheral would hardly be accurate.
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* \file
|
* \file
|
||||||
|
@ -62,7 +62,19 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
|
#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
|
||||||
#define RELOAD_VALUE (125000 - 1) /** Fire 128 times / sec */
|
|
||||||
|
/* Prescaler for GPT0:Timer A used for clock_delay_usec(). */
|
||||||
|
#if SYS_CTRL_SYS_CLOCK < SYS_CTRL_1MHZ
|
||||||
|
#error System clock speeds below 1MHz are not supported
|
||||||
|
#endif
|
||||||
|
#define PRESCALER_VALUE (SYS_CTRL_SYS_CLOCK / SYS_CTRL_1MHZ - 1)
|
||||||
|
|
||||||
|
/* Reload value for SysTick counter */
|
||||||
|
#if SYS_CTRL_SYS_CLOCK % CLOCK_SECOND
|
||||||
|
/* Too low clock speeds will lead to reduced accurracy */
|
||||||
|
#error System clock speed too slow for CLOCK_SECOND, accuracy reduced
|
||||||
|
#endif
|
||||||
|
#define RELOAD_VALUE (SYS_CTRL_SYS_CLOCK / CLOCK_SECOND - 1)
|
||||||
|
|
||||||
static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
|
static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -74,8 +86,8 @@ static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
|
||||||
*
|
*
|
||||||
* We also initialise GPT0:Timer A, which is used by clock_delay_usec().
|
* We also initialise GPT0:Timer A, which is used by clock_delay_usec().
|
||||||
* We use 16-bit range (individual), count-down, one-shot, no interrupts.
|
* We use 16-bit range (individual), count-down, one-shot, no interrupts.
|
||||||
* The system clock is at 16MHz giving us 62.5 nano sec ticks for Timer A.
|
* The prescaler is computed according to the system clock in order to get 1
|
||||||
* Prescaled by 16 gives us a very convenient 1 tick per usec
|
* tick per usec.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
clock_init(void)
|
clock_init(void)
|
||||||
|
@ -98,15 +110,14 @@ clock_init(void)
|
||||||
/* Make sure GPT0 is off */
|
/* Make sure GPT0 is off */
|
||||||
REG(GPT_0_BASE + GPTIMER_CTL) = 0;
|
REG(GPT_0_BASE + GPTIMER_CTL) = 0;
|
||||||
|
|
||||||
|
|
||||||
/* 16-bit */
|
/* 16-bit */
|
||||||
REG(GPT_0_BASE + GPTIMER_CFG) = 0x04;
|
REG(GPT_0_BASE + GPTIMER_CFG) = 0x04;
|
||||||
|
|
||||||
/* One-Shot, Count Down, No Interrupts */
|
/* One-Shot, Count Down, No Interrupts */
|
||||||
REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT;
|
REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT;
|
||||||
|
|
||||||
/* Prescale by 16 (thus, value 15 in TAPR) */
|
/* Prescale depending on system clock used */
|
||||||
REG(GPT_0_BASE + GPTIMER_TAPR) = 0x0F;
|
REG(GPT_0_BASE + GPTIMER_TAPR) = PRESCALER_VALUE;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
CCIF clock_time_t
|
CCIF clock_time_t
|
||||||
|
|
|
@ -43,15 +43,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
/*---------------------------------------------------------------------------*/
|
#include "sys-ctrl.h"
|
||||||
/* Additional functions */
|
|
||||||
static uint32_t
|
|
||||||
get_sys_clock(void)
|
|
||||||
{
|
|
||||||
/* Get the clock status diviser */
|
|
||||||
return SYS_CTRL_32MHZ /
|
|
||||||
(1 << (REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYS_DIV));
|
|
||||||
}
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
void
|
void
|
||||||
i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl,
|
i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl,
|
||||||
|
@ -111,7 +103,7 @@ void
|
||||||
i2c_set_frequency(uint32_t freq)
|
i2c_set_frequency(uint32_t freq)
|
||||||
{
|
{
|
||||||
/* Peripheral clock setting, using the system clock */
|
/* Peripheral clock setting, using the system clock */
|
||||||
REG(I2CM_TPR) = ((get_sys_clock() + (2 * 10 * freq) - 1) /
|
REG(I2CM_TPR) = ((SYS_CTRL_SYS_CLOCK + (2 * 10 * freq) - 1) /
|
||||||
(2 * 10 * freq)) - 1;
|
(2 * 10 * freq)) - 1;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -226,8 +226,8 @@ spix_init(uint8_t spi)
|
||||||
/* Start by disabling the peripheral before configuring it */
|
/* Start by disabling the peripheral before configuring it */
|
||||||
REG(regs->base + SSI_CR1) = 0;
|
REG(regs->base + SSI_CR1) = 0;
|
||||||
|
|
||||||
/* Set the IO clock as the SSI clock */
|
/* Set the system clock as the SSI clock */
|
||||||
REG(regs->base + SSI_CC) = 1;
|
REG(regs->base + SSI_CC) = 0;
|
||||||
|
|
||||||
/* Set the mux correctly to connect the SSI pins to the correct GPIO pins */
|
/* Set the mux correctly to connect the SSI pins to the correct GPIO pins */
|
||||||
ioc_set_sel(regs->clk.port,
|
ioc_set_sel(regs->clk.port,
|
||||||
|
|
|
@ -70,17 +70,18 @@ sys_ctrl_init()
|
||||||
* 32KHz source: RC or crystal, according to SYS_CTRL_OSC32K_USE_XTAL
|
* 32KHz source: RC or crystal, according to SYS_CTRL_OSC32K_USE_XTAL
|
||||||
* System Clock: 32 MHz
|
* System Clock: 32 MHz
|
||||||
* Power Down Unused
|
* Power Down Unused
|
||||||
* I/O Div: 16MHz
|
* I/O Div: according to SYS_CTRL_IO_DIV
|
||||||
* Sys Div: 16MHz
|
* Sys Div: according to SYS_CTRL_SYS_DIV
|
||||||
* Rest: Don't care
|
* Rest: Don't care
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val = SYS_CTRL_OSCS | SYS_CTRL_CLOCK_CTRL_OSC_PD
|
val = SYS_CTRL_OSCS | SYS_CTRL_CLOCK_CTRL_OSC_PD
|
||||||
| SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ | SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ;
|
| SYS_CTRL_IO_DIV | SYS_CTRL_SYS_DIV;
|
||||||
REG(SYS_CTRL_CLOCK_CTRL) = val;
|
REG(SYS_CTRL_CLOCK_CTRL) = val;
|
||||||
|
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_OSC32K |
|
while((REG(SYS_CTRL_CLOCK_STA)
|
||||||
SYS_CTRL_CLOCK_STA_OSC)) != SYS_CTRL_OSCS);
|
& (SYS_CTRL_CLOCK_STA_OSC32K | SYS_CTRL_CLOCK_STA_OSC))
|
||||||
|
!= SYS_CTRL_OSCS);
|
||||||
|
|
||||||
#if SYS_CTRL_OSC32K_USE_XTAL
|
#if SYS_CTRL_OSC32K_USE_XTAL
|
||||||
/* Wait for the 32-kHz crystal oscillator to stabilize */
|
/* Wait for the 32-kHz crystal oscillator to stabilize */
|
||||||
|
@ -94,7 +95,20 @@ sys_ctrl_reset()
|
||||||
{
|
{
|
||||||
REG(SYS_CTRL_PWRDBG) = SYS_CTRL_PWRDBG_FORCE_WARM_RESET;
|
REG(SYS_CTRL_PWRDBG) = SYS_CTRL_PWRDBG_FORCE_WARM_RESET;
|
||||||
}
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t
|
||||||
|
sys_ctrl_get_sys_clock(void)
|
||||||
|
{
|
||||||
|
return SYS_CTRL_32MHZ >> (REG(SYS_CTRL_CLOCK_STA) &
|
||||||
|
SYS_CTRL_CLOCK_STA_SYS_DIV);
|
||||||
|
}
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t
|
||||||
|
sys_ctrl_get_io_clock(void)
|
||||||
|
{
|
||||||
|
return SYS_CTRL_32MHZ >> ((REG(SYS_CTRL_CLOCK_STA) &
|
||||||
|
SYS_CTRL_CLOCK_STA_IO_DIV) >> 8);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
* @}
|
* @}
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
*/
|
*/
|
||||||
#ifndef SYS_CTRL_H_
|
#ifndef SYS_CTRL_H_
|
||||||
#define SYS_CTRL_H_
|
#define SYS_CTRL_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
/** \name SysCtrl Constants, used by the SYS_DIV and IO_DIV bits of the
|
/** \name SysCtrl Constants, used by the SYS_DIV and IO_DIV bits of the
|
||||||
* SYS_CTRL_CLOCK_CTRL register
|
* SYS_CTRL_CLOCK_CTRL register
|
||||||
|
@ -242,6 +244,33 @@
|
||||||
#endif
|
#endif
|
||||||
/** @} */
|
/** @} */
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
/** \name System clock divisor selection
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#ifdef SYS_CTRL_CONF_SYS_DIV
|
||||||
|
#if SYS_CTRL_CONF_SYS_DIV & ~SYS_CTRL_CLOCK_CTRL_SYS_DIV
|
||||||
|
#error Invalid system clock divisor
|
||||||
|
#endif
|
||||||
|
#define SYS_CTRL_SYS_DIV SYS_CTRL_CONF_SYS_DIV
|
||||||
|
#else
|
||||||
|
#define SYS_CTRL_SYS_DIV SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SYS_CTRL_CONF_IO_DIV
|
||||||
|
#if SYS_CTRL_CONF_IO_DIV & ~SYS_CTRL_CLOCK_CTRL_IO_DIV
|
||||||
|
#error Invalid I/O clock divisor
|
||||||
|
#endif
|
||||||
|
#define SYS_CTRL_IO_DIV SYS_CTRL_CONF_IO_DIV
|
||||||
|
#else
|
||||||
|
#define SYS_CTRL_IO_DIV SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Returns actual system clock in Hz */
|
||||||
|
#define SYS_CTRL_SYS_CLOCK (SYS_CTRL_32MHZ >> SYS_CTRL_SYS_DIV)
|
||||||
|
/* Returns actual I/O clock in Hz */
|
||||||
|
#define SYS_CTRL_IO_CLOCK (SYS_CTRL_32MHZ >> (SYS_CTRL_IO_DIV >> 8))
|
||||||
|
/** @} */
|
||||||
|
/*---------------------------------------------------------------------------*/
|
||||||
/** \name SysCtrl functions
|
/** \name SysCtrl functions
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
@ -253,6 +282,12 @@ void sys_ctrl_init();
|
||||||
/** \brief Generates a warm reset through the SYS_CTRL_PWRDBG register */
|
/** \brief Generates a warm reset through the SYS_CTRL_PWRDBG register */
|
||||||
void sys_ctrl_reset();
|
void sys_ctrl_reset();
|
||||||
|
|
||||||
|
/** \brief Returns the actual system clock in Hz */
|
||||||
|
uint32_t sys_ctrl_get_sys_clock();
|
||||||
|
|
||||||
|
/** \brief Returns the actual io clock in Hz */
|
||||||
|
uint32_t sys_ctrl_get_io_clock();
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
#endif /* SYS_CTRL_H_ */
|
#endif /* SYS_CTRL_H_ */
|
||||||
|
|
|
@ -136,7 +136,7 @@
|
||||||
* Baud rate defines used in uart_init() to set the values of UART_IBRD and
|
* Baud rate defines used in uart_init() to set the values of UART_IBRD and
|
||||||
* UART_FBRD in order to achieve the configured baud rates.
|
* UART_FBRD in order to achieve the configured baud rates.
|
||||||
*/
|
*/
|
||||||
#define UART_CLOCK_RATE 16000000 /* 16 MHz */
|
#define UART_CLOCK_RATE SYS_CTRL_SYS_CLOCK
|
||||||
#define UART_CTL_HSE_VALUE 0
|
#define UART_CTL_HSE_VALUE 0
|
||||||
#define UART_CTL_VALUE (UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5))
|
#define UART_CTL_VALUE (UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5))
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,8 @@ static unsigned long irq_energest = 0;
|
||||||
#if LPM_CONF_STATS
|
#if LPM_CONF_STATS
|
||||||
rtimer_clock_t lpm_stats[3];
|
rtimer_clock_t lpm_stats[3];
|
||||||
|
|
||||||
#define LPM_STATS_INIT() do { memset(lpm_stats, 0, sizeof(lpm_stats)); \
|
#define LPM_STATS_INIT() \
|
||||||
} while(0)
|
do { memset(lpm_stats, 0, sizeof(lpm_stats)); } while(0)
|
||||||
#define LPM_STATS_ADD(pm, val) do { lpm_stats[pm] += val; } while(0)
|
#define LPM_STATS_ADD(pm, val) do { lpm_stats[pm] += val; } while(0)
|
||||||
#else
|
#else
|
||||||
#define LPM_STATS_INIT()
|
#define LPM_STATS_INIT()
|
||||||
|
@ -154,7 +154,7 @@ enter_pm0(void)
|
||||||
static void
|
static void
|
||||||
select_32_mhz_xosc(void)
|
select_32_mhz_xosc(void)
|
||||||
{
|
{
|
||||||
/*First, make sure there is no ongoing clock source change */
|
/* First, make sure there is no ongoing clock source change */
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
||||||
|
|
||||||
/* Turn on the 32 MHz XOSC and source the system clock on it. */
|
/* Turn on the 32 MHz XOSC and source the system clock on it. */
|
||||||
|
@ -163,8 +163,15 @@ select_32_mhz_xosc(void)
|
||||||
/* Wait for the switch to take place */
|
/* Wait for the switch to take place */
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_OSC) != 0);
|
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_OSC) != 0);
|
||||||
|
|
||||||
/* Power down the unused oscillator. */
|
/* Power down the unused oscillator and restore divisors (silicon errata) */
|
||||||
REG(SYS_CTRL_CLOCK_CTRL) |= SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
REG(SYS_CTRL_CLOCK_CTRL) = (REG(SYS_CTRL_CLOCK_CTRL)
|
||||||
|
#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ
|
||||||
|
& ~SYS_CTRL_CLOCK_CTRL_SYS_DIV
|
||||||
|
#endif
|
||||||
|
#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ
|
||||||
|
& ~SYS_CTRL_CLOCK_CTRL_IO_DIV
|
||||||
|
#endif
|
||||||
|
) | SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
||||||
}
|
}
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
static void
|
static void
|
||||||
|
@ -172,9 +179,19 @@ select_16_mhz_rcosc(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Power up both oscillators in order to speed up the transition to the 32-MHz
|
* Power up both oscillators in order to speed up the transition to the 32-MHz
|
||||||
* XOSC after wake up.
|
* XOSC after wake up. In addition, consider CC2538 silicon errata:
|
||||||
|
* "Possible Incorrect Value of Clock Dividers after PM2 and PM3" and
|
||||||
|
* set system clock divisor / I/O clock divisor to 16 MHz in case they run
|
||||||
|
* at full speed (=32 MHz)
|
||||||
*/
|
*/
|
||||||
REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
REG(SYS_CTRL_CLOCK_CTRL) = (REG(SYS_CTRL_CLOCK_CTRL)
|
||||||
|
#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ
|
||||||
|
| SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ
|
||||||
|
#endif
|
||||||
|
#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ
|
||||||
|
| SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ
|
||||||
|
#endif
|
||||||
|
) & ~SYS_CTRL_CLOCK_CTRL_OSC_PD;
|
||||||
|
|
||||||
/*First, make sure there is no ongoing clock source change */
|
/*First, make sure there is no ongoing clock source change */
|
||||||
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0);
|
||||||
|
|
Loading…
Reference in a new issue