1. Article purpose[edit | edit source]
This article introduces the TIM Linux® and U-Boot drivers for the TIM internal peripheral[1]:
- Which TIM features are supported by the drivers
- How to configure, use and debug the drivers
- What are the structures of the drivers, and where the source code can be found.
2. Short description[edit | edit source]
The TIM internal peripheral is supported in Linux® and U-Boot software components through dedicated drivers. Refer to the TIM internal peripheral to understand how a particular TIM instance is actually supported, depending on STM32 MPU device and execution context (here U-Boot or Linux context).
2.1. U-Boot driver[edit | edit source]
Since ecosystem release ≥ v6.1.0 , the TIM internal peripheral can be used in U-Boot for PWM.
The U-Boot driver is based on the pwm-uclass. This uclass offers an API[2] which can be used to implement PWM client applications.
Similarly to the Linux® driver, the TIM U-Boot driver is based on a parent/child driver model:
- TIM multi-function parent driver:
- - handles registers and clock resources,
- - detects the TIM counter resolution, e.g. 16 or 32 bits,
- - is based on the NOP uclass.
- TIM PWM child driver:
- - detects the number of TIM channels,
- - handles PWM output channels,
- - is based on the PWM uclass.
2.2. Linux kernel driver[edit | edit source]
The TIM[1] Linux driver (kernel space) is based on the PWM, IIO and counter frameworks. It provides several functionalities:
MFD driver:
- handles registers, clock and DMA[3] resources
- detects the TIM counter resolution, e.g. 16 or 32 bits.
PWM driver:
- detects the number of TIM channels.
- handles PWM output channels.
- handles PWM capture channels (input) Deprecated. Note that the PWM capture relies on DMA, which is handled by the MFD core.
IIO driver:
- handles hardware trigger sources (synchronously with PWM) for other internal peripherals such as ADC[4], DAC[5], DFSDM[6].
Counter driver:
- handles the quadrature encoder interface[7].
- counts on internal clock.
- capture counter value with timestamps, upon external input signal edge.
2.3. Handover between U-Boot and Linux kernel PWM drivers[edit | edit source]
A typical use case for a PWM channel is to control a display panel backlight. In such a case, it can be useful to enforce a smooth transition at boot time in between U-Boot and the Linux kernel:
- U-Boot first configures the desired panel brightness, for the splash-screen,
- Then during Linux boot, the TIM PWM driver maintains the same configuration: It checks the enabled PWM channels at probe time to preserve their configuration, such as period and duty cycle. It may tuned later, as described in "How to modify the panel backlight".
3. Configuration[edit | edit source]
3.1. U-Boot configuration[edit | edit source]
The U-Boot PWM driver can be activated in the U-Boot configuration using the U-Boot
menuconfig tool.
Enable the following configurations:
- CONFIG_MFD_STM32_TIMERS
- CONFIG_DM_PWM
- CONFIG_PWM_STM32
-> ARM architecture [*] STM32 multifonction timer support -> Device Drivers [*] Enable support for pulse-width modulation devices (PWM) [*] Enable support for STM32 PWM
In addition, in order to control a display panel backlight, enable the following configurations:
- CONFIG_BACKLIGHT_PWM
-> Device Drivers
-> Graphics support
-> Enable driver model support for LCD/video
[*] Generic PWM based Backlight Driver
U-boot also implements pwm[8] command line tool. To activate it, enable the following configuration:
- CONFIG_CMD_PWM
-> Command line interface -> Device access commands [*] pwm
3.2. Kernel configuration[edit | edit source]
Activate the TIM[1] Linux driver in the kernel configuration using the Linux Menuconfig tool: Menuconfig or how to configure kernel.
Enable the following configurations (and their dependencies):
- CONFIG_MFD_STM32_TIMERS
- CONFIG_PWM_STM32
- CONFIG_IIO_STM32_TIMER_TRIGGER
- CONFIG_STM32_TIMER_CNT
Device Drivers ---> -> Multifunction device drivers ---> <*> Support for STM32 Timers -> Pulse-width modulation (PWM) support ---> <*> STMicroelectronics STM32 PWM -> Industrial I/O support ---> -> Triggers - standalone ---> <*> STM32 timer trigger -> Counter support ---> <*> STM32 Timer encoder counter driver
3.3. Device tree[edit | edit source]
Refer to the TIM device tree configuration article when configuring the TIM Linux kernel driver.
4. How to use[edit | edit source]
4.1. U-Boot driver[edit | edit source]
The pwm[8] command line tool can be used to control a TIM PWM channel:
pwm pwm - control pwm channels Usage: pwm invert <pwm_dev_num> <channel> <polarity> - invert polarity pwm config <pwm_dev_num> <channel> <period_ns> <duty_ns> - config PWM pwm enable <pwm_dev_num> <channel> - enable PWM output pwm disable <pwm_dev_num> <channel> - disable PWM output Note: All input values are in decimal
For example on STM32MP135F-DK Discovery kit , the TIM1 channel 3 can be used in PWM mode to control the panel backlight brightness:
pwm config 0 2 1000000 100000 # Sets period to 1 ms, period to 0.1 ms (10%) pwm config 0 2 1000000 500000 # Sets period to 1 ms, period to 0.5 ms (50%) pwm config 0 2 1000000 1000000 # Sets period to 1 ms, period to 1 ms (100%)
4.2. Linux kernel driver[edit | edit source]
How to use PWM with sysfs interface
How to set up a TIM or LPTIM trigger using the sysfs interface
How to use the quadrature encoder with the sysfs interface
How to capture a signal with the counter subsystem
How to modify the panel backlight
5. How to trace and debug[edit | edit source]
5.1. In U-Boot[edit | edit source]
Refer to U-Boot - How to debug for details about debug means in U-Boot.
In order to check the PWM driver in U-Boot is correctly probed, the dm tree command can be used:
# Example on STM32MP135F-DK Discovery kitdm tree Class Index Probed Driver Name ----------------------------------------------------------- ... nop 0 [ + ] stm32_timers | |-- timer@44000000 pwm 0 [ + ] stm32_pwm | | `-- pwm ... backlight 0 [ + ] pwm_backlight |-- panel-backlight
When the driver has been correctly probed, e.g. the TIM clock has been enabled, the registers may be dumped by using:
md 0x44000000 44000000: 00000081 00000000 00000000 00000000 ................ 44000010: 0003001f 00000000 00000000 00000068 ............h... 44000020: 00000f00 00006164 00000003 0000cc00 ....da.......... 44000030: 00000000 00000000 00000000 0000cc01 ................ ...
On a running PWM, the TIM CNT register (at offset 0x24) is continuously counting. It can be seen by using:
md 0x44000024 1 44000024: 00005fa0 ._.. md 0x44000024 1 44000024: 0000b21b ....
5.2. In Linux kernel[edit | edit source]
The TIM[1] Linux driver can access the timer registers through REGMAP.
It comes with debugfs[9] entries, which allow dumping registers:
cd /sys/kernel/debug/regmap ls 40004000.timer 44000000.timer cd 44000000.timer cat registers 000: 00000081 004: 00000000 008: 00000000 00c: 00000000 ...
It also comes with tracepoints[10]:
cd /sys/kernel/debug/tracing cat available_events | grep regmap ... regmap:regmap_reg_read regmap:regmap_reg_write
6. Source code location[edit | edit source]
6.1. U-Boot[edit | edit source]
The TIM U-Boot driver source code is composed of:
- timers.c to handle common resources: registers, clock,
- pwm-stm32.c to handle PWM channel(s),
- timers.h header file.
6.2. Linux kernel[edit | edit source]
The TIM Linux driver source code is composed of:
- MFD driver: stm32-timers.c to handle common resources: registers, clock, dmas.
- PWM driver: pwm-stm32.c to handle PWM channel(s).
- IIO driver: stm32-timer-trigger.c to handle trigger source for other internal peripherals.
- Counter driver: stm32-timer-cnt.c to handle the quadrature encoder interface.
7. References[edit | edit source]
- ↑ 1.0 1.1 1.2 1.3 TIM internal peripheral
- ↑ U-Boot PWM API
- ↑ DMA_internal_peripheral
- ↑ ADC internal peripheral
- ↑ DAC internal peripheral
- ↑ DFSDM internal peripheral
- ↑ Incremental encoder Incremental encoder overview
- ↑ 8.0 8.1 U-Boot pwm command
- ↑ Debugfs
- ↑ Ftrace