How to Create a New Build Target For the i.MX233
The i.MX233 port handles the following families of chips:
- i.MX233 from Freescale, which is a rebranded Sigmatel STMP3780
- STMP3700 from Sigmatel, which handles STMP37xx chips with xx < 70
- STMP3600 from Sigmatel, which handles all STMP36xx chips
These chips are very complex and the port provides many facilities to avoid writing code or simplify the drivers.
, all the new files should be in the direction
is the name of the new target.
Be sure to read PortingHowToConfigFile?
before reading this.
Like for other targets, you should create a configuration file in
and include it
. In addition to the many standard defines, you must
define the following:
IMX233_SUBTARGET is the chip id
IMX233_PACKAGE is the chip package
IMX233_PARTITIONS is the partition scheme used
will condition every
driver of the imx233 tree, so be sure to get it right. There are mostly three possibilities:
- 3600 for STMP3600 family (actually you can use value between 3600 and 3699)
- 3700 for STM37000 familiy (3700-3799)
- 3780 for the STMP3780/i.MX233
#define IMX233_SUBTARGET 3700
will condition a number of standard pins. At the moment, only BGA169 is supported even though many values are defined:
IMX233_BGA169 for the BG169 package
#define IMX233_PACKAGE IMX233_BGA169
On most targets, the storage layer provides access to the whole disc but part of it is reserved for firmware and system.
The partition schemes tells the code what is the scheme used to hide this and provide a view of the user data only.
It is handled by
and new scheme might be added in the future. The possible values are:
Currently the scheme applies to all disks with some restritions (see section on storage).
#define IMX233_PARTITIONS IMX233_CREATIVE
Freescale Partition Scheme (ATA/SD/MMC)
On those target, Freescale uses a root MBR with four partitions: one firmware (type 53), two system and one logical (type 5).
The logical one is the actual partition shown to the user. It needs to be handle specially because the type 5 is not normally used for
logical partition and thus not understand by any OS.
Creative Partition Scheme
Creative uses a very weird scheme with a proprietary partition table called the MBLK. It is located at a fixed
address in the drive
(which can be changed in the partition driver) and provide named entries. The usual entries are:
minifs for the firmware partition, using the MiniFS? file system
cfs for the user partition, using the CFS file system.
Rockbox currently uses the
partition and you need to reformat it to FAT.
Be sure to read PortingHowToButtonDriver?
before reading this.
The button driver should be named
and you must
provide an header named
provides code for common cases such as:
- touchscreen/touchpad using the LRADC controller: use
- buttons using the LRADC controller: use
- buttons using PSWITCH: use
These to do provide an actual driver but a framework to simplify them so that in most cases you don't have to write anything nontrivial.
Note that your driver can use a combination of some, even all the driver. For example, on the SamsungZ5
, the inner button are on a touchpad, reading using the touchscreen driver while the outer buttons are read using LRADC and the power button is read using PSWITCH. You can also implement others buttons on top of this using other means like GPIOs or i2c touchpad/touchscreen controllers.
If your target has a touchscreen or touchpad wired to the LRADC controller (usually it's a 4 wire touchscreen), you can make sure of the
In order to properly use it, you must:
imx233_touchscreen_enable to enable/disable it in
button_read_device to get the raw value
There are a couple things worth mentionned:
- the touchscreen driver is generic and does not force you define HAVE_TOUCHSCREEN. For example you can define a touchpad and use the touchscreen driver to read the values and translate them in the driver.
imx233_touchscreen_get_touch can be called from any context and only returns a cached value. The driver is completely asynchronous.
- the touchscreen driver can only detect one finger.
static int touch_to_pixels(int *val_x, int *val_y)
// for you to implement: does raw value -> pixel translation
void touchscreen_enable_device(bool en)
static int touchscreen_read_device(int *data)
int x, y;
*data = touch_to_pixels(&x, &y);
return touchscreen_to_pixels(x, y, data);
int button_read_device(int *data)
int res = 0;
/* read other buttons */
return res | touchscreen_read_device(data);
Resistor Ladders / ADC buttons
If your target implements some buttons using a resistor ladder and a voltage plugged into the LRADC, you can use the
already implements all the boring stuff such as proper lradc config, debouncing and so on. Of course it needs a few defines and init. You are advised to
and you must:
button-target.h, it is the LRADC channel on which it is plugged, usually it's 0
button-target.h if your target has HOLD detect. See below
- define an array called
button-mydap.c which in sorted by increasing values and gives the expected reading for each of the button. It should always end with an entry
If your target has HOLD detect, you must define
like for any target and you must tell the driver how to detect it.
It supports several methods controlled by
BLH_ADC: HOLD is read like a regular key and you must have an entry in
imx233_button_lradc_mapping for it, with the key set to
BLH_GPIO: HOLD is read on a GPIO, in which case you must provide the bank and the pin using
BLH_GPIO_PIN. If it needs a pullup, define
BLH_GPIO_PULLUP and if it's inverted, define
BLH_EXT: the driver won't detect HOLD and you must implement it yourself in a function called
On top of that, you driver must do a few calls:
btn argument should be the bitmask of all others key which are not read by the LRADC. These will be ignored if HOLD is on (as reported by LRADC/GPIO or
imx233_button_lradc_hold), and if HOLD is off, these will be ORed will the key detect by the driver.
For debug purposes and calibration, the driver provides a
function which gives you the raw LRADC value.
/* in button-target.h */
#define IMX233_BUTTON_LRADC_HOLD_DET BLH_GPIO
#define BLH_GPIO_BANK 0
#define BLH_GPIO_PIN 9
/* in button-mydap.c */
struct imx233_button_lradc_mapping_t imx233_button_lradc_mapping =
int res = 0;
if(imx233_power_read_pswitch() == 3)
res |= BUTTON_POWER;
If you need the PSWITCH value, you can call
which will provide you with it.
if(imx233_power_read_pswitch() == 1)
btn |= BUTTON_POWER;
Be sure to read PortingHowToFMRadio?
before reading this.
If your target uses has a FM tuner, you will need to provide a few functions for the driver to work: mostly i2c routines and tuner power.
These are usually boring to write so you can use the
driver to simplify most of it. Of course it needs a few defines. You are advised to
and you must put all the defines into
. You can also optionally add some code into
unsupported functionality like RDS which is not handled by this driver. You must define:
IMX233_FMRADIO_I2C is the i2c driver to use
IMX233_FMRADIO_POWER controls how the tuner power is handled.
At the moment, there are two i2c drivers:
FMI_HW uses the hardware i2c (you can use the hardware but cannot controls the pins)
FMI_SW use the generic software i2c and you must define the pins to use using
There also are two methods to controls the tuner power:
FMP_NONE means the tuner power cannot be controlled
FMP_GPIO means it is controlled by a GPIO and you must define
FMP_GPIO_PIN. In case the pin is inverted, define
FMP_GPIO_INVERTED. You can also specify a power-up delay by defining
FMP_GPIO_DELAY in ticks.
Note that the
driver will completely implement
so you don't need and must not write wrappers for them.
#define IMX233_FMRADIO_I2C FMI_SW
#define FMI_SW_SDA_BANK 1
#define FMI_SW_SDA_PIN 24
#define FMI_SW_SCL_BANK 1
#define FMI_SW_SCL_PIN 22
#define IMX233_FMRADIO_POWER FMP_GPIO
#define FMP_GPIO_BANK 0
#define FMP_GPIO_PIN 29
#define FMP_GPIO_DELAY (HZ / 10)
Be sure to read PortingHowToPowerManagement?
before reading this.
features a very complex power management unit implemented in
and it should not be attempted to alter its behaviour.
Instead, the driver relies on the existence on a few defines in
IMX233_CHARGE_CURRENT is the charging current in mA, usually between 100mA and 300mA
IMX233_STOP_CURRENT is the stop current in mA, usually charge current divided by 10
IMX233_CHARGING_TIMEOUT is the timeout before stopping the charger in ticks, usually 4h
IMX233_TOPOFF_TIMEOUT is the timeout before exiting the topoff state in ticks, usually 30min
#define IMX233_CHARGE_CURRENT 200
#define IMX233_STOP_CURRENT 30
#define IMX233_TOPOFF_TIMEOUT (30 * 60 * HZ)
#define IMX233_CHARGING_TIMEOUT (4 * 3600 * HZ)
Be sure to read PortingHowToAudio?
before reading this.
The handling of audio in Rockbox is pretty complicated, being spread accross many areas such as codecs, routing and gating.
For this reason, it is recommended to always use the
driver and the corresponding
These drivers will take care of the gory details about the builtin codec. You are advised to
. In order to work correctly, you must always define in
IMX233_AUDIO_COUPLING_MODE is the audio coupling mode of the headphones, it can be
You can optionally define many more parameters:
IMX233_AUDIO_HP_GATE_PIN if the headphones are protected by a gate. Define
IMX233_AUDIO_HP_GATE_INVERTED if it's inverted
IMX233_AUDIO_SPKR_GATE_PIN if the speaker is protected by a gate. Define
IMX233_AUDIO_SPKR_GATE_INVERTED if it's inverted.
Alternatively, you can override the weak implementation of some audio functions by reimplementing:
imx233_audio_preinit does the preinit and it's default behaviour is to init the headphones and speaker gates (if any)
imx233_audio_postinit does the postinit and usually enables the headphones by default
imx233_audio_enable_hp enables or disable the headphones and it's default behaviour is to use a GPIO gate (if any)
imx233_audio_enable_spkr does the same for the speaker
And if you are really mad, you can even override the low level functions, but this is not recommended.
audio_input_mux for input audio mux
audio_set_output_source for output audio source
There are a few things to note about the driver:
- if you defined a FM tuner, the driver will assume it is routed to Line1
- if you defined a microphone, the driver will assume it is biaised using LRADC channel 1 and at the moment you cannot change the resistor and the biais
#define IMX233_AUDIO_HP_GATE_BANK 1
#define IMX233_AUDIO_HP_GATE_PIN 30
#define IMX233_AUDIO_SPKR_GATE_BANK 1
#define IMX233_AUDIO_SPKR_GATE_PIN 22
#define IMX233_AUDIO_COUPLING_MODE ACM_CAPLESS
- 25 Nov 2013
Copyright © by the contributing authors.