Ernest · 2023年12月17日 · 浙江

【GD32F3苹果派开发板试用】+当MCU外部晶振失效实现自动切换

背景

在访问极术社区时,偶然发现GD32F3苹果派开发板的评估活动,看GD32F303的硬件配置和技术规格,120MHz、支持 DSP指令运算。Cortex-M4 内核,在同主频下的代码执行效率相比市场同类 Cortex-M4 产品提高 10%~20%,相比 Cortex-M3 产品更提高 30%。I/O 口可承受 5V 电平,全新设计的电压域支持高级电压管理功能,电流仅为 380µA/MHz,电池供电时的 RTC 待机电
流仅为 0.8µA,实现了最佳的能耗比。

很荣幸,在第一批试用名单中被选中。

想法为:

当MCU 外部晶振因特殊环境导致晶振失效情况下,实现MCU自动切换内部晶振,实现正常工作,确保产品正常运行。

实现原理

通过人为短接MCU外部晶振引脚,实现外部晶振失效,模拟产品主板中的MCU 失效,从而程序进入void NMI_Handler(void) 函数,该函数用于处理非屏蔽中断(NMI,Non-Maskable Interrupt)的处理程序。NMI是一种特殊的中断,它不能被其他中断屏蔽或关闭,在这个里面启动内部晶振,提供各外设时钟源,保证MCU尽快恢复正常运行,从而实现产品稳定性。

拉取代码

int main(void)
{

systick_config();  
rcu_hxtal_clock_monitor_enable();    
gd_eval_com_init(EVAL_COM0);
usart_disable(EVAL_COM0);
gd_eval_com_init(EVAL_COM0);
_delay(1000);
gd_eval_com_init(EVAL_COM0);
rcu_periph_clock_enable(RCU_GPIOF);
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
gpio_init(GPIOF, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
gpio_bit_reset(GPIOF, GPIO_PIN_0);
gpio_bit_reset(GPIOF, GPIO_PIN_1);
gpio_bit_reset(GPIOF, GPIO_PIN_2);    
while(1){
    printf("\r\nCK_SYS  V3  is %d", rcu_clock_freq_get(CK_SYS));  
    gpio_bit_set(GPIOF, GPIO_PIN_0);
    gpio_bit_set(GPIOF, GPIO_PIN_1);
    delay_1ms(20);
    gpio_bit_reset(GPIOF, GPIO_PIN_0);
    gpio_bit_reset(GPIOF, GPIO_PIN_1);
    delay_1ms(20);       
    ul_main_cnt++;
}

}

/*

 通过IRC 8MHZ 将系统时钟切换到72M  方案0

*/
void switch_system_clock_to_72m_irc8m(void)
{

uint32_t timeout = 0U;
uint32_t stab_flag = 0U;  
/* 选择IRC8M作为系统时钟源,反初始化RCU* */
rcu_system_clock_source_config(RCU_CKSYSSRC_IRC8M);
rcu_deinit();   
/* enable IRC8M */
RCU_CTL |= RCU_CTL_IRC8MEN;
/* 等待IRC8M稳定或启动时间比IRC8M START_TIMOUT长 */
do{
    timeout++;
    stab_flag = (RCU_CTL & RCU_CTL_IRC8MSTB);
}
while((0U == stab_flag) && (IRC8M_STARTUP_TIMEOUT != timeout));

/* if fail   如果时钟还没有稳定说明时钟异常,则在这里死循环 */
if(0U == (RCU_CTL & RCU_CTL_IRC8MSTB)){
  while(1){
  }
}

/* AHB = SYSCLK */
RCU_CFG0 |= RCU_AHB_CKSYS_DIV1;
/* APB2 = AHB */
RCU_CFG0 |= RCU_APB2_CKAHB_DIV1;
/* APB1 = AHB */
RCU_CFG0 |= RCU_APB1_CKAHB_DIV1;
/* PLL = (IRC8M/2) * 18 = 72 MHz */
RCU_CFG0 &= ~(RCU_CFG0_PLLSEL | RCU_CFG0_PLLMF);
RCU_CFG0 |= (RCU_PLLSRC_IRC8M_DIV2 | RCU_PLL_MUL2);

/* enable PLL */
RCU_CTL |= RCU_CTL_PLLEN;

/* wait until PLL is stable */
while(0 == (RCU_CTL & RCU_CTL_PLLSTB));

/* select PLL as system clock */
RCU_CFG0 &= ~RCU_CFG0_SCS;
RCU_CFG0 |= RCU_CKSYSSRC_PLL;

/* wait until PLL is selected as system clock */
while(0 == (RCU_CFG0 & RCU_SCSS_PLL));

}

void NMI_Handler(void)
{

switch_system_clock_to_72m_irc8m();

// switch_system_clock_to_72m_irc8m_V1();

}

实现效果

0.png
1.png
3.png
4.png
5.png
6.jpg
7.png

推荐阅读
关注数
0
文章数
1
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息