首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SAMD21时钟配置

SAMD21时钟配置
EN

Stack Overflow用户
提问于 2017-02-03 21:41:15
回答 2查看 3.4K关注 0票数 0

我正在尝试配置我的SAMD21时钟,使其尽可能快。下面是我的代码:

代码语言:javascript
复制
void system_clock_init(void)
{
    SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33RDY | SYSCTRL_INTFLAG_BOD33DET | SYSCTRL_INTFLAG_DFLLRDY;

    /* switch off all peripheral clocks to save power */
    //_switch_peripheral_gclk();

    /* configure and enable generic clock generator 1 (GENCTRL and GENDIV registers of GCLK module) */
    struct system_gclk_gen_config gclk_gen_config1;
    system_gclk_gen_get_config_defaults(&gclk_gen_config1);
    gclk_gen_config1.source_clock = SYSTEM_CLOCK_SOURCE_OSC8M;
    gclk_gen_config1.division_factor = 8;
    gclk_gen_config1.output_enable = false;
    system_gclk_gen_set_config(GCLK_GENERATOR_1,&gclk_gen_config1);
    system_gclk_gen_enable(GCLK_GENERATOR_1);

    /* configure and enable generic clock for DPLL (CLKCTRL of GCLK module) */
    struct system_gclk_chan_config gclk_chan_config;
    system_gclk_chan_get_config_defaults(&gclk_chan_config);
    gclk_chan_config.source_generator = GCLK_GENERATOR_1;
    system_gclk_chan_set_config(SYSCTRL_GCLK_ID_FDPLL,&gclk_chan_config);
    system_gclk_chan_enable(SYSCTRL_GCLK_ID_FDPLL);

    /* configure and enable clock source: DPLL (SYSCTRL registers) */
    struct system_clock_source_dpll_config dpll_config;
    system_clock_source_dpll_get_config_defaults(&dpll_config);
    dpll_config.reference_clock = SYSTEM_CLOCK_SOURCE_DPLL_REFERENCE_CLOCK_GCLK;
    dpll_config.reference_divider = 1;
    dpll_config.reference_frequency = 1000000;
    dpll_config.output_frequency = 30000000;
    system_clock_source_dpll_set_config(&dpll_config);
    system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DPLL);

    /* set NVM wait states */
    system_flash_set_waitstates(2);

    /* configure and enable generic clock 0 (GCLK_MAIN) */
    struct system_gclk_gen_config gclk_gen_config0;
    system_gclk_gen_get_config_defaults(&gclk_gen_config0);
    gclk_gen_config0.source_clock = SYSTEM_CLOCK_SOURCE_DPLL;
    gclk_gen_config0.division_factor = 1;
    system_gclk_gen_set_config(GCLK_GENERATOR_0,&gclk_gen_config0);
    system_gclk_gen_enable(GCLK_GENERATOR_0);
}

我更新了conf_clocks.h头以反映更改(我不知道这些宏是否在其他地方被引用,所以只是以防万一),我还更改了从system_init()调用的system_clock_init()函数。

EN

回答 2

Stack Overflow用户

发布于 2017-02-17 23:23:17

我从来都不喜欢使用Atmel的ASF,因为你永远不会只做你想做的事情。我建议你多看看数据表,因为这比潜伏在ASF中完成任务花费的时间要少得多。Atmel产品手册甚至有一个“初始化”章节,它逐步解释了要做什么。

启用OSC8基本上需要5行代码:

代码语言:javascript
复制
/* Various bits in the INTFLAG register can be set to one at startup.
This will ensure that these bits are cleared */
SYSCTRL->INTFLAG.reg = SYSCTRL_INTFLAG_BOD33RDY | SYSCTRL_INTFLAG_BOD33DET | SYSCTRL_INTFLAG_DFLLRDY;

/* OSC8M Internal 8MHz Oscillator */
SYSCTRL->OSC8M.bit.PRESC = SYSTEM_OSC8M_DIV_1;
SYSCTRL->OSC8M.bit.ONDEMAND = CONF_CLOCK_OSC8M_ON_DEMAND;
SYSCTRL->OSC8M.bit.RUNSTDBY = CONF_CLOCK_OSC8M_RUN_IN_STANDBY;

/* Enable OSC8M */
SYSCTRL->OSC8M.reg |= SYSCTRL_OSC8M_ENABLE;

剩下的步骤只是通过使用已经使能的OSC8M来配置dpll寄存器,这也只是几行代码。(写入GCLK.GENDIV/GENCTRL和CLKCTRL寄存器以及写入SYSCTRL.DPLL寄存器。

票数 1
EN

Stack Overflow用户

发布于 2018-10-24 22:44:48

要将ASF配置为以其支持的最大频率(48 MHz)工作,我不使用SAMD21,而是使用取自Arduino SAMD核心的代码;您可以在https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/startup.c的SystemInit()函数中找到它的作用。引用该文件中的注释,在SystemInit()中完成的相关步骤如下:

  • 使能XOSC32K时钟(外部板载32.768 to振荡器),将用作DFLL48M参考
  • Put XOSC32K作为通用时钟生成器1的来源
  • Put通用时钟生成器1作为通用时钟多路复用器0的来源(DFLL48M Clock DFLL48M clock
  • Switch通用时钟生成器0至DFLL48M。CPU将以48 CPU

运行。

相关代码行(假设您的主板安装了一个外部32.768 kHz晶体)为:

代码语言:javascript
复制
/* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;

/* Turn on the digital interface clock */
PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;

/* Enable XOSC32K clock (External on-board 32.768Hz oscillator) */
SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
                       SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
{
  /* Wait for oscillator stabilization */
}

/* Software reset the module to ensure it is re-initialized correctly */
GCLK->CTRL.reg = GCLK_CTRL_SWRST ;
while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
{
  /* Wait for reset to complete */
}

/* Put XOSC32K as source of Generic Clock Generator 1 */
GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Write Generic Clock Generator 1 configuration */
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
                    GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
//                  GCLK_GENCTRL_OE | // Output clock to a pin for tests
                    GCLK_GENCTRL_GENEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference) */
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
                  GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
                  GCLK_CLKCTRL_CLKEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Enable DFLL48M clock */  
SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}
SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
                       SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
                       SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK + VARIANT_MAINOSC/2) / VARIANT_MAINOSC ) ; // External 32KHz is the reference
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Write full configuration to DFLL control register */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
                         SYSCTRL_DFLLCTRL_WAITLOCK |
                         SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Enable the DFLL */
SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
        (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
{
  /* Wait for locks flags */
}
while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
{
  /* Wait for synchronization */
}

/* Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz. */
GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}

/* Write Generic Clock Generator 0 configuration */
GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
                    GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
//                  GCLK_GENCTRL_OE | // Output clock to a pin for tests
                    GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
                    GCLK_GENCTRL_GENEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
  /* Wait for synchronization */
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42025662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档