Arduino Building

jpfustc發表於2020-11-29

Intro

The arduino uno development board and the arduino open source ide provides a well prepared starting point for people with little experience and expertise to start doing embedded programming, and have fun with it. One must dig deeper however to become more than a entry-level player. Two strategies are to breakdown the building process performed by the ide, and to check the source code of the default functions to understand how the MCU controls its periphery through register manipulations.

Build Process

Pre-Preprocess

As explained here: the .ino/.pde file created from the development software is first converted to C++ code. All files with .ino/.ped extension are first concatenated and converted to a .cpp file. #include<Arduino.h> is added to enable the default libraries such as function digitalWrite or constant HIGH/LOW. Prototypes are auto created if missing, and #line directives are added to help with compiling error report.

#line directive is a processes directive that set the compiler’s reported line number and file name macros (__LINE__ and __NAME__)manually.

C/C++ Naming Decoration

Notice that if a .c function is called from a .cpp file, it must be declared with wrapper extern “C” {} to overcome name mangling issue. Below is an example of a C function declaration that is conpatible for both C and C++ callers.

C++ allows name overloading: functions with same name with different input/output. This was introduced by MS and then adopted by other compilers and languages. It does so by decorate the function name with unique information. For C, since overloading is not allowed, the decoration only depends on calling convention (how the parameters are passed, and how is the stack manipulated).

// MyCFuncs.h
#ifdef __cplusplus
extern "C" {  // only need to export C interface if
              // used by C++ source code
#endif

__declspec( dllimport ) void MyCFunc();
__declspec( dllimport ) void AnotherCFunc();

#ifdef __cplusplus
}
#endif

Dependency Resolve

For dependencies, arduino development tool includes the core and variant library paths ($arduino/hardware/*), the standard system directory, and the user defined library. If dependencies are not found, the development tool also searches for the installed libraries at $arduino/libraries, for which architecture compatibility must also be checked based on library.properties file. For multiple matching/partial matching of include, the tool also resolves priority problem. This can be addressed by specifying the exact file path when replacing development tool with standard C/C++ compiler.

Compiling

The preprocessed source files can now be compiled with avr-gcc/avr-g++ as arduino uses MCU with avr architectures. Sources files including .c, .cpp and .S (assembly code) are taken into account. (For dependency files the object files are reused). Finally the .o files are linked into a static library and the main script is linked against the library to create the final .hex file.

*Unlike .bin file, .hex file is a ascii file that contains the built program in text. Each line of .hex file is a “record” containing a start code “:”, 2 digit of byte count, 4 digit of address, 2 digit of record type, the data, and 2 digit of check sum. Programmer (uploader) may check the .hex file for write to invalid address and raise warning. The 4 hex digit address covers 64kB address, which is sufficient for 32kB program address for ATmega328P. Some record types are define for address extension. *

Uploading

The final uploading of the file is performed by avrdude such as:

sudo avrdude -v -p atmega328p -c arduino -P /dev/ttyACM0 -b 576000 -D -U flash:w:/home/jpfustc/projects/arduino/sketch_nov27a/sketch_nov27a.ino.standard.hex

Some basic options include:

-v      Enable verbose output.  More -v options increase verbosity level.
-p partno, i.e. MCU type
 -c programmer-id
                   Use the programmer specified by the argument.  Programmers and their pin configurations are read
                   from the config file (see the -C option).  New pin configurations can be easily added or modified
                   through the use of a config file to make avrdude work with different programmers as long as the
                   programmer supports the Atmel AVR serial program method.  You can use the 'default_programmer'
                   keyword in your ${HOME}/.avrduderc file to assign a default programmer to keep from having to
                   specify this option on every invocation.  A full list of all supported programmers is output to
                   the terminal by using ? as programmer-id.
-P port
-b baudrate for serial communication
-D      Disable auto erase for flash.  When the -U option with flash memory is specified, avrdude will
                   perform a chip erase before starting any of the programming operations, since it generally is a
                   mistake to program the flash without performing an erase first.  This option disables that.  Auto
                   erase is not used for ATxmega devices as these devices can use page erase before writing each
                   page so no explicit chip erase is required.  Note however that any page not affected by the cur‐
                   rent operation will retain its previous contents.
-U memtype:op:filename[:format]
                   Perform a memory operation as indicated.  The memtype field specifies the memory type to operate
                   on.  The available memory types are device-dependent, the actual configuration can be viewed with
                   the part command in terminal mode.  Typically, a device's memory configuration at least contains
                   the memory types flash and eeprom.  All memory types currently known are:
                   calibration  One or more bytes of RC oscillator calibration data.
                   eeprom       The EEPROM of the device.
                   efuse        The extended fuse byte.
                   flash        The flash ROM of the device.
                   fuse         The fuse byte in devices that have only a single fuse byte.
                   hfuse        The high fuse byte.

                   As an abbreviation, the form -U filename is equivalent to specifying -U flash:w:filename:a.  This
                   will only work if filename does not have a colon in it.

相關文章