RP2040(树莓派Pico) 时钟系统

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;
}

另外两个例子,一个是输出时钟,一个是发生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

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

发表评论

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