RTX5里面提供的各种原子操作API,可以独立复制出来使用,含MDK,IAR和GCC
复制出来开个帖子,方便以后查阅:
//==== Exclusive Access Operation ====
#if (EXCLUSIVE_ACCESS == 1)
//lint ++flb "Library Begin"
/// Atomic Access Operation: Write (8-bit)
/// \parammem Memory address
/// \paramval Value to write
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
mov r2,r0
1
ldrexb r0,
strexb r3,r1,
cbz r3,%F2
b %B1
2
bx lr
}
#else
__STATIC_INLINE uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint8_tret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrexb %,[%]\n\t"
"strexb %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (ret),
"=&l" (res)
: "l" (mem),
"l" (val)
: "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Set bits (32-bit)
/// \parammem Memory address
/// \parambits Bit mask
/// \return New value
#if defined(__CC_ARM)
static __asm uint32_t atomic_set32 (uint32_t *mem, uint32_t bits) {
mov r2,r0
1
ldrex r0,
orr r0,r0,r1
strex r3,r0,
cbz r3,%F2
b %B1
2
bx lr
}
#else
__STATIC_INLINE uint32_t atomic_set32 (uint32_t *mem, uint32_t bits) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
"mov %,%\n\t"
"orrs%,%\n\t"
#else
"orr %,%,%\n\t"
#endif
"strex %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (bits)
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
: "memory", "cc"
#else
: "memory"
#endif
);
return ret;
}
#endif
/// Atomic Access Operation: Clear bits (32-bit)
/// \parammem Memory address
/// \parambits Bit mask
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint32_t atomic_clr32 (uint32_t *mem, uint32_t bits) {
push{r4,lr}
mov r2,r0
1
ldrex r0,
bic r4,r0,r1
strex r3,r4,
cbz r3,%F2
b %B1
2
pop {r4,pc}
}
#else
__STATIC_INLINE uint32_t atomic_clr32 (uint32_t *mem, uint32_t bits) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
"mov %,%\n\t"
"bics%,%\n\t"
#else
"bic %,%,%\n\t"
#endif
"strex %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (bits)
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
: "memory", "cc"
#else
: "memory"
#endif
);
return ret;
}
#endif
/// Atomic Access Operation: Check if all specified bits (32-bit) are active and clear them
/// \parammem Memory address
/// \parambits Bit mask
/// \return Active bits before clearing or 0 if not active
#if defined(__CC_ARM)
static __asm uint32_t atomic_chk32_all (uint32_t *mem, uint32_t bits) {
push{r4,lr}
mov r2,r0
1
ldrex r0,
and r4,r0,r1
cmp r4,r1
beq %F2
clrex
movsr0,#0
pop {r4,pc}
2
bic r4,r0,r1
strex r3,r4,
cbz r3,%F3
b %B1
3
pop {r4,pc}
}
#else
__STATIC_INLINE uint32_t atomic_chk32_all (uint32_t *mem, uint32_t bits) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
"mov %,%\n\t"
"ands%,%\n\t"
#else
"and %,%,%\n\t"
#endif
"cmp %,%\n\t"
"beq 2f\n\t"
"clrex\n\t"
"movs%,#0\n\t"
"b 3f\n"
"2:\n\t"
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
"mov %,%\n\t"
"bics%,%\n\t"
#else
"bic %,%,%\n\t"
#endif
"strex %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (bits)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Check if any specified bits (32-bit) are active and clear them
/// \parammem Memory address
/// \parambits Bit mask
/// \return Active bits before clearing or 0 if not active
#if defined(__CC_ARM)
static __asm uint32_t atomic_chk32_any (uint32_t *mem, uint32_t bits) {
push{r4,lr}
mov r2,r0
1
ldrex r0,
tst r0,r1
bne %F2
clrex
movsr0,#0
pop {r4,pc}
2
bic r4,r0,r1
strex r3,r4,
cbz r3,%F3
b %B1
3
pop {r4,pc}
}
#else
__STATIC_INLINE uint32_t atomic_chk32_any (uint32_t *mem, uint32_t bits) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
"tst %,%\n\t"
"bne 2f\n\t"
"clrex\n\t"
"movs%,#0\n\t"
"b 3f\n"
"2:\n\t"
#if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
"mov %,%\n\t"
"bics%,%\n\t"
#else
"bic %,%,%\n\t"
#endif
"strex %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (bits)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Increment (32-bit)
/// \parammem Memory address
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint32_t atomic_inc32 (uint32_t *mem) {
mov r2,r0
1
ldrex r0,
addsr1,r0,#1
strex r3,r1,
cbz r3,%F2
b %B1
2
bx lr
}
#else
__STATIC_INLINE uint32_t atomic_inc32 (uint32_t *mem) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
"adds%,%,#1\n\t"
"strex %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Increment (16-bit) if Less Than
/// \parammem Memory address
/// \parammax Maximum value
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint16_t atomic_inc16_lt (uint16_t *mem, uint16_t max) {
push {r4,lr}
mov r2,r0
1
ldrexh r0,
cmp r1,r0
bhi %F2
clrex
pop {r4,pc}
2
adds r4,r0,#1
strexh r3,r4,
cbz r3,%F3
b %B1
3
pop {r4,pc}
}
#else
__STATIC_INLINE uint16_t atomic_inc16_lt (uint16_t *mem, uint16_t max) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint16_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrexh %,[%]\n\t"
"cmp %,%\n\t"
"bhi 2f\n\t"
"clrex\n\t"
"b 3f\n"
"2:\n\t"
"adds %,%,#1\n\t"
"strexh %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (max)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Increment (16-bit) and clear on Limit
/// \parammem Memory address
/// \parammax Maximum value
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint16_t atomic_inc16_lim (uint16_t *mem, uint16_t lim) {
push {r4,lr}
mov r2,r0
1
ldrexh r0,
adds r4,r0,#1
cmp r1,r4
bhi %F2
movs r4,#0
2
strexh r3,r4,
cbz r3,%F3
b %B1
3
pop {r4,pc}
}
#else
__STATIC_INLINE uint16_t atomic_inc16_lim (uint16_t *mem, uint16_t lim) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint16_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrexh %,[%]\n\t"
"adds %,%,#1\n\t"
"cmp %,%\n\t"
"bhi 2f\n\t"
"movs %,#0\n"
"2:\n\t"
"strexh %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem),
"l" (lim)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Decrement (32-bit)
/// \parammem Memory address
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint32_t atomic_dec32 (uint32_t *mem) {
mov r2,r0
1
ldrex r0,
subsr1,r0,#1
strex r3,r1,
cbz r3,%F2
b %B1
2
bx lr
}
#else
__STATIC_INLINE uint32_t atomic_dec32 (uint32_t *mem) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
"subs%,%,#1\n\t"
"strex %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Decrement (32-bit) if Not Zero
/// \parammem Memory address
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint32_t atomic_dec32_nz (uint32_t *mem) {
mov r2,r0
1
ldrex r0,
cbnzr0,%F2
clrex
bx lr
2
subsr1,r0,#1
strex r3,r1,
cbz r3,%F3
b %B1
3
bx lr
}
#else
__STATIC_INLINE uint32_t atomic_dec32_nz (uint32_t *mem) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint32_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
"cbnz%,2f\n\t"
"clrex\n\t"
"b 3f\n"
"2:\n\t"
"subs%,%,#1\n\t"
"strex %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Decrement (16-bit) if Not Zero
/// \parammem Memory address
/// \return Previous value
#if defined(__CC_ARM)
static __asm uint16_t atomic_dec16_nz (uint16_t *mem) {
mov r2,r0
1
ldrexh r0,
cbnz r0,%F2
clrex
bx lr
2
subs r1,r0,#1
strexh r3,r1,
cbz r3,%F3
b %B1
3
bx lr
}
#else
__STATIC_INLINE uint16_t atomic_dec16_nz (uint16_t *mem) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register uint16_t ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrexh %,[%]\n\t"
"cbnz %,2f\n\t"
"clrex\n\t"
"b 3f\n"
"2:\n\t"
"subs %,%,#1\n\t"
"strexh %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (mem)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Link Get
/// \paramroot Root address
/// \return Link
#if defined(__CC_ARM)
static __asm void *atomic_link_get (void **root) {
mov r2,r0
1
ldrex r0,
cbnzr0,%F2
clrex
bx lr
2
ldr r1,
strex r3,r1,
cbz r3,%F3
b %B1
3
bx lr
}
#else
__STATIC_INLINE void *atomic_link_get (void **root) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
register void *ret;
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldrex %,[%]\n\t"
"cbnz%,2f\n\t"
"clrex\n\t"
"b 3f\n"
"2:\n\t"
"ldr %,[%]\n\t"
"strex %,%,[%]\n\t"
"cbz %,3f\n\t"
"b 1b\n"
"3:"
: "=&l" (ret),
"=&l" (val),
"=&l" (res)
: "l" (root)
: "cc", "memory"
);
return ret;
}
#endif
/// Atomic Access Operation: Link Put
/// \paramroot Root address
/// \paramlnk Link
#if defined(__CC_ARM)
static __asm void atomic_link_put (void **root, void *link) {
1
ldr r2,
str r2,
dmb
ldrex r2,
ldr r3,
cmp r3,r2
bne %B1
strex r3,r1,
cbz r3,%F2
b %B1
2
bx lr
}
#else
__STATIC_INLINE void atomic_link_put (void **root, void *link) {
#ifdef__ICCARM__
#pragma diag_suppress=Pe550
#endif
register uint32_t val1, val2, res;
#ifdef__ICCARM__
#pragma diag_default=Pe550
#endif
__ASM volatile (
#ifndef __ICCARM__
".syntax unified\n\t"
#endif
"1:\n\t"
"ldr %,[%]\n\t"
"str %,[%]\n\t"
"dmb\n\t"
"ldrex %,[%]\n\t"
"ldr %,[%]\n\t"
"cmp %,%\n\t"
"bne 1b\n\t"
"strex %,%,[%]\n\t"
"cbz %,2f\n\t"
"b 1b\n"
"2:"
: "=&l" (val1),
"=&l" (val2),
"=&l" (res)
: "l" (root),
"l" (link)
: "cc", "memory"
);
}
#endif
//lint --flb "Library End"
#endif// (EXCLUSIVE_ACCESS == 1)
{:8:}{:8:} 看不懂 一脸懵 登云钓月 发表于 2021-11-29 00:11
看不懂 一脸懵
就是这个API函数,直接调用就行。 请问32位的变量赋值操作,怎么用这些函数呢?谢谢 gallop020142 发表于 2022-1-6 10:31
请问32位的变量赋值操作,怎么用这些函数呢?谢谢
直接调用提供的32bit 操作即可,不是有注释。 eric2013 发表于 2022-1-6 11:26
直接调用提供的32bit 操作即可,不是有注释。
在rtx_thread.c里面,是这样用atomic_set32的:
thread_flags = atomic_set32(&thread->thread_flags, flags);
对着注释看半天,还是不太明白怎么使用。
比如我想把 int32_t(或者uint32_t)的变量a赋值为b,请问是不是这样写:
#include "rtx_core_cm.h"
atomic_set32( &a, b);
谢谢 gallop020142 发表于 2022-1-24 20:28
在rtx_thread.c里面,是这样用atomic_set32的:
thread_flags = atomic_set32(&thread->thread_flags, f ...
就是这样的,你操作是否正常。 eric2013 发表于 2022-1-25 00:12
就是这样的,你操作是否正常。
感谢回复
有两个小问题:
1. rtx_core_cm.h 这个文件工程里面找不到。我从c盘AppData\Local\Arm\Packs\ARM\CMSIS\5.7.0\CMSIS\RTOS2\RTX\Source 复制出来到工程目录的,不知道正确的操作添加方式是什么。
2. 出来警告 warning: passing 'int32_t *' (aka 'int *') to parameter of type 'uint32_t *''
如果强制类型转换,写成如下,您觉得会改变本意吗?
atomic_set32((uint32_t*)(&a), b)
谢谢 gallop020142 发表于 2022-1-25 10:38
感谢回复
有两个小问题:
1. rtx_core_cm.h 这个文件工程里面找不到。我从c盘AppData\Local\Arm\Pack ...
直接单步调试看执行流程就行,执行了相应代码就没问题。 eric2013 发表于 2022-1-25 10:50
直接单步调试看执行流程就行,执行了相应代码就没问题。
好的,我先试试,谢谢 eric2013 发表于 2022-1-25 10:50
直接单步调试看执行流程就行,执行了相应代码就没问题。
试过了,结果不对,有空时请帮忙看看哈。谢谢。
我测试的代码大意如下,其中b是一个变化的数
int32_t a = 0, c = 0;
//一个任务里面赋值
atomic_set((uint32_t*)&a, b);
c = b;
//在另一个任务里面打印
printf("%d vs atomic %d\r\n", c, a);
结果:c跟随b变化,但是a是与b不相关的值,从15, 63, 1023 ... 到最后是-1 gallop020142 发表于 2022-1-25 22:11
试过了,结果不对,有空时请帮忙看看哈。谢谢。
我测试的代码大意如下,其中b是一个变化的数
int32_t a ...
atomic_set32是设置位的,将原有的结果进行或操作,等价于a|=b WZH 发表于 2022-2-19 12:03
atomic_set32是设置位的,将原有的结果进行或操作,等价于a|=b
感谢回复,请问赋值操作(不是自增自减),该用哪个函数呢? 像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直接写一个字节的数据把 tovinz 发表于 2022-5-10 09:50
像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直 ...
对啊,这个也需要原子操作。 难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就是直接往内存里写一个字节, 仅仅就一个写操作,需要原子操作吗 tovinz 发表于 2022-5-10 11:16
难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就 ...
是的,因为他必须先读到的寄存器才可以往对应地址写。数值不能没有CPU的参与情况下直接往地址里面写,所以它不是原子操作,除非DMA之类的。
不知道你是不是这个意思。
ps:ldrexb是字节操作,ldrex是字操作。
eric2013 发表于 2022-5-10 11:33
是的,因为他必须先读到的寄存器才可以往对应地址写。数值不能没有CPU的参与情况下直接往地址里面写,所 ...
一语点醒梦中人,读写变量还要经CPU转一手
:):):):):) 学到了 ST的库也开始带了一些原子操作API 没懂啊,硬汉哥,这些函数调用时不会被中断打断吗? LeslieChia 发表于 2022-9-29 21:57
没懂啊,硬汉哥,这些函数调用时不会被中断打断吗?
不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。 eric2013 发表于 2022-9-30 00:43
不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。
[*]static __asm uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
[*]mov r2,r0
[*]1
[*]ldrexb r0,
[*]strexb r3,r1,
[*]cbz r3,%F2
[*]b %B1
[*]2
[*]bx lr
[*]}
请教下,这个函数里面mem, val 2个参数也木有看到被调用啊 ???
hpdell 发表于 2022-9-30 10:54
[*]static __asm uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
[*]mov r2,r0
[*]1
MDK调试进入这个函数,会看到两个参数被传递给寄存器了。 eric2013 发表于 2022-9-30 11:06
MDK调试进入这个函数,会看到两个参数被传递给寄存器了。
比较神器的函数 哟 都是汇编语言吧 雷鹏 发表于 2022-9-30 11:26
都是汇编语言吧
对,就是C嵌入汇编的方式,方便调用。 hpdell 发表于 2022-9-30 11:23
比较神器的函数 哟
这个是那个AAPCS规约要求的,形参使用寄存器,有固定使用那个的。 eric2013 发表于 2022-9-30 15:46
这个是那个AAPCS规约要求的,形参使用寄存器,有固定使用那个的。
感觉蛮高大上的,只可惜不懂哟 :):lol eric2013 发表于 2022-9-30 00:43
不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。
硬汉哥,我还是不太理解它的原理,比如我执行atomic_set32函数操作A变量,执行到一半时,中断来了也调用atomic_set32函数操作A变量,这样不会冲突吗? LeslieChia 发表于 2022-10-10 14:11
硬汉哥,我还是不太理解它的原理,比如我执行atomic_set32函数操作A变量,执行到一半时,中断来了也调用a ...
这个调用的是互斥指令ldrex和strex 本帖最后由 wy_nb 于 2023-2-28 16:23 编辑
楼主好!我是一个初学者刷到这个帖子,想请问一下:
__asm uint8_t atomic_wr8(uint8_t *mem, uint8_t val)
{
mov r2,r0
1
ldrexb r0, // r0 = *mem,r0 的值并没有用到,即读出的值无意义
strexb r3,r1, // *mem = val,若写操作成功,r3 值为 0
cbz r3,%F2 // r3 为 0,则向前跳转到2,函数返回
b %B1 // r3 不为0,则向后跳转到1,重复操作
2
bx lr
}
从程序上是不是可以理解成这并不是一个"读-修改-写"操作,而仅仅是一个8位数据的写操作?
下面这个函数是否也可以完成同样的功能?
__asm uint8_t wr8(uint8_t *mem, uint8_t val)
{
strb r1, // *mem = val
}
请问楼主,下面这个函数的执行不是原子操作吗?
wy_nb 发表于 2023-2-28 14:58
楼主好!我是一个初学者刷到这个帖子,想请问一下:
__asm uint8_t atomic_wr8(uint8_t *mem, uint8_t v ...
不好意思,我理解错了,我没注意函数的返回值;atomic_wr8 函数返回的是读出值,这个函数是一个“读-修改-写”的操作! 搜索了下这两条指令,就明白什么原理了.
(25条消息) ARM平台下独占访问指令LDREX和STREX的原理与使用详解_ldrex用法_Roland_Sun的博客-CSDN博客
想请问一下__CC_ARM这个macro是GCC吗 saii 发表于 2023-4-13 07:52
想请问一下__CC_ARM这个macro是GCC吗
__GNUC__ GCC
__CC_ARM MDK
__ICCARM__ IAR 请教下您,原子变量能否会被中断打断?比如,在线程中对变量a进行读,在中断中对变量a进行写,是否能够实现在线程读变量a时,中断会等待变量a读完再对变量a进行写?
关于对32为变量修改还是不明白,能否做一个降低的示例?先“atomic_clr32”清零,再“atomic_set32 ”写入?在清零完成之后写入之前是否还是原子状态?
页:
[1]