eric2013 发表于 2021-10-12 14:27:47

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)



morning_enr6U 发表于 2021-11-24 21:18:47

{:8:}{:8:}

登云钓月 发表于 2021-11-29 00:11:30

看不懂 一脸懵

eric2013 发表于 2021-11-29 00:13:37

登云钓月 发表于 2021-11-29 00:11
看不懂 一脸懵

就是这个API函数,直接调用就行。

gallop020142 发表于 2022-1-6 10:31:12

请问32位的变量赋值操作,怎么用这些函数呢?谢谢

eric2013 发表于 2022-1-6 11:26:43

gallop020142 发表于 2022-1-6 10:31
请问32位的变量赋值操作,怎么用这些函数呢?谢谢

直接调用提供的32bit 操作即可,不是有注释。

gallop020142 发表于 2022-1-24 20:28:41

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);

谢谢

eric2013 发表于 2022-1-25 00:12:12

gallop020142 发表于 2022-1-24 20:28
在rtx_thread.c里面,是这样用atomic_set32的:
thread_flags = atomic_set32(&thread->thread_flags, f ...

就是这样的,你操作是否正常。

gallop020142 发表于 2022-1-25 10:38:40

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)

谢谢

eric2013 发表于 2022-1-25 10:50:10

gallop020142 发表于 2022-1-25 10:38
感谢回复
有两个小问题:
1. rtx_core_cm.h 这个文件工程里面找不到。我从c盘AppData\Local\Arm\Pack ...

直接单步调试看执行流程就行,执行了相应代码就没问题。

gallop020142 发表于 2022-1-25 12:47:18

eric2013 发表于 2022-1-25 10:50
直接单步调试看执行流程就行,执行了相应代码就没问题。

好的,我先试试,谢谢

gallop020142 发表于 2022-1-25 22:11:38

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

WZH 发表于 2022-2-19 12:03:24

gallop020142 发表于 2022-1-25 22:11
试过了,结果不对,有空时请帮忙看看哈。谢谢。
我测试的代码大意如下,其中b是一个变化的数
int32_t a ...

atomic_set32是设置位的,将原有的结果进行或操作,等价于a|=b

gallop020142 发表于 2022-2-23 10:50:24

WZH 发表于 2022-2-19 12:03
atomic_set32是设置位的,将原有的结果进行或操作,等价于a|=b

感谢回复,请问赋值操作(不是自增自减),该用哪个函数呢?

tovinz 发表于 2022-5-10 09:50:48

像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直接写一个字节的数据把

eric2013 发表于 2022-5-10 10:11:11

tovinz 发表于 2022-5-10 09:50
像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直 ...

对啊,这个也需要原子操作。

tovinz 发表于 2022-5-10 11:16:28

难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就是直接往内存里写一个字节, 仅仅就一个写操作,需要原子操作吗

eric2013 发表于 2022-5-10 11:33:46

tovinz 发表于 2022-5-10 11:16
难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就 ...
是的,因为他必须先读到的寄存器才可以往对应地址写。数值不能没有CPU的参与情况下直接往地址里面写,所以它不是原子操作,除非DMA之类的。
不知道你是不是这个意思。
ps:ldrexb是字节操作,ldrex是字操作。



tovinz 发表于 2022-5-10 13:37:11

eric2013 发表于 2022-5-10 11:33
是的,因为他必须先读到的寄存器才可以往对应地址写。数值不能没有CPU的参与情况下直接往地址里面写,所 ...

一语点醒梦中人,读写变量还要经CPU转一手

cheng_5230 发表于 2022-5-10 17:24:24

:):):):):) 学到了

eric2013 发表于 2022-5-11 09:52:47

ST的库也开始带了一些原子操作API

LeslieChia 发表于 2022-9-29 21:57:11

没懂啊,硬汉哥,这些函数调用时不会被中断打断吗?

eric2013 发表于 2022-9-30 00:43:53

LeslieChia 发表于 2022-9-29 21:57
没懂啊,硬汉哥,这些函数调用时不会被中断打断吗?

不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。

hpdell 发表于 2022-9-30 10:54:54

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个参数也木有看到被调用啊 ???



eric2013 发表于 2022-9-30 11:06:00

hpdell 发表于 2022-9-30 10:54
[*]static __asm    uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
[*]mov    r2,r0
[*]1


MDK调试进入这个函数,会看到两个参数被传递给寄存器了。

hpdell 发表于 2022-9-30 11:23:24

eric2013 发表于 2022-9-30 11:06
MDK调试进入这个函数,会看到两个参数被传递给寄存器了。

比较神器的函数 哟

雷鹏 发表于 2022-9-30 11:26:31

都是汇编语言吧

eric2013 发表于 2022-9-30 15:45:22

雷鹏 发表于 2022-9-30 11:26
都是汇编语言吧

对,就是C嵌入汇编的方式,方便调用。

eric2013 发表于 2022-9-30 15:46:22

hpdell 发表于 2022-9-30 11:23
比较神器的函数 哟

这个是那个AAPCS规约要求的,形参使用寄存器,有固定使用那个的。

hpdell 发表于 2022-9-30 16:48:48

eric2013 发表于 2022-9-30 15:46
这个是那个AAPCS规约要求的,形参使用寄存器,有固定使用那个的。

感觉蛮高大上的,只可惜不懂哟 :):lol

LeslieChia 发表于 2022-10-10 14:11:21

eric2013 发表于 2022-9-30 00:43
不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。

硬汉哥,我还是不太理解它的原理,比如我执行atomic_set32函数操作A变量,执行到一半时,中断来了也调用atomic_set32函数操作A变量,这样不会冲突吗?

eric2013 发表于 2022-10-10 15:50:41

LeslieChia 发表于 2022-10-10 14:11
硬汉哥,我还是不太理解它的原理,比如我执行atomic_set32函数操作A变量,执行到一半时,中断来了也调用a ...

这个调用的是互斥指令ldrex和strex

wy_nb 发表于 2023-2-28 14:58:11

本帖最后由 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-3-1 11:05:45

wy_nb 发表于 2023-2-28 14:58
楼主好!我是一个初学者刷到这个帖子,想请问一下:

__asm uint8_t atomic_wr8(uint8_t *mem, uint8_t v ...

不好意思,我理解错了,我没注意函数的返回值;atomic_wr8 函数返回的是读出值,这个函数是一个“读-修改-写”的操作!

tcs_stm32 发表于 2023-4-4 15:37:21

搜索了下这两条指令,就明白什么原理了.
(25条消息) ARM平台下独占访问指令LDREX和STREX的原理与使用详解_ldrex用法_Roland_Sun的博客-CSDN博客

saii 发表于 2023-4-13 07:52:19

想请问一下__CC_ARM这个macro是GCC吗

eric2013 发表于 2023-4-13 10:08:41

saii 发表于 2023-4-13 07:52
想请问一下__CC_ARM这个macro是GCC吗

__GNUC__          GCC
__CC_ARM          MDK
__ICCARM__       IAR

黄毅7789 发表于 2023-5-3 02:16:19

请教下您,原子变量能否会被中断打断?比如,在线程中对变量a进行读,在中断中对变量a进行写,是否能够实现在线程读变量a时,中断会等待变量a读完再对变量a进行写?

关于对32为变量修改还是不明白,能否做一个降低的示例?先“atomic_clr32”清零,再“atomic_set32 ”写入?在清零完成之后写入之前是否还是原子状态?
页: [1]
查看完整版本: RTX5里面提供的各种原子操作API,可以独立复制出来使用,含MDK,IAR和GCC