Skip to content

Commit 6c5cf91

Browse files
committed
drivers: stepper: introduce stepper event handler
Event handling mechanism was hardcoded in step-dir drivers. This commit refactors the event handling in a dedicated module. Signed-off-by: Jilay Pandya <jilay.pandya@outlook.com>
1 parent 1a2622b commit 6c5cf91

File tree

18 files changed

+217
-24
lines changed

18 files changed

+217
-24
lines changed

drivers/stepper/CMakeLists.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@
33

44
zephyr_syscall_header(${ZEPHYR_BASE}/include/zephyr/drivers/stepper.h)
55

6+
# zephyr-keep-sorted-start
7+
add_subdirectory_ifdef(CONFIG_STEPPER_EVENT_HANDLER event_handler)
8+
add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir)
9+
# zephyr-keep-sorted-stop
10+
611
# zephyr-keep-sorted-start
712
add_subdirectory_ifdef(CONFIG_STEPPER_ADI_TMC adi_tmc)
813
add_subdirectory_ifdef(CONFIG_STEPPER_ALLEGRO allegro)
914
add_subdirectory_ifdef(CONFIG_STEPPER_TI ti)
10-
add_subdirectory_ifdef(CONFIG_STEP_DIR_STEPPER step_dir)
1115
# zephyr-keep-sorted-stop
1216

1317
zephyr_library()

drivers/stepper/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config STEPPER_SHELL
2727
comment "Stepper Driver Common"
2828

2929
rsource "step_dir/Kconfig"
30+
rsource "event_handler/Kconfig"
3031

3132
comment "Stepper Drivers"
3233

drivers/stepper/adi_tmc/tmc22xx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ static DEVICE_API(stepper, tmc22xx_stepper_api) = {
186186
.common = STEP_DIR_STEPPER_DT_INST_COMMON_DATA_INIT(inst), \
187187
.resolution = DT_INST_PROP(inst, micro_step_res), \
188188
}; \
189-
DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \
189+
STEPPER_DEVICE_DT_INST_DEFINE(inst, tmc22xx_stepper_init, NULL, &tmc22xx_data_##inst, \
190190
&tmc22xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
191191
&tmc22xx_stepper_api);
192192

drivers/stepper/adi_tmc/tmc50xx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,8 @@ static void rampstat_work_handler(struct k_work *work)
277277

278278
case TMC5XXX_POS_REACHED_EVENT:
279279
LOG_DBG("RAMPSTAT %s:Position reached", stepper_data->stepper->name);
280-
execute_callback(stepper_data->stepper, STEPPER_EVENT_STEPS_COMPLETED);
280+
stepper_post_event(data->dev, data->callback, STEPPER_EVENT_STOPPED,
281+
data->event_cb_user_data);
281282
break;
282283

283284
case TMC5XXX_STOP_SG_EVENT:

drivers/stepper/allegro/a4979.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ static DEVICE_API(stepper, a4979_stepper_api) = {
296296
.micro_step_res = DT_INST_PROP(inst, micro_step_res), \
297297
}; \
298298
\
299-
DEVICE_DT_INST_DEFINE(inst, a4979_init, NULL, &a4979_data_##inst, &a4979_config_##inst, \
300-
POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, &a4979_stepper_api);
299+
STEPPER_DEVICE_DT_INST_DEFINE(inst, a4979_init, NULL, &a4979_data_##inst, \
300+
&a4979_config_##inst, POST_KERNEL, \
301+
CONFIG_STEPPER_INIT_PRIORITY, &a4979_stepper_api);
301302

302303
DT_INST_FOREACH_STATUS_OKAY(A4979_DEVICE)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
zephyr_library()
5+
6+
zephyr_library_sources(stepper_event_handler.c)
7+
zephyr_linker_sources(DATA_SECTIONS iterables.ld)

drivers/stepper/event_handler/Kconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config STEPPER_EVENT_HANDLER
5+
bool "Stepper event handler"
6+
default y
7+
help
8+
Enable the dispatch of stepper generated events via
9+
a message queue to guarantee that the event handler
10+
code is not run inside of an ISR
11+
12+
config STEPPER_EVENT_HANDLER_QUEUE_LEN
13+
int "Maximum number of pending stepper events"
14+
default 4
15+
depends on STEPPER_EVENT_HANDLER
16+
help
17+
The maximum number of stepper events that can be pending before new events
18+
are dropped.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# iterables.ld
2+
#include <zephyr/linker/iterable_sections.h>
3+
ITERABLE_SECTION_RAM(stepper_event_handler, Z_LINK_ITERABLE_SUBALIGN)
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include <zephyr/init.h>
7+
#include <zephyr/sys/iterable_sections.h>
8+
#include <zephyr/drivers/stepper.h>
9+
#include "stepper_event_handler.h"
10+
11+
#include <zephyr/logging/log.h>
12+
LOG_MODULE_REGISTER(stepper_event_handler, CONFIG_STEPPER_LOG_LEVEL);
13+
14+
int stepper_post_event(const struct device *dev, stepper_event_callback_t cb,
15+
enum stepper_event event, void *user_data)
16+
{
17+
if (cb == NULL) {
18+
LOG_ERR("Callback is NULL for device %s", dev->name);
19+
return -EINVAL;
20+
}
21+
22+
if (!k_is_in_isr()) {
23+
cb(dev, event, user_data);
24+
return 0;
25+
}
26+
27+
STRUCT_SECTION_FOREACH(stepper_event_handler, entry) {
28+
if (entry->dev == dev) {
29+
struct stepper_event_data data = {
30+
.event_cb = cb,
31+
.event = event,
32+
.user_data = user_data,
33+
};
34+
LOG_DBG("Posting event %d for device %s with cb %p", event, dev->name,
35+
data.event_cb);
36+
k_msgq_put(&entry->event_msgq, &data, K_NO_WAIT);
37+
k_work_submit(&entry->event_callback_work);
38+
return 0;
39+
}
40+
}
41+
return -ENODEV;
42+
}
43+
44+
static void stepper_work_event_handler(struct k_work *work)
45+
{
46+
struct stepper_event_handler *entry =
47+
CONTAINER_OF(work, struct stepper_event_handler, event_callback_work);
48+
struct stepper_event_data event_data;
49+
int ret;
50+
51+
LOG_DBG("Starting event handler for device %s", entry->dev->name);
52+
53+
ret = k_msgq_get(&entry->event_msgq, &event_data, K_NO_WAIT);
54+
if (ret != 0) {
55+
return;
56+
}
57+
58+
/* Run the callback */
59+
if (event_data.event_cb != NULL) {
60+
LOG_DBG("Handling event %d for device %s with cb %p", event_data.event,
61+
entry->dev->name, event_data.event_cb);
62+
event_data.event_cb(entry->dev, event_data.event, event_data.user_data);
63+
}
64+
65+
/* If there are more pending events, resubmit this work item to handle them */
66+
if (k_msgq_num_used_get(&entry->event_msgq) > 0) {
67+
k_work_submit(work);
68+
}
69+
}
70+
71+
static int stepper_event_handler_init(void)
72+
{
73+
STRUCT_SECTION_FOREACH(stepper_event_handler, entry) {
74+
k_msgq_init(&entry->event_msgq, entry->event_msgq_buffer,
75+
sizeof(struct stepper_event_data),
76+
CONFIG_STEPPER_EVENT_HANDLER_QUEUE_LEN);
77+
k_work_init(&entry->event_callback_work, stepper_work_event_handler);
78+
}
79+
return 0;
80+
}
81+
82+
SYS_INIT(stepper_event_handler_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* SPDX-FileCopyrightText: Copyright (c) 2025 Jilay Sandeep Pandya
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#ifndef ZEPHYR_DRIVER_STEPPER_STEPPER_EVENT_HANDLER_H_
7+
#define ZEPHYR_DRIVER_STEPPER_STEPPER_EVENT_HANDLER_H_
8+
9+
#include <zephyr/drivers/stepper.h>
10+
11+
/*
12+
* @brief post an event to the stepper event handler
13+
*
14+
* @param dev Pointer to the stepper device
15+
* @param cb Callback function to be called when the event is processed
16+
* @param event The stepper event to post
17+
* @param user_data User data to be passed to the callback function
18+
* @return 0 on success, negative error code on failure
19+
*/
20+
int stepper_post_event(const struct device *dev, stepper_event_callback_t cb,
21+
enum stepper_event event, void *user_data);
22+
23+
#endif /* ZEPHYR_DRIVER_STEPPER_STEPPER_EVENT_HANDLER_H_ */

drivers/stepper/fake_stepper_controller.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ static DEVICE_API(stepper, fake_stepper_driver_api) = {
149149
\
150150
static struct fake_stepper_data fake_stepper_data_##inst; \
151151
\
152-
DEVICE_DT_INST_DEFINE(inst, fake_stepper_init, NULL, &fake_stepper_data_##inst, NULL, \
153-
POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
154-
&fake_stepper_driver_api);
152+
STEPPER_DEVICE_DT_INST_DEFINE(inst, fake_stepper_init, NULL, &fake_stepper_data_##inst, \
153+
NULL, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
154+
&fake_stepper_driver_api);
155155

156156
DT_INST_FOREACH_STATUS_OKAY(FAKE_STEPPER_INIT)

drivers/stepper/gpio_stepper_controller.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <zephyr/drivers/stepper.h>
1313
#include <zephyr/sys/__assert.h>
1414

15+
#include "event_handler/stepper_event_handler.h"
16+
1517
#include <zephyr/logging/log.h>
1618
LOG_MODULE_REGISTER(gpio_stepper_motor_controller, CONFIG_STEPPER_LOG_LEVEL);
1719

@@ -141,10 +143,8 @@ static void position_mode_task(const struct device *dev)
141143
if (data->step_count) {
142144
(void)k_work_reschedule(&data->stepper_dwork, K_NSEC(data->delay_in_ns));
143145
} else {
144-
if (data->callback) {
145-
data->callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED,
146-
data->event_cb_user_data);
147-
}
146+
stepper_post_event(data->dev, data->callback, STEPPER_EVENT_STEPS_COMPLETED,
147+
data->event_cb_user_data);
148148
(void)k_work_cancel_delayable(&data->stepper_dwork);
149149
}
150150
}
@@ -359,7 +359,8 @@ static int gpio_stepper_stop(const struct device *dev)
359359
err = energize_coils(dev, true);
360360

361361
if (data->callback && !err) {
362-
data->callback(data->dev, STEPPER_EVENT_STOPPED, data->event_cb_user_data);
362+
stepper_post_event(data->dev, data->callback, STEPPER_EVENT_STOPPED,
363+
data->event_cb_user_data);
363364
}
364365
}
365366
return err;
@@ -409,7 +410,7 @@ static DEVICE_API(stepper, gpio_stepper_api) = {
409410
}; \
410411
BUILD_ASSERT(DT_INST_PROP(inst, micro_step_res) <= STEPPER_MICRO_STEP_2, \
411412
"gpio_stepper_controller driver supports up to 2 micro steps"); \
412-
DEVICE_DT_INST_DEFINE(inst, gpio_stepper_init, NULL, &gpio_stepper_data_##inst, \
413+
STEPPER_DEVICE_DT_INST_DEFINE(inst, gpio_stepper_init, NULL, &gpio_stepper_data_##inst, \
413414
&gpio_stepper_config_##inst, POST_KERNEL, \
414415
CONFIG_STEPPER_INIT_PRIORITY, &gpio_stepper_api);
415416

drivers/stepper/step_dir/step_dir_stepper_common.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6+
#include "../event_handler/stepper_event_handler.h"
67
#include "step_dir_stepper_common.h"
78

89
#include <zephyr/logging/log.h>
@@ -62,7 +63,7 @@ void stepper_trigger_callback(const struct device *dev, enum stepper_event event
6263
return;
6364
}
6465

65-
data->callback(dev, event, data->event_cb_user_data);
66+
stepper_post_event(dev, data->callback, event, data->event_cb_user_data);
6667
}
6768

6869
static void update_remaining_steps(struct step_dir_stepper_common_data *data)

drivers/stepper/ti/drv84xx.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -508,8 +508,8 @@ static DEVICE_API(stepper, drv84xx_stepper_api) = {
508508
.dev = DEVICE_DT_INST_GET(inst), \
509509
}; \
510510
\
511-
DEVICE_DT_INST_DEFINE(inst, &drv84xx_init, NULL, &drv84xx_data_##inst, \
512-
&drv84xx_config_##inst, POST_KERNEL, CONFIG_STEPPER_INIT_PRIORITY, \
513-
&drv84xx_stepper_api);
511+
STEPPER_DEVICE_DT_INST_DEFINE(inst, &drv84xx_init, NULL, &drv84xx_data_##inst, \
512+
&drv84xx_config_##inst, POST_KERNEL, \
513+
CONFIG_STEPPER_INIT_PRIORITY, &drv84xx_stepper_api);
514514

515515
DT_INST_FOREACH_STATUS_OKAY(DRV84XX_DEVICE)

include/zephyr/drivers/stepper.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,61 @@ static inline int z_impl_stepper_is_moving(const struct device *dev, bool *is_mo
540540
return api->is_moving(dev, is_moving);
541541
}
542542

543+
#ifdef CONFIG_STEPPER_EVENT_HANDLER
544+
545+
/**
546+
* @brief Stepper Event Data
547+
*
548+
* This structure is used to hold the event data for stepper events.
549+
*/
550+
struct stepper_event_data {
551+
enum stepper_event event;
552+
stepper_event_callback_t event_cb;
553+
void *user_data;
554+
};
555+
556+
/**
557+
* @brief Stepper Event Handler
558+
*
559+
* This structure is used to handle stepper events in a queue-based manner.
560+
* It allows for asynchronous handling of stepper events.
561+
*/
562+
struct stepper_event_handler {
563+
const struct device *dev;
564+
struct k_work event_callback_work;
565+
struct k_msgq event_msgq;
566+
uint8_t event_msgq_buffer[CONFIG_STEPPER_EVENT_HANDLER_QUEUE_LEN *
567+
sizeof(struct stepper_event_data)];
568+
};
569+
570+
#define STEPPER_EVENT_HANDLER_INITIALIZER(_dev) \
571+
{ \
572+
.dev = _dev, \
573+
}
574+
575+
#define STEPPER_EVENT_HANDLER_DEFINE(name, ...) \
576+
static const STRUCT_SECTION_ITERABLE(stepper_event_handler, name) = \
577+
STEPPER_EVENT_HANDLER_INITIALIZER(__VA_ARGS__)
578+
579+
#define STEPPER_DT_NAME(node_id) _CONCAT(__stepper_event_handler, DEVICE_DT_NAME_GET(node_id))
580+
581+
#define STEPPER_EVENT_HANDLER_DT_DEFINE(node_id) \
582+
STEPPER_EVENT_HANDLER_DEFINE(STEPPER_DT_NAME(node_id), DEVICE_DT_GET(node_id))
583+
584+
#else
585+
586+
#define STEPPER_EVENT_HANDLER_DT_DEFINE(node_id)
587+
588+
#endif /* CONFIG_STEPPER_EVENT_HANDLER */
589+
590+
#define STEPPER_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, \
591+
api_ptr, ...) \
592+
DEVICE_DT_DEFINE(node_id, init_fn, pm_device, data_ptr, cfg_ptr, level, prio, api_ptr, \
593+
__VA_ARGS__); \
594+
STEPPER_EVENT_HANDLER_DT_DEFINE(node_id);
595+
596+
#define STEPPER_DEVICE_DT_INST_DEFINE(inst, ...) \
597+
STEPPER_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__)
543598
/**
544599
* @}
545600
*/

samples/drivers/stepper/generic/src/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ static void stepper_callback(const struct device *dev, const enum stepper_event
3636
{
3737
switch (event) {
3838
case STEPPER_EVENT_STEPS_COMPLETED:
39+
LOG_DBG("Steps completed for device %s", dev->name);
3940
k_sem_give(&stepper_generic_sem);
4041
break;
4142
default:

tests/drivers/stepper/shell/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
cmake_minimum_required(VERSION 3.20.0)
44
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5-
project(can_shell)
5+
project(stepper_shell)
66

77
FILE(GLOB app_sources src/*.c)
88
target_sources(app PRIVATE ${app_sources})

tests/drivers/stepper/shell/testcase.yaml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,3 @@ tests:
88
drivers.stepper.shell:
99
platform_allow:
1010
- native_sim
11-
- native_sim/native/64
12-
drivers.stepper.shell_async:
13-
platform_allow:
14-
- native_sim
15-
- native_sim/native/64

0 commit comments

Comments
 (0)