IgH EtherCAT Master  1.5.3
fsm_pdo_entry.c
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * $Id$
4  *
5  * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
6  *
7  * This file is part of the IgH EtherCAT Master.
8  *
9  * The IgH EtherCAT Master is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License version 2, as
11  * published by the Free Software Foundation.
12  *
13  * The IgH EtherCAT Master is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with the IgH EtherCAT Master; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * ---
23  *
24  * The license mentioned above concerns the source code only. Using the
25  * EtherCAT technology and brand is only permitted in compliance with the
26  * industrial property and similar rights of Beckhoff Automation GmbH.
27  *
28  *****************************************************************************/
29 
34 /*****************************************************************************/
35 
36 #include "globals.h"
37 #include "master.h"
38 #include "mailbox.h"
39 #include "slave_config.h"
40 
41 #include "fsm_pdo_entry.h"
42 
43 /*****************************************************************************/
44 
48 
50 
53  ec_datagram_t *);
55  ec_datagram_t *);
57  ec_datagram_t *);
58 
60 
63 
64 /*****************************************************************************/
65 
69  ec_fsm_pdo_entry_t *fsm,
70  ec_fsm_coe_t *fsm_coe
71  )
72 {
73  fsm->fsm_coe = fsm_coe;
75 }
76 
77 /*****************************************************************************/
78 
82  ec_fsm_pdo_entry_t *fsm
83  )
84 {
86 }
87 
88 /*****************************************************************************/
89 
93  ec_fsm_pdo_entry_t *fsm
94  )
95 {
96  printk(KERN_CONT "Currently mapped PDO entries: ");
98  printk(KERN_CONT ". Entries to map: ");
100  printk(KERN_CONT "\n");
101 }
102 
103 /*****************************************************************************/
104 
108  ec_fsm_pdo_entry_t *fsm,
109  ec_slave_t *slave,
110  ec_pdo_t *pdo
111  )
112 {
113  fsm->slave = slave;
114  fsm->target_pdo = pdo;
115 
117 
119 }
120 
121 /*****************************************************************************/
122 
126  ec_fsm_pdo_entry_t *fsm,
127  ec_slave_t *slave,
128  const ec_pdo_t *pdo,
129  const ec_pdo_t *cur_pdo
130  )
131 {
132  fsm->slave = slave;
133  fsm->source_pdo = pdo;
134  fsm->cur_pdo = cur_pdo;
135 
136  if (fsm->slave->master->debug_level) {
137  EC_SLAVE_DBG(slave, 1, "Changing mapping of PDO 0x%04X.\n",
138  pdo->index);
139  EC_SLAVE_DBG(slave, 1, ""); ec_fsm_pdo_entry_print(fsm);
140  }
141 
143 }
144 
145 /*****************************************************************************/
146 
152  const ec_fsm_pdo_entry_t *fsm
153  )
154 {
155  return fsm->state != ec_fsm_pdo_entry_state_end
157 }
158 
159 /*****************************************************************************/
160 
166  ec_fsm_pdo_entry_t *fsm,
167  ec_datagram_t *datagram
168  )
169 {
170  fsm->state(fsm, datagram);
171 
172  return ec_fsm_pdo_entry_running(fsm);
173 }
174 
175 /*****************************************************************************/
176 
182  const ec_fsm_pdo_entry_t *fsm
183  )
184 {
185  return fsm->state == ec_fsm_pdo_entry_state_end;
186 }
187 
188 /******************************************************************************
189  * Reading state functions.
190  *****************************************************************************/
191 
195  ec_fsm_pdo_entry_t *fsm,
196  ec_datagram_t *datagram
197  )
198 {
201 
203  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
204  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
205 }
206 
207 /*****************************************************************************/
208 
212  ec_fsm_pdo_entry_t *fsm,
213  ec_datagram_t *datagram
214  )
215 {
216  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
217  return;
218  }
219 
220  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
221  EC_SLAVE_ERR(fsm->slave,
222  "Failed to read number of mapped PDO entries.\n");
224  return;
225  }
226 
227  if (fsm->request.data_size != sizeof(uint8_t)) {
228  EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at uploading"
229  " SDO 0x%04X:%02X.\n",
230  fsm->request.data_size, fsm->request.index,
231  fsm->request.subindex);
233  return;
234  }
235 
236  fsm->entry_count = EC_READ_U8(fsm->request.data);
237 
238  EC_SLAVE_DBG(fsm->slave, 1, "%u PDO entries mapped.\n", fsm->entry_count);
239 
240  // read first PDO entry
241  fsm->entry_pos = 1;
242  ec_fsm_pdo_entry_read_action_next(fsm, datagram);
243 }
244 
245 /*****************************************************************************/
246 
250  ec_fsm_pdo_entry_t *fsm,
251  ec_datagram_t *datagram
252  )
253 {
254  if (fsm->entry_pos <= fsm->entry_count) {
256  fsm->entry_pos);
259  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
260  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
261  return;
262  }
263 
264  // finished reading entries.
266 }
267 
268 /*****************************************************************************/
269 
273  ec_fsm_pdo_entry_t *fsm,
274  ec_datagram_t *datagram
275  )
276 {
277  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
278  return;
279  }
280 
281  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
282  EC_SLAVE_ERR(fsm->slave, "Failed to read mapped PDO entry.\n");
284  return;
285  }
286 
287  if (fsm->request.data_size != sizeof(uint32_t)) {
288  EC_SLAVE_ERR(fsm->slave, "Invalid data size %zu at"
289  " uploading SDO 0x%04X:%02X.\n",
290  fsm->request.data_size, fsm->request.index,
291  fsm->request.subindex);
293  } else {
294  uint32_t pdo_entry_info;
295  ec_pdo_entry_t *pdo_entry;
296 
297  pdo_entry_info = EC_READ_U32(fsm->request.data);
298 
299  if (!(pdo_entry = (ec_pdo_entry_t *)
300  kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) {
301  EC_SLAVE_ERR(fsm->slave, "Failed to allocate PDO entry.\n");
303  return;
304  }
305 
306  ec_pdo_entry_init(pdo_entry);
307  pdo_entry->index = pdo_entry_info >> 16;
308  pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF;
309  pdo_entry->bit_length = pdo_entry_info & 0xFF;
310 
311  if (!pdo_entry->index && !pdo_entry->subindex) {
312  if (ec_pdo_entry_set_name(pdo_entry, "Gap")) {
313  ec_pdo_entry_clear(pdo_entry);
314  kfree(pdo_entry);
316  return;
317  }
318  }
319 
320  EC_SLAVE_DBG(fsm->slave, 1,
321  "PDO entry 0x%04X:%02X, %u bit, \"%s\".\n",
322  pdo_entry->index, pdo_entry->subindex,
323  pdo_entry->bit_length,
324  pdo_entry->name ? pdo_entry->name : "???");
325 
326  list_add_tail(&pdo_entry->list, &fsm->target_pdo->entries);
327 
328  // next PDO entry
329  fsm->entry_pos++;
330  ec_fsm_pdo_entry_read_action_next(fsm, datagram);
331  }
332 }
333 
334 /******************************************************************************
335  * Configuration state functions.
336  *****************************************************************************/
337 
341  ec_fsm_pdo_entry_t *fsm,
342  ec_datagram_t *datagram
343  )
344 {
345  if (ec_sdo_request_alloc(&fsm->request, 4)) {
347  return;
348  }
349 
350  // set mapped PDO entry count to zero
351  EC_WRITE_U8(fsm->request.data, 0);
352  fsm->request.data_size = 1;
355 
356  EC_SLAVE_DBG(fsm->slave, 1, "Setting entry count to zero.\n");
357 
359  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
360  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
361 }
362 
363 /*****************************************************************************/
364 
370  const ec_fsm_pdo_entry_t *fsm,
371  const struct list_head *list
372  )
373 {
374  list = list->next;
375  if (list == &fsm->source_pdo->entries)
376  return NULL; // no next entry
377  return list_entry(list, ec_pdo_entry_t, list);
378 }
379 
380 /*****************************************************************************/
381 
385  ec_fsm_pdo_entry_t *fsm,
386  ec_datagram_t *datagram
387  )
388 {
389  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
390  return;
391  }
392 
393  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
394  EC_SLAVE_WARN(fsm->slave, "Failed to clear PDO mapping.\n");
397  return;
398  }
399 
400  // find first entry
402  fsm, &fsm->source_pdo->entries))) {
403 
404  EC_SLAVE_DBG(fsm->slave, 1, "No entries to map.\n");
405 
406  fsm->state = ec_fsm_pdo_entry_state_end; // finished
407  return;
408  }
409 
410  // add first entry
411  fsm->entry_pos = 1;
412  ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
413 }
414 
415 /*****************************************************************************/
416 
420  ec_fsm_pdo_entry_t *fsm,
421  ec_datagram_t *datagram
422  )
423 {
424  uint32_t value;
425 
426  EC_SLAVE_DBG(fsm->slave, 1, "Mapping PDO entry 0x%04X:%02X (%u bit)"
427  " at position %u.\n",
428  fsm->entry->index, fsm->entry->subindex,
429  fsm->entry->bit_length, fsm->entry_pos);
430 
431  value = fsm->entry->index << 16
432  | fsm->entry->subindex << 8 | fsm->entry->bit_length;
433  EC_WRITE_U32(fsm->request.data, value);
434  fsm->request.data_size = 4;
436  fsm->entry_pos);
438 
440  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
441  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
442 }
443 
444 /*****************************************************************************/
445 
449  ec_fsm_pdo_entry_t *fsm,
450  ec_datagram_t *datagram
451  )
452 {
453  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
454  return;
455  }
456 
457  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
458  EC_SLAVE_WARN(fsm->slave, "Failed to map PDO entry"
459  " 0x%04X:%02X (%u bit) to position %u.\n",
460  fsm->entry->index, fsm->entry->subindex,
461  fsm->entry->bit_length, fsm->entry_pos);
464  return;
465  }
466 
467  // find next entry
469  fsm, &fsm->entry->list))) {
470 
471  // No more entries to add. Write entry count.
472  EC_WRITE_U8(fsm->request.data, fsm->entry_pos);
473  fsm->request.data_size = 1;
476 
477  EC_SLAVE_DBG(fsm->slave, 1, "Setting number of PDO entries to %u.\n",
478  fsm->entry_pos);
479 
481  ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request);
482  ec_fsm_coe_exec(fsm->fsm_coe, datagram); // execute immediately
483  return;
484  }
485 
486  // add next entry
487  fsm->entry_pos++;
488  ec_fsm_pdo_entry_conf_action_map(fsm, datagram);
489 }
490 
491 /*****************************************************************************/
492 
496  ec_fsm_pdo_entry_t *fsm,
497  ec_datagram_t *datagram
498  )
499 {
500  if (ec_fsm_coe_exec(fsm->fsm_coe, datagram)) {
501  return;
502  }
503 
504  if (!ec_fsm_coe_success(fsm->fsm_coe)) {
505  EC_SLAVE_WARN(fsm->slave, "Failed to set number of entries.\n");
508  return;
509  }
510 
511  EC_SLAVE_DBG(fsm->slave, 1, "Successfully configured"
512  " mapping for PDO 0x%04X.\n", fsm->source_pdo->index);
513 
514  fsm->state = ec_fsm_pdo_entry_state_end; // finished
515 }
516 
517 /******************************************************************************
518  * Common state functions
519  *****************************************************************************/
520 
524  ec_fsm_pdo_entry_t *fsm,
525  ec_datagram_t *datagram
526  )
527 {
528 }
529 
530 /*****************************************************************************/
531 
535  ec_fsm_pdo_entry_t *fsm,
536  ec_datagram_t *datagram
537  )
538 {
539 }
540 
541 /*****************************************************************************/
ec_pdo_t * target_pdo
PDO to read the mapping for.
Definition: fsm_pdo_entry.h:60
void(* state)(ec_fsm_pdo_entry_t *, ec_datagram_t *)
state function
Definition: fsm_pdo_entry.h:54
unsigned int entry_pos
Position in PDO mapping.
Definition: fsm_pdo_entry.h:65
#define EC_SLAVE_DBG(slave, level, fmt, args...)
Convenience macro for printing slave-specific debug messages to syslog.
Definition: slave.h:106
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:90
EtherCAT datagram.
Definition: datagram.h:87
uint16_t index
SDO index.
Definition: sdo_request.h:48
#define EC_WRITE_U8(DATA, VAL)
Write an 8-bit unsigned value to EtherCAT data.
Definition: ecrt.h:2401
const ec_pdo_entry_t * entry
Current entry.
Definition: fsm_pdo_entry.h:63
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.
void ec_pdo_clear_entries(ec_pdo_t *pdo)
Clear PDO entry list.
Definition: pdo.c:106
uint8_t * data
Pointer to SDO data.
Definition: sdo_request.h:50
int ec_fsm_coe_success(const ec_fsm_coe_t *fsm)
Returns, if the state machine terminated with success.
Definition: fsm_coe.c:262
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:64
Global definitions and macros.
PDO entry description.
Definition: pdo_entry.h:48
EtherCAT master structure.
const ec_pdo_t * source_pdo
PDO with desired mapping.
Definition: fsm_pdo_entry.h:61
uint16_t index
PDO index.
Definition: pdo.h:51
uint16_t index
PDO entry index.
Definition: pdo_entry.h:50
void ec_fsm_pdo_entry_print(ec_fsm_pdo_entry_t *fsm)
Print the current and desired PDO mapping.
Definition: fsm_pdo_entry.c:92
EtherCAT slave.
Definition: slave.h:176
void ecrt_sdo_request_read(ec_sdo_request_t *req)
Schedule an SDO read operation.
Definition: sdo_request.c:224
void ec_sdo_request_clear(ec_sdo_request_t *req)
SDO request destructor.
Definition: sdo_request.c:76
EtherCAT PDO entry configuration state machine structures.
const ec_pdo_t * cur_pdo
PDO with current mapping (display only).
Definition: fsm_pdo_entry.h:62
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:2435
ec_fsm_coe_t * fsm_coe
CoE state machine to use.
Definition: fsm_pdo_entry.h:56
void ec_pdo_entry_clear(ec_pdo_entry_t *entry)
PDO entry destructor.
Definition: pdo_entry.c:76
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:49
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:285
#define EC_SLAVE_ERR(slave, fmt, args...)
Convenience macro for printing slave-specific errors to syslog.
Definition: slave.h:76
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:53
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:2329
struct list_head entries
List of PDO entries.
Definition: pdo.h:54
ec_master_t * master
Master owning the slave.
Definition: slave.h:178
void ec_pdo_entry_init(ec_pdo_entry_t *entry)
PDO entry constructor.
Definition: pdo_entry.c:45
uint8_t subindex
PDO entry subindex.
Definition: pdo_entry.h:51
uint8_t subindex
SDO subindex.
Definition: sdo_request.h:49
void ec_fsm_pdo_entry_init(ec_fsm_pdo_entry_t *fsm, ec_fsm_coe_t *fsm_coe)
Constructor.
Definition: fsm_pdo_entry.c:68
char * name
entry name
Definition: pdo_entry.h:52
size_t data_size
Size of SDO data.
Definition: sdo_request.h:52
Mailbox functionality.
void ec_sdo_request_init(ec_sdo_request_t *req)
SDO request constructor.
Definition: sdo_request.c:54
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:228
ec_slave_t * slave
Slave the FSM runs on.
Definition: fsm_pdo_entry.h:59
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:299
struct list_head list
list item
Definition: pdo_entry.h:49
#define EC_READ_U8(DATA)
Read an 8-bit unsigned value from EtherCAT data.
Definition: ecrt.h:2297
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:52
EtherCAT slave configuration structure.
void ec_fsm_pdo_entry_clear(ec_fsm_pdo_entry_t *fsm)
Destructor.
Definition: fsm_pdo_entry.c:81
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:205
int ec_sdo_request_alloc(ec_sdo_request_t *req, size_t size)
Pre-allocates the data memory.
Definition: sdo_request.c:127
int ec_fsm_pdo_entry_running(const ec_fsm_pdo_entry_t *fsm)
Get running state.
void ecrt_sdo_request_write(ec_sdo_request_t *req)
Schedule an SDO write operation.
Definition: sdo_request.c:235
int ec_pdo_entry_set_name(ec_pdo_entry_t *entry, const char *name)
Set PDO entry name.
Definition: pdo_entry.c:89
void 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:187
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:52
ec_sdo_request_t request
SDO request.
Definition: fsm_pdo_entry.h:57