7

RP2040(树莓派Pico) 时钟系统

 3 years ago
source link: https://www.taterli.com/7517/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

RP2040(树莓派Pico) 时钟系统

  • TaterLi
  • 2021年1月29日2021年1月29日

RP2040的时钟结构相当的简单:

ROSC(环形振荡器),频率精度不到1000ppm,用来做PLL有点困难.

  • PLL_SYS = 125MHz (默认) 133MHz (最高)
  • PLL_USB = 48MHz (固定)
  • CLK_SYS = PLL_SYS/CLK_REF (系统时钟,除非DORMANT模式,否则在这两个时钟中选择)
  • CLK_PERI = CLK_SYS (外设时钟)
  • CLK_USB = PLL_USB (固定)
  • CLK_ADC = PLL_USB (固定)
  • CLK_RTC = 46875Hz (用于RTC计数,12MHz / 256 = 46875Hz,CLKDIV_M1 = 46874时,频率1Hz)
  • GPCLK INPUT = 从IO输入时钟 (可选)

官方例子Hello 48MHz是从USB取时钟,直接导出到系统时钟.由于系统内目前最快的时钟给是125MHz,而时钟只有除法,所以需要先考虑调高PLL_SYS.

PLL SYS = 12MHz(REF) * 125(FBDIV) = 1500MHZ(VCO) / 6(POSTDIV1) / 2(POSTDIV2) = 125MHz

想提高频率,就得提高VCO的倍率,即调整FBDIV.VCO = 1596MHz,调整PLL_SYS时候记得先让系统切换到PLL_USB,不然系统就进入RESUS了,我修改Hello 48MHz文件得到的结果.


int main() {
    stdio_init_all();

    printf("Hello, world!\n");

    measure_freqs();

    // Change clk_sys to be 48MHz. The simplest way is to take this from PLL_USB
    // which has a source frequency of 48MHz
    clock_configure(clk_sys,
                    CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
                    CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
                    48 * MHZ,
                    48 * MHZ);

    // Turn off PLL sys for good measure
    pll_deinit(pll_sys);
    pll_init(pll_sys, 1, 1596 * MHZ, 6, 2);

    clock_configure(clk_sys,
                    CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
                    CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
                    133 * MHZ,
                    133 * MHZ);

    clock_configure(clk_peri,
                    0,
                    CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS,
                    125 * MHZ,
                    125 * MHZ);

    // Re init uart now that clk_peri has changed
    stdio_init_all();

    measure_freqs();
    printf("Hello, 48MHz");

    return 0;
}
image-30.png

另外两个例子,一个是输出时钟,一个是发生RESUS时候紧急重新初始化逻辑,由于代码很简单,这里就不多废话了.

还有XOSC Countdown计数就是用作延迟用途的,官方库的sleep_ms就自带低功耗功能的并且用上了XOSC Countdown.

最后一个知识点DORMANT模式,这是一个低功耗模式,只要一个函数就可以进入,这个函数就是xosc_dormant().

在DORMANT模式下,所有的片上时钟都暂停,降低功耗.和其他传统单片机差不多,可以通过RTC和引脚INT唤醒,如果是RTC唤醒,必须有外部时钟源,进入之前内部时钟必须切换到XOSC(唤醒1ms)或者ROSC启动(唤醒1us),唤醒后需要重新配置PLL.(真TM不智能,很多国产芯片都能自动恢复了,更不说主流老牌的.)

代码参考,记得如果要用做DORMANT模式,不能开启PLL,即输入频率等于输出频率.

ROSC => CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_ROSC_CLKSRC
XOSC => CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_XOSC_CLKSRC

那么,时钟方面就差不多了.

发表评论 取消回复

邮箱地址不会被公开。 必填项已用*标注

评论

姓名 *

电子邮件 *

站点


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK