现在在MCU上IAP用得越来越多,但我看了一下,有一个问题,这些IAP不能做到自我保护,也就是说,在升级过程中出错(升到一半就中断了,升级代码错误等等)就不能再进入IAP了,这样又要用ISP了,而在工程上,凡是可能出问题的地方一定会出问题。问题的关键在于IAP不是首先运行的,是在应用中收到命令后才进入的。 我的方案是在源程序中加入 extern uchar check_code(void); /* 用CRC、MD5等算法对全部代码进行校验,正确返回0,错误返回1 */ extern void sys_iap(void); /* 用UART、SPI、USB等方式接收上位机发来的新代码数据块,为保密可以用加密算法。并写入程序区,但是不允许写入BOOT区。代码中不用中断,程序为死循环,只有接收到上位机的复位命令后才能复位重起。 */ uchar iap_address[] _at 0x0400 //中断向量变换区,大小和硬件中断向量区大小一致, void main(void) { if( check_code() ) { sys_iap(); } /////////用户程序头 sys_ini(); while(1) { } /////////用户程序尾 程序里有接收到上位机命令后进入IAP状态的代码。 } 各中断程序按原有方式编写,编译。连接OBJ时,把check_code() sys_iap()定位在硬件中断向量区后面。它所在的扇区为BOOT扇区,IAP程序就是接到指令也不能写这段区域,比如此段代码有419BYTE,硬件中断向量区用32byte,就是说结尾是(419+32)=451byte.此MCU最小扇区为256BYTE,那iap_address就从0x0200开始,之间的空隙用数组填上。上位机在读入HEX等文件后,把原来直接指向中断程序的LJMP XXXX 变为先指向中断向量变换区的对应位置,再指向真正的地址,并做CRC等校验码的写入,并把它发给下位机。过程中还可以加密。 本方案的优点: 1:在运行正式程序前先检查代码完整性,确保运行的是正确的代码,只要BOOT区不被意外破坏,永远可以升级(前提是代码没写错)。 2:对资源影响小,对中断的响应时间就加了一条跳转指令的时间,开机的时间较长,如果在意这个时间,可以用一个IO做输入,判断一下状态再决定是否运行代码检验程序。这样要加个跳线帽。 3:通用性好,可以用于8位、16位、32位机,可以和OS们结合,可以加入密钥,比如3DES、AES等,这样可以通用一个开源程序而不发生代码安全问题。对C兼容性好。
这是一个大的平台性的工程,我希望得到大家的意见和帮助。 |