1. 程式人生 > >EFM32片內外設--RMU基本操作

EFM32片內外設--RMU基本操作

造成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);
  }
}