一.环境
编译:STVD V4.3.5 + COSMIC V4.3.4
二.问题
STM8有多种复位源,在实际应用中可能需要在程序启动后判断是不是上电复位,例如某个灯光控制器复位时如果是上电复位则必须处于
打开状态,而看门狗复位等其它复位时需要恢复复位前的开关状态,此时需要在单片机启动后判断是否是上电复位。
三.实现原理
在RAM中声明一个变量,复位后检测是否与0xAA相等,如果不相等判定是上电复位并给变量赋值0xAA,如果相等说明RAM并未丢失值, 也就是说不是上电复位。
四.存在的问题与解决方案
由于启动代码中对所有的变量要么赋初始值,要么清零,COSMIC貌似也无法声明在AVR-GCC中.noinit类似的section,所以如何定义一个变量并在启动代码中不对其初始化成为了问题的关键。针对问题,解决办法汇总如下:
1.不使用stvd的启动代码,自己写。但自己写启动代码不是笔者的风格,所以这个方案被pass!
2.将栈顶向前移动一个字节,在ram的尾部空出一个字节,用作判断变量。修改初始化栈顶需要修改lkf脚本文件,如下
# Defines - section reserved for STVD
#<BEGIN DEFINED_VARIABLES>
+def __endzp=@.ubsct # end of uninitialized zpage
+def __memory=@.bss # end of bss segment
+def __startmem=@.bss # end of bss segment
+def __endmem=0x1ff
+def __stack=0x3ff
#<END DEFINED_VARIABLES>
将__stack=0x3ff改成__stack=0x3fe可实现
但这个又存在这样一个问题:LKf文件是stvd自动生成的,生成选项如下图。如果改这个文件必须将自动生成选项去掉,但由于这个
lkf文件在最终生成的可执行的s19文件在同一个目录下,很容易导致误删除,如果删除所有的设置要重新来一次,这是一个比较麻烦的事,
所以这个方案被笔者又否决了。
3.在栈空间中找一个用不到的字节用作判断变量,因为留给栈的ram在启动代码中是不会被初始化或清零的。
笔者最终找到了一个非常合适的地址,那就是配置中Ram段后一个字节,这样做的好处是无需更改其它任何配置,具体实现代码如下:
uint8_t g_RstSource @0x2ff; //上电复位判断变量
int main(void)
{
if(g_RstSouce!=0xaa)//上电复位
{
g_RstSouce=0xaa;
//... 上电复位时执行的动作
}
else
{
//其它复位源复位时执行的动作
……
}
}
|
|