我正在尝试使用 avr-gnu 编译器在代码块下编译 arduino 代码。我收到此错误:
avr-ld.exe unrecognized emulation mode: mcu=atmega328p.
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
我找到了这个页面:https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html这表明它应该在avr5 sim模式下链接,所以我在链接器选项中添加了 -mmcu=avr5 。现在我得到:
avr-ld.exe unrecognized emulation mode: mcu=avr5
Supported emulations:avr2 avr1 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega1 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny
支持avr5怎么不识别?o0 我尝试了几年来的几种不同的工具链,但似乎链接器无法正确解释此模拟模式。较新的工具链支持 328p,但仍然无法正常工作。我还尝试创建专用于 Arduino 的 CodeBlocks 项目,但不同之处在于它本身传递了 -mmcu=atmega328p ,但仍然无法在此工具链或更新的工具链上工作。 更新: 我在这里完全缺少一些东西。我将链接器更改为 Mingw 的标准 x86 32 ld.exe 并传递 -mmcu=i386pe,我收到类似的错误:
ld.exe unrecognized emulation mode: mcu=i386pe
Supported emulations:i386pe
所以这只会导致我对如何选择/配置链接器模拟模式的机制缺乏了解。
几乎在任何情况下,您都不想手动调用链接器(
ld
或 avr-ld
)!
使用
avr-gcc
链接您的程序!
请注意,
avr-gcc
本身并不是编译器,它只是一个驱动程序,调用子程序,如编译器本身(cc1
用于C,cc1plus
用于C++,lto1
用于LTO编译的字节码) 、汇编器和链接器,具体取决于命令行选项和命令行上提供的输入文件。
avr-gcc
知道如何为相应的工具提供适当的命令行选项,例如:仿真、库、包含和库的路径、启动代码、子选项等。
为了查看
avr-gcc
调用了哪些工具,请添加 -v
选项。例如,对于一个简单的编译命令
> avr-gcc -v main.c -mmcu=atmega328p -save-temps
您会看到类似的内容(此处为 avr-gcc v8.5.0):
...
COLLECT_GCC_OPTIONS='-v' '-save-temps' '-specs=device-specs/specs-atmega328p' '-mmcu=avr5'
$AVRGCC_HOME/bin/../libexec/gcc/avr/8.5.0/collect2 <many options> -plugin-opt=-pass-through=-latmega328p -mavr5 -Tdata 0x800100 $AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5/crtatmega328p.o -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib/avr5 -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0 -L$AVRGCC_HOME/bin/../lib/gcc -L$AVRGCC_HOME/bin/../lib/gcc/avr/8.5.0/../../../../avr/lib main.o --start-group -lgcc -lm -lc -latmega328p --end-group
collect2
只是包装对 ld
调用的其他工具。如果您想看到真实的东西,请使用avr-gcc ... -v -Wl,-v
。
链接器的正确模拟是由位于编译器安装目录中的
device-specs/specs-atmega328p
的设备特定规范文件 ./lib/gcc/avr/$version
确定的。规范“语言”是描述选项映射的一种方式;特别是负责将 -mmcu=atmega328p
映射到正确仿真的位是
*link_arch:
%{mmcu=*:-m%*}
...
*self_spec:
%{!mmcu=avr*: %<mmcu=* -mmcu=avr5} %<mshort-calls %<msp8
self_spec
从命令行中删除-mmcu=*
并设置-mmcu=avr5
,这是ATmega328P的核心系列。然后,作为链接器调用的一部分,link_arch
将 -mmcu=avr5
映射到 -mavr5
,这是要使用的链接器模拟。