使用GD32F450的demo修改usb驱动,发现120M和168M时正常,200M时很不稳定。怀疑USB时钟分频有问题,一查果然是,记录如下:

200M是库函数主时钟分频代码如下

static void system_clock_200m_25m_hxtal(void)
{
uint32_t timeout = 0U;
uint32_t stab_flag = 0U; /* enable HXTAL */
RCU_CTL |= RCU_CTL_HXTALEN; /* wait until HXTAL is stable or the startup time is longer than HXTAL_STARTUP_TIMEOUT */
do{
timeout++;
stab_flag = (RCU_CTL & RCU_CTL_HXTALSTB);
}while((0U == stab_flag) && (HXTAL_STARTUP_TIMEOUT != timeout)); /* if fail */
if(0U == (RCU_CTL & RCU_CTL_HXTALSTB)){
while(){
}
} RCU_APB1EN |= RCU_APB1EN_PMUEN;
PMU_CTL |= PMU_CTL_LDOVS; /* HXTAL is stable */
/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB/2 */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV2;
/* APB1 = AHB/4 */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV4; /* Configure the main PLL, PLL_M = 25, PLL_N = 400, PLL_P = 2, PLL_Q = 9 */
RCU_PLL = (25U | (400U << 6U) | (((2U >> 1U) - 1U) << 16U) |
(RCU_PLLSRC_HXTAL) | (9U << 24U)); /* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN; /* wait until PLL is stable */
while(0U == (RCU_CTL & RCU_CTL_PLLSTB)){
} /* Enable the high-drive to extend the clock frequency to 200 Mhz */
PMU_CTL |= PMU_CTL_HDEN;
while(0U == (PMU_CS & PMU_CS_HDRF)){
} /* select the high-drive mode */
PMU_CTL |= PMU_CTL_HDS;
while(0U == (PMU_CS & PMU_CS_HDSRF)){
} /* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLLP; /* wait until PLL is selected as system clock */
while(0U == (RCU_CFG0 & RCU_SCSS_PLLP)){
}
}

这里注意几个重要信息,PLL_M=25,PLL_N=400,PLL_Q=9

再查看demo里的usb时钟配置代码,从代码里我们可以了解,USB时钟来源是PLLM_48M,而PLLM_48M是HXTAL倍频后经由PLLQ分频得到

    rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLQ);

    rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M);

    rcu_periph_clock_enable(RCU_USBFS);

对比数据手册里USB这块的时钟树我们计算下USB时钟

输入时钟25Mhz,USB时钟=25/PLL_M*PLL_N/PLL_Q=25/25*400/9=44.44444MHz,而我们知道USB需要48MHz的时钟才能稳定工作,所以这导致了USB工作的不稳定。

为什么120MHz和168MHz时不会有这个稳定呢?那是因为不同时钟主时钟分频函数不一样,在120MHz和168MHz时能分出48M的时钟给USB。

知道问题哪后,就好解决了,方法如下:

1、直接修改库函数里PLL的分频系数,这个方法新人不推荐

2、使用内部RCK_48M作为USB的时钟源,

rcu_ck48m_clock_config(RCU_CK48MSRC_IRC48M)
rcu_osci_on(RCU_IRC48M)
/* wait till RCU_IRC48M is ready */
while(SUCCESS != rcu_osci_stab_wait(RCU_IRC48M)){
}

3、修改PLLM_48M由PLLAI分频来

    //使用PLLAI_Q作为PLL_SEL的输入
rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLSAIP);
//使用PLL_SEL作为usb主频
rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M); /* configure PLLSAI
 PLLAI_N=192;PLL_P=192/4=48MHZ,PLL_Q=192/2=96MHZ,PLL_R=192/3=64MHZ
注意,此处的PLL_P用于后面的USB主时钟,要确保为48MHZ
*/
if(ERROR == rcu_pllsai_config(, , , ))
{
while();
} rcu_osci_on(RCU_PLLSAI_CK); if(ERROR == rcu_osci_stab_wait(RCU_PLLSAI_CK))
{
while();
}

GD32F450 200M时USB不稳定的更多相关文章

  1. TL-WR703 USB不稳定/当前的总结

    http://see.sl088.com/wiki/WR703_USB%E4%B8%8D%E7%A8%B3%E5%AE%9A/%E5%BD%93%E5%89%8D%E7%9A%84%E6%80%BB% ...

  2. arduino 引脚作为输入时的不稳定 解决方案

    问题描述: arduino引脚作为输入状态时,高低电平不稳定 出现的原因: arduino 引脚为输入时,引脚电平处于悬空状态,容易受外部电荷信号等干扰 解决的方案: 再程序配置为输入状态后 使用下拉 ...

  3. USB电源管理

    在USB总线接口协议中,由于涉及电源供电,因此协议中规定了完整的电源管理方案.通过USB电源管理可以实现USB设备的激活.挂起.空闲和睡眠等,从而降低无效的功率消耗,实现系统电源的有效使用和合理分配. ...

  4. usb 枚举流程

    Linux-USB总线驱动分析 如下图所示,以windows为例,我们插上一个没有USB设备驱动的USB,就会提示你安装驱动程序 为什么一插上就有会提示信息? 是因为windows自带了USB总线驱动 ...

  5. USB/232/485/TTL/CMOS(串口通信)⭐⭐⭐

    1.USB:电脑的USB口信号时USB信号,为差分信号,电压范围:+400mV~-400mV间变化:直流电压5V 驱动电流500MA 2.232电平: 逻辑1(MARK)=-3V--15V 逻辑0(S ...

  6. 《Linux总线、设备与驱动》USB设备发现机制

    说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核版本仅供参考. 一.程序在内核中的位置 1.usb host做为pci总线下的一个设备存在(嵌入式系统中有可能也会直接挂在 ...

  7. 八、USB驱动分析

    学习目标:分析USB驱动源码结构. 一.Windows下USB驱动理论问题 1. 当usb设备接入PC时,右下角弹出"发现AAA",并弹出对话框,提示安装驱动程序.没有驱动程序,W ...

  8. USB协议基础知识

    ref : https://blog.csdn.net/u010142953/article/details/82627591 USB 基本知识  USB的重要关键概念:  1. 端点:位于USB设备 ...

  9. STC8H开发(九): STC8H8K64U模拟USB HID外设

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

随机推荐

  1. 如何在windows下用IDA优雅调试ELF

    在windows下如何用IDA优雅调试ELF brief: 构建一个IDA-linux_server-docker镜像,优雅地IDA远程调试 使用传统虚拟机来运行一个linux程序就得跑一个完整的li ...

  2. linux性能系列--网络

    一.为啥网络监控不好做?   回答:网络是所有子系统中最难监控的了.首先是由于网络是抽象的,更重要的是许多影响网络的因素并不在我们的控制范围之内.这些因素包括,延迟.冲突.阻塞等 等.由于网络监控中, ...

  3. memcached源码剖析4:并发模型

    memcached是一个典型的单进程系统.虽然是单进程,但是memcached内部通过多线程实现了master-worker模型,这也是服务端最常见的一种并发模型.实际上,除了master线程和wor ...

  4. MySQL存储过程-遍历游标的例子

    delimiter $$DROP PROCEDURE IF EXISTS pro_test ;CREATE PROCEDURE pro_test()begin DECLARE var_name var ...

  5. Angular2.0知识架构图

    知识架构图:

  6. Voronoi图及matlab实现

    [题外话:想一想真是...美赛时我预测求爱尔兰的充电站位置分布,画Voronoi图,程序跑了一个小时...]   Voronoi图,又叫泰森多边形或Dirichlet图,它是由一组由连接两邻点直线的垂 ...

  7. Java并发案例03---生产者消费者问题02

    生产者消费者第二种情形 package com.maple.msb.one; public class ProducerConsumer { public static void main(Strin ...

  8. Java反序列化之Jackson-databind

    这个洞的cve编号:CVE-2017-17485,漏洞环境就如第一个链接那样,jdk需要在jdk 1.8以上. 先看一下Jackson-databind的用法,说白了就是将json转换成对象. tes ...

  9. [Python web开发] Web框架开发基础 (一)

    Python WEB框架 WSGI,WEB Server Gateway Interface,可以看做是一种底层协议,它规定了服务器程序和应用程序各自实现上面接口.Python的实现称为wsgiref ...

  10. vlc源码分析(二) 播放流程

    当点击播放文件或者输入要播放的文件后,vlc会执行一系列的流程. 首先需要了解视频以及流媒体处理及播放的流程,由链接中的描述,视频以及流媒体处理时,首先要解协议(http,rtmp,rtsp等),然后 ...