2016-06-11 45 views
1

在我的Atmel ASF项目中,我正尝试构建以下内联asm代码。然而,我在编译时遇到了不可能的约束。编译时在asm中的不可约束

编译指向这一行__asm__ __volatile__, 我错过了什么?

#define OUTPORT PORTD 
#define OUTBIT 3  // PD.3 
uint8_t rport ,rbits; 
uint8_t *buf = message; 
asm volatile( "in  __tmp_reg__, __SREG__    \n\t" // 1 Save SREG for later 
       "cli          \n\t" // 1 Clear interrupts 
       "in  %[rport], %[port]     \n\t" // 1 Move PORTB adress to rport 

       : //Outputs 
       [rport] "=&r" (rport) 

       : //Inputs 
       [port] "I" (_SFR_IO_ADDR(OUTPORT))  // Adress to port register, 6-bit positive constant 

       : //Clobber list (compiler must restore) 

       "r0"          // This is __tmp_reg__ 
); 
  1. 是什么摧毁了这个版本?
  2. 我不知道asm语法是不正确的吗?我一直在关注this manual
+0

这是非常高效的内联汇编。确保你需要asm,如果你确实考虑把它放在一个单独的asm文件中而不是内联。会节省很多头痛。 – Jester

+0

这是一个可笑的漫长的宏。为什么不把它作为一个函数,并把它放在一个汇编文件中?那么它甚至不需要变化。鉴于所有的呼吁和故意拖延,它怎么可能受伤?然后你会得到合理的诊断。如果这被称为不止一次,你的代码会变得更小。 – DigitalRoss

+0

_SFR_IO_ADDR(OUTPORT)实际上是介于0和63之间的值吗? –

回答

1

PORTD,在ATxmega128A4U,在地址0x0660,在其62 datasheet, 页陈述因此,端口不给in指令访问。 您应该使用lds而是与约束

[port] "i" (_SFR_MEM_ADDR(OUTPORT)) 

注意小写的“i”。

附录:我只是想编译如下:

#include <avr/io.h> 

void test(void) 
{ 
    uint8_t rport; 

    asm volatile(
     "in __tmp_reg__, __SREG__ \n\t" 
     "cli      \n\t" 
     "lds %[rport], %[port]  \n\t" 
     : [rport] "=&r" (rport)    // output 
     : [port] "i" (_SFR_MEM_ADDR(PORTD)) // input 
     : "r0"        // clobber 
    ); 
} 

使用AVR-GCC 4.9.2与我得到的 正确生成的代码并没有警告,甚至-Wall -Wextra选项-mmcu=atxmega128a4u -c

“我”约束是 documented 在表示“整数立即数”,而"I" means “恒大于-1,小于64”。

+0

小写“i”约束对于编译器来说是不知道的,如果我在代码段使用lds,它会抱怨操作数。 – Artec

+0

@Artec:avr-gcc 4.9.2确实支持“i”约束。看修改后的答案。 –

+0

由于这只是一个正常的负载,所以实际上并不需要内联asm来从中加载。只是'volatile char * portd =(char *)_ SFR_MEM_ADDR(PORTD)'。 –