EFM32片内外设--RMU基本操作

本文介绍如何利用EFM32的RMU(复位管理单元)模块,方便地查找MCU(微控制器)复位的原因,通过查询RMU-RSTCAUSE寄存器获取复位来源,并提供代码示例和清除复位标志的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

造成MCU复位的原因,想必很很多。但是如何找到是何原因造成的复位,有时候却并不好找。EFM32提供了RMU的模块,全称为Reset Magagement Unit,复位管理单元。利用这个单元,就可以很方便的找到复位的原因了。

在MCU运行的过程当中,RMU会一直不停的检测各种复位源,例如POR Power-on Reset上电复位,BOD Brown-out Detection,以及外部Reset脚复位,看门狗复位,软件复位,或则是EM4唤醒等等。都可以通过查询RMU->RSTCAUSE这个来获知复位的原因。注意的是,有时候复位不是单一原因造成的,例如外部复位和看门狗复位同时发生等。

通过查看reference manual里面的表格,可以知道具体那几位代表的是什么意思。

初看,你会发现这张表格会稍显复杂一些,其实很简单,我们也不需要去记这张表格,请直接使用EMLib中的函RMU_ResetCauseGet() 即可获知复位的原因。

知道可以获知复位源之后,您肯定也想到了,如何去清除这个寄存器,为下一次查询做好准备了。查看Reference manual,发现这个RMU->RSTCAUSE这个寄存器是个只读类型,要清除这个寄存器,必须经过如下三个步骤:

往RMU->CMD中的RCCLR写1,往EMU->AUXCTRL中的bit0写1,然后再往EMU->AUXCTRL中的bit0写0.

或则调用:RMU_ResetCauseClear()来完成这项复杂的工作。呵呵。各位看官也可以参考如下的这段小代码(基于TG STK)。

#include <stdint.h>
#include <stdbool.h>
#include "efm32.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_rmu.h"
#include "em_gpio.h"
#include "segmentlcd.h"
#include "lcdtest.h"
#include "trace.h"


/**************************************************************************//**
 * @brief GPIO Interrupt handler (PB11)
 *****************************************************************************/
void GPIO_ODD_IRQHandler(void)
{
  GPIO_IntClear(1 << 11);
  RMU_ResetCauseClear();//使用按键来清除复位标志
}

/**************************************************************************//**
 * @brief GPIO Interrupt handler (PD8)
 *****************************************************************************/
void GPIO_EVEN_IRQHandler(void)
{
  GPIO_IntClear(1 << 8);
  RMU_ResetCauseClear(); //使用按键来清除复位标志
}

/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
  /* Chip errata */
  CHIP_Init();

  /* Enable GPIO in CMU */
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure PD8 and PB11 as input */
  GPIO_PinModeSet(gpioPortD, 8, gpioModeInput, 0);
  GPIO_PinModeSet(gpioPortB, 11, gpioModeInput, 0);

  /* Set falling edge interrupt for both ports */
  GPIO_IntConfig(gpioPortD, 8, false, true, true);
  GPIO_IntConfig(gpioPortB, 11, false, true, true);

  /* Enable interrupt in core for even and odd gpio interrupts */
  NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
  NVIC_EnableIRQ(GPIO_EVEN_IRQn);

  NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
  NVIC_EnableIRQ(GPIO_ODD_IRQn);
 

  /* Enable LCD without voltage boost */
  SegmentLCD_Init(false);

  SegmentLCD_AllOff();

  while(1)
  {
      unsigned long ulDelay = 500000;
      while(ulDelay--);
      SegmentLCD_Number(RMU_ResetCauseGet()); //将复位标志显示在LCD上
      //SegmentLCD_Number(RMU->RSTCAUSE);
  }
}

 

/** ******************************************************************************* * @file iap/iap_boot/source/main.c * @brief Main program of IAP Boot. @verbatim Change Logs: Date Author Notes 2022-03-31 CDT First version 2022-10-31 CDT Add configuration of XTAL IO as analog function 2023-01-15 CDT Replace PWC_HighPerformanceToLowSpeed to PWC_HighPerformanceToHighSpeed 2023-09-30 CDT SysTick_Handler add __DSB for Arm Errata 838869 2024-11-08 CDT Modify XTAL pins definition @endverbatim ******************************************************************************* * Copyright (C) 2022-2025, Xiaohua Semiconductor Co., Ltd. All rights reserved. * * This software component is licensed by XHSC under BSD 3-Clause license * (the "License"); You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ******************************************************************************* */ /******************************************************************************* * Include files ******************************************************************************/ #include "main.h" /******************************************************************************* * Local type definitions ('typedef') ******************************************************************************/ /******************************************************************************* * Local pre-processor symbols/macros ('#define') ******************************************************************************/ /* unlock/lock peripheral */ #define EXAMPLE_PERIPH_WE (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | \ LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM) #define EXAMPLE_PERIPH_WP (LL_PERIPH_GPIO | LL_PERIPH_EFM | LL_PERIPH_FCG | \ LL_PERIPH_PWC_CLK_RMU | LL_PERIPH_SRAM) /* Communication timeout */ #define IAP_COM_WAIT_TIME (2000UL) //ms /* BSP XTAL Configure definition */ #define BSP_XTAL_PORT (GPIO_PORT_H) #define BSP_XTAL_PIN (GPIO_PIN_00 | GPIO_PIN_01) /******************************************************************************* * Global variable definitions (declared in header file with 'extern') ******************************************************************************/ stc_modem_com_t ModemCom; stc_modem_flash_t ModemFlash; /******************************************************************************* * Local function prototypes ('static') ******************************************************************************/ /******************************************************************************* * Local variable definitions ('static') ******************************************************************************/ static uint32_t JumpAddr; static func_ptr_t JumpToApp; /******************************************************************************* * Function implementation - global ('extern') and local ('static') ******************************************************************************/ /** * @brief SysTick interrupt handler function. * @param None * @retval None */ void SysTick_Handler(void) { SysTick_IncTick(); __DSB(); /* Arm Errata 838869 */ } /** * @brief Systick De-Initialize. * @param None * @retval None */ void SysTick_DeInit(void) { SysTick->CTRL = 0UL; SysTick->LOAD = 0UL; SysTick->VAL = 0UL; } /** * @brief IAP clock initialize. * Set board system clock to PLL@200MHz * @param None * @retval None */ void IAP_CLK_Init(void) { stc_clock_xtal_init_t stcXtalInit; stc_clock_pll_init_t stcMpllInit; /* Set bus clk div. */ CLK_SetClockDiv(CLK_BUS_CLK_ALL, (CLK_HCLK_DIV1 | CLK_EXCLK_DIV2 | CLK_PCLK0_DIV1 | CLK_PCLK1_DIV2 | CLK_PCLK2_DIV4 | CLK_PCLK3_DIV4 | CLK_PCLK4_DIV2)); GPIO_AnalogCmd(BSP_XTAL_PORT, BSP_XTAL_PIN, ENABLE); (void)CLK_XtalStructInit(&stcXtalInit); /* Config Xtal and enable Xtal */ stcXtalInit.u8Mode = CLK_XTAL_MD_OSC; stcXtalInit.u8Drv = CLK_XTAL_DRV_ULOW; stcXtalInit.u8State = CLK_XTAL_ON; stcXtalInit.u8StableTime = CLK_XTAL_STB_2MS; (void)CLK_XtalInit(&stcXtalInit); (void)CLK_PLLStructInit(&stcMpllInit); /* MPLL config (XTAL / pllmDiv * plln / PllpDiv = 200M). */ stcMpllInit.PLLCFGR = 0UL; stcMpllInit.PLLCFGR_f.PLLM = 1UL - 1UL; stcMpllInit.PLLCFGR_f.PLLN = 50UL - 1UL; stcMpllInit.PLLCFGR_f.PLLP = 2UL - 1UL; stcMpllInit.PLLCFGR_f.PLLQ = 2UL - 1UL; stcMpllInit.PLLCFGR_f.PLLR = 2UL - 1UL; stcMpllInit.u8PLLState = CLK_PLL_ON; stcMpllInit.PLLCFGR_f.PLLSRC = CLK_PLL_SRC_XTAL; (void)CLK_PLLInit(&stcMpllInit); /* Wait MPLL ready. */ while (SET != CLK_GetStableStatus(CLK_STB_FLAG_PLL)) { } /* sram init include read/write wait cycle setting */ SRAM_Init(); SRAM_SetWaitCycle(SRAM_SRAM_ALL, SRAM_WAIT_CYCLE1, SRAM_WAIT_CYCLE1); SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0); /* 3 cycles for 126MHz ~ 200MHz */ GPIO_SetReadWaitCycle(GPIO_RD_WAIT3); /* flash read wait cycle setting */ EFM_SetWaitCycle(EFM_WAIT_CYCLE5); /* Switch driver ability */ (void)PWC_HighSpeedToHighPerformance(); /* Switch system clock source to MPLL. */ CLK_SetSysClockSrc(CLK_SYSCLK_SRC_PLL); } /** * @brief IAP clock De-Initialize. * @param None * @retval None */ void IAP_CLK_DeInit(void) { CLK_SetSysClockSrc(CLK_SYSCLK_SRC_MRC); /* Switch driver ability */ (void)PWC_HighPerformanceToHighSpeed(); /* Set bus clk div. */ CLK_SetClockDiv(CLK_BUS_CLK_ALL, (CLK_HCLK_DIV1 | CLK_EXCLK_DIV1 | CLK_PCLK0_DIV1 | CLK_PCLK1_DIV1 | CLK_PCLK2_DIV1 | CLK_PCLK3_DIV1 | CLK_PCLK4_DIV1)); CLK_PLLCmd(DISABLE); CLK_XtalCmd(DISABLE); /* sram init include read/write wait cycle setting */ SRAM_SetWaitCycle(SRAM_SRAM_ALL, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0); SRAM_SetWaitCycle(SRAM_SRAMH, SRAM_WAIT_CYCLE0, SRAM_WAIT_CYCLE0); /* 0 cycles */ GPIO_SetReadWaitCycle(GPIO_RD_WAIT0); /* flash read wait cycle setting */ EFM_SetWaitCycle(EFM_WAIT_CYCLE0); } /** * @brief CRC Initialize. * @param None * @retval None */ void IAP_CRC_Init(void) { stc_crc_init_t stcCrcInit; /* Enable CRC Clock */ FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_CRC, ENABLE); /* Initialize CRC16 */ CRC_StructInit(&stcCrcInit); CRC_Init(&stcCrcInit); } /** * @brief CRC De-Initialize. * @param None * @retval None */ void IAP_CRC_DeInit(void) { CRC_DeInit(); /* Disable CRC Clock */ FCG_Fcg0PeriphClockCmd(FCG0_PERIPH_CRC, DISABLE); } /** * @brief IAP peripheral initialize. * @param None * @retval None */ void IAP_PeriphInit(void) { /* Peripheral registers write unprotected */ LL_PERIPH_WE(EXAMPLE_PERIPH_WE); EFM_FWMC_Cmd(ENABLE); /* Init Peripheral */ IAP_CLK_Init(); SysTick_Init(1000U); COM_Init(); IAP_CRC_Init(); /* Configure COM interface */ ModemCom.SendData = COM_SendData; ModemCom.RecvData = COM_RecvData; /* Configure Flash interface */ ModemFlash.u32FlashBase = FLASH_BASE; ModemFlash.u32FlashSize = FLASH_SIZE; ModemFlash.u32SectorSize = FLASH_SECTOR_SIZE; ModemFlash.CheckAddrAlign = FLASH_CheckAddrAlign; ModemFlash.EraseSector = FLASH_EraseSector; ModemFlash.WriteData = FLASH_WriteData; ModemFlash.ReadData = FLASH_ReadData; } /** * @brief IAP peripheral de-initialize. * @param None * @retval None */ void IAP_PeriphDeinit(void) { /* De-Init Peripheral */ COM_DeInit(); IAP_CRC_DeInit(); SysTick_DeInit(); IAP_CLK_DeInit(); /* Peripheral registers write protected */ EFM_FWMC_Cmd(DISABLE); LL_PERIPH_WP(EXAMPLE_PERIPH_WP); } /** * @brief Jump from boot to app function. * @param [in] u32Addr APP address * @retval LL_ERR APP address error */ int32_t IAP_JumpToApp(uint32_t u32Addr) { uint32_t u32StackTop = *((__IO uint32_t *)u32Addr); /* Check stack top pointer. */ if ((u32StackTop > SRAM_BASE) && (u32StackTop <= (SRAM_BASE + SRAM_SIZE))) { IAP_PeriphDeinit(); /* Jump to user application */ JumpAddr = *(__IO uint32_t *)(u32Addr + 4U); JumpToApp = (func_ptr_t)JumpAddr; /* Initialize user application's Stack Pointer */ __set_MSP(u32StackTop); JumpToApp(); } return LL_ERR; } /** * @brief IAP check app. * @param None * @retval None */ void IAP_CheckApp(void) { uint32_t u32AppAddr; if ((APP_UPGRADE_FLAG != *(__IO uint32_t *)APP_UPGRADE_FLAG_ADDR)) { if ((APP_EXIST_FLAG == *(__IO uint32_t *)APP_EXIST_FLAG_ADDR)) { u32AppAddr = *(__IO uint32_t *)APP_RUN_ADDR; if ((u32AppAddr >= (FLASH_BASE + IAP_BOOT_SIZE)) && (u32AppAddr < (FLASH_BASE + FLASH_SIZE))) { if (LL_OK != IAP_JumpToApp(u32AppAddr)) { /* Jump to app failed */ } } } } } /** * @brief Main function of Boot. * @param None * @retval int32_t return value, if needed */ int32_t main(void) { IAP_PeriphInit(); /* Check app validity */ IAP_CheckApp(); for (;;) { if (LL_OK == Modem_Process(&ModemCom, &ModemFlash, IAP_COM_WAIT_TIME)) { if (LL_OK != IAP_JumpToApp(*(__IO uint32_t *)APP_RUN_ADDR)) { /* Jump to app failed */ } } } } /******************************************************************************* * EOF (not truncated) ******************************************************************************/
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值