gpt4 book ai didi

裸机可移植库中的 C99 "atomic"加载

转载 作者:行者123 更新时间:2023-12-03 23:46:31 25 4
gpt4 key购买 nike

我正在为裸机嵌入式应用程序开发一个便携式库。

假设我有一个定时器 ISR,它增加一个计数器,并且在主循环中,这个计数器读取来自一个绝对不是原子负载。

我正在尝试确保负载一致性(即我没有读取垃圾,因为负载被中断并且值被更改)而不求助于禁用中断。只要读取的值正确,读取计数器后值是否发生变化都没有关系。这行得通吗?

uint32_t read(volatile uint32_t *var){
uint32_t value;
do { value = *var; } while(value != *var);
return value;
}

最佳答案

您是否在任何 uint32_t 大于单个汇编指令字读/写大小的系统上运行?如果不是,则到内存的 IO 应该是单个指令,因此是原子的(假设总线也是字大小的......)当编译器将其分解为多个较小的读/写时,您会遇到麻烦。否则,我总是不得不求助于 DI/EI。如果原子指令或最小 32 位字长可用于防止中断处理,您可以让用户配置您的库,以便它具有信息。如果你有这些保证,你就不需要验证码。

不过,要回答这个问题,在必须拆分读/写的系统上,您的代码是不安全的。想象一下这样一种情况,您在“do”部分正确读取了您的值,但在“while”部分检查期间该值被拆分。此外,在极端情况下,这是一个无限循环。为了完全安全,您需要重试计数和错误条件来防止这种情况发生。循环情况肯定是极端的,但我想要它以防万一。这当然会使运行时间更长。

让我们举例说明一个失败案例 - 将在一次读取 8 位值的机器上使用 16 位数字,以便更容易理解:

  • 从内存中读取的值 *var 是 0x1234
  • 读取 8 位 0x12
  • *var 变为 0x5678
  • 读取 8 位 0x78 - 值现在是 0x1278(无效)
  • *var 变为 0x1234
  • 验证步骤读取 8 位 0x12
  • *var 变为 0x5678
  • 验证读取 8 位 0x78

  • 值确认正确 0x1278,但这是一个错误,因为 *var 只有 0x1234 和 0x5678。

    另一种失败情况是 *var 恰好以与您的代码运行相同的频率发生变化,这可能会导致每次验证失败时的无限循环。或者即使它最终确实爆发了,这也将是一个非常难以跟踪的性能错误。

    关于裸机可移植库中的 C99 "atomic"加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62412441/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com