Introduction
Flashing an eMMC of produced board is one of the crucial manufacturing
procedures. This post series presents how one can take advantage of i.MX6
features and open source tools to prepare themselves with quite robust and easy
to use process.
Target reference platform is
Hummingboard Edge.
General concept
The general concept is inspired by
this great bootlin (former FreeElectrons) post:
I’ve run into some issues while trying to do something similar on Hummingbard
Edge, so decided to share my experience.
The general flow looks like:
- Load
U-Boot
to DDR using Serial Download Protocol
U-Boot
enters fastboot mode
- Pull in the image via fastboot protocol
In the first post, we will focus on loading U-Boot
to DDR using SDP.
Hardware preparation
Before we start, we need to prepare hardware first. HB Edge has USBOTG signals
connected to the upper back USB-A connector:

To utilize it we should prepare cable as suggested by the
SolidRun wiki
They suggest cutting two USB cables in half to create USB-A male-male cable. To
make things easier we can buy one of those directly. An example of such is
this one
We still need one more rework:
- Remove the main insulation from the middle of the cable,
- Cut the power wire (usually the read one),
- Solder it back with additional series resistance. SolidRun suggest to use 1-10
Ohms. I am using 2x10 Ohm resistors in parallel which gives me around 5 Ohms.
Resistors soldered on prototype board:

Additional series resistance in power wire path:

Connect USB A host to host cable to USB OTG port (upper port of U5 USB connector
on HB Edge board).
Now we should check whether the cable was prepared correctly. If it is, the USB
device should be detected as Freescale SoC in Recovery Mode:
1
|
Bus 002 Device 002: ID 15a2:0061 Freescale Semiconductor, Inc. i.MX 6Solo/6DualLite SystemOnChip in RecoveryMode
|
It may be convenient to set up an udev
rule right away, so we can have access
to device as a user later:
1
2
|
echo 'SUBSYSTEM =="usb", ATTRS{idVendor}=="15a2", ATTRS{idProduct}=="0061" , MODE="0666"'
| sudo tee /etc/udev/rules.d/51-fsl-flashing.rules
|
imx-usb-loader
This is an open-source alternative to NXP mfgtool
, which allows sending
binaries over UART or USB.
Getting imx_usb_loader
:
1
2
3
4
|
sudo apt-get install libusb-dev libusb-1.0
git clone git@github.com:boundarydevices/imx_usb_loader.git
cd imx_usb_loader
make
|
Output are 2 files: imx_uart
and imx_usb
that allow to send files to
platform using UART or USB respectively.
imx_usb_loader
is able to download a single file u-boot.imx
. In case of
boards with SPL
support, we have 2 binaries: SPL
and u-boot.img
. Loading
of both of them is possible using imx_usb_loader
, but it is required to take
advantage of the
U-Boot Serial Download Protocol support
U-Boot SDP support was introduced in October 2017. So we need at least v2017.11
release. I’m using the most recent v2018.01.
Following additional configuration options have to be selected to enable SDP
support in U-Boot:
1
2
3
4
5
6
|
CONFIG_SPL_USB_HOST_SUPPORT=y
CONFIG_SPL_USB_GADGET_SUPPORT=y
CONFIG_SPL_USB_SDP_SUPPORT=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DOWNLOAD=y
CONFIG_USB_FUNCTION_SDP=y
|
Load SPL and u-boot.img separately
- Copy
SPL
and u-boot.img
output files to the root directory of the
imx_usb_loader
tool
- Send
SPL
via USB:
output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
config file <.//imx_usb.conf>
vid=0x066f pid=0x3780 file_name=mx23_usb_work.conf
vid=0x15a2 pid=0x004f file_name=mx28_usb_work.conf
vid=0x15a2 pid=0x0052 file_name=mx50_usb_work.conf
vid=0x15a2 pid=0x0054 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0061 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0063 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0071 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x007d file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0080 file_name=mx6_usb_work.conf
vid=0x1fc9 pid=0x0128 file_name=mx6_usb_work.conf
vid=0x15a2 pid=0x0076 file_name=mx7_usb_work.conf
vid=0x1fc9 pid=0x0126 file_name=mx7ulp_usb_work.conf
vid=0x15a2 pid=0x0041 file_name=mx51_usb_work.conf
vid=0x15a2 pid=0x004e file_name=mx53_usb_work.conf
vid=0x15a2 pid=0x006a file_name=vybrid_usb_work.conf
vid=0x066f pid=0x37ff file_name=linux_gadget.conf
vid=0x1b67 pid=0x4fff file_name=mx6_usb_sdp_spl.conf
vid=0x0525 pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
config file <.//mx6_usb_work.conf>
parse .//mx6_usb_work.conf
Trying to open device vid=0x15a2 pid=0x0061
Interface 0 claimed
HAB security state: development mode (0x56787856)
== work item
filename SPL
load_size 0 bytes
load_addr 0x00000000
dcd 1
clear_dcd 0
plug 1
jump_mode 2
jump_addr 0x00000000
== end work item
No dcd table, barker=402000d1
loading binary file(SPL) to 00907400, skip=0, fsize=ac00 type=aa
<<<44032, 44032 bytes>>>
succeeded (status 0x88888888)
jumping to 0x00907400
|
- HB serial console output will show:
1
2
3
4
|
U-Boot SPL 2018.01-00001-gceb4ce4f78fb-dirty (Jan 16 2018 - 15:04:11)
Trying to boot from USB SDP
SDP: initialize...
SDP: handle requests...
|
Notice that once SPL
is loaded, and target board enters SDP
handler state,
the USB device seen by host PC will change.
In my case it changed from:
1
|
Bus 003 Device 013: ID 15a2:0061 Freescale Semiconductor, Inc. i.MX 6Solo/6DualLite SystemOnChip in RecoveryMode
|
to:
1
|
Bus 003 Device 014: ID 0000:0fff
|
It does not look like a proper USB device VID / PID pair. Even if we set those
in imx_usb.conf
:
1
|
echo '0x0000:0x0fff, mx6_usb_sdp_spl.conf' >> imx_usb.conf
|
We are getting following error message from the tool:
1
2
3
4
|
vid/pid cannot be 0: mx6_usb_sdp_spl.conf
[0x0000:0x0fff, mx6_usb_sdp_spl.conf
]
no matching USB device found
|
The
U-Boot SDP documentation
states that those values should be set by configuration options:
CONFIG_G_DNL_(VENDOR|PRODUCT)_NUM
and it should default to:
1
|
0x1b67:0x4fff, mx6_usb_sdp_spl.conf
|
Grepping U-Boot
sources shows only a few of those options in some of the board
config files:
1
2
3
4
5
6
7
8
9
10
11
12
|
./configs/chromebook_minnie_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/fennec-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/rock2_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/tinker-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/phycore-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/evb-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/chromebit_mickey_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/chromebook_jerry_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/popmetal-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/miqi-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/vyasa-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x2207
./configs/firefly-rk3288_defconfig:CONFIG_G_DNL_VENDOR_NUM=0x220
|
Quick search through configuration options shows that gadget USB VID / PID is
set through following options:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
config USB_GADGET_VENDOR_NUM
hex "Vendor ID of the USB device"
default 0x1f3a if ARCH_SUNXI
default 0x0
help
Vendor ID of the USB device emulated, reported to the host device.
This is usually the board or SoC vendor's, unless you've registered
for one.
config USB_GADGET_PRODUCT_NUM
hex "Product ID of the USB device"
default 0x1010 if ARCH_SUNXI
default 0x0
help
Product ID of the USB device emulated, reported to the host device.
|
The strange thing to me is that PID defaults to 0x0, while in my case it is
detected as 0x0000:0x0fff
.
Setting those to the ones as described in the documentation:
1
2
|
CONFIG_USB_GADGET_VENDOR_NUM=0x1b67
CONFIG_USB_GADGET_PRODUCT_NUM=0x4fff
|
Gives us following results:
lsusb
output gives following output:
1
|
Bus 003 Device 010: ID 1b67:5ffe
|
Note that in this case the PID is also different than specified in the
configuration.
I have also used the
recent master branch
and above information applies there as well.
In this case, we are able to flash u-boot.img
via SDP.
On more thing to do before flashing u-boot.img
is to add VID / PID pair to
imx_usb
config:
1
|
echo '0x1b67:0x5ffe, mx6_usb_sdp_spl.conf' >> imx_usb.conf
|
Now we can download SPL
and u-boot.img
with command below:
1
|
./imx_usb SPL && sleep 1 && ./imx_usb u-boot.img
|
output of u-boot.img
booting:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
U-Boot SPL 2018.01-00272-g0434429f989d (Jan 18 2018 - 12:56:59)
Trying to boot from USB SDP
SDP: initialize...
SDP: handle requests...
Downloading file of size 357536 to 0x177fffc0... done
Jumping to the header at 0x177fffc0
Header Tag is not an IMX image
U-Boot 2018.01-00272-g0434429f989d (Jan 18 2018 - 12:56:59 +0100)
CPU: Freescale i.MX6DL rev1.3 996 MHz (running at 792 MHz)
CPU: Commercial temperature grade (0C to 95C) at 60C
Reset cause: POR
Board: MX6 Hummingboard2
DRAM: 1 GiB
MMC: FSL_SDHC: 0
Card did not respond to voltage select!
mmc_init: -95, time 58
*** Warning - MMC init failed, using default environment
No panel detected: default to HDMI
Display: HDMI (1024x768)
In: serial
Out: serial
Err: serial
Net: FEC
Hit any key to stop autoboot: 0
Card did not respond to voltage select!
mmc_init: -95, time 58
** Bad device mmc 0 **
Card did not respond to voltage select!
mmc_init: -95, time 57
Device 0: Model: Firm: Ser#:
Type: Hard Disk
Capacity: not available
... is now current device
** Bad device size - sata 0 **
starting USB...
USB0: Port not available.
USB1: USB EHCI 1.00
scanning bus 1 for devices... 2 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Device 0: device type unknown
... is now current device
** Bad device usb 0 **
** Bad device usb 0 **
FEC Waiting for PHY auto negotiation to complete.
|
The interesting thing is that whenever we enter U-Boot
prompt and enter SDP
mode:
1
2
3
4
5
6
7
8
9
10
|
=> sdp
sdp - Serial Downloader Protocol
Usage:
sdp <USB_controller>
- serial downloader protocol via <USB_controller>
=> sdp 0
SDP: initialize...
SDP: handle requests...
|
The USB PID seen by my host PC changes to the one set in the configuration:
1
|
Bus 003 Device 025: ID 1b67:4fff
|
Load SPL and u-boot.img in one run
It is possible to download both SPL
and u-boot.img
with one imx_usb
command execution. To do that, we need to create configuration files with
following content:
1
2
3
4
|
cat << EOF > imx_usb.conf
#vid:pid, config_file
0x15a2:0x0061, mx6_usb_rom.conf, 0x1b67:0x5ffe, mx6_usb_sdp_spl.conf
EOF
|
1
2
3
4
5
|
cat << EOF > mx6_usb_rom.conf
mx6_qsb
hid,1024,0x910000,0x10000000,1G,0x00900000,0x40000
SPL:jump header2
EOF
|
1
2
3
4
5
|
cat << EOF > mx6_usb_sdp_spl.conf
mx6_spl_sdp
hid,uboot_header,1024,0x10000000,1G,0x00907000,0x31000
u-boot.img:jump header2
EOF
|
Above configuration files are also present in
3mdeb fork of imx_usb_loader
With such configuration in place, calling ./imx_usb
gives following output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
config file <.//imx_usb.conf>
vid=0x15a2 pid=0x0061 file_name=mx6_usb_rom.conf
-> vid=0x1b67 pid=0x5ffe file_name=mx6_usb_sdp_spl.conf
config file <.//mx6_usb_rom.conf>
parse .//mx6_usb_rom.conf
Trying to open device vid=0x15a2 pid=0x0061
Interface 0 claimed
HAB security state: development mode (0x56787856)
== work item
filename SPL
load_size 0 bytes
load_addr 0x13f00000
dcd 0
clear_dcd 0
plug 0
jump_mode 3
jump_addr 0x00000000
== end work item
loading binary file(SPL) to 00907400, skip=0, fsize=dc00 type=aa
<<<56320, 56320 bytes>>>
succeeded (status 0x88888888)
jumping to 0x00907400
config file <.//mx6_usb_sdp_spl.conf>
parse .//mx6_usb_sdp_spl.conf
Trying to open device vid=0x1b67 pid=0x5ffe.
Interface 0 claimed
HAB security state: development mode (0x56787856)
== work item
filename u-boot.img
load_size 0 bytes
load_addr 0x03f00001
dcd 0
clear_dcd 0
plug 0
jump_mode 3
jump_addr 0x00000000
== end work item
loading binary file(u-boot.img) to 177fffc0, skip=0, fsize=574a0 type=aa
<<<357536, 358400 bytes>>>
succeeded (status 0x88888888)
jumping to 0x177fffc0
|
and the board boots with U-Boot
as shown previously.
Summary
imx_usb_loader
is really handy tool for downloading binaries (especially the
bootloader) directly into memory.
- I’ve run into some strange behavior of
U-Boot
USB Gadget device PID
. I
will try to track down what really happens in the code there.
- I’ve run into some outdated
U-Boot
documentation. I can try updating it.
- Configuration files for
imx_usb_loader
can be found at
3mdeb fork
- Final configuration of
U-Boot
target for Hummingboard Edge which adds SDP
support can be found on
3mdeb fork
- I am going to present next steps towards our goal in an upcoming post from
this series.
Maciej Pijanowski
Engineering Manager at 3mdeb with years of experience in engineering and management. Open-source software enthusiast and contributor. Interested in embedded systems in general, build systems, security.