Registered User mNo edit summary |
Registered User mNo edit summary Tag: 2017 source edit |
||
(46 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
<noinclude> | <noinclude>{{ApplicableFor | ||
{{ | |MPUs list=STM32MP13x, STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | ||
|MPUs checklist=STM32MP13x,STM32MP15x, STM32MP21x, STM32MP23x, STM32MP25x | |||
}}</noinclude> | |||
}} | |||
</noinclude> | |||
== Article purpose == | == Article purpose == | ||
The purpose of this article is to explain how to configure the | The purpose of this article is to explain how to configure the [[TIM internal peripheral]] using the [[Device tree|device tree]] mechanism, relying on the bindings documentation, that is the description of the required and optional device-tree properties. | ||
When the peripheral is assigned to Linux<sup>®</sup> OS''', it explains: | |||
* | * how to enable PWM, trigger or quadrature encoder. | ||
* how to configure the '''board''', e.g. TIM input/output pins. | |||
It is used by the [[TIM_OpenSTLinux_drivers]] that registers relevant information in [[PWM overview|PWM]], [[IIO overview|IIO]] and [[Counter_overview|counter]] frameworks. | |||
The peripheral can be assigned to different contexts/software components, depending on the final product needs. Refer to [[How to assign an internal peripheral to an execution context]] for guidelines on this configuration. | |||
== DT bindings documentation == | == DT bindings documentation == | ||
The | The device tree binding documents are stored in the Linux kernel repository: | ||
* Linux<sup>®</sup> OS : {{CodeSource | Linux kernel | Documentation/devicetree/bindings/mfd/st,stm32-timers.yaml | Documentation/devicetree/bindings/mfd/mfd/st,stm32-timers.yaml}} | |||
* | |||
The ''TIM internal peripheral''<ref name="TIM internal peripheral"> [[TIM internal peripheral]]</ref> is a multifunction device (MFD), providing several functions represented by a separate compatible string: | |||
* '' | * ''st,stm32-timers'' deals with core resources. (e.g. registers, clock, DMAs) | ||
* ''st,stm32-pwm'' deals with PWM resources. (e.g. PWM input/output pins) | |||
* ''st,stm32-timer-trigger'' deals with trigger resources (e.g. trigger output connected to other STM32 internal peripherals) | |||
* ''st,stm32-timer-counter'' deals with quadrature encoder resources and external events counter. | |||
== DT configuration == | == DT configuration == | ||
This hardware description is a combination of | This hardware description is a combination of the '''STM32 microprocessor''' device tree files (''.dtsi'' extension) and '''board''' device tree files (''.dts'' extension). See the [[Device tree]] for an explanation of the device-tree file organization. | ||
'''STM32CubeMX''' can be used to generate the board device tree. Refer to [[#How_to_configure_the_DT_using_STM32CubeMX|How to configure the DT using STM32CubeMX]] for more details. | |||
=== DT configuration (STM32 level) === | === DT configuration (STM32 level) === | ||
'''DT root node''' (e.g. timers1...) and '''DT child nodes''' describe the [[TIM internal peripheral|TIM features]] such as: | |||
'''DT root node''' (e.g. timers1...) and '''DT child nodes''' describe the [[TIM internal peripheral | |||
* PWM | * PWM | ||
* trigger and quadrature encoder | * trigger | ||
* counter and quadrature encoder | |||
They also describe hardware parameters such as registers address, clock and DMA. | They also describe hardware parameters such as registers address, clock and DMA. | ||
====On {{MicroprocessorDevice | device=1}}==== | |||
TIM nodes are declared in stm32mp131.dtsi<ref name="stm32mp131_dtsi">{{CodeSource | Linux kernel | arch/arm/boot/dts/st/stm32mp131.dtsi | STM32MP131 device tree file}}</ref> on {{MicroprocessorDevice | device=13}}. | |||
TIM nodes are declared in stm32mp151.dtsi<ref name="stm32mp151_dtsi">{{CodeSource | Linux kernel | arch/arm/boot/dts/st/stm32mp151.dtsi | STM32MP151 device tree file}}</ref> on {{MicroprocessorDevice | device=15}}. | |||
timers1: timer@address { | timers1: timer@address { | ||
{{highlight|/* timer common resources */}} | |||
compatible = "st,stm32-timers"; | |||
... | ... | ||
pwm { | pwm { | ||
{{highlight|/* PWM*/}} | |||
compatible = "st,stm32-pwm"; | |||
}; | }; | ||
timer@'''0''' { | timer@'''0''' { | ||
compatible = "st,stm32h7-timer-trigger"; | compatible = "st,stm32h7-timer-trigger"; | ||
{{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}} | |||
reg = <'''0'''>; | |||
}; | |||
counter { | |||
compatible = "st,stm32-timer-counter"; | |||
}; | }; | ||
}; | }; | ||
{{Warning|This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.}} | |||
====On {{MicroprocessorDevice | device=2}}==== | |||
=====On {{MicroprocessorDevice | device=21}}===== | |||
TIM nodes are declared in stm32mp211.dtsi<ref name="stm32mp211_dtsi">{{CodeSource | Linux kernel | arch/arm64/boot/dts/st/stm32mp211.dtsi | STM32MP211 device tree file}}</ref> on {{MicroprocessorDevice | device=21}}. | |||
timers1: timer@address { | |||
{{highlight|/* timer common resources */}} | |||
compatible = "st,stm32mp21-timers"; | |||
... | |||
pwm { | |||
{{highlight|/* PWM*/}} | |||
compatible = "st,stm32mp21-pwm"; | |||
}; | |||
timer@'''0''' { | |||
compatible = "st,stm32mp21-timer-trigger"; | |||
{{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}} | |||
reg = <'''0'''>; | |||
}; | |||
counter { | |||
compatible = "st,stm32mp21-timer-counter"; | |||
}; | |||
}; | |||
{{Warning|This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.}} | |||
=====On {{MicroprocessorDevice | device=23}} and {{MicroprocessorDevice | device=25}}===== | |||
TIM nodes are declared in stm32mp231.dtsi<ref name="stm32mp231_dtsi">{{CodeSource | Linux kernel | arch/arm64/boot/dts/st/stm32mp231.dtsi | STM32MP231 device tree file}}</ref> on {{MicroprocessorDevice | device=23}}. | |||
TIM nodes are declared in stm32mp251.dtsi<ref name="stm32mp251_dtsi">{{CodeSource | Linux kernel | arch/arm64/boot/dts/st/stm32mp251.dtsi | STM32MP251 device tree file}}</ref> on {{MicroprocessorDevice | device=25}}. | |||
timers1: timer@address { | |||
{{highlight|/* timer common resources */}} | |||
compatible = "st,stm32mp25-timers"; | |||
... | |||
pwm { | |||
{{highlight|/* PWM*/}} | |||
compatible = "st,stm32mp25-pwm"; | |||
}; | |||
timer@'''0''' { | |||
compatible = "st,stm32mp25-timer-trigger"; | |||
{{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}} | |||
reg = <'''0'''>; | |||
}; | |||
counter { | |||
compatible = "st,stm32mp25-timer-counter"; | |||
}; | |||
}; | |||
{{Warning|This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.}} | {{Warning|This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.}} | ||
=== DT configuration (board level) === | === DT configuration (board level) === | ||
The objective of this chapter is to explain how to enable and configure the TIM DT nodes for a board: | |||
* | * Enable '''DT root node''' for the TIM instances in use (e.g timers1...) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}''' | ||
* | * Enable '''DT child node(s)''' for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}''' | ||
* | * Configure pins in use via [[Pinctrl overview|pinctrl]] through '''{{highlight|pinctrl-0}}''', '''{{highlight|pinctrl-1}}''' and '''{{highlight|pinctrl-names}}'''. | ||
To enable PWM capture on the board (optional), DMA must be configured: | |||
* Enable DMA channel(s) corresponding to the PWM input(s) by setting '''{{highlight|<nowiki>dmas = <...>, <...>;</nowiki>}}''' and matching '''{{highlight|<nowiki>dma-names = "ch1", "ch3";</nowiki>}}'''. | |||
When PWM capture isn't used, it's recommended to disable DMA channels by default, to spare them for other usage: | |||
* Disable DMA channels by setting '''{{highlight|/delete-property/dmas}}''' and '''{{highlight|/delete-property/dma-names}}''' | |||
Peripheral configuration should be done in specific board device tree files (board dts file and [[Pinctrl device tree configuration|pinctrl dtsi file]]). | |||
=== DT configuration examples === | === DT configuration examples === | ||
==== TIM configured in PWM mode==== | |||
The example below shows how to configure '''TIM1 channel 1''' to act as: | |||
* '''PWM output on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | |||
* PWM device tree provider (e.g. TIM1_CH1) used by a device tree consumer (e.g. like "pwm-leds"<ref name="pwm-leds">{{CodeSource | Linux kernel | Documentation/devicetree/bindings/leds/leds-pwm.yaml}}, PWM LEDs device tree bindings</ref>). | |||
{{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}} | |||
pwm1_pins_a: pwm1-0 { | |||
pins { | |||
pinmux = <STM32_PINMUX('E', 9, AF1)>; | |||
bias-pull-down; | |||
drive-push-pull; | |||
slew-rate = <0>; | |||
}; | |||
}; | |||
{{highlight|/* configure 'PE9' as analog input in low-power mode */}} | |||
pwm1_sleep_pins_a: pwm1-sleep-0 { | |||
pins { | |||
pinmux = <STM32_PINMUX('E', 9, ANALOG)>; | |||
}; | |||
}; | |||
{{Info|The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file.}} | |||
{{highlight|/* PWM DT provider on TIM1: "pwm1" */}} | |||
&timers1 { | |||
status = "{{highlight|okay}}"; | |||
/* spare all DMA channels since they are not needed for PWM output */ | |||
/delete-property/dmas; | |||
/delete-property/dma-names; | |||
/* define pwm1 label */ | |||
{{highlight|pwm1}}: pwm { | |||
{{highlight|/* configure PWM pins on TIM1_CH1 */}} | |||
pinctrl-0 = <&pwm1_pins_a>; | |||
pinctrl-1 = <&pwm1_sleep_pins_a>; | |||
pinctrl-names = "default", "sleep"; | |||
{{highlight|/* enable PWM on TIM1 */}} | |||
status = "{{highlight|okay}}"; | |||
}; | |||
}; | |||
* PWM DT user example | |||
{{Info| The TIM PWM DT user specifier encodes 3 cells: | |||
* PWM '''number''' (0 for CH1, 1 for CH2 and so on) | |||
* PWM '''period''' in nanoseconds | |||
* PWM '''polarity''' (0 for normal polarity or ''PWM_POLARITY_INVERTED'') | |||
}} | |||
/ { | |||
... | |||
{{highlight|/* PWM DT user on TIM1_CH1: "pwm1", example with "pwm-leds"<ref name="pwm-leds"/> */}} | |||
pwmleds { | |||
compatible = "pwm-leds"; | |||
example { | |||
label = "stm32-pwm-leds-example"; | |||
{{highlight|/* Use pwm1 channel 0 (e.g. TIM1_CH1) */}} | |||
/* period in nanoseconds (500000), normal polarity (0) */ | |||
pwms = <{{highlight|&pwm1 0}} 500000 0>; | |||
max-brightness = <127>; | |||
}; | |||
}; | |||
}; | |||
==== TIM configured in PWM mode and trigger source ==== | ==== TIM configured in PWM mode and trigger source ==== | ||
Line 71: | Line 188: | ||
* '''PWM output on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | * '''PWM output on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | ||
* '''trigger source''' (synchronous with PWM) for other internal peripheral such as [[ADC internal peripheral|STM32 ADC]] | * '''trigger source''' (synchronous with PWM) for other internal peripheral such as [[ADC internal peripheral|STM32 ADC]] | ||
{{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}} | |||
pwm1_pins_a: pwm1-0 { | pwm1_pins_a: pwm1-0 { | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, AF1)>; | pinmux = <STM32_PINMUX('E', 9, AF1)>; | ||
bias-pull-down; | bias-pull-down; | ||
drive-push-pull; | drive-push-pull; | ||
Line 82: | Line 198: | ||
}; | }; | ||
{{highlight|/* configure 'PE9' as analog input in low-power mode */}} | |||
pwm1_sleep_pins_a: pwm1-sleep-0 { | pwm1_sleep_pins_a: pwm1-sleep-0 { | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, ANALOG)>; | pinmux = <STM32_PINMUX('E', 9, ANALOG)>; | ||
}; | }; | ||
}; | }; | ||
{{Info|The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file.}} | |||
&timers1 { | &timers1 { | ||
status = "{{highlight|okay}}"; | status = "{{highlight|okay}}"; | ||
{{highlight|/* spare all DMA channels since they are not needed for PWM output */}} | |||
/delete-property/dmas; | |||
/delete-property/dma-names; | /delete-property/dma-names; | ||
pwm { | pwm { | ||
{{highlight|/* configure PWM on TIM1_CH1 */}} | |||
pinctrl-0 = <&pwm1_pins_a>; | |||
pinctrl-1 = <&pwm1_sleep_pins_a>; | pinctrl-1 = <&pwm1_sleep_pins_a>; | ||
pinctrl-names = "default", "sleep"; | pinctrl-names = "default", "sleep"; | ||
{{highlight|/* enable PWM on TIM1 */}} | |||
status = "{{highlight|okay}}"; | |||
}; | }; | ||
timer@0 { | timer@0 { | ||
{{highlight|/* enable trigger on TIM1 */}} | |||
status = "{{highlight|okay}}"; | |||
}; | }; | ||
}; | }; | ||
==== TIM configured in PWM input capture mode==== | ==== TIM configured in counter capture mode ==== | ||
The example below shows how to configure '''TIM10 channel 1''' in counter capture mode, based on the [[Counter_overview|counter subsystem]]. | |||
It is available on available on [[STM32MP257x-EV1_-_hardware_description#GPIO_expansion_connector|STM32MP257x-EV1 GPIO expansion connector]]. | |||
* Configure PB9 as alternate function to use TIM10_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]): | |||
{{highlight|/* select TIM10_CH1 alternate function 9 on 'PB9' */}} | |||
tim10_counter_pins_a: tim10-counter-0 { | |||
pins { | |||
pinmux = <STM32_PINMUX('B', 9, AF9)>; /* TIM10_CH1 */ | |||
bias-disable; | |||
}; | |||
}; | |||
{{highlight|/* configure 'PB9' as analog input in low-power mode */}} | |||
tim10_counter_sleep_pins_a: tim10-counter-sleep-0 { | |||
pins { | |||
pinmux = <STM32_PINMUX('B', 9, ANALOG)>; /* TIM10_CH1 */ | |||
}; | |||
}; | |||
{{Info|Note: one or more channels may be configured for capture.}} | |||
* Configure and enable the timer 10 to act as counter device: | |||
{{highlight|/* Enable timer 10 multi-function device. */}} | |||
&timers10 { | |||
status = "okay"; | |||
{{highlight|/* Enable timer 10 counter device. */}} | |||
counter { | |||
pinctrl-0 = <&tim10_counter_pins_a>; | |||
pinctrl-1 = <&tim10_counter_sleep_pins_a>; | |||
pinctrl-names = "default", "sleep"; | |||
status = "okay"; | |||
}; | |||
}; | |||
<div class="mw-collapsible mw-collapsed"> | |||
==== TIM configured in PWM input capture mode ==== | |||
<div class="mw-collapsible-content"> | |||
{{Warning|This chapter is only applicable for {{MicroprocessorDevice | device=1}}.<br/> | |||
It is recommended to use the [[#TIM configured in counter capture mode|TIM configured in counter capture mode]] instead of PWM input capture mode.}} | |||
This example shows how to configure '''TIM1 channel 1''' in PWM input capture mode (e.g. period and duty cycle). | |||
* Configure '''PWM input on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | * Configure '''PWM input on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | ||
{{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}} | |||
* | |||
* | |||
pwm1_in_pins_a: pwm1-in-0 { | pwm1_in_pins_a: pwm1-in-0 { | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, AF1)>; | pinmux = <STM32_PINMUX('E', 9, AF1)>; | ||
bias-disable; | bias-disable; | ||
}; | }; | ||
}; | }; | ||
{{highlight|/* configure 'PE9' as analog input in low-power mode */}} | |||
pwm1_in_sleep_pins_a: pwm1-in-sleep-0 { | pwm1_in_sleep_pins_a: pwm1-in-sleep-0 { | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, ANALOG)>; | pinmux = <STM32_PINMUX('E', 9, ANALOG)>; | ||
}; | }; | ||
}; | }; | ||
A DMA channel is required and must be configured depending on the PWM input channel: | |||
* Select '''DMA channel 1''', "ch1", to capture '''PWM input channel 1 and/or 2''' | |||
* Select '''DMA channel 3''', "ch3", to capture '''PWM input channel 3 and/or 4''' | |||
* Select both "ch1" and "ch3" dmas to enable capture on all PWM input channels | |||
&timers1 { | &timers1 { | ||
status = "{{highlight|okay}}"; | status = "{{highlight|okay}}"; | ||
{{highlight|/* Enable DMA "ch1" for PWM input on TIM1_CH1 */}} | |||
'''dmas = <&dmamux1 11 0x400 0x1>;''' | |||
'''dma-names = "ch1";''' | '''dma-names = "ch1";''' | ||
pwm { | pwm { | ||
{{highlight|/* configure PWM input pins, e.g. TIM1_CH1 */}} | |||
pinctrl-0 = <&pwm1_in_pins_a>; | |||
pinctrl-1 = <&pwm1_in_sleep_pins_a>; | pinctrl-1 = <&pwm1_in_sleep_pins_a>; | ||
pinctrl-names = "default", "sleep"; | pinctrl-names = "default", "sleep"; | ||
{{highlight|/* enable PWM on TIM1 */}} | |||
status = "{{highlight|okay}}"; | |||
}; | }; | ||
}; | }; | ||
{{ReviewsComments|-- [[User:Emmanuel Combette|Emmanuel Combette]] ([[User talk:Emmanuel Combette|talk]]) 10:47, 2 May 2025 (CEST)<br />Explain retation between DMA Channel and Timer Channel Input is in the Reference manual}} | |||
{{Info|DMA channels 1 and/or 3 for each TIM can be picked from the '''"dmas"''' list in stm32mp131.dtsi<ref name="stm32mp131_dtsi"/> or stm32mp151.dtsi<ref name="stm32mp151_dtsi"/> files}} | |||
</div> | |||
</div> | |||
==== TIM configured as quadrature encoder interface ==== | ==== TIM configured as quadrature encoder interface ==== | ||
The example below shows how to configure '''TIM1''' to interface with a quadrature encoder | The example below shows how to configure '''TIM1''' to interface with a quadrature encoder, based on the [[Counter_overview|counter subsystem]]: | ||
* '''Configure PE9 and PE11 as encoder input pins''', e.g. TIM1_CH1, TIM1_CH2 ([[Pinctrl_device_tree_configuration|see pinctrl device tree configuration]] and [[GPIO internal peripheral]]) | |||
{{Info|On the STM32MP157X-DKX discovery board, TIM1_CH1 and TIM1_CH2 signals are accessible via the D6 and D10 pins of the [[STM32MP157x-DKx_-_hardware_description#Arduino_Uno_connector|Arduino Uno connector]].}} | |||
tim1_in_pins_a: tim1-in-pins-0 { | tim1_in_pins_a: tim1-in-pins-0 { | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */ | pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */ | ||
<STM32_PINMUX(' | <STM32_PINMUX('E', 11, AF1)>; /* TIM1_CH2 */ | ||
bias-disable; | bias-disable; | ||
}; | }; | ||
Line 150: | Line 321: | ||
pins { | pins { | ||
pinmux = <STM32_PINMUX('E', 9, ANALOG)>, /* TIM1_CH1 */ | pinmux = <STM32_PINMUX('E', 9, ANALOG)>, /* TIM1_CH1 */ | ||
<STM32_PINMUX(' | <STM32_PINMUX('E', 11, ANALOG)>; /* TIM1_CH2 */ | ||
}; | }; | ||
}; | }; | ||
Line 156: | Line 327: | ||
&timers1 { | &timers1 { | ||
status = "{{highlight|okay}}"; | status = "{{highlight|okay}}"; | ||
/delete-property/dmas; | /delete-property/dmas; {{highlight|/* spare all DMA channels since they are not required for quadrature encoder interface */}} | ||
/delete-property/dma-names; | /delete-property/dma-names; | ||
counter { | |||
pinctrl-0 = <&tim1_in_pins_a>; | pinctrl-0 = <&tim1_in_pins_a>; {{highlight|/* configure TIM1_CH1 and TIM1_CH2 as encoder input pins */}} | ||
pinctrl-1 = <&tim1_in_pins_sleep_a>; | pinctrl-1 = <&tim1_in_pins_sleep_a>; | ||
pinctrl-names = "default", "sleep"; | pinctrl-names = "default", "sleep"; | ||
status = "{{highlight|okay}}"; | status = "{{highlight|okay}}"; {{highlight|/* enable Encoder interface mode on TIM1 */}} | ||
}; | }; | ||
}; | }; | ||
==How to configure the DT using STM32CubeMX== | ==How to configure the DT using STM32CubeMX== | ||
The [[STM32CubeMX]] tool can be used to configure the STM32MPU device and get the corresponding [[Device_tree# | The [[STM32CubeMX]] tool can be used to configure the STM32MPU device and get the corresponding [[Device_tree#STM32_MPU|platform configuration device tree]] files.<br /> | ||
STM32CubeMX may not support all the properties described in DT binding files listed in the above [[#DT bindings documentation|DT bindings documentation]] paragraph. If so, the tool inserts '''user sections''' in the generated device tree. These sections can then be edited to add some properties, and they are preserved from one generation to another. Refer to [[STM32CubeMX]] user manual for further information. | |||
==References== | ==References== | ||
Refer to the following links for additional information: | |||
<references /> | |||
< | <noinclude> | ||
[[Category:Device tree configuration]] | |||
[[Category:IIO]] | |||
[[Category:Timers]] | |||
{{PublicationRequestId | 8783 | 2018-09-20 | AnneJ}} | |||
{{ArticleBasedOnModel|Peripheral_or_framework_device_tree_configuration_model}} | |||
</noinclude> |
Latest revision as of 18:26, 23 June 2025
1. Article purpose[edit | edit source]
The purpose of this article is to explain how to configure the TIM internal peripheral using the device tree mechanism, relying on the bindings documentation, that is the description of the required and optional device-tree properties.
When the peripheral is assigned to Linux® OS, it explains:
- how to enable PWM, trigger or quadrature encoder.
- how to configure the board, e.g. TIM input/output pins.
It is used by the TIM_OpenSTLinux_drivers that registers relevant information in PWM, IIO and counter frameworks.
The peripheral can be assigned to different contexts/software components, depending on the final product needs. Refer to How to assign an internal peripheral to an execution context for guidelines on this configuration.
2. DT bindings documentation[edit | edit source]
The device tree binding documents are stored in the Linux kernel repository:
- Linux® OS : Template:CodeSource
The TIM internal peripheral[1] is a multifunction device (MFD), providing several functions represented by a separate compatible string:
- st,stm32-timers deals with core resources. (e.g. registers, clock, DMAs)
- st,stm32-pwm deals with PWM resources. (e.g. PWM input/output pins)
- st,stm32-timer-trigger deals with trigger resources (e.g. trigger output connected to other STM32 internal peripherals)
- st,stm32-timer-counter deals with quadrature encoder resources and external events counter.
3. DT configuration[edit | edit source]
This hardware description is a combination of the STM32 microprocessor device tree files (.dtsi extension) and board device tree files (.dts extension). See the Device tree for an explanation of the device-tree file organization.
STM32CubeMX can be used to generate the board device tree. Refer to How to configure the DT using STM32CubeMX for more details.
3.1. DT configuration (STM32 level)[edit | edit source]
DT root node (e.g. timers1...) and DT child nodes describe the TIM features such as:
- PWM
- trigger
- counter and quadrature encoder
They also describe hardware parameters such as registers address, clock and DMA.
3.1.1. On STM32MP1 series[edit | edit source]
TIM nodes are declared in stm32mp131.dtsi[2] on STM32MP13x lines .
TIM nodes are declared in stm32mp151.dtsi[3] on STM32MP15x lines .
Template:Highlight compatible = "st,stm32-timers"; ... pwm { Template:Highlight compatible = "st,stm32-pwm"; }; timer@0 { compatible = "st,stm32h7-timer-trigger"; Template:Highlight reg = <0>; }; counter { compatible = "st,stm32-timer-counter"; }; };timers1: timer@address {
3.1.2. On STM32MP2 series[edit | edit source]
3.1.2.1. On STM32MP21x lines
[edit | edit source]
TIM nodes are declared in stm32mp211.dtsi[4] on STM32MP21x lines .
Template:Highlight compatible = "st,stm32mp21-timers"; ... pwm { Template:Highlight compatible = "st,stm32mp21-pwm"; }; timer@0 { compatible = "st,stm32mp21-timer-trigger"; Template:Highlight reg = <0>; }; counter { compatible = "st,stm32mp21-timer-counter"; }; };timers1: timer@address {
3.1.2.2. On STM32MP23x lines
and STM32MP25x lines
[edit | edit source]
TIM nodes are declared in stm32mp231.dtsi[5] on STM32MP23x lines .
TIM nodes are declared in stm32mp251.dtsi[6] on STM32MP25x lines .
Template:Highlight compatible = "st,stm32mp25-timers"; ... pwm { Template:Highlight compatible = "st,stm32mp25-pwm"; }; timer@0 { compatible = "st,stm32mp25-timer-trigger"; Template:Highlight reg = <0>; }; counter { compatible = "st,stm32mp25-timer-counter"; }; };timers1: timer@address {
3.2. DT configuration (board level)[edit | edit source]
The objective of this chapter is to explain how to enable and configure the TIM DT nodes for a board:
- Enable DT root node for the TIM instances in use (e.g timers1...) by setting Template:Highlight
- Enable DT child node(s) for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting Template:Highlight
- Configure pins in use via pinctrl through Template:Highlight, Template:Highlight and Template:Highlight.
To enable PWM capture on the board (optional), DMA must be configured:
- Enable DMA channel(s) corresponding to the PWM input(s) by setting Template:Highlight and matching Template:Highlight.
When PWM capture isn't used, it's recommended to disable DMA channels by default, to spare them for other usage:
- Disable DMA channels by setting Template:Highlight and Template:Highlight
Peripheral configuration should be done in specific board device tree files (board dts file and pinctrl dtsi file).
3.3. DT configuration examples[edit | edit source]
3.3.1. TIM configured in PWM mode[edit | edit source]
The example below shows how to configure TIM1 channel 1 to act as:
- PWM output on PE9, e.g. TIM1_CH1 (See pinctrl device tree configuration and GPIO internal peripheral)
- PWM device tree provider (e.g. TIM1_CH1) used by a device tree consumer (e.g. like "pwm-leds"[7]).
Template:Highlight pwm1_pins_a: pwm1-0 { pins { pinmux = <STM32_PINMUX('E', 9, AF1)>; bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; Template:Highlight pwm1_sleep_pins_a: pwm1-sleep-0 { pins { pinmux = <STM32_PINMUX('E', 9, ANALOG)>; }; };
![]() |
The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file. |
Template:Highlight &timers1 { status = "Template:Highlight"; /* spare all DMA channels since they are not needed for PWM output */ /delete-property/dmas; /delete-property/dma-names; /* define pwm1 label */ Template:Highlight: pwm { Template:Highlight pinctrl-0 = <&pwm1_pins_a>; pinctrl-1 = <&pwm1_sleep_pins_a>; pinctrl-names = "default", "sleep"; Template:Highlight status = "Template:Highlight"; }; };
- PWM DT user example
![]() |
The TIM PWM DT user specifier encodes 3 cells:
|
Template:Highlight pwmleds { compatible = "pwm-leds"; example { label = "stm32-pwm-leds-example"; Template:Highlight /* period in nanoseconds (500000), normal polarity (0) */ pwms = <Template:Highlight 500000 0>; max-brightness = <127>; }; }; };/ { ...
3.3.2. TIM configured in PWM mode and trigger source[edit | edit source]
The example below shows how to configure TIM1 channel 1 to act as:
- PWM output on PE9, e.g. TIM1_CH1 (See pinctrl device tree configuration and GPIO internal peripheral)
- trigger source (synchronous with PWM) for other internal peripheral such as STM32 ADC
Template:Highlight pwm1_pins_a: pwm1-0 { pins { pinmux = <STM32_PINMUX('E', 9, AF1)>; bias-pull-down; drive-push-pull; slew-rate = <0>; }; }; Template:Highlight pwm1_sleep_pins_a: pwm1-sleep-0 { pins { pinmux = <STM32_PINMUX('E', 9, ANALOG)>; }; };
![]() |
The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file. |
Template:Highlight"; Template:Highlight /delete-property/dmas; /delete-property/dma-names; pwm { Template:Highlight pinctrl-0 = <&pwm1_pins_a>; pinctrl-1 = <&pwm1_sleep_pins_a>; pinctrl-names = "default", "sleep"; Template:Highlight status = "Template:Highlight"; }; timer@0 { Template:Highlight status = "Template:Highlight"; }; };&timers1 { status = "
3.3.3. TIM configured in counter capture mode[edit | edit source]
The example below shows how to configure TIM10 channel 1 in counter capture mode, based on the counter subsystem.
It is available on available on STM32MP257x-EV1 GPIO expansion connector.
- Configure PB9 as alternate function to use TIM10_CH1 (See pinctrl device tree configuration and GPIO internal peripheral):
Template:Highlight tim10_counter_pins_a: tim10-counter-0 { pins { pinmux = <STM32_PINMUX('B', 9, AF9)>; /* TIM10_CH1 */ bias-disable; }; }; Template:Highlight tim10_counter_sleep_pins_a: tim10-counter-sleep-0 { pins { pinmux = <STM32_PINMUX('B', 9, ANALOG)>; /* TIM10_CH1 */ }; };
![]() |
Note: one or more channels may be configured for capture. |
- Configure and enable the timer 10 to act as counter device:
Template:Highlight &timers10 { status = "okay"; Template:Highlight counter { pinctrl-0 = <&tim10_counter_pins_a>; pinctrl-1 = <&tim10_counter_sleep_pins_a>; pinctrl-names = "default", "sleep"; status = "okay"; }; };
3.3.4. TIM configured in PWM input capture mode[edit | edit source]
3.3.5. TIM configured as quadrature encoder interface[edit | edit source]
The example below shows how to configure TIM1 to interface with a quadrature encoder, based on the counter subsystem:
- Configure PE9 and PE11 as encoder input pins, e.g. TIM1_CH1, TIM1_CH2 (see pinctrl device tree configuration and GPIO internal peripheral)
![]() |
On the STM32MP157X-DKX discovery board, TIM1_CH1 and TIM1_CH2 signals are accessible via the D6 and D10 pins of the Arduino Uno connector. |
tim1_in_pins_a: tim1-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */
<STM32_PINMUX('E', 11, AF1)>; /* TIM1_CH2 */
bias-disable;
};
};
tim1_in_pins_sleep_a: tim1-in-pins-sleep-0 {
pins {
pinmux = <STM32_PINMUX('E', 9, ANALOG)>, /* TIM1_CH1 */
<STM32_PINMUX('E', 11, ANALOG)>; /* TIM1_CH2 */
};
};
Template:Highlight"; /delete-property/dmas; Template:Highlight /delete-property/dma-names; counter { pinctrl-0 = <&tim1_in_pins_a>; Template:Highlight pinctrl-1 = <&tim1_in_pins_sleep_a>; pinctrl-names = "default", "sleep"; status = "Template:Highlight"; Template:Highlight }; };&timers1 { status = "
4. How to configure the DT using STM32CubeMX[edit | edit source]
The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.
STM32CubeMX may not support all the properties described in DT binding files listed in the above DT bindings documentation paragraph. If so, the tool inserts user sections in the generated device tree. These sections can then be edited to add some properties, and they are preserved from one generation to another. Refer to STM32CubeMX user manual for further information.
5. References[edit | edit source]
Refer to the following links for additional information:
- ↑ TIM internal peripheral
- ↑ Jump up to: 2.0 2.1 Template:CodeSource
- ↑ Jump up to: 3.0 3.1 Template:CodeSource
- ↑ Template:CodeSource
- ↑ Template:CodeSource
- ↑ Template:CodeSource
- ↑ Template:CodeSource, PWM LEDs device tree bindings