GD32的时钟树如下所示
当我们需要使用usb功能升级app程序时我们需要修改时钟配置。
根据USB标准规定,USB全速模块需要使用48MHz的固定时钟。为了满足这一要求,需要同时配置两个时钟:USB控制器时钟和APB1到USB接口时钟。USB控制器时钟的频率必须精确到48MHz,而APB1到USB接口时钟实际上是APB1总线时钟,它的频率可以高于或低于48MHz。
当使用外部晶振产生USB时钟时,需要注意USB分频系数只提供了4个选项:1分频、1.5分频、2分频和2.5分频(2.5分频不可用,因为GD32F10x MCU的频率无法达到108MHz以上)。因此,为了获得48MHz的USB时钟,只有通过PLL倍频后可以获得48MHz、72MHz和96MHz这几个选项。
因此,我们需要将主时钟配置为96MHz,然后根据这个主时钟来设置其他时钟。要实现这个配置,可以修改文件system_gd32f10x.c,将108MHz的选项注释掉,将96MHz的选项打开,并指定96MHz的频率:
#define__SYSTEM_CLOCK_96M_PLL_HXTAL (uint32_t)(96000000)
// #define __SYSTEM_CLOCK_108M_PLL_HXTAL (uint32_t)(108000000)
之所以不用我们在程序中再次配置时钟是因为在系统初始化过程中,使用了以下关键的函数和操作:
我们可以在启动文件中看出在 启动文件(通常是由编译器生成的)中,定义了复位处理函数 `Reset_Handler`。在这个函数中,首先导出了 `Reset_Handler`,以确保它可以被其他模块引用。然后,通过 `IMPORT` 指令导入了 `__main` 和 `SystemInit` 函数的地址。接下来,使用汇编指令 `LDR` 和 `BLX`,调用了 `SystemInit` 函数,执行了系统初始化。最后,通过 `LDR` 和 `BX` 指令,跳转到了主程序的入口点 `__main`。
在 `SystemInit()` 函数中,调用了 `system_clock_config()` 函数,以确保在启动时进行了正确的时钟配置。
在`system_clock_config()` 函数中,根据宏定义 `__SYSTEM_CLOCK_96M_PLL_HXTAL` 的设置,调用了 `system_clock_96m_hxtal()` 函数。这个函数是用于配置系统主时钟为96MHz,并使用外部晶振(HXTAL)的函数。这是确保主时钟频率为96MHz的关键步骤 ,108MHz同理。
这一系列操作确保了在系统启动时,首先进行了正确的时钟配置,然后执行了系统初始化,最终跳转到了主程序的入口点。这样,系统可以正确的时钟频率启动并执行应用程序。