注意:对于这个问题,我不是在谈论 C 或 C++语言标准。相反,我谈论的是针对特定体系结构的 gcc 编译器实现,因为语言标准对原子性的唯一保证是使用_AtomicC11 或更高版本中的类型或std::atomic<>C++11 或更高版本中的类型。另请参阅我在这个问题底部的更新。
在任何体系结构上,某些数据类型可以原子方式读取和写入,而其他数据类型则需要多个时钟周期,并且可能在操作中间被中断,如果跨线程共享该数据,则会导致损坏。
在8 位单核 AVR 微控制器(例如:Arduino Uno、Nano 或 Mini 使用的 ATmega328 mcu)上,只有8 位数据类型具有原子读取和写入(使用 gcc 编译器和gnu C 或gnu C++语言)。我在不到 2 天的时间里进行了 25 小时的马拉松式调试,然后在这里写下了这个答案。另请参阅此问题的底部以获取更多信息。以及有关使用 AVR-libc 库的 gcc 编译器编译时 AVR 8 位微控制器具有自然原子写入和自然原子读取的 8 位变量的文档。
在(32 位)STM32 单核微控制器上,任何32 位或更小的数据类型绝对自动是原子的(当使用 gcc 编译器和 gnu C 或 gnu C++ 语言编译时,因为ISO C 和 C++ 不保证这一点直到 2011 年版本,_Atomic类型为 C11 …
以下是STM32微控制器上的数据类型: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个字节)呢?
上下文:我正在STM32上的多个线程(在FreeRTOS中称为单核,但有多个线程或称为“任务”)之间共享变量,并且需要知道是否需要通过使用中断关闭中断来强制进行原子访问互斥锁等
更新:
参考此示例代码:
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 (1)
{
// 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 …Run Code Online (Sandbox Code Playgroud) 我没有找到太多关于非原子操作的材料。
\n假设我有一个 32 位处理器,并且我想在 64 位变量中保留微秒计数。中断将每微秒更新一次变量。调度程序是非抢占式的。将有一个函数用于清除变量,另一个函数用于读取变量。由于它是 32 位处理器,因此访问将是非原子的。是否有 \xe2\x80\x9cstandard\xe2\x80\x9d 或惯用的处理方法,以便读取器函数不会获得半更新的值?
\n我想我在这里遗漏了一些明显的东西.我有这样的代码:
int *a = <some_address>;
int *b = <another_address>;
[...]
int *tmp = a;
a = b; b = tmp;
Run Code Online (Sandbox Code Playgroud)
我想原子地这样做.我一直__c11_atomic_exchange在OSX上查看OSAtomic方法,但似乎没有任何东西可以原子地执行直接交换.他们都可以原子地将值写入2个变量中的1个,但不能同时写入两个变量.
有任何想法吗?
我只是失去了几天,从字面上看,大约25个小时的工作,因为我试图调试我的代码而不是我不知道的简单.
事实证明,在C++中减少单字节数组的元素,在AVR上,ATmega328 8位微控制器(Arduino)不是原子操作,需要原子访问保护(即关闭中断).为什么是这样???此外,在Atmel AVR微控制器上确保原子访问变量的所有C技术是什么?
这是我所做的一个愚蠢的版本:
//global vars:
const uint8_t NUM_INPUT_PORTS = 3;
volatile uint8_t numElementsInBuf[NUM_INPUT_PORTS];
ISR(PCINT0_vect) //external pin change interrupt service routine on input port 0
{
//do stuff here
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
numElementsInBuf[i]++;
}
loop()
{
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
{
//do stuff here
numElementsInBuf[i]--; //<--THIS CAUSES ERRORS!!!!! THE COUNTER GETS CORRUPTED.
}
}
Run Code Online (Sandbox Code Playgroud)
这是循环的版本,没关系:
loop()
{
for (uint8_t i=0; i<NUM_INPUT_PORTS; i++)
{
//do stuff here
noInterrupts(); //globally disable interrupts
numElementsInBuf[i]--; //now it's ok...30 hrs of …Run Code Online (Sandbox Code Playgroud) 我像这样编写STM8 GPIO,PD_ODR_ODR4 = 1;但stm32f10x.h没有此功能,是否有任何.h文件定义了位。
抱歉,我不知道如何更好地解释这个问题。
我尝试了多个GPIO库。
强文本