我使用的是一个嵌入式系统(基于RISC-V),其中处理器连接到数据总线,数据总线又连接到UART模块.当读/写数据总线时,它需要两个处理器周期才能准备好进行新的读/写操作,否则会产生错误.
数据总线的内存映射如下:
struct WishboneBus {
volatile uint32_t read_addr;
volatile uint32_t write_addr;
volatile uint32_t write_data;
volatile uint32_t read_data;
};
#define WISHBONE_BUS ((struct WishboneBus *) (0x4000000))
我想要编写这样的代码:
void wb_write(uint32_t addr, uint32_t data) {
WISHBONE_BUS->write_data = data;
WISHBONE_BUS->write_addr = addr;
}
当使用-O0编译该程序时,它会生成以下六条指令:
WISHBONE_BUS->write_data = data;
153c: 400007b7 lui a5,0x40000
1540: fd842703 lw a4,-40(s0)
1544: 00e7a423 sw a4,8(a5) # 40000008 <BUS_START+0x8>
WISHBONE_BUS->write_addr = addr;
1548: 400007b7 lui a5,0x40000
154c: fdc42703 lw a4,-36(s0)
1550: 00e7a223 sw a4,4(a5) # 40000004 <BUS_START+0x4>
但在使用-os时,它会生成以下指令:
WISHBONE_BUS->write_data = data;
df8: 40000737 lui a4,0x40000
dfc: 00b72423 sw a1,8(a4) # 40000008 <BUS_START+0x8>
WISHBONE_BUS->write_addr = addr;
e00: 00a72223 sw a0,4(a4)
(函数调用的不相关部分将被删除.)
在-O0的情况下,每个sw
之间有两个指令(周期),因此它可以工作.但是在-O的情况下,有两个sw
相继,并且由于在读/写操作之间,总线需要两个周期,所以总线产生错误.
这引发了这个问题: 可以将C变量限制为特定的读/写速度吗?
我知道可以添加nop
条指令来使其工作,但所需的nop
条指令的数量将取决于优化.我意识到我可以使用宏来解决这个问题,但我想要一个优雅的解决方案.例如,一种__attribute__((min_access_cycles(2)))
或类似的东西.