Skip to content

Commit

Permalink
cpu/msp430fxyz: clean up clock initialization
Browse files Browse the repository at this point in the history
Provide a common clock initialization driver rather than leaving
clock initialization to the boards code. A declarative description of
the board's clock configuration using a struct does still allow to
fine-tune settings. In addition, a board is still allowed to just
provide a custom `void clock_init(void)` if there really is the need
to do crazy things.
  • Loading branch information
maribu committed May 16, 2023
1 parent 2b97b76 commit df5c319
Show file tree
Hide file tree
Showing 16 changed files with 669 additions and 335 deletions.
98 changes: 0 additions & 98 deletions boards/common/msb-430/board_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@
#include "msp430.h"
#include "debug.h"

static volatile uint32_t __msp430_cpu_speed = MSP430_INITIAL_CPU_SPEED;

void msp430_init_dco(void);

static void msb_ports_init(void)
{
/* Port 1: Free port, for energy saving all outputs are set to zero. */
Expand Down Expand Up @@ -99,101 +95,7 @@ static void msb_ports_init(void)
/* 1 - P6.7 [OUT] - unused */
}

void msp430_set_cpu_speed(uint32_t speed)
{
irq_disable();
__msp430_cpu_speed = speed;
msp430_init_dco();
irq_enable();
}

/*---------------------------------------------------------------------------*/
void msp430_init_dco(void)
{
#if MSP430_HAS_EXTERNAL_CRYSTAL
/*------------------ use external oszillator -----------------------*/
uint16_t i;

/* Stop watchdog */
WDTCTL = WDTPW + WDTHOLD;

/* Init crystal for mclk */
/* XT2 = HF XTAL */
BCSCTL1 = RSEL2;

/* Wait for xtal to stabilize */
do {
IFG1 &= ~OFIFG; /* Clear oscillator fault flag */

for (i = 0xFF; i > 0; i--); /* Time for flag to set */
}
while ((IFG1 & OFIFG) != 0); /* Oscillator fault flag still set? */

BCSCTL2 = SELM_2 + SELS; /* MCLK und SMCLK = XT2 (safe) */
#else
unsigned int delta = __msp430_cpu_speed >> 12;
unsigned int oldcapture = 0;
unsigned int i;

BCSCTL1 = 0xa4; /* ACLK is divided by 4. RSEL=6 no division for MCLK
and SSMCLK. XT2 is off. */

/* Init FLL to desired frequency using the 32762Hz crystal */
#if MSP430_HAS_DCOR
BCSCTL2 = 0x01;
#else
BCSCTL2 = 0x00;
#endif

WDTCTL = WDTPW + WDTHOLD; /* Stop WDT */
BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */

for (i = 0xffff; i > 0; i--); /* Delay for XTAL to settle */

CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */
TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continuous mode */

while (1) {
unsigned int compare;

while ((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occurred! */

CCTL2 &= ~CCIFG; /* Capture occurred, clear flag */
compare = CCR2; /* Get current captured SMCLK */
compare = compare - oldcapture; /* SMCLK difference */
oldcapture = CCR2; /* Save current captured SMCLK */

if (delta == compare) {
break; /* if equal, leave "while(1)" */
}
else if (delta < compare) { /* DCO is too fast, slow it down */
DCOCTL--;

if (DCOCTL == 0xFF) { /* Did DCO role under? */
BCSCTL1--;
}
}
else { /* -> Select next lower RSEL */
DCOCTL++;

if (DCOCTL == 0x00) { /* Did DCO role over? */
BCSCTL1++;
}

/* -> Select next higher RSEL */
}
}

CCTL2 = 0; /* Stop CCR2 function */
TACTL = 0; /* Stop Timer_A */

BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */
#endif
}

void board_init(void)
{
msb_ports_init();

msp430_set_cpu_speed(CLOCK_CORECLOCK);
}
12 changes: 0 additions & 12 deletions boards/msb-430/include/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,6 @@ extern "C" {
#define __MSP430F1612__
#endif

/**
* @name CPU core configuration
* @{
*/
/** @todo Move this to the periph_conf.h */
#define MSP430_INITIAL_CPU_SPEED 2457600uL
#define F_CPU MSP430_INITIAL_CPU_SPEED
#define F_RC_OSCILLATOR 32768
#define MSP430_HAS_DCOR 1
#define MSP430_HAS_EXTERNAL_CRYSTAL 0
/** @} */

/**
* @name Configure on-board SHT11 device
* @{
Expand Down
23 changes: 16 additions & 7 deletions boards/msb-430/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,28 @@
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H

#include "periph_cpu.h"
#include "macros/units.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CLOCK_CORECLOCK msp430_fxyz_dco_freq

/**
* @name Clock configuration
* @{
* @brief Clock configuration
*/
/** @todo Move all clock configuration code here from the board.h */
#define CLOCK_CORECLOCK (7372800U)

#define CLOCK_CMCLK CLOCK_CORECLOCK /* no divider programmed */
/** @} */
static const msp430_fxyz_clock_params_t clock_params = {
.target_dco_frequency = 7372800U,
.lfxt1_frequency = 32768,
.main_clock_source = MAIN_CLOCK_SOURCE_DCOCLK,
.submain_clock_source = SUBMAIN_CLOCK_SOURCE_DCOCLK,
.main_clock_divier = MAIN_CLOCK_DIVIDE_BY_1,
.submain_clock_divier = SUBMAIN_CLOCK_DIVIDE_BY_1,
.auxiliary_clock_divier = AUXILIARY_CLOCK_DIVIDE_BY_1,
.has_r_osc = true,
};

/**
* @name Timer configuration
Expand Down
12 changes: 0 additions & 12 deletions boards/msb-430h/include/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,6 @@ extern "C" {
#define __MSP430F1612__
#endif

/**
* @name CPU core configuration
* @{
*/
/** @todo Move this to the periph_conf.h */
#define MSP430_INITIAL_CPU_SPEED 7372800uL
#define F_CPU MSP430_INITIAL_CPU_SPEED
#define F_RC_OSCILLATOR 32768
#define MSP430_HAS_DCOR 1
#define MSP430_HAS_EXTERNAL_CRYSTAL 1
/** @} */

/**
* @name Configure on-board SHT11 device
* @{
Expand Down
20 changes: 13 additions & 7 deletions boards/msb-430h/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,21 @@
extern "C" {
#endif

/**
* @name Clock configuration
* @{
*/
/** @todo Move all clock configuration code here from the board.h */
#define CLOCK_CORECLOCK (7372800U)

#define CLOCK_CMCLK CLOCK_CORECLOCK /* no divider programmed */
/** @} */
/**
* @brief Clock configuration
*/
static const msp430_fxyz_clock_params_t clock_params = {
.xt2_frequency = CLOCK_CORECLOCK,
.lfxt1_frequency = 32768,
.main_clock_source = MAIN_CLOCK_SOURCE_XT2CLK,
.submain_clock_source = SUBMAIN_CLOCK_SOURCE_XT2CLK,
.main_clock_divier = MAIN_CLOCK_DIVIDE_BY_1,
.submain_clock_divier = SUBMAIN_CLOCK_DIVIDE_BY_1,
.auxiliary_clock_divier = AUXILIARY_CLOCK_DIVIDE_BY_1,
.has_r_osc = true,
};

/**
* @name Timer configuration
Expand Down
74 changes: 0 additions & 74 deletions boards/telosb/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
#include "cpu.h"
#include "periph_conf.h"

void uart_init(void);

static void telosb_ports_init(void)
{
/* Port 1: GDO, Flash, BSL TX */
Expand Down Expand Up @@ -46,79 +44,7 @@ static void telosb_ports_init(void)

}

/*---------------------------------------------------------------------------*/
/* taken from Contiki code */
void msp430_init_dco(void)
{
/* This code taken from the FU Berlin sources and reformatted. */
#define DELTA (F_CPU / (F_RC_OSCILLATOR / 8))

unsigned int oldcapture = 0;
unsigned int i;

/* 10100100 = XT2 is off, ACLK divided by 4, RSELx=4 */
BCSCTL1 = XT2OFF | DIVA_2 | RSEL2;

/* Init undivided DCO with internal resistor for MCLK and SMCLK
* DCO = 32762Hz -> FLL = 2,4576 MHz */
BCSCTL2 = 0x00;

BCSCTL1 |= DIVA1 + DIVA0; /* ACLK = LFXT1CLK/8 */

for (i = 0xFFFF; i > 0; i--) { /* Delay for XTAL to settle */
__asm__("nop");
}

CCTL2 = CCIS0 + CM0 + CAP; /* Define CCR2, CAP, ACLK */
TACTL = TASSEL1 + TACLR + MC1; /* SMCLK, continuous mode */

while (1) {
unsigned int compare;

while ((CCTL2 & CCIFG) != CCIFG); /* Wait until capture occurred!*/

CCTL2 &= ~CCIFG; /* Capture occurred, clear flag */
compare = CCR2; /* Get current captured SMCLK */
compare = compare - oldcapture; /* SMCLK difference */
oldcapture = CCR2; /* Save current captured SMCLK */

if (DELTA == compare) {
break; /* if equal, leave "while (1)" */
}
else if (DELTA < compare) { /* DCO is too fast, slow it down */
DCOCTL--;

if (DCOCTL == 0xFF) { /* Did DCO role under? */
BCSCTL1--;
}
}
else { /* -> Select next lower RSEL */
DCOCTL++;

if (DCOCTL == 0x00) { /* Did DCO role over? */
BCSCTL1++;
}

/* -> Select next higher RSEL */
}
}

CCTL2 = 0; /* Stop CCR2 function */
TACTL = 0; /* Stop Timer_A */

BCSCTL1 &= ~(DIVA1 + DIVA0); /* remove /8 divisor from ACLK again */
}

//=========================== public ==========================================

void board_init(void)
{
/* disable watchdog timer */
WDTCTL = WDTPW + WDTHOLD;

telosb_ports_init();
msp430_init_dco();

/* enable interrupts */
__bis_SR_register(GIE);
}
26 changes: 15 additions & 11 deletions boards/telosb/include/periph_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,27 @@
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H

#include "macros/units.h"
#include "periph_cpu.h"

#ifdef __cplusplus
extern "C" {
#endif

#define CLOCK_CORECLOCK msp430_fxyz_dco_freq

/**
* @name Clock configuration
* @{
* @brief Clock configuration
*/
#define CLOCK_CORECLOCK (2457600U)
#define MSP430_INITIAL_CPU_SPEED 2457600uL
#define F_CPU MSP430_INITIAL_CPU_SPEED
#define F_RC_OSCILLATOR 32768
#define MSP430_HAS_DCOR 0
#define MSP430_HAS_EXTERNAL_CRYSTAL 1

#define CLOCK_CMCLK CLOCK_CORECLOCK /* no divider programmed */
/** @} */
static const msp430_fxyz_clock_params_t clock_params = {
.target_dco_frequency = 2457600U,
.lfxt1_frequency = 32768,
.main_clock_source = MAIN_CLOCK_SOURCE_DCOCLK,
.submain_clock_source = SUBMAIN_CLOCK_SOURCE_DCOCLK,
.main_clock_divier = MAIN_CLOCK_DIVIDE_BY_1,
.submain_clock_divier = SUBMAIN_CLOCK_DIVIDE_BY_1,
.auxiliary_clock_divier = AUXILIARY_CLOCK_DIVIDE_BY_1,
};

/**
* @name Timer configuration
Expand Down
Loading

0 comments on commit df5c319

Please sign in to comment.