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

相关文章

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

如何使用Java实现请求deepseek

《如何使用Java实现请求deepseek》这篇文章主要为大家详细介绍了如何使用Java实现请求deepseek功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1.deepseek的api创建2.Java实现请求deepseek2.1 pom文件2.2 json转化文件2.2

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

在 Spring Boot 中使用 @Autowired和 @Bean注解的示例详解

《在SpringBoot中使用@Autowired和@Bean注解的示例详解》本文通过一个示例演示了如何在SpringBoot中使用@Autowired和@Bean注解进行依赖注入和Bean... 目录在 Spring Boot 中使用 @Autowired 和 @Bean 注解示例背景1. 定义 Stud

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Python快速实现链接转word文档

《使用Python快速实现链接转word文档》这篇文章主要为大家详细介绍了如何使用Python快速实现链接转word文档功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 演示代码展示from newspaper import Articlefrom docx import

oracle DBMS_SQL.PARSE的使用方法和示例

《oracleDBMS_SQL.PARSE的使用方法和示例》DBMS_SQL是Oracle数据库中的一个强大包,用于动态构建和执行SQL语句,DBMS_SQL.PARSE过程解析SQL语句或PL/S... 目录语法示例注意事项DBMS_SQL 是 oracle 数据库中的一个强大包,它允许动态地构建和执行

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2