Merge pull request #10075 from dylad/saml21_dfll_support
cpu/saml21: add DFLL support
This commit is contained in:
commit
c86dcd4611
@ -32,7 +32,7 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief GCLK reference speed
|
* @brief GCLK reference speed
|
||||||
*/
|
*/
|
||||||
#define CLOCK_CORECLOCK (16000000U)
|
#define CLOCK_CORECLOCK (48000000U)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Timer peripheral configuration
|
* @name Timer peripheral configuration
|
||||||
@ -45,8 +45,8 @@ static const tc32_conf_t timer_config[] = {
|
|||||||
.mclk = &MCLK->APBCMASK.reg,
|
.mclk = &MCLK->APBCMASK.reg,
|
||||||
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
||||||
.gclk_id = TC0_GCLK_ID,
|
.gclk_id = TC0_GCLK_ID,
|
||||||
.gclk_src = SAM0_GCLK_MAIN,
|
.gclk_src = SAM0_GCLK_8MHZ,
|
||||||
.prescaler = TC_CTRLA_PRESCALER(4),
|
.prescaler = TC_CTRLA_PRESCALER(3),
|
||||||
.flags = TC_CTRLA_MODE_COUNT32,
|
.flags = TC_CTRLA_MODE_COUNT32,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -28,7 +28,7 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief GCLK reference speed
|
* @brief GCLK reference speed
|
||||||
*/
|
*/
|
||||||
#define CLOCK_CORECLOCK (16000000U)
|
#define CLOCK_CORECLOCK (48000000U)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Timer peripheral configuration
|
* @name Timer peripheral configuration
|
||||||
@ -41,8 +41,8 @@ static const tc32_conf_t timer_config[] = {
|
|||||||
.mclk = &MCLK->APBCMASK.reg,
|
.mclk = &MCLK->APBCMASK.reg,
|
||||||
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
||||||
.gclk_id = TC0_GCLK_ID,
|
.gclk_id = TC0_GCLK_ID,
|
||||||
.gclk_src = SAM0_GCLK_MAIN,
|
.gclk_src = SAM0_GCLK_8MHZ,
|
||||||
.prescaler = TC_CTRLA_PRESCALER(4),
|
.prescaler = TC_CTRLA_PRESCALER(3),
|
||||||
.flags = TC_CTRLA_MODE_COUNT32,
|
.flags = TC_CTRLA_MODE_COUNT32,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -29,7 +29,7 @@ extern "C" {
|
|||||||
/**
|
/**
|
||||||
* @brief GCLK reference speed
|
* @brief GCLK reference speed
|
||||||
*/
|
*/
|
||||||
#define CLOCK_CORECLOCK (16000000U)
|
#define CLOCK_CORECLOCK (48000000U)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Timer peripheral configuration
|
* @name Timer peripheral configuration
|
||||||
@ -42,8 +42,8 @@ static const tc32_conf_t timer_config[] = {
|
|||||||
.mclk = &MCLK->APBCMASK.reg,
|
.mclk = &MCLK->APBCMASK.reg,
|
||||||
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
.mclk_mask = MCLK_APBCMASK_TC0 | MCLK_APBCMASK_TC1,
|
||||||
.gclk_id = TC0_GCLK_ID,
|
.gclk_id = TC0_GCLK_ID,
|
||||||
.gclk_src = SAM0_GCLK_MAIN,
|
.gclk_src = SAM0_GCLK_8MHZ,
|
||||||
.prescaler = TC_CTRLA_PRESCALER(4),
|
.prescaler = TC_CTRLA_PRESCALER(3),
|
||||||
.flags = TC_CTRLA_MODE_COUNT32,
|
.flags = TC_CTRLA_MODE_COUNT32,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -75,6 +75,8 @@ uint32_t sam0_gclk_freq(uint8_t id)
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case SAM0_GCLK_MAIN:
|
case SAM0_GCLK_MAIN:
|
||||||
return CLOCK_CORECLOCK;
|
return CLOCK_CORECLOCK;
|
||||||
|
case SAM0_GCLK_8MHZ:
|
||||||
|
return 8000000;
|
||||||
case SAM0_GCLK_32KHZ:
|
case SAM0_GCLK_32KHZ:
|
||||||
return 32768;
|
return 32768;
|
||||||
default:
|
default:
|
||||||
@ -82,6 +84,48 @@ uint32_t sam0_gclk_freq(uint8_t id)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _dfll_setup(void)
|
||||||
|
{
|
||||||
|
#if (CLOCK_CORECLOCK == 48000000U) || defined (MODULE_PERIPH_USBDEV)
|
||||||
|
GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = GCLK_PCHCTRL_CHEN |
|
||||||
|
GCLK_PCHCTRL_GEN_GCLK2;
|
||||||
|
|
||||||
|
/* wait for sync */
|
||||||
|
while (!(GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg & GCLK_PCHCTRL_CHEN)) {}
|
||||||
|
|
||||||
|
OSCCTRL->DFLLCTRL.reg = OSCCTRL_DFLLCTRL_ENABLE;
|
||||||
|
/* Wait for write synchronization */
|
||||||
|
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
|
||||||
|
OSCCTRL->DFLLVAL.reg = OSCCTRL_DFLLVAL_COARSE((*(uint32_t*)NVMCTRL_OTP5)
|
||||||
|
>> 26) | OSCCTRL_DFLLVAL_FINE(512);
|
||||||
|
|
||||||
|
/* Wait for write synchronization */
|
||||||
|
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
|
||||||
|
/* Generate a 48 Mhz clock from the 32KHz */
|
||||||
|
OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP(0x08) |
|
||||||
|
OSCCTRL_DFLLMUL_FSTEP(0x08) |
|
||||||
|
OSCCTRL_DFLLMUL_MUL((48000000U/32768));
|
||||||
|
|
||||||
|
/* Disable DFLL before setting its configuration */
|
||||||
|
OSCCTRL->DFLLCTRL.reg = 0;
|
||||||
|
while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_DFLLRDY)) {}
|
||||||
|
/* Write full configuration to DFLL control register */
|
||||||
|
OSCCTRL->DFLLCTRL.reg = OSCCTRL_DFLLCTRL_WAITLOCK |
|
||||||
|
OSCCTRL_DFLLCTRL_MODE |
|
||||||
|
OSCCTRL_DFLLCTRL_CCDIS |
|
||||||
|
OSCCTRL_DFLLCTRL_BPLCKC |
|
||||||
|
OSCCTRL_DFLLCTRL_ENABLE;
|
||||||
|
|
||||||
|
/* Ensure COARSE and FINE are locked */
|
||||||
|
while ((!(OSCCTRL->STATUS.bit.DFLLLCKC)) && (!(OSCCTRL->STATUS.bit.DFLLLCKF))) {}
|
||||||
|
while (!(OSCCTRL->STATUS.bit.DFLLRDY)) {}
|
||||||
|
|
||||||
|
/* Enable NVMCTRL */
|
||||||
|
MCLK->APBBMASK.reg |= MCLK_APBBMASK_NVMCTRL;
|
||||||
|
/* Set Wait State to meet requirements */
|
||||||
|
NVMCTRL->CTRLB.reg |= NVMCTRL_CTRLB_RWS(3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @brief Initialize the CPU, set IRQ priorities, clocks
|
* @brief Initialize the CPU, set IRQ priorities, clocks
|
||||||
*/
|
*/
|
||||||
@ -90,6 +134,14 @@ void cpu_init(void)
|
|||||||
/* disable the watchdog timer */
|
/* disable the watchdog timer */
|
||||||
WDT->CTRLA.bit.ENABLE = 0;
|
WDT->CTRLA.bit.ENABLE = 0;
|
||||||
|
|
||||||
|
/* Disable the RTC module to prevent synchronization issues during CPU init
|
||||||
|
if the RTC was running from a previous boot (e.g wakeup from backup) */
|
||||||
|
if (RTC->MODE2.CTRLA.bit.ENABLE) {
|
||||||
|
while (RTC->MODE2.SYNCBUSY.reg) {}
|
||||||
|
RTC->MODE2.CTRLA.bit.ENABLE = 0;
|
||||||
|
while (RTC->MODE2.SYNCBUSY.reg) {}
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize the Cortex-M core */
|
/* initialize the Cortex-M core */
|
||||||
cortexm_init();
|
cortexm_init();
|
||||||
|
|
||||||
@ -125,14 +177,36 @@ void cpu_init(void)
|
|||||||
_osc32k_setup();
|
_osc32k_setup();
|
||||||
_xosc32k_setup();
|
_xosc32k_setup();
|
||||||
|
|
||||||
/* Setup GCLK generators */
|
|
||||||
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M);
|
|
||||||
#if EXTERNAL_OSC32_SOURCE
|
#if EXTERNAL_OSC32_SOURCE
|
||||||
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K);
|
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC32K);
|
||||||
#else
|
#else
|
||||||
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K);
|
_gclk_setup(SAM0_GCLK_32KHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
_dfll_setup();
|
||||||
|
|
||||||
|
/* Setup GCLK generators */
|
||||||
|
#if (CLOCK_CORECLOCK == 16000000U)
|
||||||
|
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M);
|
||||||
|
#elif (CLOCK_CORECLOCK == 48000000U)
|
||||||
|
_gclk_setup(SAM0_GCLK_MAIN, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_DFLL48M);
|
||||||
|
#else
|
||||||
|
#error "Please select a valid CPU frequency"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Ensure APB Backup domain clock is within the 6MHZ limit, BUPDIV value
|
||||||
|
must be a power of 2 and between 1(2^0) and 128(2^7) */
|
||||||
|
for (unsigned i = 0; i < 8; i++) {
|
||||||
|
if (CLOCK_CORECLOCK / (1 << i) <= 6000000) {
|
||||||
|
MCLK->BUPDIV.reg = (1 << i);
|
||||||
|
while (!MCLK->INTFLAG.bit.CKRDY) {}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* clock used by timers */
|
||||||
|
_gclk_setup(SAM0_GCLK_8MHZ, GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC16M
|
||||||
|
| GCLK_GENCTRL_DIV(2));
|
||||||
|
|
||||||
#ifdef MODULE_PERIPH_PM
|
#ifdef MODULE_PERIPH_PM
|
||||||
PM->CTRLA.reg = PM_CTRLA_MASK & (~PM_CTRLA_IORET);
|
PM->CTRLA.reg = PM_CTRLA_MASK & (~PM_CTRLA_IORET);
|
||||||
|
|
||||||
|
|||||||
@ -36,8 +36,9 @@ extern "C" {
|
|||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
SAM0_GCLK_MAIN = 0, /**< 16 MHz main clock */
|
SAM0_GCLK_MAIN = 0, /**< Main clock */
|
||||||
SAM0_GCLK_32KHZ, /**< 32 kHz clock */
|
SAM0_GCLK_8MHZ = 1, /**< 8MHz clock */
|
||||||
|
SAM0_GCLK_32KHZ = 2, /**< 32 kHz clock */
|
||||||
};
|
};
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user