diff --git a/drivers/stepper/ti/drv8424.c b/drivers/stepper/ti/drv8424.c index 4acbb02e99d..a6960157d5f 100644 --- a/drivers/stepper/ti/drv8424.c +++ b/drivers/stepper/ti/drv8424.c @@ -14,6 +14,12 @@ #include LOG_MODULE_REGISTER(drv8424, CONFIG_STEPPER_LOG_LEVEL); +/* Enable and wake up times of the drv84xx stepper controller family. Only after they have elapsed + * are controller output signals guaranteed to be valid. + */ +#define DRV84XX_ENABLE_TIME K_USEC(5) +#define DRV84XX_WAKE_UP_TIME K_USEC(1200) + /** * @brief DRV8424 stepper driver configuration data. * @@ -26,6 +32,7 @@ struct drv8424_config { struct gpio_dt_spec en_pin; struct gpio_dt_spec m0_pin; struct gpio_dt_spec m1_pin; + struct gpio_dt_spec fault_pin; }; /* Struct for storing the states of output pins. */ @@ -37,15 +44,15 @@ struct drv8424_pin_states { }; /** - * @brief DRV8424 stepper driver data. - * - * This structure contains mutable data used by a DRV8424 stepper driver. + * @brief DRV84XX stepper driver data. */ struct drv8424_data { const struct step_dir_stepper_common_data common; + const struct device *dev; bool enabled; struct drv8424_pin_states pin_states; enum stepper_micro_step_resolution ustep_res; + struct gpio_callback fault_cb_data; }; STEP_DIR_STEPPER_STRUCT_CHECK(struct drv8424_config, struct drv8424_data); @@ -172,6 +179,10 @@ static int drv8424_enable(const struct device *dev) { const struct drv8424_config *config = dev->config; struct drv8424_data *data = dev->data; + bool has_enable_pin = config->en_pin.port != NULL; + bool has_sleep_pin = config->sleep_pin.port != NULL; + bool has_fault_pin = config->fault_pin.port != NULL; + k_timeout_t enable_timeout; int ret; ret = drv8424_check_en_sleep_pin(config); @@ -189,6 +200,26 @@ static int drv8424_enable(const struct device *dev) return ret; } + if (has_enable_pin) { + enable_timeout = DRV84XX_ENABLE_TIME; + } + + if (has_sleep_pin) { + enable_timeout = DRV84XX_WAKE_UP_TIME; + } + + if (has_fault_pin) { + /* Wait after enable/wakeup until the fault pin is guaranteed to be in the + * proper state. + */ + k_sleep(enable_timeout); + ret = gpio_add_callback_dt(&config->fault_pin, &data->fault_cb_data); + if (ret != 0) { + LOG_ERR("%s: Failed to add fault callback (error: %d)", dev->name, ret); + return ret; + } + } + data->enabled = true; return ret; @@ -198,6 +229,7 @@ static int drv8424_disable(const struct device *dev) { const struct drv8424_config *config = dev->config; struct drv8424_data *data = dev->data; + bool has_fault_pin = config->fault_pin.port != NULL; int ret; ret = drv8424_check_en_sleep_pin(config); @@ -215,6 +247,14 @@ static int drv8424_disable(const struct device *dev) return ret; } + if (has_fault_pin) { + ret = gpio_remove_callback_dt(&config->fault_pin, &data->fault_cb_data); + if (ret != 0) { + LOG_ERR("%s: Failed to remove fault callback (error: %d)", dev->name, ret); + return ret; + } + } + config->common.timing_source->stop(dev); data->enabled = false; @@ -339,6 +379,13 @@ static int drv8424_run(const struct device *dev, enum stepper_direction directio return step_dir_stepper_common_run(dev, direction); } +void fault_event(const struct device *dev, struct gpio_callback *cb, uint32_t pins) +{ + struct drv8424_data *data = CONTAINER_OF(cb, struct drv8424_data, fault_cb_data); + + stepper_trigger_callback(data->dev, STEPPER_EVENT_FAULT_DETECTED); +} + static int drv8424_init(const struct device *dev) { const struct drv8424_config *const config = dev->config; @@ -392,6 +439,25 @@ static int drv8424_init(const struct device *dev) return ret; } + /* Configure fault pin if it is available */ + if (config->fault_pin.port != NULL) { + ret = gpio_pin_configure_dt(&config->fault_pin, GPIO_INPUT); + if (ret != 0) { + LOG_ERR("%s: Failed to configure fault_pin (error: %d)", dev->name, ret); + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->fault_pin, + GPIO_INT_EDGE_TO_INACTIVE); + if (ret != 0) { + LOG_ERR("Error %d: failed to configure interrupt on %s pin %d", ret, + config->fault_pin.port->name, config->fault_pin.pin); + return ret; + } + + gpio_init_callback(&data->fault_cb_data, fault_event, BIT(config->fault_pin.pin)); + } + return 0; } @@ -419,11 +485,13 @@ static DEVICE_API(stepper, drv8424_stepper_api) = { .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), \ + .fault_pin = GPIO_DT_SPEC_INST_GET_OR(inst, fault_gpios, {0}), \ }; \ \ 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), \ + .dev = DEVICE_DT_GET(DT_INST(inst, DT_DRV_COMPAT)), \ }; \ \ DEVICE_DT_INST_DEFINE(inst, &drv8424_init, NULL, &drv8424_data_##inst, \