BeagleBone Black, FreeBSD and PWMs
October 2013.
Introduction
The BeagleBone black, using its AM335X CPU, provides a number of PWM output. Let's try to make them work.
Trying to find the device
dmesg indicates that the kernel found 3 PWM devices.
am335x_pwm0:mem 0x48300000-0x483000ff,0x48300100-0x4830017f,0x48300180-0x483001ff,0x48300200-0x4830025f irq 86,58 on simplebus0
am335x_pwm1:mem 0x48302000-0x483020ff,0x48302100-0x4830217f,0x48302180-0x483021ff,0x48302200-0x4830225f irq 87,59 on simplebus0
am335x_pwm2:mem 0x48304000-0x483040ff,0x48304100-0x4830417f,0x48304180-0x483041ff,0x48304200-0x4830425f irq 88,60 on simplebus0
devinfo and ofwdump confirm that the corresponding nodes exist.
# devinfo
nexus0
fdtbus0
simplebus0
aintc0
ti_scm0
am335x_prcm0
am335x_dmtimer0
gpio0
gpioc0
gpiobus0
uart0
ti_edma30
sdhci_ti0
mmc0
mmcsd0
sdhci_ti1
mmc1
mmcsd1
cpsw0
miibus0
smscphy0
iichb0
iicbus0
iic0
am335x_pmic0
am335x_pwm0
am335x_pwm1
am335x_pwm2
musbotg0
usbus0
uhub0
ustorage_fs0
usbus1
uhub1
# ofwdump -a
Node 0x38:
Node 0xc4: am335x
Node 0x124: interrupt-controller@48200000
Node 0x1b4: scm@44e10000
Node 0xb24: prcm@44E00000
Node 0xb88: dmtimers@44E05000
Node 0xc6c: gpio
Node 0xd14: serial@44E09000
Node 0xda8: serial@48022000
Node 0xe54: serial@48024000
Node 0xf00: serial@481a6000
Node 0xfac: serial@481a8000
Node 0x1058: serial@481aa000
Node 0x1104: edma3@49000000
Node 0x1188: mmchs0@48060000
Node 0x120c: mmchs1@481D8000
Node 0x12a4: ethernet@4A100000
Node 0x1340: mdio@0
Node 0x1388: ethernet-phy@0
Node 0x13c8: i2c@44e0b000
Node 0x1454: pmic@24
Node 0x1494: pwm@48300000
Node 0x1548: pwm@48302000
Node 0x15fc: pwm@48304000
Node 0x16b0: lcd@4830e000
Node 0x1738: usb@47400000
Node 0x1808: mbox0@480C8000
Node 0x1874: spinlock0@480CA000
Node 0x18c0: pruss@4A300000
Node 0x1944: aliases
Node 0x198c: memory
Node 0x19c4: chosen
# ofwdump -p /am335x/pwm@48300000
Node 0x1494: pwm@48300000
compatible:
74 69 2c 61 6d 33 33 35 78 2d 70 77 6d 00
'ti,am335x-pwm'
#address-cells:
00 00 00 01
#size-cells:
00 00 00 01
reg:
48 30 00 00 00 00 01 00 48 30 01 00 00 00 00 80 48 30 01 80
00 00 00 80 48 30 02 00 00 00 00 60
interrupts:
00 00 00 56 00 00 00 3a
interrupt-parent:
00 00 00 01
pwm-device-id:
00 00 00 00
Using the device
There doesn't seem to be much documentation on how to use these devices.
Reading the kernel indicates that the configuration is done using sysctl.
# sysctl -a | grep pwm
"Giant","am335x_pwm softc"
dev.am335x_pwm.0.%desc: AM335x PWM
dev.am335x_pwm.0.%driver: am335x_pwm
dev.am335x_pwm.0.%parent: simplebus0
dev.am335x_pwm.0.period: 1000
dev.am335x_pwm.0.dutyA: 0
dev.am335x_pwm.0.dutyB: 0
dev.am335x_pwm.1.%desc: AM335x PWM
dev.am335x_pwm.1.%driver: am335x_pwm
dev.am335x_pwm.1.%parent: simplebus0
dev.am335x_pwm.1.period: 1000
dev.am335x_pwm.1.dutyA: 0
dev.am335x_pwm.1.dutyB: 0
dev.am335x_pwm.2.%desc: AM335x PWM
dev.am335x_pwm.2.%driver: am335x_pwm
dev.am335x_pwm.2.%parent: simplebus0
dev.am335x_pwm.2.period: 1000
dev.am335x_pwm.2.dutyA: 0
dev.am335x_pwm.2.dutyB: 0
Jackpot! Let's try settings some values in these registers.
# sysctl dev.am335x_pwm.0.period=100
# sysctl dev.am335x_pwm.0.dutyA=50
# sysctl dev.am335x_pwm.0.dutyB=75
# sysctl dev.am335x_pwm.1.period=1000
# sysctl dev.am335x_pwm.1.dutyA=500
# sysctl dev.am335x_pwm.1.dutyB=50
# sysctl dev.am335x_pwm.2.period=250
# sysctl dev.am335x_pwm.2.dutyA=50
# sysctl dev.am335x_pwm.2.dutyB=150
That's it. Probing the pins confirms that the PWM work.
Pin mapping and muxing
Device | Pin |
---|---|
sysctl dev.am335x_pwm.1.dutyA | P9.14 (ehrpwm1A) |
sysctl dev.am335x_pwm.1.dutyB | P9.16 (ehrpwm1B) |
sysctl dev.am335x_pwm.2.dutyA | P8.19 (ehrpwm2A) |
sysctl dev.am335x_pwm.2.dutyB | P8.13 (ehrpwm2B) |
ehrpwm0 is not muxed in the device tree file, so it's not accessible.
Reference and relevant information
- sys/arm/ti/am335x/am335x_pwm.c: http://fxr.watson.org/fxr/source/arm/ti/am335x/am335x_pwm.c?im=excerpts
- sys/arm/ti/ti_scm.c: http://fxr.watson.org/fxr/source/arm/ti/ti_scm.c?im=excerpts
- sys/arm/ti/am335x/am335x_scm_padconf.c: http://fxr.watson.org/fxr/source/arm/ti/am335x/am335x_scm_padconf.c?im=excerpts
- sys/boot/fdt/dts/beaglebone-black.dts: http://fxr.watson.org/fxr/source/boot/fdt/dts/beaglebone-black.dts?im=10
- Flattened Device Trees for embedded FreeBSD (RafaÅ Jaworowski / BSDCan 2010, Ottawa): http://www.bsdcan.org/2010/schedule/attachments/136_FreeBSD_FDT-slides.pdf