Ale*_*lex 6 c c++ macros metaprogramming arduino
有没有办法用宏重复C代码N次?N也是一个宏.
例如,如果我有这个宏:
#define N 5
#define COODE "nop\n\t"
#define REPEAT [...]
Run Code Online (Sandbox Code Playgroud)
当我调用repeat时,预处理器会将CODE写入N次,所以
__asm__(REPEAT);
Run Code Online (Sandbox Code Playgroud)
会成为
__asm__("nop\n\t""nop\n\t""nop\n\t""nop\n\t""nop\n\t");
Run Code Online (Sandbox Code Playgroud)
我有一个Arduino,必须等待一个精确(和小,约10-15)的时钟数.每个"nop"(无操作)只需要执行1个时钟周期,它什么都不做.我不能只做一个循环,因为每个循环都在多个操作中执行(初始化计数器,递增计数器,检查是否到达结束),所以不要手动写"nop \n\t"我不喜欢有一个宏.这样我也可以简单地改变N来修改程序而不重写它.
先感谢您
如果您想在不包含整个库或使用define的情况下执行此操作,则可以使用简单的递归模板:
//By Christopher Andrews, released under MIT licence.
template< unsigned N > struct Nops{
static void generate() __attribute__((always_inline)){
__asm__ volatile ("nop");
Nops< N - 1 >::generate();
}
};
template<> struct Nops<0>{ static inline void generate(){} };
void setup() {
Nops<10>::generate();
}
void loop(){}
Run Code Online (Sandbox Code Playgroud)
这将生成所需的确切数量的nop.
0000010a设置:
10a:00 00 nop
10c:00 00 nop
10e:00 00 nop
110:00 00 nop
112:00 00 nop
114:00 00 nop
116:00 00 nop
118:00 00 nop
11a:00 00 nop
11c: 00 00 nop
11e:08 95 ret
我在Arduino的TFT驱动程序中使用了这种方法.
还有另一种方法可以在使用avr-gcc编译的AVR上轻松完成此操作.我假设这可能不适用于较旧的工具链.
为了延迟执行特定数量的周期,GCC实现了
void __builtin_avr_delay_cycles (unsigned long ticks)ticks是延迟执行的滴答数.请注意,此内置功能未考虑可能会增加延迟时间的中断的影响.ticks必须是编译时整数常量; 不支持具有可变循环次数的延迟
从这里:https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/AVR-Built_002din-Functions.html
以下代码适用于 GNU C,
#define NOP __asm__("nop")
#define ten(a) a;a;a;a;a;a;a;a;a;a
#define hundred(a) ten(ten(a))
int
main()
{
hundred(NOP);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译和调试:
code@lab:~/debug$ gcc -g -o debug_NOP debug_NOP.c
code@lab:~/debug$ gdb -q --nh debug_NOP
Reading symbols from debug_NOP...done.
(gdb) set disassembly-flavor intel
(gdb) start
Temporary breakpoint 1 at 0x664: file debug_NOP.c, line 10.
Starting program: /home/code/debug/debug_NOP
Temporary breakpoint 1, main () at debug_NOP.c:10
10 hundred(NOP);
(gdb) disassemble
Dump of assembler code for function main:
0x0000555555554660 <+0>: push rbp
0x0000555555554661 <+1>: mov rbp,rsp
=> 0x0000555555554664 <+4>: nop
0x0000555555554665 <+5>: nop
0x0000555555554666 <+6>: nop
0x0000555555554667 <+7>: nop
0x0000555555554668 <+8>: nop
0x0000555555554669 <+9>: nop
....
0x00005555555546c6 <+102>: nop
0x00005555555546c7 <+103>: nop
0x00005555555546c8 <+104>: mov eax,0x0
0x00005555555546cd <+109>: pop rbp
0x00005555555546ce <+110>: ret
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)