Building on BeagleBone White - modmaker/BeBoPr GitHub Wiki

Page history: written and tested on August 2nd, 2013

Hardware prerequisites

This page describes how to configure and build the mendel.elf software for use with an original BeBoPr (BEBOPR r2 2191) and an original BeagleBone. So for use with a BeagleBone Black, or BeBoPr Bridge see the corresponding instructions.

For initial testing, make sure to remove all strange hardware (e.g. capes or other custom devices) from the BeBoPr and BeagleBone.

When using a recent SD card image, no kernel patching and compilation is necessary. The BeBoPr will work with the original BeagleBone (a.k.a. BeagleBone White) as is.

SD card creation

If a proper kernel is available (see sections Boot the BeagleBone and Check the kernel boot log below), this section can be skipped.

Download the latest BeagleBone SD card image file (rev A6A) image file from the BeagleBone support site. Use the instructions on that page to create the SD card.

On a Windows-7 PC, Win32DiskImager version v0.7 and 7-Zip v9.20 will do the job.

Boot the BeagleBone

Boot from the SD card and connect a terminal, either via ssh (network) or via USB (serial). After booting, login as root (with empty password) and issue the dmesg command to see the bootlog (In the log show here, for the sake of clarity, some non-relevant messages have been replaced by triple dots).

root@beaglebone:~# dmesg
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.2.34 (koen@Angstrom-F16-vm-rpm) (gcc version 4.5.4 20120305 (prerelease) (GCC) ) #1 Wed Nov 21 14:17:11 CET 2012
[    0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=50c53c7d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] Machine: am335xevm
...
[    0.000122] Calibrating delay loop... 574.66 BogoMIPS (lpj=2873344)
...
[    0.192230] Board name: A335BONE
[    0.192230] Board version: 00A5
[    0.192230] The board is a AM335x Beaglebone.
...
[    0.203399]  omap_i2c.3: alias fck already exists
[    0.203643] omap_i2c omap_i2c.3: bus 3 rev2.4.0 at 100 kHz
[    0.207153] at24 3-0054: 32768 byte 24c256 EEPROM, writable, 64 bytes/write
[    0.224609] BeagleBone cape EEPROM: found eeprom at address 0x54
[    0.224609] BeagleBone cape: AES electronics BEBOPR, revision R2
[    0.224639] BeagleBone cape partnumber: 2191
[    0.224639] BeagleBone cape: initializing BEBOPR cape
[    0.224639] BeagleBone cape: revision A0 format, configuring 29 out of 74 signals:
[    0.224670] +---------+---------+---------+---------+---------+---------+---------+----+
[    0.225097] |     iiii--         o o   o           oo     ooooooooiio oooo       i i i |
[    0.225128] +---------+---------+---------+---------+---------+---------+---------+----+
[    0.225189] at24 3-0055: 32768 byte 24c256 EEPROM, writable, 64 bytes/write
[    0.276245] BeagleBone cape EEPROM: could not read eeprom at address 0x55
[    0.276306] at24 3-0056: 32768 byte 24c256 EEPROM, writable, 64 bytes/write
[    0.336303] BeagleBone cape EEPROM: could not read eeprom at address 0x56
[    0.336334] at24 3-0057: 32768 byte 24c256 EEPROM, writable, 64 bytes/write
[    0.396301] BeagleBone cape EEPROM: could not read eeprom at address 0x57
[    0.396331] BeagleBone cape: initializing mmc
[    0.396453]  omap_hsmmc.0: alias fck already exists
[    0.396636] BeagleBone cape: exporting ADC pins to sysfs
[    0.396850] Beaglebone: initializing onboard LEDs
[    0.397003] BeagleBone cape: exporting SPI pins as spidev
[    0.397277] BeagleBone cape: initializing w1-gpio
[    0.397399] w1-gpio connected to P8_6
...
[    0.472778] omap_rtc omap_rtc: setting system clock to 2000-01-01 00:00:00 UTC (946684800)
[    0.473388] Waiting for root device /dev/mmcblk0p2...
[    0.525329] mmc0: host does not support reading read-only switch. assuming write-enable.
[    0.526916] mmc0: new high speed SDHC card at address 1234
[    0.527343] mmcblk0: mmc0:1234 SA04G 3.63 GiB 
[    0.528839]  mmcblk0: p1 p2
[    0.579986] EXT4-fs (mmcblk0p2): INFO: recovery required on readonly filesystem
[    0.579986] EXT4-fs (mmcblk0p2): write access will be enabled during recovery
[    0.606384] EXT4-fs (mmcblk0p2): recovery complete
[    1.340148] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null)
[    1.340209] VFS: Mounted root (ext4 filesystem) readonly on device 179:2.
[    1.349548] devtmpfs: mounted
[    1.349853] Freeing init memory: 228K
[    1.657379] NET: Registered protocol family 10
[    2.122802] udevd[57]: starting version 182
...
[    7.538055] PHY: 0:00 - Link is Up - 100/Full
[    7.538238] ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready

Check the kernel boot log

The boot-log above shows some important sections that must be present for the BeBoPr to work:

  • Make sure that the kernel version (at t=0.000000 in the log) is 3.2.x (and not 3.8.x because that requires a completely different configuration.
  • Make sure that the BeBoPr cape is detected (at t=0.224609 in the log). The address of the EEPROM on the BeBoPr is fixed (0x54).
  • Make sure that the i/o-mux settings from the EEPROM are parsed: configuring 29 out of 74 signals.

If any one of these three conditions is not met, the BeBoPr can not work properly. If the kernel version is right, but the BeBoPr cape is not detected, a hardware failure or conflict may exist. In that case make sure that the boards are oriented and connected properly and that no other hardware (e.g. cape) is present (besides the BeBoPr and BeagleBone).

For the rare situation that the kernel version is right, but the kernel's configuration is not, prepare a new SD card image as described above in SD card creation and try again with that configuration.

Verify the presence of the relevant devices

The BeBoPr is using many of the AM335x SoC on-chip devices, and expects these to be accessible via the sysfs filesystem.

The ADC inputs

root@beaglebone:~# ls -l /sys/devices/platform/omap/tsc/
total 0
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain1
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain2
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain3
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain4
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain5
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain6
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain7
-r--r--r-- 1 root root 4096 Aug  3 10:33 ain8
-r--r--r-- 1 root root 4096 Aug  3 10:33 modalias
drwxr-xr-x 2 root root    0 Aug  3 10:33 power
lrwxrwxrwx 1 root root    0 Aug  2 16:48 subsystem -> ../../../../bus/platform
-rw-r--r-- 1 root root 4096 Jan  1  2000 uevent

The PWM outputs

root@beaglebone:~# ls -l /sys/class/pwm/ehrpwm.{1:0,2:[01]}/
/sys/class/pwm/ehrpwm.1:0/:
total 0
lrwxrwxrwx 1 root root    0 Aug  3 10:35 device -> ../../../ehrpwm.1
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_percent
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_freq
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 polarity
drwxr-xr-x 2 root root    0 Aug  3 10:35 power
-rw-r--r-- 1 root root 4096 Aug  3 10:35 request
-rw-r--r-- 1 root root 4096 Aug  3 10:35 run
lrwxrwxrwx 1 root root    0 Aug  2 16:48 subsystem -> ../../../../../../class/pwm
-r--r--r-- 1 root root 4096 Aug  3 10:35 tick_hz
-rw-r--r-- 1 root root 4096 Jan  1  2000 uevent

/sys/class/pwm/ehrpwm.2:0/:
total 0
lrwxrwxrwx 1 root root    0 Aug  3 10:35 device -> ../../../ehrpwm.2
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_percent
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_freq
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 polarity
drwxr-xr-x 2 root root    0 Aug  3 10:35 power
-rw-r--r-- 1 root root 4096 Aug  3 10:35 request
-rw-r--r-- 1 root root 4096 Aug  3 10:35 run
lrwxrwxrwx 1 root root    0 Aug  2 16:48 subsystem -> ../../../../../../class/pwm
-r--r--r-- 1 root root 4096 Aug  3 10:35 tick_hz
-rw-r--r-- 1 root root 4096 Jan  1  2000 uevent

/sys/class/pwm/ehrpwm.2:1/:
total 0
lrwxrwxrwx 1 root root    0 Aug  3 10:35 device -> ../../../ehrpwm.2
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 duty_percent
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_freq
-rw-r--r-- 1 root root 4096 Aug  3 10:35 period_ns
-rw-r--r-- 1 root root 4096 Aug  3 10:35 polarity
drwxr-xr-x 2 root root    0 Aug  3 10:35 power
-rw-r--r-- 1 root root 4096 Aug  3 10:35 request
-rw-r--r-- 1 root root 4096 Aug  3 10:35 run
lrwxrwxrwx 1 root root    0 Aug  2 16:48 subsystem -> ../../../../../../class/pwm
-r--r--r-- 1 root root 4096 Aug  3 10:35 tick_hz
-rw-r--r-- 1 root root 4096 Jan  1  2000 uevent

The PRUSS

The BeBoPr code uses the PRUSS and needs the uio and uio_pruss driver modules configured in the kernel or as loadable modules

root@beaglebone:~# zcat /proc/config.gz | grep UIO
CONFIG_UIO=m
CONFIG_UIO_PDRV=m
CONFIG_UIO_PDRV_GENIRQ=m
CONFIG_UIO_PRUSS=m

The above configuration shows that both drivers are built as modules, so the following test will load them for use. This is normally done by the BeBoPr code, just check this once to make sure it works.

root@beaglebone:~# modprobe uio_pruss
root@beaglebone:~# lsmod
Module                  Size  Used by
uio_pruss               2196  0 
uio                     7301  1 uio_pruss

The GPIO signals

root@beaglebone:~# ls -l /sys/class/gpio/
total 0
--w------- 1 root root 4096 Jan  1  2000 export
lrwxrwxrwx 1 root root    0 Jan  1  2000 gpiochip0 -> ../../devices/virtual/gpio/gpiochip0
lrwxrwxrwx 1 root root    0 Jan  1  2000 gpiochip32 -> ../../devices/virtual/gpio/gpiochip32
lrwxrwxrwx 1 root root    0 Jan  1  2000 gpiochip64 -> ../../devices/virtual/gpio/gpiochip64
lrwxrwxrwx 1 root root    0 Jan  1  2000 gpiochip96 -> ../../devices/virtual/gpio/gpiochip96
--w------- 1 root root 4096 Jan  1  2000 unexport

To test the gpio driver and setting of the i/o multiplexer, turn the status LED on the BeBoPr on:

root@beaglebone:~# echo 32 > /sys/class/gpio/export 
root@beaglebone:~# echo out > /sys/class/gpio/gpio32/direction 
root@beaglebone:~# echo 1 > /sys/class/gpio/gpio32/value 

Turn it off and release the gpio pin:

root@beaglebone:~# echo 0 > /sys/class/gpio/gpio32/value 
root@beaglebone:~# echo 32 > /sys/class/gpio/unexport

Building mendel.elf

Building the executable can be done either on on the BeagleBone (native) or via cross-compilation. Only native the compilation (on the BeagleBone) will be explained here. It does not take much time and all the tools are standard available on the BeagleBone's Angstrom image. For cross-compilation, have a look at the setenv file in the source directory.

Download

Download the BeBoPr sources from github. Either clone the repository, or download a snapshot. Create a subdirectory for the sources. In the examples below ~/BeBoPr is used.

Configuration

The proper way to configure the build process is to edit the setenv file and not the Makefile. Open ~/BeBoPr/setenv in an editor of choice and set the configuration. For our BeagleBone (White) and BeBoPr (without Bridge), make sure to select a configuration that does not set the BBB and BONE_BRIDGE defines.

Note that we're handling the build process configuration (only) here! The configuration of the printer (dimensions, stepper configuration, etc.) is in the file bebopr_r2.c.

Building

Before starting make, source the compilation environment settings from setenv. This only needs to be done once unless the configuration is changed again or a new shell is started.

root@beaglebone:~/BeBoPr# make clean depend all        
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~ *fuse
  Appending dependency information to 'Makefile'
  CC        analog.o
  CC        bebopr_r2.o
  CC        debug.o
  CC        gcode_parse.o
  CC        gcode_process.o
  CC        gpio.o
  CC        heater.o
  CC        home.o
  CC        limit_switches.o
  CC        pruss.o
  CC        pruss_stepper.o
  CC        pwm.o
  CC        temp.o
  CC        thermistor.o
  CC        traject.o
  CC        comm.o
  CC        eeprom.o
  CC        timestamp.o
  CC        xperror.o
  CC        mendel.o
  Updating version information
  CC        version.o
  LINK      mendel.elf
root@beaglebone:~/BeBoPr# 

Install

Not strictly necessary when doing native compilation, but the install target for make will copy the mendel.elf binary to the proper location as defined in the setenv file.

root@beaglebone:~/BeBoPr# make install         
  INSTALL   'mendel' TO 'root@beaglebone:/home/root'
root@beaglebone's password: 
mendel.elf                                                          100%  130KB 129.9KB/s   00:00    
root@beaglebone:~/BeBoPr# 

stepper.bin

Once the c-code is compiled and in place, the last item needed is the stepper code for the PRUSS. This object file has the name stepper-vx.y.bin with x and y being a decimal number. Rename the file to stepper.bin and put it in the same directory as that mendel.elf started from. Or better, create a symlink as shown below.

root@beaglebone:~# ls -la
drwxr-xr-x 6 root root   4096 Aug  2 21:54 .
drwxr-sr-x 3 root root   4096 Nov 21  2012 ..
drwxr-xr-x 2 root root   4096 Aug  3 11:37 BeBoPr
drwxr-xr-x 2 root root   4096 Jan  1  2000 Desktop
-rwxr-xr-x 1 root root 132967 Aug  3 11:38 mendel.elf
-rw-r--r-- 1 root root   3904 Aug  2 19:07 stepper-v6.15.bin
lrwxrwxrwx 1 root root     17 Aug  2 19:07 stepper.bin -> stepper-v6.15.bin

Run

With mendel.elf and stepper.bin in place, start the first and have a look at the generated log messages.

root@beaglebone:~# ./mendel.elf 
Starting './mendel.elf' version 1.6.912 (Sat 03-08-2013 11:37 UTC).
Starting with debug flags set to 0x0019 (25)
Starting 'arm' init ...
Scheduler set to 1, priority to 60 (min:1,max:99)
Clock resolution = 1 ns.
... 'arm' init was successfull
Starting 'bebopr (early)' init ...
Using configuration for kernel version 3.2, BBB is not defined, BONE_BRIDGE is not defined
Using stepper driver configuration: 'Pololu'
... 'bebopr (early)' init was successfull
Starting 'limsw' init ...
=== Creating limit_switches_thread...done ===
... 'limsw' init was successfull
Starting 'heater' init ...
Starting 'temp' init ...
Starting 'analog' init ...
=== Creating analog_thread...done ===
... 'analog' init was successfull
... 'temp' init was successfull
Starting 'pwm' init ...
... 'pwm' init was successfull
=== Creating heater_thread...done ===
... 'heater' init was successfull
Starting 'bebopr (late)' init ...
Turned BEBOPR I/O power on
... 'bebopr (late)' init was successfull
Starting 'gcode_process' init ...
Starting 'traject' init ...
  step: X =    15.000, Y =    12.500, Z =     0.195, E =     3.345 [um]
  amax: X =  3000.000, Y =  1000.000, Z =  1000.000, E =  1000.000 [mm/s^2]
  vmax: X =   375.000, Y =   266.667, Z =     5.000, E =    50.000 [mm/s]
Starting 'pruss_stepper' init ...
Valid STEPPER code update found in file 'stepper.bin' (version 6.15).
analog_thread: started
heater_thread: started
  timer resolution is 1 [ns]
Valid STEPPER code found in EEPROM '/sys/class/i2c-adapter/i2c-3/3-0054/eeprom' (version 6.15).
Will load STEPPER code for PRU1 from 'stepper.bin'
module 'pruss_uio' is not loaded, trying to load it...
found driver device instance 'pruss_uio'
Located driver 'pruss_uio' for the 'pruss' device 'uio0'.
Map device for 'uio0' called
Valid PRUSS ID found.
PRUSS enabled OCP master ports.
Found halted/idle PRU1
Clearing PRUSS counters, old: cycle = 0, stall = 0
Loading STEPPER code from file 'stepper.bin'
Clearing register space...
Initializing 8KB SRAM with deadbeef pattern...
Initializing SRAM buffer with fixed patterns...
Reset PRU1 and set program counter to 0
PRU1 now contains STEPPER code version 6.15.
eCap0 initialized and found operational
Setting FIFO pointers to 0 (in) and 0 (out).
PRUSS successfully started at PC=0.
... 'pruss_stepper' init was successfull
Set axis nr 1 step size to 15000 [nm] and reversed direction
Set axis nr 2 step size to 12500 [nm] and normal direction
Set axis nr 3 step size to 194 [nm] and normal direction
Set axis nr 4 step size to 3344 [nm] and reversed direction
... 'traject' init was successfull
... 'gcode_process' init was successfull
start
ok
Starting main loop...

If the program does not exit with an error, everything went fine and the required peripherals were found and initialized. After the "Starting main loop" message, the gcode interpreter is waiting for commands to be entered. Exit the program with control-D or control-C.

More information on the gcode interpreter can be found here.

Log output

The default setting for debug messages is rather verbose. To disable all debug output, issue M111 s0, or change the INIT_DEBUG_FLAGS setting in the setenv file and recompile.

Some comments to the log:

  • The first line gives the version of the executable. The digits after the second decimal-point (here 912) show a build sequence number and are incremented with every build. The actual value is not significant but used to discriminate between builds.

  • Because of the definition of FORCE_STEPPER_CODE_FROM_FILE in setenv, the code in the EEPROM is not used. If this define is not present during compilation, the resulting executable will try to load the stepper code from the EEPROM. If a file with a different version stepper code is present in the directory the contents of that file will be written to the EEPROM for use