哪些变量类型/大小在 STM32 微控制器上是原子的?

2024-04-13

以下是 STM32 微控制器上的数据类型:http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm.

这些微控制器使用 32 位 ARM 核心处理器。

哪些数据类型具有自动原子读取和原子写入访问权限?

我很确定所有 32 位数据类型都可以(因为处理器是 32 位),而所有 64 位数据类型都不会(因为读取或写入 64 位字至少需要 2 个处理器操作) ), 但是关于bool(1 个字节),以及uint16_t/int16_t(2字节)?

上下文:我在多个线程(单核,但多个线程,或所谓的“任务”)之间共享变量FreeRTOS https://www.freertos.org/)在 STM32 上,需要知道是否需要通过关闭中断、使用互斥体等来强制执行原子访问。

UPDATE:

参考这个示例代码:

volatile bool shared_bool;
volatile uint8_t shared u8;
volatile uint16_t shared_u16;
volatile uint32_t shared_u32;
volatile uint64_t shared_u64;
volatile float shared_f; // 32-bits
volatile double shared_d; // 64-bits

// Task (thread) 1
while (true)
{
    // Write to the values in this thread.
    //
    // What I write to each variable will vary. Since other threads are reading
    // these values, I need to ensure my *writes* are atomic, or else I must
    // use a mutex to prevent another thread from reading a variable in the
    // middle of this thread's writing.
    shared_bool = true;
    shared_u8 = 129;
    shared_u16 = 10108;
    shared_u32 = 130890;
    shared_f = 1083.108;
    shared_d = 382.10830;
}

// Task (thread) 2
while (true)
{
    // Read from the values in this thread.
    //
    // What thread 1 writes into these values can change at any time, so I need
    // to ensure my *reads* are atomic, or else I'll need to use a mutex to
    // prevent the other thread from writing to a variable in the midst of
    // reading it in this thread.
    if (shared_bool == whatever)
    {
        // do something
    }
    if (shared_u8 == whatever)
    {
        // do something
    }
    if (shared_u16 == whatever)
    {
        // do something
    }
    if (shared_u32 == whatever)
    {
        // do something
    }
    if (shared_u64 == whatever)
    {
        // do something
    }
    if (shared_f == whatever)
    {
        // do something
    }
    if (shared_d == whatever)
    {
        // do something
    }
}

在上面的代码中,我可以在不使用互斥体的情况下对哪些变量执行此操作?我的怀疑如下:

  1. volatile bool:安全——不需要互斥
  2. volatile uint8_t:安全——不需要互斥
  3. volatile uint16_t:安全——不需要互斥
  4. volatile uint32_t:安全——不需要互斥
  5. volatile uint64_t:不安全——您必须使用关键部分或互斥锁!
  6. volatile float:安全——不需要互斥
  7. volatile double:不安全——您必须使用关键部分或互斥锁!

FreeRTOS 的关键部分示例:

  • https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html

    // 使用这些临界区原子访问防护强制进行原子访问。 任务ENTER_CRITICAL(); // 在这里进行读或写(现在保证是安全的) 任务EXIT_CRITICAL();

相关,但没有回答我的问题:

  1. ARM 中的原子操作 https://stackoverflow.com/questions/11894059/atomic-operations-in-arm
  2. ARM:从 int 写入/读取是原子的吗? https://stackoverflow.com/questions/9399026/arm-is-writing-reading-from-int-atomic
  3. (我自己关于 8 位 AVR [和 Arduino] 微控制器原子性的问题和答案):https://stackoverflow.com/a/39693278/4561887 https://stackoverflow.com/a/39693278/4561887
  4. https://stm32f4-discovery.net/2015/06/how-to-properly-enabledisable-interrupts-in-arm-cortex-m/ https://stm32f4-discovery.net/2015/06/how-to-properly-enabledisable-interrupts-in-arm-cortex-m/

对于这个问题的最终、明确的答案,请直接跳到下面标题为“我的问题的最终答案".

2018 年 10 月 30 日更新:我不小心引用了(稍微)错误的文档(但说的是完全相同的事情),所以我在这里的答案中修复了它们。有关详细信息,请参阅本答案底部的“关于 2018 年 10 月 30 日变更的说明”。

我绝对听不懂这里的每一个字,但是ARMv7-M架构参考手册 (在线源码 https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/ddi0403/latest/armv7-m-architecture-reference-manual; PDF文件直接下载 https://static.docs.arm.com/ddi0403/ed/DDI0403E_d_armv7m_arm.pdf)(不是技术参考手册 [TRM],因为它不讨论原子性)验证了我的假设:

所以......我认为我的问题底部的 7 个假设都是正确的。 [2018 年 10 月 30 日:是的,这是正确的。详情请见下文。]


2018 年 10 月 29 日更新:

还有一个小花絮:

FreeRTOS 创始人、专家和核心开发人员 Richard Barry 在tasks.c...

/* 不需要临界区,因为变量的类型为 BaseType_t。 */

...在 STM32 上读取“unsigned long”(4 字节)易失性变量时。这意味着他至少 100% 确定 4 字节读写在 STM32 上是原子的。他没有提到较小字节的读取,但对于 4 字节的读取,他确信无疑。我必须假设 4 字节变量是本机处理器宽度,而且,字对齐 http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm,对于这一点是否成立至关重要。

From tasks.c,FreeRTOS v9.0.0 中的第 2173-2178 行,例如:

UBaseType_t uxTaskGetNumberOfTasks( void )
{
    /* A critical section is not required because the variables are of type
    BaseType_t. */
    return uxCurrentNumberOfTasks;
}

他用了这个确切的短语...

/* 不需要临界区,因为变量的类型为 BaseType_t。 */

...在此文件中的两个不同位置。

我的问题的最终答案:所有类型 bolded下面 9 行列表中的类型)是原子的。

此外,在仔细检查第141页的TRM(如我上面的屏幕截图所示)后,我想指出的关键句子是:

在 ARMv7-M 中,单拷贝原子处理器访问是:
• all byte访问。
• all halfword访问半字对齐的位置。
• all word访问字对齐的位置。

And, 根据此链接 http://www.keil.com/support/man/docs/armcc/armcc_chr1359125009502.htm,以下对于“在 ARM C 和 C++ 中实现的基本数据类型”(即:在 STM32 上)成立:

  1. bool/_Bool是“字节对齐”(1 字节对齐)
  2. int8_t/uint8_t是“字节对齐”(1 字节对齐)
  3. int16_t/uint16_t是“半字对齐”(2 字节对齐)
  4. int32_t/uint32_t是“字对齐”(4 字节对齐)
  5. int64_t/uint64_t是“双字对齐”(8 字节对齐)
  6. float是“字对齐”(4 字节对齐)
  7. double是“双字对齐”(8 字节对齐)
  8. long double是“双字对齐”(8 字节对齐)
  9. 所有指针都是“字对齐”(4 字节对齐)

这意味着我现在拥有并理解我需要的证据最后声明上面的所有粗体行都具有自动原子读写访问权限(当然不是递增/递减,这是多个操作)。这是我的问题的最终答案。 我认为这种原子性的唯一例外可能是在打包结构中,在这种情况下,这些本来自然对齐的数据类型可能不会自然对齐。

另请注意,在阅读技术参考手册时,“单副本原子性”显然仅意味着“单核 CPU 原子性”或“单 CPU 核架构上的原子性”。这与“多副本原子性”形成对比,“多副本原子性”指的是“多处理系统”或多核 CPU 架构。维基百科指出“多处理是在单个计算机系统中使用两个或多个中央处理单元(CPU)”(https://en.wikipedia.org/wiki/Multiprocessing https://en.wikipedia.org/wiki/Multiprocessing).

我的架构有问题,STM32F767ZI https://www.st.com/en/microcontrollers/stm32f767zi.html(带有 ARM Cortex-M7 内核)是单核架构,因此显然适用“单副本原子性”,正如我上面从 TRM 中引用的那样。

进一步阅读:

  • ARM:从 int 写入/读取是原子的吗? https://stackoverflow.com/questions/9399026/arm-is-writing-reading-from-int-atomic
  • 原子/易失性/同步之间有什么区别? https://stackoverflow.com/questions/9749746/what-is-the-difference-between-atomic-volatile-synchronized
  • 打包结构内的变量可以被原子读取吗? https://stackoverflow.com/questions/14662135/can-variables-inside-packed-structures-be-read-atomically

关于 2018 年 10 月 30 日变更的说明:

  • 我有这个参考:ARMv7 技术规范 https://www.cs.utexas.edu/%7Esimon/378/resources/ARMv7-AR_TRM.pdf(技术参考手册)。然而,这在两个方面是错误的:1) 这根本不是 TRM! TRM 是一本简短的(约 200 页)技术参考手册。然而,这是“架构参考手册”,而不是 TRM。这是一个更长、更通用的文档,因为架构参考手册的数量级约为 1000~2000 页。 2) 这是针对 ARMv7-A 和 ARMv7-R 处理器的,但我需要的有关 STM32 mcu 的手册是针对 ARMv7-M 处理器的。
  • 以下是 ARM Cortex-M7 处理器技术参考手册的正确链接。在线的:https://developer.arm.com/docs/ddi0489/latest https://developer.arm.com/docs/ddi0489/latest. PDF: https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf.
  • 正确的 TRM 就在上面,第 99 页 (5-36) 上说:“了解更多 有关原子性的信息,请参阅 ARM®v7-M 架构参考手册。”因此,这是该手册。在线下载链接:https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/ddi0403/latest/armv7-m-architecture-reference-manual https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs/ddi0403/latest/armv7-m-architecture-reference-manual. PDF: https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf https://static.docs.arm.com/ddi0489/d/DDI0489D_cortex_m7_trm.pdf。它讨论了第 79-80 页(A3-79 到 A3-80)的原子性。

To create原子访问防护(通常由关闭中断当读取和写入时not原子)参见:

  1. [我的问答]在 STM32 微控制器中禁用和重新启用中断以实现原子访问防护的各种方法有哪些? https://stackoverflow.com/a/71626598/4561887
  2. My doAtomicRead()func 可以在不关闭中断的情况下进行原子读取 https://stackoverflow.com/a/71625693/4561887
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

哪些变量类型/大小在 STM32 微控制器上是原子的? 的相关文章

随机推荐

  • Bash 中使用 if-else 进行整数比较

    我有一个变量叫做choice 现在 我尝试使用 if 来比较输入的值 read choice if choice 2 then do something elif choice 1 then do something else else e
  • 如何打印我的 Java 对象而不得到“SomeType@2f92e0f4”?

    我有一个类定义如下 public class Person private String name constructor and getter setter omitted 我尝试打印我的类的一个实例 System out println
  • 访问表的第n列

    我有一个包含以下结构和数据的表 tr td td tr
  • 服务绑定到活动

    这是我的代码 public class MainActivity extends Activity private ComponentName mService private Servicio serviceBinder private
  • Checkstyle,无法创建根模块

    我正在尝试在项目中配置 Checkstyle 我已经添加 apply plugin checkstyle checkstyle assign the latest checkstyle version explicitly default
  • 如何通过 selenium-webdriver 和 Java 使用 java 实现鼠标悬停

    在尝试实现门户自动化时http demo nopcommerce com http demo nopcommerce com 我无法将鼠标悬停在 电子 菜单上并选择 相机和照片 子菜单 使用以下脚本进行相同的操作 WebElement el
  • 为什么 Matplotlib 颜色图的结构不同?

    我能够绘制 RGB 分量some使用这个简单的 Python 脚本绘制 Matplotlib 颜色图 import numpy as np import matplotlib pyplot as plt from matplotlib im
  • R Shiny:渲染summary.ivreg输出

    我正在尝试在 R Shiny 中呈现工具变量回归摘要 这是代码 iv ivreg lwage educ exper nearc4 exper summary iv 当我使用 renderTable 时 出现以下错误 没有适用于 xtable
  • angular2动态表格计算金额总计

    尝试计算总 payOffs amount payOffs 是一个 FormArray 不知道如何正确执行 以便总数会观察到当前金额和新金额的变化 这是我作为基本代码的 plnkr http plnkr co edit nHSIsciSZNT
  • 使用 C++ 基类构造函数?

    在使用模板时 我遇到需要使基类构造函数可从继承类访问以创建对象 以减少复制 粘贴操作 我想通过这样做using关键字与函数 case 的方式相同 但不起作用 class A public A int val class B public A
  • 无法获取 Cabal 更新以在公司网络内工作

    我正在尝试在工作中使用 haskell 我已经安装了 HP 但无法让 cabal 进行更新 我认为这是一些防火墙或 DNS 问题 cabal update Downloading the latest package list from h
  • 如何在 JNI 中读取字节数组?

    是否可以在 JNI 中引用整个字节数组而不调用任何副本 在本机 C 代码中 我有一个从 Java 传递的字节数组 我只想将一些数据与该字节数组进行比较 因此我不想进行任何内存复制 是否可以 我知道我可以通过使用类似的 GetPrimitiv
  • Tango 的未来与 D1 的停产

    知道D1 will be discontinued effective December 31 2012 鉴于官方发行版位于 D1 之下 是否还值得继续使用 Tango 如果您谈论的是一旦 D1 的官方支持消失 是否值得继续使用 Tango
  • VirtualEnv 和 python-embed

    我有一台使用 Python 2 运行许多应用程序的 Windows 机器 我想添加一个使用 Python 3 编写的新程序 为了确保我不会搞砸任何事情 我想使用嵌入了 Python 3 的 Virtualenv Python 3 嵌入 am
  • 将两个变量加在一起?

    然而 尝试将两个整数变量添加在一起 我似乎无法弄清楚 因为它只是将它们作为字符串连接起来 var age child 10 var age gap 10 alert age child age gap 结果 1010 想要的结果 20 va
  • 使用
    制作大引号

    几年前 我使用该标签在我的网站上创建了一个引用 带有大引号 现在我想做同样的事情 但它不再起作用了 我唯一得到的是小 而不是大的 如何找回旧的 大的 Thanks 我相信您正在寻找这样的东西 blockquote font family G
  • 如何创建一个圆形按钮?

    我想创建一个圆形按钮 这个按钮应该看起来像一个圆圈 此代码给出了圆形矩形按钮 UIButton button UIButton buttonWithType UIButtonTypeRoundedRect button frame CGRe
  • 如何在 Python Selenium 中实现类似 TestNG 的功能或在一个测试套件中添加多个单元测试?

    假设我有这两个鼻子测试ExampleTest1 py和ExampleTest2 py ExampleTest1 py class ExampleTest1 TestBase def testExampleTest1 self if name
  • Tensorflow 中的深度复制

    张量流中有深度复制吗 考虑以下操作 tt tf get variable t shape 2 2 tt1 tf identity tt 0 assign 1 1 tt2 tf identity tt 1 assign 2 2 我希望 tt1
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d