bug fix - add fence to protect atomic operation
记录第二个 bug,risc-v relaxed memory model 会导致 mcu 写寄存器延时,由此导致的问题;
原理可参考 note - risc-v memory model - usage of fence。
bug 2. interrupt threshold overwrite
2.1 背景介绍
2.1.1 flash 访问冲突导致 mcu 宕机
soc 常规设计为 core + sram + flash + peripheral (uart+spi+iic+pwm+rf+…),根据软件是否可在 flash 直接运行(是否支持 XIP)来决定上电后行为:
- 支持 XIP,直接运行 flash 通常为 0 地址处的指令,默认为 _reset;
- 不支持XIP,则由启动代码将部分或全部软件从 flash copy 至 sram 中运行;
由于 sram 较为昂贵,通常无法直接存放全部程序,所以部分设计会采用 mmu (Memory Management Unit)来管理分配 sram 资源,即分配 cache 用来存放部分程序,mmu 将当前需要执行的程序实时从 flash 中读至 sram cache 来模拟出虚拟地址运行 flash 程序。
本文讨论第一种方案,即支持 XIP 的 soc;core 从 flash 通过总线实时取址,当涉及到操作 flash 相关的行为时,需要保证执行 flash 操作的这部分代码存放在 sram 中,否则总线操作 flash,同时软件又通过 mspi 操作 flash,但 flash 操作时序唯一,造成取址错误程序宕机。
所以当操作内部 flash 时通常要求关中断,防止出现类似干扰。
一般外挂 flash 通过 spi 接口操作没有此类问题,不过为了防止中断操作延时较长打断 spi 时序,通常操作 flash 相关接口还是建议关中断。
注:通常建议关闭,但在时序要求较高的应用中,保证中断运行时间足够短,可允许中断存在,可设置高优先级,同时屏蔽低优先级中断。
2.2.2 抢占式中断介绍
通常设计到抢占式中断,同时会有一个中断优先级设定,通知中断控制模块会伴有一个中断阈值寄存器用来允许高优先级中断打断,同时屏蔽低优先级中断。
举例有两个 irq1 - priority 1, irq2 - priority 2, 优先级 1 < 2,两种例子:
- 先触发 irq1,此时中断控制模块设置中断阈值为当前触发中断的优先级 1,此时如果出现了优先级 0或1的中断,则小于当前中断阈值,需排队等待,如果出现了 irq2,优先级 2 > 1,则 irq2 抢占 irq1;
- 先触发 irq2,此时中断控制模块设置中断阈值为当前触发中断的优先级 2,此时如果出现了优先级 0或1的中断,则小于当前中断阈值,需排队等待。
以上为设计初衷。
2.2 现象
压测环节,软件宕机,log 显示通常卡在 flash write 未退出。
2.3 原因
由于为 ble 应用,ble 通常为一个 interval (通常为10 - 20ms)对包一次,对包窗口为百 us 级别,所以时序要求较高,所以应用中通常 flash 操作允许 ble 中断。出现如下情形:
- flash 操作前会设置阈值寄存器为 1,ble 中断为 2 可打断,但由于 risc-v relaxed memory model 的写寄存器延时效应,导致 flash 操作设置阈值寄存器为 1 时并未真正写入;
- 此时触发中断,并由中断控制模块设置了阈值寄存器为触发中断的优先级 2;
- 此时 1 导致的延时生效,当前中断优先级重新改为 1;
- 其他优先级为 2 的中断可以打断 step 2 中已经触发了中断的优先级同为 2 中断服务程序。
注:由于软件设计原因,导致同为优先级 2 的中断不停重复打断,导致软件宕机。
2.4 解决办法
设置阈值寄存器时先关中断,设置完成后加 fence 保证写入成功,随后重新开中断。
即保证设置中断阈值寄存器期间不能进中断,同时保证阈值寄存器写入成功。