Linux上的Arduino:深入研究项目的精髓

引言


上一篇文章中 ,描述了将Qt Creator变成用于Arduino平台上项目的成熟IDE的过程。 详细描述了这些步骤,但没有描述所发生情况的含义,因此此类文章的作用很小。 在每种情况下,都会出现细微差别,并且在不了解项目安排的情况下很难理解它们。

因此,在本文中,我们将了解项目的结构和设置。

1. Arduino Core和main()函数


如您所知,在C / C ++中,任何程序的执行都从main()函数开始,包括微控制器固件。 此功能以一种或另一种形式存在于任何项目中。 在Arduino IDE中创建项目时,我们会立即提供一个草图文件(扩展名为* .ino),向开发人员隐藏入口点的位置。

在Arch中,Arduino Core源代码位于/ usr / share / arduino / hardware / archlinux-arduino / avr / cores / arduino路径中,并包含以下内容

Arduino Core文件列表
$ ls -l  320 -rw-r--r-- 1 root root 1222  3 2017 abi.cpp -rw-r--r-- 1 root root 7483  3 2017 Arduino.h -rw-r--r-- 1 root root 11214  3 2017 binary.h -rw-r--r-- 1 root root 8078  9 2017 CDC.cpp -rw-r--r-- 1 root root 1529  3 2017 Client.h -rw-r--r-- 1 root root 2605  3 2017 HardwareSerial0.cpp -rw-r--r-- 1 root root 2315  3 2017 HardwareSerial1.cpp -rw-r--r-- 1 root root 1975  3 2017 HardwareSerial2.cpp -rw-r--r-- 1 root root 1975  3 2017 HardwareSerial3.cpp -rw-r--r-- 1 root root 7743  3 2017 HardwareSerial.cpp -rw-r--r-- 1 root root 5262  3 16:57 HardwareSerial.h -rw-r--r-- 1 root root 4469  3 2017 HardwareSerial_private.h -rw-r--r-- 1 root root 1142  3 2017 hooks.c -rw-r--r-- 1 root root 2851  3 2017 IPAddress.cpp -rw-r--r-- 1 root root 2861  3 2017 IPAddress.h -rw-r--r-- 1 root root 1372  3 2017 main.cpp -rw-r--r-- 1 root root 1027  3 2017 new.cpp -rw-r--r-- 1 root root 979  3 2017 new.h -rw-r--r-- 1 root root 2725  3 2017 PluggableUSB.cpp -rw-r--r-- 1 root root 2063  3 2017 PluggableUSB.h -rw-r--r-- 1 root root 1335  3 2017 Printable.h -rw-r--r-- 1 root root 5442  3 2017 Print.cpp -rw-r--r-- 1 root root 2963  3 16:57 Print.h -rw-r--r-- 1 root root 963  3 2017 Server.h -rw-r--r-- 1 root root 8804  3 17:23 Stream.cpp -rw-r--r-- 1 root root 6060  3 17:23 Stream.h -rw-r--r-- 1 root root 15022  3 2017 Tone.cpp -rw-r--r-- 1 root root 4363  18 16:52 Udp.h -rw-r--r-- 1 root root 6261  3 16:57 USBAPI.h -rw-r--r-- 1 root root 20086  18 16:52 USBCore.cpp -rw-r--r-- 1 root root 8435  3 2017 USBCore.h -rw-r--r-- 1 root root 1519  3 2017 USBDesc.h -rw-r--r-- 1 root root 4576  3 2017 WCharacter.h -rw-r--r-- 1 root root 9409  3 2017 WInterrupts.c -rw-r--r-- 1 root root 7850  3 2017 wiring_analog.c -rw-r--r-- 1 root root 12024  3 2017 wiring.c -rw-r--r-- 1 root root 4978  3 2017 wiring_digital.c -rw-r--r-- 1 root root 2255  3 2017 wiring_private.h -rw-r--r-- 1 root root 3435  3 2017 wiring_pulse.c -rw-r--r-- 1 root root 6022  3 2017 wiring_pulse.S -rw-r--r-- 1 root root 1550  3 2017 wiring_shift.c -rw-r--r-- 1 root root 1641  3 2017 WMath.cpp -rw-r--r-- 1 root root 16989  3 2017 WString.cpp -rw-r--r-- 1 root root 9910  3 2017 WString.h 


main()函数位于main.cpp文件中,如下所示

 #include <Arduino.h> // Declared weak in Arduino.h to allow user redefinitions. int atexit(void (* /*func*/ )()) { return 0; } // Weak empty variant initialization function. // May be redefined by variant files. void initVariant() __attribute__((weak)); void initVariant() { } void setupUSB() __attribute__((weak)); void setupUSB() { } int main(void) { init(); initVariant(); #if defined(USBCON) USBDevice.attach(); #endif setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; } 

可以看出,草图中没有超自然的东西:setup()和loop()函数直接从main()调用。 我们之前创建的led-blink.cpp文件包含这些函数的定义。 如果我们从项目中删除此文件

 #  #INCLUDEPATH += ./include #HEADERS += $$files(./include/*.h) #   #SOURCES += $$files(./src/*.cpp) 

我们收到逻辑链接器错误



因此,我们添加到项目中的所有模块都将与Arduino核心链接,该核心实现了基本功能。 这是Arduino Core标头的简要说明:

  • Arduino.h-基本标头,包括标准C库的标头,AVR控制器寄存器的程序接口的定义,编程中使用的基本宏定义
  • binary.h-宏定义,用于以二进制形式写入从0到255的数字
  • Client.h-以太网客户端类
  • HardwareSerial.h,HardwareSerial_private.h-使用硬件UART的库
  • IPAddress.h-使用以太网协议的IP地址
  • new.h-new和delete C ++运算符的实现
  • PluggableUSB.h,USBAPI.h,USBCore.h,USBDesc.h-用于实现USB设备的库
  • Print.h,Printable.h,Stream.h-用于处理符号数据流(包括通过UART传输的符号数据流)的库
  • Server.h-实现Eternet服务器的类
  • udp.h-UDP协议实现
  • WCharacters.h,WString.h-用于处理字符和字符串的类
  • connection_private.h- Wiring平台的库,基于此库构建了Arduino Core。 该库为微控制器的系统资源实现了一个相对高级的接口。

因此,即使在最简单的LED闪烁程序中,也包含许多不必要的代码。 这是易于开发且入门门槛低的价格。 但是,谈到这一点,我很狡猾:上一篇文章中显示的示例与在Arduino IDE中进行组装后获得的示例不符。

2.减少固件中的脂肪


在Arduino中,IDE核心被组装到一个单独的静态core.a库中,然后与草图目标文件链接成一个现成的二进制文件。 我们将在Qt Creator中执行相同的操作。

使用以下结构创建一个核心项目



下面显示了此项目的qmake脚本:

core.pro
 #      DESTDIR = ../../lib TARGET = core #    INCLUDEPATH += $$ARDUINO_DIR/cores/arduino INCLUDEPATH += $$ARDUINO_DIR/variants/standard INCLUDEPATH += $$ARDUINO_DIR/libraries INCLUDEPATH += /usr/avr/include #   C QMAKE_CC = /usr/bin/avr-gcc QMAKE_CFLAGS += -c -g -Os -w -ffunction-sections -fdata-sections QMAKE_CFLAGS += -MMD -mmcu=$$ARDUINO_MCU -DF_CPU=$$ARDUINO_FCPU QMAKE_CFLAGS += -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR #   C++ QMAKE_CXX = /usr/bin/avr-g++ QMAKE_CXXFLAGS += -c -g -Os -w -ffunction-sections -fdata-sections QMAKE_CXXFLAGS += -fno-exceptions -fno-threadsafe-statics QMAKE_CXXFLAGS += -MMD -mmcu=$$ARDUINO_MCU -DF_CPU=$$ARDUINO_FCPU QMAKE_CXXFLAGS += -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR #  Arduino Core HEADERS += $$files($$ARDUINO_DIR/cores/arduino/*.h) HEADERS += $$files($$ARDUINO_DIR/variants/standard/*.h) #  Arduino Core SOURCES += $$files($$ARDUINO_DIR/cores/arduino/*.c) SOURCES += $$files($$ARDUINO_DIR/cores/arduino/*.cpp) 

该项目仅包含Arduino Core代码。 它的程序集提供libcore.a库输出

现在,接下来创建一个包含草图代码的固件项目。



blink.pro
 #     #    Arduino Core ARDUINO_DIR=/usr/share/arduino/hardware/archlinux-arduino/avr/ #    (Arduino Uno, Nano, Mini) ARDUINO_MCU=atmega328p #    ARDUINO_FCPU = 16000000L #  ,   Qt   ! QT -= gui core CONFIG -= qt #   - ,      ELF TEMPLATE = app #      DESTDIR = ../../bin TARGET = blink #    INCLUDEPATH += $$ARDUINO_DIR/cores/arduino INCLUDEPATH += $$ARDUINO_DIR/variants/standard INCLUDEPATH += $$ARDUINO_DIR/libraries INCLUDEPATH += /usr/avr/include #   C QMAKE_CC = /usr/bin/avr-gcc QMAKE_CFLAGS += -c -g -Os -w -ffunction-sections -fdata-sections QMAKE_CFLAGS += -MMD -mmcu=$$ARDUINO_MCU -DF_CPU=$$ARDUINO_FCPU QMAKE_CFLAGS += -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR #   C++ QMAKE_CXX = /usr/bin/avr-g++ QMAKE_CXXFLAGS += -c -g -Os -w -ffunction-sections -fdata-sections QMAKE_CXXFLAGS += -fno-exceptions -fno-threadsafe-statics QMAKE_CXXFLAGS += -MMD -mmcu=$$ARDUINO_MCU -DF_CPU=$$ARDUINO_FCPU QMAKE_CXXFLAGS += -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR #   QMAKE_LINK = /usr/bin/avr-gcc QMAKE_LFLAGS = -w -Os -Wl,--gc-sections -mmcu=$$ARDUINO_MCU QMAKE_LIBS = -lm #  QMAKE_POST_LINK += /usr/bin/avr-objcopy -O ihex -j .text -j .data -S ${TARGET} ${TARGET}.hex LIBS += -L../../lib -lcore #  INCLUDEPATH += ./include HEADERS += $$files(./include/*.h) #   SOURCES += $$files(./src/*.cpp) 


眨眼
 #ifndef LED_BLINK_H #define LED_BLINK_H #include <Arduino.h> #endif // LED_BLINK_H 


blink.cpp
 #include "blink.h" #define LED_STAND_PIN 13 unsigned long time = 0; unsigned long DELAY = 1000000; bool on = false; //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void setup() { pinMode(LED_STAND_PIN, OUTPUT); } //------------------------------------------------------------------------------ // //------------------------------------------------------------------------------ void loop() { if ( micros() >= time + DELAY ) { time = micros(); on = !on; } uint8_t state = on ? HIGH : LOW; digitalWrite(LED_STAND_PIN, state); } 


我们将使用qmake中可用的项目类型“子目录”将两个项目收集在一起

led-blink2.pro
 TEMPLATE = subdirs SUBDIRS += ./core SUBDIRS += ./blink 


我们组装项目,在板上运行它并查看固件日志

Blink.hex固件日志
 avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.00s avrdude: Device signature = 0x1e950f (probably m328p) avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: reading input file "/mnt/data/Arduino/led-blink2/bin/blink.hex" avrdude: writing flash (1040 bytes): Writing | ################################################## | 100% 0.18s avrdude: 1040 bytes of flash written avrdude: verifying flash memory against /mnt/data/Arduino/led-blink2/bin/blink.hex: avrdude: load data flash data from input file /mnt/data/Arduino/led-blink2/bin/blink.hex: avrdude: input file /mnt/data/Arduino/led-blink2/bin/blink.hex contains 1040 bytes avrdude: reading on-chip flash data: Reading | ################################################## | 100% 0.15s avrdude: verifying ... avrdude: 1040 bytes of flash verified avrdude: safemode: Fuses OK (E:00, H:00, L:00) avrdude done. Thank you. 


在这里,我们注意占用的内存量。

 avrdude: verifying ... avrdude: 1040 bytes of flash verified 

是的,该固件已经是1040字节,而上一篇文章中的项目是2838字节。 但是,Arduino IDE中的类似草图仍需要882个字节。 在仔细研究了Arduino环境的构建日志之后,我们将C编译器密钥添加到了眨眼和核心项目中

 QMAKE_CFLAGS += -flto -fno-fat-lto-objects 

和C ++编译器密钥

 QMAKE_CXXFLAGS += -fpermissive -flto -fno-devirtualize -fno-use-cxa-atexit 

我们重建,缝制,发射和...

 avrdude: verifying ... avrdude: 882 bytes of flash verified 

好的,令人梦以求的882个字节。 是什么使这种情况发生?

首先,让我们看一下在当前项目和先前项目的汇编过程中获得的ELF文件,即,我们将注意符号信息,这将使您从Arduino Core的功能和类中得出一个以二进制形式结束的想法。 发出命令

 $ avr-objdump -t led-blink 

LED闪烁字符表
 led-blink:   elf32-avr SYMBOL TABLE: 00800100 ld .data 00000000 .data 00000000 ld .text 00000000 .text 00800122 ld .bss 00000000 .bss 00000000 ld .stab 00000000 .stab 00000000 ld .stabstr 00000000 .stabstr 00000000 ld .comment 00000000 .comment 00000000 ld .note.gnu.avr.deviceinfo 00000000 .note.gnu.avr.deviceinfo 00000000 ld .debug_info 00000000 .debug_info 00000000 ld .debug_abbrev 00000000 .debug_abbrev 00000000 ld .debug_line 00000000 .debug_line 00000000 ld .debug_str 00000000 .debug_str 00000000 l df *ABS* 00000000 WInterrupts.c 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000112 l F .text 00000002 nothing 00800100 l O .data 00000004 intFunc 00000000 l df *ABS* 00000000 HardwareSerial.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000000 l df *ABS* 00000000 IPAddress.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 0000078a l F .text 00000016 _GLOBAL__sub_I_IPAddress.cpp 008001c8 l O .bss 00000006 _ZL11INADDR_NONE 00000000 l df *ABS* 00000000 Tone.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 0080011c l O .data 00000001 _ZL9tone_pins 000000b8 l O .text 00000001 _ZL21tone_pin_to_timer_PGM 00000000 l df *ABS* 00000000 led-blink.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000000 l df *ABS* 00000000 wiring_digital.c 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000304 l F .text 00000052 turnOffPWM 00000000 l df *ABS* 00000000 HardwareSerial0.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000694 l F .text 0000005a _GLOBAL__sub_I_HardwareSerial0.cpp 00000000 l df *ABS* 00000000 _clear_bss.o 000000ea l .text 00000000 .do_clear_bss_start 000000e8 l .text 00000000 .do_clear_bss_loop 00000000 l df *ABS* 00000000 wiring.c 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00800122 l O .bss 00000001 timer0_fract 00000000 l df *ABS* 00000000 main.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 00000000 l df *ABS* 00000000 Print.cpp 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 0000081e l F .text 0000001e _ZN5Print5writeEPKc.part.2 00000000 l df *ABS* 00000000 _udivmodsi4.o 00000ac6 l .text 00000000 __udivmodsi4_ep 00000aac l .text 00000000 __udivmodsi4_loop 00000000 l df *ABS* 00000000 _exit.o 00000af2 l .text 00000000 __stop_program 00000000 l df *ABS* 00000000 hooks.c 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 0000010e w .text 00000000 __vector_22 00800127 g O .bss 00000004 timer0_overflow_count 0000094a g F .text 0000002a _Z6noToneh 00000772 g F .text 00000018 _ZN9IPAddressC1Ehhhh 000000ae g O .text 0000000a port_to_mode_PGM 00000114 g F .text 0000004e __vector_1 0000ffa0 g *ABS* 00000000 __DATA_REGION_LENGTH__ 00800123 g O .bss 00000004 timer0_millis 00000442 g F .text 0000001c _ZN14HardwareSerial4peekEv 0000084a g F .text 00000098 _ZN5Print11printNumberEmh 000007c4 g F .text 0000005a _ZN5Print5writeEPKhj 00000068 g .text 00000000 __trampolines_start 008001cf g O .bss 00000002 timer2_pin_port 00000af4 g .text 00000000 _etext 0000042a g F .text 00000018 _ZN14HardwareSerial9availableEv 0000010e w .text 00000000 __vector_24 00000a34 g F .text 0000006c loop 000004c0 g F .text 00000042 _ZN14HardwareSerial17_tx_udr_empty_irqEv 0000010e w .text 00000000 __vector_12 000007a0 w F .text 00000002 initVariant 000006ee g F .text 00000084 _ZNK9IPAddress7printToER5Print 00000542 g F .text 0000008e _ZN14HardwareSerial5writeEh 0000010e g .text 00000000 __bad_interrupt 00000b16 g *ABS* 00000000 __data_load_end 0000010e w .text 00000000 __vector_6 008001d5 g O .bss 00000001 on 00000068 g .text 00000000 __trampolines_end 0000010e w .text 00000000 __vector_3 000003ce g F .text 0000005c digitalWrite 00000356 g F .text 00000078 pinMode 00000090 g O .text 00000014 digital_pin_to_port_PGM 0000010e w .text 00000000 __vector_23 00000af4 g *ABS* 00000000 __data_load_start 000000be g .text 00000000 __dtors_end 008001da g .bss 00000000 __bss_end 00000400 g *ABS* 00000000 __LOCK_REGION_LENGTH__ 0000010e w .text 00000000 __vector_25 0000090a g F .text 00000040 _Z12disableTimerh 0000010e w .text 00000000 __vector_11 00000486 g F .text 0000001e _ZN14HardwareSerial17availableForWriteEv 000000be w .text 00000000 __init 000008fc g F .text 0000000e _ZN5Print5printEhi 00000772 g F .text 00000018 _ZN9IPAddressC2Ehhhh 000004a4 w F .text 0000001c _Z14serialEventRunv 00000502 g F .text 00000040 _ZN14HardwareSerial5flushEv 0000010e w .text 00000000 __vector_13 0000010e w .text 00000000 __vector_17 00000634 g F .text 0000004c __vector_19 00000974 g F .text 000000b8 __vector_7 0080012b g O .bss 0000009d Serial 00800104 w O .data 00000012 _ZTV14HardwareSerial 000000e0 g .text 00000010 .hidden __do_clear_bss 0000083c g F .text 0000000e _ZN5Print5printEc 00000680 g F .text 00000014 _Z17Serial0_availablev 00810000 g .stab 00000000 __eeprom_end 0000007c g O .text 00000014 digital_pin_to_bit_mask_PGM 00800116 w O .data 00000006 _ZTV9IPAddress 00000000 g .text 00000000 __vectors 00800122 g .data 00000000 __data_end 00000000 w .text 00000000 __vector_default 0000010e w .text 00000000 __vector_5 00000400 g *ABS* 00000000 __SIGNATURE_REGION_LENGTH__ 00000ae4 g .text 0000000c .hidden __tablejump2__ 0000028e g F .text 00000076 init 000000ba g .text 00000000 __ctors_start 000000ca g .text 00000016 .hidden __do_copy_data 0080011d g O .data 00000004 DELAY 00800122 g .bss 00000000 __bss_start 000007a2 g F .text 00000022 main 0000010e w .text 00000000 __vector_4 008001d6 g O .bss 00000004 time 00000244 g F .text 0000004a micros 008001ce g O .bss 00000001 timer2_pin_mask 00000000 w *ABS* 00000000 __heap_end 0000010e w .text 00000000 __vector_9 00000162 g F .text 0000004e __vector_2 00000400 g *ABS* 00000000 __USER_SIGNATURE_REGION_LENGTH__ 0000010e w .text 00000000 __vector_21 0000010e w .text 00000000 __vector_15 000000a4 g O .text 0000000a port_to_output_PGM 000008e2 g F .text 0000001a _ZN5Print5printEmi 00000a2c g F .text 00000008 setup 008001da g .stab 00000000 __heap_start 000000be g .text 00000000 __dtors_start 000000be g .text 00000000 __ctors_end 000008ff w *ABS* 00000000 __stack 00800122 g .data 00000000 _edata 008001da g .stab 00000000 _end 0000010e w .text 00000000 __vector_8 00000068 g O .text 00000014 digital_pin_to_timer_PGM 00000af0 w .text 00000000 .hidden exit 0000045e g F .text 00000028 _ZN14HardwareSerial4readEv 00000aa0 g .text 00000044 .hidden __udivmodsi4 00010000 g *ABS* 00000000 __EEPROM_REGION_LENGTH__ 00000af0 g .text 00000000 .hidden _exit 0000010e w .text 00000000 __vector_14 0000010e w .text 00000000 __vector_10 008001d1 g O .bss 00000004 timer2_toggle_count 000001b0 g F .text 00000094 __vector_16 00800100 g .data 00000000 __data_start 000005d0 g F .text 00000064 __vector_18 00000400 g *ABS* 00000000 __FUSE_REGION_LENGTH__ 00020000 g *ABS* 00000000 __TEXT_REGION_LENGTH__ 0000010e w .text 00000000 __vector_20 000000f0 g .text 00000016 .hidden __do_global_ctors 


现在与第二个项目进行比较

闪烁字符表
 blink:   elf32-avr SYMBOL TABLE: 00800100 ld .data 00000000 .data 00000000 ld .text 00000000 .text 00800100 ld .bss 00000000 .bss 00000000 ld .comment 00000000 .comment 00000000 ld .note.gnu.avr.deviceinfo 00000000 .note.gnu.avr.deviceinfo 00000000 ld .debug_info 00000000 .debug_info 00000000 ld .debug_abbrev 00000000 .debug_abbrev 00000000 ld .debug_line 00000000 .debug_line 00000000 ld .debug_str 00000000 .debug_str 00000000 l df *ABS* 00000000 0000003e l *ABS* 00000000 __SP_H__ 0000003d l *ABS* 00000000 __SP_L__ 0000003f l *ABS* 00000000 __SREG__ 00000000 l *ABS* 00000000 __tmp_reg__ 00000001 l *ABS* 00000000 __zero_reg__ 000000e0 l F .text 00000038 pinMode.constprop.1 000000a4 l O .text 00000014 digital_pin_to_bit_mask_PGM 00000090 l O .text 00000014 digital_pin_to_port_PGM 00000086 l O .text 0000000a port_to_mode_PGM 0000007c l O .text 0000000a port_to_output_PGM 00000118 l F .text 00000090 digitalWrite.constprop.0 00000068 l O .text 00000014 digital_pin_to_timer_PGM 000001a8 l F .text 00000076 init 0000021e l F .text 0000004a micros 00800105 l O .bss 00000004 timer0_overflow_count 0080010a l O .bss 00000004 time 00800109 l O .bss 00000001 on 00800101 l O .bss 00000004 timer0_millis 00800100 l O .bss 00000001 timer0_fract 00000000 l df *ABS* 00000000 _clear_bss.o 000000ce l .text 00000000 .do_clear_bss_start 000000cc l .text 00000000 .do_clear_bss_loop 00000000 l df *ABS* 00000000 _exit.o 00000370 l .text 00000000 __stop_program 000000dc w .text 00000000 __vector_22 000000dc w .text 00000000 __vector_1 0000ffa0 g *ABS* 00000000 __DATA_REGION_LENGTH__ 00000068 g .text 00000000 __trampolines_start 00000372 g .text 00000000 _etext 000000dc w .text 00000000 __vector_24 000000dc w .text 00000000 __vector_12 000000dc g .text 00000000 __bad_interrupt 00000372 g *ABS* 00000000 __data_load_end 000000dc w .text 00000000 __vector_6 00000068 g .text 00000000 __trampolines_end 000000dc w .text 00000000 __vector_3 000000dc w .text 00000000 __vector_23 00000372 g *ABS* 00000000 __data_load_start 000000b8 g .text 00000000 __dtors_end 0080010e g .bss 00000000 __bss_end 00000400 g *ABS* 00000000 __LOCK_REGION_LENGTH__ 000000dc w .text 00000000 __vector_25 000000dc w .text 00000000 __vector_11 000000b8 w .text 00000000 __init 000000dc w .text 00000000 __vector_13 000000dc w .text 00000000 __vector_17 000000dc w .text 00000000 __vector_19 000000dc w .text 00000000 __vector_7 000000c4 g .text 00000010 .hidden __do_clear_bss 00810000 g .comment 00000000 __eeprom_end 00000000 g .text 00000000 __vectors 00000000 w .text 00000000 __vector_default 000000dc w .text 00000000 __vector_5 00000400 g *ABS* 00000000 __SIGNATURE_REGION_LENGTH__ 000000b8 g .text 00000000 __ctors_start 00800100 g .bss 00000000 __bss_start 000002fc g F .text 00000072 main 000000dc w .text 00000000 __vector_4 00000000 w *ABS* 00000000 __heap_end 000000dc w .text 00000000 __vector_9 000000dc w .text 00000000 __vector_2 00000400 g *ABS* 00000000 __USER_SIGNATURE_REGION_LENGTH__ 000000dc w .text 00000000 __vector_21 000000dc w .text 00000000 __vector_15 000000b8 g .text 00000000 __dtors_start 000000b8 g .text 00000000 __ctors_end 000008ff w *ABS* 00000000 __stack 00800100 g .data 00000000 _edata 0080010e g .comment 00000000 _end 000000dc w .text 00000000 __vector_8 0000036e w .text 00000000 .hidden exit 00010000 g *ABS* 00000000 __EEPROM_REGION_LENGTH__ 0000036e g .text 00000000 .hidden _exit 000000dc w .text 00000000 __vector_14 000000dc w .text 00000000 __vector_10 00000268 g F .text 00000094 __vector_16 000000dc w .text 00000000 __vector_18 00000400 g *ABS* 00000000 __FUSE_REGION_LENGTH__ 00020000 g *ABS* 00000000 __TEXT_REGION_LENGTH__ 000000dc w .text 00000000 __vector_20 


区别是显而易见的。 可以看出,将内核编译到单独的库中时,编译器仅包含固件中实际在内核中实际使用的部分。 特别是,无论哪种情况,我们都不使用UART,但是,在第一个固件中,有使用它的类。 应该单独讨论使用编译器密钥减少固件的数量以及密钥本身

3.编译器和链接器的键


编译器选项:

  • -flto-启用布局优化。 链接的目标文件中的函数就像在同一个转换单元中一样被链接
  • -fno-fat-lto-objects-除对象代码外,不要创建包含中间语言的“胖”对象文件。 它与上一个键配合使用。
  • -fpermissive-将某些编译器错误的级别降低为警告级别。 可能导致错误的代码生成
  • -fuse-cxa-aexit-在对象析构函数中使用__cxa-atexit()函数代替atexit()
  • -ffunction-sections,-fdata-sections-将每个函数和数据放在单独的部分中,以便在后续布局中进行优化。 允许链接器在输出文件中仅包含实际功能。
  • -fno-threadsafe-statics-不要使用与线程有关的方法来处理静态类成员。 这是有道理的,因为AVR控制器只有一个执行线程
  • -fno-exceptions-不使用异常处理
  • -fno-devirtualize-不要使用“虚拟化”。 如果编译器知道对象的类型,则可以直接调用其虚拟方法,而无需使用虚拟函数表。 此选项禁用此机制。
  • -MMD-为每个翻译单元生成单独的汇编规则,并在* .d文件中为它创建依赖项列表(每个文件* .c / *。Cpp对应于具有相同名称的文件,扩展名为* .d包含依赖项路径)
  • -DARDUINO_AVR_UNO,-DARDUINO_ARCH_AVR-在宏定义ARDUINO_AVR_UNO和ARDUINO_ARCH_AVR的预处理期间创建,从而激活有条件地编译源代码的必要方向。

链接器选项:

  • -w-禁用所有警告
  • -Os-优化最终文件的大小
  • -Wl-gc-sections-激活选择性功能布局。 最终文件中仅包含使用的功能
  • -mmcu-二手控制器型号

如您所见,所有设置都减少了,以关闭应用程序编程中使用的洗剂,并提高了代码安全性,并且旨在最大程度地减少最终固件的数量。

结论


我希望本文将所有点都放在“ i”上。 Arduino平台没有什么超自然的。 它的体系结构旨在向所有新手隐藏所有机制,这种机制对于那些使用纯C或汇编程序来开发AVR软件的人来说是相当普遍的。

另外,基于Linux的arduino工作者可以很方便地工作:本文和以前的文章,出于其才干和作者的能力,着重强调了在开发普通IDE时使用便捷IDE的问题。

希望此信息对您有所帮助。 在下一篇文章中,我们可能会讨论在Qt Creator中调试AVR项目的可能性

PS:本文示例项目的源代码可在此处获取

Source: https://habr.com/ru/post/zh-CN408379/


All Articles