changeset 260 | 5fe7df7f2433 |
parent 259 | 87b20532872b |
child 262 | 636d43737371 |
259:87b20532872b | 260:5fe7df7f2433 |
---|---|
55 const ec_code_msg_t al_status_messages[]; |
55 const ec_code_msg_t al_status_messages[]; |
56 |
56 |
57 /*****************************************************************************/ |
57 /*****************************************************************************/ |
58 |
58 |
59 void ec_fsm_master_start(ec_fsm_t *); |
59 void ec_fsm_master_start(ec_fsm_t *); |
60 void ec_fsm_master_wait(ec_fsm_t *); |
60 void ec_fsm_master_broadcast(ec_fsm_t *); |
61 void ec_fsm_master_proc_states(ec_fsm_t *); |
|
61 void ec_fsm_master_scan(ec_fsm_t *); |
62 void ec_fsm_master_scan(ec_fsm_t *); |
63 void ec_fsm_master_states(ec_fsm_t *); |
|
64 void ec_fsm_master_validate_vendor(ec_fsm_t *); |
|
65 void ec_fsm_master_validate_product(ec_fsm_t *); |
|
66 void ec_fsm_master_reconfigure(ec_fsm_t *); |
|
67 void ec_fsm_master_address(ec_fsm_t *); |
|
62 void ec_fsm_master_conf(ec_fsm_t *); |
68 void ec_fsm_master_conf(ec_fsm_t *); |
63 |
69 |
64 void ec_fsm_slave_start_reading(ec_fsm_t *); |
70 void ec_fsm_slave_start_reading(ec_fsm_t *); |
65 void ec_fsm_slave_read_status(ec_fsm_t *); |
71 void ec_fsm_slave_read_status(ec_fsm_t *); |
66 void ec_fsm_slave_read_base(ec_fsm_t *); |
72 void ec_fsm_slave_read_base(ec_fsm_t *); |
67 void ec_fsm_slave_read_dl(ec_fsm_t *); |
73 void ec_fsm_slave_read_dl(ec_fsm_t *); |
68 void ec_fsm_slave_prepare_sii(ec_fsm_t *); |
74 void ec_fsm_slave_prepare_sii(ec_fsm_t *); |
69 void ec_fsm_slave_read_sii(ec_fsm_t *); |
75 void ec_fsm_slave_read_sii(ec_fsm_t *); |
70 void ec_fsm_slave_category_header(ec_fsm_t *); |
76 void ec_fsm_slave_category_header(ec_fsm_t *); |
71 void ec_fsm_slave_category_data(ec_fsm_t *); |
77 void ec_fsm_slave_category_data(ec_fsm_t *); |
72 void ec_fsm_slave_conf(ec_fsm_t *); |
|
73 void ec_fsm_slave_end(ec_fsm_t *); |
78 void ec_fsm_slave_end(ec_fsm_t *); |
74 |
79 |
75 void ec_fsm_slave_conf(ec_fsm_t *); |
80 void ec_fsm_slave_conf(ec_fsm_t *); |
76 void ec_fsm_slave_sync(ec_fsm_t *); |
81 void ec_fsm_slave_sync(ec_fsm_t *); |
77 void ec_fsm_slave_preop(ec_fsm_t *); |
82 void ec_fsm_slave_preop(ec_fsm_t *); |
81 void ec_fsm_slave_op2(ec_fsm_t *); |
86 void ec_fsm_slave_op2(ec_fsm_t *); |
82 |
87 |
83 void ec_fsm_sii_start_reading(ec_fsm_t *); |
88 void ec_fsm_sii_start_reading(ec_fsm_t *); |
84 void ec_fsm_sii_check(ec_fsm_t *); |
89 void ec_fsm_sii_check(ec_fsm_t *); |
85 void ec_fsm_sii_fetch(ec_fsm_t *); |
90 void ec_fsm_sii_fetch(ec_fsm_t *); |
86 void ec_fsm_sii_finished(ec_fsm_t *); |
91 void ec_fsm_sii_end(ec_fsm_t *); |
87 void ec_fsm_sii_error(ec_fsm_t *); |
92 void ec_fsm_sii_error(ec_fsm_t *); |
88 |
93 |
89 void ec_fsm_change_start(ec_fsm_t *); |
94 void ec_fsm_change_start(ec_fsm_t *); |
90 void ec_fsm_change_check(ec_fsm_t *); |
95 void ec_fsm_change_check(ec_fsm_t *); |
91 void ec_fsm_change_status(ec_fsm_t *); |
96 void ec_fsm_change_status(ec_fsm_t *); |
95 void ec_fsm_change_end(ec_fsm_t *); |
100 void ec_fsm_change_end(ec_fsm_t *); |
96 void ec_fsm_change_error(ec_fsm_t *); |
101 void ec_fsm_change_error(ec_fsm_t *); |
97 |
102 |
98 /*****************************************************************************/ |
103 /*****************************************************************************/ |
99 |
104 |
100 int ec_fsm_init(ec_fsm_t *fsm, ec_master_t *master) |
105 /** |
106 Constructor. |
|
107 */ |
|
108 |
|
109 int ec_fsm_init(ec_fsm_t *fsm, /**< finite state machine */ |
|
110 ec_master_t *master /**< EtherCAT master */ |
|
111 ) |
|
101 { |
112 { |
102 fsm->master = master; |
113 fsm->master = master; |
103 fsm->master_state = ec_fsm_master_start; |
114 fsm->master_state = ec_fsm_master_start; |
104 fsm->master_slaves_responding = 0; |
115 fsm->master_slaves_responding = 0; |
105 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
116 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
117 fsm->master_validation = 0; |
|
106 fsm->slave_cat_data = NULL; |
118 fsm->slave_cat_data = NULL; |
107 |
119 |
108 ec_command_init(&fsm->command); |
120 ec_command_init(&fsm->command); |
109 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
121 if (ec_command_prealloc(&fsm->command, EC_MAX_DATA_SIZE)) { |
110 EC_ERR("FSM failed to allocate FSM command.\n"); |
122 EC_ERR("FSM failed to allocate FSM command.\n"); |
114 return 0; |
126 return 0; |
115 } |
127 } |
116 |
128 |
117 /*****************************************************************************/ |
129 /*****************************************************************************/ |
118 |
130 |
119 void ec_fsm_clear(ec_fsm_t *fsm) |
131 /** |
132 Destructor. |
|
133 */ |
|
134 |
|
135 void ec_fsm_clear(ec_fsm_t *fsm /**< finite state machine */) |
|
120 { |
136 { |
121 if (fsm->slave_cat_data) kfree(fsm->slave_cat_data); |
137 if (fsm->slave_cat_data) kfree(fsm->slave_cat_data); |
122 ec_command_clear(&fsm->command); |
138 ec_command_clear(&fsm->command); |
123 } |
139 } |
124 |
140 |
125 /*****************************************************************************/ |
141 /*****************************************************************************/ |
126 |
142 |
127 void ec_fsm_reset(ec_fsm_t *fsm) |
143 /** |
144 Resets the state machine. |
|
145 */ |
|
146 |
|
147 void ec_fsm_reset(ec_fsm_t *fsm /**< finite state machine */) |
|
128 { |
148 { |
129 fsm->master_state = ec_fsm_master_start; |
149 fsm->master_state = ec_fsm_master_start; |
130 fsm->master_slaves_responding = 0; |
150 fsm->master_slaves_responding = 0; |
131 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
151 fsm->master_slave_states = EC_SLAVE_STATE_UNKNOWN; |
132 |
152 |
136 } |
156 } |
137 } |
157 } |
138 |
158 |
139 /*****************************************************************************/ |
159 /*****************************************************************************/ |
140 |
160 |
141 void ec_fsm_execute(ec_fsm_t *fsm) |
161 /** |
162 Executes the current state of the state machine. |
|
163 */ |
|
164 |
|
165 void ec_fsm_execute(ec_fsm_t *fsm /**< finite state machine */) |
|
142 { |
166 { |
143 fsm->master_state(fsm); |
167 fsm->master_state(fsm); |
144 } |
168 } |
145 |
169 |
146 /****************************************************************************** |
170 /****************************************************************************** |
147 * master state machine |
171 * master state machine |
148 *****************************************************************************/ |
172 *****************************************************************************/ |
149 |
173 |
150 /** |
174 /** |
151 State: Start. |
175 Master state: START. |
152 Starts with getting slave count and slave states. |
176 Starts with getting slave count and slave states. |
153 */ |
177 */ |
154 |
178 |
155 void ec_fsm_master_start(ec_fsm_t *fsm) |
179 void ec_fsm_master_start(ec_fsm_t *fsm) |
156 { |
180 { |
157 ec_command_brd(&fsm->command, 0x0130, 2); |
181 ec_command_brd(&fsm->command, 0x0130, 2); |
158 ec_master_queue_command(fsm->master, &fsm->command); |
182 ec_master_queue_command(fsm->master, &fsm->command); |
159 fsm->master_state = ec_fsm_master_wait; |
183 fsm->master_state = ec_fsm_master_broadcast; |
160 } |
184 } |
161 |
185 |
162 /*****************************************************************************/ |
186 /*****************************************************************************/ |
163 |
187 |
164 void ec_fsm_master_wait(ec_fsm_t *fsm) |
188 /** |
165 { |
189 Master state: BROADCAST. |
166 ec_command_t *command = &fsm->command; |
190 Processes the broadcast read slave count and slaves states. |
167 unsigned int topology_change, i, eoe_slaves_active; |
191 */ |
192 |
|
193 void ec_fsm_master_broadcast(ec_fsm_t *fsm /**< finite state machine */) |
|
194 { |
|
195 ec_command_t *command = &fsm->command; |
|
196 unsigned int topology_change, states_change, i; |
|
168 ec_slave_t *slave; |
197 ec_slave_t *slave; |
198 ec_master_t *master = fsm->master; |
|
169 |
199 |
170 if (command->state != EC_CMD_RECEIVED) { |
200 if (command->state != EC_CMD_RECEIVED) { |
171 if (!fsm->master->device->link_state) |
201 if (!master->device->link_state) { |
172 // treat link down as topology change |
|
173 fsm->master_slaves_responding = 0; |
202 fsm->master_slaves_responding = 0; |
203 list_for_each_entry(slave, &master->slaves, list) { |
|
204 slave->online = 0; |
|
205 } |
|
206 } |
|
174 fsm->master_state = ec_fsm_master_start; |
207 fsm->master_state = ec_fsm_master_start; |
175 fsm->master_state(fsm); // execute immediately |
208 fsm->master_state(fsm); // execute immediately |
176 return; |
209 return; |
177 } |
210 } |
178 |
211 |
179 if (command->working_counter == fsm->master_slaves_responding && |
212 topology_change = (command->working_counter != |
180 command->data[0] == fsm->master_slave_states) |
213 fsm->master_slaves_responding); |
181 { |
214 states_change = (EC_READ_U8(command->data) != fsm->master_slave_states); |
182 // check if any slaves are not in the state, they're supposed to be |
215 |
183 list_for_each_entry(slave, &fsm->master->slaves, list) { |
216 fsm->master_slave_states = EC_READ_U8(command->data); |
184 if (slave->state_error || |
217 fsm->master_slaves_responding = command->working_counter; |
185 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
218 |
186 slave->current_state == slave->requested_state) continue; |
219 if (topology_change) { |
187 |
220 if (fsm->master_slaves_responding == master->slave_count) { |
188 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
221 EC_INFO("%i slave%s responding (VALID).\n", |
189 ec_print_states(slave->current_state); |
222 fsm->master_slaves_responding, |
190 printk(" to "); |
223 fsm->master_slaves_responding == 1 ? "" : "s"); |
191 ec_print_states(slave->requested_state); |
224 fsm->master_validation = 1; // start validation later |
192 printk(".\n"); |
225 } |
193 |
226 else { |
194 fsm->slave = slave; |
227 EC_WARN("%i slave%s responding. Invalid slave count!\n", |
195 fsm->slave_state = ec_fsm_slave_conf; |
228 fsm->master_slaves_responding, |
196 |
229 fsm->master_slaves_responding == 1 ? "" : "s"); |
197 fsm->change_new = EC_SLAVE_STATE_INIT; |
230 } |
198 fsm->change_state = ec_fsm_change_start; |
231 } |
199 |
232 |
200 fsm->master_state = ec_fsm_master_conf; |
233 if (states_change) { |
234 EC_INFO("Slave states: "); |
|
235 ec_print_states(fsm->master_slave_states); |
|
236 printk(".\n"); |
|
237 } |
|
238 |
|
239 // topology change in free-run mode: clear all slaves and scan the bus |
|
240 if (topology_change && master->mode == EC_MASTER_MODE_FREERUN) { |
|
241 EC_INFO("Scanning bus.\n"); |
|
242 |
|
243 ec_master_eoe_stop(master); |
|
244 ec_master_clear_slaves(master); |
|
245 |
|
246 if (!fsm->master_slaves_responding) { |
|
247 // no slaves present -> finish state machine. |
|
248 fsm->master_state = ec_fsm_master_start; |
|
201 fsm->master_state(fsm); // execute immediately |
249 fsm->master_state(fsm); // execute immediately |
202 return; |
250 return; |
203 } |
251 } |
204 |
252 |
205 // nothing to configure... |
253 // init slaves |
206 eoe_slaves_active = 0; |
254 for (i = 0; i < fsm->master_slaves_responding; i++) { |
207 list_for_each_entry(slave, &fsm->master->slaves, list) { |
255 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
208 if (slave->sii_mailbox_protocols & EC_MBOX_EOE) { |
256 GFP_ATOMIC))) { |
209 eoe_slaves_active++; |
257 EC_ERR("Failed to allocate slave %i!\n", i); |
258 fsm->master_state = ec_fsm_master_start; |
|
259 fsm->master_state(fsm); // execute immediately |
|
260 return; |
|
261 } |
|
262 |
|
263 if (ec_slave_init(slave, master, i, i + 1)) { |
|
264 fsm->master_state = ec_fsm_master_start; |
|
265 fsm->master_state(fsm); // execute immediately |
|
266 return; |
|
267 } |
|
268 |
|
269 if (kobject_add(&slave->kobj)) { |
|
270 EC_ERR("Failed to add kobject.\n"); |
|
271 kobject_put(&slave->kobj); // free |
|
272 fsm->master_state = ec_fsm_master_start; |
|
273 fsm->master_state(fsm); // execute immediately |
|
274 return; |
|
275 } |
|
276 |
|
277 list_add_tail(&slave->list, &master->slaves); |
|
278 } |
|
279 |
|
280 // begin scanning of slaves |
|
281 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
282 fsm->slave_state = ec_fsm_slave_start_reading; |
|
283 fsm->master_state = ec_fsm_master_scan; |
|
284 fsm->master_state(fsm); // execute immediately |
|
285 return; |
|
286 } |
|
287 |
|
288 // fetch state from each slave |
|
289 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
290 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
|
291 ec_master_queue_command(master, &fsm->command); |
|
292 fsm->master_state = ec_fsm_master_states; |
|
293 } |
|
294 |
|
295 /*****************************************************************************/ |
|
296 |
|
297 /** |
|
298 Master action: Get state of next slave. |
|
299 */ |
|
300 |
|
301 void ec_fsm_master_action_next_slave_state(ec_fsm_t *fsm |
|
302 /**< finite state machine */) |
|
303 { |
|
304 ec_master_t *master = fsm->master; |
|
305 ec_slave_t *slave = fsm->slave; |
|
306 |
|
307 // have all states been read? |
|
308 if (slave->list.next == &master->slaves) { |
|
309 |
|
310 // check, if a bus validation has to be done |
|
311 if (fsm->master_validation) { |
|
312 fsm->master_validation = 0; |
|
313 list_for_each_entry(slave, &master->slaves, list) { |
|
314 if (slave->online) continue; |
|
315 |
|
316 // At least one slave is offline. validate! |
|
317 EC_INFO("Validating bus.\n"); |
|
318 fsm->slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
319 fsm->master_state = ec_fsm_master_validate_vendor; |
|
320 fsm->sii_offset = 0x0008; // vendor ID |
|
321 fsm->sii_mode = 0; |
|
322 fsm->sii_state = ec_fsm_sii_start_reading; |
|
323 fsm->sii_state(fsm); // execute immediately |
|
324 return; |
|
210 } |
325 } |
211 } |
326 } |
212 |
327 |
213 if (eoe_slaves_active && !list_empty(&fsm->master->eoe_handlers)) |
328 fsm->master_state = ec_fsm_master_proc_states; |
214 ec_master_eoe_start(fsm->master); |
329 fsm->master_state(fsm); // execute immediately |
215 |
330 return; |
331 } |
|
332 |
|
333 // process next slave |
|
334 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
335 ec_command_nprd(&fsm->command, fsm->slave->station_address, 0x0130, 2); |
|
336 ec_master_queue_command(master, &fsm->command); |
|
337 fsm->master_state = ec_fsm_master_states; |
|
338 } |
|
339 |
|
340 /*****************************************************************************/ |
|
341 |
|
342 /** |
|
343 Master state: STATES. |
|
344 Fetches the AL- and online state of a slave. |
|
345 */ |
|
346 |
|
347 void ec_fsm_master_states(ec_fsm_t *fsm /**< finite state machine */) |
|
348 { |
|
349 ec_slave_t *slave = fsm->slave; |
|
350 ec_command_t *command = &fsm->command; |
|
351 uint8_t new_state; |
|
352 |
|
353 if (command->state != EC_CMD_RECEIVED) { |
|
216 fsm->master_state = ec_fsm_master_start; |
354 fsm->master_state = ec_fsm_master_start; |
217 fsm->master_state(fsm); // execute immediately |
355 fsm->master_state(fsm); // execute immediately |
218 return; |
356 return; |
219 } |
357 } |
220 |
358 |
221 topology_change = command->working_counter != |
359 // did the slave not respond to its station address? |
222 fsm->master_slaves_responding; |
360 if (command->working_counter != 1) { |
223 |
361 if (slave->online) { |
224 fsm->master_slaves_responding = command->working_counter; |
362 slave->online = 0; |
225 fsm->master_slave_states = command->data[0]; |
363 EC_INFO("Slave %i: offline.\n", slave->ring_position); |
226 |
364 } |
227 EC_INFO("FSM: %i slave%s responding (", fsm->master_slaves_responding, |
365 ec_fsm_master_action_next_slave_state(fsm); |
228 fsm->master_slaves_responding == 1 ? "" : "s"); |
366 return; |
229 ec_print_states(fsm->master_slave_states); |
367 } |
230 printk(")\n"); |
368 |
231 |
369 // slave responded |
232 if (!topology_change || fsm->master->mode == EC_MASTER_MODE_RUNNING) { |
370 new_state = EC_READ_U8(command->data); |
371 if (!slave->online) { // slave was offline before |
|
372 slave->online = 1; |
|
373 slave->state_error = 0; |
|
374 slave->current_state = new_state; |
|
375 EC_INFO("Slave %i: online (", slave->ring_position); |
|
376 ec_print_states(new_state); |
|
377 printk(").\n"); |
|
378 } |
|
379 else if (new_state != slave->current_state) { |
|
380 EC_INFO("Slave %i: ", slave->ring_position); |
|
381 ec_print_states(slave->current_state); |
|
382 printk(" -> "); |
|
383 ec_print_states(new_state); |
|
384 printk(".\n"); |
|
385 slave->current_state = new_state; |
|
386 } |
|
387 |
|
388 ec_fsm_master_action_next_slave_state(fsm); |
|
389 } |
|
390 |
|
391 /*****************************************************************************/ |
|
392 |
|
393 /** |
|
394 Master state: PROC_STATES. |
|
395 Processes the slave states. |
|
396 */ |
|
397 |
|
398 void ec_fsm_master_proc_states(ec_fsm_t *fsm /**< finite state machine */) |
|
399 { |
|
400 ec_master_t *master = fsm->master; |
|
401 ec_slave_t *slave; |
|
402 |
|
403 // check if any slaves are not in the state, they're supposed to be |
|
404 list_for_each_entry(slave, &master->slaves, list) { |
|
405 if (slave->state_error || !slave->online || |
|
406 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
|
407 slave->current_state == slave->requested_state) continue; |
|
408 |
|
409 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
|
410 ec_print_states(slave->current_state); |
|
411 printk(" to "); |
|
412 ec_print_states(slave->requested_state); |
|
413 printk(".\n"); |
|
414 |
|
415 fsm->slave = slave; |
|
416 fsm->slave_state = ec_fsm_slave_conf; |
|
417 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
418 fsm->change_state = ec_fsm_change_start; |
|
419 fsm->master_state = ec_fsm_master_conf; |
|
420 fsm->master_state(fsm); // execute immediately |
|
421 return; |
|
422 } |
|
423 |
|
424 // nothing to configure. restart master state machine. |
|
425 fsm->master_state = ec_fsm_master_start; |
|
426 fsm->master_state(fsm); // execute immediately |
|
427 } |
|
428 |
|
429 /*****************************************************************************/ |
|
430 |
|
431 /** |
|
432 Master state: VALIDATE_VENDOR. |
|
433 Validates the vendor ID of a slave. |
|
434 */ |
|
435 |
|
436 void ec_fsm_master_validate_vendor(ec_fsm_t *fsm /**< finite state machine */) |
|
437 { |
|
438 ec_slave_t *slave = fsm->slave; |
|
439 |
|
440 fsm->sii_state(fsm); // execute SII state machine |
|
441 |
|
442 if (fsm->sii_state == ec_fsm_sii_error) { |
|
443 EC_ERR("Failed to validate vendor ID of slave %i.\n", |
|
444 slave->ring_position); |
|
233 fsm->master_state = ec_fsm_master_start; |
445 fsm->master_state = ec_fsm_master_start; |
234 fsm->master_state(fsm); // execute immediately |
446 fsm->master_state(fsm); // execute immediately |
235 return; |
447 return; |
236 } |
448 } |
237 |
449 |
238 EC_INFO("Topology change detected - Scanning bus.\n"); |
450 if (fsm->sii_state != ec_fsm_sii_end) return; |
239 |
451 |
240 ec_master_eoe_stop(fsm->master); |
452 if (fsm->sii_result != slave->sii_vendor_id) { |
241 ec_master_clear_slaves(fsm->master); |
453 EC_ERR("Slave %i: invalid vendor ID!\n", slave->ring_position); |
242 |
|
243 if (!fsm->master_slaves_responding) { |
|
244 // no slaves present -> finish state machine. |
|
245 fsm->master_state = ec_fsm_master_start; |
454 fsm->master_state = ec_fsm_master_start; |
246 fsm->master_state(fsm); // execute immediately |
455 fsm->master_state(fsm); // execute immediately |
247 return; |
456 return; |
248 } |
457 } |
249 |
458 |
250 // init slaves |
459 // vendor ID is ok. check product code. |
251 for (i = 0; i < fsm->master_slaves_responding; i++) { |
460 fsm->master_state = ec_fsm_master_validate_product; |
252 if (!(slave = |
461 fsm->sii_offset = 0x000A; // product code |
253 (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_ATOMIC))) { |
462 fsm->sii_mode = 0; |
254 EC_ERR("FSM failed to allocate slave %i!\n", i); |
463 fsm->sii_state = ec_fsm_sii_start_reading; |
464 fsm->sii_state(fsm); // execute immediately |
|
465 } |
|
466 |
|
467 /*****************************************************************************/ |
|
468 |
|
469 /** |
|
470 Master state: VALIDATE_PRODUCT. |
|
471 Validates the product ID of a slave. |
|
472 */ |
|
473 |
|
474 void ec_fsm_master_validate_product(ec_fsm_t *fsm /**< finite state machine */) |
|
475 { |
|
476 ec_slave_t *slave = fsm->slave; |
|
477 |
|
478 fsm->sii_state(fsm); // execute SII state machine |
|
479 |
|
480 if (fsm->sii_state == ec_fsm_sii_error) { |
|
481 EC_ERR("Failed to validate product code of slave %i.\n", |
|
482 slave->ring_position); |
|
483 fsm->master_state = ec_fsm_master_start; |
|
484 fsm->master_state(fsm); // execute immediately |
|
485 return; |
|
486 } |
|
487 |
|
488 if (fsm->sii_state != ec_fsm_sii_end) return; |
|
489 |
|
490 if (fsm->sii_result != slave->sii_product_code) { |
|
491 EC_ERR("Slave %i: invalid product code!\n", slave->ring_position); |
|
492 EC_ERR("expected 0x%08X, got 0x%08X.\n", slave->sii_product_code, |
|
493 fsm->sii_result); |
|
494 fsm->master_state = ec_fsm_master_start; |
|
495 fsm->master_state(fsm); // execute immediately |
|
496 return; |
|
497 } |
|
498 |
|
499 // have all states been validated? |
|
500 if (slave->list.next == &fsm->master->slaves) { |
|
501 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
|
502 fsm->master_state = ec_fsm_master_reconfigure; |
|
503 return; |
|
504 } |
|
505 |
|
506 // validate next slave |
|
507 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
508 fsm->master_state = ec_fsm_master_validate_vendor; |
|
509 fsm->sii_offset = 0x0008; // vendor ID |
|
510 fsm->sii_mode = 0; |
|
511 fsm->sii_state = ec_fsm_sii_start_reading; |
|
512 fsm->sii_state(fsm); // execute immediately |
|
513 } |
|
514 |
|
515 /*****************************************************************************/ |
|
516 |
|
517 /** |
|
518 Master state: RECONFIGURE. |
|
519 Looks for slave, that have lost their configuration and writes |
|
520 their station address, so that they can be reconfigured later. |
|
521 */ |
|
522 |
|
523 void ec_fsm_master_reconfigure(ec_fsm_t *fsm /**< finite state machine */) |
|
524 { |
|
525 ec_command_t *command = &fsm->command; |
|
526 |
|
527 while (fsm->slave->online) { |
|
528 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
|
255 fsm->master_state = ec_fsm_master_start; |
529 fsm->master_state = ec_fsm_master_start; |
530 fsm->master_state(fsm); // execute immediately |
|
256 return; |
531 return; |
257 } |
532 } |
258 |
533 // check next slave |
259 if (ec_slave_init(slave, fsm->master, i, i + 1)) { |
534 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
260 fsm->master_state = ec_fsm_master_start; |
535 } |
261 return; |
536 |
262 } |
537 EC_INFO("Reinitializing slave %i.\n", fsm->slave->ring_position); |
263 |
538 |
264 if (kobject_add(&slave->kobj)) { |
539 // write station address |
265 EC_ERR("FSM failed to add kobject.\n"); |
540 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
266 kobject_put(&slave->kobj); // free |
541 EC_WRITE_U16(command->data, fsm->slave->station_address); |
267 fsm->master_state = ec_fsm_master_start; |
542 ec_master_queue_command(fsm->master, command); |
268 return; |
543 fsm->master_state = ec_fsm_master_address; |
269 } |
544 } |
270 |
545 |
271 list_add_tail(&slave->list, &fsm->master->slaves); |
546 /*****************************************************************************/ |
272 } |
547 |
273 |
548 /** |
274 // begin scanning of slaves |
549 Master state: ADDRESS. |
275 fsm->slave = list_entry(fsm->master->slaves.next, ec_slave_t, list); |
550 Checks, if the new station address has been written to the slave. |
276 fsm->slave_state = ec_fsm_slave_start_reading; |
551 */ |
277 |
552 |
278 fsm->master_state = ec_fsm_master_scan; |
553 void ec_fsm_master_address(ec_fsm_t *fsm /**< finite state machine */) |
554 { |
|
555 ec_slave_t *slave = fsm->slave; |
|
556 ec_command_t *command = &fsm->command; |
|
557 |
|
558 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
|
559 EC_ERR("Failed to write station address on slave %i.\n", |
|
560 slave->ring_position); |
|
561 } |
|
562 |
|
563 if (fsm->slave->list.next == &fsm->master->slaves) { // last slave? |
|
564 fsm->master_state = ec_fsm_master_start; |
|
565 fsm->master_state(fsm); // execute immediately |
|
566 return; |
|
567 } |
|
568 |
|
569 // check next slave |
|
570 fsm->slave = list_entry(fsm->slave->list.next, ec_slave_t, list); |
|
571 fsm->master_state = ec_fsm_master_reconfigure; |
|
279 fsm->master_state(fsm); // execute immediately |
572 fsm->master_state(fsm); // execute immediately |
280 } |
573 } |
281 |
574 |
282 /*****************************************************************************/ |
575 /*****************************************************************************/ |
283 |
576 |
284 /** |
577 /** |
285 State: Get Slave. |
578 Master state: SCAN. |
286 Executes the sub-statemachine of a slave. |
579 Executes the sub-statemachine for the scanning of a slave. |
287 */ |
580 */ |
288 |
581 |
289 void ec_fsm_master_scan(ec_fsm_t *fsm) |
582 void ec_fsm_master_scan(ec_fsm_t *fsm /**< finite state machine */) |
290 { |
583 { |
291 ec_master_t *master = fsm->master; |
584 ec_master_t *master = fsm->master; |
292 ec_slave_t *slave = fsm->slave; |
585 ec_slave_t *slave = fsm->slave; |
586 uint16_t coupler_index, coupler_subindex; |
|
587 uint16_t reverse_coupler_index, current_coupler_index; |
|
588 ec_slave_ident_t *ident; |
|
293 |
589 |
294 fsm->slave_state(fsm); // execute slave state machine |
590 fsm->slave_state(fsm); // execute slave state machine |
295 |
591 |
296 if (fsm->slave_state != ec_fsm_slave_end) return; |
592 if (fsm->slave_state != ec_fsm_slave_end) return; |
297 |
593 |
298 // have all slaves been fetched? |
594 // have all slaves been fetched? |
299 if (slave->list.next == &master->slaves) |
595 if (slave->list.next == &master->slaves) { |
300 { |
|
301 uint16_t coupler_index, coupler_subindex; |
|
302 uint16_t reverse_coupler_index, current_coupler_index; |
|
303 ec_slave_t *slave; |
|
304 ec_slave_ident_t *ident; |
|
305 |
|
306 EC_INFO("Bus scanning completed.\n"); |
596 EC_INFO("Bus scanning completed.\n"); |
307 |
597 |
308 // identify all slaves and calculate coupler addressing |
598 // identify all slaves and calculate coupler addressing |
309 |
599 |
310 coupler_index = 0; |
600 coupler_index = 0; |
350 if (master->mode == EC_MASTER_MODE_RUNNING) |
640 if (master->mode == EC_MASTER_MODE_RUNNING) |
351 slave->requested_state = EC_SLAVE_STATE_PREOP; |
641 slave->requested_state = EC_SLAVE_STATE_PREOP; |
352 else |
642 else |
353 slave->requested_state = EC_SLAVE_STATE_INIT; |
643 slave->requested_state = EC_SLAVE_STATE_INIT; |
354 } |
644 } |
645 slave->state_error = 0; |
|
355 |
646 |
356 // calculate coupler-based slave address |
647 // calculate coupler-based slave address |
357 slave->coupler_index = current_coupler_index; |
648 slave->coupler_index = current_coupler_index; |
358 slave->coupler_subindex = coupler_subindex; |
649 slave->coupler_subindex = coupler_subindex; |
359 coupler_subindex++; |
650 coupler_subindex++; |
360 } |
651 } |
361 |
652 |
653 if (master->mode == EC_MASTER_MODE_FREERUN) { |
|
654 // start EoE processing |
|
655 ec_master_eoe_start(master); |
|
656 } |
|
657 |
|
362 fsm->master_state = ec_fsm_master_start; |
658 fsm->master_state = ec_fsm_master_start; |
363 fsm->master_state(fsm); // execute immediately |
659 fsm->master_state(fsm); // execute immediately |
364 return; |
660 return; |
365 } |
661 } |
366 |
662 |
371 } |
667 } |
372 |
668 |
373 /*****************************************************************************/ |
669 /*****************************************************************************/ |
374 |
670 |
375 /** |
671 /** |
376 Free-Run state: Configure slaves. |
672 Master state: CONF. |
377 */ |
673 Starts configuring a slave. |
378 |
674 */ |
379 void ec_fsm_master_conf(ec_fsm_t *fsm) |
675 |
380 { |
676 void ec_fsm_master_conf(ec_fsm_t *fsm /**< finite state machine */) |
381 ec_master_t *master = fsm->master; |
677 { |
382 ec_slave_t *slave; |
|
383 |
|
384 fsm->slave_state(fsm); // execute slave's state machine |
678 fsm->slave_state(fsm); // execute slave's state machine |
385 |
|
386 if (fsm->slave_state != ec_fsm_slave_end) return; |
679 if (fsm->slave_state != ec_fsm_slave_end) return; |
387 |
680 fsm->master_state = ec_fsm_master_proc_states; |
388 // check if any slaves are not in the state, they're supposed to be |
|
389 list_for_each_entry(slave, &master->slaves, list) { |
|
390 if (slave->state_error || |
|
391 slave->requested_state == EC_SLAVE_STATE_UNKNOWN || |
|
392 slave->current_state == slave->requested_state) continue; |
|
393 |
|
394 EC_INFO("Changing state of slave %i from ", slave->ring_position); |
|
395 ec_print_states(slave->current_state); |
|
396 printk(" to "); |
|
397 ec_print_states(slave->requested_state); |
|
398 printk(".\n"); |
|
399 |
|
400 fsm->slave = slave; |
|
401 fsm->slave_state = ec_fsm_slave_conf; |
|
402 |
|
403 fsm->change_new = EC_SLAVE_STATE_INIT; |
|
404 fsm->change_state = ec_fsm_change_start; |
|
405 |
|
406 fsm->master_state = ec_fsm_master_conf; |
|
407 fsm->master_state(fsm); // execute immediately |
|
408 return; |
|
409 } |
|
410 |
|
411 fsm->master_state = ec_fsm_master_start; |
|
412 fsm->master_state(fsm); // execute immediately |
681 fsm->master_state(fsm); // execute immediately |
413 } |
682 } |
414 |
683 |
415 /****************************************************************************** |
684 /****************************************************************************** |
416 * slave state machine |
685 * slave state machine |
417 *****************************************************************************/ |
686 *****************************************************************************/ |
418 |
687 |
419 /** |
688 /** |
420 Slave state: Start. |
689 Slave state: START_READING. |
421 First state of the slave state machine. Writes the station address to the |
690 First state of the slave state machine. Writes the station address to the |
422 slave, according to its ring position. |
691 slave, according to its ring position. |
423 */ |
692 */ |
424 |
693 |
425 void ec_fsm_slave_start_reading(ec_fsm_t *fsm) |
694 void ec_fsm_slave_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
426 { |
695 { |
427 ec_command_t *command = &fsm->command; |
696 ec_command_t *command = &fsm->command; |
428 |
697 |
429 // write station address |
698 // write station address |
430 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
699 ec_command_apwr(command, fsm->slave->ring_position, 0x0010, 2); |
434 } |
703 } |
435 |
704 |
436 /*****************************************************************************/ |
705 /*****************************************************************************/ |
437 |
706 |
438 /** |
707 /** |
439 Slave state: Read status. |
708 Slave state: READ_STATUS. |
440 */ |
709 */ |
441 |
710 |
442 void ec_fsm_slave_read_status(ec_fsm_t *fsm) |
711 void ec_fsm_slave_read_status(ec_fsm_t *fsm /**< finite state machine */) |
443 { |
712 { |
444 ec_command_t *command = &fsm->command; |
713 ec_command_t *command = &fsm->command; |
445 |
714 |
446 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
715 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
447 EC_ERR("FSM failed to write station address of slave %i.\n", |
716 EC_ERR("FSM failed to write station address of slave %i.\n", |
457 } |
726 } |
458 |
727 |
459 /*****************************************************************************/ |
728 /*****************************************************************************/ |
460 |
729 |
461 /** |
730 /** |
462 Slave state: Read base. |
731 Slave state: READ_BASE. |
463 */ |
732 */ |
464 |
733 |
465 void ec_fsm_slave_read_base(ec_fsm_t *fsm) |
734 void ec_fsm_slave_read_base(ec_fsm_t *fsm /**< finite state machine */) |
466 { |
735 { |
467 ec_command_t *command = &fsm->command; |
736 ec_command_t *command = &fsm->command; |
468 ec_slave_t *slave = fsm->slave; |
737 ec_slave_t *slave = fsm->slave; |
469 |
738 |
470 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
739 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
488 } |
757 } |
489 |
758 |
490 /*****************************************************************************/ |
759 /*****************************************************************************/ |
491 |
760 |
492 /** |
761 /** |
493 Slave state: Read DL. |
762 Slave state: READ_DL. |
494 */ |
763 */ |
495 |
764 |
496 void ec_fsm_slave_read_dl(ec_fsm_t *fsm) |
765 void ec_fsm_slave_read_dl(ec_fsm_t *fsm /**< finite state machine */) |
497 { |
766 { |
498 ec_command_t *command = &fsm->command; |
767 ec_command_t *command = &fsm->command; |
499 ec_slave_t *slave = fsm->slave; |
768 ec_slave_t *slave = fsm->slave; |
500 |
769 |
501 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
770 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
521 } |
790 } |
522 |
791 |
523 /*****************************************************************************/ |
792 /*****************************************************************************/ |
524 |
793 |
525 /** |
794 /** |
526 Slave state: Prepare SII. |
795 Slave state: PREPARE_SII. |
527 */ |
796 */ |
528 |
797 |
529 void ec_fsm_slave_prepare_sii(ec_fsm_t *fsm) |
798 void ec_fsm_slave_prepare_sii(ec_fsm_t *fsm /**< finite state machine */) |
530 { |
799 { |
531 ec_command_t *command = &fsm->command; |
800 ec_command_t *command = &fsm->command; |
532 ec_slave_t *slave = fsm->slave; |
801 ec_slave_t *slave = fsm->slave; |
533 uint16_t dl_status; |
802 uint16_t dl_status; |
534 unsigned int i; |
803 unsigned int i; |
547 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
816 slave->dl_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; |
548 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
817 slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0; |
549 } |
818 } |
550 |
819 |
551 fsm->sii_offset = 0x0004; |
820 fsm->sii_offset = 0x0004; |
821 fsm->sii_mode = 1; |
|
552 fsm->sii_state = ec_fsm_sii_start_reading; |
822 fsm->sii_state = ec_fsm_sii_start_reading; |
553 fsm->slave_sii_num = 0; |
823 fsm->slave_sii_num = 0; |
554 fsm->slave_state = ec_fsm_slave_read_sii; |
824 fsm->slave_state = ec_fsm_slave_read_sii; |
555 fsm->slave_state(fsm); // execute state immediately |
825 fsm->slave_state(fsm); // execute state immediately |
556 } |
826 } |
557 |
827 |
558 /*****************************************************************************/ |
828 /*****************************************************************************/ |
559 |
829 |
560 /** |
830 /** |
561 Slave state: Read SII. |
831 Slave state: READ_SII. |
562 */ |
832 */ |
563 |
833 |
564 void ec_fsm_slave_read_sii(ec_fsm_t *fsm) |
834 void ec_fsm_slave_read_sii(ec_fsm_t *fsm /**< finite state machine */) |
565 { |
835 { |
566 ec_slave_t *slave = fsm->slave; |
836 ec_slave_t *slave = fsm->slave; |
567 |
837 |
568 // execute SII state machine |
838 // execute SII state machine |
569 fsm->sii_state(fsm); |
839 fsm->sii_state(fsm); |
573 EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n", |
843 EC_ERR("FSM failed to read SII data at 0x%04X on slave %i.\n", |
574 fsm->sii_offset, slave->ring_position); |
844 fsm->sii_offset, slave->ring_position); |
575 return; |
845 return; |
576 } |
846 } |
577 |
847 |
578 if (fsm->sii_state != ec_fsm_sii_finished) return; |
848 if (fsm->sii_state != ec_fsm_sii_end) return; |
579 |
849 |
580 switch (fsm->slave_sii_num) { |
850 switch (fsm->slave_sii_num) { |
581 case 0: |
851 case 0: |
582 slave->sii_alias = fsm->sii_result & 0xFFFF; |
852 slave->sii_alias = fsm->sii_result & 0xFFFF; |
583 fsm->sii_offset = 0x0008; |
853 fsm->sii_offset = 0x0008; |
641 } |
911 } |
642 |
912 |
643 /*****************************************************************************/ |
913 /*****************************************************************************/ |
644 |
914 |
645 /** |
915 /** |
646 Slave state: Read categories. |
916 Slave state: CATEGORY_HEADER. |
647 Start reading categories. |
917 Start reading categories. |
648 */ |
918 */ |
649 |
919 |
650 void ec_fsm_slave_category_header(ec_fsm_t *fsm) |
920 void ec_fsm_slave_category_header(ec_fsm_t *fsm /**< finite state machine */) |
651 { |
921 { |
652 // execute SII state machine |
922 // execute SII state machine |
653 fsm->sii_state(fsm); |
923 fsm->sii_state(fsm); |
654 |
924 |
655 if (fsm->sii_state == ec_fsm_sii_error) { |
925 if (fsm->sii_state == ec_fsm_sii_error) { |
659 EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n", |
929 EC_ERR("FSM failed to read category header at 0x%04X on slave %i.\n", |
660 fsm->slave_cat_offset, fsm->slave->ring_position); |
930 fsm->slave_cat_offset, fsm->slave->ring_position); |
661 return; |
931 return; |
662 } |
932 } |
663 |
933 |
664 if (fsm->sii_state != ec_fsm_sii_finished) return; |
934 if (fsm->sii_state != ec_fsm_sii_end) return; |
665 |
935 |
666 // last category? |
936 // last category? |
667 if ((fsm->sii_result & 0xFFFF) == 0xFFFF) { |
937 if ((fsm->sii_result & 0xFFFF) == 0xFFFF) { |
668 kfree(fsm->slave_cat_data); |
938 kfree(fsm->slave_cat_data); |
669 fsm->slave_cat_data = NULL; |
939 fsm->slave_cat_data = NULL; |
683 |
953 |
684 // start reading category data |
954 // start reading category data |
685 fsm->slave_cat_data_offset = 0; |
955 fsm->slave_cat_data_offset = 0; |
686 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
956 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
687 fsm->slave_cat_data_offset); |
957 fsm->slave_cat_data_offset); |
958 fsm->sii_mode = 1; |
|
688 fsm->sii_state = ec_fsm_sii_start_reading; |
959 fsm->sii_state = ec_fsm_sii_start_reading; |
689 fsm->slave_state = ec_fsm_slave_category_data; |
960 fsm->slave_state = ec_fsm_slave_category_data; |
690 fsm->slave_state(fsm); // execute state immediately |
961 fsm->slave_state(fsm); // execute state immediately |
691 } |
962 } |
692 |
963 |
693 /*****************************************************************************/ |
964 /*****************************************************************************/ |
694 |
965 |
695 /** |
966 /** |
696 Slave state: Category data. |
967 Slave state: CATEGORY_DATA. |
697 Reads category data. |
968 Reads category data. |
698 */ |
969 */ |
699 |
970 |
700 void ec_fsm_slave_category_data(ec_fsm_t *fsm) |
971 void ec_fsm_slave_category_data(ec_fsm_t *fsm /**< finite state machine */) |
701 { |
972 { |
702 // execute SII state machine |
973 // execute SII state machine |
703 fsm->sii_state(fsm); |
974 fsm->sii_state(fsm); |
704 |
975 |
705 if (fsm->sii_state == ec_fsm_sii_error) { |
976 if (fsm->sii_state == ec_fsm_sii_error) { |
710 " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset, |
981 " on slave %i.\n", fsm->slave_cat_type, fsm->sii_offset, |
711 fsm->slave->ring_position); |
982 fsm->slave->ring_position); |
712 return; |
983 return; |
713 } |
984 } |
714 |
985 |
715 if (fsm->sii_state != ec_fsm_sii_finished) return; |
986 if (fsm->sii_state != ec_fsm_sii_end) return; |
716 |
987 |
717 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] = |
988 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2] = |
718 fsm->sii_result & 0xFF; |
989 fsm->sii_result & 0xFF; |
719 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] = |
990 fsm->slave_cat_data[fsm->slave_cat_data_offset * 2 + 1] = |
720 (fsm->sii_result >> 8) & 0xFF; |
991 (fsm->sii_result >> 8) & 0xFF; |
731 fsm->slave_cat_data_offset++; |
1002 fsm->slave_cat_data_offset++; |
732 |
1003 |
733 if (fsm->slave_cat_data_offset < fsm->slave_cat_words) { |
1004 if (fsm->slave_cat_data_offset < fsm->slave_cat_words) { |
734 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
1005 fsm->sii_offset = (fsm->slave_cat_offset + 2 + |
735 fsm->slave_cat_data_offset); |
1006 fsm->slave_cat_data_offset); |
1007 fsm->sii_mode = 1; |
|
736 fsm->sii_state = ec_fsm_sii_start_reading; |
1008 fsm->sii_state = ec_fsm_sii_start_reading; |
737 fsm->slave_state = ec_fsm_slave_category_data; |
1009 fsm->slave_state = ec_fsm_slave_category_data; |
738 fsm->slave_state(fsm); // execute state immediately |
1010 fsm->slave_state(fsm); // execute state immediately |
739 return; |
1011 return; |
740 } |
1012 } |
775 } |
1047 } |
776 |
1048 |
777 // start reading next category header |
1049 // start reading next category header |
778 fsm->slave_cat_offset += 2 + fsm->slave_cat_words; |
1050 fsm->slave_cat_offset += 2 + fsm->slave_cat_words; |
779 fsm->sii_offset = fsm->slave_cat_offset; |
1051 fsm->sii_offset = fsm->slave_cat_offset; |
1052 fsm->sii_mode = 1; |
|
780 fsm->sii_state = ec_fsm_sii_start_reading; |
1053 fsm->sii_state = ec_fsm_sii_start_reading; |
781 fsm->slave_state = ec_fsm_slave_category_header; |
1054 fsm->slave_state = ec_fsm_slave_category_header; |
782 fsm->slave_state(fsm); // execute state immediately |
1055 fsm->slave_state(fsm); // execute state immediately |
783 return; |
1056 return; |
784 |
1057 |
789 } |
1062 } |
790 |
1063 |
791 /*****************************************************************************/ |
1064 /*****************************************************************************/ |
792 |
1065 |
793 /** |
1066 /** |
794 Slave state: Start configuring. |
1067 Slave state: CONF. |
795 */ |
1068 */ |
796 |
1069 |
797 void ec_fsm_slave_conf(ec_fsm_t *fsm) |
1070 void ec_fsm_slave_conf(ec_fsm_t *fsm /**< finite state machine */) |
798 { |
1071 { |
799 ec_slave_t *slave = fsm->slave; |
1072 ec_slave_t *slave = fsm->slave; |
800 ec_master_t *master = fsm->master; |
1073 ec_master_t *master = fsm->master; |
801 ec_command_t *command = &fsm->command; |
1074 ec_command_t *command = &fsm->command; |
802 |
1075 |
838 } |
1111 } |
839 |
1112 |
840 /*****************************************************************************/ |
1113 /*****************************************************************************/ |
841 |
1114 |
842 /** |
1115 /** |
843 Slave state: Configure sync managers. |
1116 Slave state: SYNC. |
844 */ |
1117 Configure sync managers. |
845 |
1118 */ |
846 void ec_fsm_slave_sync(ec_fsm_t *fsm) |
1119 |
1120 void ec_fsm_slave_sync(ec_fsm_t *fsm /**< finite state machine */) |
|
847 { |
1121 { |
848 ec_command_t *command = &fsm->command; |
1122 ec_command_t *command = &fsm->command; |
849 ec_slave_t *slave = fsm->slave; |
1123 ec_slave_t *slave = fsm->slave; |
850 unsigned int j; |
1124 unsigned int j; |
851 const ec_sync_t *sync; |
1125 const ec_sync_t *sync; |
852 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
1126 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
853 |
1127 |
854 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1128 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
855 EC_ERR("FSM failed to reset FMMUs of slave %i.\n", |
1129 EC_ERR("Failed to reset FMMUs of slave %i.\n", |
856 slave->ring_position); |
1130 slave->ring_position); |
1131 slave->state_error = 1; |
|
857 fsm->slave_state = ec_fsm_slave_end; |
1132 fsm->slave_state = ec_fsm_slave_end; |
858 return; |
1133 return; |
859 } |
1134 } |
860 |
1135 |
861 if (!slave->base_sync_count) { // no sync managers |
1136 if (!slave->base_sync_count) { // no sync managers |
921 } |
1196 } |
922 |
1197 |
923 /*****************************************************************************/ |
1198 /*****************************************************************************/ |
924 |
1199 |
925 /** |
1200 /** |
926 Slave state: Change slave state to PREOP. |
1201 Slave state: PREOP. |
927 */ |
1202 Change slave state to PREOP. |
928 |
1203 */ |
929 void ec_fsm_slave_preop(ec_fsm_t *fsm) |
1204 |
1205 void ec_fsm_slave_preop(ec_fsm_t *fsm /**< finite state machine */) |
|
930 { |
1206 { |
931 ec_command_t *command = &fsm->command; |
1207 ec_command_t *command = &fsm->command; |
932 ec_slave_t *slave = fsm->slave; |
1208 ec_slave_t *slave = fsm->slave; |
933 |
1209 |
934 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1210 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
935 EC_ERR("FSM failed to set sync managers on slave %i.\n", |
1211 EC_ERR("Failed to set sync managers on slave %i.\n", |
936 slave->ring_position); |
1212 slave->ring_position); |
1213 slave->state_error = 1; |
|
937 fsm->slave_state = ec_fsm_slave_end; |
1214 fsm->slave_state = ec_fsm_slave_end; |
938 return; |
1215 return; |
939 } |
1216 } |
940 |
1217 |
941 fsm->change_new = EC_SLAVE_STATE_PREOP; |
1218 fsm->change_new = EC_SLAVE_STATE_PREOP; |
942 fsm->change_state = ec_fsm_change_start; |
1219 fsm->change_state = ec_fsm_change_start; |
943 |
|
944 fsm->slave_state = ec_fsm_slave_fmmu; |
1220 fsm->slave_state = ec_fsm_slave_fmmu; |
945 |
|
946 fsm->change_state(fsm); // execute immediately |
1221 fsm->change_state(fsm); // execute immediately |
947 } |
1222 } |
948 |
1223 |
949 /*****************************************************************************/ |
1224 /*****************************************************************************/ |
950 |
1225 |
951 /** |
1226 /** |
952 Slave state: Configure FMMUs. |
1227 Slave state: FMMU. |
953 */ |
1228 Configure FMMUs. |
954 |
1229 */ |
955 void ec_fsm_slave_fmmu(ec_fsm_t *fsm) |
1230 |
1231 void ec_fsm_slave_fmmu(ec_fsm_t *fsm /**< finite state machine */) |
|
956 { |
1232 { |
957 ec_slave_t *slave = fsm->slave; |
1233 ec_slave_t *slave = fsm->slave; |
958 ec_master_t *master = fsm->master; |
1234 ec_master_t *master = fsm->master; |
959 ec_command_t *command = &fsm->command; |
1235 ec_command_t *command = &fsm->command; |
960 unsigned int j; |
1236 unsigned int j; |
977 // stop activation here for slaves without type |
1253 // stop activation here for slaves without type |
978 if (!slave->type) { |
1254 if (!slave->type) { |
979 fsm->slave_state = ec_fsm_slave_end; |
1255 fsm->slave_state = ec_fsm_slave_end; |
980 return; |
1256 return; |
981 } |
1257 } |
982 |
|
983 #if 0 |
|
984 // slaves that are not registered are only brought into PREOP |
|
985 // state -> nice blinking and mailbox communication possible |
|
986 if (!slave->registered && !slave->type->special) { |
|
987 EC_WARN("Slave %i was not registered!\n", slave->ring_position); |
|
988 fsm->slave_state = ec_fsm_slave_end; |
|
989 return; |
|
990 } |
|
991 #endif |
|
992 |
1258 |
993 if (!slave->base_fmmu_count) { |
1259 if (!slave->base_fmmu_count) { |
994 fsm->slave_state = ec_fsm_slave_saveop; |
1260 fsm->slave_state = ec_fsm_slave_saveop; |
995 fsm->slave_state(fsm); // execute immediately |
1261 fsm->slave_state(fsm); // execute immediately |
996 return; |
1262 return; |
1009 } |
1275 } |
1010 |
1276 |
1011 /*****************************************************************************/ |
1277 /*****************************************************************************/ |
1012 |
1278 |
1013 /** |
1279 /** |
1014 Slave state: Set slave state to SAVEOP. |
1280 Slave state: SAVEOP. |
1015 */ |
1281 Set slave state to SAVEOP. |
1016 |
1282 */ |
1017 void ec_fsm_slave_saveop(ec_fsm_t *fsm) |
1283 |
1284 void ec_fsm_slave_saveop(ec_fsm_t *fsm /**< finite state machine */) |
|
1018 { |
1285 { |
1019 ec_command_t *command = &fsm->command; |
1286 ec_command_t *command = &fsm->command; |
1020 |
1287 |
1021 if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED || |
1288 if (fsm->slave->base_fmmu_count && (command->state != EC_CMD_RECEIVED || |
1022 command->working_counter != 1)) { |
1289 command->working_counter != 1)) { |
1023 EC_ERR("FSM failed to set FMMUs on slave %i.\n", |
1290 EC_ERR("FSM failed to set FMMUs on slave %i.\n", |
1024 fsm->slave->ring_position); |
1291 fsm->slave->ring_position); |
1292 fsm->slave->state_error = 1; |
|
1025 fsm->slave_state = ec_fsm_slave_end; |
1293 fsm->slave_state = ec_fsm_slave_end; |
1026 return; |
1294 return; |
1027 } |
1295 } |
1028 |
1296 |
1029 // set state to SAVEOP |
1297 // set state to SAVEOP |
1034 } |
1302 } |
1035 |
1303 |
1036 /*****************************************************************************/ |
1304 /*****************************************************************************/ |
1037 |
1305 |
1038 /** |
1306 /** |
1039 Slave state: Set slave state to OP. |
1307 Slave state: OP. |
1040 */ |
1308 Set slave state to OP. |
1041 |
1309 */ |
1042 void ec_fsm_slave_op(ec_fsm_t *fsm) |
1310 |
1311 void ec_fsm_slave_op(ec_fsm_t *fsm /**< finite state machine */) |
|
1043 { |
1312 { |
1044 fsm->change_state(fsm); // execute state change state machine |
1313 fsm->change_state(fsm); // execute state change state machine |
1045 |
1314 |
1046 if (fsm->change_state == ec_fsm_change_error) { |
1315 if (fsm->change_state == ec_fsm_change_error) { |
1047 fsm->slave_state = ec_fsm_slave_end; |
1316 fsm->slave_state = ec_fsm_slave_end; |
1064 } |
1333 } |
1065 |
1334 |
1066 /*****************************************************************************/ |
1335 /*****************************************************************************/ |
1067 |
1336 |
1068 /** |
1337 /** |
1069 Slave state: Set slave state to OP. |
1338 Slave state: OP2 |
1070 */ |
1339 Executes the change state machine, until the OP state is set. |
1071 |
1340 */ |
1072 void ec_fsm_slave_op2(ec_fsm_t *fsm) |
1341 |
1342 void ec_fsm_slave_op2(ec_fsm_t *fsm /**< finite state machine */) |
|
1073 { |
1343 { |
1074 fsm->change_state(fsm); // execute state change state machine |
1344 fsm->change_state(fsm); // execute state change state machine |
1075 |
1345 |
1076 if (fsm->change_state == ec_fsm_change_error) { |
1346 if (fsm->change_state == ec_fsm_change_error) { |
1077 fsm->slave_state = ec_fsm_slave_end; |
1347 fsm->slave_state = ec_fsm_slave_end; |
1085 } |
1355 } |
1086 |
1356 |
1087 /*****************************************************************************/ |
1357 /*****************************************************************************/ |
1088 |
1358 |
1089 /** |
1359 /** |
1090 Slave state: End. |
1360 Slave state: END. |
1091 End state of the slave state machine. |
1361 End state of the slave state machine. |
1092 */ |
1362 */ |
1093 |
1363 |
1094 void ec_fsm_slave_end(ec_fsm_t *fsm) |
1364 void ec_fsm_slave_end(ec_fsm_t *fsm /**< finite state machine */) |
1095 { |
1365 { |
1096 } |
1366 } |
1097 |
1367 |
1098 /****************************************************************************** |
1368 /****************************************************************************** |
1099 * SII state machine |
1369 * SII state machine |
1100 *****************************************************************************/ |
1370 *****************************************************************************/ |
1101 |
1371 |
1102 /** |
1372 /** |
1103 Slave SII state: Start reading. |
1373 SII state: START_READING. |
1104 Starts reading the slave information interface. |
1374 Starts reading the slave information interface. |
1105 */ |
1375 */ |
1106 |
1376 |
1107 void ec_fsm_sii_start_reading(ec_fsm_t *fsm) |
1377 void ec_fsm_sii_start_reading(ec_fsm_t *fsm /**< finite state machine */) |
1108 { |
1378 { |
1109 ec_command_t *command = &fsm->command; |
1379 ec_command_t *command = &fsm->command; |
1110 |
1380 |
1111 // initiate read operation |
1381 // initiate read operation |
1112 ec_command_npwr(command, fsm->slave->station_address, 0x502, 6); |
1382 if (fsm->sii_mode) { |
1383 ec_command_npwr(command, fsm->slave->station_address, 0x502, 4); |
|
1384 } |
|
1385 else { |
|
1386 ec_command_apwr(command, fsm->slave->ring_position, 0x502, 4); |
|
1387 } |
|
1388 |
|
1113 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1389 EC_WRITE_U8 (command->data, 0x00); // read-only access |
1114 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1390 EC_WRITE_U8 (command->data + 1, 0x01); // request read operation |
1115 EC_WRITE_U32(command->data + 2, fsm->sii_offset); |
1391 EC_WRITE_U16(command->data + 2, fsm->sii_offset); |
1116 ec_master_queue_command(fsm->master, command); |
1392 ec_master_queue_command(fsm->master, command); |
1117 fsm->sii_state = ec_fsm_sii_check; |
1393 fsm->sii_state = ec_fsm_sii_check; |
1118 } |
1394 } |
1119 |
1395 |
1120 /*****************************************************************************/ |
1396 /*****************************************************************************/ |
1121 |
1397 |
1122 /** |
1398 /** |
1123 Slave SII state: Check. |
1399 SII state: CHECK. |
1124 Checks, if the SII-read-command has been sent and issues a fetch command. |
1400 Checks, if the SII-read-command has been sent and issues a fetch command. |
1125 */ |
1401 */ |
1126 |
1402 |
1127 void ec_fsm_sii_check(ec_fsm_t *fsm) |
1403 void ec_fsm_sii_check(ec_fsm_t *fsm /**< finite state machine */) |
1128 { |
1404 { |
1129 ec_command_t *command = &fsm->command; |
1405 ec_command_t *command = &fsm->command; |
1130 |
1406 |
1131 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1407 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1132 EC_ERR("FSM SII: Reception of check command failed.\n"); |
1408 EC_ERR("SII: Reception of read command failed.\n"); |
1133 fsm->sii_state = ec_fsm_sii_error; |
1409 fsm->sii_state = ec_fsm_sii_error; |
1134 return; |
1410 return; |
1135 } |
1411 } |
1136 |
1412 |
1137 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
1413 fsm->sii_start = get_cycles(); |
1414 |
|
1415 // issue check/fetch command |
|
1416 if (fsm->sii_mode) { |
|
1417 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
|
1418 } |
|
1419 else { |
|
1420 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
|
1421 } |
|
1422 |
|
1138 ec_master_queue_command(fsm->master, command); |
1423 ec_master_queue_command(fsm->master, command); |
1139 fsm->sii_state = ec_fsm_sii_fetch; |
1424 fsm->sii_state = ec_fsm_sii_fetch; |
1140 } |
1425 } |
1141 |
1426 |
1142 /*****************************************************************************/ |
1427 /*****************************************************************************/ |
1143 |
1428 |
1144 /** |
1429 /** |
1145 Slave SII state: Fetch. |
1430 SII state: FETCH. |
1146 Fetches the result of an SII-read command. |
1431 Fetches the result of an SII-read command. |
1147 */ |
1432 */ |
1148 |
1433 |
1149 void ec_fsm_sii_fetch(ec_fsm_t *fsm) |
1434 void ec_fsm_sii_fetch(ec_fsm_t *fsm /**< finite state machine */) |
1150 { |
1435 { |
1151 ec_command_t *command = &fsm->command; |
1436 ec_command_t *command = &fsm->command; |
1152 |
1437 |
1153 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1438 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1154 EC_ERR("FSM SII: Reception of fetch command failed.\n"); |
1439 EC_ERR("SII: Reception of check/fetch command failed.\n"); |
1155 fsm->sii_state = ec_fsm_sii_error; |
1440 fsm->sii_state = ec_fsm_sii_error; |
1156 return; |
1441 return; |
1157 } |
1442 } |
1158 |
1443 |
1159 // check "busy bit" |
1444 // check "busy bit" |
1160 if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) { |
1445 if (EC_READ_U8(command->data + 1) & 0x81) { |
1161 fsm->sii_result = EC_READ_U32(command->data + 6); |
1446 // still busy... timeout? |
1162 fsm->sii_state = ec_fsm_sii_finished; |
1447 if (get_cycles() - fsm->sii_start >= (cycles_t) 10 * cpu_khz) { |
1163 } |
1448 EC_ERR("SII: Timeout.\n"); |
1164 } |
1449 fsm->sii_state = ec_fsm_sii_error; |
1165 |
1450 #if 0 |
1166 /*****************************************************************************/ |
1451 EC_DBG("SII busy: %02X %02X %02X %02X\n", |
1167 |
1452 EC_READ_U8(command->data + 0), |
1168 /** |
1453 EC_READ_U8(command->data + 1), |
1169 Slave SII state: Finished. |
1454 EC_READ_U8(command->data + 2), |
1455 EC_READ_U8(command->data + 3)); |
|
1456 #endif |
|
1457 } |
|
1458 |
|
1459 // issue check/fetch command again |
|
1460 if (fsm->sii_mode) { |
|
1461 ec_command_nprd(command, fsm->slave->station_address, 0x502, 10); |
|
1462 } |
|
1463 else { |
|
1464 ec_command_aprd(command, fsm->slave->ring_position, 0x502, 10); |
|
1465 } |
|
1466 ec_master_queue_command(fsm->master, command); |
|
1467 return; |
|
1468 } |
|
1469 |
|
1470 #if 0 |
|
1471 EC_DBG("SII rec: %02X %02X %02X %02X - %02X %02X %02X %02X\n", |
|
1472 EC_READ_U8(command->data + 0), EC_READ_U8(command->data + 1), |
|
1473 EC_READ_U8(command->data + 2), EC_READ_U8(command->data + 3), |
|
1474 EC_READ_U8(command->data + 6), EC_READ_U8(command->data + 7), |
|
1475 EC_READ_U8(command->data + 8), EC_READ_U8(command->data + 9)); |
|
1476 #endif |
|
1477 |
|
1478 // SII value received. |
|
1479 fsm->sii_result = EC_READ_U32(command->data + 6); |
|
1480 fsm->sii_state = ec_fsm_sii_end; |
|
1481 } |
|
1482 |
|
1483 /*****************************************************************************/ |
|
1484 |
|
1485 /** |
|
1486 SII state: END. |
|
1170 End state of the slave SII state machine. |
1487 End state of the slave SII state machine. |
1171 */ |
1488 */ |
1172 |
1489 |
1173 void ec_fsm_sii_finished(ec_fsm_t *fsm) |
1490 void ec_fsm_sii_end(ec_fsm_t *fsm /**< finite state machine */) |
1174 { |
1491 { |
1175 } |
1492 } |
1176 |
1493 |
1177 /*****************************************************************************/ |
1494 /*****************************************************************************/ |
1178 |
1495 |
1179 /** |
1496 /** |
1180 Slave SII state: Error. |
1497 SII state: ERROR. |
1181 End state of the slave SII state machine. |
1498 End state of the slave SII state machine. |
1182 */ |
1499 */ |
1183 |
1500 |
1184 void ec_fsm_sii_error(ec_fsm_t *fsm) |
1501 void ec_fsm_sii_error(ec_fsm_t *fsm /**< finite state machine */) |
1185 { |
1502 { |
1186 } |
1503 } |
1187 |
1504 |
1188 /****************************************************************************** |
1505 /****************************************************************************** |
1189 * state change state machine |
1506 * state change state machine |
1190 *****************************************************************************/ |
1507 *****************************************************************************/ |
1191 |
1508 |
1192 /** |
1509 /** |
1193 State change state: Start. |
1510 Change state: START. |
1194 */ |
1511 */ |
1195 |
1512 |
1196 void ec_fsm_change_start(ec_fsm_t *fsm) |
1513 void ec_fsm_change_start(ec_fsm_t *fsm /**< finite state machine */) |
1197 { |
1514 { |
1198 ec_command_t *command = &fsm->command; |
1515 ec_command_t *command = &fsm->command; |
1199 ec_slave_t *slave = fsm->slave; |
1516 ec_slave_t *slave = fsm->slave; |
1200 |
1517 |
1201 // write new state to slave |
1518 // write new state to slave |
1206 } |
1523 } |
1207 |
1524 |
1208 /*****************************************************************************/ |
1525 /*****************************************************************************/ |
1209 |
1526 |
1210 /** |
1527 /** |
1211 State change state: Check. |
1528 Change state: CHECK. |
1212 */ |
1529 */ |
1213 |
1530 |
1214 void ec_fsm_change_check(ec_fsm_t *fsm) |
1531 void ec_fsm_change_check(ec_fsm_t *fsm /**< finite state machine */) |
1215 { |
1532 { |
1216 ec_command_t *command = &fsm->command; |
1533 ec_command_t *command = &fsm->command; |
1217 ec_slave_t *slave = fsm->slave; |
1534 ec_slave_t *slave = fsm->slave; |
1218 |
1535 |
1219 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1536 if (command->state != EC_CMD_RECEIVED) { |
1220 EC_ERR("FSM: Reception of state command failed.\n"); |
1537 EC_ERR("Failed to send state command to slave %i!\n", |
1538 fsm->slave->ring_position); |
|
1221 slave->state_error = 1; |
1539 slave->state_error = 1; |
1222 fsm->change_state = ec_fsm_change_error; |
1540 fsm->change_state = ec_fsm_change_error; |
1223 return; |
1541 return; |
1224 } |
1542 } |
1225 |
1543 |
1226 //start = get_cycles(); |
1544 if (command->working_counter != 1) { |
1227 //timeout = (cycles_t) 10 * cpu_khz; // 10ms |
1545 EC_ERR("Failed to set state 0x%02X on slave %i: Slave did not" |
1546 " respond.\n", fsm->change_new, fsm->slave->ring_position); |
|
1547 slave->state_error = 1; |
|
1548 fsm->change_state = ec_fsm_change_error; |
|
1549 return; |
|
1550 } |
|
1551 |
|
1552 fsm->change_start = get_cycles(); |
|
1228 |
1553 |
1229 // read AL status from slave |
1554 // read AL status from slave |
1230 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1555 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1231 ec_master_queue_command(fsm->master, command); |
1556 ec_master_queue_command(fsm->master, command); |
1232 fsm->change_state = ec_fsm_change_status; |
1557 fsm->change_state = ec_fsm_change_status; |
1233 } |
1558 } |
1234 |
1559 |
1235 /*****************************************************************************/ |
1560 /*****************************************************************************/ |
1236 |
1561 |
1237 /** |
1562 /** |
1238 State change state: Status. |
1563 Change state: STATUS. |
1239 */ |
1564 */ |
1240 |
1565 |
1241 void ec_fsm_change_status(ec_fsm_t *fsm) |
1566 void ec_fsm_change_status(ec_fsm_t *fsm /**< finite state machine */) |
1242 { |
1567 { |
1243 ec_command_t *command = &fsm->command; |
1568 ec_command_t *command = &fsm->command; |
1244 ec_slave_t *slave = fsm->slave; |
1569 ec_slave_t *slave = fsm->slave; |
1245 |
1570 |
1246 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1571 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1247 EC_ERR("FSM: Reception of state check command failed.\n"); |
1572 EC_ERR("Failed to check state 0x%02X on slave %i.\n", |
1573 fsm->change_new, slave->ring_position); |
|
1248 slave->state_error = 1; |
1574 slave->state_error = 1; |
1249 fsm->change_state = ec_fsm_change_error; |
1575 fsm->change_state = ec_fsm_change_error; |
1250 return; |
1576 return; |
1251 } |
1577 } |
1252 |
1578 |
1253 slave->current_state = EC_READ_U8(command->data); |
1579 slave->current_state = EC_READ_U8(command->data); |
1254 |
1580 |
1255 if (slave->current_state & 0x10) { // state change error |
1581 if (slave->current_state == fsm->change_new) { |
1582 // state has been set successfully |
|
1583 fsm->change_state = ec_fsm_change_end; |
|
1584 return; |
|
1585 } |
|
1586 |
|
1587 if (slave->current_state & 0x10) { |
|
1588 // state change error |
|
1589 fsm->change_new = slave->current_state & 0x0F; |
|
1256 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1590 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
1257 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1591 " (code 0x%02X)!\n", fsm->change_new, slave->ring_position, |
1258 slave->current_state); |
1592 slave->current_state); |
1259 |
|
1260 fsm->change_new = slave->current_state & 0x0F; |
|
1261 |
|
1262 // fetch AL status error code |
1593 // fetch AL status error code |
1263 ec_command_nprd(command, slave->station_address, 0x0134, 2); |
1594 ec_command_nprd(command, slave->station_address, 0x0134, 2); |
1264 ec_master_queue_command(fsm->master, command); |
1595 ec_master_queue_command(fsm->master, command); |
1265 fsm->change_state = ec_fsm_change_code; |
1596 fsm->change_state = ec_fsm_change_code; |
1266 return; |
1597 return; |
1267 } |
1598 } |
1268 |
1599 |
1269 if (slave->current_state == fsm->change_new) { |
1600 if (get_cycles() - fsm->change_start >= (cycles_t) 10 * cpu_khz) { |
1270 fsm->change_state = ec_fsm_change_end; |
1601 // timeout while checking |
1271 return; |
1602 slave->state_error = 1; |
1272 } |
1603 fsm->change_state = ec_fsm_change_error; |
1273 |
1604 EC_ERR("Timeout while setting state 0x%02X on slave %i.\n", |
1274 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
1605 fsm->change_new, slave->ring_position); |
1275 fsm->change_new, slave->ring_position); |
1606 return; |
1276 slave->state_error = 1; |
1607 } |
1277 fsm->change_state = ec_fsm_change_error; |
1608 |
1278 } |
1609 // still old state: check again |
1279 |
1610 ec_command_nprd(command, slave->station_address, 0x0130, 2); |
1280 /*****************************************************************************/ |
1611 ec_master_queue_command(fsm->master, command); |
1281 |
1612 } |
1282 /** |
1613 |
1283 State change state: Code. |
1614 /*****************************************************************************/ |
1284 */ |
1615 |
1285 |
1616 /** |
1286 void ec_fsm_change_code(ec_fsm_t *fsm) |
1617 Change state: CODE. |
1618 */ |
|
1619 |
|
1620 void ec_fsm_change_code(ec_fsm_t *fsm /**< finite state machine */) |
|
1287 { |
1621 { |
1288 ec_command_t *command = &fsm->command; |
1622 ec_command_t *command = &fsm->command; |
1289 ec_slave_t *slave = fsm->slave; |
1623 ec_slave_t *slave = fsm->slave; |
1290 uint32_t code; |
1624 uint32_t code; |
1291 const ec_code_msg_t *al_msg; |
1625 const ec_code_msg_t *al_msg; |
1292 |
1626 |
1293 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1627 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1294 EC_ERR("FSM: Reception of AL status code command failed.\n"); |
1628 EC_ERR("Reception of AL status code command failed.\n"); |
1295 slave->state_error = 1; |
1629 slave->state_error = 1; |
1296 fsm->change_state = ec_fsm_change_error; |
1630 fsm->change_state = ec_fsm_change_error; |
1297 return; |
1631 return; |
1298 } |
1632 } |
1299 |
1633 |
1316 } |
1650 } |
1317 |
1651 |
1318 /*****************************************************************************/ |
1652 /*****************************************************************************/ |
1319 |
1653 |
1320 /** |
1654 /** |
1321 State change state: Acknowledge. |
1655 Change state: ACK. |
1322 */ |
1656 */ |
1323 |
1657 |
1324 void ec_fsm_change_ack(ec_fsm_t *fsm) |
1658 void ec_fsm_change_ack(ec_fsm_t *fsm /**< finite state machine */) |
1325 { |
1659 { |
1326 ec_command_t *command = &fsm->command; |
1660 ec_command_t *command = &fsm->command; |
1327 ec_slave_t *slave = fsm->slave; |
1661 ec_slave_t *slave = fsm->slave; |
1328 |
1662 |
1329 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1663 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1330 EC_ERR("FSM: Reception of state ack command failed.\n"); |
1664 EC_ERR("Reception of state ack command failed.\n"); |
1331 slave->state_error = 1; |
1665 slave->state_error = 1; |
1332 fsm->change_state = ec_fsm_change_error; |
1666 fsm->change_state = ec_fsm_change_error; |
1333 return; |
1667 return; |
1334 } |
1668 } |
1335 |
1669 |
1340 } |
1674 } |
1341 |
1675 |
1342 /*****************************************************************************/ |
1676 /*****************************************************************************/ |
1343 |
1677 |
1344 /** |
1678 /** |
1345 State change state: Acknowledge 2. |
1679 Change state: ACK. |
1346 */ |
1680 Acknowledge 2. |
1347 |
1681 */ |
1348 void ec_fsm_change_ack2(ec_fsm_t *fsm) |
1682 |
1683 void ec_fsm_change_ack2(ec_fsm_t *fsm /**< finite state machine */) |
|
1349 { |
1684 { |
1350 ec_command_t *command = &fsm->command; |
1685 ec_command_t *command = &fsm->command; |
1351 ec_slave_t *slave = fsm->slave; |
1686 ec_slave_t *slave = fsm->slave; |
1352 |
1687 |
1353 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1688 if (command->state != EC_CMD_RECEIVED || command->working_counter != 1) { |
1354 EC_ERR("FSM: Reception of state ack check command failed.\n"); |
1689 EC_ERR("Reception of state ack check command failed.\n"); |
1355 slave->state_error = 1; |
1690 slave->state_error = 1; |
1356 fsm->change_state = ec_fsm_change_error; |
1691 fsm->change_state = ec_fsm_change_error; |
1357 return; |
1692 return; |
1358 } |
1693 } |
1359 |
1694 |
1374 } |
1709 } |
1375 |
1710 |
1376 /*****************************************************************************/ |
1711 /*****************************************************************************/ |
1377 |
1712 |
1378 /** |
1713 /** |
1379 State change state: End. |
1714 Change state: END. |
1380 */ |
1715 */ |
1381 |
1716 |
1382 void ec_fsm_change_end(ec_fsm_t *fsm) |
1717 void ec_fsm_change_end(ec_fsm_t *fsm /**< finite state machine */) |
1383 { |
1718 { |
1384 } |
1719 } |
1385 |
1720 |
1386 /*****************************************************************************/ |
1721 /*****************************************************************************/ |
1387 |
1722 |
1388 /** |
1723 /** |
1389 State change state: Error. |
1724 Change state: ERROR. |
1390 */ |
1725 */ |
1391 |
1726 |
1392 void ec_fsm_change_error(ec_fsm_t *fsm) |
1727 void ec_fsm_change_error(ec_fsm_t *fsm /**< finite state machine */) |
1393 { |
1728 { |
1394 } |
1729 } |
1395 |
1730 |
1396 /*****************************************************************************/ |
1731 /*****************************************************************************/ |
1397 |
1732 |