EBC Exercises on BBB - PWM

PWM

Simply enable the P9_21 to PWM, then connect to the LED. The LED connection could refer to EBC Exercises on BBB - Control LED

SLOTS=/sys/devices/bone_capemgr.*/slots
echo am33xx_pwm > $SLOTS
echo bone_pwm_P9_21 > $SLOTS
cd /sys/devices/ocp.3/pwm_test_P9_21.15/
echo 1000000000 > period
echo  250000000 > duty
echo 1 > run

From now you could see the LED begin to flash. In fact using this pwm we could control servo motor:
http://www.linux.com/learn/tutorials/776799-servo-control-from-the-beaglebone-black/

EBC Exercises on BBB -GPIO Via Mmap

Operate On Device Tree

Turn off the trigger and then shine on the LED USR3 via following command:

root@arm:~# cd /sys/class/leds/beaglebone\:green\:usr3
root@arm:/sys/class/leds/beaglebone:green:usr3# ls
brightness  device  max_brightness  power  subsystem  trigger  uevent
root@arm:/sys/class/leds/beaglebone:green:usr3# echo none > trigger 
root@arm:/sys/class/leds/beaglebone:green:usr3# echo 1 > brightness

We could find the gpio is attached to which pin:

# ./findGPIO.js USR3                                                                
{ name: 'USR3',                                                                                         
 gpio: 56,                                                                                             
 led: 'usr3',                                                                                          
 mux: 'gpmc_a8',                                                                                       
 key: 'USR3',                                                                                          
 muxRegOffset: '0x060',                                                                                
 options:                                                                                              
  [ 'gpmc_a8',                                                                                         
    'gmii2_rxd3',                                                                                      
    'rgmii2_rd3',                                                                                      
    'mmc2_dat6',                                                                                       
    'gpmc_a24',                                                                                        
    'pr1_mii1_rxd0',                                                                                   
    'mcasp0_aclkx',                                                                                    
    'gpio1_24' ] }
USR3 (gpio 56) mode: 7 (gpio1_24) 0x060 pullup
pin 24 (44e10860): (MUX UNCLAIMED) (GPIO UNCLAIMED)

gpio1_24 is what we want. Then refer Memory Map table in the Technical Reference Manual, its base address is 0x4804c000.

devmem2

An easy way to read the contents of a memory location is with devmem2:

root@arm:~/code/gpio# devmem2 0x4804c13c
/dev/mem opened.
Memory mapped at address 0xb6fea000.
Value at address 0x4804C13C (0xb6fea13c): 0x9A00000

Light ON the USR3 led:

root@arm:~/code/gpio# devmem2 0x4804c190 w 0x01000000
/dev/mem opened.
Memory mapped at address 0xb6f52000.
Value at address 0x4804C190 (0xb6f52190): 0x9800000
Written 0x1000000; readback 0x1000000

Light OFF the USR3 led:

root@arm:~/code/gpio# devmem2 0x4804c194 w 0x01000000
/dev/mem opened.
Memory mapped at address 0xb6f1c000.
Value at address 0x4804C194 (0xb6f1c194): 0x8A00000
Written 0x1000000; readback 0x1000000

mmap code

The critical Code:

    int fd = open("/dev/mem", O_RDWR);

    gpio_addr = mmap(0, GPIO1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO1_START_ADDR);

    gpio_oe_addr           = gpio_addr + GPIO_OE;
    gpio_setdataout_addr   = gpio_addr + GPIO_SETDATAOUT;
    gpio_cleardataout_addr = gpio_addr + GPIO_CLEARDATAOUT;

    // Set USR3 to be an output pin
    reg = *gpio_oe_addr;
    printf("GPIO1 configuration: %X\n", reg);
    reg &= ~USR3;       // Set USR3 bit to 0
    *gpio_oe_addr = reg;
    printf("GPIO1 configuration: %X\n", reg);

    printf("Start blinking LED USR3\n");
    while(keepgoing) {
        // printf("ON\n");
        *gpio_setdataout_addr = USR3;
        usleep(250000);
        // printf("OFF\n");
        *gpio_cleardataout_addr = USR3;
        usleep(250000);
    }

Run the program and see its heartbeat:

# ./gpioToggle 
Mapping 4804C000 - 4804E000 (size: 2000)
GPIO mapped to 0xb6f91000
GPIO OE mapped to 0xb6f91134
GPIO SETDATAOUTADDR mapped to 0xb6f91194
GPIO CLEARDATAOUT mapped to 0xb6f91190
GPIO1 configuration: F60FFFFF
GPIO1 configuration: F60FFFFF
Start blinking LED USR3

gpioThru

This example need to be clearly written later.

EBC Exercises on BBB -i2c and BBB

Connection

HMC5883L magnetometer runs in 400KHZ I2C bus, it’s for measuring the magnetic field vector in 3 dimensions.
We use its 4 ports: VCC,GND,SDA, SCL. SDA is for Data, while SCL is for Clock.

Use P9 for connecting the HMC5883L.

P9_02(GND) <----> GND    
P9_04(VCC) <----> VCC
P9_19(I2C2_SCL) <----> SCL	 I2C bus 2(pin 19 on header p9 to SCL) 
P9_20(I2C2_SDA) <----> SDA	 

I2C Detect

First you should install i2cdetect, then list the avaiable i2c bus via following command:

root@arm:~# i2cdetect -l
i2c-0   i2c             OMAP I2C adapter                        I2C adapter
i2c-1   i2c             OMAP I2C adapter                        I2C adapter

We choose i2c bus2, thus the command for detecting the connected device should be:

root@arm:~# i2cdetect -y -r 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --     

The address should be 0x1e.

Communicate with HMC5883L

The registers are listed as following, notice eavh value for each axis are 16-bits, thus we have to read them seperately and combine them:

Address	Name	Access
00	Configuration Register A	Read/Write
01	Configuration Register B	Read/Write
02	Mode Register	Read/Write
03	Data Output X MSB Register	Read
04	Data Output X LSB Register	Read
05	Data Output Z MSB Register	Read
06	Data Output Z LSB Register	Read
07	Data Output Y MSB Register	Read
08	Data Output Y LSB Register	Read
09	Status Register	Read
10	Identification register A	Read
11	Identification register B	Read
12	Identification register C	Read

Thus we could read out the X MSB Restier and X LSB Register via:

root@arm:~# i2cget -y 1 0x1e 3
0xfe
root@arm:~# i2cget -y 1 0x1e 4
0x91

Different Mode

Notice Mode Register, this will set the mesurement mode.
/images/moderegister.jpg

From the above table, we know for setting the lower 2 bits we could enable the operation mode of HMC5883L.
Now we set to single measurement mode, for one-time measure.

# i2cset -y 1 0x1e 2 1

2 means we set the register 2, and its number equals to 01(Single-Measurement Mode). After one-time measurement, it wil fall back to idle Mode.
After one-time measurement, get the register mode:

root@arm:~# i2cget -y 1 0x1e 2
0x03

Get the value of x-axis:

root@arm:~# i2cget -y 1 0x1e 3
0xfe
root@arm:~# i2cget -y 1 0x1e 4
0x77

C Code

Running Result:

root@arm:~/code/i2c# ./myi2cget 1 30 2
0x03 (3)
root@arm:~/code/i2c# ./myi2cget 1 30 34
0x00 (0)
root@arm:~/code/i2c# ./myi2cget 1 30 4
0x77 (119)

Critical Code:
Open the i2c-xxx:

        sprintf(filename, "/dev/i2c-%d", i2cbus);
        file = open(filename, O_RDWR);

ioctl for setting the address:

        if (ioctl(file, I2C_SLAVE, address) < 0) {

Now read the byte from:

        res = i2c_smbus_read_byte_data(file, daddress);

Comparing the official i2cget, myi2cget could print out the human-readable format of data.

Web Displaying

Git clone the following project form github.com:

# git clone https://github.com/duganje/ECE497_duganje.git
# cd  ECE497_duganje/
# ls
MiniProject01  MiniProject02  MiniProject03  MiniProject04  README.md

Upload the project MiniProject04 to the BBB board.
Notice change the code in buttonBox.js from i2cset -y 3 to i2cset -y 1 and i2cget -y 3toi2cget -y 1`

After modification, run buttonBox.js via:

$ node buttonBox.js

Now visit the http://xx.xx.xx.xxx:8081/buttonBox.html you could see the data displayed as following:

/images/magnetometer.jpg

EBC Exercises on BBB

Tips on Building Kenrel

Via following commands you could build the 3.8 kernel for BBB:

$ git clone git://github.com/RobertCNelson/linux-dev.git
$ cd linux-dev
$ git checkout origin/am33x-v3.8 -b am33x-v3.8
$ time git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
$ cp system.sh.sample system.sh
$ diff system.sh*
15c15
< CC=arm-linux-gnueabi-
---
> #CC=arm-linux-gnueabi-
21c21
< LINUX_GIT=~/BeagleBoard/linux-stable/
---
> #LINUX_GIT=/home/user/linux-stable/
31c31
< ZRELADDR=0x80008000
---
> #ZRELADDR=0x80008000
$ ./build_kernel.sh

U-boot Cross-compile

Download the U-boot and cross-compile it.

# git clone git://git.denx.de/u-boot.git
# cd u-boot/
# git checkout v2013.07 -b tmp
# wget https://raw.github.com/eewiki/u-boot-patches/master/v2013.07/0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
# patch -p1 < 0001-am335x_evm-uEnv.txt-bootz-n-fixes.patch
# setpogo	# For setting my cross-compiler to arm-linux-gnueabi-
# export ARCH=arm
# export CROSS_COMPILE=arm-linux-gnueabi-
# make

After building you will get MLO and u-boot.img.

Test on NFS

Prepare the NFS File System.

mkdir dtbs
tar xzvf 3.8.13-bone53-dtbs.tar.gz -C ./dtbs
cp dtbs/am335x-boneblack.dtb /srv/tftp/
cp 3.8.13-bone53.zImage /srv/tftp/
mkimage -A arm -O linux -T kernel -C none -a 0x80008000 -e 0x80008000 -n "Linux" -d /srv/tftp/3.8.13-bone53.zImage  /srv/tftp/uImage
tar xJvf ubuntu-14.04-console-armhf-2014-08-13.tar.xz -C /srv/nfs4/
cd /srv/nfs4/ubuntu-14.04-console-armhf-2014-08-13
tar xvf armhf-rootfs-ubuntu-trusty.tar -C ../Ubuntu_fs/
chmod 777 -R Ubuntu_fs/

Then boot the system from U-boot Via:

setenv ipaddr 192.168.1.16
setenv serverip 192.168.1.221
tftpboot ${fdtaddr} am335x-boneblack.dtb
tftpboot ${kloadaddr} uImage
setenv bootargs console=ttyO0,115200n8 root=/dev/nfs rootfstype=nfs rw nfsroot=192.168.1.221:/srv/nfs4/Ubuntu_fs ip=192.168.1.1 
bootm ${kloadaddr} - ${fdtaddr}

Now boot the BBB and we got the ssh enabled, via ssh ubuntu@192.168.1.1, password is temppwd.

Sometimes you will meet sudo problem, just chown and chmod is OK

# chmod 4755 some_related_file
# chown root some_related_file

Since NFS gonna the write priviledge error, go back for SD card.

SD Card

FileSystem Preparation:

$ export DISK=/dev/mmcblk0
$ dd if=/dev/zero of=${DISK} bs=1M count=10
$ dd if=./u-boot/MLO of=${DISK} count=1 seek=1 conv=notrunc bs=128k
$ dd if=./u-boot/u-boot.img of=${DISK} count=2 seek=1 conv=notrunc bs=384k
 sfdisk --in-order --Linux --unit M ${DISK} <<-__EOF__
1,,0x83,*
__EOF__
$ mkfs.ext4 /dev/mmcblk0p1 -L rootfs

Copy the Operating system into the sd card partition 1, later we will use /mnt for mounting the partition 1:

# mount /dev/mmcblk0p1 /mnt
# cd ubuntu-14.04.1-console-armhf-2014-10-29
# tar xvf armhf-rootfs-ubuntu-trusty.tar -C /mnt/
# sync

Now install the kernel image into the ubuntu system. Imagine your SD is mount to /mnt/

cp /media/y/embedded/BBB/EBC/3.8Kernel/linux-dev/deploy/3.8.13-bone53.zImage /mnt/boot/vmlinuz-3.8.13-bone53
tar xzvf /media/y/embedded/BBB/EBC/3.8Kernel/linux-dev/deploy/3.8.13-bone53-dtbs.tar.gz -C /mnt/boot/dtbs/

Now create the following uEnv.txt located in /mnt/boot/ and /mnt/:

##This will work with: Angstrom's 2013.06.20 u-boot.
 
loadaddr=0x82000000
fdtaddr=0x88000000
rdaddr=0x88080000
 
initrd_high=0xffffffff
fdt_high=0xffffffff

console=ttyO0,115200n8
mmcroot=/dev/mmcblk0p1 ro
 
loadximage=load mmc 0:1 ${loadaddr} /boot/vmlinuz-3.8.13-bone53
loadxfdt=load mmc 0:1 ${fdtaddr} /boot/dtbs/3.8.13-bone53/am335x-boneblack.dtb
loadxrd=load mmc 0:1 ${rdaddr} /boot/initrd.img-${uname_r}; setenv rdsize ${filesize}
loaduEnvtxt=load mmc 0:1 ${loadaddr} /boot/uEnv.txt ; env import -t ${loadaddr} ${filesize};
loadall=run loaduEnvtxt; run loadximage; run loadxfdt;
 
mmcargs=setenv bootargs console=tty0 console=${console} ${optargs} ${cape_disable} ${cape_enable} root=${mmcroot} rootfstype=${mmcrootfstype} ${cmdline}
 
uenvcmd=run loadall; run mmcargs; bootz ${loadaddr} - ${fdtaddr};
optargs="debug"

Enable the dhcp, /mnt/etc/network/interfaces:

auto lo
iface lo inet loopback
 
auto eth0
iface eth0 inet dhcp

Enable the serial port:

$ sudo vim /mnt/etc/init/serial.conf
start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
 
respawn
exec /sbin/getty 115200 ttyO0

Now restart and you got the 3.8 kernel enabled, so next time if you want to change the kernel, simply change the uEnv.txt file is OK.

ubuntu@arm:/boot$ uname -a
Linux arm 3.8.13-bone53 #1 SMP Tue Nov 11 18:40:19 CST 2014 armv7l armv7l armv7l GNU/Linux

EBC Exercises on BBB - Control LED

Using Sysfs

The easiest way to do general purpose I/O(gpio) on BBB is through the terminal and shell command. sysfs is the virtual file system which exposes the drivers for the hardware so you can directly use them.

# cd /sys/class/leds
# ls
# beaglebone:green:usr0  beaglebone:green:usr1  beaglebone:green:usr2  beaglebone:green:usr3
# cd beaglebone\:green\:usr0
# cat trigger 
none nand-disk mmc0 mmc1 timer oneshot [heartbeat] backlight gpio cpu0 default-on transient 

If you want to disable the heartbeat:

# echo none > trigger
# cat trigger 
[none] nand-disk mmc0 mmc1 timer oneshot heartbeat backlight gpio cpu0 default-on transient 

Turn on/off the led via:

# echo 1 > brightness
# echo 0 > brightness

More trigger options via:

# echo timer>trigger 
# cat trigger 
none nand-disk mmc0 mmc1 [timer] oneshot heartbeat backlight gpio cpu0 default-on transient 

Set the deplay frequency:

echo 100>delay_on
echo 900>delay_off

Adding Own LED

Add the connection of LED.
P9 Pin1 –> 220 ohm –> LED Negative Pin P9 Pin 12 -> Led Positive Pin

Pin 12 in the table is shown in table as GPIO1_28. Bank of 32 each, so find the gpio number via:
1*32+28=60.

We have to turn this pin on.

Turn it ON

export/unexport, turn on/off of the LED via following command:

$ cd /sys/class/gpio/
$ echo 60 > export
$ cd gpio60/
$ echo out > direction
$ echo 1 > value
$ echo 0 > value
$ cd ..
$ ls
export  gpio60  gpiochip0  gpiochip32  gpiochip64  gpiochip96  unexport
$ echo 60 > unexport
$ ls -F
export  gpiochip0@  gpiochip32@  gpiochip64@  gpiochip96@  unexport

Add Own Key

Connection for the key:
P9 Pin 3(3.3V) –>220 ohm –> Key 1
P9 Pin 42 –> Key 2
Pin 42 is GPIO0_7, then the actual gpio number is Just 7.

Read Value

export/unexport, read value via following command:

# cd /sys/class/gpio/
# echo 7 > export
# cd gpio7/
# echo in > direction
# cat value
# cat value 
0
Hold down the button and see the result: 
# cat value 
1

The script for reading the gpio value:

# ./readgpio.sh 7
sh: echo: I/O error
trap: SIGINT: bad trap
__________________________|^^^^^^^^^^^^^^^^^^^^^^^|__________|^^^^^^^^^^|___
___|^^^^^^^|______|^^^^^^^|______|^^^^^^^|______|^^^^^^^|______|^^^^^^^|______|^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^|____|^^^^^^^^|____|^^|__|^^|_|^^^^^^|___|^^
|__|^|__|^|__|^|__|^^|___|^|_|^|___|^|_|^|_|^|_|^^|_|^|_|^|_|^^|_|^^^^^^^^^^^^^|______|^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^|____|^^^^^^^^^^^|_____|^^^^^^^^^^^^^^|____|^^^^^^^^^^
^^^|___|^^^^^^^^^^^^|____|^^^^^^^^^^^^|__|^^^^^^^^^^|__|^^^^^^^^|__|^^^^^^^|___|^^^^
^|_____|^^^^^|____|^^^^^^^^^^^^^^^^^^^^^^^|___|^^^^^^^^^^^^^^^^^|___|^^^^^^^^^^^
|_^C

This seems like a little game.