硬汉嵌入式论坛

 找回密码
 立即注册
查看: 4466|回复: 37
收起左侧

RTX5里面提供的各种原子操作API,可以独立复制出来使用,含MDK,IAR和GCC

  [复制链接]

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
发表于 2021-10-12 14:27:47 | 显示全部楼层 |阅读模式


复制出来开个帖子,方便以后查阅:

  1. //  ==== Exclusive Access Operation ====

  2. #if (EXCLUSIVE_ACCESS == 1)

  3. //lint ++flb "Library Begin" [MISRA Note 12]

  4. /// Atomic Access Operation: Write (8-bit)
  5. /// \param[in]  mem             Memory address
  6. /// \param[in]  val             Value to write
  7. /// \return                     Previous value
  8. #if defined(__CC_ARM)
  9. static __asm    uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
  10.   mov    r2,r0
  11. 1
  12.   ldrexb r0,[r2]
  13.   strexb r3,r1,[r2]
  14.   cbz    r3,%F2
  15.   b      %B1
  16. 2
  17.   bx     lr
  18. }
  19. #else
  20. __STATIC_INLINE uint8_t atomic_wr8 (uint8_t *mem, uint8_t val) {
  21. #ifdef  __ICCARM__
  22. #pragma diag_suppress=Pe550
  23. #endif
  24.   register uint32_t res;
  25. #ifdef  __ICCARM__
  26. #pragma diag_default=Pe550
  27. #endif
  28.   register uint8_t  ret;

  29.   __ASM volatile (
  30. #ifndef __ICCARM__
  31.   ".syntax unified\n\t"
  32. #endif
  33.   "1:\n\t"
  34.     "ldrexb %[ret],[%[mem]]\n\t"
  35.     "strexb %[res],%[val],[%[mem]]\n\t"
  36.     "cbz    %[res],2f\n\t"
  37.     "b       1b\n"
  38.   "2:"
  39.   : [ret] "=&l" (ret),
  40.     [res] "=&l" (res)
  41.   : [mem] "l"   (mem),
  42.     [val] "l"   (val)
  43.   : "memory"
  44.   );

  45.   return ret;
  46. }
  47. #endif

  48. /// Atomic Access Operation: Set bits (32-bit)
  49. /// \param[in]  mem             Memory address
  50. /// \param[in]  bits            Bit mask
  51. /// \return                     New value
  52. #if defined(__CC_ARM)
  53. static __asm    uint32_t atomic_set32 (uint32_t *mem, uint32_t bits) {
  54.   mov   r2,r0
  55. 1
  56.   ldrex r0,[r2]
  57.   orr   r0,r0,r1
  58.   strex r3,r0,[r2]
  59.   cbz   r3,%F2
  60.   b     %B1
  61. 2
  62.   bx     lr
  63. }
  64. #else
  65. __STATIC_INLINE uint32_t atomic_set32 (uint32_t *mem, uint32_t bits) {
  66. #ifdef  __ICCARM__
  67. #pragma diag_suppress=Pe550
  68. #endif
  69.   register uint32_t val, res;
  70. #ifdef  __ICCARM__
  71. #pragma diag_default=Pe550
  72. #endif
  73.   register uint32_t ret;

  74.   __ASM volatile (
  75. #ifndef __ICCARM__
  76.   ".syntax unified\n\t"
  77. #endif
  78.   "1:\n\t"
  79.     "ldrex %[val],[%[mem]]\n\t"
  80. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  81.     "mov   %[ret],%[val]\n\t"
  82.     "orrs  %[ret],%[bits]\n\t"
  83. #else
  84.     "orr   %[ret],%[val],%[bits]\n\t"
  85. #endif
  86.     "strex %[res],%[ret],[%[mem]]\n\t"
  87.     "cbz   %[res],2f\n\t"
  88.     "b     1b\n"
  89.   "2:"
  90.   : [ret]  "=&l" (ret),
  91.     [val]  "=&l" (val),
  92.     [res]  "=&l" (res)
  93.   : [mem]  "l"   (mem),
  94.     [bits] "l"   (bits)
  95. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  96.   : "memory", "cc"
  97. #else
  98.   : "memory"
  99. #endif
  100.   );

  101.   return ret;
  102. }
  103. #endif

  104. /// Atomic Access Operation: Clear bits (32-bit)
  105. /// \param[in]  mem             Memory address
  106. /// \param[in]  bits            Bit mask
  107. /// \return                     Previous value
  108. #if defined(__CC_ARM)
  109. static __asm    uint32_t atomic_clr32 (uint32_t *mem, uint32_t bits) {
  110.   push  {r4,lr}
  111.   mov   r2,r0
  112. 1
  113.   ldrex r0,[r2]
  114.   bic   r4,r0,r1
  115.   strex r3,r4,[r2]
  116.   cbz   r3,%F2
  117.   b     %B1
  118. 2
  119.   pop   {r4,pc}
  120. }
  121. #else
  122. __STATIC_INLINE uint32_t atomic_clr32 (uint32_t *mem, uint32_t bits) {
  123. #ifdef  __ICCARM__
  124. #pragma diag_suppress=Pe550
  125. #endif
  126.   register uint32_t val, res;
  127. #ifdef  __ICCARM__
  128. #pragma diag_default=Pe550
  129. #endif
  130.   register uint32_t ret;

  131.   __ASM volatile (
  132. #ifndef __ICCARM__
  133.   ".syntax unified\n\t"
  134. #endif
  135.   "1:\n\t"
  136.     "ldrex %[ret],[%[mem]]\n\t"
  137. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  138.     "mov   %[val],%[ret]\n\t"
  139.     "bics  %[val],%[bits]\n\t"
  140. #else
  141.     "bic   %[val],%[ret],%[bits]\n\t"
  142. #endif
  143.     "strex %[res],%[val],[%[mem]]\n\t"
  144.     "cbz   %[res],2f\n\t"
  145.     "b     1b\n"
  146.   "2:"
  147.   : [ret]  "=&l" (ret),
  148.     [val]  "=&l" (val),
  149.     [res]  "=&l" (res)
  150.   : [mem]  "l"   (mem),
  151.     [bits] "l"   (bits)
  152. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  153.   : "memory", "cc"
  154. #else
  155.   : "memory"
  156. #endif
  157.   );

  158.   return ret;
  159. }
  160. #endif

  161. /// Atomic Access Operation: Check if all specified bits (32-bit) are active and clear them
  162. /// \param[in]  mem             Memory address
  163. /// \param[in]  bits            Bit mask
  164. /// \return                     Active bits before clearing or 0 if not active
  165. #if defined(__CC_ARM)
  166. static __asm    uint32_t atomic_chk32_all (uint32_t *mem, uint32_t bits) {
  167.   push  {r4,lr}
  168.   mov   r2,r0
  169. 1
  170.   ldrex r0,[r2]
  171.   and   r4,r0,r1
  172.   cmp   r4,r1
  173.   beq   %F2
  174.   clrex
  175.   movs  r0,#0
  176.   pop   {r4,pc}
  177. 2
  178.   bic   r4,r0,r1
  179.   strex r3,r4,[r2]
  180.   cbz   r3,%F3
  181.   b     %B1
  182. 3
  183.   pop   {r4,pc}
  184. }
  185. #else
  186. __STATIC_INLINE uint32_t atomic_chk32_all (uint32_t *mem, uint32_t bits) {
  187. #ifdef  __ICCARM__
  188. #pragma diag_suppress=Pe550
  189. #endif
  190.   register uint32_t val, res;
  191. #ifdef  __ICCARM__
  192. #pragma diag_default=Pe550
  193. #endif
  194.   register uint32_t ret;

  195.   __ASM volatile (
  196. #ifndef __ICCARM__
  197.   ".syntax unified\n\t"
  198. #endif
  199.   "1:\n\t"
  200.     "ldrex %[ret],[%[mem]]\n\t"
  201. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  202.     "mov   %[val],%[ret]\n\t"
  203.     "ands  %[val],%[bits]\n\t"
  204. #else
  205.     "and   %[val],%[ret],%[bits]\n\t"
  206. #endif
  207.     "cmp   %[val],%[bits]\n\t"
  208.     "beq   2f\n\t"
  209.     "clrex\n\t"
  210.     "movs  %[ret],#0\n\t"
  211.     "b     3f\n"
  212.   "2:\n\t"
  213. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  214.     "mov   %[val],%[ret]\n\t"
  215.     "bics  %[val],%[bits]\n\t"
  216. #else
  217.     "bic   %[val],%[ret],%[bits]\n\t"
  218. #endif
  219.     "strex %[res],%[val],[%[mem]]\n\t"
  220.     "cbz   %[res],3f\n\t"
  221.     "b     1b\n"
  222.   "3:"
  223.   : [ret]  "=&l" (ret),
  224.     [val]  "=&l" (val),
  225.     [res]  "=&l" (res)
  226.   : [mem]  "l"   (mem),
  227.     [bits] "l"   (bits)
  228.   : "cc", "memory"
  229.   );

  230.   return ret;
  231. }
  232. #endif

  233. /// Atomic Access Operation: Check if any specified bits (32-bit) are active and clear them
  234. /// \param[in]  mem             Memory address
  235. /// \param[in]  bits            Bit mask
  236. /// \return                     Active bits before clearing or 0 if not active
  237. #if defined(__CC_ARM)
  238. static __asm    uint32_t atomic_chk32_any (uint32_t *mem, uint32_t bits) {
  239.   push  {r4,lr}
  240.   mov   r2,r0
  241. 1
  242.   ldrex r0,[r2]
  243.   tst   r0,r1
  244.   bne   %F2
  245.   clrex
  246.   movs  r0,#0
  247.   pop   {r4,pc}
  248. 2
  249.   bic   r4,r0,r1
  250.   strex r3,r4,[r2]
  251.   cbz   r3,%F3
  252.   b     %B1
  253. 3
  254.   pop   {r4,pc}
  255. }
  256. #else
  257. __STATIC_INLINE uint32_t atomic_chk32_any (uint32_t *mem, uint32_t bits) {
  258. #ifdef  __ICCARM__
  259. #pragma diag_suppress=Pe550
  260. #endif
  261.   register uint32_t val, res;
  262. #ifdef  __ICCARM__
  263. #pragma diag_default=Pe550
  264. #endif
  265.   register uint32_t ret;

  266.   __ASM volatile (
  267. #ifndef __ICCARM__
  268.   ".syntax unified\n\t"
  269. #endif
  270.   "1:\n\t"
  271.     "ldrex %[ret],[%[mem]]\n\t"
  272.     "tst   %[ret],%[bits]\n\t"
  273.     "bne   2f\n\t"
  274.     "clrex\n\t"
  275.     "movs  %[ret],#0\n\t"
  276.     "b     3f\n"
  277.   "2:\n\t"
  278. #if (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0))
  279.     "mov   %[val],%[ret]\n\t"
  280.     "bics  %[val],%[bits]\n\t"
  281. #else
  282.     "bic   %[val],%[ret],%[bits]\n\t"
  283. #endif
  284.     "strex %[res],%[val],[%[mem]]\n\t"
  285.     "cbz   %[res],3f\n\t"
  286.     "b     1b\n"
  287.   "3:"
  288.   : [ret]  "=&l" (ret),
  289.     [val]  "=&l" (val),
  290.     [res]  "=&l" (res)
  291.   : [mem]  "l"   (mem),
  292.     [bits] "l"   (bits)
  293.   : "cc", "memory"
  294.   );

  295.   return ret;
  296. }
  297. #endif

  298. /// Atomic Access Operation: Increment (32-bit)
  299. /// \param[in]  mem             Memory address
  300. /// \return                     Previous value
  301. #if defined(__CC_ARM)
  302. static __asm    uint32_t atomic_inc32 (uint32_t *mem) {
  303.   mov   r2,r0
  304. 1
  305.   ldrex r0,[r2]
  306.   adds  r1,r0,#1
  307.   strex r3,r1,[r2]
  308.   cbz   r3,%F2
  309.   b     %B1
  310. 2
  311.   bx     lr
  312. }
  313. #else
  314. __STATIC_INLINE uint32_t atomic_inc32 (uint32_t *mem) {
  315. #ifdef  __ICCARM__
  316. #pragma diag_suppress=Pe550
  317. #endif
  318.   register uint32_t val, res;
  319. #ifdef  __ICCARM__
  320. #pragma diag_default=Pe550
  321. #endif
  322.   register uint32_t ret;

  323.   __ASM volatile (
  324. #ifndef __ICCARM__
  325.   ".syntax unified\n\t"
  326. #endif
  327.   "1:\n\t"
  328.     "ldrex %[ret],[%[mem]]\n\t"
  329.     "adds  %[val],%[ret],#1\n\t"
  330.     "strex %[res],%[val],[%[mem]]\n\t"
  331.     "cbz   %[res],2f\n\t"
  332.     "b     1b\n"
  333.   "2:"
  334.   : [ret] "=&l" (ret),
  335.     [val] "=&l" (val),
  336.     [res] "=&l" (res)
  337.   : [mem] "l"   (mem)
  338.   : "cc", "memory"
  339.   );

  340.   return ret;
  341. }
  342. #endif

  343. /// Atomic Access Operation: Increment (16-bit) if Less Than
  344. /// \param[in]  mem             Memory address
  345. /// \param[in]  max             Maximum value
  346. /// \return                     Previous value
  347. #if defined(__CC_ARM)
  348. static __asm    uint16_t atomic_inc16_lt (uint16_t *mem, uint16_t max) {
  349.   push   {r4,lr}
  350.   mov    r2,r0
  351. 1
  352.   ldrexh r0,[r2]
  353.   cmp    r1,r0
  354.   bhi    %F2
  355.   clrex
  356.   pop    {r4,pc}
  357. 2
  358.   adds   r4,r0,#1
  359.   strexh r3,r4,[r2]
  360.   cbz    r3,%F3
  361.   b      %B1
  362. 3
  363.   pop    {r4,pc}
  364. }
  365. #else
  366. __STATIC_INLINE uint16_t atomic_inc16_lt (uint16_t *mem, uint16_t max) {
  367. #ifdef  __ICCARM__
  368. #pragma diag_suppress=Pe550
  369. #endif
  370.   register uint32_t val, res;
  371. #ifdef  __ICCARM__
  372. #pragma diag_default=Pe550
  373. #endif
  374.   register uint16_t ret;

  375.   __ASM volatile (
  376. #ifndef __ICCARM__
  377.   ".syntax unified\n\t"
  378. #endif
  379.   "1:\n\t"
  380.     "ldrexh %[ret],[%[mem]]\n\t"
  381.     "cmp    %[max],%[ret]\n\t"
  382.     "bhi    2f\n\t"
  383.     "clrex\n\t"
  384.     "b      3f\n"
  385.   "2:\n\t"
  386.     "adds   %[val],%[ret],#1\n\t"
  387.     "strexh %[res],%[val],[%[mem]]\n\t"
  388.     "cbz    %[res],3f\n\t"
  389.     "b      1b\n"
  390.   "3:"
  391.   : [ret] "=&l" (ret),
  392.     [val] "=&l" (val),
  393.     [res] "=&l" (res)
  394.   : [mem] "l"   (mem),
  395.     [max] "l"   (max)
  396.   : "cc", "memory"
  397.   );

  398.   return ret;
  399. }
  400. #endif

  401. /// Atomic Access Operation: Increment (16-bit) and clear on Limit
  402. /// \param[in]  mem             Memory address
  403. /// \param[in]  max             Maximum value
  404. /// \return                     Previous value
  405. #if defined(__CC_ARM)
  406. static __asm    uint16_t atomic_inc16_lim (uint16_t *mem, uint16_t lim) {
  407.   push   {r4,lr}
  408.   mov    r2,r0
  409. 1
  410.   ldrexh r0,[r2]
  411.   adds   r4,r0,#1
  412.   cmp    r1,r4
  413.   bhi    %F2
  414.   movs   r4,#0
  415. 2
  416.   strexh r3,r4,[r2]
  417.   cbz    r3,%F3
  418.   b      %B1
  419. 3
  420.   pop    {r4,pc}
  421. }
  422. #else
  423. __STATIC_INLINE uint16_t atomic_inc16_lim (uint16_t *mem, uint16_t lim) {
  424. #ifdef  __ICCARM__
  425. #pragma diag_suppress=Pe550
  426. #endif
  427.   register uint32_t val, res;
  428. #ifdef  __ICCARM__
  429. #pragma diag_default=Pe550
  430. #endif
  431.   register uint16_t ret;

  432.   __ASM volatile (
  433. #ifndef __ICCARM__
  434.   ".syntax unified\n\t"
  435. #endif
  436.   "1:\n\t"
  437.     "ldrexh %[ret],[%[mem]]\n\t"
  438.     "adds   %[val],%[ret],#1\n\t"
  439.     "cmp    %[lim],%[val]\n\t"
  440.     "bhi    2f\n\t"
  441.     "movs   %[val],#0\n"
  442.   "2:\n\t"
  443.     "strexh %[res],%[val],[%[mem]]\n\t"
  444.     "cbz    %[res],3f\n\t"
  445.     "b      1b\n"
  446.   "3:"
  447.   : [ret] "=&l" (ret),
  448.     [val] "=&l" (val),
  449.     [res] "=&l" (res)
  450.   : [mem] "l"   (mem),
  451.     [lim] "l"   (lim)
  452.   : "cc", "memory"
  453.   );

  454.   return ret;
  455. }
  456. #endif

  457. /// Atomic Access Operation: Decrement (32-bit)
  458. /// \param[in]  mem             Memory address
  459. /// \return                     Previous value
  460. #if defined(__CC_ARM)
  461. static __asm    uint32_t atomic_dec32 (uint32_t *mem) {
  462.   mov   r2,r0
  463. 1
  464.   ldrex r0,[r2]
  465.   subs  r1,r0,#1
  466.   strex r3,r1,[r2]
  467.   cbz   r3,%F2
  468.   b     %B1
  469. 2
  470.   bx     lr
  471. }
  472. #else
  473. __STATIC_INLINE uint32_t atomic_dec32 (uint32_t *mem) {
  474. #ifdef  __ICCARM__
  475. #pragma diag_suppress=Pe550
  476. #endif
  477.   register uint32_t val, res;
  478. #ifdef  __ICCARM__
  479. #pragma diag_default=Pe550
  480. #endif
  481.   register uint32_t ret;

  482.   __ASM volatile (
  483. #ifndef __ICCARM__
  484.   ".syntax unified\n\t"
  485. #endif
  486.   "1:\n\t"
  487.     "ldrex %[ret],[%[mem]]\n\t"
  488.     "subs  %[val],%[ret],#1\n\t"
  489.     "strex %[res],%[val],[%[mem]]\n\t"
  490.     "cbz   %[res],2f\n\t"
  491.     "b     1b\n"
  492.   "2:"
  493.   : [ret] "=&l" (ret),
  494.     [val] "=&l" (val),
  495.     [res] "=&l" (res)
  496.   : [mem] "l"   (mem)
  497.   : "cc", "memory"
  498.   );

  499.   return ret;
  500. }
  501. #endif

  502. /// Atomic Access Operation: Decrement (32-bit) if Not Zero
  503. /// \param[in]  mem             Memory address
  504. /// \return                     Previous value
  505. #if defined(__CC_ARM)
  506. static __asm    uint32_t atomic_dec32_nz (uint32_t *mem) {
  507.   mov   r2,r0
  508. 1
  509.   ldrex r0,[r2]
  510.   cbnz  r0,%F2
  511.   clrex
  512.   bx    lr
  513. 2
  514.   subs  r1,r0,#1
  515.   strex r3,r1,[r2]
  516.   cbz   r3,%F3
  517.   b     %B1
  518. 3
  519.   bx     lr
  520. }
  521. #else
  522. __STATIC_INLINE uint32_t atomic_dec32_nz (uint32_t *mem) {
  523. #ifdef  __ICCARM__
  524. #pragma diag_suppress=Pe550
  525. #endif
  526.   register uint32_t val, res;
  527. #ifdef  __ICCARM__
  528. #pragma diag_default=Pe550
  529. #endif
  530.   register uint32_t ret;

  531.   __ASM volatile (
  532. #ifndef __ICCARM__
  533.   ".syntax unified\n\t"
  534. #endif
  535.   "1:\n\t"
  536.     "ldrex %[ret],[%[mem]]\n\t"
  537.     "cbnz  %[ret],2f\n\t"
  538.     "clrex\n\t"
  539.     "b     3f\n"
  540.   "2:\n\t"
  541.     "subs  %[val],%[ret],#1\n\t"
  542.     "strex %[res],%[val],[%[mem]]\n\t"
  543.     "cbz   %[res],3f\n\t"
  544.     "b     1b\n"
  545.   "3:"
  546.   : [ret] "=&l" (ret),
  547.     [val] "=&l" (val),
  548.     [res] "=&l" (res)
  549.   : [mem] "l"   (mem)
  550.   : "cc", "memory"
  551.   );

  552.   return ret;
  553. }
  554. #endif

  555. /// Atomic Access Operation: Decrement (16-bit) if Not Zero
  556. /// \param[in]  mem             Memory address
  557. /// \return                     Previous value
  558. #if defined(__CC_ARM)
  559. static __asm    uint16_t atomic_dec16_nz (uint16_t *mem) {
  560.   mov    r2,r0
  561. 1
  562.   ldrexh r0,[r2]
  563.   cbnz   r0,%F2
  564.   clrex
  565.   bx     lr
  566. 2
  567.   subs   r1,r0,#1
  568.   strexh r3,r1,[r2]
  569.   cbz    r3,%F3
  570.   b      %B1
  571. 3
  572.   bx      lr
  573. }
  574. #else
  575. __STATIC_INLINE uint16_t atomic_dec16_nz (uint16_t *mem) {
  576. #ifdef  __ICCARM__
  577. #pragma diag_suppress=Pe550
  578. #endif
  579.   register uint32_t val, res;
  580. #ifdef  __ICCARM__
  581. #pragma diag_default=Pe550
  582. #endif
  583.   register uint16_t ret;

  584.   __ASM volatile (
  585. #ifndef __ICCARM__
  586.   ".syntax unified\n\t"
  587. #endif
  588.   "1:\n\t"
  589.     "ldrexh %[ret],[%[mem]]\n\t"
  590.     "cbnz   %[ret],2f\n\t"
  591.     "clrex\n\t"
  592.     "b      3f\n"
  593.   "2:\n\t"
  594.     "subs   %[val],%[ret],#1\n\t"
  595.     "strexh %[res],%[val],[%[mem]]\n\t"
  596.     "cbz    %[res],3f\n\t"
  597.     "b      1b\n"
  598.   "3:"
  599.   : [ret] "=&l" (ret),
  600.     [val] "=&l" (val),
  601.     [res] "=&l" (res)
  602.   : [mem] "l"   (mem)
  603.   : "cc", "memory"
  604.   );

  605.   return ret;
  606. }
  607. #endif

  608. /// Atomic Access Operation: Link Get
  609. /// \param[in]  root            Root address
  610. /// \return                     Link
  611. #if defined(__CC_ARM)
  612. static __asm    void *atomic_link_get (void **root) {
  613.   mov   r2,r0
  614. 1
  615.   ldrex r0,[r2]
  616.   cbnz  r0,%F2
  617.   clrex
  618.   bx    lr
  619. 2
  620.   ldr   r1,[r0]
  621.   strex r3,r1,[r2]
  622.   cbz   r3,%F3
  623.   b     %B1
  624. 3
  625.   bx     lr
  626. }
  627. #else
  628. __STATIC_INLINE void *atomic_link_get (void **root) {
  629. #ifdef  __ICCARM__
  630. #pragma diag_suppress=Pe550
  631. #endif
  632.   register uint32_t val, res;
  633. #ifdef  __ICCARM__
  634. #pragma diag_default=Pe550
  635. #endif
  636.   register void    *ret;

  637.   __ASM volatile (
  638. #ifndef __ICCARM__
  639.   ".syntax unified\n\t"
  640. #endif
  641.   "1:\n\t"
  642.     "ldrex %[ret],[%[root]]\n\t"
  643.     "cbnz  %[ret],2f\n\t"
  644.     "clrex\n\t"
  645.     "b     3f\n"
  646.   "2:\n\t"
  647.     "ldr   %[val],[%[ret]]\n\t"
  648.     "strex %[res],%[val],[%[root]]\n\t"
  649.     "cbz   %[res],3f\n\t"
  650.     "b     1b\n"
  651.   "3:"
  652.   : [ret]  "=&l" (ret),
  653.     [val]  "=&l" (val),
  654.     [res]  "=&l" (res)
  655.   : [root] "l"   (root)
  656.   : "cc", "memory"
  657.   );

  658.   return ret;
  659. }
  660. #endif

  661. /// Atomic Access Operation: Link Put
  662. /// \param[in]  root            Root address
  663. /// \param[in]  lnk             Link
  664. #if defined(__CC_ARM)
  665. static __asm    void atomic_link_put (void **root, void *link) {
  666. 1
  667.   ldr   r2,[r0]
  668.   str   r2,[r1]
  669.   dmb
  670.   ldrex r2,[r0]
  671.   ldr   r3,[r1]
  672.   cmp   r3,r2
  673.   bne   %B1
  674.   strex r3,r1,[r0]
  675.   cbz   r3,%F2
  676.   b     %B1
  677. 2
  678.   bx    lr
  679. }
  680. #else
  681. __STATIC_INLINE void atomic_link_put (void **root, void *link) {
  682. #ifdef  __ICCARM__
  683. #pragma diag_suppress=Pe550
  684. #endif
  685.   register uint32_t val1, val2, res;
  686. #ifdef  __ICCARM__
  687. #pragma diag_default=Pe550
  688. #endif

  689.   __ASM volatile (
  690. #ifndef __ICCARM__
  691.   ".syntax unified\n\t"
  692. #endif
  693.   "1:\n\t"
  694.     "ldr   %[val1],[%[root]]\n\t"
  695.     "str   %[val1],[%[link]]\n\t"
  696.     "dmb\n\t"
  697.     "ldrex %[val1],[%[root]]\n\t"
  698.     "ldr   %[val2],[%[link]]\n\t"
  699.     "cmp   %[val2],%[val1]\n\t"
  700.     "bne   1b\n\t"
  701.     "strex %[res],%[link],[%[root]]\n\t"
  702.     "cbz   %[res],2f\n\t"
  703.     "b     1b\n"
  704.   "2:"
  705.   : [val1] "=&l" (val1),
  706.     [val2] "=&l" (val2),
  707.     [res]  "=&l" (res)
  708.   : [root] "l"   (root),
  709.     [link] "l"   (link)
  710.   : "cc", "memory"
  711.   );
  712. }
  713. #endif

  714. //lint --flb "Library End" [MISRA Note 12]

  715. #endif  // (EXCLUSIVE_ACCESS == 1)
复制代码




回复

使用道具 举报

3

主题

1220

回帖

1229

积分

至尊会员

积分
1229
发表于 2021-11-24 21:18:47 | 显示全部楼层
回复

使用道具 举报

0

主题

34

回帖

34

积分

新手上路

积分
34
发表于 2021-11-29 00:11:30 | 显示全部楼层
看不懂 一脸懵
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2021-11-29 00:13:37 | 显示全部楼层

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

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 2022-1-6 10:31:12 | 显示全部楼层
请问32位的变量赋值操作,怎么用这些函数呢?谢谢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-1-6 11:26:43 | 显示全部楼层
gallop020142 发表于 2022-1-6 10:31
请问32位的变量赋值操作,怎么用这些函数呢?谢谢

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

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 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);

谢谢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 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 ...

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

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 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)

谢谢
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-1-25 10:50:10 | 显示全部楼层
gallop020142 发表于 2022-1-25 10:38
感谢回复
有两个小问题:
1. rtx_core_cm.h 这个文件工程里面找不到。我从c盘  AppData\Local\Arm\Pack ...

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

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 2022-1-25 12:47:18 | 显示全部楼层
eric2013 发表于 2022-1-25 10:50
直接单步调试看执行流程就行,执行了相应代码就没问题。

好的,我先试试,谢谢
回复

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 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
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
发表于 2022-2-19 12:03:24 | 显示全部楼层
gallop020142 发表于 2022-1-25 22:11
试过了,结果不对,有空时请帮忙看看哈。谢谢。
我测试的代码大意如下,其中b是一个变化的数
int32_t a ...

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

使用道具 举报

12

主题

176

回帖

212

积分

高级会员

积分
212
发表于 2022-2-23 10:50:24 | 显示全部楼层
WZH 发表于 2022-2-19 12:03
atomic_set32是设置位的,将原有的结果进行或操作,等价于a|=b

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

使用道具 举报

18

主题

233

回帖

287

积分

高级会员

积分
287
发表于 2022-5-10 09:50:48 | 显示全部楼层
像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直接写一个字节的数据把
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-5-10 10:11:11 | 显示全部楼层
tovinz 发表于 2022-5-10 09:50
像 atomic_set32 置位,复位操作我懂,因为需要读改写三步走。但为什么要有 atomic_wr8 , 这个函数应该是直 ...

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

使用道具 举报

18

主题

233

回帖

287

积分

高级会员

积分
287
发表于 2022-5-10 11:16:28 | 显示全部楼层
难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就是直接往内存里写一个字节, 仅仅就一个写操作,需要原子操作吗
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-5-10 11:33:46 | 显示全部楼层
tovinz 发表于 2022-5-10 11:16
难道arm的处理器不能直接以字节的形式访问内存吗, 只能是16bit和32bit的形式。我的意思是 atomic_wr8 不就 ...

是的,因为他必须先读到的寄存器才可以往对应地址写。数值不能没有CPU的参与情况下直接往地址里面写,所以它不是原子操作,除非DMA之类的。
不知道你是不是这个意思。
ps:ldrexb是字节操作,ldrex是字操作。



回复

使用道具 举报

18

主题

233

回帖

287

积分

高级会员

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

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

使用道具 举报

0

主题

43

回帖

43

积分

新手上路

积分
43
发表于 2022-5-10 17:24:24 | 显示全部楼层
学到了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-5-11 09:52:47 | 显示全部楼层
ST的库也开始带了一些原子操作API
回复

使用道具 举报

1

主题

14

回帖

17

积分

新手上路

积分
17
发表于 2022-9-29 21:57:11 | 显示全部楼层
没懂啊,硬汉哥,这些函数调用时不会被中断打断吗?
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 2022-9-30 00:43:53 | 显示全部楼层
LeslieChia 发表于 2022-9-29 21:57
没懂啊,硬汉哥,这些函数调用时不会被中断打断吗?

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

使用道具 举报

608

主题

3038

回帖

4882

积分

至尊会员

积分
4882
发表于 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,[r2]
  •   strexb r3,r1,[r2]
  •   cbz    r3,%F2
  •   b      %B1
  • 2
  •   bx     lr
  • }




请教下,这个函数里面  mem, val 2个参数也木有看到被调用啊 ???



回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
 楼主| 发表于 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调试进入这个函数,会看到两个参数被传递给寄存器了。
    回复

    使用道具 举报

    608

    主题

    3038

    回帖

    4882

    积分

    至尊会员

    积分
    4882
    发表于 2022-9-30 11:23:24 | 显示全部楼层
    eric2013 发表于 2022-9-30 11:06
    MDK调试进入这个函数,会看到两个参数被传递给寄存器了。

    比较神器的函数 哟
    回复

    使用道具 举报

    82

    主题

    399

    回帖

    665

    积分

    金牌会员

    积分
    665
    QQ
    发表于 2022-9-30 11:26:31 | 显示全部楼层
    都是汇编语言吧
    武汉天纵鹏元科技有限公司。承接嵌入式项目开发,相关技术交流。STM32,物联网,工业控制方向。QQ  408137104
    回复

    使用道具 举报

    1万

    主题

    6万

    回帖

    10万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    106437
    QQ
     楼主| 发表于 2022-9-30 15:45:22 | 显示全部楼层
    雷鹏 发表于 2022-9-30 11:26
    都是汇编语言吧

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

    使用道具 举报

    1万

    主题

    6万

    回帖

    10万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    106437
    QQ
     楼主| 发表于 2022-9-30 15:46:22 | 显示全部楼层
    hpdell 发表于 2022-9-30 11:23
    比较神器的函数 哟

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

    使用道具 举报

    608

    主题

    3038

    回帖

    4882

    积分

    至尊会员

    积分
    4882
    发表于 2022-9-30 16:48:48 | 显示全部楼层
    eric2013 发表于 2022-9-30 15:46
    这个是那个AAPCS规约要求的,形参使用寄存器,有固定使用那个的。

    感觉蛮高大上的,只可惜不懂哟
    回复

    使用道具 举报

    1

    主题

    14

    回帖

    17

    积分

    新手上路

    积分
    17
    发表于 2022-10-10 14:11:21 | 显示全部楼层
    eric2013 发表于 2022-9-30 00:43
    不影响,随意被中断。原子操作保证的是你对这个变量操作的原子性。

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

    使用道具 举报

    1万

    主题

    6万

    回帖

    10万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    106437
    QQ
     楼主| 发表于 2022-10-10 15:50:41 | 显示全部楼层
    LeslieChia 发表于 2022-10-10 14:11
    硬汉哥,我还是不太理解它的原理,比如我执行atomic_set32函数操作A变量,执行到一半时,中断来了也调用a ...

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

    使用道具 举报

    2

    主题

    7

    回帖

    13

    积分

    新手上路

    积分
    13
    发表于 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,[r2]           // r0 = *mem,r0 的值并没有用到,即读出的值无意义
      strexb r3,r1,[r2]       // *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, [r0]     // *mem = val
    }

    请问楼主,下面这个函数的执行不是原子操作吗?
    回复

    使用道具 举报

    2

    主题

    7

    回帖

    13

    积分

    新手上路

    积分
    13
    发表于 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 函数返回的是读出值,这个函数是一个“读-修改-写”的操作!
    回复

    使用道具 举报

    8

    主题

    135

    回帖

    159

    积分

    初级会员

    积分
    159
    发表于 2023-4-4 15:37:21 | 显示全部楼层
    回复

    使用道具 举报

    0

    主题

    1

    回帖

    1

    积分

    新手上路

    积分
    1
    发表于 2023-4-13 07:52:19 | 显示全部楼层
    想请问一下__CC_ARM这个macro是GCC吗
    回复

    使用道具 举报

    1万

    主题

    6万

    回帖

    10万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    106437
    QQ
     楼主| 发表于 2023-4-13 10:08:41 | 显示全部楼层
    saii 发表于 2023-4-13 07:52
    想请问一下__CC_ARM这个macro是GCC吗

    __GNUC__          GCC
    __CC_ARM          MDK
    __ICCARM__       IAR
    回复

    使用道具 举报

    5

    主题

    26

    回帖

    41

    积分

    新手上路

    积分
    41
    发表于 2023-5-3 02:16:19 | 显示全部楼层
    请教下您,原子变量能否会被中断打断?比如,在线程中对变量a进行读,在中断中对变量a进行写,是否能够实现在线程读变量a时,中断会等待变量a读完再对变量a进行写?

    关于对32为变量修改还是不明白,能否做一个降低的示例?先“atomic_clr32”清零,再“atomic_set32 ”写入?在清零完成之后写入之前是否还是原子状态?
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

    GMT+8, 2024-4-20 16:11 , Processed in 0.348749 second(s), 25 queries .

    Powered by Discuz! X3.4 Licensed

    Copyright © 2001-2023, Tencent Cloud.

    快速回复 返回顶部 返回列表