以下是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字节)呢?
上下文:我在多个线程(单核,但多个线程,在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 (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
}
}
在上述代码中,哪些变量可以不使用互斥锁进行操作? 我的怀疑如下:
volatile bool
:安全 - 无需互斥锁volatile uint8_t
:安全 - 无需互斥锁volatile uint16_t
:安全 - 无需互斥锁volatile uint32_t
:安全 - 无需互斥锁volatile uint64_t
:不安全 - 必须使用临界区或互斥锁!volatile float
:安全 - 无需互斥锁volatile double
:不安全 - 必须使用临界区或互斥锁!
使用FreeRTOS的示例临界区:
https://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html
// 使用这些临界区原子访问守卫来强制进行原子访问。 taskENTER_CRITICAL(); // 在此处执行(现在保证是安全的)读取或写入 taskEXIT_CRITICAL();