42 /*****************************************************************************/ |
42 /*****************************************************************************/ |
43 |
43 |
44 void ec_fsm_slave_state_idle(ec_fsm_slave_t *); |
44 void ec_fsm_slave_state_idle(ec_fsm_slave_t *); |
45 void ec_fsm_slave_state_ready(ec_fsm_slave_t *); |
45 void ec_fsm_slave_state_ready(ec_fsm_slave_t *); |
46 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *); |
46 int ec_fsm_slave_action_process_sdo(ec_fsm_slave_t *); |
|
47 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *); |
47 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *); |
48 int ec_fsm_slave_action_process_foe(ec_fsm_slave_t *); |
48 void ec_fsm_slave_state_sdo_request(ec_fsm_slave_t *); |
|
49 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *); |
49 void ec_fsm_slave_state_foe_request(ec_fsm_slave_t *); |
50 |
50 int ec_fsm_slave_action_process_soe(ec_fsm_slave_t *); |
|
51 void ec_fsm_slave_state_soe_request(ec_fsm_slave_t *); |
51 |
52 |
52 /*****************************************************************************/ |
53 /*****************************************************************************/ |
53 |
54 |
54 /** Constructor. |
55 /** Constructor. |
55 */ |
56 */ |
105 |
108 |
106 fsm->state(fsm); |
109 fsm->state(fsm); |
107 return; |
110 return; |
108 } |
111 } |
109 |
112 |
110 |
|
111 /*****************************************************************************/ |
113 /*****************************************************************************/ |
112 |
114 |
113 /** Sets the current state of the state machine to READY |
115 /** Sets the current state of the state machine to READY |
114 * |
|
115 */ |
116 */ |
116 void ec_fsm_slave_ready( |
117 void ec_fsm_slave_ready( |
117 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
118 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
118 ) |
119 ) |
119 { |
120 { |
120 if (fsm->state == ec_fsm_slave_state_idle) { |
121 if (fsm->state == ec_fsm_slave_state_idle) { |
121 if (fsm->slave->master->debug_level) { |
122 if (fsm->slave->master->debug_level) { |
122 EC_DBG("Slave %u ready for SDO/FOE.\n", |
123 EC_DBG("Slave %u ready for requests.\n", |
123 fsm->slave->ring_position); |
124 fsm->slave->ring_position); |
124 } |
125 } |
125 fsm->state = ec_fsm_slave_state_ready; |
126 fsm->state = ec_fsm_slave_state_ready; |
126 } |
127 } |
127 return; |
|
128 } |
128 } |
129 |
129 |
130 /****************************************************************************** |
130 /****************************************************************************** |
131 * Slave state machine |
131 * Slave state machine |
132 *****************************************************************************/ |
132 *****************************************************************************/ |
133 |
133 |
134 /*****************************************************************************/ |
|
135 |
|
136 /** Slave state: IDLE. |
134 /** Slave state: IDLE. |
137 * |
|
138 * |
|
139 */ |
135 */ |
140 void ec_fsm_slave_state_idle( |
136 void ec_fsm_slave_state_idle( |
141 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
137 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
142 ) |
138 ) |
143 { |
139 { |
146 |
142 |
147 |
143 |
148 /*****************************************************************************/ |
144 /*****************************************************************************/ |
149 |
145 |
150 /** Slave state: READY. |
146 /** Slave state: READY. |
151 * |
|
152 * |
|
153 */ |
147 */ |
154 void ec_fsm_slave_state_ready( |
148 void ec_fsm_slave_state_ready( |
155 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
149 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
156 ) |
150 ) |
157 { |
151 { |
158 // Check for pending external SDO requests |
152 // Check for pending external SDO requests |
159 if (ec_fsm_slave_action_process_sdo(fsm)) |
153 if (ec_fsm_slave_action_process_sdo(fsm)) |
160 return; |
154 return; |
161 |
155 |
162 // Check for pending FOE requests |
156 // Check for pending FoE requests |
163 if (ec_fsm_slave_action_process_foe(fsm)) |
157 if (ec_fsm_slave_action_process_foe(fsm)) |
|
158 return; |
|
159 |
|
160 // Check for pending SoE requests |
|
161 if (ec_fsm_slave_action_process_soe(fsm)) |
164 return; |
162 return; |
165 } |
163 } |
166 |
164 |
167 /*****************************************************************************/ |
165 /*****************************************************************************/ |
168 |
166 |
218 return 1; |
216 return 1; |
219 } |
217 } |
220 return 0; |
218 return 0; |
221 } |
219 } |
222 |
220 |
223 |
|
224 /*****************************************************************************/ |
|
225 |
|
226 /** Check for pending FOE requests and process one. |
|
227 * |
|
228 * \return non-zero, if an FOE request is processed. |
|
229 */ |
|
230 int ec_fsm_slave_action_process_foe( |
|
231 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
|
232 ) |
|
233 { |
|
234 ec_slave_t *slave = fsm->slave; |
|
235 ec_master_t *master = slave->master; |
|
236 ec_master_foe_request_t *request, *next; |
|
237 |
|
238 // search the first request to be processed |
|
239 list_for_each_entry_safe(request, next, &slave->foe_requests, list) { |
|
240 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
|
241 EC_WARN("Aborting FOE request, slave %u has ERROR.\n", |
|
242 slave->ring_position); |
|
243 request->req.state = EC_INT_REQUEST_FAILURE; |
|
244 wake_up(&slave->sdo_queue); |
|
245 fsm->sdo_request = NULL; |
|
246 fsm->state = ec_fsm_slave_state_idle; |
|
247 return 0; |
|
248 } |
|
249 list_del_init(&request->list); // dequeue |
|
250 request->req.state = EC_INT_REQUEST_BUSY; |
|
251 |
|
252 if (master->debug_level) |
|
253 EC_DBG("Processing FOE request for slave %u.\n", |
|
254 slave->ring_position); |
|
255 |
|
256 fsm->foe_request = &request->req; |
|
257 fsm->state = ec_fsm_slave_state_foe_request; |
|
258 ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req); |
|
259 ec_fsm_foe_exec(&fsm->fsm_foe); |
|
260 ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram); |
|
261 return 1; |
|
262 } |
|
263 return 0; |
|
264 } |
|
265 |
|
266 |
|
267 |
|
268 /*****************************************************************************/ |
221 /*****************************************************************************/ |
269 |
222 |
270 /** Slave state: SDO_REQUEST. |
223 /** Slave state: SDO_REQUEST. |
271 */ |
224 */ |
272 void ec_fsm_slave_state_sdo_request( |
225 void ec_fsm_slave_state_sdo_request( |
304 fsm->state = ec_fsm_slave_state_ready; |
257 fsm->state = ec_fsm_slave_state_ready; |
305 } |
258 } |
306 |
259 |
307 /*****************************************************************************/ |
260 /*****************************************************************************/ |
308 |
261 |
|
262 /** Check for pending FOE requests and process one. |
|
263 * |
|
264 * \return non-zero, if an FOE request is processed. |
|
265 */ |
|
266 int ec_fsm_slave_action_process_foe( |
|
267 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
|
268 ) |
|
269 { |
|
270 ec_slave_t *slave = fsm->slave; |
|
271 ec_master_t *master = slave->master; |
|
272 ec_master_foe_request_t *request, *next; |
|
273 |
|
274 // search the first request to be processed |
|
275 list_for_each_entry_safe(request, next, &slave->foe_requests, list) { |
|
276 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
|
277 EC_WARN("Aborting FOE request, slave %u has ERROR.\n", |
|
278 slave->ring_position); |
|
279 request->req.state = EC_INT_REQUEST_FAILURE; |
|
280 wake_up(&slave->sdo_queue); |
|
281 fsm->sdo_request = NULL; |
|
282 fsm->state = ec_fsm_slave_state_idle; |
|
283 return 0; |
|
284 } |
|
285 list_del_init(&request->list); // dequeue |
|
286 request->req.state = EC_INT_REQUEST_BUSY; |
|
287 |
|
288 if (master->debug_level) |
|
289 EC_DBG("Processing FOE request for slave %u.\n", |
|
290 slave->ring_position); |
|
291 |
|
292 fsm->foe_request = &request->req; |
|
293 fsm->state = ec_fsm_slave_state_foe_request; |
|
294 ec_fsm_foe_transfer(&fsm->fsm_foe, slave, &request->req); |
|
295 ec_fsm_foe_exec(&fsm->fsm_foe); |
|
296 ec_master_queue_external_datagram(fsm->slave->master,fsm->datagram); |
|
297 return 1; |
|
298 } |
|
299 return 0; |
|
300 } |
|
301 |
|
302 /*****************************************************************************/ |
|
303 |
309 /** Slave state: FOE REQUEST. |
304 /** Slave state: FOE REQUEST. |
310 */ |
305 */ |
311 void ec_fsm_slave_state_foe_request( |
306 void ec_fsm_slave_state_foe_request( |
312 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
307 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
313 ) |
308 ) |
343 fsm->foe_request = NULL; |
338 fsm->foe_request = NULL; |
344 fsm->state = ec_fsm_slave_state_ready; |
339 fsm->state = ec_fsm_slave_state_ready; |
345 } |
340 } |
346 |
341 |
347 /*****************************************************************************/ |
342 /*****************************************************************************/ |
|
343 |
|
344 /** Check for pending SoE requests and process one. |
|
345 * |
|
346 * \return non-zero, if a request is processed. |
|
347 */ |
|
348 int ec_fsm_slave_action_process_soe( |
|
349 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
|
350 ) |
|
351 { |
|
352 ec_slave_t *slave = fsm->slave; |
|
353 ec_master_t *master = slave->master; |
|
354 ec_master_soe_request_t *req, *next; |
|
355 |
|
356 // search the first request to be processed |
|
357 list_for_each_entry_safe(req, next, &slave->soe_requests, list) { |
|
358 |
|
359 list_del_init(&req->list); // dequeue |
|
360 if (slave->current_state & EC_SLAVE_STATE_ACK_ERR) { |
|
361 EC_WARN("Aborting SoE request, slave %u has ERROR.\n", |
|
362 slave->ring_position); |
|
363 req->req.state = EC_INT_REQUEST_FAILURE; |
|
364 wake_up(&slave->soe_queue); |
|
365 fsm->state = ec_fsm_slave_state_idle; |
|
366 return 0; |
|
367 } |
|
368 |
|
369 if (slave->current_state == EC_SLAVE_STATE_INIT) { |
|
370 EC_WARN("Aborting SoE request, slave %u is in INIT.\n", |
|
371 slave->ring_position); |
|
372 req->req.state = EC_INT_REQUEST_FAILURE; |
|
373 wake_up(&slave->soe_queue); |
|
374 fsm->state = ec_fsm_slave_state_idle; |
|
375 return 0; |
|
376 } |
|
377 |
|
378 req->req.state = EC_INT_REQUEST_BUSY; |
|
379 |
|
380 // Found pending request. Execute it! |
|
381 if (master->debug_level) |
|
382 EC_DBG("Processing SoE request for slave %u...\n", |
|
383 slave->ring_position); |
|
384 |
|
385 // Start SoE transfer |
|
386 fsm->soe_request = &req->req; |
|
387 fsm->state = ec_fsm_slave_state_soe_request; |
|
388 ec_fsm_soe_transfer(&fsm->fsm_soe, slave, &req->req); |
|
389 ec_fsm_soe_exec(&fsm->fsm_soe); // execute immediately |
|
390 ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); |
|
391 return 1; |
|
392 } |
|
393 return 0; |
|
394 } |
|
395 |
|
396 /*****************************************************************************/ |
|
397 |
|
398 /** Slave state: SOE_REQUEST. |
|
399 */ |
|
400 void ec_fsm_slave_state_soe_request( |
|
401 ec_fsm_slave_t *fsm /**< Slave state machine. */ |
|
402 ) |
|
403 { |
|
404 ec_slave_t *slave = fsm->slave; |
|
405 ec_master_t *master = slave->master; |
|
406 ec_soe_request_t *request = fsm->soe_request; |
|
407 |
|
408 if (ec_fsm_soe_exec(&fsm->fsm_soe)) { |
|
409 ec_master_queue_external_datagram(fsm->slave->master, fsm->datagram); |
|
410 return; |
|
411 } |
|
412 |
|
413 if (!ec_fsm_soe_success(&fsm->fsm_soe)) { |
|
414 EC_DBG("Failed to process SoE request for slave %u.\n", |
|
415 fsm->slave->ring_position); |
|
416 request->state = EC_INT_REQUEST_FAILURE; |
|
417 wake_up(&slave->soe_queue); |
|
418 fsm->soe_request = NULL; |
|
419 fsm->state = ec_fsm_slave_state_idle; |
|
420 return; |
|
421 } |
|
422 |
|
423 if (master->debug_level) |
|
424 EC_DBG("Finished SoE request for slave %u.\n", |
|
425 fsm->slave->ring_position); |
|
426 |
|
427 // SoE request finished |
|
428 request->state = EC_INT_REQUEST_SUCCESS; |
|
429 wake_up(&slave->soe_queue); |
|
430 |
|
431 fsm->soe_request = NULL; |
|
432 fsm->state = ec_fsm_slave_state_ready; |
|
433 } |
|
434 |
|
435 /*****************************************************************************/ |