diff --git a/drivers/stepper/ti/Kconfig.drv8424 b/drivers/stepper/ti/Kconfig.drv8424 index f01a7b1bc34..38421ae645f 100644 --- a/drivers/stepper/ti/Kconfig.drv8424 +++ b/drivers/stepper/ti/Kconfig.drv8424 @@ -5,17 +5,7 @@ config DRV8424 bool "TI DRV8424 stepper motor driver" default y depends on DT_HAS_TI_DRV8424_ENABLED - select COUNTER + select STEP_DIR_STEPPER + select STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS help Enable driver for TI DRV8424 stepper motor driver. - -if DRV8424 - -config DRV8424_EVENT_QUEUE_LEN - int "Maximum number of pending stepper events" - default 4 - help - The maximum number of stepper events that can be pending before new events - are dropped. - -endif # DRV8424 diff --git a/drivers/stepper/ti/drv8424.c b/drivers/stepper/ti/drv8424.c index 79981dc79ea..57aa64f9ff4 100644 --- a/drivers/stepper/ti/drv8424.c +++ b/drivers/stepper/ti/drv8424.c @@ -5,14 +5,11 @@ #define DT_DRV_COMPAT ti_drv8424 -#include -#include #include #include #include -#include -#include #include +#include "../step_dir/step_dir_stepper_common.h" #include LOG_MODULE_REGISTER(drv8424, CONFIG_STEPPER_LOG_LEVEL); @@ -24,13 +21,11 @@ LOG_MODULE_REGISTER(drv8424, CONFIG_STEPPER_LOG_LEVEL); * needed by a given DRV8424 stepper driver. */ struct drv8424_config { - struct gpio_dt_spec dir_pin; - struct gpio_dt_spec step_pin; + struct step_dir_stepper_common_config common; struct gpio_dt_spec sleep_pin; struct gpio_dt_spec en_pin; struct gpio_dt_spec m0_pin; struct gpio_dt_spec m1_pin; - const struct device *counter; }; /* Struct for storing the states of output pins. */ @@ -47,119 +42,13 @@ struct drv8424_pin_states { * This structure contains mutable data used by a DRV8424 stepper driver. */ struct drv8424_data { - const struct device *dev; + const struct step_dir_stepper_common_data common; bool enabled; struct drv8424_pin_states pin_states; enum stepper_micro_step_resolution ustep_res; - uint32_t max_velocity; - int32_t reference_position; - int32_t target_position; - bool is_moving; - bool constant_velocity; - enum stepper_direction constant_velocity_direction; - stepper_event_callback_t event_callback; - struct k_work event_callback_work; - void *event_callback_user_data; - struct k_msgq event_msgq; - char event_msgq_buffer[CONFIG_DRV8424_EVENT_QUEUE_LEN * sizeof(enum stepper_event)]; - bool step_signal_high; - struct counter_top_cfg counter_top_cfg; }; -static void drv8424_user_callback_work_fn(struct k_work *work) -{ - int ret; - - /* Get containing data struct */ - struct drv8424_data *driver_data = - CONTAINER_OF(work, struct drv8424_data, event_callback_work); - - /* Get next pending event (if any) from message queue */ - enum stepper_event event; - - ret = k_msgq_get(&driver_data->event_msgq, &event, K_NO_WAIT); - if (ret != 0) { - /* No pending events */ - return; - } - - /* Run the callback */ - if (driver_data->event_callback != NULL) { - driver_data->event_callback(driver_data->dev, event, - driver_data->event_callback_user_data); - } - - /* If there are more pending events, resubmit this work item to handle them */ - if (k_msgq_num_used_get(&driver_data->event_msgq) > 0) { - k_work_submit(work); - } -} - -static int drv8424_schedule_user_callback(struct drv8424_data *data, enum stepper_event event) -{ - int ret; - - /* Place event in message queue to be picked up by work item */ - ret = k_msgq_put(&data->event_msgq, &event, K_NO_WAIT); - if (ret != 0) { - LOG_WRN("%s: Too many concurrent events, dropping event of type %d", - data->dev->name, event); - return -ENOBUFS; - } - - /* Submit work item */ - ret = k_work_submit(&data->event_callback_work); - if (ret < 0) { - LOG_ERR("%s: Failed to submit work item (error %d)", data->dev->name, ret); - return ret; - } - - return 0; -} - -static void drv8424_positioning_top_interrupt(const struct device *dev, void *user_data) -{ - struct drv8424_data *data = user_data; - const struct drv8424_config *config = data->dev->config; - - if (!data->constant_velocity && data->reference_position == data->target_position) { - /* Check if target position is reached */ - counter_stop(config->counter); - if (data->event_callback != NULL) { - /* Ignore return value since we can't do anything about it anyway */ - drv8424_schedule_user_callback(data, STEPPER_EVENT_STEPS_COMPLETED); - } - data->is_moving = false; - return; - } - - /* Determine direction we're going in for counting purposes */ - enum stepper_direction direction; - - if (data->constant_velocity) { - direction = data->constant_velocity_direction; - } else { - direction = (data->target_position >= data->reference_position) - ? STEPPER_DIRECTION_POSITIVE - : STEPPER_DIRECTION_NEGATIVE; - } - - /* Switch step pin on or off depending position in step period */ - if (data->step_signal_high) { - /* Generate a falling edge and count a completed step */ - gpio_pin_set_dt(&config->step_pin, 0); - if (direction == STEPPER_DIRECTION_POSITIVE) { - data->reference_position++; - } else { - data->reference_position--; - } - } else { - /* Generate a rising edge */ - gpio_pin_set_dt(&config->step_pin, 1); - } - - data->step_signal_high = !data->step_signal_high; -} +STEP_DIR_STEPPER_STRUCT_CHECK(struct drv8424_config, struct drv8424_data); static int drv8424_set_microstep_pin(const struct device *dev, const struct gpio_dt_spec *pin, int value) @@ -263,216 +152,13 @@ static int drv8424_enable(const struct device *dev, bool enable) data->enabled = enable; if (!enable) { - counter_stop(config->counter); - data->is_moving = false; - gpio_pin_set_dt(&config->step_pin, 0); - data->step_signal_high = false; + config->common.timing_source->stop(dev); + gpio_pin_set_dt(&config->common.step_pin, 0); } return 0; } -static int drv8424_set_counter_frequency(const struct device *dev, uint32_t freq_hz) -{ - const struct drv8424_config *config = dev->config; - struct drv8424_data *data = dev->data; - int ret; - - if (freq_hz == 0) { - return -EINVAL; - } - - data->counter_top_cfg.ticks = - DIV_ROUND_UP(counter_us_to_ticks(config->counter, USEC_PER_SEC), freq_hz); - - ret = counter_set_top_value(config->counter, &data->counter_top_cfg); - if (ret != 0) { - LOG_ERR("%s: Failed to set counter top value (error: %d)", dev->name, ret); - return ret; - } - - return 0; -} - -static int drv8424_start_positioning(const struct device *dev) -{ - - const struct drv8424_config *config = dev->config; - struct drv8424_data *data = dev->data; - int ret; - - /* Unset constant velocity flag if present */ - data->constant_velocity = false; - - int dir_value = (data->target_position >= data->reference_position) ? 1 : 0; - - ret = gpio_pin_set_dt(&config->dir_pin, dir_value); - if (ret != 0) { - LOG_ERR("%s: Failed to set direction pin (error %d)", dev->name, ret); - return ret; - } - - /* Lock interrupts while modifying counter settings */ - int key = irq_lock(); - - /* Set counter to step signal frequency */ - ret = drv8424_set_counter_frequency(dev, data->max_velocity * 2); - if (ret != 0) { - LOG_ERR("%s: Failed to set counter frequency (error %d)", dev->name, ret); - goto end; - } - - data->is_moving = true; - - ret = counter_start(config->counter); - if (ret != 0) { - LOG_ERR("%s: Failed to start counter (error: %d)", dev->name, ret); - data->is_moving = false; - goto end; - } - -end: - irq_unlock(key); - return ret; -} - -static int drv8424_move_by(const struct device *dev, int32_t micro_steps) -{ - struct drv8424_data *data = dev->data; - int ret; - - if (data->max_velocity == 0) { - LOG_ERR("%s: Invalid max. velocity %d configured", dev->name, data->max_velocity); - return -EINVAL; - } - - if (!data->enabled) { - return -ECANCELED; - } - - /* Compute target position */ - data->target_position = data->reference_position + micro_steps; - - ret = drv8424_start_positioning(dev); - if (ret != 0) { - LOG_ERR("%s: Failed to begin positioning (error %d)", dev->name, ret); - return ret; - }; - - return 0; -} - -static int drv8424_is_moving(const struct device *dev, bool *is_moving) -{ - struct drv8424_data *data = dev->data; - - *is_moving = data->is_moving; - - return 0; -} - -static int drv8424_set_reference_position(const struct device *dev, int32_t position) -{ - struct drv8424_data *data = dev->data; - - data->reference_position = position; - - return 0; -} - -static int drv8424_get_actual_position(const struct device *dev, int32_t *position) -{ - struct drv8424_data *data = dev->data; - - *position = data->reference_position; - - return 0; -} - -static int drv8424_move_to(const struct device *dev, int32_t position) -{ - struct drv8424_data *data = dev->data; - int ret; - - if (!data->enabled) { - return -ECANCELED; - } - - data->target_position = position; - - ret = drv8424_start_positioning(dev); - if (ret != 0) { - LOG_ERR("%s: Failed to begin positioning (error %d)", dev->name, ret); - return ret; - }; - - return 0; -} - -static int drv8424_set_max_velocity(const struct device *dev, uint32_t velocity) -{ - struct drv8424_data *data = dev->data; - - data->max_velocity = velocity; - return 0; -} - -static int drv8424_run(const struct device *dev, const enum stepper_direction direction, - const uint32_t velocity) -{ - const struct drv8424_config *config = dev->config; - struct drv8424_data *data = dev->data; - int ret; - - if (!data->enabled) { - return -ECANCELED; - } - - int dir_value = (direction == STEPPER_DIRECTION_POSITIVE) ? 1 : 0; - - ret = gpio_pin_set_dt(&config->dir_pin, dir_value); - if (ret != 0) { - LOG_ERR("%s: Failed to set direction pin (error %d)", dev->name, ret); - return ret; - } - - /* Lock interrupts while modifying settings used by ISR */ - int key = irq_lock(); - - /* Set data used in counter interrupt */ - data->constant_velocity = true; - data->constant_velocity_direction = direction; - data->is_moving = false; - - /* Treat velocity 0 by not stepping at all */ - if (velocity == 0) { - ret = counter_stop(config->counter); - if (ret != 0) { - LOG_ERR("%s: Failed to stop counter (error %d)", dev->name, ret); - goto end; - } - gpio_pin_set_dt(&config->step_pin, 0); - data->step_signal_high = false; - } else { - ret = drv8424_set_counter_frequency(dev, velocity * 2); - if (ret != 0) { - LOG_ERR("%s: Failed to set counter frequency (error %d)", dev->name, ret); - goto end; - } - - ret = counter_start(config->counter); - if (ret != 0) { - LOG_ERR("%s: Failed to start counter (error %d)", dev->name, ret); - goto end; - } - data->is_moving = true; - } - -end: - irq_unlock(key); - return ret; -} - static int drv8424_set_micro_step_res(const struct device *dev, enum stepper_micro_step_resolution micro_step_res) { @@ -554,15 +240,41 @@ static int drv8424_get_micro_step_res(const struct device *dev, return 0; } -static int drv8424_set_event_callback(const struct device *dev, stepper_event_callback_t callback, - void *user_data) +static int drv8424_move_to(const struct device *dev, int32_t target) { struct drv8424_data *data = dev->data; - data->event_callback = callback; - data->event_callback_user_data = user_data; + if (!data->enabled) { + LOG_ERR("Failed to move to target position, device is not enabled"); + return -ECANCELED; + } - return 0; + return step_dir_stepper_common_move_to(dev, target); +} + +static int drv8424_move_by(const struct device *dev, int32_t steps) +{ + struct drv8424_data *data = dev->data; + + if (!data->enabled) { + LOG_ERR("Failed to move by delta, device is not enabled"); + return -ECANCELED; + } + + return step_dir_stepper_common_move_by(dev, steps); +} + +static int drv8424_run(const struct device *dev, enum stepper_direction direction, + uint32_t velocity) +{ + struct drv8424_data *data = dev->data; + + if (!data->enabled) { + LOG_ERR("Failed to run stepper, device is not enabled"); + return -ECANCELED; + } + + return step_dir_stepper_common_run(dev, direction, velocity); } static int drv8424_init(const struct device *dev) @@ -571,22 +283,6 @@ static int drv8424_init(const struct device *dev) struct drv8424_data *const data = dev->data; int ret; - data->dev = dev; - - /* Configure direction pin */ - ret = gpio_pin_configure_dt(&config->dir_pin, GPIO_OUTPUT_ACTIVE); - if (ret != 0) { - LOG_ERR("%s: Failed to configure dir_pin (error: %d)", dev->name, ret); - return ret; - } - - /* Configure step pin */ - ret = gpio_pin_configure_dt(&config->step_pin, GPIO_OUTPUT_INACTIVE); - if (ret != 0) { - LOG_ERR("%s: Failed to configure step_pin (error: %d)", dev->name, ret); - return ret; - } - /* Configure sleep pin if it is available */ if (config->sleep_pin.port != NULL) { ret = gpio_pin_configure_dt(&config->sleep_pin, GPIO_OUTPUT_ACTIVE); @@ -628,17 +324,11 @@ static int drv8424_init(const struct device *dev) return ret; } - /* Set initial counter configuration */ - data->step_signal_high = false; - data->counter_top_cfg.callback = drv8424_positioning_top_interrupt; - data->counter_top_cfg.user_data = data; - data->counter_top_cfg.flags = 0; - data->counter_top_cfg.ticks = counter_us_to_ticks(config->counter, 1000000); - - /* Initialize work item and message queue for handling event callbacks */ - k_msgq_init(&data->event_msgq, data->event_msgq_buffer, sizeof(enum stepper_event), - CONFIG_DRV8424_EVENT_QUEUE_LEN); - k_work_init(&data->event_callback_work, drv8424_user_callback_work_fn); + ret = step_dir_stepper_common_init(dev); + if (ret != 0) { + LOG_ERR("Failed to initialize common step direction stepper (error: %d)", ret); + return ret; + } return 0; } @@ -647,31 +337,29 @@ static DEVICE_API(stepper, drv8424_stepper_api) = { .enable = drv8424_enable, .move_by = drv8424_move_by, .move_to = drv8424_move_to, - .is_moving = drv8424_is_moving, - .set_reference_position = drv8424_set_reference_position, - .get_actual_position = drv8424_get_actual_position, - .set_max_velocity = drv8424_set_max_velocity, + .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, + .set_max_velocity = step_dir_stepper_common_set_max_velocity, .run = drv8424_run, .set_micro_step_res = drv8424_set_micro_step_res, .get_micro_step_res = drv8424_get_micro_step_res, - .set_event_callback = drv8424_set_event_callback, + .set_event_callback = step_dir_stepper_common_set_event_callback, }; #define DRV8424_DEVICE(inst) \ \ static const struct drv8424_config drv8424_config_##inst = { \ - .dir_pin = GPIO_DT_SPEC_INST_GET(inst, dir_gpios), \ - .step_pin = GPIO_DT_SPEC_INST_GET(inst, step_gpios), \ + .common = STEP_DIR_STEPPER_DT_INST_COMMON_CONFIG_INIT(inst), \ .sleep_pin = GPIO_DT_SPEC_INST_GET_OR(inst, sleep_gpios, {0}), \ .en_pin = GPIO_DT_SPEC_INST_GET_OR(inst, en_gpios, {0}), \ .m0_pin = GPIO_DT_SPEC_INST_GET(inst, m0_gpios), \ .m1_pin = GPIO_DT_SPEC_INST_GET(inst, m1_gpios), \ - .counter = DEVICE_DT_GET(DT_INST_PHANDLE(inst, counter)), \ }; \ \ static struct drv8424_data drv8424_data_##inst = { \ + .common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \ .ustep_res = DT_INST_PROP(inst, micro_step_res), \ - .reference_position = 0, \ }; \ \ DEVICE_DT_INST_DEFINE(inst, &drv8424_init, NULL, &drv8424_data_##inst, \ diff --git a/dts/bindings/stepper/ti/ti,drv8424.yaml b/dts/bindings/stepper/ti/ti,drv8424.yaml index a1a42f09c93..e02d85e5026 100644 --- a/dts/bindings/stepper/ti/ti,drv8424.yaml +++ b/dts/bindings/stepper/ti/ti,drv8424.yaml @@ -34,6 +34,7 @@ include: - step-gpios - dir-gpios - en-gpios + - counter properties: fault-gpios: @@ -53,8 +54,3 @@ properties: required: true type: phandle-array description: Microstep configuration pin 1. - - counter: - required: true - type: phandle - description: Counter used for generating step-accurate pulse signals.