@@ -47,20 +47,70 @@ static inline int step_dir_stepper_perform_step(const struct device *dev)
4747 return 0 ;
4848}
4949
50+ static void stepper_trigger_callback (const struct device * dev , enum stepper_event event )
51+ {
52+ struct step_dir_stepper_common_data * data = dev -> data ;
53+
54+ if (!data -> callback ) {
55+ LOG_WRN_ONCE ("No callback set" );
56+ return ;
57+ }
58+
59+ if (!k_is_in_isr ()) {
60+ data -> callback (dev , event , data -> event_cb_user_data );
61+ return ;
62+ }
63+
64+ #ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS
65+ /* Dispatch to msgq instead of raising directly */
66+ int ret = k_msgq_put (& data -> event_msgq , & event , K_NO_WAIT );
67+
68+ if (ret != 0 ) {
69+ LOG_WRN ("Failed to put event in msgq: %d" , ret );
70+ }
71+
72+ ret = k_work_submit (& data -> event_callback_work );
73+ if (ret < 0 ) {
74+ LOG_ERR ("Failed to submit work item: %d" , ret );
75+ }
76+ #else
77+ LOG_WRN_ONCE ("Event callback called from ISR context without ISR safe events enabled" );
78+ #endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */
79+ }
80+
81+ #ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS
82+ static void stepper_work_event_handler (struct k_work * work )
83+ {
84+ struct step_dir_stepper_common_data * data =
85+ CONTAINER_OF (work , struct step_dir_stepper_common_data , event_callback_work );
86+ enum stepper_event event ;
87+ int ret ;
88+
89+ ret = k_msgq_get (& data -> event_msgq , & event , K_NO_WAIT );
90+ if (ret != 0 ) {
91+ return ;
92+ }
93+
94+ /* Run the callback */
95+ if (data -> callback != NULL ) {
96+ data -> callback (data -> dev , event , data -> event_cb_user_data );
97+ }
98+
99+ /* If there are more pending events, resubmit this work item to handle them */
100+ if (k_msgq_num_used_get (& data -> event_msgq ) > 0 ) {
101+ k_work_submit (work );
102+ }
103+ }
104+ #endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */
105+
50106static void update_remaining_steps (struct step_dir_stepper_common_data * data )
51107{
52108 if (data -> step_count > 0 ) {
53109 data -> step_count -- ;
54- (void )k_work_reschedule (& data -> stepper_dwork , K_USEC (data -> delay_in_us ));
55110 } else if (data -> step_count < 0 ) {
56111 data -> step_count ++ ;
57- (void )k_work_reschedule (& data -> stepper_dwork , K_USEC (data -> delay_in_us ));
58112 } else {
59- if (!data -> callback ) {
60- LOG_WRN_ONCE ("No callback set" );
61- return ;
62- }
63- data -> callback (data -> dev , STEPPER_EVENT_STEPS_COMPLETED , data -> event_cb_user_data );
113+ stepper_trigger_callback (data -> dev , STEPPER_EVENT_STEPS_COMPLETED );
64114 }
65115}
66116
@@ -80,34 +130,41 @@ static void update_direction_from_step_count(const struct device *dev)
80130static void position_mode_task (const struct device * dev )
81131{
82132 struct step_dir_stepper_common_data * data = dev -> data ;
133+ const struct step_dir_stepper_common_config * config = dev -> config ;
83134
84135 if (data -> step_count ) {
85136 (void )step_dir_stepper_perform_step (dev );
86137 }
138+
87139 update_remaining_steps (dev -> data );
140+
141+ if (config -> timing_source -> needs_reschedule (dev ) && data -> step_count != 0 ) {
142+ (void )config -> timing_source -> start (dev );
143+ }
88144}
89145
90146static void velocity_mode_task (const struct device * dev )
91147{
92- struct step_dir_stepper_common_data * data = dev -> data ;
148+ const struct step_dir_stepper_common_config * config = dev -> config ;
93149
94150 (void )step_dir_stepper_perform_step (dev );
95- (void )k_work_reschedule (& data -> stepper_dwork , K_USEC (data -> delay_in_us ));
151+
152+ if (config -> timing_source -> needs_reschedule (dev )) {
153+ (void )config -> timing_source -> start (dev );
154+ }
96155}
97156
98- static void stepper_work_step_handler ( struct k_work * work )
157+ void stepper_handle_timing_signal ( const struct device * dev )
99158{
100- struct k_work_delayable * dwork = k_work_delayable_from_work (work );
101- struct step_dir_stepper_common_data * data =
102- CONTAINER_OF (dwork , struct step_dir_stepper_common_data , stepper_dwork );
159+ struct step_dir_stepper_common_data * data = dev -> data ;
103160
104161 K_SPINLOCK (& data -> lock ) {
105162 switch (data -> run_mode ) {
106163 case STEPPER_RUN_MODE_POSITION :
107- position_mode_task (data -> dev );
164+ position_mode_task (dev );
108165 break ;
109166 case STEPPER_RUN_MODE_VELOCITY :
110- velocity_mode_task (data -> dev );
167+ velocity_mode_task (dev );
111168 break ;
112169 default :
113170 LOG_WRN ("Unsupported run mode: %d" , data -> run_mode );
@@ -119,7 +176,6 @@ static void stepper_work_step_handler(struct k_work *work)
119176int step_dir_stepper_common_init (const struct device * dev )
120177{
121178 const struct step_dir_stepper_common_config * config = dev -> config ;
122- struct step_dir_stepper_common_data * data = dev -> data ;
123179 int ret ;
124180
125181 if (!gpio_is_ready_dt (& config -> step_pin ) || !gpio_is_ready_dt (& config -> dir_pin )) {
@@ -139,25 +195,41 @@ int step_dir_stepper_common_init(const struct device *dev)
139195 return ret ;
140196 }
141197
142- k_work_init_delayable (& data -> stepper_dwork , stepper_work_step_handler );
198+ if (config -> timing_source -> init ) {
199+ ret = config -> timing_source -> init (dev );
200+ if (ret < 0 ) {
201+ LOG_ERR ("Failed to initialize timing source: %d" , ret );
202+ return ret ;
203+ }
204+ }
205+
206+ #ifdef CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS
207+ struct step_dir_stepper_common_data * data = dev -> data ;
208+
209+ k_msgq_init (& data -> event_msgq , data -> event_msgq_buffer , sizeof (enum stepper_event ),
210+ CONFIG_STEPPER_STEP_DIR_EVENT_QUEUE_LEN );
211+ k_work_init (& data -> event_callback_work , stepper_work_event_handler );
212+ #endif /* CONFIG_STEPPER_STEP_DIR_GENERATE_ISR_SAFE_EVENTS */
143213
144214 return 0 ;
145215}
146216
147217int step_dir_stepper_common_move_by (const struct device * dev , const int32_t micro_steps )
148218{
149219 struct step_dir_stepper_common_data * data = dev -> data ;
220+ const struct step_dir_stepper_common_config * config = dev -> config ;
150221
151- if (data -> delay_in_us == 0 ) {
222+ if (data -> max_velocity == 0 ) {
152223 LOG_ERR ("Velocity not set or invalid velocity set" );
153224 return - EINVAL ;
154225 }
155226
156227 K_SPINLOCK (& data -> lock ) {
157228 data -> run_mode = STEPPER_RUN_MODE_POSITION ;
158229 data -> step_count = micro_steps ;
230+ config -> timing_source -> update (dev , data -> max_velocity );
159231 update_direction_from_step_count (dev );
160- ( void ) k_work_reschedule ( & data -> stepper_dwork , K_NO_WAIT );
232+ config -> timing_source -> start ( dev );
161233 }
162234
163235 return 0 ;
@@ -166,6 +238,7 @@ int step_dir_stepper_common_move_by(const struct device *dev, const int32_t micr
166238int step_dir_stepper_common_set_max_velocity (const struct device * dev , const uint32_t velocity )
167239{
168240 struct step_dir_stepper_common_data * data = dev -> data ;
241+ const struct step_dir_stepper_common_config * config = dev -> config ;
169242
170243 if (velocity == 0 ) {
171244 LOG_ERR ("Velocity cannot be zero" );
@@ -178,7 +251,8 @@ int step_dir_stepper_common_set_max_velocity(const struct device *dev, const uin
178251 }
179252
180253 K_SPINLOCK (& data -> lock ) {
181- data -> delay_in_us = USEC_PER_SEC / velocity ;
254+ data -> max_velocity = velocity ;
255+ config -> timing_source -> update (dev , velocity );
182256 }
183257
184258 return 0 ;
@@ -209,43 +283,47 @@ int step_dir_stepper_common_get_actual_position(const struct device *dev, int32_
209283int step_dir_stepper_common_move_to (const struct device * dev , const int32_t value )
210284{
211285 struct step_dir_stepper_common_data * data = dev -> data ;
286+ const struct step_dir_stepper_common_config * config = dev -> config ;
212287
213- if (data -> delay_in_us == 0 ) {
288+ if (data -> max_velocity == 0 ) {
214289 LOG_ERR ("Velocity not set or invalid velocity set" );
215290 return - EINVAL ;
216291 }
217292
218293 K_SPINLOCK (& data -> lock ) {
219294 data -> run_mode = STEPPER_RUN_MODE_POSITION ;
220295 data -> step_count = value - data -> actual_position ;
296+ config -> timing_source -> update (dev , data -> max_velocity );
221297 update_direction_from_step_count (dev );
222- ( void ) k_work_reschedule ( & data -> stepper_dwork , K_NO_WAIT );
298+ config -> timing_source -> start ( dev );
223299 }
224300
225301 return 0 ;
226302}
227303
228304int step_dir_stepper_common_is_moving (const struct device * dev , bool * is_moving )
229305{
230- struct step_dir_stepper_common_data * data = dev -> data ;
306+ const struct step_dir_stepper_common_config * config = dev -> config ;
231307
232- * is_moving = k_work_delayable_is_pending ( & data -> stepper_dwork );
308+ * is_moving = config -> timing_source -> is_running ( dev );
233309 return 0 ;
234310}
235311
236312int step_dir_stepper_common_run (const struct device * dev , const enum stepper_direction direction ,
237313 const uint32_t velocity )
238314{
239315 struct step_dir_stepper_common_data * data = dev -> data ;
316+ const struct step_dir_stepper_common_config * config = dev -> config ;
240317
241318 K_SPINLOCK (& data -> lock ) {
242319 data -> run_mode = STEPPER_RUN_MODE_VELOCITY ;
243320 data -> direction = direction ;
321+ data -> max_velocity = velocity ;
322+ config -> timing_source -> update (dev , velocity );
244323 if (velocity != 0 ) {
245- data -> delay_in_us = USEC_PER_SEC / velocity ;
246- (void )k_work_reschedule (& data -> stepper_dwork , K_NO_WAIT );
324+ config -> timing_source -> start (dev );
247325 } else {
248- ( void ) k_work_cancel_delayable ( & data -> stepper_dwork );
326+ config -> timing_source -> stop ( dev );
249327 }
250328 }
251329
0 commit comments