Beaglebone Black Kernel 4.1 PWM and OCP?

Hey guys, I’m working on a project where as I was using the ocp.X/bone_pwm_P9_11 and such in kernel 3.8. I just recently updated my Beaglebone black to kernel 4.1 and couldn’t get PWM to work…

I was trying to use dtc, rebuild the device tree overlay. I pulled the old am33xx_pwm from https://github.com/beagleboard/devicetree-source/blob/master/arch/arm/boot/dts/am33xx_pwm-00A0.dts and some of these bad boys bone_pwm_PX_YZ from https://github.com/beagleboard/devicetree-source/blob/master/arch/arm/boot/dts/bone_pwm_P8_13-00A0.dts. I know that these are pretty old, but was just thinking maybe it would work with the new kernel?

Then I was able to build these device tree overlays and load them into the /boot/uEnv.txt. However, when I went to /sys/devices/platform, I only saw ocp:pwm and it’s nothing like the old kernel 3.8 where you’d have duty, period, and all that good stuff. Is this the right way to access PWM or I had to use the example in the Bacon device tree overlay? If so, is there a document on how to know which PWM pin to export?

I’ve been playing with this new kernel for quite a while now and still haven’t got any luck. Any advice or pointers will be greatly appreciated.

Thanks

Khanh,

Have you got the PWMs working yet? This documentation (http://processors.wiki.ti.com/index.php/Linux_Core_PWM_User’s_Guide) most closely matches what I am seeing under the 4.1 kernel, but I had to fall back on these same old overlays to even see the PWMs. Seem to able to export, configure, and enable the PWM, but I’m just not seeing anything on the output pin.

-Kevin

No, I haven’t been able to get kernel 4.1 and PWM working. I haven’t looked at the link you included either. I’ll definitely take a look over the weekend. Hey, can you send me the link to this post on google group? I can’t seem to find my post…

Thanks,

Khanh

I have the PWM working perfectly on the 4.1 kernel, and I am planning to post the solution to this thread within a few days.

I am using the ehrpwm2A PWM on P8_19. Usage of this requires the following device tree overlay (BB-PWM2-00A0.dts):

/dts-v1/;

/plugin/;

/{

compatible = “ti,beaglebone”, “ti,beaglebone-black”;

part-number = “BB-PWM2”;

version = “00A0”;

fragment@0 {

target = <&am33xx_pinmux>;

overlay {

pinctrl_spec: Panel_Pins {

pinctrl-single,pins = <

0x020 0x04 /* P8_19 MODE4 ehrpwm2A PWM */

;

};

};

};

fragment@1 {

target = <&ocp>;

overlay {

test_helper: helper {

compatible = “bone-pinmux-helper”;

pinctrl-names = “default”;

pinctrl-0 = <&pinctrl_spec>;

status = “okay”;

};

};

};

fragment@2 {

target = <&epwmss2>;

overlay {

status = “okay”;

};

};

fragment@3 {

target = <&ehrpwm2>;

overlay {

status = “okay”;

};

};

};

In the above device tree overlay, fragment 0 configures P8_19 to be the output of PWM2A (instead of a GPIO or other function), and fragments 1, 2, and 3 enable the needed on-chip peripherals. ‘ocp’ is on-chip-peripherals, ‘epwmss’ is PWM sub-system, and ‘ehrpwm2’ is PWM2.

Compile this overlay using:

dtc -O dtb -o BB-PWM2-00A0.dtbo -b 0 -@ BB-PWM2-00A0.dts

Copy to /lib/firmware:

sudo cp BB-PWM2-00A0.dtbo /lib/firmware

At this point, get to root:

sudo su

Load the device tree overlay (this must be done logged in as root, sudo won’t work – I think because of the redirect). Note that this path is different than the earlier kernels due to a redesign of the cape manager:

root@arm:/home/ubuntu# echo BB-PWM > /sys/devices/platform/bone_capemgr/slots

Check that overlay was loaded:

root@arm:/home/ubuntu# cat /sys/devices/platform/bone_capemgr/slots

0: PF---- -1
1: PF---- -1
2: PF---- -1
3: PF---- -1
4: P-O-L- 0 Override Board Name,00A0,Override Manuf,BB-PWM2

Check that the pin is configured to output the PWM2A:

root@arm:/home/ubuntu# cat /sys/kernel/debug/pinctrl/44e10800.pinmux/pins | grep 0820

pin 8 (44e10820.0) 00000004 pinctrl-single

You need to see the pinmux at offset $820 have mode 4. If it is not 4, your PWM may be working fine, but you won’t see the signal on pin P8_19.

You should also see pwmchip0 appear at /sys/class/pwm:

root@arm:/home/ubuntu# ls /sys/class/pwm

pwmchip0

Change to pwmchip0 folder:

root@arm:/home/ubuntu# cd /sys/class/pwm/pwmchip0

Export the PWM to userspace:

root@arm:/sys/class/pwm/pwmchip0# echo 0 > export

You should now see a pwm0 folder:

root@arm:/sys/class/pwm/pwmchip0# ls

device export npwm power pwm0 subsystem uevent unexport

Change to the pwm0 folder, configure the PWM and enable it:

root@arm:/sys/class/pwm/pwmchip0/pwm0# ls

duty_cycle enable period polarity power uevent

root@arm:/sys/class/pwm/pwmchip0/pwm0# echo 1000000 > period

root@arm:/sys/class/pwm/pwmchip0/pwm0# echo 250000 > duty_cycle

root@arm:/sys/class/pwm/pwmchip0/pwm0# echo 1 > enable

I think the units of period and duty_cycle are both nanoseconds (not confirmed with a scope). duty_cycle is not a percentage, so these setting are running the PWM at 1kHz, 25% duty cycle.

Hope this helps!

Hey Kevin,

Thanks for the guide on enabling PWM on kernel 4.1. I’m a little confused with PWM now though,…Based on the values that you provide, are you saying that, there are only 3 PWM’s on the Beagleboard? I thought there were more than that or maybe I was wrong.

The 2nd question would be, is this right?

0x024  0x4	corresponds to ehrpwm2B = P8_13
0x020  0x4      corresponds to ehrpwm2A = P8_19
0x150  0x3	corresponds to ehrpwm0A = P9_14
(Are we missing some pins)

Also, how do you know it's pin 0 to export? I thought this were more like exporting GPIO, whereas you'd need to know which pin is which to export?

Thanks,
Khanh

I think there are only three PWM units (ehrpwm0, ehrpwm1, and ehrpwm2), but two of them have an A and a B. I didn’t dig too far, but I suspect there are some constraints on how the A and B can be used, such as maybe they have to both be at the same frequency, but they could have different duty cycles. The question about which pwmchipN to export is a good one, and I think this is where the documentation is the weakest. I think that when I had all the PWMs enabled in the device tree, ehrpwm2B was pwmchip6. I think it just starts with a base of zero and increments for each enabled pwm unit. When I only had ehrpwm2A enabled, I saw only pwmchip0, so I knew that was it. An remember, you are not exporting the pin, but the PWM itself, to user space. I finally realized that’s what ‘export’ means. The pinmux table handles the routing of the PWM output to the physical pin. I’m pretty sure you are right about P8_13 and P8_19, but I don’t recall the other ehrpwm pins. I found these tables (http://www.embedded-things.com/bbb/beaglebone-black-pin-mux-spreadsheet/) by googling “beaglebone black pin mux table”.

Can you confirm that this works?

I had this loaded before but there was no solution to be found. Is this overlay a custom overlay you made or something you found from someone else?
I don’t believe this overlay is provided with the actual BeagleBone.

By the way, what OS are you running with kernel 4.x?

Thanks again,

Chris.

Chris,

This is a custom overlay that I created based on other overlays. I have not tested this exact overlay, since it is extracted from the larger overlay that matches my additional hardware (about 20 discrete inputs and 2 quadrature encoders). In the end, I think the standard overlays work, but the difficulty is how different the Linux 4.1 kernel is from 3.8 with regard to the bone manager. I’m running Ubuntu Linux on my beaglegone:

ubuntu@arm:~$ uname -a
Linux arm 4.1.6-ti-r15 #1 SMP PREEMPT Fri Sep 11 02:38:50 UTC 2015 armv7l armv7l armv7l GNU/Linux

When I started adding support for the eqep peripherals for the quadrature encoders, I did run into hardware conflicts where my pin muxing was failing, and “dmesg | tail” was telling me all along that my overlays were not loading (and what the conflicts were). As an embedded software engineer, I understand pin muxing and SOC peripherals, but dealing with the idiosyncrasies of embedded Linux is where I find it difficult. The trick is to check that what you are telling the system in your overlay is actually happening, and this where checking the ‘slots’, ‘pins’, and ‘dmesg’ is really helpful.

When I get a spare moment, I’ll isolate the PWM portion of the overlay and complete end-to-end test and post the results.

Hi,

I’ve followed you procedure fairly carefully, and everything seems to work fine, except I can’t get a signal on an oscilloscope. I’ve had this working fine in the old 3.8 kernel, and am trying to get the pwms working in the latest 4.1.13-bone16 kernel.

Have you verified it actually works on the output pin?

Erik

Hello again,

After a few hours of tinkering it works!
Note that upon doing this im using kernel 4.1.10-ti-r21 #1.

The main issue here is the version of the device tree compiler you are using.

I took as an exemple the device tree structure above (that you did) and tried to compile and load it into the beaglebone with DTC version 1.4.0 and this did not work.
Looking around on the glorious internet, I found a post saying that I should try using https://github.com/beagleboard/bb.org-overlays (only up to step 2)

After compiling the above structure and copying it to the exact same location as above and executing the echo BB-PWM2 > /sys/devices/platform/bone_capemgr/slots with root privileges i was able to see the pwmchip0 and export the pwm module created from the structure!

Thanks again for this! :slight_smile:
+Erik i confirmed that this works on P8_19. Tested with a voltmeter. @ 750000 duty and 250000 to make sure.