BBB Enabling PWM

From Klaus' wiki
Jump to: navigation, search

These notes are based on the 3.8.13-bone70 complete installation as described over at BBB New Debian Image.

Selecting Overlays to use

Having being reading numerous pages about Device Tree Overlays I finally came up with a couple of solutions for how to enable the AM355 pinmux and setting the correct modes in order to enable PWM output.

If you just need one or a few PWM outputs you can generate overlay files over at this page.

If you want to enable a complete set of facilities on the BBB you can jump down to the #Complete Setup section below.

A common preparation

If you frequently access the /sys/devices/bone_capemgr.9/slots file it is highly recommended that yo prepare an environment variable called SLOTS.

In you ~/.bashrc add these lines

export SLOTS=/sys/devices/bone_capemgr.9/slots
export PINS=/sys/kernel/debug/pinctrl/44e10800.pinmux/pins

The former set the environment variable SLOTS to point to the slots file and the latter sets the PINS environment variable to point to the file that lists the pins assigned in the pinmux.

In order to immediately gain effect of the new setting issue

root@beaglebone$] . ~/.bashrc

which will read the .bashrc file from the home directory and execute whatever in there in the current shell. Don't try to execute the .bashrc file because the changes will only be seen shortly in the new shell (bash) that executes the script.

At every login hereafter SLOTS is set to point the correct directory.

Single PWM Setup

Over at this page you can generate a device overlay file for each PWM channel you want to use.

Giving Input to the Configurator

For example in order to enable PWM on P9 pin 14. See the figure below how to setup the configurator where the output is pulled up - you may want to selct a pull down instead.

PWM Configuration.png

From the generator you will get an output like this:

/*
 * Copyright (C) 2013 CircuitCo
 * Copyright (C) 2013 Texas Instruments
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.   
 *                                        
 * This is a template-generated file from BoneScript
*/                                        
/dts-v1/;                                
/plugin/;                                         
/ {                                       
       compatible = "ti,beaglebone", "ti,beaglebone-black";                                  

       /* identification */               
       part-number = "BS_PWM_P9_14_0x16";                   

       /* state the resources this cape uses */
       exclusive-use =                   
                /* the pin header uses */   
                "P9.14",
                /* the hardware IP uses */  
                "ehrpwm1A";

       fragment@0 {
                target = <&am33xx_pinmux>;
                __overlay__ {
                        bs_pwm_P9_14_0x16: pinmux_bs_pwm_P9_14_0x16 {
                                pinctrl-single,pins = <0x048 0x16>;
                        };
                };
        };

        fragment@1 {
                target = <&ocp>;
                __overlay__ {
                        bs_pwm_test_P9_14 {
                                compatible      = "pwm_test";
                                pwms            = <&ehrpwm1 0 500000 1>;
                                pwm-names       = "PWM_P9_14";

                                pinctrl-names   = "default";
                                pinctrl-0       = <&bs_pwm_P9_14_0x16>;

                                enabled         = <1>;
                                duty            = <0>;
                                status          = "okay";
                        };
                };
        };
};

Save this in a file name as suggested: bspwm_P9_14_16-00A0.dts

If you want the polarity to initially set to 0 change the 1 to 0 in the line pwms so it looks like this

pwms            = <&ehrpwm1 0 500000 0>;

Compile and Test

Compile it using this command:

root@begalebone $] dtc -O dtb -o bspwm_P9_14_16-00A0.dtbo -b 0 -@ bspwm_P9_14_16-00A0.dts

Copy the .dtbo file to /lib/firmware

As instructed on the generator page you can enable this ovelay by issuing these commands:

root@beaglebone $] grep -q am33xx_pwm $SLOTS || echo am33xx_pwm > $SLOTS
root@beaglebone $] echo bspwm_P9_14_16 > $SLOTS

Check if this works and you can see the PWM device by issuing

root@beaglebone:~$] ll /sys/devices/ocp.3/bs_pwm_test_P9_14.15/

and get this output

total 0
drwxr-xr-x  3 root root    0 May 31 09:34 .
drwxr-xr-x 42 root root    0 Mar  1 21:19 ..
lrwxrwxrwx  1 root root    0 May 31 09:37 driver -> ../../../bus/platform/drivers/pwm_test
-rw-------  1 root root 4096 May 31 09:37 duty
-r--r--r--  1 root root 4096 May 31 09:37 modalias
-rw-------  1 root root 4096 May 31 09:37 period
-rw-------  1 root root 4096 May 31 09:37 polarity
drwxr-xr-x  2 root root    0 May 31 09:37 power
-rw-------  1 root root 4096 May 31 09:37 run
lrwxrwxrwx  1 root root    0 May 31 09:34 subsystem -> ../../../bus/platform
-rw-r--r--  1 root root 4096 May 31 09:34 uevent

Finally create an ini-script that will perform the enabling every times the BBB boots.

In /etc/init.d create a file enable-pwm with this content

#! /bin/sh

### BEGIN INIT INFO
# Provides: enable-pwm
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Enables the PWM chips and connects it through the pinmux
# Description: Conneting the pwm output through the pinmux and enables the PWM chip on board
### END INIT INFO
case "$1" in
        start)
                echo "Enabling PWM on P9 Pin 14"
                grep -q am33xx_pwm /sys/devices/bone_capemgr.9/slots || echo "am33xx_pwm" > /sys/devices/bone_capemgr.9/slots
                echo bspwm_P9_14_16 > /sys/devices/bone_capemgr.9/slots
        ;;
        stop)
                #no-op
        ;;
        *)
                #no-op
        ;;
esac

exit 0 

After creating the file execute

root@beaglebone $] chmod 755 enable-pwm
root@beaglebone $] update-rc.d enable-pwm defaults

The first command set the file permissions and the second updates the init system to execute the file at a correct time depending on the information given in the first part of the script.

Complete Setup

This section describes a setup of the complete - almost - IO system on the BBB.

Preparing

In /opt/source/beaglebone-universal-io you'll find some general device drivers for the BBB.

Since BBB uses the FDT (Flattened Device Tree), where a general driver performs the most of the work, no special driver is needed for PWM.

There are two steps in enabling a device:

1. Setup the multiplexing of the pins (i.e. connect the internal device to a pin accessible on the outside)

2. Setup the peripheral (the internal device such as PWM, GPIO, etc.) to the pin assigned above

Ensure that your general pinmux is setup for defaults by ensuring that the /sys/devices/ocp.N (with N currently showing 3) exists. If not then perform:

root@beaglebone$] cd /opt/source/beaglebone-universal-io
root@beaglebone$] echo cape-universaln > /sys/devices/bone_capemgr.*/slots

expect an output with this included:

drwxr-xr-x  3 root root    0 May 24 09:24 P8_07_pinmux.15
drwxr-xr-x  3 root root    0 May 24 09:24 P8_08_pinmux.16
drwxr-xr-x  3 root root    0 May 24 09:24 P8_09_pinmux.17
drwxr-xr-x  3 root root    0 May 24 09:24 P8_10_pinmux.18
drwxr-xr-x  3 root root    0 May 24 09:24 P8_11_pinmux.19
drwxr-xr-x  3 root root    0 May 24 09:24 P8_12_pinmux.20
drwxr-xr-x  3 root root    0 May 24 09:24 P8_13_pinmux.21
drwxr-xr-x  3 root root    0 May 24 09:24 P8_14_pinmux.22
drwxr-xr-x  3 root root    0 May 24 09:24 P8_15_pinmux.23
drwxr-xr-x  3 root root    0 May 24 09:24 P8_16_pinmux.24
drwxr-xr-x  3 root root    0 May 24 09:24 P8_17_pinmux.25
drwxr-xr-x  3 root root    0 May 24 09:24 P8_18_pinmux.26
drwxr-xr-x  3 root root    0 May 24 09:24 P8_19_pinmux.27
drwxr-xr-x  3 root root    0 May 24 09:24 P8_26_pinmux.28
drwxr-xr-x  3 root root    0 May 24 09:24 P9_11_pinmux.29
drwxr-xr-x  3 root root    0 May 24 09:24 P9_12_pinmux.30
drwxr-xr-x  3 root root    0 May 24 09:24 P9_13_pinmux.31
drwxr-xr-x  3 root root    0 May 24 09:24 P9_14_pinmux.32
drwxr-xr-x  3 root root    0 May 24 09:24 P9_15_pinmux.33
drwxr-xr-x  3 root root    0 May 24 09:24 P9_16_pinmux.34
drwxr-xr-x  3 root root    0 May 24 09:24 P9_17_pinmux.35
drwxr-xr-x  3 root root    0 May 24 09:24 P9_18_pinmux.36
drwxr-xr-x  3 root root    0 May 24 09:24 P9_21_pinmux.37
drwxr-xr-x  3 root root    0 May 24 09:24 P9_22_pinmux.38
drwxr-xr-x  3 root root    0 May 24 09:24 P9_23_pinmux.39
drwxr-xr-x  3 root root    0 May 24 09:24 P9_24_pinmux.40
drwxr-xr-x  3 root root    0 May 24 09:24 P9_26_pinmux.41
drwxr-xr-x  3 root root    0 May 24 09:24 P9_27_pinmux.42
drwxr-xr-x  3 root root    0 May 24 09:24 P9_30_pinmux.43
drwxr-xr-x  3 root root    0 May 24 09:24 P9_41_pinmux.44
drwxr-xr-x  3 root root    0 May 24 09:24 P9_42_pinmux.46
drwxr-xr-x  3 root root    0 May 24 09:24 P9_91_pinmux.45
drwxr-xr-x  3 root root    0 May 24 09:24 P9_92_pinmux.47

Connecting pins to the PWM Chip

Now in order to connect the PWM to a pin look up what pin PWM can be output to in the cape-universaln-00A0.dts file. You'll find that you can connect them to for instance P9.14, P9.16, P9.21, and P9.22.

To convince yourself on your choice issue this command:

root@beagelbone$] config-pin -l P9.14

expect this output:

default gpio gpio_pu gpio_pd pwm

Now in order to enable the pwm to the P9.14 pin issue:

root@begalebone$] config-pin P9.14 pwm

To ensure yourself that you've got the PWM connected to the pin issue

root@beaglebone$] cat /sys/devices/ocp.3/P9_14_pinmux.32/state

expect this output

pwm

Locate the PWM control files

Now where are the PWM?

Issue

root@beaglebone$] ll /sys/class/pwm/

and expect this

total 0
drwxr-xr-x  2 root root    0 Jan  1  2000 .
drwxr-xr-x 59 root root    0 Jan  1  2000 .. 
--w-------  1 root root 4096 Jan  1  2000 export
lrwxrwxrwx  1 root root    0 May 24 09:30 pwmchip0 -> ../../devices/ocp.3/48300000.epwmss/48300200.ehrpwm/pwm/pwmchip0
lrwxrwxrwx  1 root root    0 May 24 09:30 pwmchip2 -> ../../devices/ocp.3/48300000.epwmss/48300100.ecap/pwm/pwmchip2
lrwxrwxrwx  1 root root    0 May 24 09:30 pwmchip3 -> ../../devices/ocp.3/48302000.epwmss/48302200.ehrpwm/pwm/pwmchip3
lrwxrwxrwx  1 root root    0 May 24 09:30 pwmchip5 -> ../../devices/ocp.3/48304000.epwmss/48304200.ehrpwm/pwm/pwmchip5
lrwxrwxrwx  1 root root    0 May 24 09:30 pwmchip7 -> ../../devices/ocp.3/48304000.epwmss/48304100.ecap/pwm/pwmchip7
--w-------  1 root root 4096 Jan  1  2000 unexport

How to interpret this output. First we'll have to look into this technical document over the AM335x Sitara Processors. (If the document is not available search for AM335 Sitara Processor Technical Reference Manual - it's a ~22 MB document).

Looking for address 48300000 in the memory map, you'll find this is in the L4_PER block, and this is listed as the “PWM subsystem 0″, and 48300200 is the EHR0 PWM channel and 48300100 the eCAP0 PWM. Also, address 4830200 is the “PWM subsystem 1″, and address 4830400 is the “PWM subsystem 2″.

Now, using the pin names found from the BeagleBoard.org – bone101 page served from the board, and deductive reasoning you'll come up with the following maping of pin to export number:

export number 	pin name 	pins
0 	        EHRPWM0A 	P9.22,P9.31
1 	        EHRPWM0B 	P9.21,P9.29
2 	        ECAPPWM0 	P9.42
3 	        EHRPWM1A 	P9.14,P8.36
4 	        EHRPWM1B 	P9.16,P8.34
5 	        EHRPWM2A 	P8.19,P8.45
6 	        EHRPWM2B 	P8.13,P8.46
7 	        ECAPPWM2 	P9.28

Enable the pin for the PWM

Now we're ready to enable a pwm for instance P9_14. This is done by looking up P9.14 in the table above and see that it is export number 3. So perform

root@beaglebone$] echo 3 > /sys/class/pwm/export

NOTE here there needs to be a space between 3 and >!

root@beaglebone$] ls /sys/class/pwm/

will give you this

export  pwm3  pwmchip0  pwmchip2  pwmchip3  pwmchip5  pwmchip7  unexport

No issuing

root@begalebone$] ll /sys/class/pwm/pwm3/

will output

total 0
drwxr-xr-x 3 root root    0 May 24 09:52 .
drwxr-xr-x 4 root root    0 May 24 09:24 ..
lrwxrwxrwx 1 root root    0 May 24 09:57 device -> ../../../48302200.ehrpwm
-rw-r--r-- 1 root root 4096 May 24 09:57 duty_ns
-rw-r--r-- 1 root root 4096 May 24 09:57 period_ns
-rw-r--r-- 1 root root 4096 May 24 09:57 polarity
drwxr-xr-x 2 root root    0 May 24 09:57 power
-rw-r--r-- 1 root root 4096 May 24 09:57 run
lrwxrwxrwx 1 root root    0 May 24 09:52 subsystem -> ../../../../../../class/pwm
-rw-r--r-- 1 root root 4096 May 24 09:52 uevent

The files of interest here are the duty_ns, period_ns and polarity.

The polarity sets the polarity of the output signal. Typically setup once at initialisation.

The period_ns sets the period time active for the PWM signal. In nano seconds. Typically setup once at initialisation.

The duty_ns sets the duty cycle for the PWM signal - i.e. the length of the period time the PWM signal is active. In nano seconds. This one is constantly updated with the desired duty cycle.

Control the PWM

No you can control the PWM from the command line or you can write a C/C++ program that will open, write and close the above mentioned files in order to control the PWM.

Set the Pinmux and Enable at boot

If you want to enable the PWM in a quick way create a script in /etc/init.d called enable-pwm and put in this text into the file

#! /bin/sh

### BEGIN INIT INFO
# Provides: enable-pwm
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Enables the PWM chips and connects it through the pinmux
# Description: Connecting the pwm output through the pinmux and enables the PWM chip on board
### END INIT INFO
case “$1″ in
    start)
        # Add the BeagleBone overlay to the default setup
        echo cape-universaln > /sys/devices/bone_capemgr.9/slots
        # Connect the P9.14 to the PWM
        config-pin P9.14 pwm

        # Now we are ready to enable the PWM chip
        echo 3 > /sys/class/pwm/export
     ;;
     stop)
         #no-op
     ;;
     *)
         #no-op
     ;;
esac

exit 0 

The first part after the #!/bin/sh tells the systemd information about your service.

Next comes the actual code part, where the case switches on the first parameter to the script. It can be start or stop. The start command will be handled in the section start). Likewise goes for the stop command.

In order to insert this as a service in the systemd execute these instructions:

root@beaglebone$] chmod +x enable-pwm    ## Give execute rights to the script
root@beaglebone$] insserv -n enable-pwm  ## Checks the script
root@beaglebone$] insserv enable-pwm     ## Actually inserts the script

Now reboot the system and check if your PWM has be enables and routed to P9_14.

Removing an entry from slots

In the previous sections echo'ing a value into /sys/devices/bone_capemgr.9/slots (typically refered to as $SLOTS) enabled the device overlay. If the overlay should be removed without rebooting then issue this command

root@beaglebone$] cat $SLOTS

This is a typical output

0: 54:PF--- 
1: 55:PF--- 
2: 56:PF--- 
3: 57:PF--- 
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
7: ff:P-O-L Override Board Name,00A0,Override Manuf,DS1820
8: ff:P-O-L Override Board Name,00A0,Override Manuf,am33xx_pwm
9: ff:P-O-L Override Board Name,00A0,Override Manuf,bspwm_P9_14_16

If the bspwm_P9_14_16 is to be removed issue

root@beaglebone$] echo -9 > $SLOTS
root@beaglebone$] cat $SLOTS

with this result

0: 54:PF--- 
1: 55:PF--- 
2: 56:PF--- 
3: 57:PF--- 
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
7: ff:P-O-L Override Board Name,00A0,Override Manuf,DS1820
8: ff:P-O-L Override Board Name,00A0,Override Manuf,am33xx_pwm

Acknowledgements

Thanks goes to this

for inspiration.