↓ Archives ↓

Category → Uncategorized

Making U-boot Faster on a Beaglebone

We use a custom beaglebone for a project, and we wanted to get it booted as fast as possible. One way of speeding up the boot was to optimize u-boot. By turning off everything we weren’t using, we got the time to “start linux” from 5.498 seconds to 2.248 seconds– that is a savings of 3.250 seconds.

Here is the original boot sequence, with timestamps provided by the tstamp utility:

0.000 0.000:
0.004 0.004: U-Boot SPL 2013.10-dirty (Nov 14 2013 - 12:59:11)
0.267 0.263: reading args
0.272 0.005: spl: error reading image args, err - -1
0.274 0.002: reading u-boot.img
0.278 0.004: reading u-boot.img
0.320 0.042:
0.320 0.000:
0.324 0.004: U-Boot 2013.04-dirty (Apr 22 2014 - 22:11:16)
0.324 0.000:
0.377 0.053: I2C: ready
0.379 0.002: DRAM: 512 MiB
0.863 0.484: WARNING: Caches not enabled
1.565 0.701: NAND: No NAND device found!!!
1.566 0.001: 0 MiB
1.568 0.003: MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1
1.574 0.005: *** Warning - readenv() failed, using default environment
1.574 0.000:
2.128 0.555: musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, HB-ISO Rx, HB-ISO Tx, SoftConn)
2.131 0.003: musb-hdrc: MHDRC RTL version 2.0
2.133 0.002: musb-hdrc: setup fifo_mode 4
2.138 0.004: musb-hdrc: 28/31 max ep, 16384/16384 memory
2.144 0.006: USB Peripheral mode controller at 47401000 using PIO, IRQ 0
2.150 0.007: musb-hdrc: ConfigData=0xde (UTMI-8, dyn FIFOs, HB-ISO Rx, HB-ISO Tx, SoftConn)
2.153 0.003: musb-hdrc: MHDRC RTL version 2.0
2.157 0.004: musb-hdrc: setup fifo_mode 4
2.160 0.003: musb-hdrc: 28/31 max ep, 16384/16384 memory
2.165 0.005: USB Host mode controller at 47401800 using PIO, IRQ 0
2.170 0.005: Net: not set. Validating first E-fuse MAC
2.193 0.023: cpsw, usb_ether
2.196 0.003: Hit any key to stop autoboot: 0
3.213 1.017: mmc_send_cmd : timeout: No status update
3.264 0.051: reading uEnv.txt
3.269 0.005: 115 bytes read in 4 ms (27.3 KiB/s)
3.273 0.004: Importing environment from mmc ...
3.935 0.662: 4403952 bytes read in 651 ms (6.5 MiB/s)
3.982 0.047: 24864 bytes read in 38 ms (638.7 KiB/s)
3.985 0.003: Booting from mmc ...
3.994 0.009: ## Booting kernel from Legacy Image at 80007fc0 ...
3.996 0.002: Image Name: Linux-3.8.13
4.001 0.005: Image Type: ARM Linux Kernel Image (uncompressed)
4.005 0.004: Data Size: 4403888 Bytes = 4.2 MiB
4.007 0.002: Load Address: 80008000
4.010 0.003: Entry Point: 80008000
5.078 1.069: Verifying Checksum ... OK
5.082 0.004: ## Flattened Device Tree blob at 80f80000
5.086 0.004: Booting using the fdt blob at 0x80f80000
5.088 0.002: XIP Kernel Image ... OK
5.097 0.009: OK
5.102 0.005: Using Device Tree in place at 80f80000, end 80f8911f
5.113 0.011:
5.115 0.002: Starting kernel ...
5.115 0.000:
5.255 0.140: Uncompressing Linux... done, booting the kernel.
5.498 0.244: [ 0.000000] Booting Linux on physical CPU 0x0

And here is the optimized u-boot log:

0.000 0.000: 
0.005 0.005: U-Boot SPL 2013.04-dirty (May 09 2014 - 17:41:58)
0.127 0.122: OMAP SD/MMC: 0
0.183 0.056: reading u-boot.img
0.186 0.003: reading u-boot.img
0.216 0.031: 
0.217 0.001: 
0.221 0.004: U-Boot 2013.04-dirty (May 09 2014 - 17:41:58)
0.221 0.000: 
0.274 0.053: I2C:   ready
0.276 0.002: DRAM:  512 MiB
0.300 0.024: WARNING: Caches not enabled
0.815 0.515: MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
0.818 0.003: Using default environment
0.818 0.000: 
0.961 0.143: Net:   Net Initialization Skipped
0.963 0.002: No ethernet found.
0.966 0.003: Hit any key to stop autoboot:  0 
1.831 0.865: 4403952 bytes read in 802 ms (5.2 MiB/s)
1.887 0.056: 24864 bytes read in 46 ms (527.3 KiB/s)
1.890 0.003: Booting from mmc ...
1.900 0.010: ## Booting kernel from Legacy Image at 80007fc0 ...
1.903 0.003:    Image Name:   Linux-3.8.13
1.908 0.005:    Image Type:   ARM Linux Kernel Image (uncompressed)
1.912 0.004:    Data Size:    4403888 Bytes = 4.2 MiB
1.914 0.002:    Load Address: 80008000
1.916 0.002:    Entry Point:  80008000
1.920 0.004: ## Flattened Device Tree blob at 80f80000
1.924 0.004:    Booting using the fdt blob at 0x80f80000
1.926 0.002:    XIP Kernel Image ... OK
1.942 0.016: OK
1.947 0.005:    Using Device Tree in place at 80f80000, end 80f8911f
1.961 0.014: 
1.963 0.002: Starting kernel ...
1.963 0.000: 
2.169 0.206: Uncompressing Linux... done, booting the kernel.
2.480 0.310: [    0.000000] Booting Linux on physical CPU 0x0

We did this by being merciless with the u-boot config file. Our system always boots from the eMMC, so we turned off everything else. This includes hardcoding anything that may have been in uEnv.txt. All of this can be done by editing the /include/configs/am335x_evm.h file.

Here is the am335x_evm.h file that I ended up with:

Another fix is related to the mmc timeout. This can be fixed by adding a udelay() in omap_hsmmc.c.

Index: git/drivers/mmc/omap_hsmmc.c
--- git.orig/drivers/mmc/omap_hsmmc.c	2014-05-09 18:24:10.044401801 -0500
+++ git/drivers/mmc/omap_hsmmc.c	2014-05-09 18:25:00.655765532 -0500
@@ -378,6 +378,7 @@
 	writel(cmd->cmdarg, &mmc_base->arg);
+	udelay(50);
 	writel((cmd->cmdidx << 24) | flags, &mmc_base->cmd);
 	start = get_timer(0);

My bitbake recipe for this modified version of u-boot is here:

Arduino Controlled Toaster Oven “Thermal Chamber”

This project started because of some reported problems with a product I worked on in the past. Customers were reporting strange errors which seemed to be heat related. To reproduce the problem, I really needed a thermal chamber. Unfortunately, that’s not something I have in my lab, and getting involved in selecting heating elements and rigging up an enclosure sounded time consuming.

I did, however, have an inexpensive toaster oven that I bought for small SMD reflow assembly sitting nearby. While not ideal, I figured I should be able to add a relay to control the on/off power to the oven, and with a temperature sensor and some Arduino code, create a poor man’s environmental chamber.

Again, to keep the project quick and simple, I purchased the PowerSwitch Tail II (which is a pre-package AC relay control box), and a “high temperature” Dallas 1-wire temperature sensor from Adafruit. In this case, high temperature only means +125°C, but that was plenty for my application where I only wanted to get things up around +38°C to +50°C (+100°F to +120°F).


Wiring everything up to the Arduino was straight forward. Everything is driven directly by the Arduino with pins configured for digital mode. The only thing to remember is the 4.7K pull-up resistor for the 1-wire data line (which Adafuit conveniently included with the sensor). Here is a quick schematic:


There are two “off the shelf” libraries I used in my Arduino sketch: the Arduino PID Library and the OneWire Arduino Library. I followed the PID library example for using “relay output”, and coupled it with a function to read the temperature sensor at one second increments. I dumped the current readings to the serial port so that I could capture them, and plot the data in OpenOffice Calc. Here is the Arduino code I used in my experiments: toasteroven.zip

Everything so far had seemed to go quick and smooth, but when I started trying to tune the PID parameters, I started to realize this was going to take a little more time. Partly because after each “test run”, I had to turn things off and wait for everything to cool down. Working in the evenings, I generally only got one or two runs in.

It’s been years since I’ve done anything with PID control, but I knew I should start simple with just proportional control. Setting the tuning parameters (Kp, Ki, and Kd) to (5,0,0) and my setpoint to 38°C, I recorded the data shown by the yellow line in the graph below. Lots of overshoot! So I tried again, with a proportional gain of 2, and no integral or derivative (2,0,0). See the red line, which is not much better. One more try, this time with a proportional gain of 1. This is shown by the blue line, which actually doesn’t look too bad, but it still has an overshoot of nearly seven degrees.


To try to improve things, I added some derivative gain. In the next graph, I compared the “proportional only” data with that of “proportional and derivative”. I used the same Kp of 1, and set Kd to 100, just as a starting point, based on other examples I had seen. My overshoot is gone, but it takes even longer to get up to temperature.


Even when it did get up to temperature, the (1,0,100) settings didn’t seem to hold temperature very well, as shown in this graph…


To try to make things a little more aggressive, I bumped up the Kp back to 2, and this helped the steady state, but gave me overshoot again (see the blue 2,0,100 line below). Having had luck with increasing Kd to remove overshoot, I tried that again, and actually got something that looked pretty good. Check out the red (2,0,200) line!


Looking at the data, I get up to temperature in about 210 seconds, and then I’m never more than +/- 0.87°C from my setpoint. One final test is shown below– This time, over several setpoints, and for a longer period of time. I could probably spend even more time tuning things, but it seems fine for my purposes right now, and I need to get back to investigating that customer problem that initiated this whole project!


Gumstix Overo TVP5151 Board

If you are interested in capturing NTSC/PAL with your Overo, this PCB should get you going.

I originally designed the board thinking that it could be hand assembled as a kit. That explains why all the caps and resistors are 0805, and the crystal is a big thru hole version.

When I built up the first one, I figured out that I hadn’t fully considered the flat flex cable connector that goes to the Gumstix. I don’t think the average guy could solder it without a microscope to inspect it.

At any rate, it works, and here are the data files. You can contact me via email if you have specific questions. I am whittenburg at gmail dot com.

PDF of the Schematic
PDF of the PCB
ZIP of the Eagle Design Files

Here are some dirty patches I used with a 3.5 kernel:
Patches to ISP to support BT656
Patches to overo board file, and tvp5150 driver to support tvp5151.

Configuring the ISP:

media-ctl -v -r                                                                 
media-ctl -v -l '"tvp5150 3-005c":0->"OMAP3 ISP CCDC":0[1]'                     
media-ctl -v -l '"OMAP3 ISP CCDC":1->"OMAP3 ISP CCDC output":0[1]'              
media-ctl -v -f '"tvp5150 3-005c":0 [UYVY2X8 720x480]'                          
media-ctl -v -f '"OMAP3 ISP CCDC":1 [UYVY2X8 720x480]' 

Stream H.264 video to your linux desktop at IP address
(I see around 55% idle cpu on my Overo when running this):

gst-launch -v v4l2src device=/dev/video2 always-copy=false do-timestamp=true ! \
queue ! \                                                                       
TIVidenc1 codecName=h264enc engineName=codecServer ! \                          
dmaiperf ! \                                                                    
rtph264pay pt=96 ! \                                                            
udpsink host= port=5000   

Receive the stream on your desktop:

gst-launch -v udpsrc port=5000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, sprop-parameter-sets=(string)\"Z0KAHukBaHpCAAAH0AAB1MAI\\,aM48gA\\=\\=\"" ! \
rtph264depay ! \
ffdec_h264 ! \
ffmpegcolorspace ! \
xvimagesink sync=false

Working Access Point Mode for the Gumstix SD8686

I think I have some good news in regards to access point mode on the Overos.

I took the GPL’ed code from Marvell for the “Dreamplug”, fixed it up, and got it working with the micro access point (UAP) firmware for the SD8686 which can be found in the Palm Pre jar files– all of this on a 3.5.0 kernel, but I would expect it to be fine on newer kernels as well.

Without any trouble, I was able to achieve 10+ Mbps with WPA2 encryption enabled.

You can find everything here:


The README gives instructions for finding the firmware as well.

Using the DSP on Gumstix with Yocto

Lots of discussion on the mailing list lately on how to get the DSP working using the new yocto build system. This works for me…

Start with the standard instructions and make sure you can build gumstix-console-image.

I’m using 64-bit (AMD64) Ubuntu 12.04 LTS, so I needed to also install ia32-libs for the TI installer. You may not need this, depending on your build host.

sudo apt-get install ia32-libs

Now, add the meta-ti layer:

cd ~/yocto/poky
git clone git://git.yoctoproject.org/meta-ti
cd meta-ti
git checkout denzil

Then edit ~/yocto/build/conf/bblayers.conf to add the meta-ti layer so that it looks something like this:

  /home/chris/yocto/poky/meta \
  /home/chris/yocto/poky/meta-yocto \
  /home/chris/yocto/poky/meta-openembedded/meta-gnome \
  /home/chris/yocto/poky/meta-openembedded/meta-oe \
  /home/chris/yocto/poky/meta-openembedded/meta-xfce \
  /home/chris/yocto/poky/meta-gumstix \
  /home/chris/yocto/poky/meta-ti \

Edit ~/yocto/build/conf/local.conf and add the following line to ignore some of the meta-ti recipes:

BBMASK ?= ".*/meta-ti/recipes-(misc|bsp/formfactor)/"

Fix up the toolchain_path env variable by editing ~/yocto/poky/meta-gumstix/conf/machine/overo.inc and adding the line below. This fixes the problem finding the compiler when building dsplink.


Then edit ~/yocto/poky/meta-gumstix/conf/machine/include/omap3.inc and just before the tune-cortexa8.inc line, add the line below. This fixes the problem building the DMAI recipe.

require conf/machine/include/soc-family.inc

Now, download ti_cgt_c6000_7.2.7_setup_linux_x86.bin from TI and place in your ~/yocto/build/downloads directory. Touch ti_cgt_c6000_7.2.7_setup_linux_x86.bin.done in the same directory.

Ok! You should now be able to “bitbake gstreamer-ti”. It will take a bit of time.

If this works, you can build an image that has gstreamer-ti along with other gstreamer-plugins. Here is one such image recipe: gumstix-dsp-image.bb

Once the image is built, create your sd card. When booting for the first time, stop the u-boot countdown and change the env vars to leave a memory hole for cmemk.

setenv mem 'mem=96M@0x80000000 mem=384M@0x88000000'
setenv mpurate 800
setenv mmcargs 'setenv bootargs console=${console} mpurate=${mpurate} vram=${vram} omapfb.mode=dvi:${dvimode} omapfb.debug=y omapfb.vram=${fbvram} omapdss.def_disp=${defaultdisplay} ${mem} root=${mmcroot} rootfstype=${mmcrootfstype}'

Go ahead and boot into linux, then edit /lib/systemd/system/gstti-init.service and remove the line which starts “ConditionKernelCommandLine=”. This condition causes the modules to only get loaded if the memory hole is very specific.

Now reboot one more time.

Once booted, check your modules and make sure cmemk loaded for you:

root@overo:~# lsmod                                                             
Module                  Size  Used by                                           
mt9v032                 7237  4294967295                                        
omap3_isp             131955  0                                                 
v4l2_common             8933  2 mt9v032,omap3_isp                               
videodev               99128  3 mt9v032,omap3_isp,v4l2_common                   
media                  12714  3 mt9v032,omap3_isp,videodev                      
ads7846                10488  0                                                 
sdmak                   4076  0                                                 
lpm_omap3530            6797  0                                                 
dsplinkk              131408  1 lpm_omap3530                                    
cmemk                  22005  0                                                 
rfcomm                 56119  0                                                 
hidp                   16251  0                                                 
bluetooth             258745  4 rfcomm,hidp                                     
rfkill                 17524  1 bluetooth                                       
ipv6                  249350  16      

Test out the dsp with a simple pipeline:

gst-launch videotestsrc num-buffers=5 ! TIVidenc1 codecName=mpeg4enc engineName=codecServer ! fakesink

Good luck.

SDIO support for libertas_tf

Here are the required patches and kernel config:

Assuming you are using the current yocto meta-gumstix layer, then place the patches in ~/yocto/poky/meta-gumstix/recipes-kernel/linux/linux-sakoman-3.5


Place the new defconfig in 

Edit the linux-sakoman_3.5.bb recipe to apply the patches:

SRC_URI = "git://www.sakoman.com/git/linux.git;branch=omap-3.5;protocol=git \
           file://libertas-tf-sdio.patch \
           file://046-122-mac80211-fix-crash-with-single-queue-drivers.patch \
           file://defconfig \
           file://${BOOT_SPLASH} \

Clean and rebuild the kernel and modules with the following commands:

$ bitbake -c cleanall -f virtual/kernel
$ bitbake virtual/kernel

Create your SD card, and put the thin firmware in the /lib/firmware directory.
Name them sd8686_helper.bin and sd8686tf.bin
You can get them here:

When you boot, you will see the following message at boot, but wlan0 will not be present:

[   16.643249] libertas_tf_sdio: Libertas Thinfirmware SDIO driver 
[   16.650085] libertas_tf_sdio: Copyright cozybit Inc.                         
[   16.655670] libertas_tf_sdio: buildstamp: 6

Then about 30 seconds later, after the firmware finally loads, you will get:

libertas_tf_sdio: 00:19:88:15:b1:be, fw 9.0.7p4, c3
libertas_tf: Marvell WLAN 802.11 thinfirm adapter                
libertas_tf: 00:19:88:15:b1:be, fw 9.0.7p4, cap 0x00000303       
libertas_tf: Marvell WLAN 802.11 thinfirm adapter                
IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready

You should then be able to configure the interface, and use it with hostap, etc (assuming network-manager doesn’t get in the way). I have another set of patches which add asynchronous firmware loading, but they need a little clean up.

You may have to delete the /lib/modules/3.5.0/kernel/drivers/net/wireless/libertas directory if the fat firmware module keeps loading (or blacklist it?)

I mainly put these out here for others to try and see if someone can help with the throughput issues. I’m only seeing ~2Mbps one direction, and ~500Kbps the other.

TVP5150 Patch Update

While testing the TVP5150 boards this weekend, I found that I sometimes got video which seemed to be shifting colors. It didn’t seem to be hardware related, so I started investigating the tvp5150 register settings. I’m using the defaults for everything, but I did seem to isolate it down to the color subcarrier PLL. By setting the “Color subcarrier PLL frozen” bit, the problem seemed to go away. So, I’m attaching v2 of the patch for the RR SDK. If you’re interested in the particular change, it’s the tvp5150_init_reg_seq structure in tvp5150_davinci.c file. Here is the new version:

static const struct tvp5150_reg tvp5150_init_reg_seq[] = {

And here is the new patch…