Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Current »

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 https://sunplus.atlassian.net/wiki/spaces/C3/pages/1971126471/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

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:

~ # cat /sys/class/pwm/pwmchip0/npwm
4

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

~ # echo 0 > /sys/class/pwm/pwmchip0/export
~ # echo 1 > /sys/class/pwm/pwmchip0/export
~ # echo 2 > /sys/class/pwm/pwmchip0/export
~ # echo 3 > /sys/class/pwm/pwmchip0/export

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:

~ # 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 01:07 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
drwxr-xr-x    3 root     root             0 Jan  1 01:07 pwm0
drwxr-xr-x    3 root     root             0 Jan  1 01:07 pwm1
drwxr-xr-x    3 root     root             0 Jan  1 01:07 pwm2
drwxr-xr-x    3 root     root             0 Jan  1 01:07 pwm3
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

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:

~ # ls -l /sys/class/pwm/pwmchip0/pwm0
-r--r--r--    1 root     root          4096 Jan  1 01:08 capture
-rw-r--r--    1 root     root          4096 Jan  1 01:08 duty_cycle
-rw-r--r--    1 root     root          4096 Jan  1 01:08 enable
-rw-r--r--    1 root     root          4096 Jan  1 01:08 period
-rw-r--r--    1 root     root          4096 Jan  1 01:08 polarity
drwxr-xr-x    2 root     root             0 Jan  1 01:08 power
-rw-r--r--    1 root     root          4096 Jan  1 01:08 uevent

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:

~ # echo 1000000 > /sys/class/pwm/pwmchip0/pwm0/period
~ # echo 250000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
~ # echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable

PWM1 to 2 kHz with 50% duty cycle:

~ # echo 500000 > /sys/class/pwm/pwmchip0/pwm1/period
~ # echo 250000 > /sys/class/pwm/pwmchip0/pwm1/duty_cycle
~ # echo 1 > /sys/class/pwm/pwmchip0/pwm1/enable

PWM2 to 1 kHz with 75% duty cycle:

~ # echo 500000 > /sys/class/pwm/pwmchip0/pwm2/period
~ # echo 375000 > /sys/class/pwm/pwmchip0/pwm2/duty_cycle
~ # echo 1 > /sys/class/pwm/pwmchip0/pwm2/enable

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

~ # echo 1000000 > /sys/class/pwm/pwmchip0/pwm3/period
~ # echo 200000 > /sys/class/pwm/pwmchip0/pwm3/duty_cycle
~ # echo inversed > /sys/class/pwm/pwmchip0/pwm3/polarity
~ # echo 1 > /sys/class/pwm/pwmchip0/pwm3/enable

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.

  • No labels