diff --git a/drivers/stepper/CMakeLists.txt b/drivers/stepper/CMakeLists.txt index 1cda468fac48..a067f12d8493 100644 --- a/drivers/stepper/CMakeLists.txt +++ b/drivers/stepper/CMakeLists.txt @@ -3,11 +3,15 @@ zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h) +# zephyr-keep-sorted-start +add_subdirectory_ifdef(CONFIG_STEPPER_EVENT_HANDLER event_handler) +add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir) +# zephyr-keep-sorted-stop + # zephyr-keep-sorted-start add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc) add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro) add_subdirectory_ifdef(CONFIG_STEPPER_TI ti) -add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir) # zephyr-keep-sorted-stop zephyr_library() diff --git a/drivers/stepper/Kconfig b/drivers/stepper/Kconfig index 075c9130e33f..725a63cc7344 100644 --- a/drivers/stepper/Kconfig +++ b/drivers/stepper/Kconfig @@ -27,6 +27,7 @@ config STEPPER_SHELL comment "Stepper Driver Common" rsource "step_dir/Kconfig" +rsource "event_handler/Kconfig" comment "Stepper Drivers" diff --git a/drivers/stepper/Kconfig.stepper_event_template b/drivers/stepper/Kconfig.stepper_event_template deleted file mode 100644 index fb29a1e91e0e..000000000000 --- a/drivers/stepper/Kconfig.stepper_event_template +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2024 Fabian Blatz -# SPDX-License-Identifier: Apache-2.0 - -config STEPPER_$(module)_GENERATE_ISR_SAFE_EVENTS - bool "$(module-str) guarantee non ISR callbacks upon stepper events" - help - Enable the dispatch of stepper generated events via - a message queue to guarantee that the event handler - code is not run inside of an ISR. Can be disabled, but - then registered stepper event callback must be ISR safe. - -config STEPPER_$(module)_EVENT_QUEUE_LEN - int "$(module-str) maximum number of pending stepper events" - default 4 - depends on STEPPER_$(module)_GENERATE_ISR_SAFE_EVENTS - help - The maximum number of stepper events that can be pending before new events - are dropped. diff --git a/drivers/stepper/adi_tmc/tmc22xx.c b/drivers/stepper/adi_tmc/tmc22xx.c index fb73dc35fc28..1a05bf1cec0d 100644 --- a/drivers/stepper/adi_tmc/tmc22xx.c +++ b/drivers/stepper/adi_tmc/tmc22xx.c @@ -186,7 +186,7 @@ static DEVICE_API(stepper, tmc22xx_stepper_api) = { .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, \ + STEPPER_DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \ &tmc22xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \ &tmc22xx_stepper_api); diff --git a/drivers/stepper/adi_tmc/tmc50xx.c b/drivers/stepper/adi_tmc/tmc50xx.c index b9eaafa70be9..e35e160bcb42 100644 --- a/drivers/stepper/adi_tmc/tmc50xx.c +++ b/drivers/stepper/adi_tmc/tmc50xx.c @@ -14,6 +14,7 @@ #include "adi_tmc_spi.h" #include "adi_tmc5xxx_common.h" +#include #include LOG_MODULE_REGISTER(tmc50xx, CONFIG_STEPPER_LOG_LEVEL); @@ -175,18 +176,6 @@ static void stallguard_work_handler(struct k_work *work) } } - -static void execute_callback(const struct device *dev, const enum stepper_event event) -{ - struct tmc50xx_stepper_data *data = dev->data; - - if (!data->callback) { - LOG_WRN_ONCE("No callback registered"); - return; - } - data->callback(dev, event, data->event_cb_user_data); -} - #ifdef CONFIG_STEPPER_ADI_TMC50XX_RAMPSTAT_POLL_STALLGUARD_LOG static void log_stallguard(struct tmc50xx_stepper_data *stepper_data, const uint32_t drv_status) @@ -204,8 +193,8 @@ static void log_stallguard(struct tmc50xx_stepper_data *stepper_data, const uint const uint8_t sg_result = FIELD_GET(TMC5XXX_DRV_STATUS_SG_RESULT_MASK, drv_status); const bool sg_status = FIELD_GET(TMC5XXX_DRV_STATUS_SG_STATUS_MASK, drv_status); - LOG_DBG("%s position: %d | sg result: %3d status: %d", - stepper_data->stepper->name, position, sg_result, sg_status); + LOG_DBG("%s position: %d | sg result: %3d status: %d", stepper_data->stepper->name, + position, sg_result, sg_status); } #endif @@ -213,7 +202,7 @@ static void log_stallguard(struct tmc50xx_stepper_data *stepper_data, const uint static void rampstat_work_reschedule(struct k_work_delayable *rampstat_callback_dwork) { k_work_reschedule(rampstat_callback_dwork, - K_MSEC(CONFIG_STEPPER_ADI_TMC50XX_RAMPSTAT_POLL_INTERVAL_IN_MSEC)); + K_MSEC(CONFIG_STEPPER_ADI_TMC50XX_RAMPSTAT_POLL_INTERVAL_IN_MSEC)); } static void rampstat_work_handler(struct k_work *work) @@ -265,25 +254,31 @@ static void rampstat_work_handler(struct k_work *work) case TMC5XXX_STOP_LEFT_EVENT: LOG_DBG("RAMPSTAT %s:Left end-stop detected", stepper_data->stepper->name); - execute_callback(stepper_data->stepper, - STEPPER_EVENT_LEFT_END_STOP_DETECTED); + stepper_post_event(stepper_data->stepper, stepper_data->callback, + STEPPER_EVENT_LEFT_END_STOP_DETECTED, + stepper_data->event_cb_user_data); break; case TMC5XXX_STOP_RIGHT_EVENT: LOG_DBG("RAMPSTAT %s:Right end-stop detected", stepper_data->stepper->name); - execute_callback(stepper_data->stepper, - STEPPER_EVENT_RIGHT_END_STOP_DETECTED); + stepper_post_event(stepper_data->stepper, stepper_data->callback, + STEPPER_EVENT_RIGHT_END_STOP_DETECTED, + stepper_data->event_cb_user_data); break; case TMC5XXX_POS_REACHED_EVENT: LOG_DBG("RAMPSTAT %s:Position reached", stepper_data->stepper->name); - execute_callback(stepper_data->stepper, STEPPER_EVENT_STEPS_COMPLETED); + stepper_post_event(stepper_data->stepper, stepper_data->callback, + STEPPER_EVENT_STEPS_COMPLETED, + stepper_data->event_cb_user_data); break; case TMC5XXX_STOP_SG_EVENT: LOG_DBG("RAMPSTAT %s:Stall detected", stepper_data->stepper->name); stallguard_enable(stepper_data->stepper, false); - execute_callback(stepper_data->stepper, STEPPER_EVENT_STALL_DETECTED); + stepper_post_event(stepper_data->stepper, stepper_data->callback, + STEPPER_EVENT_STALL_DETECTED, + stepper_data->event_cb_user_data); break; default: LOG_ERR("Illegal ramp stat bit field"); @@ -733,10 +728,10 @@ static DEVICE_API(stepper, tmc50xx_stepper_api) = { static struct tmc50xx_stepper_data tmc50xx_stepper_data_##child = { \ .stepper = DEVICE_DT_GET(child),}; -#define TMC50XX_STEPPER_DEFINE(child) \ - DEVICE_DT_DEFINE(child, tmc50xx_stepper_init, NULL, &tmc50xx_stepper_data_##child, \ - &tmc50xx_stepper_config_##child, POST_KERNEL, \ - CONFIG_STEPPER_INIT_PRIORITY, &tmc50xx_stepper_api); +#define TMC50XX_STEPPER_DEFINE(child) \ + STEPPER_DEVICE_DT_DEFINE(child, tmc50xx_stepper_init, NULL, &tmc50xx_stepper_data_##child, \ + &tmc50xx_stepper_config_##child, POST_KERNEL, \ + CONFIG_STEPPER_INIT_PRIORITY, &tmc50xx_stepper_api); #define TMC50XX_DEFINE(inst) \ BUILD_ASSERT(DT_INST_CHILD_NUM(inst) <= 2, "tmc50xx can drive two steppers at max"); \ diff --git a/drivers/stepper/allegro/a4979.c b/drivers/stepper/allegro/a4979.c index f08dbd61d37b..7619fed3daaf 100644 --- a/drivers/stepper/allegro/a4979.c +++ b/drivers/stepper/allegro/a4979.c @@ -296,7 +296,8 @@ static DEVICE_API(stepper, a4979_stepper_api) = { .micro_step_res = DT_INST_PROP(inst, micro_step_res), \ }; \ \ - DEVICE_DT_INST_DEFINE(inst, a4979_init, NULL, &a4979_data_##inst, &a4979_config_##inst, \ - POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, &a4979_stepper_api); + STEPPER_DEVICE_DT_INST_DEFINE(inst, a4979_init, NULL, &a4979_data_##inst, \ + &a4979_config_##inst, POST_KERNEL, \ + CONFIG_STEPPER_INIT_PRIORITY, &a4979_stepper_api); DT_INST_FOREACH_STATUS_OKAY(A4979_DEVICE) diff --git a/drivers/stepper/event_handler/CMakeLists.txt b/drivers/stepper/event_handler/CMakeLists.txt new file mode 100644 index 000000000000..a1f8d6572e71 --- /dev/null +++ b/drivers/stepper/event_handler/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(stepper_event_handler.c) +zephyr_linker_sources(DATA_SECTIONS iterables.ld) diff --git a/drivers/stepper/event_handler/Kconfig b/drivers/stepper/event_handler/Kconfig new file mode 100644 index 000000000000..8067c0c09a23 --- /dev/null +++ b/drivers/stepper/event_handler/Kconfig @@ -0,0 +1,18 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya +# SPDX-License-Identifier: Apache-2.0 + +config STEPPER_EVENT_HANDLER + bool "Stepper event handler" + default y + help + Enable the dispatch of stepper generated events via + a message queue to guarantee that the event handler + code is not run inside of an ISR + +config STEPPER_EVENT_HANDLER_QUEUE_LEN + int "Maximum number of pending stepper events" + default 4 + depends on STEPPER_EVENT_HANDLER + help + The maximum number of stepper events that can be pending before new events + are dropped. diff --git a/drivers/stepper/event_handler/iterables.ld b/drivers/stepper/event_handler/iterables.ld new file mode 100644 index 000000000000..ff385791f02a --- /dev/null +++ b/drivers/stepper/event_handler/iterables.ld @@ -0,0 +1,3 @@ +# iterables.ld +#include +ITERABLE_SECTION_RAM(stepper_event_handler, Z_LINK_ITERABLE_SUBALIGN) diff --git a/drivers/stepper/event_handler/stepper_event_handler.c b/drivers/stepper/event_handler/stepper_event_handler.c new file mode 100644 index 000000000000..8dd10c1d476a --- /dev/null +++ b/drivers/stepper/event_handler/stepper_event_handler.c @@ -0,0 +1,82 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(stepper_event_handler, CONFIG_STEPPER_LOG_LEVEL); + +int stepper_post_event(const struct device *dev, stepper_event_callback_t cb, + enum stepper_event event, void *user_data) +{ + if (cb == NULL) { + LOG_ERR("Callback is NULL for device %s", dev->name); + return -EINVAL; + } + + if (!k_is_in_isr()) { + cb(dev, event, user_data); + return 0; + } + + STRUCT_SECTION_FOREACH(stepper_event_handler, entry) { + if (entry->dev == dev) { + struct stepper_event_data data = { + .event_cb = cb, + .event = event, + .user_data = user_data, + }; + LOG_DBG("Posting event %d for device %s with cb %p", event, dev->name, + data.event_cb); + k_msgq_put(&entry->event_msgq, &data, K_NO_WAIT); + k_work_submit(&entry->event_callback_work); + return 0; + } + } + return -ENODEV; +} + +static void stepper_work_event_handler(struct k_work *work) +{ + struct stepper_event_handler *entry = + CONTAINER_OF(work, struct stepper_event_handler, event_callback_work); + struct stepper_event_data event_data; + int ret; + + LOG_DBG("Starting event handler for device %s", entry->dev->name); + + ret = k_msgq_get(&entry->event_msgq, &event_data, K_NO_WAIT); + if (ret != 0) { + return; + } + + /* Run the callback */ + if (event_data.event_cb != NULL) { + LOG_DBG("Handling event %d for device %s with cb %p", event_data.event, + entry->dev->name, event_data.event_cb); + event_data.event_cb(entry->dev, event_data.event, event_data.user_data); + } + + /* If there are more pending events, resubmit this work item to handle them */ + if (k_msgq_num_used_get(&entry->event_msgq) > 0) { + k_work_submit(work); + } +} + +static int stepper_event_handler_init(void) +{ + STRUCT_SECTION_FOREACH(stepper_event_handler, entry) { + k_msgq_init(&entry->event_msgq, entry->event_msgq_buffer, + sizeof(struct stepper_event_data), + CONFIG_STEPPER_EVENT_HANDLER_QUEUE_LEN); + k_work_init(&entry->event_callback_work, stepper_work_event_handler); + } + return 0; +} + +SYS_INIT(stepper_event_handler_init, APPLICATION, CONFIG_STEPPER_INIT_PRIORITY); diff --git a/drivers/stepper/fake_stepper_controller.c b/drivers/stepper/fake_stepper_controller.c index 3abce9726c50..d76bd8482d87 100644 --- a/drivers/stepper/fake_stepper_controller.c +++ b/drivers/stepper/fake_stepper_controller.c @@ -149,8 +149,8 @@ static DEVICE_API(stepper, fake_stepper_driver_api) = { \ static struct fake_stepper_data fake_stepper_data_##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, fake_stepper_init, NULL, &fake_stepper_data_##inst, NULL, \ - POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \ - &fake_stepper_driver_api); + STEPPER_DEVICE_DT_INST_DEFINE(inst, fake_stepper_init, NULL, &fake_stepper_data_##inst, \ + NULL, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \ + &fake_stepper_driver_api); DT_INST_FOREACH_STATUS_OKAY(FAKE_STEPPER_INIT) diff --git a/drivers/stepper/gpio_stepper_controller.c b/drivers/stepper/gpio_stepper_controller.c index 331d2413ec1d..47cbd7152e99 100644 --- a/drivers/stepper/gpio_stepper_controller.c +++ b/drivers/stepper/gpio_stepper_controller.c @@ -12,6 +12,8 @@ #include #include +#include + #include LOG_MODULE_REGISTER(gpio_stepper_motor_controller, CONFIG_STEPPER_LOG_LEVEL); @@ -141,10 +143,8 @@ static void position_mode_task(const struct device *dev) if (data->step_count) { (void)k_work_reschedule(&data->stepper_dwork, K_NSEC(data->delay_in_ns)); } else { - if (data->callback) { - data->callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED, - data->event_cb_user_data); - } + stepper_post_event(data->dev, data->callback, STEPPER_EVENT_STEPS_COMPLETED, + data->event_cb_user_data); (void)k_work_cancel_delayable(&data->stepper_dwork); } } @@ -359,7 +359,8 @@ static int gpio_stepper_stop(const struct device *dev) err = energize_coils(dev, true); if (data->callback && !err) { - data->callback(data->dev, STEPPER_EVENT_STOPPED, data->event_cb_user_data); + stepper_post_event(data->dev, data->callback, STEPPER_EVENT_STOPPED, + data->event_cb_user_data); } } return err; @@ -409,7 +410,7 @@ static DEVICE_API(stepper, gpio_stepper_api) = { }; \ BUILD_ASSERT(DT_INST_PROP(inst, micro_step_res) <= STEPPER_MICRO_STEP_2, \ "gpio_stepper_controller driver supports up to 2 micro steps"); \ - DEVICE_DT_INST_DEFINE(inst, gpio_stepper_init, NULL, &gpio_stepper_data_##inst, \ + STEPPER_DEVICE_DT_INST_DEFINE(inst, gpio_stepper_init, NULL, &gpio_stepper_data_##inst, \ &gpio_stepper_config_##inst, POST_KERNEL, \ CONFIG_STEPPER_INIT_PRIORITY, &gpio_stepper_api); diff --git a/drivers/stepper/step_dir/Kconfig b/drivers/stepper/step_dir/Kconfig index d8629c649ffd..ce6b184eb278 100644 --- a/drivers/stepper/step_dir/Kconfig +++ b/drivers/stepper/step_dir/Kconfig @@ -15,8 +15,4 @@ config STEP_DIR_STEPPER_COUNTER_TIMING help Enable usage of a counter device for accurate stepping. -module = STEP_DIR -module-str = step_dir -rsource "../Kconfig.stepper_event_template" - endif # STEP_DIR_STEPPER diff --git a/drivers/stepper/step_dir/step_dir_stepper_common.c b/drivers/stepper/step_dir/step_dir_stepper_common.c index b6b7566f07fb..faad2c2e4a88 100644 --- a/drivers/stepper/step_dir/step_dir_stepper_common.c +++ b/drivers/stepper/step_dir/step_dir_stepper_common.c @@ -5,6 +5,7 @@ #include "step_dir_stepper_common.h" +#include #include LOG_MODULE_REGISTER(step_dir_stepper, CONFIG_STEPPER_LOG_LEVEL); @@ -62,52 +63,8 @@ void stepper_trigger_callback(const struct device *dev, enum stepper_event event return; } - if (!k_is_in_isr()) { - data->callback(dev, event, data->event_cb_user_data); - return; - } - -#ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS - /* Dispatch to msgq instead of raising directly */ - int ret = k_msgq_put(&data->event_msgq, &event, K_NO_WAIT); - - if (ret != 0) { - LOG_WRN("Failed to put event in msgq: %d", ret); - } - - ret = k_work_submit(&data->event_callback_work); - if (ret < 0) { - LOG_ERR("Failed to submit work item: %d", ret); - } -#else - LOG_WRN_ONCE("Event callback called from ISR context without ISR safe events enabled"); -#endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */ -} - -#ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS -static void stepper_work_event_handler(struct k_work *work) -{ - struct step_dir_stepper_common_data *data = - CONTAINER_OF(work, struct step_dir_stepper_common_data, event_callback_work); - enum stepper_event event; - int ret; - - ret = k_msgq_get(&data->event_msgq, &event, K_NO_WAIT); - if (ret != 0) { - return; - } - - /* Run the callback */ - if (data->callback != NULL) { - data->callback(data->dev, event, data->event_cb_user_data); - } - - /* If there are more pending events, resubmit this work item to handle them */ - if (k_msgq_num_used_get(&data->event_msgq) > 0) { - k_work_submit(work); - } + stepper_post_event(dev, data->callback, event, data->event_cb_user_data); } -#endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */ static void update_remaining_steps(struct step_dir_stepper_common_data *data) { @@ -212,14 +169,6 @@ int step_dir_stepper_common_init(const struct device *dev) } } -#ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS - struct step_dir_stepper_common_data *data = dev->data; - - k_msgq_init(&data->event_msgq, data->event_msgq_buffer, sizeof(enum stepper_event), - CONFIG_STEPPER_STEP_DIR_EVENT_QUEUE_LEN); - k_work_init(&data->event_callback_work, stepper_work_event_handler); -#endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */ - return 0; } diff --git a/drivers/stepper/step_dir/step_dir_stepper_common.h b/drivers/stepper/step_dir/step_dir_stepper_common.h index b345cf5d68a5..e33a37480c15 100644 --- a/drivers/stepper/step_dir/step_dir_stepper_common.h +++ b/drivers/stepper/step_dir/step_dir_stepper_common.h @@ -83,13 +83,6 @@ struct step_dir_stepper_common_data { struct counter_top_cfg counter_top_cfg; bool counter_running; #endif /* CONFIG_STEP_DIR_STEPPER_COUNTER_TIMING */ - -#ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS - struct k_work event_callback_work; - struct k_msgq event_msgq; - uint8_t event_msgq_buffer[CONFIG_STEPPER_STEP_DIR_EVENT_QUEUE_LEN * - sizeof(enum stepper_event)]; -#endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */ }; /** diff --git a/drivers/stepper/ti/Kconfig.drv84xx b/drivers/stepper/ti/Kconfig.drv84xx index e5466890c66d..10cdd06433ee 100644 --- a/drivers/stepper/ti/Kconfig.drv84xx +++ b/drivers/stepper/ti/Kconfig.drv84xx @@ -7,6 +7,5 @@ config DRV84XX depends on DT_HAS_TI_DRV84XX_ENABLED select STEPPER_TI select STEP_DIR_STEPPER - select STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS help Enable driver for TI DRV84XX stepper motor driver. diff --git a/drivers/stepper/ti/drv84xx.c b/drivers/stepper/ti/drv84xx.c index cc4a8651e8aa..e6d84009fddf 100644 --- a/drivers/stepper/ti/drv84xx.c +++ b/drivers/stepper/ti/drv84xx.c @@ -508,8 +508,8 @@ static DEVICE_API(stepper, drv84xx_stepper_api) = { .dev = DEVICE_DT_INST_GET(inst), \ }; \ \ - DEVICE_DT_INST_DEFINE(inst, &drv84xx_init, NULL, &drv84xx_data_##inst, \ - &drv84xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \ - &drv84xx_stepper_api); + STEPPER_DEVICE_DT_INST_DEFINE(inst, &drv84xx_init, NULL, &drv84xx_data_##inst, \ + &drv84xx_config_##inst, POST_KERNEL, \ + CONFIG_STEPPER_INIT_PRIORITY, &drv84xx_stepper_api); DT_INST_FOREACH_STATUS_OKAY(DRV84XX_DEVICE) diff --git a/include/zephyr/drivers/stepper.h b/include/zephyr/drivers/stepper.h index 16632e2579ff..19d9a5b2082f 100644 --- a/include/zephyr/drivers/stepper.h +++ b/include/zephyr/drivers/stepper.h @@ -21,9 +21,11 @@ * @{ */ +#include + #include #include -#include +#include #ifdef __cplusplus extern "C" { @@ -540,6 +542,61 @@ static inline int z_impl_stepper_is_moving(const struct device *dev, bool *is_mo return api->is_moving(dev, is_moving); } +#ifdef CONFIG_STEPPER_EVENT_HANDLER + +/** + * @brief Stepper Event Data + * + * This structure is used to hold the event data for stepper events. + */ +struct stepper_event_data { + enum stepper_event event; + stepper_event_callback_t event_cb; + void *user_data; +}; + +/** + * @brief Stepper Event Handler + * + * This structure is used to handle stepper events in a queue-based manner. + * It allows for asynchronous handling of stepper events. + */ +struct stepper_event_handler { + const struct device *dev; + struct k_work event_callback_work; + struct k_msgq event_msgq; + uint8_t event_msgq_buffer[CONFIG_STEPPER_EVENT_HANDLER_QUEUE_LEN * + sizeof(struct stepper_event_data)]; +}; + +#define STEPPER_EVENT_HANDLER_INITIALIZER(_dev) \ + { \ + .dev = _dev, \ + } + +#define STEPPER_EVENT_HANDLER_DEFINE(name, ...) \ + static const STRUCT_SECTION_ITERABLE(stepper_event_handler, name) = \ + STEPPER_EVENT_HANDLER_INITIALIZER(__VA_ARGS__) + +#define STEPPER_DT_NAME(node_id) _CONCAT(__stepper_event_handler, DEVICE_DT_NAME_GET(node_id)) + +#define STEPPER_EVENT_HANDLER_DT_DEFINE(node_id) \ + STEPPER_EVENT_HANDLER_DEFINE(STEPPER_DT_NAME(node_id), DEVICE_DT_GET(node_id)) + +#else + +#define STEPPER_EVENT_HANDLER_DT_DEFINE(node_id) + +#endif /* CONFIG_STEPPER_EVENT_HANDLER */ + +#define STEPPER_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, \ + api_ptr, ...) \ + DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, api_ptr, \ + __VA_ARGS__); \ + STEPPER_EVENT_HANDLER_DT_DEFINE(node_id); + +#define STEPPER_DEVICE_DT_INST_DEFINE(inst, ...) \ + STEPPER_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) /** * @} */ diff --git a/include/zephyr/drivers/stepper/stepper_event_handler.h b/include/zephyr/drivers/stepper/stepper_event_handler.h new file mode 100644 index 000000000000..db6d84307002 --- /dev/null +++ b/include/zephyr/drivers/stepper/stepper_event_handler.h @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_EVENT_HANDLER_H_ +#define ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_EVENT_HANDLER_H_ + +#include + +#ifdef CONFIG_STEPPER_EVENT_HANDLER + +/* + * @brief post an event to the stepper event handler + * + * @param dev Pointer to the stepper device + * @param cb Callback function to be called when the event is processed + * @param event The stepper event to post + * @param user_data User data to be passed to the callback function + * @return 0 on success, negative error code on failure + */ +int stepper_post_event(const struct device *dev, stepper_event_callback_t cb, + enum stepper_event event, void *user_data); + +#else + +/** + * @brief Execute the stepper event handler callback directly if the event handler is not enabled + * + * @param dev Pointer to the stepper device + * @param cb Callback function to be called when the event is processed + * @param event The stepper event to post + * @param user_data User data to be passed to the callback function + * @return 0 on success, negative error code on failure + */ +static inline int stepper_post_event(const struct device *dev, stepper_event_callback_t cb, + enum stepper_event event, void *user_data) +{ + if (cb == NULL) { + return -EINVAL; + } + cb(dev, event, user_data); + return 0; +} + +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_STEPPER_STEPPER_EVENT_HANDLER_H_ */ diff --git a/samples/drivers/stepper/generic/src/main.c b/samples/drivers/stepper/generic/src/main.c index f1323e50850a..cdae1ae3445f 100644 --- a/samples/drivers/stepper/generic/src/main.c +++ b/samples/drivers/stepper/generic/src/main.c @@ -36,6 +36,7 @@ static void stepper_callback(const struct device *dev, const enum stepper_event { switch (event) { case STEPPER_EVENT_STEPS_COMPLETED: + LOG_DBG("Steps completed for device %s", dev->name); k_sem_give(&stepper_generic_sem); break; default: diff --git a/tests/drivers/stepper/drv84xx/api/boards/native_sim.overlay b/tests/drivers/stepper/drv84xx/api/app.overlay similarity index 100% rename from tests/drivers/stepper/drv84xx/api/boards/native_sim.overlay rename to tests/drivers/stepper/drv84xx/api/app.overlay diff --git a/tests/drivers/stepper/drv84xx/api/testcase.yaml b/tests/drivers/stepper/drv84xx/api/testcase.yaml index ef3e866c983f..eb3543ddeb4a 100644 --- a/tests/drivers/stepper/drv84xx/api/testcase.yaml +++ b/tests/drivers/stepper/drv84xx/api/testcase.yaml @@ -9,4 +9,4 @@ tests: - api - drv84xx platform_allow: - - native_sim + - native_sim/native/64 diff --git a/tests/drivers/stepper/drv84xx/emul/boards/native_sim.overlay b/tests/drivers/stepper/drv84xx/emul/app.overlay similarity index 100% rename from tests/drivers/stepper/drv84xx/emul/boards/native_sim.overlay rename to tests/drivers/stepper/drv84xx/emul/app.overlay diff --git a/tests/drivers/stepper/drv84xx/emul/testcase.yaml b/tests/drivers/stepper/drv84xx/emul/testcase.yaml index 5ea422718caa..abb727145573 100644 --- a/tests/drivers/stepper/drv84xx/emul/testcase.yaml +++ b/tests/drivers/stepper/drv84xx/emul/testcase.yaml @@ -8,4 +8,4 @@ tests: - stepper - drv84xx platform_allow: - - native_sim + - native_sim/native/64 diff --git a/tests/drivers/stepper/shell/CMakeLists.txt b/tests/drivers/stepper/shell/CMakeLists.txt index 7a7892c68da6..7afca16e6238 100644 --- a/tests/drivers/stepper/shell/CMakeLists.txt +++ b/tests/drivers/stepper/shell/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(can_shell) +project(stepper_shell) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/tests/drivers/stepper/shell/testcase.yaml b/tests/drivers/stepper/shell/testcase.yaml index 4a7dbd352435..a97377b60876 100644 --- a/tests/drivers/stepper/shell/testcase.yaml +++ b/tests/drivers/stepper/shell/testcase.yaml @@ -7,9 +7,4 @@ common: tests: drivers.stepper.shell: platform_allow: - - native_sim - - native_sim/native/64 - drivers.stepper.shell_async: - platform_allow: - - native_sim - native_sim/native/64 diff --git a/tests/drivers/stepper/stepper_api/testcase.yaml b/tests/drivers/stepper/stepper_api/testcase.yaml index bf07964f0743..503b00399504 100644 --- a/tests/drivers/stepper/stepper_api/testcase.yaml +++ b/tests/drivers/stepper/stepper_api/testcase.yaml @@ -13,7 +13,6 @@ tests: extra_configs: - CONFIG_GPIO=y - CONFIG_COUNTER=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y platform_allow: - native_sim/native/64 drivers.stepper.stepper_api.adi_tmc2209_work_q: @@ -21,7 +20,6 @@ tests: - platform:native_sim/native/64:DTC_OVERLAY_FILE="boards/native_sim_adi_tmc2209_work_q.overlay" extra_configs: - CONFIG_GPIO=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y - CONFIG_STEPPER_TEST_TIMING_TIMEOUT_TOLERANCE_PCT=30 platform_allow: - native_sim/native/64 @@ -31,7 +29,6 @@ tests: extra_configs: - CONFIG_GPIO=y - CONFIG_COUNTER=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y platform_allow: - native_sim/native/64 drivers.stepper.stepper_api.allegro_a4979_work_q: @@ -39,7 +36,6 @@ tests: - platform:native_sim/native/64:DTC_OVERLAY_FILE="boards/native_sim_allegro_a4979_work_q.overlay" extra_configs: - CONFIG_GPIO=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y - CONFIG_STEPPER_TEST_TIMING_TIMEOUT_TOLERANCE_PCT=30 platform_allow: - native_sim/native/64 @@ -49,7 +45,6 @@ tests: extra_configs: - CONFIG_GPIO=y - CONFIG_COUNTER=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y platform_allow: - native_sim/native/64 drivers.stepper.stepper_api.ti_drv84xx_work_q: @@ -57,7 +52,6 @@ tests: - platform:native_sim/native/64:DTC_OVERLAY_FILE="boards/native_sim_ti_drv84xx_work_q.overlay" extra_configs: - CONFIG_GPIO=y - - CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS=y - CONFIG_STEPPER_TEST_TIMING_TIMEOUT_TOLERANCE_PCT=30 platform_allow: - native_sim/native/64 @@ -67,6 +61,7 @@ tests: - platform:qemu_x86_64/atom:DTC_OVERLAY_FILE="boards/qemu_x86_64_zephyr_gpio_stepper.overlay" extra_configs: - CONFIG_GPIO=y + - CONFIG_STEPPER_EVENT_HANDLER=n platform_allow: - native_sim/native/64 - qemu_x86_64/atom