Adventures in BeagleBone Cape EEPROMs

Recently I had to figure out how to put data into a BeagleBone Cape EEPROM. It was not a hard thing to do but I figured I would document it because I could not find this information anywhere…

In this post, I will show two methods to prepare the data for the EEPROM. One method will be using bonescript files that are provided in the CircuitCo factory images. The other method will be using a small utility I made to prompt for the data.

Before you start to develop data for the EEPROM, you should become familiar with the data stored in the EEPROM. This information is in the BeagleBone SRM. The current version of this document is located here:

http://beagleboard.org/static/beaglebone/latest/Docs/Hardware/BONE_SRM.pdf

The Cape EEPROM information is located in section “8.0  Cape Board Support“. Here is a quick summary of the data for the current version of the EEPROM (“A0″).

Name

Offset

Size (bytes)

Contents

Header

0

4

0xAA, 0x55, 0x33, 0xEE

EEPROM Format Revision

4

2

Revision number of the overall format of this
EEPROM in ASCII =A0

Board Name

6

32

Name of board in ASCII

Version

38

4

Hardware version code for board in ASCII

Manufacturer

42

16

ASCII name of the manufacturer

Part Number

58

16

ASCII Characters for the part number

Number of Pins

74

2

Number of pins used by the daughter board

Serial Number

76

12

Serial number of the board. This is a 12 character
string which is: WWYY4P13nnnn
where: WW = 2 digit week of the year of production
YY = 2 digit year of production
nnnn = incrementing board number

Pin Usage

88

148

Two bytes for each configurable 74 pins on the
expansion connectors

Bit 15: Pin is used or not; 0=Unused by
Cape 1=Used by Cape

Bit 14-13: Pin Direction; 1 0=Output 01=Input
11=BDIR
Bits 12-7: Reserved
Bit 6: Slew Rate; 0=Fast 1=Slow

Bit 5: Rx Enable; 0=Disabled 1=Enabled
Bit 4: Pull Up/Dn Select; 0=Pulldown 1=PullUp
Bit 3: Pull Up/DN enabled; 0=Enabled 1=Disabled

Bits 2-0: Mux Mode Selection; Mode 0-7

VDD_3V3EXP Current

236

2

Maximum current in milliamps

VDD_5V Current

238

2

Maximum current in milliamps

SYS_5V Current

240

2

Maximum current in milliamps

DC Supplied

242

2

Indicates whether or not the board is supplying
voltage on the VDD_5V rail and the current rating 000=No 1-0xFFFF is the
current supplied

Available

244

32543

Available space for other non-volatile codes/data

NOTE: The offset of the Part Number field is incorrect in the current version of the BeagleBone SRM (Rev A5.0.1). I corrected it here.

All of the examples and work was developed on the CircuitCo factory BeagleBone image for A6. Everything was tested and ran on both a BeagleBone revision A5 and A3. The image can be downloaded here:

http://circuitco.com/support/index.php?title=BeagleBone#Revision_A6_Image

Bonescript

This section will give instructions on how to make the EEPROM data file using bonescript.

The first thing to do is to make sure you are using the latest bonescript. +Boris has been making many great changes recently. To update your bonescript…

# cd /var/lib/cloud9/
# git pull

I will use some of the bonescript to make the data file that has all of the EEPROM data in it. To help contain everything in one spot, I usually copy the appropriate bonescript file to a local directory.

# cd
# mkdir eeprom
# cd eeprom
# cp /var/lib/cloud9/bonescript/eeprom.js .
# cp /var/lib/cloud9/bonescript/bone.js .

The eeprom.js file contains routines that parse and make the data in the EEPROMs. The bone.js file contains the fundamental BeagleBone hardware definitions. If you run eeprom.js (using node) with a “-h” option it will give you a small explanation of how to use it from the command line…

# node ./eeprom.js -h
Print usage:
  node bonescript/eeprom.js -h

Read eeproms and write the output to a JSON-compatible file:
  node bonescript/eeprom.js [-r [type:source.eeprom ...] destination.json] 
    type               : the word "bone" or "cape"
    source.eeprom      : source eeprom file

Read JSON eeproms file and write the output to eeprom(s):
  node bonescript/eeprom.js -w source.json [[source-eeprom] destination.eeprom]
    source.json        : source JSON file containing one or more eeprom structures
    destination.eeprom : where to write the output,
                         must either match eeprom structure name or
                         provide a source-eeprom parameter
    source-eeprom      : which eeprom structure to use as source

The command line functions all deal with EEPROM data in a JSON file. These functions either read the EEPROM data from the Cape (or BeagleBone itself) or prepares data to be written to the EEPROM. (Know what a JSON file is? See http://en.wikipedia.org/wiki/JSON). These routines also make EEPROM data files for the BeagleBone itself. I will not cover this in this entry. Example of a JSON file for a Cape EEPROM…

# cat data1.json                       
{
 "Display-Cape.eeprom": {
    "type": "cape",
    "header": "aa5533ee",
    "formatRev": "A0",
    "boardName": "Nokia 5110 Display Cape",
    "version": "01",
    "manufacturer": "CabinProgramming",
    "partNumber": "000100-001",
    "numPins": 2,
    "serialNumber": "00000000001",
    "currentVDD_3V3EXP": 40,
    "currentVDD_5V": 0,
    "currentSYS_5V": 0,
    "DCSupplied": 0,
    "mux": {
      "P8_46": {
        "used": "used",
        "direction": "out",
        "pullup": "pulldown",
        "rx": "disabled",
        "mode": 7,
        "function": "gpio2_7"
      },
      "P8_45": {
        "used": "used",
        "direction": "out",
        "pullup": "pullup",
        "slew": "fast",
        "mode": 7,
        "function": "gpio2_6"
      }
    }
  }
}

As you can see, the data is presented in a readable manner and is not that hard to understand. Here is a list of key words and the values that they can have…

  • type: “cape” or “bone”
  • header: “aa5533ee” (Defined in this version of the EEPROM spec)
  • formatRev: “A0″ (Defined in this version of the EEPROM spec)
  • boardName: Your Cape name in ASCII and in quotes
  • version: Your version number in ASCII and in quotes
  • manufacturer: Manufacturer name in ASCII and in quotes
  • partNumber: Your part number in ASCII and in quotes
  • numPins: Number of I/O pins used in your design. Needs to match the number of mux: data entries.
  • serialNumber: Your serial number in ASCII and in quotes. Note: See the suggested format in the SRM and the table above.
  • currentVDD_3V3EXP: Maximum current drawn in milliamps (Range 0 to 250)
  • currentVDD_5V: Maximum current drawn in milliamps (Range 0 to 250)
  • currentSYS_5V: Maximum current drawn in milliamps (Range 0 to 1000)
  • DCSupplied: Amount of current in supplied milliamps on the VDD_5V rail by the Cape. (Range 0 to 65535)
  • used: “used” or “available”
  • direction: “in” or “out” or “bidir”
  • pullup: “disabled” or “pullup” or pulldown”
  • rx: “enabled” or “disabled”
  • slew: “slow” or “fast”
  • mode: Mode mux value (Range 0 to 7)

A good example of a complex multi Cape EEPROM JSON file is in:  /var/lib/cloud9/bonescript/test-eeproms.json on the BeagleBone.

To turn the JSON file into an EEPROM data file you issue the following command (this example has the JSON file named “data1.json” ):

# node ./eeprom.js -w data1.json

This command writes a file to the current directory with the name specified in the JSON file. In my example above, it would be: “Display-Cape.eeprom”.

If you want to check the EEPROM file, use the hex dump command…

# hexdump -C Display-Cape.eeprom 
00000000  aa 55 33 ee 41 30 4e 6f  6b 69 61 20 35 31 31 30  |.U3.A0Nokia 5110|
00000010  20 44 69 73 70 6c 61 79  20 43 61 70 65 00 00 00  | Display Cape...|
00000020  00 00 00 00 00 00 30 31  00 00 43 61 62 69 6e 50  |......01..CabinP|
00000030  72 6f 67 72 61 6d 6d 69  6e 67 30 30 30 31 30 30  |rogramming000100|
00000040  2d 30 30 31 00 00 00 00  00 00 00 02 30 30 30 30  |-001........0000|
00000050  30 30 30 30 30 30 31 00  00 00 00 00 00 00 00 00  |0000001.........|
00000060  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000b0  00 00 c0 17 c0 07 00 00  00 00 00 00 00 00 00 00  |................|
000000c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 28 00 00  |.............(..|
000000f0  00 00 00 00                                       |....|
000000f4

See the “How to Program the EEPROM” section of this post on how to write this file to the EEPROM on the cape…

Utility Program

As an alternate method to make the EEPROM data, I wrote a simple utility to walk you through inputting the data needed. This is a very simple program and is not very fancy but gets the job done. It uses gets() so be prepared for a warning when you compile the utility.  I do not plan on going through all of the design details of the program but will show you where to get the source, how to compile it and use it.

Source is located here… mkeeprom.c

To compile and use the program do this…

# cd
# mkdir utility
# cd utility
<get file source and put the file in here>
# make mkeeprom
cc     mkeeprom.c   -o mkeeprom
/tmp/cciVqrCD.o: In function `main':
mkeeprom.c:(.text+0xe8): warning: the `gets' function is dangerous and should not be used.
# ./mkeeprom 

---EEPROM MAKER---

This is a program to make the EEPROM data file for a BeagleBone Cape.

This program produces an output file named: data.eeprom
The data file follows EEPROM Format Revision 'A0'
This data file can be put in the BeagleBone EEPROM by this command on a BeagleBone:
   > cat data.eeprom >/sys/bus/i2c/drivers/at24/3-005x/eeprom
         Where:  5x is 54, 55, 56, 57 depending on Cape addressing.
         NOTE:  See blog.azkeller.com for more details.

+++ No warranties or support is implied - sorry for CYA +++

Enter Name of Board in ASCII (max 32): Nokia 5110 Display Cape
Enter HW Version of Board in ASCII (max 4): 01
Enter Name of Manufacturer in ASCII (max 16): CabinProgramming
Enter Part Number in ASCII (max 16): 000100-001
Enter Serial Number in ASCII (max 16): 00000000001
Enter MAX Current (mA) on VDD_3V3EXP Used by Cape (Range 0 to 250mA): 40
Enter MAX Current (mA) on VDD_5V Used by Cape (Range 0 to 1000mA): 0
Enter MAX Current (mA) on SYS_5V Used by Cape (Range 0 to 250mA): 0
Enter Current (mA) Supplied on VDD_5V by Cape (Range 0 to 65535mA): 0

Enter Number of Pins Used by Cape (Range 0 to 74): 2

Get data for pin 1
    PIN # 1 - Enter Connector number (8 or 9): 8
    PIN # 1 - Enter pin number (1 through 46): 46
    PIN # 1 P8_46 - Usage? 1=pin used, 0=unused: 1
    PIN # 1 P8_46 - Type? 1=input, 2=output, 3=bidirectional: 2
    PIN # 1 P8_46 - Slew? 0=fast, 1=slow: 0
    PIN # 1 P8_46 - RX Enabled? 0=disabled, 1=enabled: 0
    PIN # 1 P8_46 - Pullup or Pulldown? 0=pulldown, 1=pullup: 0
    PIN # 1 P8_46 - Pull up-down Enabled? 0=enabled, 1=disabled: 0
    PIN # 1 P8_46 - Pin Mux Mode? (0 through 7): 7

Get data for pin 2
    PIN # 2 - Enter Connector number (8 or 9): 8
    PIN # 2 - Enter pin number (1 through 46): 45
    PIN # 2 P8_45 - Usage? 1=pin used, 0=unused: 1
    PIN # 2 P8_45 - Type? 1=input, 2=output, 3=bidirectional: 2
    PIN # 2 P8_45 - Slew? 0=fast, 1=slow: 0
    PIN # 2 P8_45 - RX Enabled? 0=disabled, 1=enabled: 0
    PIN # 2 P8_45 - Pullup or Pulldown? 0=pulldown, 1=pullup: 1
    PIN # 2 P8_45 - Pull up-down Enabled? 0=enabled, 1=disabled: 0
    PIN # 2 P8_45 - Pin Mux Mode? (0 through 7): 7

Creating output file... ./data.eeprom

Now you have an EEPROM data file…

How to Program the EEPROM

The following section describes how to get the EEPROM data file into your Cape EEPROM. The pin numbering used is the same as on the schematic in the BeagleBone SRM section “8.1  EEPROM“.

BeagleBone Capes should have an address selection on each board. This may be in the form of switches, jumpers or resistors soldered in place. The BeagleBone Cape I am using to do my prototype work on is the FlyingBone Prototype Cape (https://github.com/piranha32/FlyingBone). This uses a set of jumpers to perform the addressing. The addressing becomes important because you need it to find out where to copy the data. Here is a table showing the addressing scheme…

Pin Grounded

Location of EEPROM

NONE

/sys/bus/i2c/drivers/at24/3-0057/eeprom

A0

/sys/bus/i2c/drivers/at24/3-0056/eeprom

A1

/sys/bus/i2c/drivers/at24/3-0055/eeprom

A0 and A1

/sys/bus/i2c/drivers/at24/3-0054/eeprom

Now that you have the location of the EEPROM driver, it is simply a matter of copying the data to the EEPROM using “cat”.

# cat data.eeprom >/sys/bus/i2c/drivers/at24/3-0057/eeprom

And now you are done…

A Little More on EEPROMs

If you want to check what is in the EEPROMs, you can run the eeprom.js and get a listing of all of the  EEPROMs including the BeagleBone’s EEPROM. Note in my example below, that I have one Cape installed with A0 and A1 grounded (/sys/bus/i2c/drivers/at24/3-0054/). All of the other EEPROM locations show “Error: ETIMEDOUT, connection timed out”.

# node ./eeprom.js
Reading EEPROM at /sys/bus/i2c/drivers/at24/1-0050/eeprom
Reading EEPROM at /sys/bus/i2c/drivers/at24/1-0051/eeprom
Unable to open EEPROM at /sys/bus/i2c/drivers/at24/1-0051/eeprom: Error: ETIMEDOUT, connection timed out
Reading EEPROM at /sys/bus/i2c/drivers/at24/3-0054/eeprom
Reading EEPROM at /sys/bus/i2c/drivers/at24/3-0055/eeprom
Unable to open EEPROM at /sys/bus/i2c/drivers/at24/3-0055/eeprom: Error: ETIMEDOUT, connection timed out
Reading EEPROM at /sys/bus/i2c/drivers/at24/3-0056/eeprom
Unable to open EEPROM at /sys/bus/i2c/drivers/at24/3-0056/eeprom: Error: ETIMEDOUT, connection timed out
Reading EEPROM at /sys/bus/i2c/drivers/at24/3-0057/eeprom
Unable to open EEPROM at /sys/bus/i2c/drivers/at24/3-0057/eeprom: Error: ETIMEDOUT, connection timed out
Reading EEPROM at test-bone.eeprom
Unable to open EEPROM at test-bone.eeprom: Error: ENOENT, no such file or directory 'test-bone.eeprom'
Reading EEPROM at test-cape.eeprom
Unable to open EEPROM at test-cape.eeprom: Error: ENOENT, no such file or directory 'test-cape.eeprom'
{
  "/sys/bus/i2c/drivers/at24/1-0050/eeprom": {
    "header": "aa5533ee",
    "boardName": "A335BONE",
    "version": "00A5",
    "serialNumber": "0812BB000028",
    "configOption": "0000000000000000000000000000000000000000000000000000000000000000",
    "type": "bone"
  },
  "/sys/bus/i2c/drivers/at24/3-0054/eeprom": {
    "header": "aa5533ee",
    "formatRev": "A0",
    "boardName": "Nokia 5110 Display Cape",
    "version": "01",
    "manufacturer": "Cabin Programs",
    "partNumber": "CB0100-001",
    "numPins": 9,
    "serialNumber": "00000000001",
    "currentVDD_3V3EXP": 40,
    "currentVDD_5V": 0,
    "currentSYS_5V": 0,
    "DCSupplied": 0,
    "mux": {
      "P8_40": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_13"
      },
      "P8_41": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_10"
      },
      "P8_42": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_11"
      },
      "P8_43": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_8"
      },
      "P8_44": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_9"
      },
      "P8_45": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_6"
      },
      "P8_46": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 7,
        "function": "gpio2_7"
      },
      "P9_30": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 3,
        "function": "spi1_d1"
      },
      "P9_31": {
        "used": "used",
        "direction": "out",
        "slew": "fast",
        "rx": "disabled",
        "pullup": "pulldown",
        "mode": 3,
        "function": "spi1_sclk"
      }
    },
    "type": "cape"
  }
}

 

BeagleBone POST handler… Get access to digital inputs, outputs, analog inputs and SPI (via shiftOut( ) )

I have been working on interfacing the BeagleBone to a client run on a mobile phone. In doing this, I needed a POST request handler running on the BeagleBone. So after a little reading and learning, I developed this project. It allows a client to query the BeagleBone via HTML POST requests. Access is given to digital and analog inputs, setting digital outputs and send commands to devices attached to the BeagleBone via the Arduino like shiftOut() SPI interface in node.js / Cloud9.

The code has two parts… server code that runs on the BeagleBone in Cloud9 and client code that runs on a remote system in a compatible browser. The client code is just an HTML page that displays all of the analog inputs (updated every 5 seconds), displays BeagleBone GPIO input pins updated every second (currently configured for three inputs), HTML buttons to toggle USR3 LED on/off, and a series of buttons to send complex digital outputs and SPI commands to an off board MSP430 that I am using to control steppers, servos, PWM and misc.digital outputs (that project will be discussed later in a different entry). The code can be found on my GitHub site:  https://github.com/kkeller/BBone-POST-Server

Client HTML page

Client side…

I have written a series of javascript functions that can be used on the client HTML page to build the POST and return values. This makes the use of the POST functionality simple and easy to use. For example, if you want a button to set a GPIO output on pin P8_43, then this would be the HTML code needed in the <body> section of the page:

<BODY>
  <script type="text/javascript">
      init('P8_43','OUTPUT');
  </script>
  <button type="button" onclick="digout('P8_43','HIGH')">BeagleBone P8_43 ON</button>
</BODY>

As you can see, I choose to use the pin names in the functions. This should hopefully be easy to use. See the list at the end of this post. Here is the list of routines that I have made in the client test program:

  • value = analog ( analog# );
  • init ( pin, dir );
  • digout ( pin, value );
  • value = digin ( pin );
  • shiftout ( datapin, clockpin, bitorder, value );

POST handler side…

The POST requests are very simple and can interface into the node.js / cloud9 Bonescript functions.

analogRead() interface:
 - http://<BBone IP>:8888/analog?pin=[0-7]
   example:  http://192.168.1.119:8888/analog?pin=0

pinMode() interface:
 - http://<BBone IP>:8888/init?pin=[see below]&value=[INPUT,OUTPUT]
   example:  http://192.168.1.119:8888/init?pin=P8_43&value=OUTPUT

digitalRead() interface:
 - http://<BBone IP>:8888/input?pin=[see below]
   example:  http://192.168.1.119:8888/input?pin=P8_42

digitalWrite() interface:
 - http://<BBone IP>:8888/output?pin=[see below]&value=[HIGH,LOW,0,1]
   example:  http://192.168.1.119:8888/output?pin=USR3&value=HIGH

shiftOut() interface (SPI using digital outputs):
 - http://<BBone IP>:8888/shift?data=[see below]&clock=[see below]&order=[LSBFIRST,MSBFIRST]&value=[0-0xff]
   example:  http://192.168.1.119:8888/shift?data=P8_43&clock=P8_44&order=LSBFIRST&value=0x20

Source code contents…

Server (run on BeagleBone using cloud9)

  • index.js : main file – run this file to start the POST server
  • server.js : creates the actual server
  • router.js : routes request to handler or 404 page
  • requestHandler.js : file with all of the handlers

client (run on remote system using a web browser)

  • test.html : test page for remote browser
  • analog.html : iframe page to display analogs every 5 seconds
  • input.html : iframe page to display digital inputs every second

Boring video…

Here is a boring video of the LEDs, servo, steppers operating.

BeagleBone operating with POST commands (m4v)

Pin names used in the calls or POSTs…

Possible “pin” names for init, output, input, shiftOut POST requests and init, digin, digout, shiftout and analog client javascript commands.

NOTE: Depending on your Linux configuration, some of these pins maybe used by other drivers or system functions.

"pin"     SIGNAL
======  =========
 P8_3   "GPIO1_6"
 P8_4   "GPIO1_7"
 P8_5   "GPIO1_2"
 P8_6   "GPIO1_3"
 P8_7   "TIMER4"
 P8_8   "TIMER7"
 P8_9   "TIMER5"
 P8_10  "TIMER6"
 P8_11  "GPIO1_13"
 P8_12  "GPIO1_12"
 P8_13  "EHRPWM2B"
 P8_14  "GPIO0_26"
 P8_15  "GPIO1_15"
 P8_16  "GPIO1_14"
 P8_17  "GPIO0_27"
 P8_18  "GPIO2_1"
 P8_19  "EHRPWM2A"
 P8_20  "GPIO1_31"
 P8_21  "GPIO1_30"
 P8_22  "GPIO1_5"
 P8_23  "GPIO1_4"
 P8_24  "GPIO1_1"
 P8_25  "GPIO1_0"
 P8_26  "GPIO1_29"
 P8_27  "GPIO2_22"
 P8_28  "GPIO2_24"
 P8_29  "GPIO2_23"
 P8_30  "GPIO2_25"
 P8_31  "UART5_CTSN"
 P8_32  "UART5_RTSN"
 P8_33  "UART4_RTSN"
 P8_34  "UART3_RTSN"
 P8_35  "UART4_CTSN"
 P8_36  "UART3_CTSN"
 P8_37  "UART5_TXD"
 P8_38  "UART5_RXD"
 P8_39  "GPIO2_12"
 P8_40  "GPIO2_13"
 P8_41  "GPIO2_10"
 P8_42  "GPIO2_11"
 P8_43  "GPIO2_8"
 P8_44  "GPIO2_9"
 P8_45  "GPIO2_6"
 P8_46  "GPIO2_7"
 P9_11  "UART4_RXD"
 P9_12  "GPIO1_28"
 P9_13  "UART4_TXD"
 P9_14  "EHRPWM1A"
 P9_15  "GPIO1_16"
 P9_16  "EHRPWM1B"
 P9_17  "I2C1_SCL"
 P9_18  "I2C1_SDA"
 P9_19  "I2C2_SCL"
 P9_20  "I2C2_SDA"
 P9_21  "UART2_TXD"
 P9_22  "UART2_RXD"
 P9_23  "GPIO1_17"
 P9_24  "UART1_TXD"
 P9_25  "GPIO3_21"
 P9_26  "UART1_RXD"
 P9_27  "GPIO3_19"
 P9_28  "SPI1_CS0"
 P9_29  "SPI1_D0"
 P9_30  "SPI1_D1"
 P9_31  "SPI1_SCLK"
 P9_41  "CLKOUT2"
 P9_42  "GPIO0_7"
 USR0   "USR0"    
 USR1   "USR1"     
 USR2   "USR2"       
 USR3   "USR3"