29 * standard) as the (only) precondition to have the right to use EtherCAT |
29 * standard) as the (only) precondition to have the right to use EtherCAT |
30 * Technology, IP and trade marks. |
30 * Technology, IP and trade marks. |
31 * |
31 * |
32 *****************************************************************************/ |
32 *****************************************************************************/ |
33 |
33 |
34 /** |
34 /** \file |
35 \file |
35 * EtherCAT PDO mapping state machine. |
36 EtherCAT PDO mapping state machine. |
36 */ |
37 */ |
|
38 |
37 |
39 /*****************************************************************************/ |
38 /*****************************************************************************/ |
40 |
39 |
41 #include "globals.h" |
40 #include "globals.h" |
42 #include "master.h" |
41 #include "master.h" |
43 #include "mailbox.h" |
42 #include "mailbox.h" |
|
43 #include "slave_config.h" |
|
44 |
44 #include "fsm_mapping.h" |
45 #include "fsm_mapping.h" |
45 |
46 |
46 /*****************************************************************************/ |
47 /*****************************************************************************/ |
47 |
48 |
48 void ec_fsm_mapping_state_start(ec_fsm_mapping_t *); |
49 void ec_fsm_mapping_state_start(ec_fsm_mapping_t *); |
54 |
55 |
55 void ec_fsm_mapping_next_sync(ec_fsm_mapping_t *); |
56 void ec_fsm_mapping_next_sync(ec_fsm_mapping_t *); |
56 |
57 |
57 /*****************************************************************************/ |
58 /*****************************************************************************/ |
58 |
59 |
59 /** |
60 /** Constructor. |
60 * Constructor. |
61 */ |
61 */ |
62 void ec_fsm_mapping_init( |
62 |
63 ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
63 void ec_fsm_mapping_init(ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
|
64 ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */ |
64 ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */ |
65 ) |
65 ) |
66 { |
66 { |
67 fsm->fsm_coe = fsm_coe; |
67 fsm->fsm_coe = fsm_coe; |
68 fsm->sdodata.data = (uint8_t *) &fsm->sdo_value; |
68 fsm->sdodata.data = (uint8_t *) &fsm->sdo_value; |
69 } |
69 } |
70 |
70 |
71 /*****************************************************************************/ |
71 /*****************************************************************************/ |
72 |
72 |
73 /** |
73 /** Destructor. |
74 * Destructor. |
74 */ |
75 */ |
75 void ec_fsm_mapping_clear( |
76 |
76 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
77 void ec_fsm_mapping_clear(ec_fsm_mapping_t *fsm /**< mapping state machine */) |
77 ) |
78 { |
78 { |
79 } |
79 } |
80 |
80 |
81 /*****************************************************************************/ |
81 /*****************************************************************************/ |
82 |
82 |
83 /** |
83 /** Start PDO mapping configuration state machine. |
84 * Start PDO mapping configuration state machine. |
84 */ |
85 */ |
|
86 |
|
87 void ec_fsm_mapping_start( |
85 void ec_fsm_mapping_start( |
88 ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
86 ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
89 ec_slave_t *slave /**< slave to configure */ |
87 ec_slave_t *slave /**< slave to configure */ |
90 ) |
88 ) |
91 { |
89 { |
93 fsm->state = ec_fsm_mapping_state_start; |
91 fsm->state = ec_fsm_mapping_state_start; |
94 } |
92 } |
95 |
93 |
96 /*****************************************************************************/ |
94 /*****************************************************************************/ |
97 |
95 |
98 /** |
96 /** Get running state. |
|
97 * |
99 * \return false, if state machine has terminated |
98 * \return false, if state machine has terminated |
100 */ |
99 */ |
101 |
|
102 int ec_fsm_mapping_running( |
100 int ec_fsm_mapping_running( |
103 const ec_fsm_mapping_t *fsm /**< mapping state machine */ |
101 const ec_fsm_mapping_t *fsm /**< mapping state machine */ |
104 ) |
102 ) |
105 { |
103 { |
106 return fsm->state != ec_fsm_mapping_state_end |
104 return fsm->state != ec_fsm_mapping_state_end |
107 && fsm->state != ec_fsm_mapping_state_error; |
105 && fsm->state != ec_fsm_mapping_state_error; |
108 } |
106 } |
109 |
107 |
110 /*****************************************************************************/ |
108 /*****************************************************************************/ |
111 |
109 |
112 /** |
110 /** Executes the current state of the state machine. |
113 * Executes the current state of the state machine. |
111 * |
114 * If the state machine's datagram is not sent or received yet, the execution |
112 * If the state machine's datagram is not sent or received yet, the execution |
115 * of the state machine is delayed to the next cycle. |
113 * of the state machine is delayed to the next cycle. |
|
114 * |
116 * \return false, if state machine has terminated |
115 * \return false, if state machine has terminated |
117 */ |
116 */ |
118 |
|
119 int ec_fsm_mapping_exec( |
117 int ec_fsm_mapping_exec( |
120 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
118 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
121 ) |
119 ) |
122 { |
120 { |
123 fsm->state(fsm); |
121 fsm->state(fsm); |
124 return ec_fsm_mapping_running(fsm); |
122 return ec_fsm_mapping_running(fsm); |
125 } |
123 } |
126 |
124 |
127 /*****************************************************************************/ |
125 /*****************************************************************************/ |
128 |
126 |
129 /** |
127 /** Get execution result. |
|
128 * |
130 * \return true, if the state machine terminated gracefully |
129 * \return true, if the state machine terminated gracefully |
131 */ |
130 */ |
132 |
|
133 int ec_fsm_mapping_success( |
131 int ec_fsm_mapping_success( |
134 const ec_fsm_mapping_t *fsm /**< mapping state machine */ |
132 const ec_fsm_mapping_t *fsm /**< mapping state machine */ |
135 ) |
133 ) |
136 { |
134 { |
137 return fsm->state == ec_fsm_mapping_state_end; |
135 return fsm->state == ec_fsm_mapping_state_end; |
138 } |
136 } |
139 |
137 |
140 /****************************************************************************** |
138 /****************************************************************************** |
141 * state functions |
139 * State functions. |
142 *****************************************************************************/ |
140 *****************************************************************************/ |
143 |
141 |
144 /** |
142 /** Start mapping configuration. |
145 * Start mapping configuration. |
143 */ |
146 */ |
|
147 |
|
148 void ec_fsm_mapping_state_start( |
144 void ec_fsm_mapping_state_start( |
149 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
145 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
150 ) |
146 ) |
151 { |
147 { |
|
148 if (!fsm->slave->config) { |
|
149 fsm->state = ec_fsm_mapping_state_end; |
|
150 return; |
|
151 } |
|
152 |
152 fsm->dir = EC_DIR_OUTPUT; |
153 fsm->dir = EC_DIR_OUTPUT; |
153 ec_fsm_mapping_next_sync(fsm); |
154 ec_fsm_mapping_next_sync(fsm); |
154 } |
155 } |
155 |
156 |
156 /*****************************************************************************/ |
157 /*****************************************************************************/ |
157 |
158 |
158 /** |
159 /** Process mapping of next sync manager. |
159 * Process mapping of next sync manager. |
160 */ |
160 */ |
|
161 |
|
162 void ec_fsm_mapping_next_sync( |
161 void ec_fsm_mapping_next_sync( |
163 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
162 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
164 ) |
163 ) |
165 { |
164 { |
166 while (1) { |
165 while (1) { |
169 fsm->state = ec_fsm_mapping_state_end; |
168 fsm->state = ec_fsm_mapping_state_end; |
170 return; |
169 return; |
171 } |
170 } |
172 |
171 |
173 if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) { |
172 if (!(fsm->sync = ec_slave_get_pdo_sync(fsm->slave, fsm->dir))) { |
174 // no sync manager found for this direction |
173 EC_WARN("next_sync(): No sync manager!\n"); |
175 fsm->dir++; |
174 fsm->dir++; |
176 continue; |
175 continue; |
177 } |
176 } |
178 |
177 |
179 fsm->dir++; |
178 fsm->mapping = &fsm->slave->config->mapping[fsm->dir]; |
180 if (fsm->sync->alt_mapping) |
179 |
|
180 if (ec_pdo_mapping_equal(&fsm->sync->mapping, fsm->mapping)) { |
|
181 // the mapping for this direction does not have to be altered |
|
182 fsm->dir++; |
|
183 continue; |
|
184 } else { |
|
185 fsm->dir++; |
181 break; |
186 break; |
|
187 } |
182 } |
188 } |
183 |
189 |
184 if (fsm->slave->master->debug_level) { |
190 if (fsm->slave->master->debug_level) { |
185 EC_DBG("Configuring PDO mapping for SM%u of slave %i.\n", |
191 EC_DBG("Configuring PDO mapping for SM%u of slave %u.\n", |
186 fsm->sync->index, fsm->slave->ring_position); |
192 fsm->sync->index, fsm->slave->ring_position); |
187 } |
193 } |
188 |
194 |
189 // set mapped PDO count to zero |
195 // set mapped PDO count to zero |
190 fsm->sdodata.index = 0x1C10 + fsm->sync->index; |
196 fsm->sdodata.index = 0x1C10 + fsm->sync->index; |
199 ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately |
205 ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately |
200 } |
206 } |
201 |
207 |
202 /*****************************************************************************/ |
208 /*****************************************************************************/ |
203 |
209 |
204 /** |
210 /** Process mapping of next PDO. |
205 * Process mapping of next PDO. |
211 */ |
206 */ |
|
207 |
|
208 ec_pdo_t *ec_fsm_mapping_next_pdo( |
212 ec_pdo_t *ec_fsm_mapping_next_pdo( |
209 ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
213 const ec_fsm_mapping_t *fsm, /**< mapping state machine */ |
210 struct list_head *list /**< current PDO list item */ |
214 const struct list_head *list /**< current PDO list item */ |
211 ) |
215 ) |
212 { |
216 { |
213 ec_pdo_t *pdo; |
217 list = list->next; |
214 |
218 if (list == &fsm->mapping->pdos) |
215 do { |
219 return NULL; // no next PDO |
216 list = list->next; |
220 return list_entry(list, ec_pdo_t, list); |
217 if (list == &fsm->sync->pdos) |
221 } |
218 return NULL; // no next PDO |
222 |
219 pdo = list_entry(list, ec_pdo_t, list); |
223 /*****************************************************************************/ |
220 } |
224 |
221 while (pdo->sync_index != fsm->sync->index); |
225 /** Set the number of mapped PDOs to zero. |
222 |
226 */ |
223 return pdo; |
|
224 } |
|
225 |
|
226 /*****************************************************************************/ |
|
227 |
|
228 /** |
|
229 * Set the number of mapped PDOs to zero. |
|
230 */ |
|
231 |
|
232 void ec_fsm_mapping_state_zero_count( |
227 void ec_fsm_mapping_state_zero_count( |
233 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
228 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
234 ) |
229 ) |
235 { |
230 { |
236 if (ec_fsm_coe_exec(fsm->fsm_coe)) return; |
231 if (ec_fsm_coe_exec(fsm->fsm_coe)) return; |
243 } |
238 } |
244 |
239 |
245 // map all PDOs belonging to the current sync manager |
240 // map all PDOs belonging to the current sync manager |
246 |
241 |
247 // find first PDO |
242 // find first PDO |
248 if (!(fsm->pdo = ec_fsm_mapping_next_pdo( |
243 if (!(fsm->pdo = ec_fsm_mapping_next_pdo(fsm, &fsm->mapping->pdos))) { |
249 fsm, &fsm->sync->pdos))) { |
|
250 if (fsm->slave->master->debug_level) |
244 if (fsm->slave->master->debug_level) |
251 EC_DBG("No PDOs to map for SM%u of slave %u.\n", |
245 EC_DBG("No PDOs to map for SM%u of slave %u.\n", |
252 fsm->sync->index, fsm->slave->ring_position); |
246 fsm->sync->index, fsm->slave->ring_position); |
253 ec_fsm_mapping_next_sync(fsm); |
247 ec_fsm_mapping_next_sync(fsm); |
254 return; |
248 return; |
287 fsm->state = ec_fsm_mapping_state_error; |
279 fsm->state = ec_fsm_mapping_state_error; |
288 return; |
280 return; |
289 } |
281 } |
290 |
282 |
291 // find next PDO |
283 // find next PDO |
292 if (!(fsm->pdo = ec_fsm_mapping_next_pdo( |
284 if (!(fsm->pdo = ec_fsm_mapping_next_pdo(fsm, &fsm->pdo->list))) { |
293 fsm, &fsm->pdo->list))) { |
|
294 // no more PDOs to map. write PDO count |
285 // no more PDOs to map. write PDO count |
295 fsm->sdodata.subindex = 0; |
286 fsm->sdodata.subindex = 0; |
296 EC_WRITE_U8(&fsm->sdo_value, fsm->pdo_count); |
287 EC_WRITE_U8(&fsm->sdo_value, fsm->pdo_count); |
297 fsm->sdodata.size = 1; |
288 fsm->sdodata.size = 1; |
298 |
289 |
349 |
338 |
350 /****************************************************************************** |
339 /****************************************************************************** |
351 * Common state functions |
340 * Common state functions |
352 *****************************************************************************/ |
341 *****************************************************************************/ |
353 |
342 |
354 /** |
343 /** State: ERROR. |
355 State: ERROR. |
344 */ |
356 */ |
|
357 |
|
358 void ec_fsm_mapping_state_error( |
345 void ec_fsm_mapping_state_error( |
359 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
346 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
360 ) |
347 ) |
361 { |
348 { |
362 } |
349 } |
363 |
350 |
364 /*****************************************************************************/ |
351 /*****************************************************************************/ |
365 |
352 |
366 /** |
353 /** State: END. |
367 State: END. |
354 */ |
368 */ |
|
369 |
|
370 void ec_fsm_mapping_state_end( |
355 void ec_fsm_mapping_state_end( |
371 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
356 ec_fsm_mapping_t *fsm /**< mapping state machine */ |
372 ) |
357 ) |
373 { |
358 { |
374 } |
359 } |