使用gcc -O2优化时为何需要添加延迟?STM32 LCD驱动代码疑问
该自赋值语句在-O2优化下的作用解释
void LCD_WR_REG(uint16_t regval) { regval = regval; // Necessary delay when using -o2 optimization LCD->LCD_REG = regval; }
- 首先
-O2是编译器的高优化等级,开启后会默认做冗余代码消除、指令精简、无效语句删除等优化,普通无意义的自赋值语句通常会被直接删掉,这行能生效的前提是当前代码使用的编译器版本/配置没有把该类自赋值判定为可消除的冗余代码。 - 这行代码的本质是补充极短的时序延迟:STM32驱动LCD大多采用FSMC或者模拟8080并行接口,这类接口对寄存器写入的建立时间有明确要求,也就是往
LCD->LCD_REG这个内存映射寄存器写值之前,需要保证总线、片选信号稳定足够的时长,否则LCD控制器会采样到错误的寄存器地址,驱动直接失效。 - 不开优化时,函数参数入栈、上下文保存的冗余指令已经能满足时序要求,但开
-O2优化后,这类短小的寄存器写入函数通常会被精简到最少指令,甚至直接inline到调用位置,导致写寄存器前的时序余量不足,写入失败。自赋值语句本身只消耗1~2个CPU时钟周期,刚好能补上这部分缺失的时序余量,开销比调用通用delay函数小很多。
该写法属于兼容性较差的非常规操作:不同编译器版本、不同编译参数下,完全有可能把
regval = regval判定为无效代码直接删除,导致高优化等级下驱动失效。更规范的实现方式是使用ARM架构内置的__NOP()空指令补延迟,或者给需要保证不被优化的变量添加volatile声明强制编译器保留对应操作。
内容的提问来源于stack exchange,提问作者momoxinduo
相关产品推荐
相关产品推荐

