Using PWM

This guide demonstrates how to configure and use PWM (Pulse Width Modulation) on the SP7350 platform using the sysfs interface. We'll cover setting up the period, duty cycle, and enabling PWM.

Table of Contents

1. Modify Device-tree Source

To enable and configure PWM pins, edit the PWM node in the device-tree source. For the SP7350 Evaluation Board, you can find the file at "arch/arm64/boot/dts/sunplus/sp7350-ev.dts" within the kernel directory.

Locate the PWM node, configure the pins, and activate it. For instance,

&pwm { pinctrl-names = "default"; pinctrl-0 = <&pwm0_pins &pwm1_pins &pwm2_pins &pwm3_pins>; //status = "disabled"; }; &pctl { // ... (previous configurations) pwm0_pins: pinmux_pwm0-pins { function = "PWM0"; groups = "PWM0_X2"; drive-strength-microamp = <SPPCTRL_DVIO_DRV_IOH_15200_IOL_18700UA>; }; pwm1_pins: pinmux_pwm1-pins { function = "PWM1"; groups = "PWM1_X2"; drive-strength-microamp = <SPPCTRL_DVIO_DRV_IOH_15200_IOL_18700UA>; }; pwm2_pins: pinmux_pwm2-pins { function = "PWM2"; groups = "PWM2_X1"; drive-strength-microamp = <SPPCTRL_DVIO_DRV_IOH_15200_IOL_18700UA>; }; pwm3_pins: pinmux_pwm3-pins { function = "PWM3"; groups = "PWM3_X1"; drive-strength-microamp = <SPPCTRL_DVIO_DRV_IOH_15200_IOL_18700UA>; }; // ... (other configurations) };

Please note that the "pwm" label refers to the node "pwm@f8800d80" in "arch/arm64/boot/dts/sunplus/sp7350-common.dtsi" located in the kernel directory.

The subnodes under "pinctrl", "pinmux_pwm0-pins", "pinmux_pwm1-pins", "pinmux_pwm2-pins", and "pinmux_pwm3-pins", configure the output pins for PWM channels 0, 1, 2, and 3. These channels correspond to the pins AO_MX8, AO_MX9, AO_MX10, and AO_MX11, respectively. For detailed pin configurations, please refer to the table available at SP7350 Specification | 13.3 Pulse Width Modulation (PWM). Each PWM output can support two pin positions:

Channel

Pin at Position X1

Pin at Position X2

Remarks

Channel

Pin at Position X1

Pin at Position X2

Remarks

PWM_CH0

AO_MX28

AO_MX8

 

PWM_CH1

AO_MX29

AO_MX9

 

PWM_CH2

AO_MX10

AO_MX42

 

PWM_CH3

AO_MX11

AO_MX43

 

2. Enable Linux PWM Driver

The Linux PWM driver should be enabled by default. Confirm by running make kconfig in the project top directory and check "Device Drivers" → "Pulse-width Modulation (PWM) support" for "Sunplus PWM support". Refer to screenshot of Linux Kernel Configuration menu below:

image-20240418-044125.png

3. Build Linux Image

Whether you modify the device-tree source or kernel features, execute the make command to build the Linux image.

4. Check PWM Output Pins

After booting into Linux, you can check the pin assignments by running:

cat /sys/kernel/debug/pinctrl/f8800080pinctl/pinmux-pins

This will provide a report on the pin assignments for all GPIOs. Referring to the relevant portion of the report:

~ # cat /sys/kernel/debug/pinctrl/f8800080.pinctrl/pinmux-pins Pinmux settings per pin Format: pin (name): mux_owner|gpio_owner (strict) hog? pin 0 (GPIO0): UNCLAIMED pin 1 (GPIO1): UNCLAIMED pin 2 (GPIO2): UNCLAIMED pin 3 (GPIO3): device f8103000.stmmac function GMAC group GMAC_RGMII : : pin 58 (GPIO58): device f8800d80.pwm function PWM0 group PWM0_X2 pin 59 (GPIO59): device f8800d80.pwm function PWM1 group PWM1_X2 pin 60 (GPIO60): device f8800d80.pwm function PWM2 group PWM2_X1 pin 61 (GPIO61): device f8800d80.pwm function PWM3 group PWM3_X1 pin 62 (GPIO62): UNCLAIMED :

GPIO58 (AO_MX8), GPIO59 (AO_MX9), GPIO60 (AO_MX10), and GPIO61 (AO_MX11) are assigned to PWM channels as follows:

  • GPIO58 (AO_MX8) is set to PWM0 (X2 position)

  • GPIO59 (AO_MX9) is set to PWM1 (X2 position)

  • GPIO60 (AO_MX10) is set to PWM2 (X1 position)

  • GPIO61 (AO_MX11) is set to PWM3 (X1 position)

5. Using PWM with the sysfs Interface

A straightforward sysfs interface is available for PWM control from userspace. The path to this interface is /sys/class/pwm/pwmchipN, where N represents the base of the PWM controller. Since the SP7350 has only one PWM controller, N is 0. Within this directory, you'll find the following files and directories: npwm, export, unexport, and so on.

Here's the content of the /sys/class/pwm/pwmchip0 directory as shown by the ls -l command:

~ # ls -l /sys/class/pwm/pwmchip0/ lrwxrwxrwx 1 root root 0 Jan 1 00:48 device -> ../../../f8800d80.pwm --w------- 1 root root 4096 Jan 1 00:48 export -r--r--r-- 1 root root 4096 Jan 1 00:48 npwm drwxr-xr-x 2 root root 0 Jan 1 00:48 power lrwxrwxrwx 1 root root 0 Jan 1 00:48 subsystem -> ../../../../../class/pwm -rw-r--r-- 1 root root 4096 Jan 1 00:48 uevent --w------- 1 root root 4096 Jan 1 00:48 unexport

Files and Their Descriptions:

  • npwm: This file indicates the number of PWM channels supported by this chip (read-only).

  • export: Use this file to export a PWM channel for sysfs use (write-only).

  • unexport: This file allows you to unexport a PWM channel from sysfs (write-only).

The SP7350 PWM controller supports 4 channels, as indicated by the output of the cat command:

To export PWM channels 0 through 3, you can use the following commands:

Once a PWM channel is exported, a corresponding folder pwmX is created within the pwmchipN directory, where X is the channel number. As shown by the output of the ls -l command:

You can see that the directories pwm0, pwm1, pwm2, and pwm3 have been created under /sys/class/pwm/pwmchip0/.

Here's a breakdown of the content of the /sys/class/pwm/pwmchip0/pwm0 directory:

Files and Their Descriptions:

  • period: The period of PWM signal (read/write). The unit is nanoseconds.

  • duty_cycle: The active time of PWM signal (read/write). The unit is nanoseconds. It must be less than period.

  • polarity: Changes the polarity of PWM signal (read/write). Value can be either “normal” or “inversed”.

  • enable: Enable/disable the PWM signal (read/write). Value can be either 0 (disabled) or 1 (enabled).

To set the PWM channels to the specified configurations, you can use the following commands:

PWM0 to 1 kHz with 25% duty cycle:

PWM1 to 2 kHz with 50% duty cycle:

PWM2 to 1 kHz with 75% duty cycle:

PWM3 to 1 kHz with 20% duty cycle and inverted:

Refer to snapshot of oscilloscope:

image-20240419-035233.png
  • Channels:

    • C1 (yellow) - PWM0 signal

    • C2 (red) - PWM1 signal

    • C3 (blue) - PWM2 signal

    • C4 (green) - PWM3 signal

  • PWM Signal:

    • Period:

      • PWM0 and PWM3: 1 millisecond

      • PWM1 and PWM2: 0.5 millisecond

    • Duty Cycle:

      • PWM0: 25%

      • PWM1: 50%

      • PWM2: 75%

      • PWM3: 20% (inverted)

6. PWMtest

Refer to GitHub - simonqin09/PWMtest which provides a PWM test program.