Thursday, November 5, 2015

Modify EEPROM on BeagleBone Black

I'm finishing a short project where I'm helping a customer support their BeagleBone Black derivative board in the official BBB images. From a software point of view, their board differs in that it has a different HDMI encoder chip. As such, the board must load a different .dts file on boot.

BeagleBones use the am335x_evm configuration in U-Boot which supports running a single image on any board that provides identity information via an EEPROM. U-Boot determines which BeagleBone variant is present by reading board-specific information from the EEPROM and selects a .dts file to load based on that information. The BBB EEPROM is located at I2C bus 0 address 0x50, as mentioned in the BBB SRM. The allowable EEPROM contents are defined at the EEPROM database. A new variant must use a unique board revision to allow identification and selection of the proper .dts file. In our case, the board revision (last 4 bytes) is AIA0.

The early derivative board I received had 00A0 as the board revision since the specified contents hadn't been determined at the time that these were first made. After modifying U-Boot to support identifying the AIA0 revision, I now needed to update my board to test this code and the new .dts file for this board. This can all be done from the U-Boot command line as detailed below.

So first, I dump the contents of the EEPROM as offset 0xc (where we find the 4 bytes of the board revision). Note that we must use the syntax of 0x0c.2 where the 2 indicates that 16-bit addressing is to be used because this EEPROM is large enough to require 16-bit addresses. Omitting that would result in reading garbage.

=> i2c md 0x50 0x0c.2 4
000c: 30 30 41 30    00A0
This is simply what was put in as a placeholder value when these early boards were rolled. Now I fill a free spot in memory with the new board revision I want to write to the EEPROM.
=> mm.b 0x82000000
82000000: 35 ? 41
82000001: 71 ? 49
82000002: fd ? 41
82000003: f7 ? 30
82000004: ff ? .

And then verify it's there.
=> md.b 0x82000000 4
82000000: 41 49 41 30  AIA0

Now I can try to write to the EEPROM.
=> i2c write 0x82000000 0x50 0xc.2 4
=> i2c md 0x50 0x0c.2 4
000c: 30 30 41 30    00A0
Oops, that didn't work because the EEPROM is asserted high through a pullup resistor by default. Luckily, there's a handy test point that we can ground to disable the write protect. Find TP4 between the barrel jack and the RJ45 jack and jumper it to a ground pin like P9-2 that is right nearby. Now try again.
=> i2c write 0x82000000 0x50 0xc.2 4
=> i2c md 0x50 0x0c.2 4
000c: 41 49 41 30    AIA0

Success! Now let's view the entire contents in context.
=> i2c md 0x50 0x00.2 10
0000: aa 55 33 ee 41 33 33 35 42 4e 4c 54 41 49 41 30    .U3.A335BNLTAIA0

The board revision is updated and now U-Boot can identify my board as an AIA0 and load the new .dts file to support the HDMI encoder.

Back at it again

It's been three years and two job changes. After a friend from the community suggested that I should be writing about my projects rather than just informally chatting about them on IRC, I decided to take his advice. 

Quite frankly, there's just never enough good documentation on how to do stuff so every little bit helps people that are new to embedded Linux (or other software).

I'm going to try to keep all my project notes here rather than in little text files scattered all over my system as one improvement. I'll also start documenting various projects I've been working on lately.

Tuesday, October 23, 2012

Homebrew BeagleBone RS-232 cape


I'm not a huge fan of console output via USB to uart converters. It causes me problems in my home office/lab with using a power controller and my conventional console server. conmux almost solves some issues but if I have to even unplug the USB cable I need to restart it. It's maddening and frustrating to not be able to power cycle the BeagleBone for a cold boot because USB is supplying it power when I cut power to the DC input. Given that this annoys me so much, I finally got around to getting an RS-232 cape from Boardzoo so I can have at least one of my BeagleBones unhooked from USB and able to be used via power/console control.

It's Just Software

This works great with current U-Boot master and Andrew Bradford's AM33xx U-Boot patches applied. Simply configure with make am335x_evm_uart2_config and the MLO/u-boot.img from the build will have console on UART2, which is the default setting for the RS-232 cape.

In order to support the entire kernel/rootfs chain of s/w on BeagleBone, it's then possible to take kernel 3.7-rc2 and add the following to arch/arm/boot/dts/am335x-bone.dts:

               uart3: serial@48024000 {
                       status = "okay";

Note that the uart numbering is actually off by 1 so uart3 is actually physical UART2. Be sure to change the bootargs and the rootfs to use ttyO2 and everything should be working on the RS-232 cape.

Let's Build Something

Ok, so let's say you don't have an RS-232 cape? It's trivial to clone that cape with parts that may be sitting in a junk box, or picked up cheaply at any electronics store. You'll need:

  1. MAX232IN (or equivalent) RS-232 line driver
  2. 6 1 uF tantalum capacitors
  3. DB9 connector (I used an old AT DB9 ribbon cable from my junk box)
Wire up the MAX232 as shown in the Fritzing diagram below boot with an MLO/u-boot.img as described above and you'll have real RS-232 console on your DB9.

Please note that there are many MAX232 variants available. Take careful note of the coupling capacitor requirements on the version you use. Some call for a different capacitor or integrate them into the part. Also, the supply voltage on the MAX232IN I'm using is strictly required to be 5V whereas some variants are designed to operate from 3.3V.

Homebrew RS-232 cape Fritzing diagram
Here's a photo of both the production RS-232 cape on the Beaglebone in the upper right and the equivalent nest of wires version attached the BeagleBone sitting in the breakout platform on the left.

Nest of wires RS-232 cape in action

Wednesday, June 13, 2012

Faux GPMC interfacing with the BeagleBone


Read TI's e2e forums, #beagle, and Google and you'll quickly find endless dead-end threads with people trying to interface something to a TI part's GPMC interface. Often, people just don't quite understand how to even set up the most basic use case with the GPMC any many posts simply go around an around on how to get anything at all working.

In preparation for a project where I was planning to interface a dual-port SRAM to BeagleBone, I did a simple GPMC test to demonstrate that it functions. In the spirit of KISS, I made the test case so simple that you don't need a real part to test out basic operation.

GPMC Testing

Let's take a look at the circuit.

BeagleBone GPMC Test Circuit
It's quite simple as illustrated in the above Fritzing diagram. The only connections required are wiring GPMC_AD7..0 to either 3.3V or Ground as necessary to hardcode the byte 0x42 on those data lines.

How It Works

I recommend running a fairly recent BeagleBone Angstrom image to ensure that you have the latest kernel updates. The latest images can be found at Koen's site and I have verified the 2012.05.31 image as working with this tutorial. If you haven't written out an Angstrom release image to an SD card before, I recommend following the "easy way" instructions.

Once Angstrom is up and running, copy the following script to your SD card however you choose to do so.

# Simple read test for hardcoded GPMC data on AD7..0


# GPMC pinmuxing

# Enable Mode 0 and output for CS0, ADV, and OE
# (Needed to illustrate timing on logic analyzer)
echo $CTLMODE > $MUX/gpmc_csn0
echo $CTLMODE > $MUX/gpmc_advn_ale
echo $CTLMODE > $MUX/gpmc_oen_ren

# Enable Mode 0, receiver and pullup for AD7..0
echo $ADMODE > $MUX/gpmc_ad7
echo $ADMODE > $MUX/gpmc_ad6
echo $ADMODE > $MUX/gpmc_ad5
echo $ADMODE > $MUX/gpmc_ad4
echo $ADMODE > $MUX/gpmc_ad3
echo $ADMODE > $MUX/gpmc_ad2
echo $ADMODE > $MUX/gpmc_ad1
echo $ADMODE > $MUX/gpmc_ad0

# CS0 Configuration

# Disable CS
# (TRM says to disable before modifying config and is enabled at pwr on)
devmem2 0x50000078 w 0x00000000 > /dev/null

# No burst, async, 8-bit, non multiplexed
devmem2 0x50000060 w 0x00000000 > /dev/null
# Assert CS on fclk 0, deassert CS on fclk 3
devmem2 0x50000064 w 0x00000300 > /dev/null
# Unused ADV/ALE
devmem2 0x50000068 w 0x00000000 > /dev/null
# Assert OE on fclk 1, deassert OE on fclk 3
devmem2 0x5000006c w 0x00000301 > /dev/null
# Data valid on fclk 2, cycle time 3 fclks
devmem2 0x50000070 w 0x00020003 > /dev/null
# No back to back cycle restrictions
devmem2 0x50000074 w 0x00000000 > /dev/null
# CS0: Set base address 0x01000000, 16MB region, and enable CS
devmem2 0x50000078 w 0x00000f41 > /dev/null

# Read 32-bits from 0x01000000, four 8-bit async GPMC cycles
devmem2 0x01000000 w   

Ok, now run this script

root@bone1:~# mv
root@bone1:~# ./ 
/dev/mem opened.
Memory mapped at address 0x402a3000.
Read at address  0x01000000 (0x402a3000): 0x42424242

What happened here is the following:

  1. Configure the GPMC control signal pinmuxes (not strictly required for this simple use case and not shown wired, but I needed them to capture control timing on the logic analyzer)
  2. Configure the GPMC data pinmuxes
  3. Configure the GPMC's chip select 0 config registers for an 8-bit device with it being decoded at address 0x01000000 over a 16MB region. Also, I configured a timing window for our faux device such that the chip select is asserted at the start of a cycle, then output enable one clock later, instructing the GPMC that data is valid on our faux device on the next clock and the total read cycle time is 3 clocks
  4. Perform a 32-bit read to our decoded address space. This is broken into 4 8-bit cycles by the GPMC since we programmed it to handle an 8-bit device. The data we read is our hardcoded 0x42 byte in each case.
For extra credit, try pulling GPMC_AD0 on P8-25 to 3.3V instead of Ground. Run the script again and prove to yourself that it now reads 0x43.

Let's look at a timing diagram captured on my logic analyzer.

BeagleBone GPMC Test Timing Capture

This timing diagram illustrates that the GPMC is doing exactly what we asked it to do for us. First note that the AM335x GPMC_FCLK operates at 100MHz. At 0ns, we see CS0n asserted, exactly as requested at the beginning of a cycle. At 10ns (exactly 1 GPMC_FCLK later) we see OEn asserted. OEn is asserted for 2 GPMC_FCLKs, ending at 30ns. The total time for one 8-bit read cycle is therefore 30ns (or 3 GPMC_FCLKs). Notice that CS0 stays asserted as each of the 4 8-bit read cycles is issued to complete the 32-bit access to our GPMC address space.


Keep in mind that this is a truly trivial example, but it does set forward the fundamentals of communication with GPMC-connected devices. Interfacing a real device requires complete understanding of a given part's datasheet timing diagrams in order to program the GPMC timing accordingly. In the future, I will show a real world GPMC use case with a common asynchronous SRAM.

Monday, June 11, 2012

Fritzing part for BeagleBone


I first discovered Fritzing while working on various Arduino projects. Anybody working around the Arduino community will quickly notice the high quality diagrams found in many tutorials. The diagram below is out of the very basic Arduino Blink tutorial.

Arduino Blink

Since the official Arduino tutorials themselves utilize this tool, it's become quite popular with many people documenting their Arduino projects.

BeagleBone is used in pretty much the same way as an Arduino in terms of people interfacing all kinds of random devices to it, so I quickly found myself lamenting the fact that I didn't have Fritzing BeagleBone part to make diagrams. I'll admit it, I'm a poor artist...I can't stand freehand drawing stuff as it's time consuming and I'm always disappointed in the end product. When I was working on slideware for my SPI framebuffer driver ELC session, it was driving me nuts trying to get a nice slide-worthy diagram showing how the display was interfaced to the BeagleBone.

Creating the Part

Fast forward to a couple months ago, I finally realized that if I was going to retain my sanity while documenting various projects I have on the BeagleBone, I needed a Fritzing part. So I fumbled around learning Inkscape and how line-up the graphical female pin headers with the Fritzing connector nodes and my good friend, Ken Keller, went through the painful iterations of labeling all of the pin-muxed pins very nicely. The end result is I can now quickly create drawings like the BeagleBone SPI display interface used in the ST7735 framebuffer driver.
BeagleBone SPI Display

Both the BeagleBone and Adafruit 1.8" LCD parts seen above are found in my Github fritzing-parts repo.

Getting Started with Fritzing and BeagleBone

I only use Linux and OSX...if you are using Windows, you are out of luck here. Please see the platform-specific installation and starting instructions for your system.

Download and install Fritzing (Linux or OSX please)
Clone the fritzing-parts repo
    cd ~
    git clone git://
Link the fritzing-parts repo to the Fritzing user directory's parts directory. This allows one to git pull in updates and/or fork and add your own experimental parts in the user directory so that Fritzing updates do not overwrite your parts.
    ln -sf ~/fritzing-parts/parts ~/.config/Fritzing/parts
Start Fritzing
Click the magnifying glass search tool in the parts pane

Type in beagle and it will search and show the BeagleBone icon

Drag and drop the BeagleBone part into the sketch window. Notice that this is the Fritzing Breadboard View.

We will now interface an LED to a GPIO line on the BeagleBone.

Hover over the bottom connector, P9. Connector P9, pin 27 carries a GPIO signal that can be used.

Notice that the Beaglebone part displays the complete signal information for each pin exposed on the expansion headers. In this case, pin P9-27 carries GPIO3_19 when configured in pinmux Mode 7. This popup reference is very useful when designing or breadboarding an interface.

In order to complete the simple LED interface, an LED and a resistor can be pulled from the core parts bin. These parts are placed on the virtual breadboard and wired as shown below.

LED Breadboard View

Fritzing also supports a schematic view.  Ff we wanted a neatly formatted schematic of our breadboarded LED circuit, we simply switch to schematic view using the view switcher or View menu options. Once in schematic view, each wire connection made in the breadboard view is visible as temporary rats nest wires. The schematic drawing can be completed by converting each rats nest wire to a connection and tidying up the rotation and orientation of  schematic elements with a little drag and drop housecleaning.

LED Schematic View

That's it! For more detailed documentation and tutorials on building up Fritzing sketches see the Learning Fritzing pages.

Thursday, June 7, 2012

BeagleBone and Adafruit 1.8" SPI LCD

Back about the time the BeagleBone was released, I spent some time on interfacing and writing a Linux framebuffer driver for the Adafruit 1.8" SPI LCD.

Some time later, I did a presentation at ELC (.us) 2012 on this project. The slides and video are available, however, there was a technical issue during the session that caused the audio feed to drop out at the 13:48 mark. Luckily, the great folks at Free Electrons were also recording their usual ELC videos and you can watch the entire session with audio.

Since then, I've been working on a Fritzing part for the BeagleBone and I decided to circle back and show a nice diagram of how one can interface the BeagleBone with the LCD.

As you can see, it's a pretty simple interface. Three SPI signals (output only to this display) and the out-of-band Reset and Data/Command signals which are driven by two GPIOs.

For the framebuffer driver, I leveraged an earlier version of the ST7735 Arduino library. The current Arduino library now supports multiple variants of the display that require different initialization. Although I haven't yet incorporated support for the other board, the current working st7735fb driver is available in my github linux repo st7735 branch. Please note that it's important to disable framebuffer console (just like in the top level directory's defconfig I commited), else the kernel will lock up on boot due to a bug.

Going forward, the driver plan is:

  • Merge PWM backlight support from Matt Ranostay
  • Add support for pdata configurable display variants (fixes other display shipping)
  • Debug the fbcon lockup issue
  • Support and test on Beagleboard xM with level shifters
  • Send upstream
In the meantime, you can see what some other folks have built on top of the st7735fb framebuffer driver with these videos of Enlightenment and Mplayer dishing out the ubiquitous Big Buck Bunny.