Pulse-width modulation (PWM) is a technique that modifies the duty cycle of a pulsing signal to encode information or to control the amount of energy provided to a charge.
On the ConnectCore MP25 system-on-module:
-
Up to three Advanced-control timers signals (TIM1, TIM8 and TIM20 ) available from the STM32MP25 system-on-chip (multiplexed with other signals) that can be used to generate PWM output waveform.
-
Up to twelve General-purpose timers signals (from TIM2 to TIM5 and from TIM10 to TIM17) available from the STM32MP25 system-on-chip (multiplexed with other signals) that can be used to generate PWM output waveform.
On the ConnectCore MP25 Development Kit:
-
PWM20 channel 4 (Port B GPIO0) is used for display backlight.
-
PWM2 channel 4 (Port F GPIO0) is available at PWM pin of MikroBus connector.
Kernel configuration
You can manage the STM32MP25 PWM driver support through the following kernel configuration options:
-
PWM support (
CONFIG_PWM
) -
STM32 PWM support (
CONFIG_PWM_STM32
) -
STM32 PWM low power support (
CONFIG_PWM_STM32_LP
)
These options are enabled as built-in on the default ConnectCore MP25 kernel configuration file.
Kernel driver
The driver for the STM32MP25 PWM is located at:
File | Description |
---|---|
STM32 PWM driver |
|
STM32 PWM LP driver |
Device tree bindings and customization
The STM32MP25 PWM interface is documented at Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml
.
The STM32MP25 PWM LP interface is documented at Documentation/devicetree/bindings/mfd/st,stm32-lptimer.yaml
.
STM32MP25 PWM interfaces
The common STM32MP25 CPU device tree file contains entries for all the timers that can have PWM functionality (excerpt shows a few):
timers2: timer@40000000 {
compatible = "st,stm32mp25-timers";
reg = <0x40000000 0x400>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "global";
clocks = <&rcc CK_KER_TIM2>;
clock-names = "int";
#address-cells = <1>;
#size-cells = <0>;
feature-domains = <&rifsc STM32MP25_RIFSC_TIM2_ID>;
power-domains = <&CLUSTER_PD>;
status = "disabled";
pwm {
compatible = "st,stm32mp25-pwm";
#pwm-cells = <3>;
status = "disabled";
};
timer@1 {
compatible = "st,stm32mp25-timer-trigger";
reg = <1>;
status = "disabled";
};
counter {
compatible = "st,stm32mp25-timer-counter";
status = "disabled";
};
};
lptimer1: timer@40090000 {
compatible = "st,stm32mp25-lptimer";
reg = <0x40090000 0x400>;
interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CK_KER_LPTIM1>;
clock-names = "mux";
#address-cells = <1>;
#size-cells = <0>;
feature-domains = <&rifsc STM32MP25_RIFSC_LPTIM1_ID>;
power-domains = <&RET_PD>;
status = "disabled";
counter {
compatible = "st,stm32mp25-lptimer-counter";
status = "disabled";
};
pwm {
compatible = "st,stm32mp25-pwm-lp";
#pwm-cells = <3>;
status = "disabled";
};
timer {
compatible = "st,stm32mp25-lptimer-timer";
status = "disabled";
};
trigger@0 {
compatible = "st,stm32mp25-lptimer-trigger";
reg = <0>;
status = "disabled";
};
};
PINCTRL configuration
You must configure the pads that are to be used as STM32MP25 PWMs. See Pin multiplexing (IOMUX).
STM32MP25 pads should only have one IOMUX configuration. Remove other configurations for those pads, like GPIO, when configuring them as PWMs. |
The following external pads are configured as PWMs on the default ConnectCore MP25 Development Kit device tree:
-
On the LVDS connector:
Pad Signal PWM 16
BCKL_PWM
PWM20 channel 4 (PWM20_CH4)
-
On the mikroBUS™ connector J40:
Pad Signal PWM 1
MIKROBUS_PWM
PWM2 channel 4 (PWM2_CH4)
Example: enable PWM2 on ConnectCore MP25 Development Kit
For example, PWM2 is available on the ConnectCore MP25 Development Kit MikroBus connector which corresponds to pad Port F GPIO0 (PWM2_CH4) of the CPU. In order to enable it, you must:
-
Configure the pad Port F GPIO0 (PWM2_CH4)
-
Enable the PWM node.
&timers2 {
/delete-property/dmas;
/delete-property/dma-names;
status = "okay";
pwm_mikrobus: pwm {
pinctrl-0 = <&ccmp25_pwm2_pins>;
pinctrl-1 = <&ccmp25_pwm2_sleep_pins>;
pinctrl-names = "default", "sleep";
status = "okay";
};
timer@1 {
status = "okay";
};
};
&pinctrl {
ccmp25_pwm2_pins: ccmp25-pwm2-0 {
pins {
pinmux = <STM32_PINMUX('F', 11, AF7)>; /* TIM2_CH4 */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
};
ccmp25_pwm2_sleep_pins: ccmp25-pwm2-sleep-0 {
pins {
pinmux = <STM32_PINMUX('F', 11, ANALOG)>; /* TIM2_CH4 */
};
};
};
Using the PWM channels
Control PWM signal from sysfs
Each of the {number-of-timers} TIM interfaces is registered in the system as a standalone PWM controller.
On the ConnectCore MP25 Development Kit:
-
PWM2 is enabled (used for backlight control of LCD and LVDS displays)
-
PWM2 is enabled on pin 1 of MikroBus™ connector (J40)
-
All other PWM channels are disabled by default
The PWM interfaces appear under /sys/class/pwm
:
# ls /sys/class/pwm/
pwmchip0
The PWM interfaces begin numbering with an index of 0.
Each PWM interface can manage several PWM channels.
Check the number of channels of an interface by printing the value of npwm
:
# cat /sys/class/pwm/pwmchip0/npwm
4
To access a channel of the PWM interface, write the channel index to the export
descriptor.
Notice the hardware manuals name the channels starting from 1 but Linux indexes start at 0.
To access channel 1, write 0 to the export
descriptor:
# echo 0 > /sys/class/pwm/pwmchip0/export
To get a PWM output on a given pad, the selected channel must match the pinctrl functionality for that pad.
For instance, in the example above, pad at Port F GPIO0 can function as PWM 2 channel 4, thus the 0 on the command.
Exporting a different channel would require to use a different pinctrl on a different pad.
|
You won’t be able to request PWM channels that are in use by other drivers, like the one used by the backlight. |
Now you can access the PWM channel and configure its settings:
# ls /sys/class/pwm/pwmchip0/pwm0/
duty_cycle enable period polarity power uevent
Period and duty cycle must be given in nanoseconds. For example, to configure a 100kHz signal with 20% duty cycle:
# echo 10000 > /sys/class/pwm/pwmchip0/pwm0/period
# echo 2000 > /sys/class/pwm/pwmchip0/pwm0/duty_cycle
To enable the PWM signal:
# echo 1 > /sys/class/pwm/pwmchip0/pwm0/enable
The default polarity is normal
(active high for the duty cycle).
To invert the polarity:
# echo inversed > /sys/class/pwm/pwmchip0/pwm0/polarity
Using Digi APIx library from a C application
An example application called apix-pwm-example
is included in the dey-examples-digiapix recipe (part of dey-examples package) of the meta-digi layer.
This application shows how to generate a PWM signal using Digi APIx library on the ConnectCore MP25 platform.
Go to GitHub to see the application instructions and source code.
See PWM API for more information about the PWM APIx.