Compiling BeagleBone Kernel and Making a Kernel Module.

In my process of learning Linux and the BeagleBone, I have needed to compile the CircuitCo standard released kernel and to make kernel modules. This post will give a brief overview of how I have accomplished this and hopefully help out others that seem to be struggling in the same area.

First I would like to thank several long time friends and past co-workers for their help and patience in helping me get over some of the hurdles I have encountered. Thanks goes to Matt Porter (http://engineersofthecorn.blogspot.com) and Mark Greer of Animal Creek Technologies (mgreer@animalcreek.com) for their continued friendship and assistance in git and Linux.

Note: All of this blog entry was performed as root. If you are not root then there is a good chance you will have to proceed the commands with “sudo” to not get errors.

Step #1 – Getting a Linux Development Environment

If you have a Linux system set up already, skip to step #2.

Instead of going through what is needed in a Linux development environment, I’ll just point you to what I was pointed to when I first started. The link below is a virtual machine based on the VMware architecture that has everything you need to get started except the cross environment tools.

http://www.trendsigma.net/vmware/lubuntu1110t.zip

This image can be used on Windows (by VMware Player – http://www.trendsigma.net/vmware/vmwareplayer.html ) or on a MAC (by Parallels – http://www.parallels.com ). If you want to see details on this,  see http://www.trendsigma.net/vmware/lubuntu1110t.html.

Step #2 – Getting Cross Development Tools

Once you get the Linux up and going, login as root (note: on kernel above acct and password are:  “root” and “password”) and get a terminal window up. In the terminal window issue the following command:

# apt-get install build-essential gcc-arm-linux-gnueabi git lzop u-boot-tools

This command will download and install:

Step #3 – Find Out What Kernel Branch is Used on a CircuitCo Release

In this section we will determine what makes up the current CircuitCo kernel .To do this, we will need to load up the kernel and boot it. The BeagleBone CircuitCo standard releases are located here: http://circuitco.com/support/index.php?title=BeagleBone. At the time of this writing, the latest version (Revision A6 Image) is located here. All of the examples are based on this Linux 3.2.18 based A6 image.

Follow the instructions on how to make an SD card and boot it on your BeagleBone. From a terminal window do the following command…

# opkg list_installed | grep kernel-image-3.2.18
kernel-image-3.2.18 - 3.2.18-r12j+gitr720e07b4c1f687b61b147b31c698cb6816d72f01

We are interested in the long string after the kernel image. This is the branch that the kernel was made from. Copy it down or copy/paste it somewhere for reference in the next step.

Step #4 – Git the Linux Kernel

Note:  There is a lot of commands below that are for the git revision control system. I am not going to get into detail on what these commands do or how git works. If you need help or background, see this page for a list of the Top 10 Git Tutorials for Beginners.

In this step you will get (or clone) the Linux kernel repository used by CircuitCo and set up the branch that makes up the current kernel from CircuitCo.

The BeagleBone Linux kernel that is used is located in Koen Kooi’s Linux github repository. In your Linux development system start a terminal widow and execute the commands below. Be warned, the first command will take a while to complete depending on your network connection and system performance. Also, the output from the commands are omitted due to the length of the output.

# git clone git://github.com/koenkooi/linux.git
# cd linux
# git checkout remotes/origin/linux-ti33x-psp-3.2.18-r12j+gitr720e07b4c1f687b61b147b31c698cb6816d72f01 -b beaglebone-a6

The first command will clone the repository on your system. This will make a snapshot of what has been checked in at this moment. This includes code that has been changed since the release we are trying to duplicate (A6) was produced.

The next two commands (cd and git checkout), set up a branch that contains the version of the source that was used to produce the A6 kernel. This is where the long string that was found in the previous step is used.

Check to make sure you are on the proper branch by doing the following and see that the asterisk “*” is located on the branch we made above (beaglebone-a6).
# git branch
 * beaglebone-a6
   master
#

And finally we need to get the firmware that the BeagleBone kernel needs. The kernel will need this binary PM firmware blob to build.

# wget -O firmware/am335x-pm-firmware.bin http://arago-project.org/git/projects/?p=am33x-cm3.git;a=blob_plain;f=bin/am335x-pm-firmware.bin;hb=HEAD

Step #5 – Build The Kernel…

And now that we have the proper tools, the kernel source and firmware blob we can start it building. In these steps we will make a directory to put the kernel we are building, copy the configuration file that was used and finally start the build.

# mkdir a6
# cp defconfig a6/.config
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- O=./a6 uImage modules

Note: Again I did not put in the output from the commands. The make command will take a fair amount of time depending on your system performance and output pages and pages.  Also note, the directory name ( “a6″ ) can be changed to anything you want it to be. But you will have to change the Makefile in the later kernel module build steps.

When the make command is completed, you have duplicated the CircuitCo A6 kernel and kernel modules. Now this has made all of the necessary directories, source and headers that are needed to easily build a kernel module. And if you wanted to, you could even replace the kernel and modules on the BeagleBone SD card and reboot the kernel. I’ll make another post later on how to do that as well as how to change the kernel configuration away form the default.

Step #6 – Making a New Kernel Module

In this section I will finally make a kernel module and get it on the BeagleBone. First steps will be to make a directory for building the kernel module, putting in some source (I have example source) and compiling the module.

The kernel module that I am going to build is my version of the “hello world” kernel module. It is a version of the hello_world.c program made into a kernel module and is a fairly common first kernel module. Do a little googling and you will see several versions of it on the internet. In my version (like others), a kernel message will be made when the module is added and when it is removed.

hello.c source here… ( kernel module )
#include <linux/module.h>       /* Needed by all modules */
#include <linux/kernel.h>       /* Needed for KERN_INFO */
#include <linux/init.h>         /* Needed for the macros */

static int __init hello_start(void)
{
    printk(KERN_INFO "Loading hello.ko module...\n");
    printk(KERN_INFO "Hello world\n");
    return 0;
}

static void __exit hello_end(void)
{
    printk(KERN_INFO "Goodbye: hello.ko exiting...\n");
}

module_init(hello_start);
module_exit(hello_end);

MODULE_DESCRIPTION("Example kernel module based on many sources on the internet.");
MODULE_AUTHOR("Ken Keller <kkeller@cabinprograms.com>");
MODULE_LICENSE("GPL");
Makefile source here… ( kernel module Makefile )
obj-m = hello.o
KDIR := /root/linux/a6
all:
    make -C $(KDIR) M=$(shell pwd) modules
clean:
    make -C $(KDIR) M=$(shell pwd) clean

Note: In the Makefile above, you will need to change the KDIR to point to the directory path where you compiled the kernel.

Here are the simple commands to make the kernel module. When these are done, you will have a hello.ko file that can be put in the kernel on the BeagleBone.

# cd
# mkdir kernel_mod
# cd kernel_mod
<get hello.c and Makefile source above and put the files in here>
# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

At this point, you need to copy the hello.ko kernel module over to the BeagleBone. I personally use the “scp” command to move files around. There are many different ways to do this so choose your favorite way. (I see need for another blog post on this subject…)

Once the kernel module is moved over, login to the BeagleBone and “cd” to where you moved the module. Below are the commands to install the module (insmod), check to see if the module was installed (lsmod) and remove (rmmod) the module into the kernel.

# insmod hello.ko
# lsmod
Module                  Size  Used by
hello                    738  0 
ip_tables               7829  0 
x_tables               14368  1 ip_tables
spidev                  3920  0 
g_mass_storage         24002  0 
rfcomm                 24289  0 
ircomm_tty             14015  0 
ircomm                  8515  1 ircomm_tty
irda                   85575  2 ircomm_tty,ircomm
hidp                   10079  0 
bluetooth             109011  4 rfcomm,hidp
rfkill                 14663  2 bluetooth
ipv6                  208881  16 
# dmesg | tail
[ 8307.639412] gpio_request: gpio-38 (sysfs) status -16
[ 8307.639424] export_store: status -16
[ 8307.639534] gpio_request: gpio-73 (sysfs) status -16
[ 8307.639546] export_store: status -16
[ 8307.639647] gpio_request: gpio-70 (sysfs) status -16
[ 8307.639659] export_store: status -16
[ 8307.639756] gpio_request: gpio-71 (sysfs) status -16
[ 8307.639767] export_store: status -16
[13479.961098] Loading hello.ko module...
[13479.961112] Hello world
# rmmod hello
# dmesg | tail
[ 8307.639424] export_store: status -16
[ 8307.639534] gpio_request: gpio-73 (sysfs) status -16
[ 8307.639546] export_store: status -16
[ 8307.639647] gpio_request: gpio-70 (sysfs) status -16
[ 8307.639659] export_store: status -16
[ 8307.639756] gpio_request: gpio-71 (sysfs) status -16
[ 8307.639767] export_store: status -16
[13479.961098] Loading hello.ko module...
[13479.961112] Hello world
[13511.073550] Goodbye: hello.ko exiting
#

Final comment…  This is a really long set of instructions and not much was said about what can go wrong. Believe me, there is a lot that go wrong. Good luck and hope it helps!

Note: All of this blog entry was performed as root. If you are not root then there is a good chance you will have to proceed the commands with “sudo” to not get errors.

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 LCD Cape

Here are some details on the BeagleBone LCD Cape I have been working on. The cape uses an Nokia 5110 LCD display. Along with the display, there are four buttons for general purpose use. The LCD is wired to the BeagleBone SPI interface and the four buttons are connected to the GPIO pins that are typically used for LCD interfacing.

I’ve developed a library of graphics routines to add in the use of the LCD Cape.

Direct to LCD routines:

lcdSetup() - initializes the interface and LCD
lcdGotoXY() - position cursor
lcdInverse() - inverse the LCD
lcdBitmap() - display a bitmap to the LCD
lcdCharacter() - display a character at current cursor position
lcdString() - display a character string at current cursor position
lcdClear() - clear the LCD display and set cursor to 0,0
lcdScrollInit()  -  clears the scroll area and init local vars
lcdScroll()  -  scrolls string one char, repeat call to scroll again
lcdScrollLength() - returns number to scroll string one time off screen
lcdProgressInit()  -  clears the scroll area and initializes local vars
lcdProgressBar()  -  draws a progress bar of value length - value from 0 to 100

Also available are a series of routines that draws in a frame buffer and then sends the frame buffer to the LCD at a later time.

initFB() - initalizes the frame buffer
clearFB() - clears the frame buffer
refreshFB() - refreshes the frame buffer to the LCD
bitmapFB() - sends a bitmap to the frame buffer
storFB() - makes a copy of the frame buffer
restorFB() - restores the frame buffer from the stored copy
DrawPoint() - draws a point (one pixel) 
DrawLine() - draws a line
DrawRectangle() - draws a rectangle
DrawRoundRect() - draws a rectangle with rounded corners
DrawCircle() - draws a circle
DrawCharacter() - draws a character
DrawString() - draws a character string
DrawSmallCharacter() - draws a character using a small font
DrawSmallString() - draws a character string using a small font

The menus that are shown in the pictures and videos use these routines. These routines will pop up a menu, allow for selection of menu items and remove the menu when down. This is all done without destroying the frame buffer or what is displayed on the LCD.

mkMenu() - makes and displays a pop up menu w/o destroying the frame buffer
rmMenu() - removes the menu and restores the LCD with the original frame buffer
selMenu() - highlight a specified menu item

Prototype BeagleBone LCD Cape: pop up menu – first item selected.

Here is a link to a (poorly made) video of the display and menu system running. The menu demo application has five menu items; display beagle, display world map, run LCD test program, set number of LCD test loops (defaults to one), and clear the display. The test loop count uses a picker menu that uses the up/down buttons to pick a value.

Prototype LCD Cape menu system running (.m4v)

More pictures of the display running…

To be completed:

  • Code uploaded to my repository.
  • Cape EEPROM added to prototype.
  • Program EEPROM on prototype.
  • Board layout.
  • Get boards made.

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"