Skip to content

Commit 6e79997

Browse files
faxe1008fabiobaltieri
authored andcommitted
drivers: stepper: Add adi,tmc2209 driver
Adds the tmc2209 driver using the step dir interface. Signed-off-by: Fabian Blatz <[email protected]>
1 parent ba2aee2 commit 6e79997

File tree

7 files changed

+283
-26
lines changed

7 files changed

+283
-26
lines changed

drivers/stepper/adi_tmc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ zephyr_library()
55
zephyr_library_property(ALLOW_EMPTY TRUE)
66

77
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC_SPI adi_tmc_spi.c)
8+
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC2209 adi_tmc22xx_stepper_controller.c)
89
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC5041 adi_tmc5041_stepper_controller.c)

drivers/stepper/adi_tmc/Kconfig

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,30 +26,7 @@ config STEPPER_ADI_TMC_SPI
2626

2727
comment "Trinamic Stepper Drivers"
2828

29-
config STEPPER_ADI_TMC5041
30-
bool "Activate trinamic tmc5041 stepper driver"
31-
depends on DT_HAS_ADI_TMC5041_ENABLED && STEPPER_ADI_TMC
32-
select STEPPER_ADI_TMC_SPI
33-
default y
34-
help
35-
Stepper driver for TMC5041.
36-
37-
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL
38-
bool "TMC5041 poll ramp status"
39-
depends on STEPPER_ADI_TMC5041
40-
default y
41-
help
42-
When enabled, the ramp status will be polled on TMC5041, to check for events:
43-
- TMC5041_POS_REACHED_EVENT
44-
- TMC5041_STOP_SG_EVENT
45-
- TMC5041_STOP_LEFT_EVENT
46-
- TMC5041_STOP_RIGHT_EVENT
47-
48-
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL_INTERVAL_IN_MSEC
49-
int "TMC5041 poll ramp status interval in ms"
50-
depends on STEPPER_ADI_TMC5041_RAMPSTAT_POLL
51-
default 100
52-
help
53-
The interval in ms to poll the ramp status on TMC5041.
29+
rsource "Kconfig.tmc22xx"
30+
rsource "Kconfig.tmc5041"
5431

5532
endif # STEPPER_ADI_TMC
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <[email protected]>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config STEPPER_ADI_TMC2209
5+
bool "Activate trinamic tmc2209 stepper driver"
6+
depends on DT_HAS_ADI_TMC2209_ENABLED
7+
select STEP_DIR_STEPPER
8+
default y
9+
help
10+
Stepper driver for TMC2209.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <[email protected]>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config STEPPER_ADI_TMC5041
5+
bool "Activate trinamic tmc5041 stepper driver"
6+
depends on DT_HAS_ADI_TMC5041_ENABLED && STEPPER_ADI_TMC
7+
select STEPPER_ADI_TMC_SPI
8+
default y
9+
help
10+
Stepper driver for TMC5041.
11+
12+
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL
13+
bool "TMC5041 poll ramp status"
14+
depends on STEPPER_ADI_TMC5041
15+
default y
16+
help
17+
When enabled, the ramp status will be polled on TMC5041, to check for events:
18+
- TMC5041_POS_REACHED_EVENT
19+
- TMC5041_STOP_SG_EVENT
20+
- TMC5041_STOP_LEFT_EVENT
21+
- TMC5041_STOP_RIGHT_EVENT
22+
23+
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL_INTERVAL_IN_MSEC
24+
int "TMC5041 poll ramp status interval in ms"
25+
depends on STEPPER_ADI_TMC5041_RAMPSTAT_POLL
26+
default 100
27+
help
28+
The interval in ms to poll the ramp status on TMC5041.
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <[email protected]>
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include "../step_dir_stepper_common.h"
7+
8+
#include <zephyr/logging/log.h>
9+
LOG_MODULE_REGISTER(tmc22xx, CONFIG_STEPPER_LOG_LEVEL);
10+
11+
#define MSX_PIN_COUNT 2
12+
#define MSX_PIN_STATE_COUNT 4
13+
14+
struct tmc22xx_config {
15+
struct step_dir_stepper_common_config common;
16+
const struct gpio_dt_spec enable_pin;
17+
const struct gpio_dt_spec *msx_pins;
18+
enum stepper_micro_step_resolution *msx_resolutions;
19+
};
20+
21+
struct tmc22xx_data {
22+
struct step_dir_stepper_common_data common;
23+
enum stepper_micro_step_resolution resolution;
24+
};
25+
26+
STEP_DIR_STEPPER_STRUCT_CHECK(struct tmc22xx_config, struct tmc22xx_data);
27+
28+
static int tmc22xx_stepper_enable(const struct device *dev, const bool enable)
29+
{
30+
const struct tmc22xx_config *config = dev->config;
31+
32+
LOG_DBG("Stepper motor controller %s %s", dev->name, enable ? "enabled" : "disabled");
33+
if (enable) {
34+
return gpio_pin_set_dt(&config->enable_pin, 1);
35+
} else {
36+
return gpio_pin_set_dt(&config->enable_pin, 0);
37+
}
38+
}
39+
40+
static int tmc22xx_stepper_set_micro_step_res(const struct device *dev,
41+
enum stepper_micro_step_resolution micro_step_res)
42+
{
43+
struct tmc22xx_data *data = dev->data;
44+
const struct tmc22xx_config *config = dev->config;
45+
int ret;
46+
47+
if (!config->msx_pins) {
48+
LOG_ERR("Microstep resolution pins are not configured");
49+
return -ENODEV;
50+
}
51+
52+
for (uint8_t i = 0; i < MSX_PIN_STATE_COUNT; i++) {
53+
if (micro_step_res != config->msx_resolutions[i]) {
54+
continue;
55+
}
56+
57+
ret = gpio_pin_set_dt(&config->msx_pins[0], i & 0x01);
58+
if (ret < 0) {
59+
LOG_ERR("Failed to set MS1 pin: %d", ret);
60+
return ret;
61+
}
62+
63+
ret = gpio_pin_set_dt(&config->msx_pins[1], (i & 0x02) >> 1);
64+
if (ret < 0) {
65+
LOG_ERR("Failed to set MS2 pin: %d", ret);
66+
return ret;
67+
}
68+
69+
data->resolution = micro_step_res;
70+
return 0;
71+
}
72+
73+
LOG_ERR("Unsupported microstep resolution: %d", micro_step_res);
74+
return -EINVAL;
75+
}
76+
77+
static int tmc22xx_stepper_get_micro_step_res(const struct device *dev,
78+
enum stepper_micro_step_resolution *micro_step_res)
79+
{
80+
struct tmc22xx_data *data = dev->data;
81+
82+
*micro_step_res = data->resolution;
83+
return 0;
84+
}
85+
86+
static int tmc22xx_stepper_configure_msx_pins(const struct device *dev)
87+
{
88+
const struct tmc22xx_config *config = dev->config;
89+
int ret;
90+
91+
for (uint8_t i = 0; i < MSX_PIN_COUNT; i++) {
92+
if (!gpio_is_ready_dt(&config->msx_pins[i])) {
93+
LOG_ERR("MSX pin %u are not ready", i);
94+
return -ENODEV;
95+
}
96+
97+
ret = gpio_pin_configure_dt(&config->msx_pins[i], GPIO_OUTPUT);
98+
if (ret < 0) {
99+
LOG_ERR("Failed to configure msx pin %u", i);
100+
return ret;
101+
}
102+
}
103+
return 0;
104+
}
105+
106+
static int tmc22xx_stepper_init(const struct device *dev)
107+
{
108+
const struct tmc22xx_config *config = dev->config;
109+
struct tmc22xx_data *data = dev->data;
110+
int ret;
111+
112+
if (!gpio_is_ready_dt(&config->enable_pin)) {
113+
LOG_ERR("GPIO pins are not ready");
114+
return -ENODEV;
115+
}
116+
117+
ret = gpio_pin_configure_dt(&config->enable_pin, GPIO_OUTPUT);
118+
if (ret < 0) {
119+
LOG_ERR("Failed to configure enable pin: %d", ret);
120+
return ret;
121+
}
122+
123+
if (config->msx_pins) {
124+
ret = tmc22xx_stepper_configure_msx_pins(dev);
125+
if (ret < 0) {
126+
LOG_ERR("Failed to configure MSX pins: %d", ret);
127+
return ret;
128+
}
129+
130+
ret = tmc22xx_stepper_set_micro_step_res(dev, data->resolution);
131+
if (ret < 0) {
132+
LOG_ERR("Failed to set microstep resolution: %d", ret);
133+
return ret;
134+
}
135+
}
136+
137+
ret = step_dir_stepper_common_init(dev);
138+
if (ret < 0) {
139+
LOG_ERR("Failed to init step dir common stepper: %d", ret);
140+
return ret;
141+
}
142+
143+
return 0;
144+
}
145+
146+
static DEVICE_API(stepper, tmc22xx_stepper_api) = {
147+
.enable = tmc22xx_stepper_enable,
148+
.move_by = step_dir_stepper_common_move_by,
149+
.is_moving = step_dir_stepper_common_is_moving,
150+
.set_reference_position = step_dir_stepper_common_set_reference_position,
151+
.get_actual_position = step_dir_stepper_common_get_actual_position,
152+
.move_to = step_dir_stepper_common_move_to,
153+
.set_max_velocity = step_dir_stepper_common_set_max_velocity,
154+
.run = step_dir_stepper_common_run,
155+
.set_event_callback = step_dir_stepper_common_set_event_callback,
156+
.set_micro_step_res = tmc22xx_stepper_set_micro_step_res,
157+
.get_micro_step_res = tmc22xx_stepper_get_micro_step_res,
158+
};
159+
160+
#define TMC22XX_STEPPER_DEFINE(inst, msx_table) \
161+
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \
162+
static const struct gpio_dt_spec tmc22xx_stepper_msx_pins_##inst[] = { \
163+
DT_INST_FOREACH_PROP_ELEM_SEP( \
164+
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \
165+
), \
166+
}; \
167+
BUILD_ASSERT( \
168+
ARRAY_SIZE(tmc22xx_stepper_msx_pins_##inst) == MSX_PIN_COUNT, \
169+
"Two microstep config pins needed"); \
170+
)) \
171+
\
172+
static const struct tmc22xx_config tmc22xx_config_##inst = { \
173+
.common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \
174+
.enable_pin = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
175+
.msx_pins = DT_INST_NODE_HAS_PROP(inst, msx_gpios) \
176+
? tmc22xx_stepper_msx_pins_##inst \
177+
: NULL, \
178+
.msx_resolutions = msx_table, \
179+
}; \
180+
static struct tmc22xx_data tmc22xx_data_##inst = { \
181+
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \
182+
.resolution = DT_INST_PROP(inst, micro_step_res), \
183+
}; \
184+
DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \
185+
&tmc22xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
186+
&tmc22xx_stepper_api);
187+
188+
#define DT_DRV_COMPAT adi_tmc2209
189+
static enum stepper_micro_step_resolution tmc2209_msx_resolutions[MSX_PIN_STATE_COUNT] = {
190+
STEPPER_MICRO_STEP_8,
191+
STEPPER_MICRO_STEP_32,
192+
STEPPER_MICRO_STEP_64,
193+
STEPPER_MICRO_STEP_16,
194+
};
195+
DT_INST_FOREACH_STATUS_OKAY_VARGS(TMC22XX_STEPPER_DEFINE, tmc2209_msx_resolutions)
196+
#undef DT_DRV_COMPAT

drivers/stepper/step_dir_stepper_common.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ int step_dir_stepper_common_run(const struct device *dev, const enum stepper_dir
241241
K_SPINLOCK(&data->lock) {
242242
data->run_mode = STEPPER_RUN_MODE_VELOCITY;
243243
data->direction = direction;
244-
if (value != 0) {
244+
if (velocity != 0) {
245245
data->delay_in_us = USEC_PER_SEC / velocity;
246246
(void)k_work_reschedule(&data->stepper_dwork, K_NO_WAIT);
247247
} else {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <[email protected]>
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: |
5+
Analog Devices TMC2209 stepper motor driver.
6+
7+
Example:
8+
tmc2209: tmc2209 {
9+
compatible = "adi,tmc2209";
10+
enable-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
11+
msx-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>,
12+
<&gpio0 2 GPIO_ACTIVE_HIGH>;
13+
step-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
14+
direction-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
15+
dual-edge-step;
16+
}
17+
18+
compatible: "adi,tmc2209"
19+
20+
include:
21+
- name: stepper-controller.yaml
22+
property-allowlist:
23+
- micro-step-res
24+
- step-gpios
25+
- direction-gpios
26+
27+
properties:
28+
enable-gpios:
29+
type: phandle-array
30+
description: |
31+
GPIO pins used to control the enable signal of the motor driver.
32+
33+
msx-gpios:
34+
type: phandle-array
35+
description: |
36+
An array of GPIO pins for configuring the microstep resolution of the driver.
37+
The pins should be listed in the following order:
38+
- MS1
39+
- MS2
40+
41+
dual-edge-step:
42+
type: boolean
43+
description: |
44+
If present, the stepper motor controller supports dual edge step signals.
45+
This means that the step signal can be toggled on both the rising and falling edge.

0 commit comments

Comments
 (0)