Difference between revisions of "TIM device tree configuration"

[quality revision] [quality revision]
m
m (TIM configured in PWM mode)
 

1 Article purpose[edit]

The purpose of this article is to explain how to configure the timer (TIM)[1] when the peripheral is assigned to Linux® OS:

  • Configuring the timer peripheral to enable PWM, trigger or quadrature encoder.
  • Configuring the board, e.g. TIM pins.

The configuration is performed using the device tree mechanism[2].

It is used by the TIM Linux driver that registers relevant information in PWM and IIO frameworks.

2 DT bindings documentation[edit]

The TIM internal peripheral[1] is a multifunction device (MFD).

Each function is represented by a separate DT binding document:

  • STM32 TIM MFD device tree bindings[3] document deals with core resources (e.g. registers, clock, DMAs)
  • STM32 TIM PWM device tree bindings[4] document deals with PWM resources (e.g. PWM input/output pins)
  • STM32 TIM IIO trigger/encoder device tree bindings[5] document deals with other internal peripheral triggering and quadrature encoder resources

3 DT configuration[edit]

This hardware description is a combination of both STM32 microprocessor and board device tree files. Refer to Device tree for more explanations about device tree file split.

The 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]

TIM nodes are declared in stm32mp157c.dtsi[6].

DT root node (e.g. timers1...) and DT child nodes describe the TIM features such as:

  • PWM
  • trigger and quadrature encoder

They also describe hardware parameters such as registers address, clock and DMA.

timers1: timer@address {
	compatible = "st,stm32-timers";                      /* timer common resources */
	...
	pwm {
		compatible = "st,stm32-pwmtimers";
	...
	pwm               {
		/* PWM*/
	};
	timer@0 {
		compatible = "st,stm32h7stm32-timer-triggerpwm";
	};
	timer@0 {
 		/* trigger and quadrature encoder */
		regcompatible = <0>;                                   "st,stm32h7-timer-trigger";
		/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */
		reg = <0>;
	};
};
Warning.png This device tree part is related to STM32 microprocessors. It must be kept as is, without being modified by the end-user.

3.2 DT configuration (board level)[edit]

This part is used to configure and enable the TIM hardware used on the board:

  • Enabling DT root node for the TIM instances in use (e.g timers1...) by setting status = "okay";
  • Enabling DT child node(s) for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting status = "okay";
  • Configuring pins in use via pinctrl through pinctrl-0, pinctrl-1 and 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 dmas = <...>, <...>; and matching dma-names = "ch1", "ch3";.

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 /delete-property/dmas and /delete-property/dma-names

3.3 DT configuration examples[edit]

3.3.1 TIM configured in PWM mode and trigger source[edit]

The example below shows how to configure TIM1 channel 1 to act as:

Note: The PWM output does not require any DMA channel. Disable them if they are configured by default in the .dtsi file.

  • PWM device tree provider (e.g. TIM1_CH1) used by a device tree consumer (e.g. like "pwm-leds"[7]). This is available since ecosystem release ≥ v1.1.0 More info.png
/* select TIM1_CH1 alternate function 1 on 'PE9' */
pwm1_pins_a: pwm1-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, AF1)>;
       /* select TIM1_CH1 alternate function 1 on 'PE9' */
		bias-pull-down;
		drive-push-pull;
		slew-rate = <0>;
	};
};

/* configure 'PE9' as analog input in low-power mode */
pwm1_sleep_pins_a: pwm1-sleep-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, ANALOG)>;
	};
   };

Info.png The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file.
/* configurePWM 'PE9'DT asprovider analogon input in low-power mode TIM1: "pwm1" */
	};
};
&timers1 {
	status = "okay";
	/delete-property/dmas;                               /* spare all DMA channels since they are not needed for PWM output */
	/delete-property/dmas;
	/delete-property/dma-names;
	/* define pwm1 label */
	pwm1: pwm {
		/* configure PWM pins on TIM1_CH1 */
		pinctrl-0 = <&pwm1_pins_a>;
		pinctrl-1 = <&pwm1_sleep_pins_a>;
		pinctrl-names = "default", "sleep";
		/* enable PWM on TIM1 */
		status = "okay";
	};
};

PWM DT user example below is available since ecosystem release ≥ v1.1.0 More info.png

Info.png 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)
/ {
	...
	/* configure PWM DT user on TIM1_CH1: "pwm1", example with "pwm-leds"[7] */
		pinctrl-1 = <&pwm1_sleep_pins_a>;
		pinctrl-names = "default", "sleep";
		status = "okay";                             /* enable PWM on TIM1 */
	};
	timer@0 {
		status = "okay"pwmleds {
		compatible = "pwm-leds";
		example {
			label = "stm32-pwm-leds-example";
			/* Use pwm1 channel 0 (e.g. TIM1_CH1) */
			/* period in nanoseconds (500000), normal polarity (0) */
			pwms = <&pwm1 0 500000 0>;
			max-brightness = <127>;
		};
	};
};

3.3.2 TIM configured in PWM mode and trigger source[edit]

The example below shows how to configure TIM1 channel 1 to act as:

/* 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>;
	};
};

/* configure 'PE9' as analog input in low-power mode */
pwm1_sleep_pins_a: pwm1-sleep-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, ANALOG)>;
	};
};

Info.png The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file.
&timers1 {
	status = "okay";
	/* spare all DMA channels since they are not needed for PWM output */
	/delete-property/dmas;
	/delete-property/dma-names;
	pwm {
		/* configure PWM on TIM1_CH1 */
		pinctrl-0 = <&pwm1_pins_a>;          
		pinctrl-1 = <&pwm1_sleep_pins_a>;
		pinctrl-names = "default", "sleep";
		/* enable PWM on TIM1 */
		status = "okay";
	};
	timer@0 {
		/* enable trigger on TIM1 */
		status = "okay";
	};
};

3.3.23 TIM configured in PWM input capture mode[edit]

The example below shows how to configure TIM1 channel 1 in PWM input capture mode (e.g. period and duty cycle):

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 TIM1_CH1 alternate function 1 on 'PE9' */
pwm1_in_pins_a: pwm1-in-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, AF1)>;
		bias-disable;
	};
};

   /* select TIM1_CH1 alternate function 1 on 'PE9' */
		bias-disable;
	};
};

configure 'PE9' as analog input in low-power mode */
pwm1_in_sleep_pins_a: pwm1-in-sleep-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, ANALOG)>;
    /* configure 'PE9' as analog input in low-power mode */
	};
};

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 {
	status = "okay";
	dmas = <&dmamux1 11 0x400 0x5>;                      /* Enable DMA "ch1" for PWM input on TIM1_CH1 */
	dmas = <&dmamux1 11 0x400 0x5>;
	dma-names = "ch1";
	pwm {
		pinctrl-0 = <&pwm1_in_pins_a>;               /* configure PWM input pins, e.g. TIM1_CH1 */
		pinctrl-0 = <&pwm1_in_pins_a>;
		pinctrl-1 = <&pwm1_in_sleep_pins_a>;
		pinctrl-names = "default", "sleep";
		status = "okay";                             /* enable PWM on TIM1 */
		status = "okay";
	};
};
Info.png DMA channels 1 and/or 3 for each TIM can be picked from the "dmas" list in stm32mp157c.dtsi[6] file

3.3.4 TIM configured as quadrature encoder interface[edit]

The example below shows how to configure TIM1 to interface with a quadrature encoder:

tim1_in_pins_a: tim1-in-pins-0 {
	pins {
		pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */
			 <STM32_PINMUX('J', 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('J', 11, ANALOG)>; /* TIM1_CH2 */
	};
};
&timers1 {
	status = "okay";
	/delete-property/dmas;                               /* spare all DMA channels since they are not required for quadrature encoder interface */
	/delete-property/dma-names;
	timer@0 {
		pinctrl-0 = <&tim1_in_pins_a>;               /* configure TIM1_CH1 and TIM1_CH2 as encoder input pins */
		pinctrl-1 = <&tim1_in_pins_sleep_a>;
		pinctrl-names = "default", "sleep";
		status = "okay";                             /* enable Encoder interface mode on TIM1 */
	};
};

4 How to configure the DT using STM32CubeMX[edit]

The STM32CubeMX tool can be used to configure the STM32MPU device and get the corresponding platform configuration device tree files.
The STM32CubeMX may not support all the properties described 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]

Please refer to the following links for additional information:





<noinclude>

{{ArticleBasedOnModel|[[Peripheral or framework device tree configuration model]]}}
{{ArticleMainWriter|FabriceG}}
{{ArticleApprovedVersion| FabriceG| BenjaminG | No previous approved version | AnneJ - 20Sept'18 - 8783 | 20Sept'18 }}

[[Category:Device tree configuration]]
[[Category:IIO]]
[[Category:Timers]]

{{ReviewsComments|JCT 1840: alignment needed with the last version of the model [[Peripheral or framework device tree configuration model]]<br>

[[Category:ToBeAlignedWithModel]]
}}</noinclude>

==  Article purpose ==
The purpose of this article is to explain how to configure the ''timer (TIM)''<ref name="TIM internal peripheral"> [[TIM internal peripheral]]</ref> ''' when the peripheral is assigned to Linux<sup>&reg;</sup> OS''':

* Configuring the timer '''peripheral''' to enable PWM, trigger or quadrature encoder.
* Configuring the '''board''', e.g. TIM pins.

The configuration is performed using the '''device tree mechanism'''<ref> [[Device tree]]</ref>.

It is used by the [[TIM Linux driver]] that registers relevant information in [[PWM overview|PWM]] and [[IIO overview|IIO]] frameworks.

== DT bindings documentation ==
The ''TIM internal peripheral''<ref name="TIM internal peripheral"/> is a multifunction device (MFD).

Each function is represented by a separate DT binding document:
* ''STM32 TIM MFD device tree bindings''<ref>{{CodeSource | Linux kernel | Documentation/devicetree/bindings/mfd/stm32-timers.txt | Documentation/devicetree/bindings/mfd/stm32-timers.txt}}, STM32 TIM MFD device tree bindings</ref> document deals with core resources (e.g. registers, clock, DMAs)

* ''STM32 TIM PWM device tree bindings''<ref>{{CodeSource | Linux kernel | Documentation/devicetree/bindings/pwm/pwm-stm32.txt | Documentation/devicetree/bindings/pwm/pwm-stm32.txt}}, STM32 TIM PWM device tree bindings</ref> document deals with PWM resources (e.g. PWM input/output pins)

* ''STM32 TIM IIO trigger/encoder device tree bindings''<ref>{{CodeSource | Linux kernel | Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt | Documentation/devicetree/bindings/iio/timer/stm32-timer-trigger.txt}}, STM32 TIM trigger/encoder device tree bindings</ref> document deals with other internal peripheral triggering and quadrature encoder resources

== DT configuration ==
This hardware description is a combination of both STM32 microprocessor and board device tree files. Refer to [[Device tree]] for more explanations about device tree file split.

The '''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) ===
TIM nodes are declared in stm32mp157c.dtsi<ref name="stm32mp157c.dtsi">{{CodeSource | Linux kernel | arch/arm/boot/dts/stm32mp157c.dtsi | stm32mp157c.dtsi}}, STM32.dtsi file</ref>.

'''DT root node''' (e.g. timers1...) and '''DT child nodes''' describe the [[TIM internal peripheral#Features|TIM features]] such as:
* PWM
* trigger and quadrature encoder

They also describe hardware parameters such as registers address, clock and DMA.
 timers1: timer@address {compatible = "st,stm32-timers";                      {{highlight|/* timer common resources */}}...
 	pwm {
 		compatible = "st,stm32-pwm";                 {{highlight|/* PWM*/}}
 	};
 	timer@'''0''' {
 		compatible = "st,stm32h7-timer-trigger";     compatible = "st,stm32-timers";
 	...
 	pwm {
 		{{highlight|/* PWM*/}}
 		compatible = "st,stm32-pwm";
 	};
 	timer@'''0''' {{{highlight|/* trigger and quadrature encoder */}}reg = <'''0'''>;                                   compatible = "st,stm32h7-timer-trigger";{{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}}	reg = <'''0'''>;};
 };
{{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) ===
This part is used to configure and enable the TIM hardware used on the board:
* Enabling '''DT root node''' for the TIM instances in use (e.g timers1...) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}'''
* Enabling '''DT child node(s)''' for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}'''
* Configuring pins in use via [[Pinctrl overview|pinctrl]] through '''{{highlight|pinctrl-0''', '''pinctrl-1''' and '''pinctrl-names'''.

=== DT configuration examples ===
}}''', '''{{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}}'''
=== DT configuration examples ======= TIM configured in PWM mode and trigger source ====
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]])
* '''trigger source''' (synchronous with PWM) for other internal peripheral such as [[ADC internal peripheral|STM32 ADC]]
Note: The PWM output does not require any DMA channel. Disable them if they are configured by default in the .dtsi file.

 pwm1_pins_a: pwm1-0 {
 	pins {
 		pinmux = <STM32_PINMUX('E', 9, AF1)>;        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.txt}}, PWM LEDs device tree bindings</ref>). This is available since {{EcosystemRelease | revision=1.1.0 | range=and after}} 
{{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>;
 	};
 };
pwm1_sleep_pins_a: pwm1-sleep-0 {
 	pins {
 		pinmux = <STM32_PINMUX('E', 9, ANALOG)>;     {{{{highlight|/* configure 'PE9' as analog input in low-power mode */}}	};
 };

 &timers1 {
 	status = "{{highlight|okay}}";
 	/delete-property/dmas;                               {{highlight|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/dma-names;
 	pwm {
 		pinctrl-0 = <&pwm1_pins_a>;                  {{highlight|/* configure PWM 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";status = "{{highlight|okay}}";                             {{highlight|/* enable PWM on TIM1 */}}
 	};
 	timer@0 {
 		status = "{{highlight|okay}}";                             {{highlight|/* enable trigger on TIM1 */}}{{highlight|/* enable PWM on TIM1 */}}
 		status = "{{highlight|okay}}";
 	};
 };

PWM DT user example below is available since  {{EcosystemRelease | revision=1.1.0 | range=and after}}
{{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 input capture modemode and trigger source ====
The example below shows how to configure '''TIM1 channel 1''' in PWM input capture mode (e.g. period and duty cycle):
* Configure '''PWM inputto act as:
* '''PWM output on PE9''', e.g. TIM1_CH1 ([[Pinctrl_device_tree_configuration|See pinctrl device tree configuration]] and [[GPIO internal peripheral]])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'''
 pwm1_in_pins_a: pwm1-in* '''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 {
 	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, AF1ANALOG)>;      {{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}}
 		bias-disable;
 	};
 };

 pwm1_in_sleep_	};
 };
{{Info|The PWM output doesn't require any DMA channel. Disable them if they are configured by default in the .dtsi file.}}
 &timers1 {
 	status = "{{highlight|okay}}";
 	{{highlight|/* spare all DMA channels since they are not needed for PWM output */}}
 	/delete-property/dmas;
 	/delete-property/dma-names;
 	pwm {
 		{{highlight|/* configure PWM 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}}";
 	};
 	timer@0 {
 		{{highlight|/* enable trigger on TIM1 */}}
 		status = "{{highlight|okay}}";
 	};
 };

==== TIM configured in PWM input capture mode====
The example below 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]])
 {{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}}
 pwm1_in_pins_a: pwm1-in-sleep-0 {
 	pins {
 		pinmux = <STM32_PINMUX('E', 9, ANALOGAF1)>;   		bias-disable;
 	};
 };
{{highlight|/* configure 'PE9' as analog input in low-power mode */}}	};
 };

{{ReviewsComments|BPU W851: maybe good to mention here that the dma instance to put here is from the order in the declaration dma list (ch1 is first, ch2 is second, ...). It seems obvious when you know it but when you want to choose ch3 and no other dma is used you may have a doudt }}pwm1_in_sleep_pins_a: pwm1-in-sleep-0 {
 	pins {
 		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 {
 	status = "{{highlight|okay}}";'''dmas = <&dmamux1 11 0x400 0x5>;'''                      {{highlight|/* Enable DMA "ch1" for PWM input on TIM1_CH1 */}}
 	'''dmas = <&dmamux1 11 0x400 0x5>;'''
 	'''dma-names = "ch1";'''
 	pwm {pinctrl-0 = <&pwm1_in_pins_a>;               {{highlight|/* configure PWM input pins, e.g. TIM1_CH1 */}}
 		pinctrl-0 = <&pwm1_in_pins_a>;
 		pinctrl-1 = <&pwm1_in_sleep_pins_a>;
 		pinctrl-names = "default", "sleep";status = "{{highlight|okay}}";                             {{highlight|/* enable PWM on TIM1 */}}
 	};
 };
{{highlight|/* enable PWM on TIM1 */}}
 		status = "{{highlight|okay}}";
 	};
 };
{{Info|DMA channels 1 and/or 3 for each TIM can be picked from the '''"dmas"''' list in stm32mp157c.dtsi<ref name="stm32mp157c.dtsi"/> file}}==== TIM configured as quadrature encoder interface ====
The example below shows how to configure '''TIM1''' to interface with a quadrature encoder:
* '''Configure PE9 and PJ11 as encoder input pins''', e.g. TIM1_CH1, TIM1_CH2 ([[Pinctrl_device_tree_configuration|see pinctrl device tree configuration]] and [[GPIO internal peripheral]])

 tim1_in_pins_a: tim1-in-pins-0 {
 	pins {
 		pinmux = <STM32_PINMUX('E', 9, AF1)>, /* TIM1_CH1 */<STM32_PINMUX('J', 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('J', 11, ANALOG)>; /* TIM1_CH2 */
 	};
 };

 &timers1 {
 	status = "{{highlight|okay}}";
 	/delete-property/dmas;                               {{highlight|/* spare all DMA channels since they are not required for quadrature encoder interface */}}
 	/delete-property/dma-names;
 	timer@0 {
 		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-names = "default", "sleep";
 		status = "{{highlight|okay}}";                             {{highlight|/* enable Encoder interface mode on TIM1 */}}
 	};
 };

==How to configure the DT using STM32CubeMX==
The [[STM32CubeMX]] tool can be used to configure the STM32MPU device and get the corresponding [[Device_tree#STM32|platform configuration device tree]] files.<br />

The STM32CubeMX may not support all the properties described 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==
Please refer to the following links for additional information:
<references />
<noinclude>

{{ArticleBasedOnModel|[[Contributors:Peripheral_or_framework_device_tree_configuration_model]]}}
{{ArticleMainWriter|FabriceG}}
{{ArticleApprovedVersion| FabriceG| BenjaminG | No previous approved version | AnneJ - 20Sept'18 - 8783 | 20Sept'18 }}

[[Category:Device tree configuration]]
[[Category:IIO]]
[[Category:Timers]]

{{ReviewsComments|JCT 1840: alignment needed with the last version of the model [[Contributors:Peripheral_or_framework_device_tree_configuration_model]]<br>

[[Category:ToBeAlignedWithModel]]
}}</noinclude>
(7 intermediate revisions by 2 users not shown)
Line 1: Line 1:
<noinclude>
 
{{ArticleBasedOnModel|[[Peripheral or framework device tree configuration model]]}}
 
{{ArticleMainWriter|FabriceG}}
 
{{ArticleApprovedVersion| FabriceG| BenjaminG | No previous approved version | AnneJ - 20Sept'18 - 8783 | 20Sept'18 }}
 
 
[[Category:Device tree configuration]]
 
[[Category:IIO]]
 
[[Category:Timers]]
 
 
{{ReviewsComments|JCT 1840: alignment needed with the last version of the model [[Peripheral or framework device tree configuration model]]<br>
 
[[Category:ToBeAlignedWithModel]]
 
}}
 
</noinclude>
 
 
 
==  Article purpose ==
 
==  Article purpose ==
 
The purpose of this article is to explain how to configure the ''timer (TIM)''<ref name="TIM internal peripheral"> [[TIM internal peripheral]]</ref> ''' when the peripheral is assigned to Linux<sup>&reg;</sup> OS''':
 
The purpose of this article is to explain how to configure the ''timer (TIM)''<ref name="TIM internal peripheral"> [[TIM internal peripheral]]</ref> ''' when the peripheral is assigned to Linux<sup>&reg;</sup> OS''':
Line 47: Line 33:
 
They also describe hardware parameters such as registers address, clock and DMA.
 
They also describe hardware parameters such as registers address, clock and DMA.
 
  timers1: timer@address {
 
  timers1: timer@address {
  compatible = "st,stm32-timers";                      {{highlight|/* timer common resources */}}
+
  {{highlight|/* timer common resources */}}
  +
compatible = "st,stm32-timers";
 
  ...
 
  ...
 
  pwm {
 
  pwm {
  compatible = "st,stm32-pwm";                {{highlight|/* PWM*/}}
+
  {{highlight|/* PWM*/}}
  +
compatible = "st,stm32-pwm";
 
  };
 
  };
 
  timer@'''0''' {
 
  timer@'''0''' {
  compatible = "st,stm32h7-timer-trigger";    {{highlight|/* trigger and quadrature encoder */}}
+
  {{highlight|/* trigger and quadrature encoder */}}
  reg = <'''0'''>;                                   {{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}}
+
  compatible = "st,stm32h7-timer-trigger";
  +
{{highlight|/* trigger identifier (e.g. 0 for TIM1 triggers, 1 for TIM2... */}}
  +
reg = <'''0'''>;
 
  };
 
  };
 
  };
 
  };
Line 61: Line 51:
 
=== DT configuration (board level) ===
 
=== DT configuration (board level) ===
 
This part is used to configure and enable the TIM hardware used on the board:
 
This part is used to configure and enable the TIM hardware used on the board:
* Enabling '''DT root node''' for the TIM instances in use (e.g timers1...) by setting '''status = "okay";'''
+
* Enabling '''DT root node''' for the TIM instances in use (e.g timers1...) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}'''
* Enabling '''DT child node(s)''' for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting '''status = "okay";'''
+
* Enabling '''DT child node(s)''' for the feature(s) in use (PWM input/output, trigger and quadrature encoder) by setting '''{{highlight|<nowiki>status = "okay";</nowiki>}}'''
* Configuring pins in use via [[Pinctrl overview|pinctrl]] through '''pinctrl-0''', '''pinctrl-1''' and '''pinctrl-names'''.
+
* Configuring 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}}'''
  +
=== 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.txt}}, PWM LEDs device tree bindings</ref>). This is available since {{EcosystemRelease | revision=1.1.0 | range=and after}}
  +
 
  +
{{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}}";
  +
};
  +
};
   
=== DT configuration examples ===
+
PWM DT user example below is available since  {{EcosystemRelease | revision=1.1.0 | range=and after}}
  +
{{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 123:
 
* '''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]]
Note: The PWM output does not require any DMA channel. Disable them if they are configured by default in the .dtsi file.
+
{{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)>;       {{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}}
+
  pinmux = <STM32_PINMUX('E', 9, AF1)>;
 
  bias-pull-down;
 
  bias-pull-down;
 
  drive-push-pull;
 
  drive-push-pull;
Line 82: Line 133:
 
  };
 
  };
 
   
 
   
  +
{{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)>;     {{highlight|/* configure 'PE9' as analog input in low-power mode */}}
+
  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}}";
  /delete-property/dmas;                              {{highlight|/* spare all DMA channels since they are not needed for PWM output */}}
+
  {{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 {
  pinctrl-0 = <&pwm1_pins_a>;                  {{highlight|/* configure PWM on TIM1_CH1 */}}
+
  {{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";
  status = "{{highlight|okay}}";                            {{highlight|/* enable PWM on TIM1 */}}
+
  {{highlight|/* enable PWM on TIM1 */}}
  +
status = "{{highlight|okay}}";
 
  };
 
  };
 
  timer@0 {
 
  timer@0 {
  status = "{{highlight|okay}}";                            {{highlight|/* enable trigger on TIM1 */}}
+
  {{highlight|/* enable trigger on TIM1 */}}
  +
status = "{{highlight|okay}}";
 
  };
 
  };
 
  };
 
  };
Line 106: Line 162:
 
The example below shows how to configure '''TIM1 channel 1''' in PWM input capture mode (e.g. period and duty cycle):
 
The example below 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]])
A DMA channel is required and must be configured depending on the PWM input channel:
+
{{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}}
* 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'''
 
 
  pwm1_in_pins_a: pwm1-in-0 {
 
  pwm1_in_pins_a: pwm1-in-0 {
 
  pins {
 
  pins {
  pinmux = <STM32_PINMUX('E', 9, AF1)>;       {{highlight|/* select TIM1_CH1 alternate function 1 on 'PE9' */}}
+
  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)>;     {{highlight|/* configure 'PE9' as analog input in low-power mode */}}
+
  pinmux = <STM32_PINMUX('E', 9, ANALOG)>;
 
  };
 
  };
 
  };
 
  };
   
{{ReviewsComments|BPU W851: maybe good to mention here that the dma instance to put here is from the order in the declaration dma list (ch1 is first, ch2 is second, ...). It seems obvious when you know it but when you want to choose ch3 and no other dma is used you may have a doudt }}
+
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}}";
  '''dmas = <&dmamux1 11 0x400 0x5>;'''                      {{highlight|/* Enable DMA "ch1" for PWM input on TIM1_CH1 */}}
+
  {{highlight|/* Enable DMA "ch1" for PWM input on TIM1_CH1 */}}
  +
'''dmas = <&dmamux1 11 0x400 0x5>;'''
 
  '''dma-names = "ch1";'''
 
  '''dma-names = "ch1";'''
 
  pwm {
 
  pwm {
  pinctrl-0 = <&pwm1_in_pins_a>;              {{highlight|/* configure PWM input pins, e.g. TIM1_CH1 */}}
+
  {{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";
  status = "{{highlight|okay}}";                            {{highlight|/* enable PWM on TIM1 */}}
+
  {{highlight|/* enable PWM on TIM1 */}}
  +
status = "{{highlight|okay}}";
 
  };
 
  };
 
  };
 
  };
 
+
{{Info|DMA channels 1 and/or 3 for each TIM can be picked from the '''"dmas"''' list in stm32mp157c.dtsi<ref name="stm32mp157c.dtsi"/> file}}
 
==== 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:
Line 156: Line 217:
 
  &timers1 {
 
  &timers1 {
 
  status = "{{highlight|okay}}";
 
  status = "{{highlight|okay}}";
  /delete-property/dmas;                               {{highlight|/* spare all DMA channels since they are not required for quadrature encoder interface */}}
+
  /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;
 
  timer@0 {
 
  timer@0 {
  pinctrl-0 = <&tim1_in_pins_a>;               {{highlight|/* configure TIM1_CH1 and TIM1_CH2 as encoder input pins */}}
+
  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}}";                             {{highlight|/* enable Encoder interface mode on TIM1 */}}
+
  status = "{{highlight|okay}}";                     {{highlight|/* enable Encoder interface mode on TIM1 */}}
 
  };
 
  };
 
  };
 
  };
Line 174: Line 235:
   
 
<references />
 
<references />
  +
<noinclude>
  +
{{ArticleBasedOnModel|[[Contributors:Peripheral_or_framework_device_tree_configuration_model]]}}
  +
{{ArticleMainWriter|FabriceG}}
  +
{{ArticleApprovedVersion| FabriceG| BenjaminG | No previous approved version | AnneJ - 20Sept'18 - 8783 | 20Sept'18 }}
  +
  +
[[Category:Device tree configuration]]
  +
[[Category:IIO]]
  +
[[Category:Timers]]
  +
  +
{{ReviewsComments|JCT 1840: alignment needed with the last version of the model [[Contributors:Peripheral_or_framework_device_tree_configuration_model]]<br>
  +
[[Category:ToBeAlignedWithModel]]
  +
}}
  +
</noinclude>

Attachments

Discussions