背景
因项目国产化需要,使用国产化MCU(雅特力)ATF32F413CBT6替代STM32F103C8T6。该项目使用8M外部晶振作为系统时钟来源,经PLL锁相环倍频至72M作为系统时钟,在使用过程中发现,系统时钟设置失败,默认使用内部8M频率源作为系统时钟来源。
原因分析
首先想到的原因是因为硬件电路的问题导致外部晶振未起振,因此系统初始化的过程中系统时钟设置失败,外部时钟启动失败后,MCU会自动将内部8M频率源作为系统时钟来源。但通过示波器测量晶振引脚可观察到稳定的8M频率的正弦波震荡波形,证明外部晶是正常工作的,该现象应该是程序问题导致的。
该项目中使用的是STM32的库函数,未对程序进行改动。STM32的库函数中是在系统初始化阶段对系统时钟进行设置的。通过STlinK在线调试发现,在进行单步调试时,初始化阶段是可以将系统设置为72M的,但在程序全速运行时却设置失败。通过查看库函数代码:
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
程序在使能外部晶振后,会有一个等待时间,等待外部晶振稳定后继续执行频率设置指令。但这个等待时间不是无限长的,有一个超时时间计数 HSE_STARTUP_TIMEOUT,超时之后就会默认外部晶振开启失败。
因为在手动单步调试时,指令间的间隔时间较长,外部晶振稳定有足够的时间稳定,所以可以设置成功。但程序全速运行后,等待的时间不足导致超时,系统时间设置失败。库函数中HSE_STARTUP_TIMEOUT 的值定义为0x0500,通过将其增为0x0800后,系统时钟可设置成功。
结论
ATF32F413CBT6在使用外部晶振作为系统来源时,等待外部晶振稳定的时间比STM32F103C8T6要长,如果不将超时时间延长会导致系统设置失败。