NXP

Cortex-M0的BOD中断及重启-掉电检测的可利用性+BOD汇编启动

2019-07-12 12:23发布

BOD

Brown-Out Detection,又称掉电检测,一般用来检测单片机电源掉到一定电压之后执行相应操作。 有些产品由于受外围电路的影响,在断电时会存在残余电压,使得单片机仍能运行(一般情况下是外设停止,但内核运行),这样变会出现单片机无法正常复位,更严重点如果电压不稳会导致内核pc指针跑飞,造成程序灾难。 为了避免这个现象,我们可以在单片机程序中加入BOD检测功能,使单片机在检测到掉电到一定电压后,能够执行复位操作。 BOD分为几个等级:如下 #define BOD_INT_RESV (0 << 2) /* Reserved */ #define BOD_INT_LVL1 (1 << 2) /* 2.3 ~2.4 */ #define BOD_INT_LVL2 (2 << 2) /* 2.6 ~2.7 */ #define BOD_INT_LVL3 (3 << 2) /* 2.8 ~2.9 */ /* BOD复位电压 */ #define BOD_RST_RESV (0 << 0) /* Reserved */ #define BOD_RST_LVL1 (1 << 0) /* 2.1 ~2.2 */ #define BOD_RST_LVL2 (2 << 0) /* 2.4 ~2.5 */ #define BOD_RST_LVL3 (3 << 0) /* 2.6 ~2.8 */ 我们可以根据自己的需要选择不同的等级,需要考虑的是外设的工作电压,如E2Prom,Flash等。 BOD初始化代码如下,一般放置在main函数的初始进行初始化。笔者用的是NXP的一款芯片。 void BODInit(void) { LPC_SYSCON->BODCTRL = BOD_INT_LVL3 | /* BOD中断电压2.8 ~ 2.9 */ BOD_RST_LVL2 | /* BOD复位电压2.4 ~ 2.5 */ BOD_RST_ENABLE; /* BOD复位功能使能 */ NVIC_EnableIRQ(BOD_IRQn); /* 打开BOD中断 */ } int main (void) { SystemInit(); /* 初始化目标板,切勿删除 */ GPIOInit(); /* GPIO初始化 */ BODInit(); /* BOD初始化 */ if ((LPC_SYSCON->SYSRSTSTAT & BOD_RESET) == BOD_RESET) { /* 掉电复位,LED闪烁 */ LPC_SYSCON->SYSRSTSTAT |= BOD_RESET; /* 清除掉电复位标志位 */ while (1) { LPC_GPIO_PORT->PIN[0] &= ~LED; /* 点亮LED */ myDelay(100); /* 延时 100ms */ LPC_GPIO_PORT->PIN[0] |= LED; /* 熄灭LED */ myDelay(100); /* 延时 100ms */ } } else { while (1) { LPC_GPIO_PORT->PIN[0] &= ~LED; /* 上电复位,点亮LED */ } } }

关于BOD汇编启动

既然我们可以在初始化的时候配置BOD的参数,那为什么还需要用汇编启动呢?
考虑之一是单片机内核从启动代码启动到运行到main函数的时候,需要有及ms的延时,虽然时间在ms级,但是对于一些严格要求的程序和产品,芯片在上电时由于电压抖动会导致芯片PC值跑飞,由于此时还没有初始化BOD,因此无法完成复位。 解决办法之一便是在启动代码中增加BOD初始化,使BOD在运行在main函数之前便完成初始化,可防止上电电压抖动造成的不必要的影响。 启动代码中汇编BOD的初始化代码如下。
首先声明BOD初始化程序。 ; Cortex-M version ; MODULE ?cstartup ;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start EXTERN SystemInit EXTERN BODInit //声明BOD函数 EXTERN IRC_Only_SystemInit PUBLIC __vector_table PUBLIC __vector_table_0x1c DATA __vector_table DCD sfe(CSTACK) ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler 然后在程序执行main之前加入执行BODinit的代码段。 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; Default interrupt handlers. ;; THUMB PUBWEAK Reset_Handler SECTION .text:CODE:REORDER:NOROOT(2) Reset_Handler LDR R0, =BODInit //加入BODInit 此函数体在main中 BLX R0 LDR R0, =SystemInit BLX R0 LDR R0, =__iar_program_start BX R0 这样便可完成BOD的汇编启动。