Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions drivers/stepper/h_bridge_stepper.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,15 @@ static int h_bridge_stepper_move_by(const struct device *dev, int32_t micro_step
LOG_ERR("Step interval not set or invalid step interval set");
return -EINVAL;
}

if (micro_steps == 0) {
(void)k_work_cancel_delayable(&data->stepper_dwork);
if (data->callback) {
data->callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED,
data->event_cb_user_data);
}
return 0;
}
K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_POSITION;
data->step_count = micro_steps;
Expand Down
84 changes: 38 additions & 46 deletions drivers/stepper/step_dir/step_dir_stepper_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ LOG_MODULE_REGISTER(step_dir_stepper, CONFIG_STEPPER_LOG_LEVEL);
static inline int step_dir_stepper_perform_step(const struct device *dev)
{
const struct step_dir_stepper_common_config *config = dev->config;
struct step_dir_stepper_common_data *data = dev->data;
int ret;

ret = gpio_pin_toggle_dt(&config->step_pin);
Expand All @@ -28,12 +27,6 @@ static inline int step_dir_stepper_perform_step(const struct device *dev)
}
}

if (data->direction == STEPPER_DIRECTION_POSITIVE) {
data->actual_position++;
} else {
data->actual_position--;
}

return 0;
}

Expand Down Expand Up @@ -120,25 +113,20 @@ static void stepper_work_event_handler(struct k_work *work)

static void update_remaining_steps(struct step_dir_stepper_common_data *data)
{
const struct step_dir_stepper_common_config *config = data->dev->config;

if (data->step_count > 0) {
data->step_count--;
} else if (data->step_count < 0) {
data->step_count++;
} else {
stepper_trigger_callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED);
config->timing_source->stop(data->dev);
if (atomic_get(&data->step_count) > 0) {
atomic_dec(&data->step_count);
} else if (atomic_get(&data->step_count) < 0) {
atomic_inc(&data->step_count);
}
}

static void update_direction_from_step_count(const struct device *dev)
{
struct step_dir_stepper_common_data *data = dev->data;

if (data->step_count > 0) {
if (atomic_get(&data->step_count) > 0) {
data->direction = STEPPER_DIRECTION_POSITIVE;
} else if (data->step_count < 0) {
} else if (atomic_get(&data->step_count) < 0) {
data->direction = STEPPER_DIRECTION_NEGATIVE;
} else {
LOG_ERR("Step count is zero");
Expand All @@ -150,23 +138,20 @@ static void position_mode_task(const struct device *dev)
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;

if (data->step_count) {
(void)step_dir_stepper_perform_step(dev);
}
update_remaining_steps(dev->data);

if (config->timing_source->needs_reschedule(dev) && data->step_count != 0) {
if (config->timing_source->needs_reschedule(dev) && atomic_get(&data->step_count) != 0) {
(void)config->timing_source->start(dev);
} else if (atomic_get(&data->step_count) == 0) {
stepper_trigger_callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED);
config->timing_source->stop(data->dev);
}

update_remaining_steps(dev->data);
}

static void velocity_mode_task(const struct device *dev)
{
const struct step_dir_stepper_common_config *config = dev->config;

(void)step_dir_stepper_perform_step(dev);

if (config->timing_source->needs_reschedule(dev)) {
(void)config->timing_source->start(dev);
}
Expand All @@ -176,18 +161,23 @@ void stepper_handle_timing_signal(const struct device *dev)
{
struct step_dir_stepper_common_data *data = dev->data;

K_SPINLOCK(&data->lock) {
switch (data->run_mode) {
case STEPPER_RUN_MODE_POSITION:
position_mode_task(dev);
break;
case STEPPER_RUN_MODE_VELOCITY:
velocity_mode_task(dev);
break;
default:
LOG_WRN("Unsupported run mode: %d", data->run_mode);
break;
}
(void)step_dir_stepper_perform_step(dev);
if (data->direction == STEPPER_DIRECTION_POSITIVE) {
atomic_inc(&data->actual_position);
} else {
atomic_dec(&data->actual_position);
}

switch (data->run_mode) {
case STEPPER_RUN_MODE_POSITION:
position_mode_task(dev);
break;
case STEPPER_RUN_MODE_VELOCITY:
velocity_mode_task(dev);
break;
default:
LOG_WRN("Unsupported run mode: %d", data->run_mode);
break;
}
}

Expand Down Expand Up @@ -243,9 +233,15 @@ int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micr
return -EINVAL;
}

if (micro_steps == 0) {
stepper_trigger_callback(data->dev, STEPPER_EVENT_STEPS_COMPLETED);
config->timing_source->stop(dev);
return 0;
}

K_SPINLOCK(&data->lock) {
data->run_mode = STEPPER_RUN_MODE_POSITION;
data->step_count = micro_steps;
atomic_set(&data->step_count, micro_steps);
update_direction_from_step_count(dev);
ret = update_dir_pin(dev);
if (ret < 0) {
Expand All @@ -259,7 +255,7 @@ int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micr
}

int step_dir_stepper_common_set_microstep_interval(const struct device *dev,
const uint64_t microstep_interval_ns)
const uint64_t microstep_interval_ns)
{
struct step_dir_stepper_common_data *data = dev->data;
const struct step_dir_stepper_common_config *config = dev->config;
Expand Down Expand Up @@ -292,9 +288,7 @@ int step_dir_stepper_common_get_actual_position(const struct device *dev, int32_
{
struct step_dir_stepper_common_data *data = dev->data;

K_SPINLOCK(&data->lock) {
*value = data->actual_position;
}
*value = atomic_get(&data->actual_position);

return 0;
}
Expand All @@ -305,9 +299,7 @@ int step_dir_stepper_common_move_to(const struct device *dev, const int32_t valu
int32_t steps_to_move;

/* Calculate the relative movement required */
K_SPINLOCK(&data->lock) {
steps_to_move = value - data->actual_position;
}
steps_to_move = value - atomic_get(&data->actual_position);

return step_dir_stepper_common_move_by(dev, steps_to_move);
}
Expand Down
4 changes: 2 additions & 2 deletions drivers/stepper/step_dir/step_dir_stepper_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ struct step_dir_stepper_common_data {
struct k_spinlock lock;
enum stepper_direction direction;
enum stepper_run_mode run_mode;
int32_t actual_position;
uint64_t microstep_interval_ns;
int32_t step_count;
atomic_t actual_position;
atomic_t step_count;
stepper_event_callback_t callback;
void *event_cb_user_data;

Expand Down
29 changes: 22 additions & 7 deletions tests/drivers/stepper/stepper_api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ static void *stepper_setup(void)
&stepper_signal);

zassert_not_null(fixture.dev);
zassert_equal(
stepper_set_event_callback(fixture.dev, fixture.callback, (void *)fixture.dev), 0,
"Failed to set event callback");
(void)stepper_enable(fixture.dev);
return &fixture;
}
Expand Down Expand Up @@ -131,12 +134,9 @@ ZTEST_F(stepper, test_target_position_w_fixed_step_interval)
int ret;

ret = stepper_set_microstep_interval(fixture->dev, 100 * USEC_PER_SEC);

if (ret == -ENOSYS) {
ztest_test_skip();
}
/* Pass the function name as user data */
(void)stepper_set_event_callback(fixture->dev, fixture->callback, (void *)fixture->dev);

(void)stepper_move_to(fixture->dev, pos);

Expand All @@ -154,7 +154,6 @@ ZTEST_F(stepper, test_move_by_positive_step_count)
int32_t steps = 20;

(void)stepper_set_microstep_interval(fixture->dev, 100 * USEC_PER_SEC);
(void)stepper_set_event_callback(fixture->dev, fixture->callback, (void *)fixture->dev);
(void)stepper_move_by(fixture->dev, steps);

POLL_AND_CHECK_SIGNAL(
Expand All @@ -169,7 +168,6 @@ ZTEST_F(stepper, test_move_by_negative_step_count)
int32_t steps = -20;

(void)stepper_set_microstep_interval(fixture->dev, 100 * USEC_PER_SEC);
(void)stepper_set_event_callback(fixture->dev, fixture->callback, (void *)fixture->dev);
(void)stepper_move_by(fixture->dev, steps);

POLL_AND_CHECK_SIGNAL(
Expand All @@ -181,8 +179,6 @@ ZTEST_F(stepper, test_move_by_negative_step_count)

ZTEST_F(stepper, test_stop)
{
(void)stepper_set_event_callback(fixture->dev, fixture->callback, (void *)fixture->dev);

/* Run the stepper in positive direction */
(void)stepper_run(fixture->dev, STEPPER_DIRECTION_POSITIVE);

Expand All @@ -206,3 +202,22 @@ ZTEST_F(stepper, test_stop)
zassert_unreachable("Stepper stop failed");
}
}

ZTEST_F(stepper, test_move_by_zero_steps)
{
bool is_moving;
int err;

err = stepper_set_microstep_interval(fixture->dev, 100 * USEC_PER_SEC);
if (err == -ENOSYS) {
ztest_test_skip();
}
zassert_equal(err, 0, "Failed to set microstep interval");

zassert_equal(stepper_move_by(fixture->dev, 0), 0, "Failed to move by zero steps");
POLL_AND_CHECK_SIGNAL(stepper_signal, stepper_event, STEPPER_EVENT_STEPS_COMPLETED,
K_NO_WAIT);
zassert_equal(stepper_is_moving(fixture->dev, &is_moving), 0,
"Failed to check if stepper is moving");
zassert_equal(is_moving, false, "Stepper is still moving");
}