硬汉嵌入式论坛

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

[技术文档] 请大家翻译一个宏safe_atom_code()!!

[复制链接]

45

主题

70

回帖

205

积分

高级会员

积分
205
发表于 2021-1-25 22:52:37 | 显示全部楼层 |阅读模式
在网上看到per_counter这个开源项目,里边有一个宏这么用的。

  1. int32_t stop_cycle_counter(void)
  2. {
  3. int32_t nTemp = 0;

  4. safe_atom_code(){
  5. nTemp = check_systick() + s_nCycleCounts;
  6. }

  7. return nTemp - s_nOffset;
  8. }
复制代码
这个safe_atom_code(){} 应该是防止被打断的,但是我看了.h中的宏,没看懂。求教大神给发发。
  1. /*============================ MACROS ========================================*/

  2. #define __PLOOC_VA_NUM_ARGS_IMPL(   _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,  \
  3.                                     _13,_14,_15,_16,__N,...)      __N
  4. #define __PLOOC_VA_NUM_ARGS(...)                                                \
  5.             __PLOOC_VA_NUM_ARGS_IMPL( 0,##__VA_ARGS__,16,15,14,13,12,11,10,9,   \
  6.                                       8,7,6,5,4,3,2,1,0)
  7.             
  8. #define __CONNECT2(__A, __B)                        __A##__B
  9. #define __CONNECT3(__A, __B, __C)                   __A##__B##__C
  10. #define __CONNECT4(__A, __B, __C, __D)              __A##__B##__C##__D
  11. #define __CONNECT5(__A, __B, __C, __D, __E)         __A##__B##__C##__D##__E
  12. #define __CONNECT6(__A, __B, __C, __D, __E, __F)    __A##__B##__C##__D##__E##__F
  13. #define __CONNECT7(__A, __B, __C, __D, __E, __F, __G)                           \
  14.                                                     __A##__B##__C##__D##__E##__F##__G
  15. #define __CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)                      \
  16.                                                     __A##__B##__C##__D##__E##__F##__G##__H
  17. #define __CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)                 \
  18.                                                     __A##__B##__C##__D##__E##__F##__G##__H##__I
  19.                                                    
  20. #define CONNECT2(__A, __B)                  __CONNECT2(__A, __B)
  21. #define CONNECT3(__A, __B, __C)             __CONNECT3(__A, __B, __C)
  22. #define CONNECT4(__A, __B, __C, __D)        __CONNECT4(__A, __B, __C, __D)
  23. #define CONNECT5(__A, __B, __C, __D, __E)   __CONNECT5(__A, __B, __C, __D, __E)      
  24. #define CONNECT6(__A, __B, __C, __D, __E, __F)                                  \
  25.                                             __CONNECT6(__A, __B, __C, __D, __E, __F)
  26. #define CONNECT7(__A, __B, __C, __D, __E, __F, __G)                             \
  27.                                             __CONNECT7(__A, __B, __C, __D, __E, __F, __G)
  28. #define CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)                        \
  29.                                             __CONNECT8(__A, __B, __C, __D, __E, __F, __G, __H)
  30. #define CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)                   \
  31.                                             __CONNECT9(__A, __B, __C, __D, __E, __F, __G, __H, __I)
  32.       
  33. #define CONNECT(...)                                                            \
  34.             CONNECT2(CONNECT, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)
  35.             
  36.             

  37. #define __using1(__declare)                                                     \
  38.             for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL;          \
  39.                  CONNECT3(__using_, __LINE__,_ptr)++ == NULL;                   \
  40.                 )

  41. #define __using2(__declare, __on_leave_expr)                                    \
  42.             for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL;          \
  43.                  CONNECT3(__using_, __LINE__,_ptr)++ == NULL;                   \
  44.                  __on_leave_expr                                                \
  45.                 )

  46. #define __using3(__declare, __on_enter_expr, __on_leave_expr)                   \
  47.             for (__declare, *CONNECT3(__using_, __LINE__,_ptr) = NULL;          \
  48.                  CONNECT3(__using_, __LINE__,_ptr)++ == NULL ?                  \
  49.                     ((__on_enter_expr),1) : 0;                                  \
  50.                  __on_leave_expr                                                \
  51.                 )
  52.                
  53. #define __using4(__dcl1, __dcl2, __on_enter_expr, __on_leave_expr)              \
  54.             for (__dcl1, __dcl2, *CONNECT3(__using_, __LINE__,_ptr) = NULL;     \
  55.                  CONNECT3(__using_, __LINE__,_ptr)++ == NULL ?                  \
  56.                     ((__on_enter_expr),1) : 0;                                  \
  57.                  __on_leave_expr                                                \
  58.                 )
  59.                
  60. #define using(...)                                                              \
  61.             CONNECT2(__using, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)


  62. #define safe_atom_code()                                                        \
  63.             using(  uint32_t CONNECT2(temp,__LINE__) = __disable_irq(),         \
  64.                     __set_PRIMASK(CONNECT2(temp,__LINE__)))

  65. #define __with2(__type, __addr)                                                 \
  66.             using(__type *_p=(__addr))
  67. #define __with3(__type, __addr, __item)                                         \
  68.             using(__type *_p=(__addr), *__item = _p, _p=_p, )

  69. #define with(...)                                                               \
  70.             CONNECT2(__with, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)

  71. #undef _
  72. #define _       (*_p)

  73. #ifndef dimof
  74. #   define dimof(__array)          (sizeof(__array)/sizeof(__array[0]))
  75. #endif

  76. #define foreach2(__type, __array)                                               \
  77.             using(__type *_p = __array)                                         \
  78.             for (   uint_fast32_t CONNECT2(count,__LINE__) = dimof(__array);    \
  79.                     CONNECT2(count,__LINE__) > 0;                               \
  80.                     _p++, CONNECT2(count,__LINE__)--                            \
  81.                 )

  82. #define foreach3(__type, __array, __item)                                       \
  83.             using(__type *_p = __array, *__item = _p, _p = _p, )                \
  84.             for (   uint_fast32_t CONNECT2(count,__LINE__) = dimof(__array);    \
  85.                     CONNECT2(count,__LINE__) > 0;                               \
  86.                     _p++, __item = _p, CONNECT2(count,__LINE__)--               \
  87.                 )

  88. #define foreach(...)                                                            \
  89.             CONNECT2(foreach, __PLOOC_VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)

  90. #ifndef safe_atom_code
  91. #   define safe_atom_code()                                                     \
  92.             using(  uint32_t CONNECT2(temp,__LINE__) = __disable_irq(),         \
  93.                     __set_PRIMASK(CONNECT2(temp,__LINE__)))
  94. #endif
复制代码


perf_counter-main.zip

71.01 KB, 下载次数: 9

表征Cortex-M systick的性能

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2021-1-26 07:28:59 | 显示全部楼层
帮顶。
回复

使用道具 举报

2

主题

62

回帖

68

积分

初级会员

积分
68
发表于 2021-1-29 13:49:09 | 显示全部楼层
uint32_t temp__LINE__ = __disable_irq();
__set_PRIMASK(temp__LINE__);

就等于 这两条语句
回复

使用道具 举报

0

主题

26

回帖

26

积分

新手上路

积分
26
发表于 2023-4-20 00:25:46 | 显示全部楼层
预编译后生成代码如下
for循环执行一次,执行前关中断(查了一下,temp123 = __disable_irq()返回关闭中断之前的中断状态,这样的话应该是可以嵌套的),执行后开中断
2.png
1.png
回复

使用道具 举报

38

主题

194

回帖

318

积分

高级会员

积分
318
发表于 2023-11-25 17:08:52 | 显示全部楼层
应该是不同的变量给不一样的命名用的吧。
1.png
回复

使用道具 举报

75

主题

683

回帖

908

积分

金牌会员

积分
908
发表于 2023-11-25 22:22:00 | 显示全部楼层
会飞的猪_2020 发表于 2023-11-25 17:08
应该是不同的变量给不一样的命名用的吧。

应该是根据不同的输入执行不同的操作。在Marlin里面看到过,虽然看起来很高大上也很适用,但是不适合用于项目,很难理解。如果确实想用的话不要深究其实现原理,知道怎么用就好
回复

使用道具 举报

0

主题

4

回帖

4

积分

新手上路

积分
4
发表于 2023-11-27 15:08:58 | 显示全部楼层
个人理解,这个宏的作用是让代码工作在临界区:获取当前全局中断状态---关闭中断---执行代码---恢复中断

[C] 纯文本查看 复制代码
for (uint32_t tempxxx = __disable_irq(), *ptrxxx = NULL; ptrxxx++ != NULL; __set_PRIMASK(tempxxx)) {
    // 执行代码
}


其中,xxx是使用宏时所在行号,使用宏连接符##将temp与行号连接起来,即temp##__LINE__,当__LINE__等于123时,就是temp123,ptrxxx也是同理。

回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-28 15:22 , Processed in 0.257034 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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