↓ Archives ↓

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:
/include/configs/am335x_evm.h

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:
bbone-optimized-uboot

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).

toaster

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:

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.

fig1

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.

fig2

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…

fig3

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!

fig4

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!

fig5

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 192.168.1.100
(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=192.168.1.100 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:

http://github.com/chrisw957/sd8686_uap

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:

BBLAYERS ?= " \
  /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.

TOOLCHAIN_PATH ?= "${STAGING_DIR_NATIVE}${prefix_native}/bin/${TUNE_PKGARCH}${HOST_VENDOR}-${HOST_OS}"
TOOLCHAIN_SYSPATH ?= "${TOOLCHAIN_PATH}/${TARGET_SYS}"

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}'
saveenv
reset

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:
tf-sdio-patches.tar.gz

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

libertas-tf-sdio.patch
046-122-mac80211-fix-crash-with-single-queue-drivers.patch

Place the new defconfig in 
~/yocto/poky/meta-gumstix/recipes-kernel/linux/linux-sakoman-3.5/overo

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:
sd8686_helper.bin
lbtf_sdio-9.0.7.p4.bin

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.

Constant Current Dummy Load Revised

I revised my EEVblog inspired constant current dummy load.  I was able to improve the performance under higher currents by shortening up some of the traces on the pcb and adding a couple of components. Some of these PCBs didn’t get the back silkscreen of the Golden Driller (or “Tulsa Man” as Dave called it.)

ccdl rev2

Revsied Dummy Load

Here is the complete documentation:

Constant Current Dummy Load rev2 Schematic

Constant Current Dummy Load rev2 BOM

Constant Current Dummy Load rev2 Gerbers

I sold all the kits I had… Hopefully I’ll be able to put some more together soon!

EEVBlog Inspired Constant Current Dummy Load

Many months ago, I watched the EEVBlog posting on building a constant current dummy load.  It seemed like a very useful device to have around, and I planned on building my own, but only got around to it recently.

My version is pretty faithful to the original.  I made a few changes, mainly to decrease cost. For instance, in place of the panel meter, I just put a couple holes where you can insert the leads from a cheap multimeter. I also replaced the pricy multiturn potentiometer with a couple cheap single turn versions which provide a coarse and fine adjustment. (I know Dave hates those!) I think the only performance related change I made was to replace the LM324 op amp with a MCP6004, which has better rail to rail performance.

Here’s a little video of the board, and the schematic and BOM. I have a few PCBs and kit of parts available if you want to build your own. The kit includes PCB and all parts except the 9V battery. Shipping is a flat $5.20 using USPS small priority mail box. I can only ship to customers in the USA with this method.

Constant Current Dummy Load Schematic (PDF)
Constant Current Dummy Load Bill of Materials (PDF)

 

Alternative to udev in openembedded/Angstrom

I use Angstrom on a Gumstix Overo platform, and one of the things that bothers me is the seemingly long boot times.  One of the items that takes awhile is udev startup.  To try to speed things up, I though I would replace udev with busybox’s mdev.

The first thing I did was create a new image recipe based on the omap3-console-image, but with everything stripped out that I didn’t need.  Then I added the line below to my image file. This will override the IMAGE_DEV_MANAGER default value which is defined in the image.bbclass file.

IMAGE_DEV_MANAGER = "busybox-mdev"

What you’ll soon find though is that many packages (R)DEPEND on udev, it’s very hard to build anything these days
without dragging in udev. To satisfy them, I followed an example from the OE mailing list, and changed the busybox recipe to also provide udev and udev-utils.  Edit the busybox.inc file to add:

PROVIDES += "udev"
PROVIDES += "udev-utils"
RPROVIDES_${PN}-mdev += "udev"
RPROVIDES_${PN}-mdev += "udev-utils"

Now if we go to build the image, bitbake will see more than one possible provider for the “udev” package.  To tell it which one I preferred, I edited my local.conf file to add these lines:

PREFERRED_PROVIDER_udev = "busybox"
PREFERRED_PROVIDER_udev-utils = "busybox"

Now if I build my image, everyone will use busybox-mdev instead of udev.

TVP5150 Patch for RidgeRun SDK (BT656)

I finally had a little time to put together the patch for the RR SDK which allows you to use the TVP5150 board in BT.656 mode.  This requires the 1.5 version of the Leopard Board, and the DM355SDK840402 SDK from RidgeRun.

The image quality looks very good.  If you’ve been using the board in generic mode, you may have noticed the DM355 sometimes gets the fields backwards.  With BT.656 mode, embedded sync is used and it clears up any issue with that.  I think the image could still be improved with a real de-interlacing algorithm, but I think that would require resizer support in the RR SDK.

tvp5150-bt656.patch

  • To install the patch, first make sure you RR SDK is configured and builds ok.
  • Then download the patch and place in your kernel/linux-2.6.29/patches directory
  • Then, in the patches directory, edit the “series” file, and place tvp5150-bt656.patch at the end of the series.
  • Next, you can do a “quilt push” command to apply the patch. It should apply cleanly, and you should get a “Now at patch tvp5150-bt656.patch” message at the end.
  • Change to your linux 2.6.29 directory, do a “make menuconfig”, then go
    device drivers -> multimedia devices -> video capture adapters ->
    encoders/decoders and other helper chips -> and select tvp5150 for
    leopard. Unselect the Aptina MT9V113.
  • Go back to the SDK root directory, DM355SDK840402 and rebuild the kernel with a “make kernel”
  • Once that is done, do a “make install” to download the kernel to your Leopard board. You really shouldn’t need to rebuild the filesystem.
  • Power down your Leopard, attach the TVP5150 card, and apply power.
  • To test your install, see the Gstreamer test pipelines in another posting.