dev builds
themes manual
device status forums
mailing lists
IRC bugs
dev guide

Search | Go
Wiki > Main > RockboxArchitecture > TargetTree

The Target Tree structure


Rockbox builds on many different targets. We need a way to separate the target specific code to keep the common/generic code as clean as possible. The traditional solution in Rockbox so far has been to use #ifdef to conditionally compile target specific stuff.

%CODE{"cpp"}% void my_hw_init(void) { #ifdef IRIVER_H100_SERIES or_l(0x00020000, &GPIO1_ENABLE); #elif defined(IRIVER_H300_SERIES) or_l(0x00040000, &GPIO1_ENABLE); #endif } %ENDCODE%

When we have many targets, these #ifdef statements will clutter the code. The solution is to move the target specific code to separate files. The idea is that each target defines its own my_hw_init() function in a separate file, and the firmware/SOURCES file decides what files to compile depending on the target.

The directory structure

The target tree is divided into subdirectories, where each directory is an abstraction level.

The idea is to have CPU-specific code in the <cpu> directory, manufacturer specific stuff in <manufacturer> etc. For example, a Coldfire optimized memcpy() would be put in firmware/target/coldfire/memcpy-coldfire.S, and the firmware/SOURCES file would contain something like this:

%CODE{"cpp"}% #ifndef SIMULATOR #ifdef CPU_COLDFIRE target/coldfire/memcpy-coldfire.S #endif #endif %ENDCODE%

Backlight example

The backlight code is a perfect example of the benefit of the target tree structure. Here we have a generic functionality that turns off the backlight after a user-defined timeout. However, controlling the actual backlight is done differently in virtually all targets. The backlight code calls two functions, __backlight_on() and __backlight_off() to turn on and off the backlight, and these two have to be defined in a target specific file. Let's take the iAudio X5 as an example. The backlight code is in the X5 target directory:


The file is called backlight-x5.c to make it easier to distinguish from the generic one when doing a file search. We recommend you to do the same when you port to a new target. This file defines the __backlight_xxx() functions:

%CODE{"cpp"}% void __backlight_on(void) { int level = set_irq_level(HIGHEST_IRQ_LEVEL); pcf50606_write(0x38, 0x30); /* Backlight ON */ set_irq_level(level); }

void __backlight_off(void) { int level = set_irq_level(HIGHEST_IRQ_LEVEL); pcf50606_write(0x38, 0x70); /* Backlight OFF */ set_irq_level(level); } %ENDCODE%

What about targets not yet ported to the target tree?

The tools/configure script adds a preprocessor macro, TARGET_TREE for targets that use the target tree. For older targets, the old #ifdef hell is still there. Here's how it typically looks in the generic source file:

%CODE{"cpp"}% #ifndef TARGET_TREE void my_hw_init(void) { #ifdef IRIVER_H100_SERIES bla bla #elif defined(IRIVER_H300_SERIES) bla bla #endif } #endif %ENDCODE%

The function is defined in the generic file unless the TARGET_TREE macro is defined. The goal is to remove all target specific code to the target tree, but we're not there yet.

What about include files?

The target tree is supposed to use the firmware/SOURCES file to select the source files to compile for each target. However, there are occasions where you want to have target specific information in an include file, like setting up preprocessor macros to be used by the generic driver file. The solution is to have a *_target.h file which is included by the generic driver file. The include search path for target-tree enabled targets is as follows:

For example, the firmware/drivers/m5636.h file does this: %CODE{"cpp"}% #include "m5636-target.h" %ENDCODE%

The m5636-target.h is in the target specific directory, for example firmware/target/coldfire/iaudio/x5/m5636-target.h, along with firmware/target/coldfire/iaudio/x5/m5636-x5.c.

r4 - 02 Apr 2021 - 20:46:07 - UnknownUser

Copyright © by the contributing authors.