gcrt1.S:195:`__bad_interrupt'的多重定义

时间:2014-01-19 15:28:42

标签: c gcc avr-gcc

this question相关,但采用不同的方法。

我正在尝试重现这个4-key-keyboard ,为此我试图通过在我的Linux机器上用avr-gcc编译来编译its source

要解决当前版本的avr-gcc的编译器问题,我下载了V-USB库的latest release (20121206),将旧版本usbdrv替换为新版本usbdrv 4键键盘源树。

要编译代码,我将main.c中的第105行从PROGMEM char更改为PROGMEM const char,并使用以下命令编译源代码:

avr-gcc main.c -I /usr/lib/avr/include/ -mmcu=attiny85 -DF_CPU=16000000 -Os -I ./usbdrv -I . usbdrv/usbdrv.c usbdrv/usbdrvasm.S -o main.o

据我所知,下一步是创建一个.elf文件。我使用以下命令:

avr-gcc -I /usr/lib/avr/include/ -mmcu=attiny85 -DF_CPU=16000000 -Os -I ./usbdrv -I . -o main.elf main.o

但它会引发错误:

main.o: In function `__bad_interrupt':
../../../../crt1/gcrt1.S:195: multiple definition of `__bad_interrupt'
/usr/lib/gcc/avr/4.7.2/../../../avr/lib/avr25/crttn85.o:../../../../crt1/gcrt1.S:195: first defined here
main.o: In function `__vectors':
../../../../crt1/gcrt1.S:52: multiple definition of `__vectors'
/usr/lib/gcc/avr/4.7.2/../../../avr/lib/avr25/crttn85.o:../../../../crt1/gcrt1.S:195: first defined here
collect2: error: ld returned 1 exit status

__bad_interrupt__vectors都是指微控制器的中断向量表。它似乎是标准avr库的一个问题/误用,但我无法弄清楚它们将如何连接两次。事实上,我甚至无法在我的系统上找到名为gcrt1.S的文件。

问题是:我如何解决这些错误以及原因是什么?

编辑:似乎在第二个avr-gcc命令中添加-nostartfiles标志可以解决问题,但为什么在编译时需要包含该参数之前我从未遇到过这个问题对于AVR?当我将标志添加到我自己的一个简单的ATtiny程序时,不再包含向量表。 (感谢@angelatlarge)

所以新问题:为什么需要这个-nostartfiles参数,是什么原因引起的?

1 个答案:

答案 0 :(得分:1)

您已在第一步中完全编译了代码。如果您想稍后更改或添加目标文件,则应编译可重定位的代码。换句话说,在你的第一个命令中你应该添加-c标志(注意你必须为每个带-c的文件单独运行gcc,如果用-c编译,你不能提供超过1个文件)。 / p>

在这种情况下,它似乎没有必要,但您可以直接从第一步继续而不使用-c标志。在执行第1步(不使用-c)之后,您需要执行的操作就像avr-objcopy一样,将所有内容发送到intel hex文件(.hex)或您使用的二进制格式,然后再将代码上传到芯片。

现在,如果你想进一步了解编译过程中发生的事情以及编译WITH -c与之间的区别,我建议如下。制作一个非常简单的源文件,例如:

int main(void)
{
     while(1);
}

假设你调用了上面的源代码示例test.c并编译了两次:

avr-gcc -c -mmcu=attiny85 -o test-with-c.o
avr-gcc -mmcu-attiny85 -o test-no-c.o

然后转储这两个文件:

avr-objdump -DSx test-no-c.o > test-no-c.dmp
avr-objdump -DSx test-with-c.o > test-with-c.dmp

现在打开vim,gedit等中的转储文件并进行比较。现在你应该能够解释为什么你们不能将两个目标文件链接在一起,如果它们都是在没有重定位标志的情况下编译的(这是你试图用的第二个命令)。