笔记:
(1)怎么制止KEIL初始化RAM为零?
1. 在KEIL Noinit 打钩
2.<1> 另须对需求热发动坚持的变量用__at关键字指定某个区域,不然仍是没用 (#include “absacc.h”)
<2>或许__attribute__((zero_init)) 关键字 .bss段
int test1=1;
__attribute__((zero_init)) int test2;
int test3 __at(0x20001000);
检查MAP文件
test1 0x20000000 Data 4 main.o(.data)
test2 0x2000000c Data 4 main.o(.bss)
test3 0x20001000 Data 4 main.o(.ARM.__AT_0x20001000)
(2) 对STM32怎么判别是软复位仍是上电复位?
if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
{
//这是上电复位
}
else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
{
//这是外部RST管脚复位
}
else if (RCC_GetFlagStatus(RCC_FLAG_SFTRST) != RESET)
{
//这是外部RST管脚复位
}
//铲除RCC中复位标志
RCC_ClearFlag();
void RestStm32Cpu(void)
{
__set_FAULTMASK(1); // 封闭一切中端
NVIC_SystemReset(); // 复位
}
微处理器:LPC2114
编译环境:Keil MDK V4.10
思路:
常把单片机体系的复位分为冷发动和热发动。所谓冷发动,也便是一般所说的上电复位,冷发动后片表里RAM的内容是随机的,通常是0x00或0xFF;单片机的热发动是经过外部电路给运转中的单片机的复位端一复位电平而完成的,也便是所说的按键复位或看门狗复位。复位后,RAM的内容都没有改动。在某些场合,有必要区分出设备的重启是热重启仍是冷重启。常用的办法是:确认某内存单位为标志位(如0x40003FF4~0x40003FF7 RAM单元),发动时首先读该内存单元的内容,假如它等于一个特定的值(例如为0xAA55AA55),就认为是热发动,不然便是冷发动。
依据以上的规划思路思路界说一个变量:
uint32unStartFlag;
在程序发动时判别:
if(unStartFlag==0xAA55AA55)
{
//热发动处理
}
else
{
//冷发动处理
unStartFlag=0xAA55AA55;
}
但是实践调试中发现,无论是热发动仍是冷发动,开机后一切内存单元的值都被复位为0,当然也完成不了热发动的要求。经过看keil MDK自带的发动代码Startup.s,在这个发动代码中也并没有发现将整个RAM区域清零的句子。反汇编程序,发现从发动代码履行完毕到跳转到main函数过程中,编译器还履行了许多库函数,其间__scatterload_zeroinit函数将一切W/R RAM都初始化为0(默认设置下)。为了判别冷、热发动,有必要人为操控某些特定RAM在复位时不被编译器初始化为0。经过查找编译器手册,在为处理器的RAM中分出一块小片RAM,设置为NoInit格局(不对其初始化为0),如下图:
然后运用__at关键字将冷、热发动标志位定位到这个NoInit区域:
uint32 unStartFlag __at (0x40003FF4);
这样,当热发动时,变量unStartFlag地点的内存区域就不会被初始化为0,也完成了冷热发动的判别。
界说铁电0xFF7~0xFF8区域存储冷发动次数
0xFF9~0xFFA区域存储热发动次数
0xFFB~0xFFC区域存储总发动次数
另一种办法: