RP2040 C SDK clocks时钟源配置使用

2024-09-07 00:28

本文主要是介绍RP2040 C SDK clocks时钟源配置使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

RP2040 C SDK clocks时钟源配置使用


  • 🌿RP2040时钟源API函数文档:https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#group_hardware_clocks

  • 🍁RP2040时钟树:
    在这里插入图片描述

系统时钟源可以来自外部时钟输入(external clocks)、 晶体振荡器(XOSC)或者经过晶体振荡器到USB时钟倍频、或者系统倍频、ROSC(环形振荡器)。

  • ✨RP2040系统默认工作频率是125MHz ,最高是133MHz ,应该是可以超频,但是不建议这么做。

📘PLL倍频介绍

从上面的那张图可以看到系统倍频源可以选择USB PLL和System PLL。

• pll_sys - Used to generate up to a 133MHz system clock
• pll_usb - Used to generate a 48MHz USB reference clock

  • 倍频内部转换结构图:
    在这里插入图片描述
    注解:在两个PLLs上,FREF(参考)输入连接到晶体振荡器的XI输入。PLL包含一个VCO,它通过反馈回路(相位频率检测器和环路滤波器)锁定到参考时钟的恒定比率。这可以合成非常高的频率,它可以被后分频器所划分。
  • 🔖PLL的最终输出频率计算公式: FOUTPOSTDIV = (FREF / REFDIV) × FBDIV / (POSTDIV1 × POSTDIV2).
  • 🌿PLL设计时,需要注意以下约束条件来选择PLL参数:
  • 最小参考频率(FREF / REFDIV)是5MHz
  • 振荡器频率(FOUTVCO))必须在750兆赫→1600MHz
  • 反馈分配器(FBDIV)必须在16→320
  • 后分配器POSTDIV1和POSTDIV2必须在1→7
  • 最大输入频率(FREF/REFDIV)VCO频率除以16,由于最小反馈除数
    此外,必须遵守芯片时钟发生器(连接到输出)的最大频率。对于系统PLL,这是133MHz,而对于USB PLL,这是48MHz。
  • 🔖数据手册原文(第229页):
    • Minimum reference frequency (FREF / REFDIV) is 5MHz
    • Oscillator frequency (FOUTVCO) must be in the range 750MHz → 1600MHz
    • Feedback divider (FBDIV) must be in the range 16 → 320
    • The post dividers POSTDIV1 and POSTDIV2 must be in the range 1 → 7
    • Maximum input frequency (FREF / REFDIV) is VCO frequency divided by 16, due to minimum feedback divisor
    Additionally, the maximum frequencies of the chip’s clock generators (attached to FOUTPOSTDIV) must be respected. For the system PLL this is 133MHz, and for the USB PLL, 48MHz.
  • ✨在硬件设计上,选择外部晶体振荡器是,时钟频率参数:5- 15MHz
  • 👉当POSTDIV1和POSTDIV2需要两个不同的值时,最好将较高的值分配给POSTDIV1,以获得较低的功耗。
  • 将12MHz晶体连接到晶体振荡器,这意味着最小可实现和合法的VCO频率是12MHz×63 = 756MHz,最大VCO是12MHz×133 = 1596MHz,所以FBDIV必须保持在63→133范围内。例如,将FBDIV设置为100将合成一个1200MHz的VCO频率。一个POSTDIV1值为6,一个POSTDIV2值为2,将总共除以12,在PLL的最终输出处产生一个干净的100MHz。
  • 📐官方在PICO SDK资料包,中提供了一个换算PLL参数的.py文件:"\Pico SDK v1.5.1\pico-sdk\src\rp2_common\hardware_clocks\scripts\vcocalc.py",输入最终频率,即可获得各PLL参数。
    在这里插入图片描述
  • 🔖其中的PD1对应的是POSTDIV1,PD2对应POSTDIV2
  • 🌿通过vcocalc.py计算获得的参数,软件代码配置函数:
void pll_init(PLL pll, uint refdiv, uint vco_freq, uint post_div1, uint post_div2)
  • 📑配置频率方法:

✨调整PLL_SYS时,需要先让系统时钟切换到PLL_USB,不然系统就进入锁死状态(RESUS).


// Change clk_sys to be 48MHz. The simplest way is to take this from PLL_USB// which has a source frequency of 48MHzclock_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 measurepll_deinit(pll_sys);
pll_init(pll_sys, 1, 1596 * MHZ, 6, 2);
clock_configure(clk_sys,//设置系统时钟,设置源为PLL_SYS,辅助源为CLK_SYS_AUX,目标频率为133MHzCLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,133 * MHZ,//辅助源频率133 * MHZ);//目标频率
  • 主时钟源:
    在这里插入图片描述
  • 辅助时钟源
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

📒Resus状态

有可能编写出无意中阻止clk_sys的软件。这通常会导致内核和片上调试器的不可恢复的锁定,从而使用户无法跟踪该问题。为了缓解这种情况,提供了一个自动复苏电路,如果在用户定义的间隔内没有检测到边缘,该电路将clk_sys切换到已知的良好时钟源。已知的良好源是clk_ref,它可以从XOSC、ROSC或外部源驱动。(手册189页)

  • 👉一旦芯片进入Resus状态,则需要按住Boot按键,接入USB口,让芯片进入DFU模式,才能正常通过CMSIS-DAP重新烧写程序。

  • 🌿或者使用下面的函数,直接自动配置:

set_sys_clock_khz(133000, true);

🌟请注意,并非所有时钟频率都是可能的;
Note that not all clock frequencies are possible;
最好是你it is preferred that you
*使用src/rp2_common/hardware_clocks/scripts/vcocalc.py计算参数
*use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
*用于set_sys_clock_pll
*for use with set_sys_clock_pll

📗clock API有关函数
bool clock_configure (clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t freq)
Configure the specified clock.void clock_configure_undivided (clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq)
Configure the specified clock to use the undividded input source.void clock_configure_int_divider (clock_handle_t clock, uint32_t src, uint32_t auxsrc, uint32_t src_freq, uint32_t int_divider)
Configure the specified clock to use the undividded input source.void clock_stop (clock_handle_t clock)
Stop the specified clock.uint32_t clock_get_hz (clock_handle_t clock)
Get the current frequency of the specified clock.uint32_t frequency_count_khz (uint src)
Measure a clocks frequency using the Frequency counter.void clock_set_reported_hz (clock_handle_t clock, uint hz)
Set the "current frequency" of the clock as reported by clock_get_hz without actually changing the clock.void clocks_enable_resus (resus_callback_t resus_callback)
Enable the resus function. Restarts clk_sys if it is accidentally stopped.void clock_gpio_init_int_frac (uint gpio, uint src, uint32_t div_int, uint8_t div_frac)
Output an optionally divided clock to the specified gpio pin.static void clock_gpio_init (uint gpio, uint src, float div)
Output an optionally divided clock to the specified gpio pin.bool clock_configure_gpin (clock_handle_t clock, uint gpio, uint32_t src_freq, uint32_t freq)
Configure a clock to come from a gpio input.
🛠使用时钟配置相关函数,CMakeLists.txt,需要包含hardware_clocks
# Add the standard library to the build
target_link_libraries(RP2040_CLOCKpico_stdlibhardware_clocks)

📝测试例程

// This code is used to test the clocks of the RP2040 chip.
/*
时钟倍频参数计算:"\Pico SDK v1.5.1\pico-sdk\src\rp2_common\hardware_clocks\scripts\vcocalc.py"
计算方法:vcocalc.py 133CMSIS-DAP烧录命令:openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c  "adapter speed 5000"-c "program RP2040_CLOCK.elf verify reset exit"jlink命令: openocd -f interface/jlink.cfg -f target/rp2040.cfg  -c  "adapter speed 2000" -c  "program RP2040_RTC.elf verify reset exit"*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "hardware/divider.h"
#include "hardware/clocks.h"
#include "hardware/pll.h"
#include "hardware/clocks.h"
#include "hardware/structs/pll.h"
#include "hardware/structs/clocks.h"#define BUILTIN_LED PICO_DEFAULT_LED_PIN    // LED is on the same pin as the default LED 25void measure_freqs(void) {uint f_pll_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_SYS_CLKSRC_PRIMARY);uint f_pll_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_PLL_USB_CLKSRC_PRIMARY);uint f_rosc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_ROSC_CLKSRC);uint f_clk_sys = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS);uint f_clk_peri = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_PERI);uint f_clk_usb = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_USB);uint f_clk_adc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_ADC);uint f_clk_rtc = frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_RTC);printf("pll_sys  = %dkHz\n", f_pll_sys);printf("pll_usb  = %dkHz\n", f_pll_usb);printf("rosc     = %dkHz\n", f_rosc);printf("clk_sys  = %dkHz\n", f_clk_sys);printf("clk_peri = %dkHz\n", f_clk_peri);printf("clk_usb  = %dkHz\n", f_clk_usb);printf("clk_adc  = %dkHz\n", f_clk_adc);printf("clk_rtc  = %dkHz\n", f_clk_rtc);// Can't measure clk_ref / xosc as it is the ref
}int main()
{stdio_init_all();sleep_ms(3500);printf("RP204 Clock Test\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 48MHzclock_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);                48 * MHZ);// Turn off PLL sys for good measurepll_deinit(pll_sys);pll_init(pll_sys, 1, 1596 * MHZ, 6, 2);clock_configure(clk_sys,//设置系统时钟,设置源为PLL_SYS,辅助源为CLK_SYS_AUX,目标频率为133MHzCLOCKS_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);//set_sys_clock_khz(124000, true); // 346us//set_sys_clock_khz(126000, true); // 340us//set_sys_clock_khz(128000, true); // 335us//set_sys_clock_khz(130000, true); // 330us//set_sys_clock_khz(131000, true); // 328us// set_sys_clock_khz(133000, true);// 325us// GPIO initialisation.// We will make this GPIO an input, and pull it up by defaultgpio_init(BUILTIN_LED);gpio_set_dir(BUILTIN_LED, 1);gpio_pull_up(BUILTIN_LED);while(true){sleep_ms(1000);gpio_xor_mask(1ul << BUILTIN_LED); // Toggle the LEDmeasure_freqs();__asm volatile ("nop\n");}return 0;
}

在这里插入图片描述

这篇关于RP2040 C SDK clocks时钟源配置使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1143534

相关文章

springboot security快速使用示例详解

《springbootsecurity快速使用示例详解》:本文主要介绍springbootsecurity快速使用示例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝... 目录创www.chinasem.cn建spring boot项目生成脚手架配置依赖接口示例代码项目结构启用s

Python如何使用__slots__实现节省内存和性能优化

《Python如何使用__slots__实现节省内存和性能优化》你有想过,一个小小的__slots__能让你的Python类内存消耗直接减半吗,没错,今天咱们要聊的就是这个让人眼前一亮的技巧,感兴趣的... 目录背景:内存吃得满满的类__slots__:你的内存管理小助手举个大概的例子:看看效果如何?1.

springboot security之前后端分离配置方式

《springbootsecurity之前后端分离配置方式》:本文主要介绍springbootsecurity之前后端分离配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的... 目录前言自定义配置认证失败自定义处理登录相关接口匿名访问前置文章总结前言spring boot secu

一文详解SpringBoot响应压缩功能的配置与优化

《一文详解SpringBoot响应压缩功能的配置与优化》SpringBoot的响应压缩功能基于智能协商机制,需同时满足很多条件,本文主要为大家详细介绍了SpringBoot响应压缩功能的配置与优化,需... 目录一、核心工作机制1.1 自动协商触发条件1.2 压缩处理流程二、配置方案详解2.1 基础YAML

java中使用POI生成Excel并导出过程

《java中使用POI生成Excel并导出过程》:本文主要介绍java中使用POI生成Excel并导出过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录需求说明及实现方式需求完成通用代码版本1版本2结果展示type参数为atype参数为b总结注:本文章中代码均为

springboot简单集成Security配置的教程

《springboot简单集成Security配置的教程》:本文主要介绍springboot简单集成Security配置的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录集成Security安全框架引入依赖编写配置类WebSecurityConfig(自定义资源权限规则

SpringBoot中封装Cors自动配置方式

《SpringBoot中封装Cors自动配置方式》:本文主要介绍SpringBoot中封装Cors自动配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录SpringBoot封装Cors自动配置背景实现步骤1. 创建 GlobalCorsProperties

Spring Boot结成MyBatis-Plus最全配置指南

《SpringBoot结成MyBatis-Plus最全配置指南》本文主要介绍了SpringBoot结成MyBatis-Plus最全配置指南,包括依赖引入、配置数据源、Mapper扫描、基本CRUD操... 目录前言详细操作一.创建项目并引入相关依赖二.配置数据源信息三.编写相关代码查zsRArly询数据库数

Spring Boot3虚拟线程的使用步骤详解

《SpringBoot3虚拟线程的使用步骤详解》虚拟线程是Java19中引入的一个新特性,旨在通过简化线程管理来提升应用程序的并发性能,:本文主要介绍SpringBoot3虚拟线程的使用步骤,... 目录问题根源分析解决方案验证验证实验实验1:未启用keep-alive实验2:启用keep-alive扩展建

SpringBoot配置Ollama实现本地部署DeepSeek

《SpringBoot配置Ollama实现本地部署DeepSeek》本文主要介绍了在本地环境中使用Ollama配置DeepSeek模型,并在IntelliJIDEA中创建一个Sprin... 目录前言详细步骤一、本地配置DeepSeek二、SpringBoot项目调用本地DeepSeek前言随着人工智能技