1、访问寄存器的操作(以32位机器分析)
- 在嵌入式开发时,经常需要访问寄存器,有时候只需要得到寄存器的部分bit位,会将寄存器的值读出来再进行移位操作,从而解析出特定的bit位
- 上面的C代码,想要读取出某个寄存器的高16bit,从C代码层面看是没有问题的,但是实际运行时可能会出错,这取决于使用的编译器优化等级。编译器不优化执行不会出错,编译器优化就可能出错
2、编译器优化:使用-Os优化等级
- 使用-Os优化等级编译代码,程序运行时会导致core挂死,原因如下:
- 使用-Os优化等级编译代码,编译器判断本次读寄存器只需要使用16bit,刚好是short变量(2字节),可以优化
- 原来:从0x80026000地址处读取4B,再右移16bit得到高16bit
- 优化后:直接从0x80026002地址处读取2B(直接读取寄存器的高2B)
- lh a1 2(a5):
- 此时a5的值是0x80026000
- 本条汇编的作用:从0x80026000开始偏移2字节地址处(0x80026002),读取2B存放到a1
- 出错原因:
- 寄存器必须4B整体读写(0x80026000开始读取4B),不支持只访问寄存器的2B(0x80026002开始读取2B),导致读操作返回异常(加载访问异常)或者没有返回
- 如果0x80026000地址是sram,这样的优化是没有问题的,能节省指令条数,提高性能
3、解决办法
- 使用内嵌汇编,将读寄存器的操作强制指定用lw指令,不让编译器优化成lh
- 将读寄存器的内嵌汇编封装成内联函数RegRead
- 内嵌汇编可以参考博客:《RISC-V架构学习——C语言内嵌汇编总结》