Skip to content

Commit cd2e18e

Browse files
drivers: stepper: Stepper driver architectural refactoring
Introduced modular architecture to the stepper driver to allow usage of different software and hardware components during stepper motion. Signed-off-by: Andre Stefanov <mail@andrestefanov.de>
1 parent 6636d65 commit cd2e18e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+2118
-1051
lines changed

drivers/stepper/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# SPDX-FileCopyrightText: Copyright (c) 2023 Carl Zeiss Meditec AG
2+
# SPDX-FileCopyrightText: Copyright (c) 2025 Andre Stefanov <mail@andrestefanov.de>
23
# SPDX-License-Identifier: Apache-2.0
34

45
zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h)
@@ -7,12 +8,17 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h)
78
add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc)
89
add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro)
910
add_subdirectory_ifdef(CONFIG_STEPPER_TI ti)
10-
add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir)
11+
# zephyr-keep-sorted-stop
12+
13+
# zephyr-keep-sorted-start
14+
add_subdirectory(motion_controller)
15+
add_subdirectory(interface)
1116
# zephyr-keep-sorted-stop
1217

1318
zephyr_library()
1419
zephyr_library_property(ALLOW_EMPTY TRUE)
1520

21+
zephyr_library_sources(stepper_common.c)
1622
zephyr_library_sources_ifdef(CONFIG_FAKE_STEPPER fake_stepper_controller.c)
1723
zephyr_library_sources_ifdef(CONFIG_GPIO_STEPPER gpio_stepper_controller.c)
1824
zephyr_library_sources_ifdef(CONFIG_STEPPER_SHELL stepper_shell.c)

drivers/stepper/Kconfig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ config STEPPER_SHELL
2626

2727
comment "Stepper Driver Common"
2828

29-
rsource "step_dir/Kconfig"
29+
rsource "motion_controller/Kconfig"
30+
rsource "interface/Kconfig"
3031

3132
comment "Stepper Drivers"
3233

3334
# zephyr-keep-sorted-start
3435
rsource "Kconfig.fake"
35-
rsource "Kconfig.gpio"
3636
rsource "adi_tmc/Kconfig"
3737
rsource "allegro/Kconfig"
3838
rsource "ti/Kconfig"

drivers/stepper/adi_tmc/Kconfig.tmc22xx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
config STEPPER_ADI_TMC2209
55
bool "Activate trinamic tmc2209 stepper driver"
66
depends on DT_HAS_ADI_TMC2209_ENABLED
7-
select STEP_DIR_STEPPER
7+
select STEPPER_INTERFACE_STEP_DIR
88
default y
99
help
1010
Stepper driver for TMC2209.

drivers/stepper/adi_tmc/tmc22xx.c

Lines changed: 57 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
/*
22
* SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
3+
* SPDX-FileCopyrightText: Copyright (c) 2025 Andre Stefanov <mail@andrestefanov.de>
34
* SPDX-License-Identifier: Apache-2.0
45
*/
56

6-
#include "../step_dir/step_dir_stepper_common.h"
7+
#include "../motion_controller/stepper_motion_controller.h"
8+
#include "../interface/stepper_interface_step_dir.h"
9+
#include "../stepper_common.h"
10+
11+
#include <zephyr/drivers/gpio.h>
712

813
#include <zephyr/logging/log.h>
914
LOG_MODULE_REGISTER(tmc22xx, CONFIG_STEPPER_LOG_LEVEL);
@@ -12,33 +17,23 @@ LOG_MODULE_REGISTER(tmc22xx, CONFIG_STEPPER_LOG_LEVEL);
1217
#define MSX_PIN_STATE_COUNT 4
1318

1419
struct tmc22xx_config {
15-
struct step_dir_stepper_common_config common;
16-
const struct gpio_dt_spec enable_pin;
20+
const struct stepper_common_config *common;
1721
const struct gpio_dt_spec *msx_pins;
1822
enum stepper_micro_step_resolution *msx_resolutions;
1923
};
2024

2125
struct tmc22xx_data {
22-
struct step_dir_stepper_common_data common;
26+
struct stepper_common_data *const common;
2327
enum stepper_micro_step_resolution resolution;
2428
};
2529

26-
STEP_DIR_STEPPER_STRUCT_CHECK(struct tmc22xx_config, struct tmc22xx_data);
27-
28-
static int tmc22xx_stepper_enable(const struct device *dev)
29-
{
30-
const struct tmc22xx_config *config = dev->config;
31-
32-
LOG_DBG("Enabling Stepper motor controller %s", dev->name);
33-
return gpio_pin_set_dt(&config->enable_pin, 1);
34-
}
35-
36-
static int tmc22xx_stepper_disable(const struct device *dev)
30+
static int tmc22xx_stepper_get_micro_step_res(const struct device *dev,
31+
enum stepper_micro_step_resolution *micro_step_res)
3732
{
38-
const struct tmc22xx_config *config = dev->config;
33+
const struct tmc22xx_data *data = dev->data;
3934

40-
LOG_DBG("Disabling Stepper motor controller %s", dev->name);
41-
return gpio_pin_set_dt(&config->enable_pin, 0);
35+
*micro_step_res = data->resolution;
36+
return 0;
4237
}
4338

4439
static int tmc22xx_stepper_set_micro_step_res(const struct device *dev,
@@ -78,15 +73,6 @@ static int tmc22xx_stepper_set_micro_step_res(const struct device *dev,
7873
return -ENOTSUP;
7974
}
8075

81-
static int tmc22xx_stepper_get_micro_step_res(const struct device *dev,
82-
enum stepper_micro_step_resolution *micro_step_res)
83-
{
84-
struct tmc22xx_data *data = dev->data;
85-
86-
*micro_step_res = data->resolution;
87-
return 0;
88-
}
89-
9076
static int tmc22xx_stepper_configure_msx_pins(const struct device *dev)
9177
{
9278
const struct tmc22xx_config *config = dev->config;
@@ -110,17 +96,11 @@ static int tmc22xx_stepper_configure_msx_pins(const struct device *dev)
11096
static int tmc22xx_stepper_init(const struct device *dev)
11197
{
11298
const struct tmc22xx_config *config = dev->config;
113-
struct tmc22xx_data *data = dev->data;
114-
int ret;
99+
const struct tmc22xx_data *data = dev->data;
115100

116-
if (!gpio_is_ready_dt(&config->enable_pin)) {
117-
LOG_ERR("GPIO pins are not ready");
118-
return -ENODEV;
119-
}
120-
121-
ret = gpio_pin_configure_dt(&config->enable_pin, GPIO_OUTPUT);
101+
int ret = step_dir_interface_init(dev);
122102
if (ret < 0) {
123-
LOG_ERR("Failed to configure enable pin: %d", ret);
103+
LOG_ERR("Failed to init step dir interface: %d", ret);
124104
return ret;
125105
}
126106

@@ -138,7 +118,7 @@ static int tmc22xx_stepper_init(const struct device *dev)
138118
}
139119
}
140120

141-
ret = step_dir_stepper_common_init(dev);
121+
ret = stepper_motion_controller_init(dev);
142122
if (ret < 0) {
143123
LOG_ERR("Failed to init step dir common stepper: %d", ret);
144124
return ret;
@@ -147,43 +127,55 @@ static int tmc22xx_stepper_init(const struct device *dev)
147127
return 0;
148128
}
149129

130+
static const struct stepper_motion_controller_callbacks_api motion_controller_callbacks = {
131+
.step = stepper_common_step,
132+
.set_direction = stepper_common_set_direction,
133+
.event = stepper_common_handle_event,
134+
};
135+
150136
static DEVICE_API(stepper, tmc22xx_stepper_api) = {
151-
.enable = tmc22xx_stepper_enable,
152-
.disable = tmc22xx_stepper_disable,
153-
.move_by = step_dir_stepper_common_move_by,
154-
.is_moving = step_dir_stepper_common_is_moving,
155-
.set_reference_position = step_dir_stepper_common_set_reference_position,
156-
.get_actual_position = step_dir_stepper_common_get_actual_position,
157-
.move_to = step_dir_stepper_common_move_to,
158-
.set_microstep_interval = step_dir_stepper_common_set_microstep_interval,
159-
.run = step_dir_stepper_common_run,
160-
.stop = step_dir_stepper_common_stop,
161-
.set_event_callback = step_dir_stepper_common_set_event_callback,
137+
.enable = stepper_common_enable,
138+
.disable = stepper_common_disable,
139+
.move_by = stepper_common_move_by,
140+
.is_moving = stepper_common_is_moving,
141+
.set_reference_position = stepper_common_set_position,
142+
.get_actual_position = stepper_common_get_position,
143+
.move_to = stepper_common_move_to,
144+
.run = stepper_common_run,
145+
.stop = stepper_common_stop,
146+
.set_event_callback = stepper_common_set_event_callback,
162147
.set_micro_step_res = tmc22xx_stepper_set_micro_step_res,
163148
.get_micro_step_res = tmc22xx_stepper_get_micro_step_res,
149+
.set_ramp = stepper_motion_controller_set_ramp,
164150
};
165151

166152
#define TMC22XX_STEPPER_DEFINE(inst, msx_table) \
167-
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \
168-
static const struct gpio_dt_spec tmc22xx_stepper_msx_pins_##inst[] = { \
169-
DT_INST_FOREACH_PROP_ELEM_SEP( \
170-
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \
171-
), \
153+
STEPPER_MOTION_CONTROLLER_DT_INST_DEFINE(inst, &motion_controller_callbacks) \
154+
STEPPER_INTERFACE_STEP_DIR_DT_INST_DEFINE(inst) \
155+
static const struct stepper_common_config common_cfg_##inst = { \
156+
.motion_controller = STEPPER_MOTION_CONTROLLER_DT_INST_GET(inst), \
157+
.interface = STEPPER_INTERFACE_STEP_DIR_DT_INST_GET(inst), \
158+
.step = step_dir_interface_step, \
159+
.set_direction = step_dir_interface_set_dir, \
172160
}; \
173-
BUILD_ASSERT( \
174-
ARRAY_SIZE(tmc22xx_stepper_msx_pins_##inst) == MSX_PIN_COUNT, \
175-
"Two microstep config pins needed"); \
176-
)) \
177-
\
161+
static struct stepper_common_data common_data_##inst = {}; \
162+
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \
163+
static const struct gpio_dt_spec tmc22xx_stepper_msx_pins_## inst[] = { \
164+
DT_INST_FOREACH_PROP_ELEM_SEP( \
165+
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \
166+
), \
167+
}; \
168+
BUILD_ASSERT( \
169+
ARRAY_SIZE(tmc22xx_stepper_msx_pins_## inst) == MSX_PIN_COUNT, \
170+
"Two microstep config pins needed"); \
171+
)) \
178172
static const struct tmc22xx_config tmc22xx_config_##inst = { \
179-
.common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \
180-
.enable_pin = GPIO_DT_SPEC_INST_GET(inst, en_gpios), \
173+
.common = &common_cfg_##inst, \
181174
.msx_resolutions = msx_table, \
182-
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), \
183-
(.msx_pins = tmc22xx_stepper_msx_pins_##inst)) \
184-
}; \
175+
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), \
176+
(.msx_pins = tmc22xx_stepper_msx_pins_## inst)) }; \
185177
static struct tmc22xx_data tmc22xx_data_##inst = { \
186-
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \
178+
.common = &common_data_##inst, \
187179
.resolution = DT_INST_PROP(inst, micro_step_res), \
188180
}; \
189181
DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \
@@ -198,4 +190,5 @@ static enum stepper_micro_step_resolution tmc2209_msx_resolutions[MSX_PIN_STATE_
198190
STEPPER_MICRO_STEP_16,
199191
};
200192
DT_INST_FOREACH_STATUS_OKAY_VARGS(TMC22XX_STEPPER_DEFINE, tmc2209_msx_resolutions)
193+
201194
#undef DT_DRV_COMPAT
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Andre Stefanov
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
zephyr_library_property(ALLOW_EMPTY TRUE)
6+
7+
zephyr_library_sources_ifdef(CONFIG_STEPPER_INTERFACE_STEP_DIR stepper_interface_step_dir.c)

drivers/stepper/interface/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
2+
# Copyright (c) 2025 Andre Stefanov
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
config STEPPER_INTERFACE_STEP_DIR
6+
bool
7+
help
8+
Enable library used for step/dir stepper drivers.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 Andre Stefanov <mail@andrestefanov.de>
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "stepper_interface_step_dir.h"
7+
8+
#include <zephyr/drivers/stepper.h>
9+
#include <zephyr/drivers/gpio.h>
10+
#include "../stepper_common.h"
11+
12+
#include <zephyr/logging/log.h>
13+
LOG_MODULE_REGISTER(stepper_interface_step_dir, CONFIG_STEPPER_LOG_LEVEL);
14+
15+
#define STEPPER_COMMON_FROM_DEV(dev) ((const struct stepper_common_config_base *)dev->config)
16+
#define STEPPER_CONFIG_FROM_DEV(dev) (STEPPER_COMMON_FROM_DEV(dev)->config)
17+
#define INTERFACE_FROM_DEV(dev) \
18+
((const struct stepper_interface_step_dir *)STEPPER_CONFIG_FROM_DEV(dev)->interface)
19+
20+
int step_dir_interface_init(const struct device *dev)
21+
{
22+
const struct stepper_interface_step_dir *interface = INTERFACE_FROM_DEV(dev);
23+
24+
if (!gpio_is_ready_dt(&interface->en_pin)) {
25+
LOG_ERR("Enable pin is not ready");
26+
return -ENODEV;
27+
}
28+
29+
if (!gpio_is_ready_dt(&interface->step_pin)) {
30+
LOG_ERR("Step pin is not ready");
31+
return -ENODEV;
32+
}
33+
34+
if (!gpio_is_ready_dt(&interface->dir_pin)) {
35+
LOG_ERR("Dir pin is not ready");
36+
return -ENODEV;
37+
}
38+
39+
int ret = gpio_pin_configure_dt(&interface->en_pin, GPIO_OUTPUT);
40+
if (ret < 0) {
41+
LOG_ERR("Failed to configure enable pin: %d", ret);
42+
return ret;
43+
}
44+
45+
ret = gpio_pin_configure_dt(&interface->step_pin, GPIO_OUTPUT);
46+
if (ret < 0) {
47+
LOG_ERR("Failed to configure step pin: %d", ret);
48+
return ret;
49+
}
50+
51+
ret = gpio_pin_configure_dt(&interface->dir_pin, GPIO_OUTPUT);
52+
if (ret < 0) {
53+
LOG_ERR("Failed to configure dir pin: %d", ret);
54+
return ret;
55+
}
56+
57+
return 0;
58+
}
59+
60+
int step_dir_interface_step(const struct device *dev)
61+
{
62+
const struct stepper_interface_step_dir *interface = INTERFACE_FROM_DEV(dev);
63+
64+
int ret = gpio_pin_set_dt(&interface->step_pin, interface->invert_direction ? 0 : 1);
65+
if (ret < 0) {
66+
LOG_ERR("Failed to set step pin: %d", ret);
67+
return ret;
68+
}
69+
70+
ret = gpio_pin_set_dt(&interface->step_pin, 0 ^ interface->invert_direction ? 1 : 0);
71+
if (ret < 0) {
72+
LOG_ERR("Failed to set step pin: %d", ret);
73+
return ret;
74+
}
75+
76+
return 0;
77+
}
78+
79+
int step_dir_interface_set_dir(const struct device *dev, const enum stepper_direction direction)
80+
{
81+
const struct stepper_interface_step_dir *interface = INTERFACE_FROM_DEV(dev);
82+
83+
const int dir_value = (direction == STEPPER_DIRECTION_POSITIVE) ? 1 : 0;
84+
const int ret = gpio_pin_set_dt(&interface->dir_pin, dir_value);
85+
if (ret < 0) {
86+
LOG_ERR("Failed to set direction pin: %d", ret);
87+
return ret;
88+
}
89+
90+
return 0;
91+
}
92+
93+
int step_dir_interface_enable(const struct device *dev)
94+
{
95+
const struct stepper_interface_step_dir *interface = INTERFACE_FROM_DEV(dev);
96+
97+
LOG_DBG("Enabling Stepper motor controller %s", dev->name);
98+
return gpio_pin_set_dt(&interface->en_pin, 0);
99+
}
100+
101+
int step_dir_interface_disable(const struct device *dev)
102+
{
103+
const struct stepper_interface_step_dir *interface = INTERFACE_FROM_DEV(dev);
104+
105+
LOG_DBG("Disabling Stepper motor controller %s", dev->name);
106+
return gpio_pin_set_dt(&interface->en_pin, 1);
107+
}

0 commit comments

Comments
 (0)