diff --git a/cpu/cc2538/cpu.c b/cpu/cc2538/cpu.c index 35203832e8..6011c614ab 100644 --- a/cpu/cc2538/cpu.c +++ b/cpu/cc2538/cpu.c @@ -18,23 +18,11 @@ */ #include +#include "stdio_base.h" #include "cpu.h" #include "periph/init.h" -#include "stdio_base.h" - -#define BIT(n) ( 1UL << (n) ) - -/* Select CLOCK_CTRL register bit masks: */ -#define OSC32K BIT(24) /**< 32-kHz clock oscillator selection */ -#define OSC_PD BIT(17) /**< Oscillator power-down */ -#define OSC BIT(16) /**< System clock oscillator selection */ - -/* CLOCK_CTRL register field offsets: */ -#define IO_DIV_SHIFT 8 -#define SYS_DIV_SHIFT 0 - -#define CLOCK_STA_MASK ( OSC32K | OSC ) +#include "periph_conf.h" static void cpu_clock_init(void); @@ -55,22 +43,14 @@ void cpu_init(void) periph_init(); } + /** * @brief Configure the controllers clock system */ static void cpu_clock_init(void) { - const uint32_t CLOCK_CTRL_VALUE = - OSC_PD /**< Power down the oscillator not selected by OSC bit (hardware-controlled when selected). */ - | (1 << IO_DIV_SHIFT) /**< 16 MHz IO_DIV */ - | (1 << SYS_DIV_SHIFT) /**< 16 MHz SYS_DIV */ -#if !SYS_CTRL_OSC32K_USE_XTAL - | OSC32K /**< Use internal RC oscillator. */ -#endif - ; - #if SYS_CTRL_OSC32K_USE_XTAL - /* Set the XOSC32K_Q pads to analog for the external crystal: */ + /* set the XOSC32K_Q pads to analog for the external crystal: */ gpio_software_control(GPIO_PD6); gpio_dir_input(GPIO_PD6); IOC_PXX_OVER[GPIO_PD6] = IOC_OVERRIDE_ANA; @@ -80,15 +60,41 @@ static void cpu_clock_init(void) IOC_PXX_OVER[GPIO_PD7] = IOC_OVERRIDE_ANA; #endif - /* Configure the clock settings: */ - SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRL = CLOCK_CTRL_VALUE; - - /* Wait for the new clock settings to take effect: */ - while ((SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STA ^ CLOCK_CTRL_VALUE) & CLOCK_STA_MASK); + /* CLOCK_CTRL.OSC32K register bit can be written at any time, but only takes + effect when 16MHz RCOSC is the active system clock source, 16MHz RCOSC is + the active clock on reset but to be idempotent make sure it's the + selected source clock */ + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC = 1; + while (SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SOURCE_CHANGE) {} #if SYS_CTRL_OSC32K_USE_XTAL - /* Wait for the 32-kHz crystal oscillator to stabilize: */ - while ( SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SYNC_32K); - while (!SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SYNC_32K); + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC32K = 0; + while (SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.OSC32K) {} +#else + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC32K = 1; + while (!SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.OSC32K) {} +#endif + +#if SYS_CTRL_OSC_USE_XTAL + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC = 0; +#else + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC = 1; +#endif + + /* power down the oscillator not selected by OSC bit */ + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.OSC_PD = 1; + /* set desired system clock rate */ + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.SYS_DIV = \ + __builtin_ctz(XOSC32M_FREQ / CLOCK_CORECLOCK); + /* set desired I/O clock rate */ + SYS_CTRL->cc2538_sys_ctrl_clk_ctrl.CLOCK_CTRLbits.IO_DIV = \ + __builtin_ctz(XOSC32M_FREQ / CLOCK_IO); + /* wait for new clock settings to take effect */ + while (SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SOURCE_CHANGE) {} + +#if SYS_CTRL_OSC32K_USE_XTAL + /* 32-kHz crystal oscillator to stabilize after a positive transition */ + while (SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SYNC_32K) {} + while (!SYS_CTRL->cc2538_sys_ctrl_clk_sta.CLOCK_STAbits.SYNC_32K) {} #endif } diff --git a/cpu/cc2538/include/cc2538.h b/cpu/cc2538/include/cc2538.h index 6f97718a17..5088eec238 100644 --- a/cpu/cc2538/include/cc2538.h +++ b/cpu/cc2538/include/cc2538.h @@ -798,10 +798,14 @@ typedef volatile uint32_t cc2538_reg_t; /**< Least-significant 32 bits of the IE #define CCTEST_USBCTRL ( *(cc2538_reg_t*)0x44010050 ) /**< CCTEST USB PHY stand-by control */ /** @} */ -#define XOSC32M_FREQ 32000000 /**< 32 MHz external oscillator/clock frequency */ -#define RCOSC16M_FREQ 16000000 /**< 16 MHz internal RC oscillator frequency */ +#define XOSC32M_FREQ 32000000U /**< 32 MHz external oscillator/clock frequency */ +#define RCOSC16M_FREQ 16000000U /**< 16 MHz internal RC oscillator frequency */ -#define CC2538_VTOR_ALIGN 512 /**< CC2538 Vector Table alignment */ +#define XOSC32K_FREQ 32768U /**< 32 KHz external oscillator/clock frequency */ +#define RCOSC32K_FREQ 32753U /**< 32 KHz internal RC oscillator frequency */ + + +#define CC2538_VTOR_ALIGN 512 /**< CC2538 Vector Table alignment */ #ifdef __cplusplus }