关中断,还是开中断?这是个问题。
前一段十一期间,当大家都在休假嗨皮时,在TopSemic交流群里,有几个同学似乎还在学习,而且展开了一场激烈的讨论。
大家知道,在单片机运行的时候,经常有一些数据需要保存,而且即使掉电后,这些数据也不能丢失。用一片EEPROM,如24C02可以解决,但是这会增加成本。所以,一个比较常用的办法,是把数据存入单片机的Flash,这种方法叫IAP(In Application Programming)。
此方法虽然省钱,但用的不对也会带来各种困扰,看看大家的讨论就知道了:
我们先看一下Flash的原理,然后探讨一下写程序时,有什么需要注意的。现在单片机中集成的一般是Nor Flash,这种技术是Intel在1988年推出的,它利用浮栅场效应管(Floating Gate MOSFET)存储程序或数据。简单来说,浮栅就像一个囚禁电子的笼子,通过在栅极加正向电压,可以把电子捕获到笼子里,通过加负电压,可以把电子从笼子里全部赶走。而数据的读取,是通过检测栅极中有没有存储电子,这一过程不会导致浮栅中电子的状态改变。
(From Technical Note by Macronix International)
这样,我们很容易理解,在擦写Flash的时候,不应该去读Flash。回到开始的问题,在程序擦写Flash期间,是不是应该把中断关掉呢?因为我们知道中断向量表,默认是存放在Flash中的。真不一定,还是需要具体情况具体分析。一些早期的单片机,擦写Flash的代码,需要拷贝到RAM里执行,并且必须关闭所有中断,否则会出错。但是现在推出的单片机,一般都引入了Stall机制,在擦写Flash的时候,读Flash的操作会被阻止,擦写完之后,才能继续执行。
比如STM32F030手册中,有以下描述:
我们可以用程序观察一下。程序里有一个1ms中断,每进入一次中断翻转一次引脚,在主程序的循环中,每1S执行一次Flash页擦除操作。可以看到擦除Flash一个页用了21.9ms。在擦除期间,1ms中断停止响应,擦完后1ms中断继续执行。
如果程序对中断响应要求特别高,比如精确计时,或者中断需要马上响应,可以把中断向量表和中断响应代码都放到RAM中执行,有兴趣的同学可以自己试一下。
再有一种情况就是,如果单片机中有两个以上的Flash Bank,中断向量表在一个Bank中,那么擦写其它Bank时,中断响应是不受影响的。
参考资料:
Program/Erase Cycling Endurance and Data Retention in NOR Flash Memories. Macronix
STM32F030RM. ST