The Linux counter framework provides a generic kernel subsystem for counting events produced by hardware devices, such as pulses, or revolutions of rotary elements (motors).
Counters are available on pads that multiplex a timer functionality. Timer channels can be configured as outputs (PWM) or as inputs (counter, quadrature decoder).
On the ConnectCore MP25, there are:
-
Up to three advanced-control timer signals (
TIM1, TIM8, TIM20) available from the STM32MP25 system-on-chip (multiplexed with other signals) that can be used as counters. -
Up to twelve general-purpose timer signals (
TIM2..TIM5, TIM10..TIM17) available from the STM32MP25 system-on-chip (multiplexed with other signals) that can be used as counters. -
One low-power timer (
LPTIM1..LPTIM4) available from the STM32MP25 system-on-chip (multiplexed with other signals) that can be used as counter.
On the ConnectCore MP25 Development Kit:
-
Most timers (
TIM) and low-power timers (LPTIM) are multiplexed with other functionalities on the ConnectCore MP25 and not easily accessible on connectors.
| Because the timers are multiplexed with crucial interfaces such as Ethernet and unavailable on pin headers, testing their functionality on the ConnectCore MP25 Development Kit is not straightforward. See the ConnectCore MP25 Hardware Reference Manuals for SOM and DVK for information about pads and their multiplexed functionality. |
Types of timers
For counter and quadrature decoder functionality, there are two types of timer interfaces on the STM32MP25:
-
Timers (
TIMx): these include advanced-control timers, general-purpose timers, and basic timers. -
Low-power timers (
LPTIMx)
Supported functionality
The drivers support the following functionalities:
-
Counter: increments a counter according to detected edges (rising/falling/both) on a signal. Requires a single pad with the signal. Only supported on
LPTIMx_INypads ofLPTIMtimers. -
Quadrature x2 A: counts both edges on signal A period. Signal B gives the direction (forward/reverse). Requires two pads (signals A and B). Only supported on
TIMx_CH1, TIMx_CH2pads ofTIMtimers. -
Quadrature x2 B: counts both edges on signal B period. Signal A gives the direction (forward/reverse). Only supported on
TIMx_CH1, TIMx_CH2pads ofTIMtimers. -
Quadrature x4: counts both edges on both signals A and B. Requires two pads (signals A and B). Supported on
TIMx_CH1, TIMx_CH2pads ofTIMtimers andLPTIMx_IN1, LPTIMx_IN2ofLPTIMtimers.
The following table describes which functionality is available depending on the type of timer:
| Function | Timers (TIMx) |
Low power timers (LPTIMx) |
|---|---|---|
Counter |
Counts internal clock pulses only |
Counts external signal pulses |
Quadrature x2 A |
||
Quadrature x2 B |
||
Quadrature x4 |
Basic timers (TIM6, TIM7) do not support counter (input capture) functionality.
|
Kernel configuration
You can manage the STM32MP25 counter driver support through the following kernel configuration options:
-
Counter support (
CONFIG_COUNTER) -
STM32 LP Timer encoder counter driver (
CONFIG_STM32_LPTIMER_CNT) -
STM32 Timer encoder counter driver (
CONFIG_STM32_TIMER_CNT)
Kernel driver
The counter drivers are located at:
| File | Description |
|---|---|
STM32MP25 LP Timer Counter driver |
|
STM32MP25 Timer Counter driver |
Device tree customization
The device tree must contain entries for:
-
The timer interface to use
-
The channel to enable
-
The IOMUX for the pads with timer channel functionality
Example 1: LPTIM as external signal edge counter
The following example configures LPTIM2 to count on edges detected on an external signal applied to LPTIM2_IN1.
On the pinctrl, you must select a pad that multiplexes the LPTIM2_IN1 functionality in one of the alternate functions.
&lptimer2 {
status = "okay";
counter {
pinctrl-0 = <&lptim2_in_pins>;
pinctrl-1 = <&lptim2_sleep_in_pins>;
pinctrl-names = "default", "sleep";
status = "okay";
};
}
&pinctrl {
lptim2_in_pins: lptim2-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 2, AF1)>; /* LPTIM2_IN1 */
bias-disabled;
};
};
lptim2_sleep_in_pins: lptim2-sleep-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 2, ANALOG)>;
};
};
};
Example 2: LPTIM as quadrature x4 decoder
The following example configures LPTIM2 to count on edges detected on external signals applied to LPTIM2_IN1 and LPTIM2_IN2 from a quadrature encoder.
On the pinctrl, you must select pads that multiplex the LPTIM2_IN1 and LPTIM2_IN2 functionality in one of their alternate functions.
&lptimer2 {
status = "okay";
counter {
pinctrl-0 = <&lptim2_in_pins>;
pinctrl-1 = <&lptim2_sleep_in_pins>;
pinctrl-names = "default", "sleep";
status = "okay";
};
}
&pinctrl {
lptim2_in_pins: lptim2-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 2, AF1)>, /* LPTIM2_IN1 */
<STM32_PINMUX('H', 6, AF1)>; /* LPTIM2_IN2 */
bias-disabled;
};
};
lptim2_sleep_in_pins: lptim2-sleep-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('A', 2, ANALOG)>,
<STM32_PINMUX('H', 6, ANALOG)>;
};
};
};
The quadrature decoder functionality is only available on IN1 and IN2 inputs of a given LPTIMx timer.
|
Example 3: TIM as quadrature x2 A configuration
The following example configures TIM1 to count on edges detected on external signal A applied to TIM1_CH1 and signal B (direction) applied to TIM1_CH2.
On the pinctrl, you must select pads that multiplex the TIM1_CH1 and TIM1_CH2 functionality in one of their alternate functions.
&timers1 {
status = "okay";
counter {
/* spare DMA channels, not used for counter */
/delete-property/dmas;
/delete-property/dma-names;
pinctrl-0 = <&tim1_counter_pins>;
pinctrl-1 = <&tim1_counter_sleep_pins>;
pinctrl-names = "default", "sleep";
status = "okay";
};
};
&pinctrl {
tim1_in_pins: tim1-ch-pins-0 {
pins {
pinmux = <STM32_PINMUX('D', 11, AF8)>, /* TIM1_CH1 */
<STM32_PINMUX('D', 10, AF8)>; /* TIM1_CH2 */
bias-disabled;
};
};
tim1_sleep_in_pins: tim1-sleep-in-pins-0 {
pins {
pinmux = <STM32_PINMUX('D', 11, ANALOG)>,
<STM32_PINMUX('D', 10, ANALOG)>;
};
};
};
The quadrature decoder functionality is only available on CH1 and CH2 channels of a given TIMx timer.
|
User space usage
The counter subsystem offers a generic user interface through:
-
the sysfs interface
-
character device interfaces (supported only by
TIMdriver
Identify system counters
List the available counters on the system:
# ls /sys/bus/counter/devices/
counter0 counter1
This example shows two counters enabled on the device tree. To learn which timer a certain counter relates to, run:
# cd /sys/bus/counter/devices/
# cat counter0/name
40009000.timer:counter
This reports the name and address of the device tree node of the timer. Check the STM32MP25 device tree include file to identify the exact timer this corresponds to:
lptimer1: timer@40090000 {
This example corresponds to LPTIM1.
Configure the counter
Navigate to the specific counter folder and check the available functions.
For LPTIM counters, these are:
# cd /sys/bus/counter/devices/counter0/count0
# cat function_available
increase
quadrature x4
For TIM counters these are:
# cd /sys/bus/counter/devices/counter0/count0
# cat function_available
increase
quadrature x2 a
quadrature x2 b
quadrature x4
To configure a function, write one of the available function strings to the function node.
For example, to count on edges from a unipolar external signal use increase.
# echo increase > function
This only works on LPTIM timers.
See Supported functionality.
|
To configure a quadrature decoder function, write one of the available quadrature functions:
# echo "quadrature x4" > function
To read the ceiling (the number at which the counter wraps):
# cat ceiling
65535
This is set by default to the highest possible number, but you can configure a smaller number by writing a value to it:
# echo 10000 > ceiling
TIMx counters support a prescaler, used to divide the counter frequency by any factor between 1 (default) and 65536.
# cat prescaler
1
# echo 100 > prescaler
Although LPTIMx counters also have an internal prescaler, the current driver doesn’t support it.
|
Enable counter and read the count
To enable the counter:
# echo 1 > enable
To read the count:
# cat count
1977
To reset the count:
# echo 0 > count
When configured as quadrature decoder, TIMx timers have a direction node that you can read:
# cat direction
forward
In quadrature function mode, direction can also be determined by successive reads to count, given that increments on the count mean "forward", while decrements mean "reverse".
|
Disable the counter
To disable the counter:
# echo 0 > enable
See also
Refer to Generic Counter Interface article for information on the Linux counter framework.
To use the timers' PWM functionality refer to Pulse-width Modulation (PWM).