IgH EtherCAT Master  1.6.0
fsm_pdo_entry.c
Go to the documentation of this file.
1 /*****************************************************************************
2  *
3  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
4  *
5  * This file is part of the IgH EtherCAT Master.
6  *
7  * The IgH EtherCAT Master is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License version 2, as
9  * published by the Free Software Foundation.
10  *
11  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with the IgH EtherCAT Master; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  *
20  ****************************************************************************/
21 
26 /****************************************************************************/
27 
28 #include "globals.h"
29 #include "master.h"
30 #include "mailbox.h"
31 #include "slave_config.h"
32 
33 #include "fsm_pdo_entry.h"
34 
35 /****************************************************************************/
36 
40 
42 
45  ec_datagram_t *);
47  ec_datagram_t *);
49  ec_datagram_t *);
50 
52 
55 
56 /****************************************************************************/
57 
61  ec_fsm_pdo_entry_t *fsm,
62  ec_fsm_coe_t *fsm_coe
63  )
64 {
65  fsm->fsm_coe = fsm_coe;
67 }
68 
69 /****************************************************************************/
70 
74  ec_fsm_pdo_entry_t *fsm
75  )
76 {
78 }
79 
80 /****************************************************************************/
81 
85  ec_fsm_pdo_entry_t *fsm
86  )
87 {
88  printk(KERN_CONT "Currently mapped PDO entries: ");
90  printk(KERN_CONT ". Entries to map: ");
92  printk(KERN_CONT "\n");
93 }
94 
95 /****************************************************************************/
96 
100  ec_fsm_pdo_entry_t *fsm,
101  ec_slave_t *slave,
102  ec_pdo_t *pdo
103  )
104 {
105  fsm->slave = slave;
106  fsm->target_pdo = pdo;
107 
109 
111 }
112 
113 /****************************************************************************/
114 
118  ec_fsm_pdo_entry_t *fsm,
119  ec_slave_t *slave,
120  const ec_pdo_t *pdo,
121  const ec_pdo_t *cur_pdo
122  )
123 {
124  fsm->slave = slave;
125  fsm->source_pdo = pdo;
126  fsm->cur_pdo = cur_pdo;
127 
128  if (fsm->slave->master->debug_level) {
129  EC_SLAVE_DBG(slave, 1, "Changing mapping of PDO 0x%04X.\n",
130  pdo->index);
131  EC_SLAVE_DBG(slave, 1, ""); ec_fsm_pdo_entry_print(fsm);
132  }
133 
135 }
136 
137 /****************************************************************************/
138 
144  const ec_fsm_pdo_entry_t *fsm
145  )
146 {
147  return fsm->state != ec_fsm_pdo_entry_state_end
149 }
150 
151 /****************************************************************************/
152 
158  ec_fsm_pdo_entry_t *fsm,
159  ec_datagram_t *datagram
160  )
161 {
162  fsm->state(fsm, datagram);
163 
164  return ec_fsm_pdo_entry_running(fsm);
165 }
166 
167 /****************************************************************************/
168 
174  const ec_fsm_pdo_entry_t *fsm
175  )
176 {
177  return fsm->state == ec_fsm_pdo_entry_state_end;
178 }
179 
180 /*****************************************************************************
181  * Reading state functions.
182  ****************************************************************************/
183 
187  ec_fsm_pdo_entry_t *fsm,
188  ec_datagram_t *datagram
189  )
190 {
193 
195  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
196  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
197 }
198 
199 /****************************************************************************/
200 
204  ec_fsm_pdo_entry_t *fsm,
205  ec_datagram_t *datagram
206  )
207 {
208  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
209  return;
210  }
211 
212  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
213  EC_SLAVE_ERR(fsm->slave,
214  "Failed to read number of mapped PDO entries.\n");
216  return;
217  }
218 
219  if (fsm->request.data_size != sizeof(uint8_t)) {
220  EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at uploading"
221  " SDO 0x%04X:%02X.\n",
222  fsm->request.data_size, fsm->request.index,
223  fsm->request.subindex);
225  return;
226  }
227 
228  fsm->entry_count = EC_READ_U8(fsm->request.data);
229 
230  EC_SLAVE_DBG(fsm->slave, 1, "%u PDO entries mapped.\n", fsm->entry_count);
231 
232  // read first PDO entry
233  fsm->entry_pos = 1;
234  ec_fsm_pdo_entry_read_action_next(fsm, datagram);
235 }
236 
237 /****************************************************************************/
238 
242  ec_fsm_pdo_entry_t *fsm,
243  ec_datagram_t *datagram
244  )
245 {
246  if (fsm->entry_pos <= fsm->entry_count) {
248  fsm->entry_pos);
251  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
252  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
253  return;
254  }
255 
256  // finished reading entries.
258 }
259 
260 /****************************************************************************/
261 
265  ec_fsm_pdo_entry_t *fsm,
266  ec_datagram_t *datagram
267  )
268 {
269  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
270  return;
271  }
272 
273  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
274  EC_SLAVE_ERR(fsm->slave, "Failed to read mapped PDO entry.\n");
276  return;
277  }
278 
279  if (fsm->request.data_size != sizeof(uint32_t)) {
280  EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at"
281  " uploading SDO 0x%04X:%02X.\n",
282  fsm->request.data_size, fsm->request.index,
283  fsm->request.subindex);
285  } else {
286  uint32_t pdo_entry_info;
287  ec_pdo_entry_t *pdo_entry;
288 
289  pdo_entry_info = EC_READ_U32(fsm->request.data);
290 
291  if (!(pdo_entry = (ec_pdo_entry_t *)
292  kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
293  EC_SLAVE_ERR(fsm->slave, "Failed to allocate PDO entry.\n");
295  return;
296  }
297 
298  ec_pdo_entry_init(pdo_entry);
299  pdo_entry->index = pdo_entry_info >> 16;
300  pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
301  pdo_entry->bit_length = pdo_entry_info & 0xFF;
302 
303  if (!pdo_entry->index && !pdo_entry->subindex) {
304  if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
305  ec_pdo_entry_clear(pdo_entry);
306  kfree(pdo_entry);
308  return;
309  }
310  }
311 
312  EC_SLAVE_DBG(fsm->slave, 1,
313  "PDO entry 0x%04X:%02X, %u bit, \"%s\".\n",
314  pdo_entry->index, pdo_entry->subindex,
315  pdo_entry->bit_length,
316  pdo_entry->name ? pdo_entry->name : "???");
317 
318  list_add_tail(&pdo_entry->list, &fsm->target_pdo->entries);
319 
320  // next PDO entry
321  fsm->entry_pos++;
322  ec_fsm_pdo_entry_read_action_next(fsm, datagram);
323  }
324 }
325 
326 /*****************************************************************************
327  * Configuration state functions.
328  ****************************************************************************/
329 
333  ec_fsm_pdo_entry_t *fsm,
334  ec_datagram_t *datagram
335  )
336 {
337  if (ec_sdo_request_alloc(&fsm->request, 4)) {
339  return;
340  }
341 
342  // set mapped PDO entry count to zero
343  EC_WRITE_U8(fsm->request.data, 0);
344  fsm->request.data_size = 1;
347 
348  EC_SLAVE_DBG(fsm->slave, 1, "Setting entry count to zero.\n");
349 
351  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
352  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
353 }
354 
355 /****************************************************************************/
356 
362  const ec_fsm_pdo_entry_t *fsm,
363  const struct list_head *list
364  )
365 {
366  list = list->next;
367  if (list == &fsm->source_pdo->entries)
368  return NULL; // no next entry
369  return list_entry(list, ec_pdo_entry_t, list);
370 }
371 
372 /****************************************************************************/
373 
377  ec_fsm_pdo_entry_t *fsm,
378  ec_datagram_t *datagram
379  )
380 {
381  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
382  return;
383  }
384 
385  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
386  EC_SLAVE_WARN(fsm->slave, "Failed to clear PDO mapping.\n");
389  return;
390  }
391 
392  // find first entry
394  fsm, &fsm->source_pdo->entries))) {
395 
396  EC_SLAVE_DBG(fsm->slave, 1, "No entries to map.\n");
397 
398  fsm->state = ec_fsm_pdo_entry_state_end; // finished
399  return;
400  }
401 
402  // add first entry
403  fsm->entry_pos = 1;
404  ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
405 }
406 
407 /****************************************************************************/
408 
412  ec_fsm_pdo_entry_t *fsm,
413  ec_datagram_t *datagram
414  )
415 {
416  uint32_t value;
417 
418  EC_SLAVE_DBG(fsm->slave, 1, "Mapping PDO entry 0x%04X:%02X (%u bit)"
419  " at position %u.\n",
420  fsm->entry->index, fsm->entry->subindex,
421  fsm->entry->bit_length, fsm->entry_pos);
422 
423  value = fsm->entry->index << 16
424  | fsm->entry->subindex << 8 | fsm->entry->bit_length;
425  EC_WRITE_U32(fsm->request.data, value);
426  fsm->request.data_size = 4;
428  fsm->entry_pos);
430 
432  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
433  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
434 }
435 
436 /****************************************************************************/
437 
441  ec_fsm_pdo_entry_t *fsm,
442  ec_datagram_t *datagram
443  )
444 {
445  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
446  return;
447  }
448 
449  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
450  EC_SLAVE_WARN(fsm->slave, "Failed to map PDO entry"
451  " 0x%04X:%02X (%u bit) to position %u.\n",
452  fsm->entry->index, fsm->entry->subindex,
453  fsm->entry->bit_length, fsm->entry_pos);
456  return;
457  }
458 
459  // find next entry
461  fsm, &fsm->entry->list))) {
462 
463  // No more entries to add. Write entry count.
464  EC_WRITE_U8(fsm->request.data, fsm->entry_pos);
465  fsm->request.data_size = 1;
468 
469  EC_SLAVE_DBG(fsm->slave, 1, "Setting number of PDO entries to %u.\n",
470  fsm->entry_pos);
471 
473  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
474  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
475  return;
476  }
477 
478  // add next entry
479  fsm->entry_pos++;
480  ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
481 }
482 
483 /****************************************************************************/
484 
488  ec_fsm_pdo_entry_t *fsm,
489  ec_datagram_t *datagram
490  )
491 {
492  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
493  return;
494  }
495 
496  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
497  EC_SLAVE_WARN(fsm->slave, "Failed to set number of entries.\n");
500  return;
501  }
502 
503  EC_SLAVE_DBG(fsm->slave, 1, "Successfully configured"
504  " mapping for PDO 0x%04X.\n", fsm->source_pdo->index);
505 
506  fsm->state = ec_fsm_pdo_entry_state_end; // finished
507 }
508 
509 /*****************************************************************************
510  * Common state functions
511  ****************************************************************************/
512 
516  ec_fsm_pdo_entry_t *fsm,
517  ec_datagram_t *datagram
518  )
519 {
520 }
521 
522 /****************************************************************************/
523 
527  ec_fsm_pdo_entry_t *fsm,
528  ec_datagram_t *datagram
529  )
530 {
531 }
532 
533 /****************************************************************************/
ec_pdo_t * target_pdo
PDO to read the mapping for.
Definition: fsm_pdo_entry.h:52
void(* state)(ec_fsm_pdo_entry_t *, ec_datagram_t *)
state function
Definition: fsm_pdo_entry.h:46
unsigned int entry_pos
Position in PDO mapping.
Definition: fsm_pdo_entry.h:57
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:98
void ec_fsm_pdo_entry_conf_state_set_entry_count(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Set the number of entries.
#define EC_SLAVE_WARN(slave, fmt, args...)
Convenience macro for printing slave-specific warnings to syslog.
Definition: slave.h:82
EtherCAT datagram.
Definition: datagram.h:79
uint16_t index
SDO index.
Definition: sdo_request.h:42
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2699
const ec_pdo_entry_t * entry
Current entry.
Definition: fsm_pdo_entry.h:55
void ec_fsm_pdo_entry_read_state_entry(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Read PDO entry information.
void ec_fsm_pdo_entry_start_reading(ec_fsm_pdo_entry_t *fsm, ec_slave_t *slave, ec_pdo_t *pdo)
Start reading a PDO&#39;s entries.
Definition: fsm_pdo_entry.c:99
void ec_pdo_clear_entries(ec_pdo_t *pdo)
Clear PDO entry list.
Definition: pdo.c:98
uint8_t * data
Pointer to SDO data.
Definition: sdo_request.h:44
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:254
void ec_fsm_pdo_entry_state_end(ec_fsm_pdo_entry_t *, ec_datagram_t *)
State: END.
void ec_fsm_pdo_entry_start_configuration(ec_fsm_pdo_entry_t *fsm, ec_slave_t *slave, const ec_pdo_t *pdo, const ec_pdo_t *cur_pdo)
Start PDO mapping state machine.
unsigned int entry_count
Number of entries.
Definition: fsm_pdo_entry.h:56
Global definitions and macros.
PDO entry description.
Definition: pdo_entry.h:40
EtherCAT master structure.
const ec_pdo_t * source_pdo
PDO with desired mapping.
Definition: fsm_pdo_entry.h:53
uint16_t index
PDO index.
Definition: pdo.h:43
uint16_t index
PDO entry index.
Definition: pdo_entry.h:42
void ec_fsm_pdo_entry_print(ec_fsm_pdo_entry_t *fsm)
Print the current and desired PDO mapping.
Definition: fsm_pdo_entry.c:84
EtherCAT slave.
Definition: slave.h:168
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
Definition: sdo_request.c:70
EtherCAT PDO entry configuration state machine structures.
const ec_pdo_t * cur_pdo
PDO with current mapping (display only).
Definition: fsm_pdo_entry.h:54
int ecrt_sdo_request_index(ec_sdo_request_t *req, uint16_t index, uint8_t subindex)
Set the SDO index and subindex.
Definition: sdo_request.c:181
void ec_fsm_pdo_entry_state_error(ec_fsm_pdo_entry_t *, ec_datagram_t *)
State: ERROR.
#define EC_WRITE_U32(DATA, VAL)
Write a 32-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2733
ec_fsm_coe_t * fsm_coe
CoE state machine to use.
Definition: fsm_pdo_entry.h:48
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:68
void ec_fsm_pdo_entry_conf_action_map(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Starts to add a PDO entry.
PDO description.
Definition: pdo.h:41
int ec_fsm_pdo_entry_success(const ec_fsm_pdo_entry_t *fsm)
Get execution result.
unsigned int debug_level
Master debug level.
Definition: master.h:271
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:68
void ec_fsm_pdo_entry_read_state_start(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Request reading the number of mapped PDO entries.
uint8_t bit_length
entry length in bit
Definition: pdo_entry.h:45
int ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
Definition: sdo_request.c:232
int ec_fsm_pdo_entry_exec(ec_fsm_pdo_entry_t *fsm, ec_datagram_t *datagram)
Executes the current state.
void ec_fsm_pdo_entry_conf_state_map_entry(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Add a PDO entry.
void ec_fsm_pdo_entry_conf_state_start(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Start PDO mapping.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2627
struct list_head entries
List of PDO entries.
Definition: pdo.h:46
ec_master_t * master
Master owning the slave.
Definition: slave.h:170
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:37
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:43
uint8_t subindex
SDO subindex.
Definition: sdo_request.h:43
void ec_fsm_pdo_entry_init(ec_fsm_pdo_entry_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo_entry.c:60
char * name
entry name
Definition: pdo_entry.h:44
size_t data_size
Size of SDO data.
Definition: sdo_request.h:46
Mailbox functionality.
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
Definition: sdo_request.c:48
int ec_fsm_coe_exec(ec_fsm_coe_t *fsm, ec_datagram_t *datagram)
Executes the current state of the state machine.
Definition: fsm_coe.c:220
int ecrt_sdo_request_read(ec_sdo_request_t *req)
Schedule an SDO read operation.
Definition: sdo_request.c:220
ec_slave_t * slave
Slave the FSM runs on.
Definition: fsm_pdo_entry.h:51
ec_pdo_entry_t * ec_fsm_pdo_entry_conf_next_entry(const ec_fsm_pdo_entry_t *fsm, const struct list_head *list)
Process next PDO entry.
void ec_pdo_print_entries(const ec_pdo_t *pdo)
Outputs the PDOs in the list.
Definition: pdo.c:291
struct list_head list
list item
Definition: pdo_entry.h:41
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2595
void ec_fsm_pdo_entry_read_state_count(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Read number of mapped PDO entries.
PDO configuration state machine.
Definition: fsm_pdo_entry.h:44
EtherCAT slave configuration structure.
void ec_fsm_pdo_entry_clear(ec_fsm_pdo_entry_t *fsm)
Destructor.
Definition: fsm_pdo_entry.c:73
void ec_fsm_coe_transfer(ec_fsm_coe_t *fsm, ec_slave_t *slave, ec_sdo_request_t *request)
Starts to transfer an SDO to/from a slave.
Definition: fsm_coe.c:197
int ec_sdo_request_alloc(ec_sdo_request_t *req, size_t size)
Pre-allocates the data memory.
Definition: sdo_request.c:121
int ec_fsm_pdo_entry_running(const ec_fsm_pdo_entry_t *fsm)
Get running state.
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:81
void ec_fsm_pdo_entry_read_action_next(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Read next PDO entry.
void ec_fsm_pdo_entry_conf_state_zero_entry_count(ec_fsm_pdo_entry_t *, ec_datagram_t *)
Set the number of mapped entries to zero.
Finite state machines for the CANopen over EtherCAT protocol.
Definition: fsm_coe.h:44
ec_sdo_request_t request
SDO request.
Definition: fsm_pdo_entry.h:49