- Source tree
This page presents the Dooba SDK source tree.
It is located at /src in the SDK distribution.
The source tree is simple: every sub-directory within it represents a Firmware Element.
Such an element can be either a library (a collection of re-usable methods and definitions) or an application (a solution built for a specific hardware target).
Firmware elements are defined by a file placed within their directory named dfe.conf.
This file should follow a YAML structure and may contain the following fields:
name- The name of the element
type- Either app or lib
mmcu- ("type: app" only) Target microcontroller
freq- ("type: app" only) Target microcontroller CPU frequency
deps- List of immediate dependencies
compiler_options- List of compiler options
linker_options- List of linker options
Below is an example of a simple dfe.conf element definition: the hello_world application:
# Dooba Firmware Element Configuration name: hello_world type: app mmcu: atmega1284p freq: 10000000L
Library definitions are often very short:
# Dooba Firmware Element Configuration name: i2c type: lib
What can we build?¶
First and obvious, .c files will be compiled as C code.
Aside from that, other formats are handled by the build process:
Binary resources such as images, sounds, or any other non-code element can be embedded into any library or application.
Any file with a .bin extension will be converted into a C source file and header. This will ensure that the resource's data (inside the C source file) will be included in the final object.
Also, the associated header file allows accessing the resource from C code.
The resource's size will be defined (in bytes) as
XXX_DATA_SIZE, where XXX is the name of the resource file without the .bin extension, capitalized and with all occurences of '.' (dot), ' ' (space) and '-' (hyphen) replaced with '_' (underscore).
For example, a file called foobar.bin containing six bytes would produce the following:
#define FOOBAR_DATA_SIZE 6 extern uint8_t foobar_data[FOOBAR_DATA_SIZE];
The SSD1306 is an OLED controller commonly found on monochrome displays.
A library is provided with the SDK to control such devices.
Raw image data (such as exported from Gimp using "raw" output) can be placed in a firmware element with a name ending with .WIDTH.HEIGHT.ssd1306_img, where WIDTH & HEIGHT are to be replaced with the image's size in pixels.
Such a file would be transformed for easy drawing to the display (adapted to framebuffer format) and converted into a .bin resource file.
Note: image height MUST be a multiple of 8 (8, 16, 32, ...).
For example, a 32x48 (32 wide, 48 high) image called foobar could be stored as foobar.32.48.ssd1306_img, and would be accessible from the code as
A heavier application example is the Shiva MP3 player:
# Dooba Firmware Element Configuration name: shiva type: app mmcu: atmega1284p freq: 10000000L deps: - ionode - fatfs - sdcard - ssd1306 - mcp23008 - sta013 - lm4811 - scom - i2c
Finally, a curious and rather uncommon example is the kiwi bootloader.
This one requires additional compiler and linker flags:
# Dooba Firmware Element Configuration name: kiwi type: app mmcu: atmega1284p freq: 10000000L compiler_options: - -fno-split-wide-types - -mrelax linker_options: - -fno-split-wide-types - -mrelax - -Wl,--section-start=.text=0x1fc00 - -Wl,--section-start=.version=0x1fffe - -nostartfiles - -nostdlib
A word on dependencies¶
Whether defining an application or a library, if you wish to rely on another library within the source tree, you need to add it to the list of dependencies -
However, everything is built recursively, so you only need to list out immediate dependencies for your element. No need to worry about your dependency's dependencies.
As you may have seen in some of the examples above, defining this list is done as follows:
deps: - scom - i2c
When run, the build script (
./dbuild) first collects all firmware elements and parses their definitions. All applications are then selected from the tree and built one after the other.
Building an application implies recursively building all of its dependencies. While doing so, the build scripts also recursively collects compiler & linker definitions, passing them along to dependencies.
When re-using libraries for embedded hardware designs it is fairly common to have different pin setups or connector configurations (compared to the "default" configurations of some libraries). This build model offers a transparent and simple approach to overriding compiler definitions from the application level, without needing to touch the libraries.
Applications are built as .hex files, and placed in the /out/bin folder.