drivers: stepper: Add adi,tmc2209 driver
Adds the tmc2209 driver using the step dir interface. Signed-off-by: Fabian Blatz <fabianblatz@gmail.com>
This commit is contained in:
parent
ba2aee24c9
commit
6e799979d8
7 changed files with 283 additions and 26 deletions
|
@ -5,4 +5,5 @@ zephyr_library()
|
||||||
zephyr_library_property(ALLOW_EMPTY TRUE)
|
zephyr_library_property(ALLOW_EMPTY TRUE)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC_SPI adi_tmc_spi.c)
|
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC_SPI adi_tmc_spi.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC2209 adi_tmc22xx_stepper_controller.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC5041 adi_tmc5041_stepper_controller.c)
|
zephyr_library_sources_ifdef(CONFIG_STEPPER_ADI_TMC5041 adi_tmc5041_stepper_controller.c)
|
||||||
|
|
|
@ -26,30 +26,7 @@ config STEPPER_ADI_TMC_SPI
|
||||||
|
|
||||||
comment "Trinamic Stepper Drivers"
|
comment "Trinamic Stepper Drivers"
|
||||||
|
|
||||||
config STEPPER_ADI_TMC5041
|
rsource "Kconfig.tmc22xx"
|
||||||
bool "Activate trinamic tmc5041 stepper driver"
|
rsource "Kconfig.tmc5041"
|
||||||
depends on DT_HAS_ADI_TMC5041_ENABLED && STEPPER_ADI_TMC
|
|
||||||
select STEPPER_ADI_TMC_SPI
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Stepper driver for TMC5041.
|
|
||||||
|
|
||||||
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL
|
|
||||||
bool "TMC5041 poll ramp status"
|
|
||||||
depends on STEPPER_ADI_TMC5041
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
When enabled, the ramp status will be polled on TMC5041, to check for events:
|
|
||||||
- TMC5041_POS_REACHED_EVENT
|
|
||||||
- TMC5041_STOP_SG_EVENT
|
|
||||||
- TMC5041_STOP_LEFT_EVENT
|
|
||||||
- TMC5041_STOP_RIGHT_EVENT
|
|
||||||
|
|
||||||
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL_INTERVAL_IN_MSEC
|
|
||||||
int "TMC5041 poll ramp status interval in ms"
|
|
||||||
depends on STEPPER_ADI_TMC5041_RAMPSTAT_POLL
|
|
||||||
default 100
|
|
||||||
help
|
|
||||||
The interval in ms to poll the ramp status on TMC5041.
|
|
||||||
|
|
||||||
endif # STEPPER_ADI_TMC
|
endif # STEPPER_ADI_TMC
|
||||||
|
|
10
drivers/stepper/adi_tmc/Kconfig.tmc22xx
Normal file
10
drivers/stepper/adi_tmc/Kconfig.tmc22xx
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config STEPPER_ADI_TMC2209
|
||||||
|
bool "Activate trinamic tmc2209 stepper driver"
|
||||||
|
depends on DT_HAS_ADI_TMC2209_ENABLED
|
||||||
|
select STEP_DIR_STEPPER
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Stepper driver for TMC2209.
|
28
drivers/stepper/adi_tmc/Kconfig.tmc5041
Normal file
28
drivers/stepper/adi_tmc/Kconfig.tmc5041
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config STEPPER_ADI_TMC5041
|
||||||
|
bool "Activate trinamic tmc5041 stepper driver"
|
||||||
|
depends on DT_HAS_ADI_TMC5041_ENABLED && STEPPER_ADI_TMC
|
||||||
|
select STEPPER_ADI_TMC_SPI
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Stepper driver for TMC5041.
|
||||||
|
|
||||||
|
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL
|
||||||
|
bool "TMC5041 poll ramp status"
|
||||||
|
depends on STEPPER_ADI_TMC5041
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
When enabled, the ramp status will be polled on TMC5041, to check for events:
|
||||||
|
- TMC5041_POS_REACHED_EVENT
|
||||||
|
- TMC5041_STOP_SG_EVENT
|
||||||
|
- TMC5041_STOP_LEFT_EVENT
|
||||||
|
- TMC5041_STOP_RIGHT_EVENT
|
||||||
|
|
||||||
|
config STEPPER_ADI_TMC5041_RAMPSTAT_POLL_INTERVAL_IN_MSEC
|
||||||
|
int "TMC5041 poll ramp status interval in ms"
|
||||||
|
depends on STEPPER_ADI_TMC5041_RAMPSTAT_POLL
|
||||||
|
default 100
|
||||||
|
help
|
||||||
|
The interval in ms to poll the ramp status on TMC5041.
|
196
drivers/stepper/adi_tmc/adi_tmc22xx_stepper_controller.c
Normal file
196
drivers/stepper/adi_tmc/adi_tmc22xx_stepper_controller.c
Normal file
|
@ -0,0 +1,196 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../step_dir_stepper_common.h"
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(tmc22xx, CONFIG_STEPPER_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define MSX_PIN_COUNT 2
|
||||||
|
#define MSX_PIN_STATE_COUNT 4
|
||||||
|
|
||||||
|
struct tmc22xx_config {
|
||||||
|
struct step_dir_stepper_common_config common;
|
||||||
|
const struct gpio_dt_spec enable_pin;
|
||||||
|
const struct gpio_dt_spec *msx_pins;
|
||||||
|
enum stepper_micro_step_resolution *msx_resolutions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tmc22xx_data {
|
||||||
|
struct step_dir_stepper_common_data common;
|
||||||
|
enum stepper_micro_step_resolution resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
STEP_DIR_STEPPER_STRUCT_CHECK(struct tmc22xx_config, struct tmc22xx_data);
|
||||||
|
|
||||||
|
static int tmc22xx_stepper_enable(const struct device *dev, const bool enable)
|
||||||
|
{
|
||||||
|
const struct tmc22xx_config *config = dev->config;
|
||||||
|
|
||||||
|
LOG_DBG("Stepper motor controller %s %s", dev->name, enable ? "enabled" : "disabled");
|
||||||
|
if (enable) {
|
||||||
|
return gpio_pin_set_dt(&config->enable_pin, 1);
|
||||||
|
} else {
|
||||||
|
return gpio_pin_set_dt(&config->enable_pin, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmc22xx_stepper_set_micro_step_res(const struct device *dev,
|
||||||
|
enum stepper_micro_step_resolution micro_step_res)
|
||||||
|
{
|
||||||
|
struct tmc22xx_data *data = dev->data;
|
||||||
|
const struct tmc22xx_config *config = dev->config;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!config->msx_pins) {
|
||||||
|
LOG_ERR("Microstep resolution pins are not configured");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < MSX_PIN_STATE_COUNT; i++) {
|
||||||
|
if (micro_step_res != config->msx_resolutions[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_set_dt(&config->msx_pins[0], i & 0x01);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to set MS1 pin: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_set_dt(&config->msx_pins[1], (i & 0x02) >> 1);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to set MS2 pin: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->resolution = micro_step_res;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_ERR("Unsupported microstep resolution: %d", micro_step_res);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmc22xx_stepper_get_micro_step_res(const struct device *dev,
|
||||||
|
enum stepper_micro_step_resolution *micro_step_res)
|
||||||
|
{
|
||||||
|
struct tmc22xx_data *data = dev->data;
|
||||||
|
|
||||||
|
*micro_step_res = data->resolution;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmc22xx_stepper_configure_msx_pins(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct tmc22xx_config *config = dev->config;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < MSX_PIN_COUNT; i++) {
|
||||||
|
if (!gpio_is_ready_dt(&config->msx_pins[i])) {
|
||||||
|
LOG_ERR("MSX pin %u are not ready", i);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_configure_dt(&config->msx_pins[i], GPIO_OUTPUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to configure msx pin %u", i);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tmc22xx_stepper_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct tmc22xx_config *config = dev->config;
|
||||||
|
struct tmc22xx_data *data = dev->data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!gpio_is_ready_dt(&config->enable_pin)) {
|
||||||
|
LOG_ERR("GPIO pins are not ready");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = gpio_pin_configure_dt(&config->enable_pin, GPIO_OUTPUT);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to configure enable pin: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->msx_pins) {
|
||||||
|
ret = tmc22xx_stepper_configure_msx_pins(dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to configure MSX pins: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tmc22xx_stepper_set_micro_step_res(dev, data->resolution);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to set microstep resolution: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = step_dir_stepper_common_init(dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
LOG_ERR("Failed to init step dir common stepper: %d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_API(stepper, tmc22xx_stepper_api) = {
|
||||||
|
.enable = tmc22xx_stepper_enable,
|
||||||
|
.move_by = step_dir_stepper_common_move_by,
|
||||||
|
.is_moving = step_dir_stepper_common_is_moving,
|
||||||
|
.set_reference_position = step_dir_stepper_common_set_reference_position,
|
||||||
|
.get_actual_position = step_dir_stepper_common_get_actual_position,
|
||||||
|
.move_to = step_dir_stepper_common_move_to,
|
||||||
|
.set_max_velocity = step_dir_stepper_common_set_max_velocity,
|
||||||
|
.run = step_dir_stepper_common_run,
|
||||||
|
.set_event_callback = step_dir_stepper_common_set_event_callback,
|
||||||
|
.set_micro_step_res = tmc22xx_stepper_set_micro_step_res,
|
||||||
|
.get_micro_step_res = tmc22xx_stepper_get_micro_step_res,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TMC22XX_STEPPER_DEFINE(inst, msx_table) \
|
||||||
|
IF_ENABLED(DT_INST_NODE_HAS_PROP(inst, msx_gpios), ( \
|
||||||
|
static const struct gpio_dt_spec tmc22xx_stepper_msx_pins_##inst[] = { \
|
||||||
|
DT_INST_FOREACH_PROP_ELEM_SEP( \
|
||||||
|
inst, msx_gpios, GPIO_DT_SPEC_GET_BY_IDX, (,) \
|
||||||
|
), \
|
||||||
|
}; \
|
||||||
|
BUILD_ASSERT( \
|
||||||
|
ARRAY_SIZE(tmc22xx_stepper_msx_pins_##inst) == MSX_PIN_COUNT, \
|
||||||
|
"Two microstep config pins needed"); \
|
||||||
|
)) \
|
||||||
|
\
|
||||||
|
static const struct tmc22xx_config tmc22xx_config_##inst = { \
|
||||||
|
.common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \
|
||||||
|
.enable_pin = GPIO_DT_SPEC_INST_GET(inst, enable_gpios), \
|
||||||
|
.msx_pins = DT_INST_NODE_HAS_PROP(inst, msx_gpios) \
|
||||||
|
? tmc22xx_stepper_msx_pins_##inst \
|
||||||
|
: NULL, \
|
||||||
|
.msx_resolutions = msx_table, \
|
||||||
|
}; \
|
||||||
|
static struct tmc22xx_data tmc22xx_data_##inst = { \
|
||||||
|
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \
|
||||||
|
.resolution = DT_INST_PROP(inst, micro_step_res), \
|
||||||
|
}; \
|
||||||
|
DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \
|
||||||
|
&tmc22xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
|
||||||
|
&tmc22xx_stepper_api);
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT adi_tmc2209
|
||||||
|
static enum stepper_micro_step_resolution tmc2209_msx_resolutions[MSX_PIN_STATE_COUNT] = {
|
||||||
|
STEPPER_MICRO_STEP_8,
|
||||||
|
STEPPER_MICRO_STEP_32,
|
||||||
|
STEPPER_MICRO_STEP_64,
|
||||||
|
STEPPER_MICRO_STEP_16,
|
||||||
|
};
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY_VARGS(TMC22XX_STEPPER_DEFINE, tmc2209_msx_resolutions)
|
||||||
|
#undef DT_DRV_COMPAT
|
|
@ -241,7 +241,7 @@ int step_dir_stepper_common_run(const struct device *dev, const enum stepper_dir
|
||||||
K_SPINLOCK(&data->lock) {
|
K_SPINLOCK(&data->lock) {
|
||||||
data->run_mode = STEPPER_RUN_MODE_VELOCITY;
|
data->run_mode = STEPPER_RUN_MODE_VELOCITY;
|
||||||
data->direction = direction;
|
data->direction = direction;
|
||||||
if (value != 0) {
|
if (velocity != 0) {
|
||||||
data->delay_in_us = USEC_PER_SEC / velocity;
|
data->delay_in_us = USEC_PER_SEC / velocity;
|
||||||
(void)k_work_reschedule(&data->stepper_dwork, K_NO_WAIT);
|
(void)k_work_reschedule(&data->stepper_dwork, K_NO_WAIT);
|
||||||
} else {
|
} else {
|
||||||
|
|
45
dts/bindings/stepper/adi/adi,tmc2209.yaml
Normal file
45
dts/bindings/stepper/adi/adi,tmc2209.yaml
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# SPDX-FileCopyrightText: Copyright (c) 2024 Fabian Blatz <fabianblatz@gmail.com>
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Analog Devices TMC2209 stepper motor driver.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
tmc2209: tmc2209 {
|
||||||
|
compatible = "adi,tmc2209";
|
||||||
|
enable-gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
|
||||||
|
msx-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>,
|
||||||
|
<&gpio0 2 GPIO_ACTIVE_HIGH>;
|
||||||
|
step-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
direction-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
dual-edge-step;
|
||||||
|
}
|
||||||
|
|
||||||
|
compatible: "adi,tmc2209"
|
||||||
|
|
||||||
|
include:
|
||||||
|
- name: stepper-controller.yaml
|
||||||
|
property-allowlist:
|
||||||
|
- micro-step-res
|
||||||
|
- step-gpios
|
||||||
|
- direction-gpios
|
||||||
|
|
||||||
|
properties:
|
||||||
|
enable-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
description: |
|
||||||
|
GPIO pins used to control the enable signal of the motor driver.
|
||||||
|
|
||||||
|
msx-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
description: |
|
||||||
|
An array of GPIO pins for configuring the microstep resolution of the driver.
|
||||||
|
The pins should be listed in the following order:
|
||||||
|
- MS1
|
||||||
|
- MS2
|
||||||
|
|
||||||
|
dual-edge-step:
|
||||||
|
type: boolean
|
||||||
|
description: |
|
||||||
|
If present, the stepper motor controller supports dual edge step signals.
|
||||||
|
This means that the step signal can be toggled on both the rising and falling edge.
|
Loading…
Add table
Add a link
Reference in a new issue