BeagleBone Black and OSD335x EEPROM during boot

There is a 32Kbit (4KB) EEPROM that is used by software such as u-boot to identify the board.

If you have developed your own board, then the contents of the EEPROM will initially be blank, which can make life ‘interesting’, as there is no information for any of the software to configure itself.

Table of EEPROM Fields

NameOffsetSize (Bytes)Description
Header04The BeagleBone Magic Number 0xAA 0x55 0x33 0xEE
Board Name48The name of the board in ASCII - e.g. A335BNLT for the BeagleBone Black
Version124The board revision in ASCII
Serial Number1612A 12 character string which comprises of:

  • 2 digit week of the year of production

  • 2 digit year of production

  • 4 character board type (e.g. BBBK is BeagleBone Black)

  • 4 digit incrementing board number

Configuration Options2832The configuration of the board - normally all 0xFF
Reserved 1606All 0xFF
Reserved 2666All 0xFF
Reserved 3726All 0xFF
User Data784018Available for user data. Initially, it will be all 0xFF

Reading the EEPROM

The EEPROM is connected via the i2c on I2C0 with a device address of 0x50

The contents of the EEPROM are available from Userspace using the file /sys/bus/i2c/devices/0-0050/eeprom

As the contents of the EEPROM are raw bytes, you may find it useful to use a utiliy such as hexdump to display the data.

Using hexdump

A simple format for using hexdump is:

hexdump -e "FORMAT STRING" FILENAME -s START_BYTE -n NUMBER_OF_BYTES_TO_READ

You can find the byte range to read from the table above, so to read the Board Name use:

hexdump -e '8/1 "%c"' /sys/bus/i2c/devices/0-0050/eeprom -s 4 -n 8

Other Methods

Given that the EEPROM is just a file, you can use any utility you wish that can read raw files. As an example, I have written a small Python3 utility to read the EEPROM that is available on GitHub

Understanding the EEPROM fields

Most of the fields are relevent to u-boot during the boot process, as this allows a single u-boot binary to be able to boot multiple boards – which can be quite useful if you have many different board designs.

Header or Magic Number

The header bytes are read by u-boot to identify that the board is a BeagleBone.

Board Name and Version

U-boot will use the board name and Version for further configuration. The characters A335 means that the board is using an ARM 335x chip. The next 4 characters help identify the name of board.

Options for the name include:

  • BNLT – BeagleBone
  • BLNK – A black board, in which case u-boot will look for a file /boot/.eeprom.txt which it will then use to program the EEPROM.
  • PBGL – The PocketBeagle

Serial Number

If you are using a standard BeagleBone, then the serial will already be programmed in. However, if you have designed your own, then you will need to design your own serial numbering scheme. It can be useful to have access to the serial number, as that can then identify the exact board for things like debugging and checking failure rates.

User Data

The 4018 bytes of user data can be used to store any information you want. I have found it useful when using bespoke boards to hold system specific information that then allows a single system image to be used for multiple board types.

Writing to the EEPROM

Given that u-boot uses the fields in the EEPROM for configuration, if you have a blank EEPROM, you will probablly need to populate at least the magic number and board name – possibly the version as well.

The simplest way to program the EEPROM is from u-boot during boot time. There are two ways you can do this:

  • Intractively
  • Using a boot script

Programming the EEPROM interactively

If you can access the u-boot console during boot, then you can interactively program the EEPROM. Accessing the console is only possible if you have a bootdelay option set in your uEnv.txt file such as:

bootdelay=2

If you have a serial connection open, you should see something like:

U-Boot SPL 2019.04-00002-gbb4af0f50f (Jul 08 2019 - 11:44:39 -0500)
Trying to boot from MMC1
Loading Environment from EXT4... ** File not found /boot/uboot.env **

** Unable to read "/boot/uboot.env" from mmc0:1 **


U-Boot 2019.04-00002-gbb4af0f50f (Jul 08 2019 - 11:44:39 -0500), Build: jenkins-github_Bootloader-Builder-128

CPU  : AM335X-GP rev 2.0
I2C:   ready
DRAM:  512 MiB
No match for driver 'omap_hsmmc'
No match for driver 'omap_hsmmc'
Some drivers were not found
Reset Source: Global warm SW reset has occurred.
Reset Source: Power-on reset has occurred.
RTC 32KCLK Source: External.
MMC:   OMAP SD/MMC: 0, OMAP SD/MMC: 1
Loading Environment from EXT4... ** File not found /boot/uboot.env **

** Unable to read "/boot/uboot.env" from mmc0:1 **
Board: BeagleBone Black
<ethaddr> not set. Validating first E-fuse MAC
BeagleBone Black:
BeagleBone: cape eeprom: i2c_probe: 0x54:
BeagleBone: cape eeprom: i2c_probe: 0x55:
BeagleBone: cape eeprom: i2c_probe: 0x56:
BeagleBone: cape eeprom: i2c_probe: 0x57:
Net:   eth0: MII MODE
cpsw, usb_ether
Press SPACE to abort autoboot in 2 seconds
=>

Knowing that the EEPROM is on I2C0, you can set the i2c device and use the u-boot i2c commands to read and write the EEPROM. The format of the write command is:

i2c mw DEVICE_ADDRESS BYTE_NUMBER.2 HEX_VALUE

An example would be:

// Set i2c device
i2c dev 0

// Set the header “magic number”:  0xAA5533EE
i2c mw 0x50 0x00.2 aa
i2c mw 0x50 0x01.2 55
i2c mw 0x50 0x02.2 33
i2c mw 0x50 0x03.2 ee

// Set the Board name (bytes 0 – 4):  “A335”
i2c mw 0x50 0x04.2 41
i2c mw 0x50 0x05.2 33
i2c mw 0x50 0x06.2 33
i2c mw 0x50 0x07.2 35

// Set the Board name (bytes 4 – 7):  “BNLT”
i2c mw 0x50 0x08.2 42
i2c mw 0x50 0x09.2 4e
i2c mw 0x50 0x0a.2 4c
i2c mw 0x50 0x0b.2 54

// Set the Board version - only required for BeagleBone devices.
i2c mw 0x50 0x0c.2 30
i2c mw 0x50 0x0d.2 41
i2c mw 0x50 0x0e.2 35
i2c mw 0x50 0x0f.2 43

You can then read the values back using the u-boot i2c read commands

=> i2c dev 0
Setting bus to 0
=> i2c md 0x50 0x00.2 20
0000: aa 55 33 ee 41 33 33 35 42 4e 4c 54 30 41 35 43    .U3.A335BNLT0A5C
0010: 32 38 31 33 42 42 42 4b 33 32 37 36 ff ff ff ff    2813BBBK3276....
=>
         

Using a script to program the EEPROM

As part of the boot process, u-boot will look for a file called /boot/boot.scr and if it finds it, will run it.

Unfortunately, this is not a simple text file, but is a compiled file using the mkimage tool from u-boot. This tool is created as part of the u-boot build process. (There is an article on compiling u-boot here)

In order to create the /boot/boot.scr, first create a text file that contains the u-boot commands you want to run, such as the commands to program the EEPROM above.

You then compile the source into the /boot/boot.scr using the command:

mkimage -T script -C none -n 'Program EEPROM' -d SOURCE_FILE boot.scr

Copy the boot.scr to /boot/boot.scr and reboot. This should then set the values in your EEPROM.