# HG changeset patch # User Florian Pose # Date 1217520809 0 # Node ID 235f34ca50e2a64c9fac2c9a7a1cbfba143fc028 # Parent 2ec9651a6c8923f23c300eaf59ad5dd208d5bd84 Major Pdo configuration change: Read mapping of unknown Pdos during configuration. diff -r 2ec9651a6c89 -r 235f34ca50e2 TODO --- a/TODO Thu Jul 31 09:30:38 2008 +0000 +++ b/TODO Thu Jul 31 16:13:29 2008 +0000 @@ -8,12 +8,14 @@ Version 1.4.0: -* Read Pdo mapping for unknown Pdos before configuring them. * Attach Pdo names from SII or Coe dictioary to Pdos read via CoE. * Update documentation. -* Get original driver for r8169. * Race in jiffies frame timeout? -* Error at no sync manager for configuration. +* Remove ec_sync_t::assign_source? +* Repair rcethercat status. +* Debug output for all configuration functions of the application interface. +* Output warning, if there is no sync manager for a configuration. +* Abort code messages in userspace. Future issues: @@ -37,12 +39,12 @@ - Add a -n (numeric) switch. - Check for unwanted options. * Segmented Sdo downloads. +* Get original driver for r8169. Smaller issues: * Stop master thread at ecrt_master_request() to get rid of allow_* flags? * Evaluate SII Size field (0x003E) to determine maximum SII memory size. -* Unite fsm_pdo_mapping, fsm_pdo_config and fsm_coe_map. * Clear sync managers in INIT. * Read out CRC counters. * Configure slave ports to automatically open on link detection. diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/Makefile --- a/documentation/graphs/Makefile Thu Jul 31 09:30:38 2008 +0000 +++ b/documentation/graphs/Makefile Thu Jul 31 16:13:29 2008 +0000 @@ -5,10 +5,11 @@ #----------------------------------------------------------------------------- GRAPHS := \ - fsm_coe_map \ fsm_master \ - fsm_pdo_assign \ - fsm_pdo_mapping \ + fsm_pdo_conf \ + fsm_pdo_read \ + fsm_pdo_entry_conf \ + fsm_pdo_entry_read \ fsm_slave_conf \ fsm_slave_scan diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_coe_map.dot --- a/documentation/graphs/fsm_coe_map.dot Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ - -/* $Id$ */ - -digraph readpdomapping { - size="7,9" - center=1 - ratio=fill - - next_sync [shape=point,label=""] - next_pdo [shape=point,label=""] - next_pdo_entry [shape=point,label=""] - - start -> next_sync [label="first SM"] - - next_sync -> pdo_count [weight=5] - next_sync -> end - - pdo_count -> next_pdo [weight=5] - - next_pdo -> pdo [weight=5] - next_pdo -> next_sync - - pdo -> pdo_entry_count [weight=5] - - pdo_entry_count -> next_pdo_entry [weight=10] - - next_pdo_entry -> pdo_entry [weight=5] - next_pdo_entry -> next_pdo - - pdo_entry -> next_pdo_entry - - end -} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_assign.dot --- a/documentation/graphs/fsm_pdo_assign.dot Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - -/* $Id$ */ - -digraph pdomapping { - size="7,9" - center=1 - ratio=fill - - next_sync [shape=point,label=""] - - start -> next_sync [label="First SM"] - next_sync -> end [label="No more SMs"] - next_sync -> zero_count [label="Next SM"] - zero_count -> next_sync [label="No Pdos"] - zero_count -> add_pdo [label="Map first Pdo", weight=5] - add_pdo -> add_pdo [label="Map next Pdo"] - add_pdo -> pdo_count [label="No more Pdos", weight=5] - pdo_count -> next_sync -} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_conf.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/documentation/graphs/fsm_pdo_conf.dot Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,54 @@ + +/* $Id$ */ + +digraph pdo_conf { + size="7,9" + center=1 + ratio=fill + + start [fontname="Helvetica"] + start -> action_next_sync [fontname="Helvetica",label="First SM",weight=10] + start -> end [fontname="Helvetica",label="No config"] + + action_next_sync [shape=point,label=""] + action_next_sync -> action_check_assignment [fontname="Helvetica",label="No Pdos"] + action_next_sync -> action_pdo_mapping [fontname="Helvetica",label="First Pdo",weight=10] + action_next_sync -> end [fontname="Helvetica",label="No more SMs"] + + action_pdo_mapping [shape=point,label=""] + action_pdo_mapping -> read_mapping [fontname="Helvetica",label="Unknown"] + action_pdo_mapping -> action_check_mapping [weight=10] + + read_mapping [fontname="Helvetica"] + read_mapping -> action_check_mapping + + action_check_mapping [shape=point,label=""] + action_check_mapping -> action_next_pdo_mapping + action_check_mapping -> mapping [weight=10] + + mapping [fontname="Helvetica"] + mapping -> action_next_pdo_mapping [weight=10] + + action_next_pdo_mapping [shape=point,label=""] + action_next_pdo_mapping -> action_check_assignment [weight=10] + action_next_pdo_mapping -> action_pdo_mapping + [fontname="Helvetica",label="Next Pdo"] + + action_check_assignment [shape=point,label=""] + action_check_assignment -> action_next_sync [fontname="Helvetica",label="Assign ok"] + action_check_assignment -> zero_pdo_count [weight=10] + + zero_pdo_count [fontname="Helvetica"] + zero_pdo_count -> action_next_sync [fontname="Helvetica",label="No Pdos"] + zero_pdo_count -> action_assign_pdo [fontname="Helvetica",label="First Pdo", weight=10] + + action_assign_pdo [shape=point,label=""] + action_assign_pdo -> assign_pdo [weight=10] + + assign_pdo [fontname="Helvetica"] + assign_pdo -> set_pdo_count [fontname="Helvetica",label="No more Pdos", weight=10] + assign_pdo -> action_assign_pdo [fontname="Helvetica",label="Next Pdo"] + + set_pdo_count [fontname="Helvetica"] + set_pdo_count -> action_next_sync +} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_entry_conf.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/documentation/graphs/fsm_pdo_entry_conf.dot Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,28 @@ + +/* $Id$ */ + +digraph pdo_entry_conf { + size="7,9" + center=1 + ratio=fill + + start [fontname="Helvetica"] + start -> zero_entry_count [weight=10] + + zero_entry_count [fontname="Helvetica"] + zero_entry_count -> end [fontname="Helvetica",label="No Entries"] + zero_entry_count -> action_map [fontname="Helvetica",label="Add first entry", weight=10] + + action_map [shape=point,label=""] + action_map -> map_entry [weight=10] + + map_entry [fontname="Helvetica"] + map_entry -> action_map [fontname="Helvetica",label="Next entry"] + map_entry -> set_entry_count [fontname="Helvetica",label="No more Entries", weight=10] + + set_entry_count [fontname="Helvetica"] + set_entry_count -> end [weight=10] + + end [fontname="Helvetica"] + end +} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_entry_read.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/documentation/graphs/fsm_pdo_entry_read.dot Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,23 @@ + +/* $Id$ */ + +digraph pdo_entry_read { + size="7,9" + center=1 + ratio=fill + + start [fontname="Helvetica"] + start -> count [weight=5] + + count [fontname="Helvetica"] + count -> action_next [weight=5] + + action_next [shape=point,label=""] + action_next -> pdo_entry [fontname="Helvetica", label="Next entry", weight=5] + action_next -> end [fontname="Helvetica", label="No more entries"] + + pdo_entry [fontname="Helvetica"] + pdo_entry -> action_next + + end [fontname="Helvetica"] +} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_mapping.dot --- a/documentation/graphs/fsm_pdo_mapping.dot Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - -/* $Id$ */ - -digraph pdoconfig { - size="7,9" - center=1 - ratio=fill - - next_pdo [shape=point,label=""] - - start -> next_pdo [label="First Pdo"] - next_pdo -> end [label="No more Pdos"] - next_pdo -> zero_count [label="Next Pdo"] - zero_count -> next_pdo [label="No Entries"] - zero_count -> add_entry [label="Add first entry", weight=5] - add_entry -> add_entry [label="Add next entry"] - add_entry -> entry_count [label="No more Entries", weight=5] - entry_count -> next_pdo -} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_pdo_read.dot --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/documentation/graphs/fsm_pdo_read.dot Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,30 @@ + +/* $Id$ */ + +digraph pdo_read { + size="7,9" + center=1 + ratio=fill + + start [fontname="Helvetica"] + start -> action_next_sync [fontname="Helvetica", label="First SM", weight=5] + + action_next_sync [shape=point,label=""] + action_next_sync -> pdo_count [weight=5] + action_next_sync -> end + + pdo_count [fontname="Helvetica"] + pdo_count -> action_next_pdo [weight=5] + + action_next_pdo [shape=point,label=""] + action_next_pdo -> pdo [fontname="Helvetica", label="Next Pdo", weight=5] + action_next_pdo -> action_next_sync [fontname="Helvetica", label="No more Pdos"] + + pdo [fontname="Helvetica"] + pdo -> pdo_entries [weight=5] + + pdo_entries [fontname="Helvetica"] + pdo_entries -> action_next_pdo + + end [fontname="Helvetica"] +} diff -r 2ec9651a6c89 -r 235f34ca50e2 documentation/graphs/fsm_slave_conf.dot --- a/documentation/graphs/fsm_slave_conf.dot Thu Jul 31 09:30:38 2008 +0000 +++ b/documentation/graphs/fsm_slave_conf.dot Thu Jul 31 16:13:29 2008 +0000 @@ -53,17 +53,12 @@ pdo_sync [fontname="Helvetica"] //pdo_sync -> pdo_sync //pdo_sync -> error - pdo_sync -> pdo_mapping [weight=10] + pdo_sync -> pdo_conf [weight=10] - pdo_mapping [fontname="Helvetica"] - //pdo_mapping -> pdo_mapping - //pdo_mapping -> error - pdo_mapping -> pdo_assign [weight=10] - - pdo_assign [fontname="Helvetica"] - //pdo_assign -> pdo_assign - //pdo_assign -> error - pdo_assign -> enter_fmmu [weight=10] + pdo_conf [fontname="Helvetica"] + //pdo_conf -> pdo_conf + //pdo_conf -> error + pdo_conf -> enter_fmmu [weight=10] enter_fmmu [shape=point,label=""] enter_fmmu -> enter_safeop [fontname="Helvetica",label="No FMMUs\nto configure"] diff -r 2ec9651a6c89 -r 235f34ca50e2 master/Kbuild.in --- a/master/Kbuild.in Thu Jul 31 09:30:38 2008 +0000 +++ b/master/Kbuild.in Thu Jul 31 16:13:29 2008 +0000 @@ -43,10 +43,9 @@ fmmu_config.o \ fsm_change.o \ fsm_coe.o \ - fsm_coe_map.o \ fsm_master.o \ - fsm_pdo_assign.o \ - fsm_pdo_mapping.o \ + fsm_pdo.o \ + fsm_pdo_entry.o \ fsm_sii.o \ fsm_slave_config.o \ fsm_slave_scan.o \ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/Makefile.am --- a/master/Makefile.am Thu Jul 31 09:30:38 2008 +0000 +++ b/master/Makefile.am Thu Jul 31 16:13:29 2008 +0000 @@ -43,10 +43,9 @@ fmmu_config.c fmmu_config.h \ fsm_change.c fsm_change.h \ fsm_coe.c fsm_coe.h \ - fsm_coe_map.c fsm_coe_map.h \ fsm_master.c fsm_master.h \ - fsm_pdo_assign.c fsm_pdo_assign.h \ - fsm_pdo_mapping.c fsm_pdo_mapping.h \ + fsm_pdo.c fsm_pdo.h \ + fsm_pdo_entry.c fsm_pdo_entry.h \ fsm_sii.c fsm_sii.h \ fsm_slave_config.c fsm_slave_config.h \ fsm_slave_scan.c fsm_slave_scan.h \ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_coe_map.c --- a/master/fsm_coe_map.c Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,460 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** - \file - EtherCAT Pdo information state machines. -*/ - -/*****************************************************************************/ - -#include "globals.h" -#include "master.h" -#include "mailbox.h" -#include "sdo_request.h" -#include "fsm_coe_map.h" - -/*****************************************************************************/ - -void ec_fsm_coe_map_state_start(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_state_pdo_count(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_state_pdo(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_state_pdo_entry_count(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_state_pdo_entry(ec_fsm_coe_map_t *); - -void ec_fsm_coe_map_state_end(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_state_error(ec_fsm_coe_map_t *); - -void ec_fsm_coe_map_action_next_sync(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_action_next_pdo(ec_fsm_coe_map_t *); -void ec_fsm_coe_map_action_next_pdo_entry(ec_fsm_coe_map_t *); - -/*****************************************************************************/ - -/** - Constructor. -*/ - -void ec_fsm_coe_map_init( - ec_fsm_coe_map_t *fsm, /**< finite state machine */ - ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */ - ) -{ - fsm->fsm_coe = fsm_coe; - fsm->state = NULL; - ec_sdo_request_init(&fsm->request); - ec_pdo_list_init(&fsm->pdos); -} - -/*****************************************************************************/ - -/** - Destructor. -*/ - -void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *fsm /**< finite state machine */) -{ - ec_sdo_request_clear(&fsm->request); - ec_pdo_list_clear(&fsm->pdos); -} - -/*****************************************************************************/ - -/** - Starts to upload an Sdo from a slave. -*/ - -void ec_fsm_coe_map_start( - ec_fsm_coe_map_t *fsm, /**< finite state machine */ - ec_slave_t *slave /**< EtherCAT slave */ - ) -{ - fsm->slave = slave; - fsm->state = ec_fsm_coe_map_state_start; -} - -/*****************************************************************************/ - -/** - Executes the current state of the state machine. - \return false, if state machine has terminated -*/ - -int ec_fsm_coe_map_exec(ec_fsm_coe_map_t *fsm /**< finite state machine */) -{ - fsm->state(fsm); - - return fsm->state != ec_fsm_coe_map_state_end - && fsm->state != ec_fsm_coe_map_state_error; -} - -/*****************************************************************************/ - -/** - Returns, if the state machine terminated with success. - \return non-zero if successful. -*/ - -int ec_fsm_coe_map_success(ec_fsm_coe_map_t *fsm /**< Finite state machine */) -{ - return fsm->state == ec_fsm_coe_map_state_end; -} - -/****************************************************************************** - * state functions - *****************************************************************************/ - -/** Start reading Pdo assignment. - */ -void ec_fsm_coe_map_state_start( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - // read Pdo assignment for first sync manager not reserved for mailbox - fsm->sync_index = 1; // next is 2 - ec_fsm_coe_map_action_next_sync(fsm); -} - -/*****************************************************************************/ - -/** Read Pdo assignment of next sync manager. - */ -void ec_fsm_coe_map_action_next_sync( - ec_fsm_coe_map_t *fsm /**< Finite state machine */ - ) -{ - ec_slave_t *slave = fsm->slave; - - fsm->sync_index++; - - for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) { - if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index))) - continue; - - fsm->sync_sdo_index = 0x1C10 + fsm->sync_index; - - if (slave->master->debug_level) - EC_DBG("Reading Pdo assignment of SM%u of slave %u.\n", - fsm->sync_index, slave->ring_position); - - ec_pdo_list_clear_pdos(&fsm->pdos); - - ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index, 0); - ecrt_sdo_request_read(&fsm->request); - fsm->state = ec_fsm_coe_map_state_pdo_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - if (slave->master->debug_level) - EC_DBG("Reading of Pdo assignment finished for slave %u.\n", - slave->ring_position); - - fsm->state = ec_fsm_coe_map_state_end; -} - -/*****************************************************************************/ - -/** - * Count assigned Pdos. - */ - -void ec_fsm_coe_map_state_pdo_count( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_ERR("Failed to read number of assigned Pdos from slave %u.\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - if (fsm->request.data_size != sizeof(uint8_t)) { - EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " - "from slave %u.\n", fsm->request.data_size, - fsm->request.index, fsm->request.subindex, - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - fsm->sync_subindices = EC_READ_U8(fsm->request.data); - - if (fsm->slave->master->debug_level) - EC_DBG("%u Pdos assigned.\n", fsm->sync_subindices); - - // read first Pdo - fsm->sync_subindex = 1; - ec_fsm_coe_map_action_next_pdo(fsm); -} - -/*****************************************************************************/ - -/** - * Read next Pdo. - */ - -void ec_fsm_coe_map_action_next_pdo( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (fsm->sync_subindex <= fsm->sync_subindices) { - ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index, - fsm->sync_subindex); - ecrt_sdo_request_read(&fsm->request); - fsm->state = ec_fsm_coe_map_state_pdo; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - // finished reading Pdo assignment/mapping - - if (ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos)) { - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - fsm->sync->assign_source = EC_ASSIGN_COE; - ec_pdo_list_clear_pdos(&fsm->pdos); - - // next sync manager - ec_fsm_coe_map_action_next_sync(fsm); -} - -/*****************************************************************************/ - -/** - * Fetch Pdo information. - */ - -void ec_fsm_coe_map_state_pdo( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_ERR("Failed to read assigned Pdo index from slave %u.\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - if (fsm->request.data_size != sizeof(uint16_t)) { - EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " - "from slave %u.\n", fsm->request.data_size, - fsm->request.index, fsm->request.subindex, - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - if (!(fsm->pdo = (ec_pdo_t *) - kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate Pdo.\n"); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - ec_pdo_init(fsm->pdo); - fsm->pdo->index = EC_READ_U16(fsm->request.data); - fsm->pdo->sync_index = fsm->sync_index; - - if (fsm->slave->master->debug_level) - EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index); - - list_add_tail(&fsm->pdo->list, &fsm->pdos.list); - - ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0); - ecrt_sdo_request_read(&fsm->request); - fsm->state = ec_fsm_coe_map_state_pdo_entry_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately -} - -/*****************************************************************************/ - -/** - * Read number of mapped Pdo entries. - */ - -void ec_fsm_coe_map_state_pdo_entry_count( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_ERR("Failed to read number of mapped Pdo entries from slave %u.\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - if (fsm->request.data_size != sizeof(uint8_t)) { - EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " - "from slave %u.\n", fsm->request.data_size, - fsm->request.index, fsm->request.subindex, - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - fsm->pdo_subindices = EC_READ_U8(fsm->request.data); - - if (fsm->slave->master->debug_level) - EC_DBG("%u Pdo entries mapped.\n", fsm->pdo_subindices); - - // read first Pdo entry - fsm->pdo_subindex = 1; - ec_fsm_coe_map_action_next_pdo_entry(fsm); -} - -/*****************************************************************************/ - -/** - * Read next Pdo entry. - */ - -void ec_fsm_coe_map_action_next_pdo_entry( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (fsm->pdo_subindex <= fsm->pdo_subindices) { - ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->pdo_subindex); - ecrt_sdo_request_read(&fsm->request); - fsm->state = ec_fsm_coe_map_state_pdo_entry; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - // next Pdo - fsm->sync_subindex++; - ec_fsm_coe_map_action_next_pdo(fsm); -} - -/*****************************************************************************/ - -/** - * Read Pdo entry information. - */ - -void ec_fsm_coe_map_state_pdo_entry( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_ERR("Failed to read mapped Pdo entry from slave %u.\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - if (fsm->request.data_size != sizeof(uint32_t)) { - EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " - "from slave %u.\n", fsm->request.data_size, - fsm->request.index, fsm->request.subindex, - fsm->slave->ring_position); - fsm->state = ec_fsm_coe_map_state_error; - } else { - uint32_t pdo_entry_info; - ec_pdo_entry_t *pdo_entry; - - pdo_entry_info = EC_READ_U32(fsm->request.data); - - if (!(pdo_entry = (ec_pdo_entry_t *) - kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { - EC_ERR("Failed to allocate Pdo entry.\n"); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - - ec_pdo_entry_init(pdo_entry); - pdo_entry->index = pdo_entry_info >> 16; - pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF; - pdo_entry->bit_length = pdo_entry_info & 0xFF; - - if (!pdo_entry->index && !pdo_entry->subindex) { - if (ec_pdo_entry_set_name(pdo_entry, "Gap")) { - ec_pdo_entry_clear(pdo_entry); - kfree(pdo_entry); - fsm->state = ec_fsm_coe_map_state_error; - return; - } - } - - if (fsm->slave->master->debug_level) { - EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n", - pdo_entry->index, pdo_entry->subindex, - pdo_entry->bit_length, - pdo_entry->name ? pdo_entry->name : "???"); - } - - // next Pdo entry - list_add_tail(&pdo_entry->list, &fsm->pdo->entries); - fsm->pdo_subindex++; - ec_fsm_coe_map_action_next_pdo_entry(fsm); - } -} - -/*****************************************************************************/ - -/** - State: ERROR. -*/ - -void ec_fsm_coe_map_state_error( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ -} - -/*****************************************************************************/ - -/** - State: END. -*/ - -void ec_fsm_coe_map_state_end( - ec_fsm_coe_map_t *fsm /**< finite state machine */ - ) -{ -} - -/*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_coe_map.h --- a/master/fsm_coe_map.h Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** - \file - EtherCAT CoE mapping state machines. -*/ - -/*****************************************************************************/ - -#ifndef __EC_FSM_COE_MAP_H__ -#define __EC_FSM_COE_MAP_H__ - -#include "globals.h" -#include "datagram.h" -#include "slave.h" -#include "fsm_coe.h" - -/*****************************************************************************/ - -typedef struct ec_fsm_coe_map ec_fsm_coe_map_t; /**< \see ec_fsm_coe_map */ - -/** - * \todo doc - */ -struct ec_fsm_coe_map -{ - void (*state)(ec_fsm_coe_map_t *); /**< CoE mapping state function */ - ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */ - - ec_slave_t *slave; /**< EtherCAT slave */ - ec_sdo_request_t request; /**< Sdo request */ - - uint8_t sync_index; /**< Index of the current sync manager. */ - ec_sync_t *sync; /**< Pdo sync manager. */ - uint16_t sync_sdo_index; /**< Index of the mapping Sdo. */ - uint8_t sync_subindices; /**< number of mapped Pdos */ - uint16_t sync_subindex; /**< current subindex in mapping Sdo */ - - ec_pdo_list_t pdos; /**< List of read in Pdos. */ - ec_pdo_t *pdo; /**< Current Pdo. */ - ec_sdo_t *pdo_sdo; /**< Current Pdo Sdo. */ - uint8_t pdo_subindices; /**< Number of Pdo entries. */ - uint16_t pdo_subindex; /**< Current subindex in Pdo Sdo. */ -}; - -/*****************************************************************************/ - -void ec_fsm_coe_map_init(ec_fsm_coe_map_t *, ec_fsm_coe_t *); -void ec_fsm_coe_map_clear(ec_fsm_coe_map_t *); - -void ec_fsm_coe_map_start(ec_fsm_coe_map_t *, ec_slave_t *); - -int ec_fsm_coe_map_exec(ec_fsm_coe_map_t *); -int ec_fsm_coe_map_success(ec_fsm_coe_map_t *); - -/*****************************************************************************/ - -#endif diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_master.c --- a/master/fsm_master.c Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_master.c Thu Jul 31 16:13:29 2008 +0000 @@ -79,13 +79,14 @@ fsm->slave_states = EC_SLAVE_STATE_UNKNOWN; // init sub-state-machines - ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram); + ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram); + ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe); + ec_fsm_change_init(&fsm->fsm_change, fsm->datagram); + ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram, + &fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_pdo); ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram, - &fsm->fsm_slave_config, &fsm->fsm_coe_map); + &fsm->fsm_slave_config, &fsm->fsm_pdo); ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram); - ec_fsm_change_init(&fsm->fsm_change, fsm->datagram); - ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram); - ec_fsm_coe_map_init(&fsm->fsm_coe_map, &fsm->fsm_coe); } /*****************************************************************************/ @@ -97,12 +98,12 @@ ) { // clear sub-state machines + ec_fsm_coe_clear(&fsm->fsm_coe); + ec_fsm_pdo_clear(&fsm->fsm_pdo); + ec_fsm_change_clear(&fsm->fsm_change); ec_fsm_slave_config_clear(&fsm->fsm_slave_config); ec_fsm_slave_scan_clear(&fsm->fsm_slave_scan); ec_fsm_sii_clear(&fsm->fsm_sii); - ec_fsm_change_clear(&fsm->fsm_change); - ec_fsm_coe_clear(&fsm->fsm_coe); - ec_fsm_coe_map_clear(&fsm->fsm_coe_map); } /*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_master.h --- a/master/fsm_master.h Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_master.h Thu Jul 31 16:13:29 2008 +0000 @@ -48,7 +48,7 @@ #include "sdo_request.h" #include "fsm_slave_config.h" #include "fsm_slave_scan.h" -#include "fsm_coe_map.h" +#include "fsm_pdo.h" /*****************************************************************************/ @@ -95,12 +95,12 @@ off_t sii_index; /**< index to SII write request data */ ec_sdo_request_t *sdo_request; /**< Sdo request to process. */ + ec_fsm_coe_t fsm_coe; /**< CoE state machine */ + ec_fsm_pdo_t fsm_pdo; /**< Pdo configuration state machine. */ + ec_fsm_change_t fsm_change; /**< State change state machine */ ec_fsm_slave_config_t fsm_slave_config; /**< slave state machine */ ec_fsm_slave_scan_t fsm_slave_scan; /**< slave state machine */ ec_fsm_sii_t fsm_sii; /**< SII state machine */ - ec_fsm_change_t fsm_change; /**< State change state machine */ - ec_fsm_coe_t fsm_coe; /**< CoE state machine */ - ec_fsm_coe_map_t fsm_coe_map; /**< CoE mapping state machine */ }; /*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_pdo.c Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,762 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** \file + * EtherCAT Pdo configuration state machine. + */ + +/*****************************************************************************/ + +#include "globals.h" +#include "master.h" +#include "mailbox.h" +#include "slave_config.h" + +#include "fsm_pdo.h" + +/*****************************************************************************/ + +void ec_fsm_pdo_read_state_start(ec_fsm_pdo_t *); +void ec_fsm_pdo_read_state_pdo_count(ec_fsm_pdo_t *); +void ec_fsm_pdo_read_state_pdo(ec_fsm_pdo_t *); +void ec_fsm_pdo_read_state_pdo_entries(ec_fsm_pdo_t *); + +void ec_fsm_pdo_read_action_next_sync(ec_fsm_pdo_t *); +void ec_fsm_pdo_read_action_next_pdo(ec_fsm_pdo_t *); + +void ec_fsm_pdo_conf_state_start(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_read_mapping(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_mapping(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_zero_pdo_count(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_assign_pdo(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_set_pdo_count(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_state_entries(ec_fsm_pdo_t *); + +void ec_fsm_pdo_conf_action_next_sync(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_action_pdo_mapping(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_action_check_mapping(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_action_next_pdo_mapping(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_action_check_assignment(ec_fsm_pdo_t *); +void ec_fsm_pdo_conf_action_assign_pdo(ec_fsm_pdo_t *); + +void ec_fsm_pdo_state_end(ec_fsm_pdo_t *); +void ec_fsm_pdo_state_error(ec_fsm_pdo_t *); + +/*****************************************************************************/ + +/** Constructor. + */ +void ec_fsm_pdo_init( + ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */ + ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */ + ) +{ + fsm->fsm_coe = fsm_coe; + ec_fsm_pdo_entry_init(&fsm->fsm_pdo_entry, fsm_coe); + ec_pdo_list_init(&fsm->pdos); + ec_sdo_request_init(&fsm->request); + ec_pdo_init(&fsm->slave_pdo); +} + +/*****************************************************************************/ + +/** Destructor. + */ +void ec_fsm_pdo_clear( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + ec_fsm_pdo_entry_clear(&fsm->fsm_pdo_entry); + ec_pdo_list_clear(&fsm->pdos); + ec_sdo_request_clear(&fsm->request); + ec_pdo_clear(&fsm->slave_pdo); +} + +/*****************************************************************************/ + +/** Start reading the Pdo configuration. + */ +void ec_fsm_pdo_start_reading( + ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */ + ec_slave_t *slave /**< slave to configure */ + ) +{ + fsm->slave = slave; + fsm->state = ec_fsm_pdo_read_state_start; +} + +/*****************************************************************************/ + +/** Start writing the Pdo configuration. + */ +void ec_fsm_pdo_start_configuration( + ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */ + ec_slave_t *slave /**< slave to configure */ + ) +{ + fsm->slave = slave; + fsm->state = ec_fsm_pdo_conf_state_start; +} + +/*****************************************************************************/ + +/** Get running state. + * + * \return false, if state machine has terminated + */ +int ec_fsm_pdo_running( + const ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + return fsm->state != ec_fsm_pdo_state_end + && fsm->state != ec_fsm_pdo_state_error; +} + +/*****************************************************************************/ + +/** Executes the current state of the state machine. + * + * If the state machine's datagram is not sent or received yet, the execution + * of the state machine is delayed to the next cycle. + * + * \return false, if state machine has terminated + */ +int ec_fsm_pdo_exec( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + fsm->state(fsm); + return ec_fsm_pdo_running(fsm); +} + +/*****************************************************************************/ + +/** Get execution result. + * + * \return true, if the state machine terminated gracefully + */ +int ec_fsm_pdo_success( + const ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + return fsm->state == ec_fsm_pdo_state_end; +} + +/****************************************************************************** + * Reading state funtions. + *****************************************************************************/ + +/** Start reading Pdo assignment. + */ +void ec_fsm_pdo_read_state_start( + ec_fsm_pdo_t *fsm /**< finite state machine */ + ) +{ + // read Pdo assignment for first sync manager not reserved for mailbox + fsm->sync_index = 1; // next is 2 + ec_fsm_pdo_read_action_next_sync(fsm); +} + +/*****************************************************************************/ + +/** Read Pdo assignment of next sync manager. + */ +void ec_fsm_pdo_read_action_next_sync( + ec_fsm_pdo_t *fsm /**< Finite state machine */ + ) +{ + ec_slave_t *slave = fsm->slave; + + fsm->sync_index++; + + for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) { + if (!(fsm->sync = ec_slave_get_sync(slave, fsm->sync_index))) + continue; + + if (slave->master->debug_level) + EC_DBG("Reading Pdo assignment of SM%u.\n", fsm->sync_index); + + ec_pdo_list_clear_pdos(&fsm->pdos); + + ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0); + ecrt_sdo_request_read(&fsm->request); + fsm->state = ec_fsm_pdo_read_state_pdo_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately + return; + } + + if (slave->master->debug_level) + EC_DBG("Reading of Pdo configuration finished.\n"); + + fsm->state = ec_fsm_pdo_state_end; +} + +/*****************************************************************************/ + +/** Count assigned Pdos. + */ +void ec_fsm_pdo_read_state_pdo_count( + ec_fsm_pdo_t *fsm /**< finite state machine */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_ERR("Failed to read number of assigned Pdos for SM%u.\n", + fsm->sync_index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + if (fsm->request.data_size != sizeof(uint8_t)) { + EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " + "from slave %u.\n", fsm->request.data_size, + fsm->request.index, fsm->request.subindex, + fsm->slave->ring_position); + fsm->state = ec_fsm_pdo_state_error; + return; + } + fsm->pdo_count = EC_READ_U8(fsm->request.data); + + if (fsm->slave->master->debug_level) + EC_DBG("%u Pdos assigned.\n", fsm->pdo_count); + + // read first Pdo + fsm->pdo_pos = 1; + ec_fsm_pdo_read_action_next_pdo(fsm); +} + +/*****************************************************************************/ + +/** Read next Pdo. + */ +void ec_fsm_pdo_read_action_next_pdo( + ec_fsm_pdo_t *fsm /**< finite state machine */ + ) +{ + if (fsm->pdo_pos <= fsm->pdo_count) { + ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, + fsm->pdo_pos); + ecrt_sdo_request_read(&fsm->request); + fsm->state = ec_fsm_pdo_read_state_pdo; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately + return; + } + + // finished reading Pdo configuration + + if (ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos)) { + fsm->state = ec_fsm_pdo_state_error; + return; + } + + fsm->sync->assign_source = EC_ASSIGN_COE; + ec_pdo_list_clear_pdos(&fsm->pdos); + + // next sync manager + ec_fsm_pdo_read_action_next_sync(fsm); +} + +/*****************************************************************************/ + +/** Fetch Pdo information. + */ +void ec_fsm_pdo_read_state_pdo( + ec_fsm_pdo_t *fsm /**< finite state machine */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_ERR("Failed to read index of assigned Pdo %u from SM%u.\n", + fsm->pdo_pos, fsm->sync_index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + if (fsm->request.data_size != sizeof(uint16_t)) { + EC_ERR("Invalid data size %u returned when uploading Sdo 0x%04X:%02X " + "from slave %u.\n", fsm->request.data_size, + fsm->request.index, fsm->request.subindex, + fsm->slave->ring_position); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + if (!(fsm->pdo = (ec_pdo_t *) + kmalloc(sizeof(ec_pdo_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate Pdo.\n"); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + ec_pdo_init(fsm->pdo); + fsm->pdo->index = EC_READ_U16(fsm->request.data); + fsm->pdo->sync_index = fsm->sync_index; + + if (fsm->slave->master->debug_level) + EC_DBG("Pdo 0x%04X.\n", fsm->pdo->index); + + list_add_tail(&fsm->pdo->list, &fsm->pdos.list); + + fsm->state = ec_fsm_pdo_read_state_pdo_entries; + ec_fsm_pdo_entry_start_reading(&fsm->fsm_pdo_entry, fsm->slave, fsm->pdo); + fsm->state(fsm); // execute immediately +} + +/*****************************************************************************/ + +/** Fetch Pdo information. + */ +void ec_fsm_pdo_read_state_pdo_entries( + ec_fsm_pdo_t *fsm /**< finite state machine */ + ) +{ + if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry)) + return; + + if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry)) { + EC_ERR("Failed to read mapped Pdo entries for Pdo 0x%04X.\n", + fsm->pdo->index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + // next Pdo + fsm->pdo_pos++; + ec_fsm_pdo_read_action_next_pdo(fsm); +} + +/****************************************************************************** + * Writing state functions. + *****************************************************************************/ + +/** Start Pdo configuration. + */ +void ec_fsm_pdo_conf_state_start( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (!fsm->slave->config) { + fsm->state = ec_fsm_pdo_state_end; + return; + } + + fsm->sync_index = 0xff; // next is zero + ec_fsm_pdo_conf_action_next_sync(fsm); +} + +/*****************************************************************************/ + +/** Assign next Pdo. + */ +ec_pdo_t *ec_fsm_pdo_conf_action_next_pdo( + const ec_fsm_pdo_t *fsm, /**< Pdo configuration state machine. */ + const struct list_head *list /**< current Pdo list item */ + ) +{ + list = list->next; + if (list == &fsm->pdos.list) + return NULL; // no next Pdo + return list_entry(list, ec_pdo_t, list); +} + +/*****************************************************************************/ + +/** Get the next sync manager for a pdo configuration. + */ +void ec_fsm_pdo_conf_action_next_sync( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + fsm->sync_index++; + + for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) { + if (ec_pdo_list_copy(&fsm->pdos, + &fsm->slave->config->sync_configs[fsm->sync_index].pdos)) { + fsm->state = ec_fsm_pdo_state_error; + return; + } + + if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) { + if (!list_empty(&fsm->pdos.list)) + EC_WARN("Pdos configured for SM%u, but slave %u does not " + "provide a sync manager configuration!\n", + fsm->sync_index, fsm->slave->ring_position); + continue; + } + + // get first configured Pdo + if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdos.list))) { + // no pdos configured + ec_fsm_pdo_conf_action_check_assignment(fsm); + return; + } + + ec_fsm_pdo_conf_action_pdo_mapping(fsm); + return; + } + + fsm->state = ec_fsm_pdo_state_end; +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_action_pdo_mapping( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + const ec_pdo_t *assigned_pdo; + + fsm->slave_pdo.index = fsm->pdo->index; + + if ((assigned_pdo = ec_slave_find_pdo(fsm->slave, fsm->pdo->index))) { + ec_pdo_copy_entries(&fsm->slave_pdo, assigned_pdo); + } else { // configured Pdo is not assigned and thus unknown + ec_pdo_clear_entries(&fsm->slave_pdo); + } + + if (list_empty(&fsm->slave_pdo.entries)) { + + if (fsm->slave->master->debug_level) + EC_DBG("Reading mapping of Pdo 0x%04X.\n", + fsm->pdo->index); + + // pdo mapping is unknown; start loading it + ec_fsm_pdo_entry_start_reading(&fsm->fsm_pdo_entry, fsm->slave, + &fsm->slave_pdo); + fsm->state = ec_fsm_pdo_conf_state_read_mapping; + fsm->state(fsm); // execute immediately + return; + } + + // pdo mapping is known, check if it most be re-configured + ec_fsm_pdo_conf_action_check_mapping(fsm); +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_state_read_mapping( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry)) + return; + + if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry)) + EC_WARN("Failed to read mapped Pdo entries for Pdo 0x%04X.\n", + fsm->pdo->index); + + // check if the mapping must be re-configured + ec_fsm_pdo_conf_action_check_mapping(fsm); +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_action_check_mapping( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_pdo_equal_entries(fsm->pdo, &fsm->slave_pdo)) { + if (fsm->slave->master->debug_level) + EC_DBG("Mapping of Pdo 0x%04X is already configured correctly.\n", + fsm->pdo->index); + ec_fsm_pdo_conf_action_next_pdo_mapping(fsm); + return; + } + + if (fsm->slave->master->debug_level) { + // TODO display diff + EC_DBG("Changing mapping of Pdo 0x%04X.\n", fsm->pdo->index); + } + + ec_fsm_pdo_entry_start_configuration(&fsm->fsm_pdo_entry, fsm->slave, + fsm->pdo); + fsm->state = ec_fsm_pdo_conf_state_mapping; + fsm->state(fsm); // execure immediately +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_state_mapping( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_fsm_pdo_entry_exec(&fsm->fsm_pdo_entry)) + return; + + if (!ec_fsm_pdo_entry_success(&fsm->fsm_pdo_entry)) + EC_WARN("Failed to configure mapping of Pdo 0x%04X.\n", + fsm->pdo->index); + + ec_fsm_pdo_conf_action_next_pdo_mapping(fsm); +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_action_next_pdo_mapping( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + // get next configured Pdo + if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdo->list))) { + // no more configured pdos + ec_fsm_pdo_conf_action_check_assignment(fsm); + return; + } + + ec_fsm_pdo_conf_action_pdo_mapping(fsm); +} + +/*****************************************************************************/ + +/** + */ +void ec_fsm_pdo_conf_action_check_assignment( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + // check if assignment has to be re-configured + if (ec_pdo_list_equal(&fsm->sync->pdos, &fsm->pdos)) { + + if (fsm->slave->master->debug_level) + EC_DBG("Pdo assignment for SM%u is already configured " + "correctly.\n", fsm->sync_index); + + ec_fsm_pdo_conf_action_next_sync(fsm); + return; + } + + if (fsm->slave->master->debug_level) { + EC_DBG("Pdo assignment of SM%u differs:\n", fsm->sync_index); + EC_DBG("Currently assigned Pdos: "); + ec_pdo_list_print(&fsm->sync->pdos); + printk("\n"); + EC_DBG("Pdos to assign: "); + ec_pdo_list_print(&fsm->pdos); + printk("\n"); + } + + // Pdo assignment has to be changed. Does the slave support this? + if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE) + || (fsm->slave->sii.has_general + && !fsm->slave->sii.coe_details.enable_pdo_assign)) { + EC_WARN("Slave %u does not support assigning Pdos!\n", + fsm->slave->ring_position); + ec_fsm_pdo_conf_action_next_sync(fsm); + return; + } + + if (ec_sdo_request_alloc(&fsm->request, 2)) { + fsm->state = ec_fsm_pdo_state_error; + return; + } + + // set mapped Pdo count to zero + EC_WRITE_U8(fsm->request.data, 0); // zero Pdos mapped + fsm->request.data_size = 1; + ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0); + ecrt_sdo_request_write(&fsm->request); + + if (fsm->slave->master->debug_level) + EC_DBG("Setting number of assigned Pdos to zero.\n"); + + fsm->state = ec_fsm_pdo_conf_state_zero_pdo_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately +} + +/*****************************************************************************/ + +/** Set the number of assigned Pdos to zero. + */ +void ec_fsm_pdo_conf_state_zero_pdo_count( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) + return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_WARN("Failed to clear Pdo assignment of SM%u.\n", fsm->sync_index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + // the sync manager's assigned Pdos have been cleared + ec_pdo_list_clear_pdos(&fsm->sync->pdos); + + // assign all Pdos belonging to the current sync manager + + // find first Pdo + if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdos.list))) { + + if (fsm->slave->master->debug_level) + EC_DBG("No Pdos to assign.\n"); + + // check for mapping to be altered + ec_fsm_pdo_conf_action_next_sync(fsm); + return; + } + + // assign first Pdo + fsm->pdo_pos = 1; + ec_fsm_pdo_conf_action_assign_pdo(fsm); +} + +/*****************************************************************************/ + +/** Assign a Pdo. + */ +void ec_fsm_pdo_conf_action_assign_pdo( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + EC_WRITE_U16(fsm->request.data, fsm->pdo->index); + fsm->request.data_size = 2; + ec_sdo_request_address(&fsm->request, + 0x1C10 + fsm->sync_index, fsm->pdo_pos); + ecrt_sdo_request_write(&fsm->request); + + if (fsm->slave->master->debug_level) + EC_DBG("Assigning Pdo 0x%04X at position %u.\n", + fsm->pdo->index, fsm->pdo_pos); + + fsm->state = ec_fsm_pdo_conf_state_assign_pdo; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately +} + +/*****************************************************************************/ + +/** Add a Pdo to the sync managers Pdo assignment. + */ +void ec_fsm_pdo_conf_state_assign_pdo( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_WARN("Failed to assign Pdo 0x%04X at position %u of SM%u.\n", + fsm->pdo->index, fsm->pdo_pos, fsm->sync_index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + // find next Pdo + if (!(fsm->pdo = ec_fsm_pdo_conf_action_next_pdo(fsm, &fsm->pdo->list))) { + + // no more Pdos to assign, set Pdo count + EC_WRITE_U8(fsm->request.data, fsm->pdo_pos); + fsm->request.data_size = 1; + ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0); + ecrt_sdo_request_write(&fsm->request); + + if (fsm->slave->master->debug_level) + EC_DBG("Setting number of assigned Pdos to %u.\n", fsm->pdo_pos); + + fsm->state = ec_fsm_pdo_conf_state_set_pdo_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately + return; + } + + // add next Pdo to assignment + fsm->pdo_pos++; + ec_fsm_pdo_conf_action_assign_pdo(fsm); +} + +/*****************************************************************************/ + +/** Set the number of assigned Pdos. + */ +void ec_fsm_pdo_conf_state_set_pdo_count( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_WARN("Failed to set number of assigned Pdos of SM%u.\n", + fsm->sync_index); + fsm->state = ec_fsm_pdo_state_error; + return; + } + + // Pdos have been configured + ec_pdo_list_copy(&fsm->sync->pdos, &fsm->pdos); + + if (fsm->slave->master->debug_level) + EC_DBG("Successfully configured Pdo assignment of SM%u.\n", + fsm->sync_index); + + // check if Pdo mapping has to be altered + ec_fsm_pdo_conf_action_next_sync(fsm); +} + +/****************************************************************************** + * Common state functions + *****************************************************************************/ + +/** State: ERROR. + */ +void ec_fsm_pdo_state_error( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ +} + +/*****************************************************************************/ + +/** State: END. + */ +void ec_fsm_pdo_state_end( + ec_fsm_pdo_t *fsm /**< Pdo configuration state machine. */ + ) +{ +} + +/*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_pdo.h Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,90 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** + \file + EtherCAT Pdo configuration state machine structures. +*/ + +/*****************************************************************************/ + +#ifndef __EC_FSM_PDO_H__ +#define __EC_FSM_PDO_H__ + +#include "../include/ecrt.h" + +#include "globals.h" +#include "datagram.h" +#include "fsm_coe.h" +#include "fsm_pdo_entry.h" + +/*****************************************************************************/ + +/** + * \see ec_fsm_pdo + */ +typedef struct ec_fsm_pdo ec_fsm_pdo_t; + +/** Pdo configuration state machine. + */ +struct ec_fsm_pdo +{ + void (*state)(ec_fsm_pdo_t *); /**< State function. */ + ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */ + ec_fsm_pdo_entry_t fsm_pdo_entry; /**< Pdo entry state machine. */ + ec_pdo_list_t pdos; /**< Pdo configuration. */ + ec_sdo_request_t request; /**< Sdo request. */ + ec_pdo_t slave_pdo; /**< Pdo actually appearing in a slave. */ + + ec_slave_t *slave; /**< Slave the FSM runs on. */ + uint8_t sync_index; /**< Current sync manager index. */ + ec_sync_t *sync; /**< Current sync manager. */ + ec_pdo_t *pdo; /**< Current Pdo. */ + unsigned int pdo_pos; /**< Assignment position of current Pdos. */ + unsigned int pdo_count; /**< Number of assigned Pdos. */ +}; + +/*****************************************************************************/ + +void ec_fsm_pdo_init(ec_fsm_pdo_t *, ec_fsm_coe_t *); +void ec_fsm_pdo_clear(ec_fsm_pdo_t *); + +void ec_fsm_pdo_start_reading(ec_fsm_pdo_t *, ec_slave_t *); +void ec_fsm_pdo_start_configuration(ec_fsm_pdo_t *, ec_slave_t *); + +int ec_fsm_pdo_exec(ec_fsm_pdo_t *); +int ec_fsm_pdo_success(const ec_fsm_pdo_t *); + +/*****************************************************************************/ + +#endif diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_assign.c --- a/master/fsm_pdo_assign.c Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,389 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** \file - * EtherCAT Pdo assignment state machine. - */ - -/*****************************************************************************/ - -#include "globals.h" -#include "master.h" -#include "mailbox.h" -#include "slave_config.h" - -#include "fsm_pdo_assign.h" - -/*****************************************************************************/ - -void ec_fsm_pdo_assign_state_start(ec_fsm_pdo_assign_t *); -void ec_fsm_pdo_assign_state_zero_count(ec_fsm_pdo_assign_t *); -void ec_fsm_pdo_assign_state_add_pdo(ec_fsm_pdo_assign_t *); -void ec_fsm_pdo_assign_state_pdo_count(ec_fsm_pdo_assign_t *); -void ec_fsm_pdo_assign_state_end(ec_fsm_pdo_assign_t *); -void ec_fsm_pdo_assign_state_error(ec_fsm_pdo_assign_t *); - -void ec_fsm_pdo_assign_next_sync(ec_fsm_pdo_assign_t *); - -/*****************************************************************************/ - -/** Constructor. - */ -void ec_fsm_pdo_assign_init( - ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */ - ec_fsm_coe_t *fsm_coe /**< CoE state machine to use */ - ) -{ - fsm->fsm_coe = fsm_coe; - ec_sdo_request_init(&fsm->request); -} - -/*****************************************************************************/ - -/** Destructor. - */ -void ec_fsm_pdo_assign_clear( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - ec_sdo_request_clear(&fsm->request); -} - -/*****************************************************************************/ - -/** Start Pdo assignment state machine. - */ -void ec_fsm_pdo_assign_start( - ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */ - ec_slave_t *slave /**< slave to configure */ - ) -{ - fsm->slave = slave; - fsm->state = ec_fsm_pdo_assign_state_start; -} - -/*****************************************************************************/ - -/** Get running state. - * - * \return false, if state machine has terminated - */ -int ec_fsm_pdo_assign_running( - const ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - return fsm->state != ec_fsm_pdo_assign_state_end - && fsm->state != ec_fsm_pdo_assign_state_error; -} - -/*****************************************************************************/ - -/** Executes the current state of the state machine. - * - * If the state machine's datagram is not sent or received yet, the execution - * of the state machine is delayed to the next cycle. - * - * \return false, if state machine has terminated - */ -int ec_fsm_pdo_assign_exec( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - fsm->state(fsm); - return ec_fsm_pdo_assign_running(fsm); -} - -/*****************************************************************************/ - -/** Get execution result. - * - * \return true, if the state machine terminated gracefully - */ -int ec_fsm_pdo_assign_success( - const ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - return fsm->state == ec_fsm_pdo_assign_state_end; -} - -/****************************************************************************** - * State functions. - *****************************************************************************/ - -/** Start Pdo assignment. - */ -void ec_fsm_pdo_assign_state_start( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - if (!fsm->slave->config) { - fsm->state = ec_fsm_pdo_assign_state_end; - return; - } - - fsm->sync_index = 0xff; // next is zero - fsm->num_configured_syncs = 0; - ec_fsm_pdo_assign_next_sync(fsm); -} - -/*****************************************************************************/ - -/** Process Pdo assignment of next sync manager. - */ -void ec_fsm_pdo_assign_next_sync( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - fsm->sync_index++; - - for (; fsm->sync_index < EC_MAX_SYNC_MANAGERS; fsm->sync_index++) { - fsm->pdos = &fsm->slave->config->sync_configs[fsm->sync_index].pdos; - - if (!(fsm->sync = ec_slave_get_sync(fsm->slave, fsm->sync_index))) { - if (!list_empty(&fsm->pdos->list)) { - EC_WARN("Slave %u does not provide a configuration " - "for SM%u!\n", fsm->slave->ring_position, - fsm->sync_index); - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - continue; - } - - // check if assignment has to be altered - if (ec_pdo_list_equal(&fsm->sync->pdos, fsm->pdos)) - continue; - - if (fsm->slave->master->debug_level) { - EC_DBG("Pdo assignment of SM%u differs:\n", fsm->sync_index); - EC_DBG("Currently assigned Pdos: "); - ec_pdo_list_print(&fsm->sync->pdos); - printk("\n"); - EC_DBG("Pdos to assign: "); - ec_pdo_list_print(fsm->pdos); - printk("\n"); - } - - // Pdo assignment has to be changed. Does the slave support this? - if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE) - || (fsm->slave->sii.has_general - && !fsm->slave->sii.coe_details.enable_pdo_assign)) { - EC_WARN("Slave %u does not support assigning Pdos!\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - - fsm->num_configured_syncs++; - - if (ec_sdo_request_alloc(&fsm->request, 2)) { - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - - // set mapped Pdo count to zero - EC_WRITE_U8(fsm->request.data, 0); // zero Pdos mapped - fsm->request.data_size = 1; - ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0); - ecrt_sdo_request_write(&fsm->request); - - if (fsm->slave->master->debug_level) - EC_DBG("Setting Pdo count to zero.\n"); - - fsm->state = ec_fsm_pdo_assign_state_zero_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - if (fsm->slave->master->debug_level && !fsm->num_configured_syncs) - EC_DBG("Pdo assignments are already configured correctly.\n"); - fsm->state = ec_fsm_pdo_assign_state_end; -} - -/*****************************************************************************/ - -/** Assign next Pdo. - */ -ec_pdo_t *ec_fsm_pdo_assign_next_pdo( - const ec_fsm_pdo_assign_t *fsm, /**< Pdo assignment state machine. */ - const struct list_head *list /**< current Pdo list item */ - ) -{ - list = list->next; - if (list == &fsm->pdos->list) - return NULL; // no next Pdo - return list_entry(list, ec_pdo_t, list); -} - -/*****************************************************************************/ - -/** Assign a Pdo. - */ -void ec_fsm_pdo_assign_add_pdo( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - EC_WRITE_U16(fsm->request.data, fsm->pdo->index); - fsm->request.data_size = 2; - ec_sdo_request_address(&fsm->request, - 0x1C10 + fsm->sync_index, fsm->pdo_count); - ecrt_sdo_request_write(&fsm->request); - - if (fsm->slave->master->debug_level) - EC_DBG("Assigning Pdo 0x%04X at position %u.\n", - fsm->pdo->index, fsm->pdo_count); - - fsm->state = ec_fsm_pdo_assign_state_add_pdo; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately -} - -/*****************************************************************************/ - -/** Set the number of assigned Pdos to zero. - */ -void ec_fsm_pdo_assign_state_zero_count( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to clear Pdo assignment of SM%u.\n", fsm->sync_index); - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - - // assign all Pdos belonging to the current sync manager - - // find first Pdo - if (!(fsm->pdo = ec_fsm_pdo_assign_next_pdo(fsm, &fsm->pdos->list))) { - if (fsm->slave->master->debug_level) - EC_DBG("No Pdos to assign.\n"); - ec_fsm_pdo_assign_next_sync(fsm); - return; - } - - // assign first Pdo - fsm->pdo_count = 1; - ec_fsm_pdo_assign_add_pdo(fsm); -} - -/*****************************************************************************/ - -/** Add a Pdo to the sync managers Pdo assignment. - */ -void ec_fsm_pdo_assign_state_add_pdo( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to assign Pdo 0x%04X to position %u in SM%u.\n", - fsm->pdo->index, fsm->pdo_count, fsm->sync_index); - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - - // find next Pdo - if (!(fsm->pdo = ec_fsm_pdo_assign_next_pdo(fsm, &fsm->pdo->list))) { - // no more Pdos to map. write Pdo count - EC_WRITE_U8(fsm->request.data, fsm->pdo_count); - fsm->request.data_size = 1; - ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync_index, 0); - ecrt_sdo_request_write(&fsm->request); - - if (fsm->slave->master->debug_level) - EC_DBG("Setting number of assigned Pdos to %u.\n", - fsm->pdo_count); - - fsm->state = ec_fsm_pdo_assign_state_pdo_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - // add next Pdo to assignment - fsm->pdo_count++; - ec_fsm_pdo_assign_add_pdo(fsm); -} - -/*****************************************************************************/ - -/** Set the number of assigned Pdos. - */ -void ec_fsm_pdo_assign_state_pdo_count( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to set number of assigned Pdos for SM%u.\n", - fsm->sync_index); - fsm->state = ec_fsm_pdo_assign_state_error; - return; - } - - if (fsm->slave->master->debug_level) - EC_DBG("Pdo assignment successful for SM%u.\n", fsm->sync_index); - - // assignment for this sync manager finished - ec_fsm_pdo_assign_next_sync(fsm); -} - -/****************************************************************************** - * Common state functions - *****************************************************************************/ - -/** State: ERROR. - */ -void ec_fsm_pdo_assign_state_error( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ -} - -/*****************************************************************************/ - -/** State: END. - */ -void ec_fsm_pdo_assign_state_end( - ec_fsm_pdo_assign_t *fsm /**< Pdo assignment state machine. */ - ) -{ -} - -/*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_assign.h --- a/master/fsm_pdo_assign.h Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** - \file - EtherCAT Pdo assignment state machine structures. -*/ - -/*****************************************************************************/ - -#ifndef __EC_FSM_PDO_ASSIGN_H__ -#define __EC_FSM_PDO_ASSIGN_H__ - -#include "../include/ecrt.h" - -#include "globals.h" -#include "datagram.h" -#include "fsm_coe.h" - -/*****************************************************************************/ - -/** - * \see ec_fsm_pdo_assign - */ -typedef struct ec_fsm_pdo_assign ec_fsm_pdo_assign_t; - -/** Pdo assignment state machine. - */ -struct ec_fsm_pdo_assign -{ - void (*state)(ec_fsm_pdo_assign_t *); /**< State function. */ - ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use. */ - ec_slave_t *slave; /**< Slave the FSM runs on. */ - - uint8_t sync_index; /**< Current sync manager index. */ - const ec_pdo_list_t *pdos; /**< Target Pdo assignment. */ - const ec_sync_t *sync; /**< Current sync manager. */ - unsigned int num_configured_syncs; /**< Number of configured - assignments. */ - const ec_pdo_t *pdo; /**< Current Pdo. */ - - ec_sdo_request_t request; /**< Sdo request. */ - unsigned int pdo_count; /**< Number of assigned Pdos. */ -}; - -/*****************************************************************************/ - -void ec_fsm_pdo_assign_init(ec_fsm_pdo_assign_t *, ec_fsm_coe_t *); -void ec_fsm_pdo_assign_clear(ec_fsm_pdo_assign_t *); - -void ec_fsm_pdo_assign_start(ec_fsm_pdo_assign_t *, ec_slave_t *); -int ec_fsm_pdo_assign_exec(ec_fsm_pdo_assign_t *); -int ec_fsm_pdo_assign_success(const ec_fsm_pdo_assign_t *); - -/*****************************************************************************/ - -#endif diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_entry.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_pdo_entry.c Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,500 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** \file + * EtherCAT Pdo mapping state machine. + */ + +/*****************************************************************************/ + +#include "globals.h" +#include "master.h" +#include "mailbox.h" +#include "slave_config.h" + +#include "fsm_pdo_entry.h" + +/*****************************************************************************/ + +void ec_fsm_pdo_entry_read_state_start(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_read_state_count(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_read_state_entry(ec_fsm_pdo_entry_t *); + +void ec_fsm_pdo_entry_read_action_next(ec_fsm_pdo_entry_t *); + +void ec_fsm_pdo_entry_conf_state_start(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_conf_state_zero_entry_count(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_conf_state_map_entry(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_conf_state_set_entry_count(ec_fsm_pdo_entry_t *); + +void ec_fsm_pdo_entry_state_end(ec_fsm_pdo_entry_t *); +void ec_fsm_pdo_entry_state_error(ec_fsm_pdo_entry_t *); + +/*****************************************************************************/ + +/** Constructor. + */ +void ec_fsm_pdo_entry_init( + ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */ + ec_fsm_coe_t *fsm_coe /**< CoE state machine to use. */ + ) +{ + fsm->fsm_coe = fsm_coe; + ec_sdo_request_init(&fsm->request); +} + +/*****************************************************************************/ + +/** Destructor. + */ +void ec_fsm_pdo_entry_clear( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + ec_sdo_request_clear(&fsm->request); +} + +/*****************************************************************************/ + +/** Start reading a Pdo's entries. + */ +void ec_fsm_pdo_entry_start_reading( + ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */ + ec_slave_t *slave, /**< slave to configure */ + ec_pdo_t *pdo /**< Pdo to read entries for. */ + ) +{ + fsm->slave = slave; + fsm->target_pdo = pdo; + + ec_pdo_clear_entries(fsm->target_pdo); + + fsm->state = ec_fsm_pdo_entry_read_state_start; +} + +/*****************************************************************************/ + +/** Start Pdo mapping state machine. + */ +void ec_fsm_pdo_entry_start_configuration( + ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */ + ec_slave_t *slave, /**< slave to configure */ + const ec_pdo_t *pdo /**< Pdo with the desired entries. */ + ) +{ + fsm->slave = slave; + fsm->source_pdo = pdo; + + fsm->state = ec_fsm_pdo_entry_conf_state_start; +} + +/*****************************************************************************/ + +/** Get running state. + * + * \return false, if state machine has terminated + */ +int ec_fsm_pdo_entry_running( + const ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + return fsm->state != ec_fsm_pdo_entry_state_end + && fsm->state != ec_fsm_pdo_entry_state_error; +} + +/*****************************************************************************/ + +/** Executes the current state. + * + * \return false, if state machine has terminated + */ +int ec_fsm_pdo_entry_exec( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + fsm->state(fsm); + return ec_fsm_pdo_entry_running(fsm); +} + +/*****************************************************************************/ + +/** Get execution result. + * + * \return true, if the state machine terminated gracefully + */ +int ec_fsm_pdo_entry_success( + const ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + return fsm->state == ec_fsm_pdo_entry_state_end; +} + +/****************************************************************************** + * Reading state functions. + *****************************************************************************/ + +/** Request reading the number of mapped Pdo entries. + */ +void ec_fsm_pdo_entry_read_state_start( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + ec_sdo_request_address(&fsm->request, fsm->target_pdo->index, 0); + ecrt_sdo_request_read(&fsm->request); + + fsm->state = ec_fsm_pdo_entry_read_state_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately +} + +/*****************************************************************************/ + +/** Read number of mapped Pdo entries. + */ +void ec_fsm_pdo_entry_read_state_count( + ec_fsm_pdo_entry_t *fsm /**< finite state machine */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) + return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_ERR("Failed to read number of mapped Pdo entries.\n"); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + if (fsm->request.data_size != sizeof(uint8_t)) { + EC_ERR("Invalid data size %u at uploading Sdo 0x%04X:%02X.\n", + fsm->request.data_size, fsm->request.index, + fsm->request.subindex); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + fsm->entry_count = EC_READ_U8(fsm->request.data); + + if (fsm->slave->master->debug_level) + EC_DBG("%u Pdo entries mapped.\n", fsm->entry_count); + + // read first Pdo entry + fsm->entry_pos = 1; + ec_fsm_pdo_entry_read_action_next(fsm); +} + +/*****************************************************************************/ + +/** Read next Pdo entry. + */ +void ec_fsm_pdo_entry_read_action_next( + ec_fsm_pdo_entry_t *fsm /**< finite state machine */ + ) +{ + if (fsm->entry_pos <= fsm->entry_count) { + ec_sdo_request_address(&fsm->request, fsm->target_pdo->index, fsm->entry_pos); + ecrt_sdo_request_read(&fsm->request); + fsm->state = ec_fsm_pdo_entry_read_state_entry; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately + return; + } + + // finished reading entries. + fsm->state = ec_fsm_pdo_entry_state_end; +} + +/*****************************************************************************/ + +/** Read Pdo entry information. + */ +void ec_fsm_pdo_entry_read_state_entry( + ec_fsm_pdo_entry_t *fsm /**< finite state machine */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_ERR("Failed to read mapped Pdo entry.\n"); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + if (fsm->request.data_size != sizeof(uint32_t)) { + EC_ERR("Invalid data size %u at uploading Sdo 0x%04X:%02X.\n", + fsm->request.data_size, fsm->request.index, + fsm->request.subindex); + fsm->state = ec_fsm_pdo_entry_state_error; + } else { + uint32_t pdo_entry_info; + ec_pdo_entry_t *pdo_entry; + + pdo_entry_info = EC_READ_U32(fsm->request.data); + + if (!(pdo_entry = (ec_pdo_entry_t *) + kmalloc(sizeof(ec_pdo_entry_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate Pdo entry.\n"); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + ec_pdo_entry_init(pdo_entry); + pdo_entry->index = pdo_entry_info >> 16; + pdo_entry->subindex = (pdo_entry_info >> 8) & 0xFF; + pdo_entry->bit_length = pdo_entry_info & 0xFF; + + if (!pdo_entry->index && !pdo_entry->subindex) { + if (ec_pdo_entry_set_name(pdo_entry, "Gap")) { + ec_pdo_entry_clear(pdo_entry); + kfree(pdo_entry); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + } + + if (fsm->slave->master->debug_level) { + EC_DBG("Pdo entry 0x%04X:%02X, %u bit, \"%s\".\n", + pdo_entry->index, pdo_entry->subindex, + pdo_entry->bit_length, + pdo_entry->name ? pdo_entry->name : "???"); + } + + list_add_tail(&pdo_entry->list, &fsm->target_pdo->entries); + + // next Pdo entry + fsm->entry_pos++; + ec_fsm_pdo_entry_read_action_next(fsm); + } +} + +/****************************************************************************** + * Configuration state functions. + *****************************************************************************/ + +/** Start Pdo mapping. + */ +void ec_fsm_pdo_entry_conf_state_start( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + // Pdo mapping has to be changed. Does the slave support this? + if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE) + || (fsm->slave->sii.has_general + && !fsm->slave->sii.coe_details.enable_pdo_configuration)) { + EC_WARN("Slave %u does not support changing the Pdo mapping!\n", + fsm->slave->ring_position); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + if (ec_sdo_request_alloc(&fsm->request, 4)) { + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + // set mapped Pdo entry count to zero + EC_WRITE_U8(fsm->request.data, 0); + fsm->request.data_size = 1; + ec_sdo_request_address(&fsm->request, fsm->source_pdo->index, 0); + ecrt_sdo_request_write(&fsm->request); + + if (fsm->slave->master->debug_level) + EC_DBG("Setting entry count to zero.\n"); + + fsm->state = ec_fsm_pdo_entry_conf_state_zero_entry_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately +} + +/*****************************************************************************/ + +/** Process next Pdo entry. + */ +ec_pdo_entry_t *ec_fsm_pdo_entry_conf_next_entry( + const ec_fsm_pdo_entry_t *fsm, /**< Pdo mapping state machine. */ + const struct list_head *list /**< current entry list item */ + ) +{ + list = list->next; + if (list == &fsm->source_pdo->entries) + return NULL; // no next entry + return list_entry(list, ec_pdo_entry_t, list); +} + +/*****************************************************************************/ + +/** Set the number of mapped entries to zero. + */ +void ec_fsm_pdo_entry_conf_state_zero_entry_count( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) + return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_WARN("Failed to clear Pdo mapping.\n"); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + // find first entry + if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry( + fsm, &fsm->source_pdo->entries))) { + + if (fsm->slave->master->debug_level) + EC_DBG("No entries to map.\n"); + + fsm->state = ec_fsm_pdo_entry_state_end; // finished + return; + } + + // add first entry + fsm->entry_pos = 1; + ec_fsm_pdo_entry_conf_action_map(fsm); +} + +/*****************************************************************************/ + +/** Starts to add a Pdo entry. + */ +void ec_fsm_pdo_entry_conf_action_map( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + uint32_t value; + + if (fsm->slave->master->debug_level) + EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n", + fsm->entry->index, fsm->entry->subindex, + fsm->entry->bit_length, fsm->entry_pos); + + value = fsm->entry->index << 16 + | fsm->entry->subindex << 8 | fsm->entry->bit_length; + EC_WRITE_U32(fsm->request.data, value); + fsm->request.data_size = 4; + ec_sdo_request_address(&fsm->request, fsm->source_pdo->index, fsm->entry_pos); + ecrt_sdo_request_write(&fsm->request); + + fsm->state = ec_fsm_pdo_entry_conf_state_map_entry; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately +} + +/*****************************************************************************/ + +/** Add a Pdo entry. + */ +void ec_fsm_pdo_entry_conf_state_map_entry( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_WARN("Failed to map Pdo entry 0x%04X:%02X (%u bit) to " + "position %u.\n", fsm->entry->index, fsm->entry->subindex, + fsm->entry->bit_length, fsm->entry_pos); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + // find next entry + if (!(fsm->entry = ec_fsm_pdo_entry_conf_next_entry( + fsm, &fsm->entry->list))) { + + // No more entries to add. Write entry count. + EC_WRITE_U8(fsm->request.data, fsm->entry_pos); + fsm->request.data_size = 1; + ec_sdo_request_address(&fsm->request, fsm->source_pdo->index, 0); + ecrt_sdo_request_write(&fsm->request); + + if (fsm->slave->master->debug_level) + EC_DBG("Setting number of Pdo entries to %u.\n", fsm->entry_pos); + + fsm->state = ec_fsm_pdo_entry_conf_state_set_entry_count; + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately + return; + } + + // add next entry + fsm->entry_pos++; + ec_fsm_pdo_entry_conf_action_map(fsm); +} + +/*****************************************************************************/ + +/** Set the number of entries. + */ +void ec_fsm_pdo_entry_conf_state_set_entry_count( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { + EC_ERR("Failed to set number of entries.\n"); + fsm->state = ec_fsm_pdo_entry_state_error; + return; + } + + if (fsm->slave->master->debug_level) + EC_DBG("Successfully configured mapping for Pdo 0x%04X.\n", + fsm->source_pdo->index); + + fsm->state = ec_fsm_pdo_entry_state_end; // finished +} + +/****************************************************************************** + * Common state functions + *****************************************************************************/ + +/** State: ERROR. + */ +void ec_fsm_pdo_entry_state_error( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ +} + +/*****************************************************************************/ + +/** State: END. + */ +void ec_fsm_pdo_entry_state_end( + ec_fsm_pdo_entry_t *fsm /**< Pdo mapping state machine. */ + ) +{ +} + +/*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_entry.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/fsm_pdo_entry.h Thu Jul 31 16:13:29 2008 +0000 @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * The right to use EtherCAT Technology is granted and comes free of + * charge under condition of compatibility of product made by + * Licensee. People intending to distribute/sell products based on the + * code, have to sign an agreement to guarantee that products using + * software based on IgH EtherCAT master stay compatible with the actual + * EtherCAT specification (which are released themselves as an open + * standard) as the (only) precondition to have the right to use EtherCAT + * Technology, IP and trade marks. + * + *****************************************************************************/ + +/** \file + * EtherCAT Pdo entry configuration state machine structures. + */ + +/*****************************************************************************/ + +#ifndef __EC_FSM_PDO_ENTRY_H__ +#define __EC_FSM_PDO_ENTRY_H__ + +#include "globals.h" +#include "../include/ecrt.h" +#include "datagram.h" +#include "fsm_coe.h" + +/*****************************************************************************/ + +/** + * \see ec_fsm_pdo_entry + */ +typedef struct ec_fsm_pdo_entry ec_fsm_pdo_entry_t; + +/** Pdo configuration state machine. + */ +struct ec_fsm_pdo_entry +{ + void (*state)(ec_fsm_pdo_entry_t *); /**< state function */ + ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */ + ec_sdo_request_t request; /**< Sdo request. */ + + ec_slave_t *slave; /**< Slave the FSM runs on. */ + ec_pdo_t *target_pdo; /**< Pdo to read the mapping for. */ + const ec_pdo_t *source_pdo; /**< Pdo with desired mapping. */ + const ec_pdo_entry_t *entry; /**< Current entry. */ + unsigned int entry_count; /**< Number of entries. */ + unsigned int entry_pos; /**< Position in Pdo mapping. */ +}; + +/*****************************************************************************/ + +void ec_fsm_pdo_entry_init(ec_fsm_pdo_entry_t *, ec_fsm_coe_t *); +void ec_fsm_pdo_entry_clear(ec_fsm_pdo_entry_t *); + +void ec_fsm_pdo_entry_start_reading(ec_fsm_pdo_entry_t *, ec_slave_t *, + ec_pdo_t *); +void ec_fsm_pdo_entry_start_configuration(ec_fsm_pdo_entry_t *, ec_slave_t *, + const ec_pdo_t *); + +int ec_fsm_pdo_entry_exec(ec_fsm_pdo_entry_t *); +int ec_fsm_pdo_entry_success(const ec_fsm_pdo_entry_t *); + +/*****************************************************************************/ + +#endif diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_mapping.c --- a/master/fsm_pdo_mapping.c Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,383 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** \file - * EtherCAT Pdo mapping state machine. - */ - -/*****************************************************************************/ - -#include "globals.h" -#include "master.h" -#include "mailbox.h" -#include "slave_config.h" - -#include "fsm_pdo_mapping.h" - -/*****************************************************************************/ - -void ec_fsm_pdo_mapping_state_start(ec_fsm_pdo_mapping_t *); -void ec_fsm_pdo_mapping_state_zero_count(ec_fsm_pdo_mapping_t *); -void ec_fsm_pdo_mapping_state_add_entry(ec_fsm_pdo_mapping_t *); -void ec_fsm_pdo_mapping_state_entry_count(ec_fsm_pdo_mapping_t *); -void ec_fsm_pdo_mapping_state_end(ec_fsm_pdo_mapping_t *); -void ec_fsm_pdo_mapping_state_error(ec_fsm_pdo_mapping_t *); - -void ec_fsm_pdo_mapping_next_pdo(ec_fsm_pdo_mapping_t *); - -/*****************************************************************************/ - -/** Constructor. - */ -void ec_fsm_pdo_mapping_init( - ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */ - ec_fsm_coe_t *fsm_coe /**< CoE state machine to use. */ - ) -{ - fsm->fsm_coe = fsm_coe; - ec_sdo_request_init(&fsm->request); -} - -/*****************************************************************************/ - -/** Destructor. - */ -void ec_fsm_pdo_mapping_clear( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - ec_sdo_request_clear(&fsm->request); -} - -/*****************************************************************************/ - -/** Start Pdo mapping state machine. - */ -void ec_fsm_pdo_mapping_start( - ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */ - ec_slave_t *slave /**< slave to configure */ - ) -{ - fsm->slave = slave; - fsm->state = ec_fsm_pdo_mapping_state_start; -} - -/*****************************************************************************/ - -/** Get running state. - * - * \return false, if state machine has terminated - */ -int ec_fsm_pdo_mapping_running( - const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - return fsm->state != ec_fsm_pdo_mapping_state_end - && fsm->state != ec_fsm_pdo_mapping_state_error; -} - -/*****************************************************************************/ - -/** Executes the current state. - * - * \return false, if state machine has terminated - */ -int ec_fsm_pdo_mapping_exec( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - fsm->state(fsm); - return ec_fsm_pdo_mapping_running(fsm); -} - -/*****************************************************************************/ - -/** Get execution result. - * - * \return true, if the state machine terminated gracefully - */ -int ec_fsm_pdo_mapping_success( - const ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - return fsm->state == ec_fsm_pdo_mapping_state_end; -} - -/****************************************************************************** - * State functions. - *****************************************************************************/ - -/** Start Pdo mapping. - */ -void ec_fsm_pdo_mapping_state_start( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - if (!fsm->slave->config) { - fsm->state = ec_fsm_pdo_mapping_state_end; - return; - } - - fsm->pdo = NULL; - fsm->num_configured_pdos = 0; - ec_fsm_pdo_mapping_next_pdo(fsm); -} - -/*****************************************************************************/ - -/** Process mapping of next Pdo. - */ -void ec_fsm_pdo_mapping_next_pdo( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - uint8_t sync_index; - const ec_pdo_list_t *pdos; - const ec_pdo_t *pdo, *assigned_pdo; - - for (sync_index = 0; sync_index < EC_MAX_SYNC_MANAGERS; sync_index++) { - pdos = &fsm->slave->config->sync_configs[sync_index].pdos; - - list_for_each_entry(pdo, &pdos->list, list) { - if (fsm->pdo) { // there was a Pdo mapping changed in the last run - if (pdo == fsm->pdo) // this is the previously configured Pdo - fsm->pdo = NULL; // take the next one - } else { - if ((assigned_pdo = ec_slave_find_pdo(fsm->slave, pdo->index))) - if (ec_pdo_equal_entries(pdo, assigned_pdo)) - continue; // Pdo entries mapped correctly - - fsm->pdo = pdo; - fsm->num_configured_pdos++; - break; - } - } - } - - if (!fsm->pdo) { - if (fsm->slave->master->debug_level && !fsm->num_configured_pdos) - EC_DBG("Pdo mappings are already configured correctly.\n"); - fsm->state = ec_fsm_pdo_mapping_state_end; - return; - } - - // Pdo mapping has to be changed. Does the slave support this? - if (!(fsm->slave->sii.mailbox_protocols & EC_MBOX_COE) - || (fsm->slave->sii.has_general - && !fsm->slave->sii.coe_details.enable_pdo_configuration)) { - EC_WARN("Slave %u does not support Pdo mapping configuration!\n", - fsm->slave->ring_position); - fsm->state = ec_fsm_pdo_mapping_state_error; - return; - } - - if (fsm->slave->master->debug_level) { - EC_DBG("Changing mapping of Pdo 0x%04X.\n", fsm->pdo->index); - } - - if (ec_sdo_request_alloc(&fsm->request, 4)) { - fsm->state = ec_fsm_pdo_mapping_state_error; - return; - } - - // set mapped Pdo count to zero - EC_WRITE_U8(fsm->request.data, 0); - fsm->request.data_size = 1; - ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0); - ecrt_sdo_request_write(&fsm->request); - if (fsm->slave->master->debug_level) - EC_DBG("Setting entry count to zero.\n"); - - fsm->state = ec_fsm_pdo_mapping_state_zero_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately -} - -/*****************************************************************************/ - -/** Process next Pdo entry. - */ -ec_pdo_entry_t *ec_fsm_pdo_mapping_next_entry( - const ec_fsm_pdo_mapping_t *fsm, /**< Pdo mapping state machine. */ - const struct list_head *list /**< current entry list item */ - ) -{ - list = list->next; - if (list == &fsm->pdo->entries) - return NULL; // no next entry - return list_entry(list, ec_pdo_entry_t, list); -} - -/*****************************************************************************/ - -/** Starts to add a Pdo entry. - */ -void ec_fsm_pdo_mapping_add_entry( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - uint32_t value; - - if (fsm->slave->master->debug_level) - EC_DBG("Mapping Pdo entry 0x%04X:%02X (%u bit) at position %u.\n", - fsm->entry->index, fsm->entry->subindex, - fsm->entry->bit_length, fsm->entry_count); - - value = fsm->entry->index << 16 - | fsm->entry->subindex << 8 | fsm->entry->bit_length; - EC_WRITE_U32(fsm->request.data, value); - fsm->request.data_size = 4; - ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->entry_count); - ecrt_sdo_request_write(&fsm->request); - - fsm->state = ec_fsm_pdo_mapping_state_add_entry; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately -} - -/*****************************************************************************/ - -/** Set the number of mapped entries to zero. - */ -void ec_fsm_pdo_mapping_state_zero_count( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to clear mapping of Pdo 0x%04X.\n", fsm->pdo->index); - fsm->state = ec_fsm_pdo_mapping_state_error; - return; - } - - // find first entry - if (!(fsm->entry = - ec_fsm_pdo_mapping_next_entry(fsm, &fsm->pdo->entries))) { - if (fsm->slave->master->debug_level) - EC_DBG("No entries to map.\n"); - ec_fsm_pdo_mapping_next_pdo(fsm); - return; - } - - // add first entry - fsm->entry_count = 1; - ec_fsm_pdo_mapping_add_entry(fsm); -} - -/*****************************************************************************/ - -/** Add a Pdo entry. - */ -void ec_fsm_pdo_mapping_state_add_entry( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to map Pdo entry 0x%04X:%02X at 0x%04X:%02X.\n", - fsm->entry->index, fsm->entry->subindex, fsm->pdo->index, - fsm->entry_count); - fsm->state = ec_fsm_pdo_mapping_state_error; - return; - } - - // find next entry - if (!(fsm->entry = ec_fsm_pdo_mapping_next_entry(fsm, &fsm->entry->list))) { - // No more entries to add. Write entry count. - EC_WRITE_U8(fsm->request.data, fsm->entry_count); - fsm->request.data_size = 1; - ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0); - ecrt_sdo_request_write(&fsm->request); - - if (fsm->slave->master->debug_level) - EC_DBG("Setting number of Pdo entries to %u.\n", fsm->entry_count); - - fsm->state = ec_fsm_pdo_mapping_state_entry_count; - ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, &fsm->request); - ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately - return; - } - - // add next entry - fsm->entry_count++; - ec_fsm_pdo_mapping_add_entry(fsm); -} - -/*****************************************************************************/ - -/** Set the number of entries. - */ -void ec_fsm_pdo_mapping_state_entry_count( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ - if (ec_fsm_coe_exec(fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(fsm->fsm_coe)) { - EC_WARN("Failed to set number of entries for Pdo 0x%04X.\n", - fsm->pdo->index); - fsm->state = ec_fsm_pdo_mapping_state_error; - return; - } - - if (fsm->slave->master->debug_level) - EC_DBG("Pdo mapping configuration successful.\n"); - - ec_fsm_pdo_mapping_next_pdo(fsm); -} - -/****************************************************************************** - * Common state functions - *****************************************************************************/ - -/** State: ERROR. - */ -void ec_fsm_pdo_mapping_state_error( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ -} - -/*****************************************************************************/ - -/** State: END. - */ -void ec_fsm_pdo_mapping_state_end( - ec_fsm_pdo_mapping_t *fsm /**< Pdo mapping state machine. */ - ) -{ -} - -/*****************************************************************************/ diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_pdo_mapping.h --- a/master/fsm_pdo_mapping.h Thu Jul 31 09:30:38 2008 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,82 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The right to use EtherCAT Technology is granted and comes free of - * charge under condition of compatibility of product made by - * Licensee. People intending to distribute/sell products based on the - * code, have to sign an agreement to guarantee that products using - * software based on IgH EtherCAT master stay compatible with the actual - * EtherCAT specification (which are released themselves as an open - * standard) as the (only) precondition to have the right to use EtherCAT - * Technology, IP and trade marks. - * - *****************************************************************************/ - -/** \file - * EtherCAT Pdo configuration state machine structures. - */ - -/*****************************************************************************/ - -#ifndef __EC_FSM_PDO_MAPPING_H__ -#define __EC_FSM_PDO_MAPPING_H__ - -#include "globals.h" -#include "../include/ecrt.h" -#include "datagram.h" -#include "fsm_coe.h" - -/*****************************************************************************/ - -/** - * \see ec_fsm_pdo_mapping - */ -typedef struct ec_fsm_pdo_mapping ec_fsm_pdo_mapping_t; - -/** Pdo configuration state machine. - */ -struct ec_fsm_pdo_mapping -{ - void (*state)(ec_fsm_pdo_mapping_t *); /**< state function */ - ec_fsm_coe_t *fsm_coe; /**< CoE state machine to use */ - ec_slave_t *slave; /**< Slave the FSM runs on. */ - - const ec_pdo_t *pdo; /**< Current Pdo to configure. */ - unsigned int num_configured_pdos; /**< Number of configured Pdos. */ - const ec_pdo_entry_t *entry; /**< Current entry. */ - - ec_sdo_request_t request; /**< Sdo request. */ - unsigned int entry_count; /**< Number of configured entries. */ -}; - -/*****************************************************************************/ - -void ec_fsm_pdo_mapping_init(ec_fsm_pdo_mapping_t *, ec_fsm_coe_t *); -void ec_fsm_pdo_mapping_clear(ec_fsm_pdo_mapping_t *); - -void ec_fsm_pdo_mapping_start(ec_fsm_pdo_mapping_t *, ec_slave_t *); -int ec_fsm_pdo_mapping_exec(ec_fsm_pdo_mapping_t *); -int ec_fsm_pdo_mapping_success(const ec_fsm_pdo_mapping_t *); - -/*****************************************************************************/ - -#endif diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_slave_config.c --- a/master/fsm_slave_config.c Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_slave_config.c Thu Jul 31 16:13:29 2008 +0000 @@ -53,8 +53,7 @@ void ec_fsm_slave_config_state_preop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_state_pdo_assign(ec_fsm_slave_config_t *); -void ec_fsm_slave_config_state_pdo_mapping(ec_fsm_slave_config_t *); +void ec_fsm_slave_config_state_pdo_conf(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_fmmu(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_safeop(ec_fsm_slave_config_t *); void ec_fsm_slave_config_state_op(ec_fsm_slave_config_t *); @@ -75,16 +74,16 @@ */ void ec_fsm_slave_config_init( ec_fsm_slave_config_t *fsm, /**< slave state machine */ - ec_datagram_t *datagram /**< datagram structure to use */ + ec_datagram_t *datagram, /**< datagram structure to use */ + ec_fsm_change_t *fsm_change, /**< State change state machine to use. */ + ec_fsm_coe_t *fsm_coe, /**< CoE state machine to use. */ + ec_fsm_pdo_t *fsm_pdo /**< Pdo configuration state machine to use. */ ) { fsm->datagram = datagram; - - // init sub state machines - ec_fsm_change_init(&fsm->fsm_change, fsm->datagram); - ec_fsm_coe_init(&fsm->fsm_coe, fsm->datagram); - ec_fsm_pdo_assign_init(&fsm->fsm_pdo_assign, &fsm->fsm_coe); - ec_fsm_pdo_mapping_init(&fsm->fsm_pdo_mapping, &fsm->fsm_coe); + fsm->fsm_change = fsm_change; + fsm->fsm_coe = fsm_coe; + fsm->fsm_pdo = fsm_pdo; } /*****************************************************************************/ @@ -95,11 +94,6 @@ ec_fsm_slave_config_t *fsm /**< slave state machine */ ) { - // clear sub state machines - ec_fsm_change_clear(&fsm->fsm_change); - ec_fsm_coe_clear(&fsm->fsm_coe); - ec_fsm_pdo_assign_clear(&fsm->fsm_pdo_assign); - ec_fsm_pdo_mapping_clear(&fsm->fsm_pdo_mapping); } /*****************************************************************************/ @@ -181,8 +175,8 @@ // force flag fsm->slave->force_config = 0; - ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT); - ec_fsm_change_exec(&fsm->fsm_change); + ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_INIT); + ec_fsm_change_exec(fsm->fsm_change); fsm->state = ec_fsm_slave_config_state_init; } @@ -198,10 +192,10 @@ ec_slave_t *slave = fsm->slave; ec_datagram_t *datagram = fsm->datagram; - if (ec_fsm_change_exec(&fsm->fsm_change)) return; - - if (!ec_fsm_change_success(&fsm->fsm_change)) { - if (!fsm->fsm_change.spontaneous_change) + if (ec_fsm_change_exec(fsm->fsm_change)) return; + + if (!ec_fsm_change_success(fsm->fsm_change)) { + if (!fsm->fsm_change->spontaneous_change) slave->error_flag = 1; fsm->state = ec_fsm_slave_config_state_error; return; @@ -385,8 +379,8 @@ ) { fsm->state = ec_fsm_slave_config_state_preop; - ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP); - ec_fsm_change_exec(&fsm->fsm_change); // execute immediately + ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_PREOP); + ec_fsm_change_exec(fsm->fsm_change); // execute immediately } /*****************************************************************************/ @@ -400,10 +394,10 @@ ec_slave_t *slave = fsm->slave; ec_master_t *master = fsm->slave->master; - if (ec_fsm_change_exec(&fsm->fsm_change)) return; - - if (!ec_fsm_change_success(&fsm->fsm_change)) { - if (!fsm->fsm_change.spontaneous_change) + if (ec_fsm_change_exec(fsm->fsm_change)) return; + + if (!ec_fsm_change_success(fsm->fsm_change)) { + if (!fsm->fsm_change->spontaneous_change) slave->error_flag = 1; fsm->state = ec_fsm_slave_config_state_error; return; @@ -455,8 +449,8 @@ fsm->request = list_entry(fsm->slave->config->sdo_configs.next, ec_sdo_request_t, list); ecrt_sdo_request_write(fsm->request); - ec_fsm_coe_transfer(&fsm->fsm_coe, fsm->slave, fsm->request); - ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately } /*****************************************************************************/ @@ -467,9 +461,9 @@ ec_fsm_slave_config_t *fsm /**< slave state machine */ ) { - if (ec_fsm_coe_exec(&fsm->fsm_coe)) return; - - if (!ec_fsm_coe_success(&fsm->fsm_coe)) { + if (ec_fsm_coe_exec(fsm->fsm_coe)) return; + + if (!ec_fsm_coe_success(fsm->fsm_coe)) { EC_ERR("Sdo configuration failed for slave %u.\n", fsm->slave->ring_position); fsm->slave->error_flag = 1; @@ -482,8 +476,8 @@ fsm->request = list_entry(fsm->request->list.next, ec_sdo_request_t, list); ecrt_sdo_request_write(fsm->request); - ec_fsm_coe_transfer(&fsm->fsm_coe, fsm->slave, fsm->request); - ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately + ec_fsm_coe_transfer(fsm->fsm_coe, fsm->slave, fsm->request); + ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately return; } @@ -571,45 +565,25 @@ return; } - // Start configuring Pdo mapping - ec_fsm_pdo_mapping_start(&fsm->fsm_pdo_mapping, fsm->slave); - fsm->state = ec_fsm_slave_config_state_pdo_mapping; + // Start configuring Pdos + ec_fsm_pdo_start_configuration(fsm->fsm_pdo, fsm->slave); + fsm->state = ec_fsm_slave_config_state_pdo_conf; fsm->state(fsm); // execute immediately } /*****************************************************************************/ -/** Slave configuration state: PDO_MAPPING. - */ -void ec_fsm_slave_config_state_pdo_mapping( - ec_fsm_slave_config_t *fsm /**< slave state machine */ - ) -{ - if (ec_fsm_pdo_mapping_exec(&fsm->fsm_pdo_mapping)) return; - - if (!ec_fsm_pdo_mapping_success(&fsm->fsm_pdo_mapping)) { - EC_WARN("Configuration of Pdo mappings failed on slave %u.\n", - fsm->slave->ring_position); - } - - // start applying Pdo assignments - ec_fsm_pdo_assign_start(&fsm->fsm_pdo_assign, fsm->slave); - fsm->state = ec_fsm_slave_config_state_pdo_assign; - fsm->state(fsm); // execute immediately -} - -/*****************************************************************************/ - -/** Slave configuration state: PDO_ASSIGN. - */ -void ec_fsm_slave_config_state_pdo_assign( - ec_fsm_slave_config_t *fsm /**< slave state machine */ - ) -{ - if (ec_fsm_pdo_assign_exec(&fsm->fsm_pdo_assign)) return; - - if (!ec_fsm_pdo_assign_success(&fsm->fsm_pdo_assign)) { - EC_WARN("Configuration of Pdo assignments failed on slave %u.\n", +/** Slave configuration state: PDO_CONF. + */ +void ec_fsm_slave_config_state_pdo_conf( + ec_fsm_slave_config_t *fsm /**< slave state machine */ + ) +{ + if (ec_fsm_pdo_exec(fsm->fsm_pdo)) + return; + + if (!ec_fsm_pdo_success(fsm->fsm_pdo)) { + EC_WARN("Pdo configuration failed on slave %u.\n", fsm->slave->ring_position); } @@ -708,8 +682,8 @@ ) { fsm->state = ec_fsm_slave_config_state_safeop; - ec_fsm_change_start(&fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAFEOP); - ec_fsm_change_exec(&fsm->fsm_change); // execute immediately + ec_fsm_change_start(fsm->fsm_change, fsm->slave, EC_SLAVE_STATE_SAFEOP); + ec_fsm_change_exec(fsm->fsm_change); // execute immediately } /*****************************************************************************/ @@ -723,10 +697,10 @@ ec_master_t *master = fsm->slave->master; ec_slave_t *slave = fsm->slave; - if (ec_fsm_change_exec(&fsm->fsm_change)) return; - - if (!ec_fsm_change_success(&fsm->fsm_change)) { - if (!fsm->fsm_change.spontaneous_change) + if (ec_fsm_change_exec(fsm->fsm_change)) return; + + if (!ec_fsm_change_success(fsm->fsm_change)) { + if (!fsm->fsm_change->spontaneous_change) fsm->slave->error_flag = 1; fsm->state = ec_fsm_slave_config_state_error; return; @@ -749,8 +723,8 @@ // set state to OP fsm->state = ec_fsm_slave_config_state_op; - ec_fsm_change_start(&fsm->fsm_change, slave, EC_SLAVE_STATE_OP); - ec_fsm_change_exec(&fsm->fsm_change); // execute immediately + ec_fsm_change_start(fsm->fsm_change, slave, EC_SLAVE_STATE_OP); + ec_fsm_change_exec(fsm->fsm_change); // execute immediately } /*****************************************************************************/ @@ -764,10 +738,10 @@ ec_master_t *master = fsm->slave->master; ec_slave_t *slave = fsm->slave; - if (ec_fsm_change_exec(&fsm->fsm_change)) return; - - if (!ec_fsm_change_success(&fsm->fsm_change)) { - if (!fsm->fsm_change.spontaneous_change) + if (ec_fsm_change_exec(fsm->fsm_change)) return; + + if (!ec_fsm_change_success(fsm->fsm_change)) { + if (!fsm->fsm_change->spontaneous_change) slave->error_flag = 1; fsm->state = ec_fsm_slave_config_state_error; return; diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_slave_config.h --- a/master/fsm_slave_config.h Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_slave_config.h Thu Jul 31 16:13:29 2008 +0000 @@ -48,8 +48,7 @@ #include "datagram.h" #include "fsm_change.h" #include "fsm_coe.h" -#include "fsm_pdo_assign.h" -#include "fsm_pdo_mapping.h" +#include "fsm_pdo.h" /*****************************************************************************/ @@ -60,21 +59,21 @@ */ struct ec_fsm_slave_config { + ec_datagram_t *datagram; /**< Datagram used in the state machine. */ + ec_fsm_change_t *fsm_change; /**< State change state machine. */ + ec_fsm_coe_t *fsm_coe; /**< CoE state machine. */ + ec_fsm_pdo_t *fsm_pdo; /**< Pdo configuration state machine. */ + ec_slave_t *slave; /**< Slave the FSM runs on. */ - ec_datagram_t *datagram; /**< Datagram used in the state machine. */ + void (*state)(ec_fsm_slave_config_t *); /**< State function. */ unsigned int retries; /**< Retries on datagram timeout. */ - - void (*state)(ec_fsm_slave_config_t *); /**< State function. */ ec_sdo_request_t *request; /**< Sdo request for Sdo configuration. */ - ec_fsm_change_t fsm_change; /**< State change state machine. */ - ec_fsm_coe_t fsm_coe; /**< CoE state machine. */ - ec_fsm_pdo_assign_t fsm_pdo_assign; /**< Pdo assignment state machine. */ - ec_fsm_pdo_mapping_t fsm_pdo_mapping; /**< Pdo mapping state machine. */ }; /*****************************************************************************/ -void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *); +void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *, + ec_fsm_change_t *, ec_fsm_coe_t *, ec_fsm_pdo_t *); void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *); void ec_fsm_slave_config_start(ec_fsm_slave_config_t *, ec_slave_t *); diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_slave_scan.c --- a/master/fsm_slave_scan.c Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_slave_scan.c Thu Jul 31 16:13:29 2008 +0000 @@ -72,13 +72,12 @@ ec_datagram_t *datagram, /**< Datagram to use. */ ec_fsm_slave_config_t *fsm_slave_config, /**< Slave configuration state machine to use. */ - ec_fsm_coe_map_t *fsm_coe_map /**< Pdo mapping state machine to use. - */ + ec_fsm_pdo_t *fsm_pdo /**< Pdo configuration machine to use. */ ) { fsm->datagram = datagram; fsm->fsm_slave_config = fsm_slave_config; - fsm->fsm_coe_map = fsm_coe_map; + fsm->fsm_pdo = fsm_pdo; // init sub state machines ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram); @@ -633,8 +632,8 @@ EC_DBG("Scanning Pdo assignment and mapping of slave %u.\n", slave->ring_position); fsm->state = ec_fsm_slave_scan_state_pdos; - ec_fsm_coe_map_start(fsm->fsm_coe_map, slave); - ec_fsm_coe_map_exec(fsm->fsm_coe_map); // execute immediately + ec_fsm_pdo_start_reading(fsm->fsm_pdo, slave); + ec_fsm_pdo_exec(fsm->fsm_pdo); // execute immediately } /*****************************************************************************/ @@ -645,15 +644,15 @@ ec_fsm_slave_scan_t *fsm /**< slave state machine */ ) { - if (ec_fsm_coe_map_exec(fsm->fsm_coe_map)) - return; - - if (!ec_fsm_coe_map_success(fsm->fsm_coe_map)) { - fsm->state = ec_fsm_slave_scan_state_error; - return; - } - - // fetching of Pdo assignment/mapping finished + if (ec_fsm_pdo_exec(fsm->fsm_pdo)) + return; + + if (!ec_fsm_pdo_success(fsm->fsm_pdo)) { + fsm->state = ec_fsm_slave_scan_state_error; + return; + } + + // reading Pdo configuration finished fsm->state = ec_fsm_slave_scan_state_end; } diff -r 2ec9651a6c89 -r 235f34ca50e2 master/fsm_slave_scan.h --- a/master/fsm_slave_scan.h Thu Jul 31 09:30:38 2008 +0000 +++ b/master/fsm_slave_scan.h Thu Jul 31 16:13:29 2008 +0000 @@ -49,7 +49,7 @@ #include "fsm_sii.h" #include "fsm_change.h" #include "fsm_coe.h" -#include "fsm_coe_map.h" +#include "fsm_pdo.h" /*****************************************************************************/ @@ -64,7 +64,7 @@ ec_datagram_t *datagram; /**< Datagram used in the state machine. */ ec_fsm_slave_config_t *fsm_slave_config; /**< Slave configuration state machine to use. */ - ec_fsm_coe_map_t *fsm_coe_map; /**< Pdo mapping state machine to use. */ + ec_fsm_pdo_t *fsm_pdo; /**< Pdo configuration state machine to use. */ unsigned int retries; /**< Retries on datagram timeout. */ void (*state)(ec_fsm_slave_scan_t *); /**< State function. */ @@ -76,7 +76,7 @@ /*****************************************************************************/ void ec_fsm_slave_scan_init(ec_fsm_slave_scan_t *, ec_datagram_t *, - ec_fsm_slave_config_t *, ec_fsm_coe_map_t *); + ec_fsm_slave_config_t *, ec_fsm_pdo_t *); void ec_fsm_slave_scan_clear(ec_fsm_slave_scan_t *); void ec_fsm_slave_scan_start(ec_fsm_slave_scan_t *, ec_slave_t *);