本帖最后由 buzhichi 于 2016-4-13 21:40 编辑
1.整个flash可以分为UBC和非UBC,就是用户区和应用程序区。看到这里,就会觉得有难度了,分成两个区还要,用一个区升级另一个区,那么我要先搞清楚怎么分成两个区,两个区主要是UBC区到底有什么特性,有什么要注意的地方,这时,我开始查阅资料。并且觉得很难。
2.经过一通查资料后发现,其实所谓UBC,完全可以忽视掉,flash就是一整片,我们随意规定,比如前面4K当做自己的boot,然后后面的当做应用程序,只要在前面4K去写后面应用程序区域的flash就可以了。写flash都是库函数,忘掉UBC,并且把UBC设置为0,不会设置就用默认就是0.
3.为什么flash要划分出UBC呢,其实UBC就是保护级别高,所谓高就是不会被擦写,你设置成UBC的区域,在应用程序中是无法擦写UBC区域的数据,这样保证即使你的程序跑飞或者bug去误操作boot程序所在的flash也很安全。设置为UBC,用swim也无法擦写,要想擦写要先改选项字 。如果不用boot并且应用程序中没有对flash的擦写操作,可以把整个flash定义为UBC区域,所谓定义成UBC区域,也就是说提高一下安全级别。
4.到这里,可以换一个概念,flash分为UBC区域和应用程序区,其实可以说成把一片flash分成两个安全级别,一个安全级别高,就理解为不能被擦写,放boot程序,一个安全级别较低,falsh可以给擦写,放应用程序。如果你不在意安全级别保证应用程序不会去擦写boot区域的数据就完全可以不用管安全级别,所以UBC不是必要的。
5.所以建议刚开始搞IAP,先不要分析UBC了,就是一整片flash。用前面的更新后面的。
以上是我对于UBC的理解,跟大家分享一下,刚开始搞的时候对这些有些迷惑,最后发现花了很多时间都是不必要的,希望可以帮到和我一样的初学者。
我用的型号是STM8S105C6 32K的程序量,我把boot放在了前面4K的程序。在boot程序中做了中断向量映射如下
__root const long reintvec[]@".intvec"=
{ 0x82008080,0x82009004,0x82009008,0x8200900c,
0x82009010,0x82009014,0x82009018,0x8200901c,
0x82009020,0x82009024,0x82009028,0x8200902c,
0x82009030,0x82009034,0x82009038,0x8200903c,
0x82009040,0x82009044,0x82009048,0x8200904c,
0x82009050,0x82009054,0x82009058,0x8200905c,
0x82009060,0x82009064,0x82009068,0x8200906c,
0x82009070,0x82009074,0x82009078,0x8200907c,
};
大家注意下,从第二个开始0x82009004,改成了9,因为应用程序是从9000开始的,前面的8000到8fff留给了boot
boot跳转指令如下
inline void JumpToApp(void)
{
if(*(u16*)(0x9000) == 0x8200)
{
asm("LDW X, SP ");
asm("LD A, $FF");
asm("LD XL, A ");
asm("LDW SP, X ");
asm("JPF $9000");
}
}
在应用程序中,修改icf文件如下:
define region NearFuncCode = [from 0x9000 to 0xFFFF];
define region FarFuncCode = [from 0x9000 to 0xFFFF];
define region HugeFuncCode = [from 0x9000 to 0xFFFF];
对上面的修改做点说明,在boot中做了中断向量映射,其实这时的中断向量是给应用程序用的,对于boot是错的,但是我在boot中没有用到任何中断,所以就没问题。如果想在boot和应用程序中都用中断,可能会复杂。
|