From e1d91ca3c915e28ecac1cca5cc7b2abd1a86b63f Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Mon, 20 Mar 2006 15:28:25 +0000 Subject: [PATCH] Slave alias implementiert. --- include/ecrt.h | 2 + master/master.c | 115 +++++++++++++++++++++++++++++++++++------------- master/slave.c | 94 ++++++++++++++++++++++++++++++++++++--- master/slave.h | 2 + mini/mini.c | 10 ++++- 5 files changed, 187 insertions(+), 36 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index 499e7105..357f2487 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -69,6 +69,8 @@ int ecrt_master_sdo_read(ec_master_t *master, uint16_t sdo_index, uint8_t sdo_subindex, uint32_t *value); +int ecrt_master_write_slave_alias(ec_master_t *master, + const char *slave_address, uint16_t alias); /*****************************************************************************/ // Domain Methods diff --git a/master/master.c b/master/master.c index 6e294108..69d6da30 100644 --- a/master/master.c +++ b/master/master.c @@ -524,11 +524,13 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */) Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger. Gültige Adress-Strings sind Folgende: - - \a "X" = der X. Slave im Bus, - \a "X:Y" = der Y. Slave hinter dem X. Buskoppler, - - \a "#X" = der Slave mit der SSID X, - - \a "#X:Y" = der Y. Slave hinter dem Buskoppler mit der SSID X. + - \a "#X" = der Slave mit dem Alias X, + - \a "#X:Y" = der Y. Slave hinter dem Buskoppler mit dem Alias X. + + X und Y fangen immer bei 0 an und können auch hexadezimal oder oktal + angegeben werden (mit entsprechendem Prefix). \return Zeiger auf Slave bei Erfolg, sonst NULL */ @@ -541,65 +543,94 @@ ec_slave_t *ec_master_slave_address(const ec_master_t *master, { unsigned long first, second; char *remainder, *remainder2; - unsigned int i; + unsigned int i, alias_requested, alias_slave_index, alias_found; int coupler_idx, slave_idx; ec_slave_t *slave; if (!address || address[0] == 0) return NULL; + alias_requested = 0; + alias_slave_index = 0; if (address[0] == '#') { - EC_ERR("Bus ID \"%s\" - #<SSID> not implemented yet!\n", address); - return NULL; + alias_requested = 1; + address++; } first = simple_strtoul(address, &remainder, 0); if (remainder == address) { - EC_ERR("Bus ID \"%s\" - First number empty!\n", address); + EC_ERR("Slave address \"%s\" - First number empty!\n", address); return NULL; } - if (!remainder[0]) { // absolute position - if (first < master->slave_count) { - return master->slaves + first; + if (alias_requested) { + alias_found = 0; + for (i = 0; i < master->slave_count; i++) { + if (master->slaves[i].sii_alias == first) { + alias_slave_index = i; + alias_found = 1; + break; + } + } + if (!alias_found) { + EC_ERR("Slave address \"%s\" - Alias not found!\n", address); + return NULL; } - - EC_ERR("Bus ID \"%s\" - Absolute position invalid!\n", address); } + if (!remainder[0]) { // absolute position + if (alias_requested) { + return master->slaves + alias_slave_index; + } + else { + if (first < master->slave_count) { + return master->slaves + first; + } + EC_ERR("Slave address \"%s\" - Absolute position invalid!\n", + address); + } + } else if (remainder[0] == ':') { // field position - remainder++; second = simple_strtoul(remainder, &remainder2, 0); if (remainder2 == remainder) { - EC_ERR("Bus ID \"%s\" - Sencond number empty!\n", address); + EC_ERR("Slave address \"%s\" - Second number empty!\n", address); return NULL; } if (remainder2[0]) { - EC_ERR("Bus ID \"%s\" - Invalid trailer (2)!\n", address); + EC_ERR("Slave address \"%s\" - Invalid trailer!\n", address); return NULL; } - coupler_idx = -1; - slave_idx = 0; - for (i = 0; i < master->slave_count; i++, slave_idx++) { - slave = master->slaves + i; - if (!slave->type) continue; - - if (slave->type->bus_coupler) { - coupler_idx++; - slave_idx = 0; + if (alias_requested) { + for (i = alias_slave_index + 1; i < master->slave_count; i++) { + slave = master->slaves + i; + if (!slave->type || slave->type->bus_coupler) break; + if (i - alias_slave_index - 1 == second) return slave; + } + EC_ERR("Slave address \"%s\" - Bus coupler %i has no %lu. slave" + " following!\n", address, + (master->slaves + alias_slave_index)->ring_position, + second); + return NULL; + } + else { + coupler_idx = -1; + slave_idx = 0; + for (i = 0; i < master->slave_count; i++, slave_idx++) { + slave = master->slaves + i; + if (!slave->type) continue; // FIXME + if (slave->type->bus_coupler) { + coupler_idx++; + slave_idx = 0; + } + if (coupler_idx == first && slave_idx == second) return slave; } - - if (coupler_idx == first && slave_idx == second) return slave; } } - else - EC_ERR("Bus ID \"%s\" - Invalid trailer!\n", address); - - // FIXME ??? + EC_ERR("Slave address \"%s\" - Invalid format!\n", address); return NULL; } @@ -1030,6 +1061,29 @@ void ecrt_master_print(const ec_master_t *master /**< EtherCAT-Master */) /*****************************************************************************/ +/** + Schreibt den "Configured station alias". + + \return 0, wenn alles ok, sonst < 0 +*/ + +int ecrt_master_write_slave_alias(ec_master_t *master, + /** EtherCAT-Master */ + const char *slave_address, + /** Slave-Adresse, + siehe ec_master_slave_address() */ + uint16_t alias + /** Neuer Alias */ + ) +{ + ec_slave_t *slave; + if (!(slave = ec_master_slave_address(master, slave_address))) + return -1; + return ec_slave_sii_write(slave, 0x0004, alias); +} + +/*****************************************************************************/ + EXPORT_SYMBOL(ecrt_master_create_domain); EXPORT_SYMBOL(ecrt_master_activate); EXPORT_SYMBOL(ecrt_master_deactivate); @@ -1039,6 +1093,7 @@ EXPORT_SYMBOL(ecrt_master_async_send); EXPORT_SYMBOL(ecrt_master_async_receive); EXPORT_SYMBOL(ecrt_master_debug); EXPORT_SYMBOL(ecrt_master_print); +EXPORT_SYMBOL(ecrt_master_write_slave_alias); /*****************************************************************************/ diff --git a/master/slave.c b/master/slave.c index 69f7f347..a429023c 100644 --- a/master/slave.c +++ b/master/slave.c @@ -34,6 +34,7 @@ void ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */ slave->base_sync_count = 0; slave->ring_position = 0; slave->station_address = 0; + slave->sii_alias = 0; slave->sii_vendor_id = 0; slave->sii_product_code = 0; slave->sii_revision_number = 0; @@ -85,6 +86,12 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */) // Read identification from "Slave Information Interface" (SII) + if (unlikely(ec_slave_sii_read(slave, 0x0004, + (uint32_t *) &slave->sii_alias))) { + EC_ERR("Could not read SII alias!\n"); + return -1; + } + if (unlikely(ec_slave_sii_read(slave, 0x0008, &slave->sii_vendor_id))) { EC_ERR("Could not read SII vendor id!\n"); return -1; @@ -134,10 +141,9 @@ int ec_slave_sii_read(ec_slave_t *slave, // Initiate read operation - EC_WRITE_U8 (data, 0x00); - EC_WRITE_U8 (data + 1, 0x01); - EC_WRITE_U16(data + 2, offset); - EC_WRITE_U16(data + 4, 0x0000); + EC_WRITE_U8 (data, 0x00); // read-only access + EC_WRITE_U8 (data + 1, 0x01); // request read operation + EC_WRITE_U32(data + 2, offset); ec_command_init_npwr(&command, slave->station_address, 0x502, 6, data); if (unlikely(ec_master_simple_io(slave->master, &command))) { @@ -166,7 +172,7 @@ int ec_slave_sii_read(ec_slave_t *slave, end = get_cycles(); if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) { - memcpy(target, command.data + 6, 4); + *target = EC_READ_U32(command.data + 6); return 0; } @@ -179,6 +185,81 @@ int ec_slave_sii_read(ec_slave_t *slave, /*****************************************************************************/ +/** + Schreibt Daten in das Slave-Information-Interface + eines EtherCAT-Slaves. + + \return 0 bei Erfolg, sonst < 0 +*/ + +int ec_slave_sii_write(ec_slave_t *slave, + /**< EtherCAT-Slave */ + uint16_t offset, + /**< Adresse des zu lesenden SII-Registers */ + uint16_t value + /**< Zu schreibender Wert */ + ) +{ + ec_command_t command; + uint8_t data[8]; + cycles_t start, end, timeout; + + EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n", + slave->ring_position, offset, value); + + // Initiate write operation + + EC_WRITE_U8 (data, 0x01); // enable write access + EC_WRITE_U8 (data + 1, 0x02); // request write operation + EC_WRITE_U32(data + 2, offset); + EC_WRITE_U16(data + 6, value); + + ec_command_init_npwr(&command, slave->station_address, 0x502, 8, data); + if (unlikely(ec_master_simple_io(slave->master, &command))) { + EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); + return -1; + } + + // Der Slave legt die Informationen des Slave-Information-Interface + // in das Datenregister und löscht daraufhin ein Busy-Bit. Solange + // den Status auslesen, bis das Bit weg ist. + + start = get_cycles(); + timeout = cpu_khz; // 1ms + + while (1) + { + udelay(10); + + ec_command_init_nprd(&command, slave->station_address, 0x502, 2); + if (unlikely(ec_master_simple_io(slave->master, &command))) { + EC_ERR("Getting SII-write status failed on slave %i!\n", + slave->ring_position); + return -1; + } + + end = get_cycles(); + + if (likely((EC_READ_U8(command.data + 1) & 0x82) == 0)) { + if (EC_READ_U8(command.data + 1) & 0x40) { + EC_ERR("SII-write failed!\n"); + return -1; + } + else { + EC_INFO("SII-write succeeded!\n"); + return 0; + } + } + + if (unlikely((end - start) >= timeout)) { + EC_ERR("SSI-write: Slave %i timed out!\n", slave->ring_position); + return -1; + } + } +} + +/*****************************************************************************/ + /** Bestätigt einen Fehler beim Zustandswechsel. @@ -377,6 +458,8 @@ void ec_slave_print(const ec_slave_t *slave /**< EtherCAT-Slave */) slave->base_fmmu_count, slave->base_sync_count); EC_INFO(" Slave information interface:\n"); + EC_INFO(" Configured station alias: 0x%04X (%i)\n", slave->sii_alias, + slave->sii_alias); EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", slave->sii_vendor_id, slave->sii_product_code); EC_INFO(" Revision number: 0x%08X, Serial number: 0x%08X\n", @@ -429,3 +512,4 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */) ;;; c-basic-offset:4 *** ;;; End: *** */ + diff --git a/master/slave.h b/master/slave.h index 0dfb1783..edaaa3af 100644 --- a/master/slave.h +++ b/master/slave.h @@ -71,6 +71,7 @@ struct ec_slave uint16_t base_sync_count; /**< Anzahl unterstützter Sync-Manager */ // Slave information interface + uint16_t sii_alias; /**< Configured station alias */ uint32_t sii_vendor_id; /**< Identifikationsnummer des Herstellers */ uint32_t sii_product_code; /**< Herstellerspezifischer Produktcode */ uint32_t sii_revision_number; /**< Revisionsnummer */ @@ -94,6 +95,7 @@ void ec_slave_clear(ec_slave_t *); // Slave control int ec_slave_fetch(ec_slave_t *); int ec_slave_sii_read(ec_slave_t *, uint16_t, uint32_t *); +int ec_slave_sii_write(ec_slave_t *, uint16_t, uint16_t); int ec_slave_state_change(ec_slave_t *, uint8_t); int ec_slave_set_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sync_t *); diff --git a/mini/mini.c b/mini/mini.c index 8132a1b5..26327510 100644 --- a/mini/mini.c +++ b/mini/mini.c @@ -45,7 +45,7 @@ ec_field_init_t domain1_fields[] = { {NULL, "6", "Beckhoff", "EL1014", "InputValue", 0}, {NULL, "7", "Beckhoff", "EL2004", "OutputValue", 0}, {NULL, "8", "Beckhoff", "EL4132", "OutputValue", 0}, - {NULL, "9", "Beckhoff", "EL4132", "OutputValue", 0}, + {NULL, "#48879:8", "Beckhoff", "EL4132", "OutputValue", 0}, {} }; @@ -144,6 +144,14 @@ int __init init_mini_module(void) //ecrt_master_debug(master, 0); +#if 0 + printk(KERN_INFO "Writing alias...\n"); + if (ecrt_master_write_slave_alias(master, "0", 0xBEEF)) { + printk(KERN_ERR "EtherCAT: Failed to write alias!\n"); + goto out_deactivate; + } +#endif + #ifdef ASYNC // Einmal senden und warten... ecrt_master_prepare_async_io(master); -- GitLab