Skip to content

drivers: stepper: introduce stepper_drv api to facilitate implementing motion controllers as device drivers #91979

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2312,7 +2312,7 @@ Documentation Infrastructure:
- include/zephyr/drivers/stepper/
- include/zephyr/drivers/stepper.h
- dts/bindings/stepper/
- doc/hardware/peripherals/stepper.rst
- doc/hardware/peripherals/stepper/
- samples/drivers/stepper/
- tests/drivers/build_all/stepper/
- tests/drivers/stepper/
Expand Down
2 changes: 1 addition & 1 deletion doc/hardware/peripherals/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ Peripherals
sensor/index.rst
sent.rst
spi.rst
stepper.rst
stepper/index.rst
smbus.rst
uart.rst
usbc_vbus.rst
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,33 @@
Steppers
########

The stepper driver API provides a set of functions for controlling and configuring stepper drivers.
The stepper driver subsystem consists of two device driver APIs:

Configure Stepper Driver
========================
.. figure:: stepper_driver_subsystem_class_diagram.webp
:align: center
:alt: Stepper driver subsystem class diagram

Stepper Driver API
******************

The stepper driver API provides a common interface for stepper drivers.

- Configure **micro-stepping resolution** using :c:func:`stepper_drv_set_micro_step_res`
and :c:func:`stepper_drv_get_micro_step_res`.
- **Enable** the stepper driver using :c:func:`stepper_drv_enable`.
- **Disable** the stepper driver using :c:func:`stepper_drv_disable`.
- Set the **direction** of the stepper using :c:func:`stepper_drv_set_direction`.
- **Step** a single step using :c:func:`stepper_drv_step`.
- Register an **event callback** using :c:func:`stepper_drv_set_event_cb`.

Stepper API
***********

The stepper API provides a common interface for stepper controllers.

- Configure **micro-stepping resolution** using :c:func:`stepper_set_micro_step_res`
and :c:func:`stepper_get_micro_step_res`.
- Configure **reference position** in microsteps using :c:func:`stepper_set_reference_position`
and :c:func:`stepper_get_actual_position`.
- Set **step interval** in nanoseconds between steps using :c:func:`stepper_set_microstep_interval`
- **Enable** the stepper driver using :c:func:`stepper_enable`.
- **Disable** the stepper driver using :c:func:`stepper_disable`.

Control Stepper
===============

- **Move by** +/- micro-steps also known as **relative movement** using :c:func:`stepper_move_by`.
- **Move to** a specific position also known as **absolute movement** using :c:func:`stepper_move_to`.
- Run continuously with a **constant step interval** in a specific direction until
Expand All @@ -27,19 +38,27 @@ Control Stepper
- Check if the stepper is **moving** using :c:func:`stepper_is_moving`.
- Register an **event callback** using :c:func:`stepper_set_event_callback`.

.. _stepper-device-tree:

Device Tree
===========
***********

In the context of stepper controllers device tree provides the initial hardware
configuration for stepper drivers on a per device level. Each device must specify
a device tree binding in Zephyr, and ideally, a set of hardware configuration options
for things such as current settings, ramp parameters and furthermore. These can then
be used in a boards devicetree to configure a stepper driver to its initial state.

See examples in:
Driver Composition Scenarios
============================

Below are two typical scenarios:

- :dtcompatible:`zephyr,h-bridge-stepper`
- :dtcompatible:`adi,tmc50xx`
.. toctree::
:maxdepth: 1

integrated_controller_driver.rst
individual_controller_driver.rst

Discord
=======
Expand All @@ -48,9 +67,10 @@ Zephyr has a `stepper discord`_ channel for stepper related discussions, which
is open to all.

.. _stepper-api-reference:
.. _stepper-drv-api-reference:

Stepper API Test Suite
======================
**********************

The stepper API test suite provides a set of tests that can be used to verify the functionality of
stepper drivers.
Expand Down Expand Up @@ -93,6 +113,10 @@ API Reference

A common set of functions which should be implemented by all stepper drivers.

.. doxygengroup:: stepper_drv_interface

A common set of functions which should be implemented by all stepper controllers.

.. doxygengroup:: stepper_interface

Stepper controller specific APIs
Expand Down
55 changes: 55 additions & 0 deletions doc/hardware/peripherals/stepper/individual_controller_driver.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.. _stepper-individual-controller-driver:

Individual Stepper Motion Controller and Driver
###############################################

A motion control driver implements ``stepper`` API, for instance, :dtcompatible:`zephyr,stepper-motion-control`
and a hardware driver implements ``stepper_drv`` API, for instance, :dtcompatible:`ti,drv84xx` or
:dtcompatible:`zephyr,h-bridge-stepper`.

Following is an example of a device tree configuration for a stepper driver with a dedicated stepper motion
controller:

.. code-block:: dts

/ {
aliases {
x_axis_stepper_motion_controller = &stepper_motion_control;
x_axis_stepper_driver = &drv8424;
};
};

/* DEVICE_API: stepper_drv api */
drv8424: drv8424 {
status = "okay";
compatible = "ti,drv84xx";

dir-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
step-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
sleep-gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
en-gpios = <&gpio4 1 GPIO_ACTIVE_LOW>;
m0-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
m1-gpios = <&gpio6 1 GPIO_ACTIVE_LOW>;
};

/* DEVICE_API: stepper api */
stepper_motion_control: stepper_motion_control {
compatible = "zephyr,stepper-motion-control";
status = "okay";
counter = <&counter0>;
stepper = <&drv8424>;
};

All the stepper api functions need a stepper motor index, since a stepper motion controller can control
multiple motors. However, this can be configured via application specific Kconfig to use a specific index,
for instance, :kconfig:option-regex:`CONFIG_STEPPER_AXIS_*`.

Following the aforementioned configurations, the stepper driver subsystem can be used in the application code
as follows:

.. code-block:: c

/* Configure the index of motor and respective axis via Kconfig */
stepper_move_to(x_axis_stepper_motion_controller, CONFIG_STEPPER_AXIS_X_*, 200);
stepper_stop(x_axis_stepper_motion_controller, CONFIG_STEPPER_AXIS_X_*);
stepper_drv_disable(x_axis_stepper_driver);
86 changes: 86 additions & 0 deletions doc/hardware/peripherals/stepper/integrated_controller_driver.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
.. _stepper-integrated-controller-driver:

Integrated Stepper Motion Control and Driver
############################################

Implements both ``stepper`` and ``stepper_drv`` APIs in a single driver. For instance, :dtcompatible:`adi,tmc50xx`.

Following is an example of a device tree configuration for a stepper driver with integrated motion control:

.. code-block:: dts

/ {
aliases {
x_y_stepper_motion_controller = &tmc50xx;
x_axis_stepper_driver = &motor_x;
y_axis_stepper_driver = &motor_y;
};
};

&spi0 {
/* SPI bus options here, not shown */

/* Dual controller/driver for up to two 2-phase bipolar stepper motors */
/* DEVICE_API: stepper api */
tmc50xx: tmc50xx@0 {
compatible = "adi,tmc50xx";
reg = <0>;
spi-max-frequency = <DT_FREQ_M(8)>; /* Maximum SPI bus frequency */

#address-cells = <1>;
#size-cells = <0>;

poscmp-enable; test-mode; lock-gconf; /* ADI TMC Global configuration flags */
clock-frequency = <DT_FREQ_M(16)>; /* Internal/External Clock frequency */

/* DEVICE_API: stepper_drv api */
motor_x: motor@0 {
status = "okay";
reg = <0>;

/* common stepper controller settings */
invert-direction;
micro-step-res = <256>;

/* ADI TMC stallguard settings specific to TMC50XX */
activate-stallguard2;
.....................

/* ADI TMC ramp generator as well as current settings */
vstart = <10>;
..............
};

/* DEVICE_API: stepper_drv api */
motor_y: motor@1 {
status = "okay";
reg = <1>;

/* common stepper controller settings */
micro-step-res = <256>;

/* ADI TMC stallguard settings specific to TMC50XX */
activate-stallguard2;
.....................

/* ADI TMC ramp generator as well as current settings */
vstart = <10>;
..............
};
};
};

All the stepper api functions need a stepper motor index, since a stepper motion controller can control
multiple motors. However, this can be configured via application specific Kconfig to use a specific index,
for instance, :kconfig:option-regex:`CONFIG_STEPPER_AXIS_*`.

Following the aforementioned configurations, the stepper driver subsystem can be used in the application code
as follows:

.. code-block:: c

/* Configure the index of motor and respective axis via Kconfig */
stepper_move_to(x_y_stepper_motion_controller, CONFIG_STEPPER_AXIS_X_*, 200);
stepper_stop(x_y_stepper_motion_controller, CONFIG_STEPPER_AXIS_Y_*);
stepper_drv_disable(x_axis_stepper_driver);
stepper_drv_disable(y_axis_stepper_driver);
Binary file not shown.
8 changes: 7 additions & 1 deletion drivers/stepper/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h)
add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc)
add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro)
add_subdirectory_ifdef(CONFIG_STEPPER_TI ti)
# zephyr-keep-sorted-stop

# zephyr-keep-sorted-start
add_subdirectory_ifdef(CONFIG_STEPPER_TIMING_SOURCES stepper_timing_sources)
add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir)
# zephyr-keep-sorted-stop

zephyr_library()
zephyr_library_property(ALLOW_EMPTY TRUE)

zephyr_library_sources_ifdef(CONFIG_FAKE_STEPPER fake_stepper_controller.c)
zephyr_library_sources_ifdef(CONFIG_FAKE_STEPPER fake_stepper_drv.c)
zephyr_library_sources_ifdef(CONFIG_FAKE_STEPPER_CONTROLLER fake_stepper_controller.c)
zephyr_library_sources_ifdef(CONFIG_H_BRIDGE_STEPPER h_bridge_stepper.c)
zephyr_library_sources_ifdef(CONFIG_STEPPER_SHELL stepper_shell.c)
zephyr_library_sources_ifdef(CONFIG_ZEPHYR_STEPPER_MOTION_CONTROL zephyr_stepper_motion_controller.c)
5 changes: 5 additions & 0 deletions drivers/stepper/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ config STEPPER_SHELL
comment "Stepper Driver Common"

rsource "step_dir/Kconfig"
rsource "stepper_timing_sources/Kconfig"

comment "Stepper Drivers"

# zephyr-keep-sorted-start
rsource "Kconfig.fake"
rsource "Kconfig.h_bridge"
rsource "Kconfig.zephyr_stepper_motion_controller"
# zephyr-keep-sorted-stop

# zephyr-keep-sorted-start
rsource "adi_tmc/Kconfig"
rsource "allegro/Kconfig"
rsource "ti/Kconfig"
Expand Down
7 changes: 7 additions & 0 deletions drivers/stepper/Kconfig.fake
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,10 @@ config FAKE_STEPPER
depends on DT_HAS_ZEPHYR_FAKE_STEPPER_ENABLED
help
Enable support for the FFF-based fake stepper driver.

config FAKE_STEPPER_CONTROLLER
bool "Fake stepper controller driver"
default y
depends on DT_HAS_ZEPHYR_FAKE_STEPPER_CONTROLLER_ENABLED
help
Enable support for the FFF-based fake stepper controller driver.
18 changes: 0 additions & 18 deletions drivers/stepper/Kconfig.stepper_event_template

This file was deleted.

24 changes: 24 additions & 0 deletions drivers/stepper/Kconfig.zephyr_stepper_motion_controller
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
# SPDX-License-Identifier: Apache-2.0

config ZEPHYR_STEPPER_MOTION_CONTROL
bool "Zephyr CPU based Stepper motion control"
depends on DT_HAS_ZEPHYR_STEPPER_MOTION_CONTROL_ENABLED
select STEPPER_TIMING_SOURCES
default y

config ZEPHYR_STEPPER_MOTION_CONTROL_GENERATE_ISR_SAFE_EVENTS
bool "Guarantee non ISR callbacks upon stepper events"
help
Enable the dispatch of stepper generated events via
a message queue to guarantee that the event handler
code is not run inside of an ISR. Can be disabled, but
then registered stepper event callback must be ISR safe.

config ZEPHYR_STEPPER_MOTION_CONTROL_EVENT_QUEUE_LEN
int "Maximum number of pending stepper events"
default 4
depends on ZEPHYR_STEPPER_MOTION_CONTROL_GENERATE_ISR_SAFE_EVENTS
help
The maximum number of stepper events that can be pending before new events
are dropped.
1 change: 0 additions & 1 deletion drivers/stepper/adi_tmc/Kconfig.tmc_rampgen_template
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

config STEPPER_ADI_$(module)_RAMPSTAT_POLL_INTERVAL_IN_MSEC
int "$(module-str) poll ramp status interval in ms"
depends on !$(dt_compat_any_has_prop,$(DT_COMPAT_ADI_$(module)),diag0-gpios)
default 100
help
When DIAG0 pin is not available, the driver automatically falls back to
Expand Down
Loading