“TIM device tree configuration”的版本间的差异

来自百问网嵌入式Linux wiki
第12行: 第12行:
  
 
== DT bindings documentation ==
 
== DT bindings documentation ==
The ''TIM internal peripheral''<ref name="TIM internal peripheral"/> is a multifunction device (MFD).
+
“ TIM内部外围设备”<ref name="TIM internal peripheral"/> 是多功能设备(MFD)。
  
Each function is represented by a separate DT binding document:
+
每个功能由单独的DT绑定文档表示:
* ''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 MFD设备树绑定''<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> 文档涉及核心资源(例如寄存器,时钟,DMA)
  
* ''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 PWM设备树绑定''<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> 文档涉及PWM资源(例如PWM输入/输出引脚)
 
+
* ''STM32 TIM IIO触发器/编码器设备树绑定''<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>文档涉及其他内部外设触发和正交编码器资源
* ''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 ==
 
== DT configuration ==

2020年11月10日 (二) 10:07的版本

Article purpose

本文的目的是解释'在将外围设备分配给 Linux® OS,如何配置“Timer(Tim)”[1] ':

  • 配置定时器peripheral以启用PWM,触发或正交编码器。
  • 配置board,例如 TIM引脚。

使用设备树机制[2]执行配置。

TIM Linux driver 使用它在PWMIIO 框架中注册相关信息。

如果外围设备已分配给另一个执行上下文,请参阅 How to assign an internal peripheral to a runtime context 文章,以获取有关外围设备分配和配置的准则。

DT bindings documentation

“ TIM内部外围设备”[1] 是多功能设备(MFD)。

每个功能由单独的DT绑定文档表示:

  • STM32 TIM MFD设备树绑定[3] 文档涉及核心资源(例如寄存器,时钟,DMA)
  • STM32 TIM PWM设备树绑定[4] 文档涉及PWM资源(例如PWM输入/输出引脚)
  • STM32 TIM IIO触发器/编码器设备树绑定[5]文档涉及其他内部外设触发和正交编码器资源

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 for more details.

DT configuration (STM32 level)

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 {
	/* timer common resources */
	compatible = "st,stm32-timers";
	...
	pwm {
		/* PWM*/
		compatible = "st,stm32-pwm";
	};
	timer@0 {
		/* trigger and quadrature encoder */
		compatible = "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.

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

DT configuration examples

TIM configured in PWM mode

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.
/* PWM DT provider on TIM1: "pwm1" */
&timers1 {
	status = "okay";
	/* 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{{#set:Ecosystem release=revision of a previous flow 1.1.0}}

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)
/ {
	...
	/* PWM DT user on TIM1_CH1: "pwm1", example with "pwm-leds"[7] */
	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>;
		};
	};
};

TIM configured in PWM mode and trigger source

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";
	};
};

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):

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

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";
	/* Enable DMA "ch1" for PWM input on TIM1_CH1 */
	dmas = <&dmamux1 11 0x400 0x5>;
	dma-names = "ch1";
	pwm {
		/* 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";
		/* 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

TIM configured as quadrature encoder interface

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

How to configure the DT using STM32CubeMX

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.