# HG changeset patch # User Florian Pose # Date 1142868505 0 # Node ID e4b4b5a85e75ed7b0a4e82a7e0ea5c389684e2dc # Parent a3dbd6bc8fce3c52f1956fee027c912bc8439530 Slave alias implementiert. diff -r a3dbd6bc8fce -r e4b4b5a85e75 include/ecrt.h --- a/include/ecrt.h Mon Mar 20 13:36:10 2006 +0000 +++ b/include/ecrt.h Mon Mar 20 15:28:25 2006 +0000 @@ -69,6 +69,8 @@ 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 -r a3dbd6bc8fce -r e4b4b5a85e75 master/master.c --- a/master/master.c Mon Mar 20 13:36:10 2006 +0000 +++ b/master/master.c Mon Mar 20 15:28:25 2006 +0000 @@ -524,11 +524,13 @@ 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 @@ { 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\" - # 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 (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; + } + } + if (!remainder[0]) { // absolute position - if (first < master->slave_count) { - return master->slaves + first; - } - - EC_ERR("Bus ID \"%s\" - Absolute position invalid!\n", address); - } - + 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; } - - if (coupler_idx == first && slave_idx == 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; + } + } + } 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 @@ /*****************************************************************************/ +/** + 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_receive); EXPORT_SYMBOL(ecrt_master_debug); EXPORT_SYMBOL(ecrt_master_print); +EXPORT_SYMBOL(ecrt_master_write_slave_alias); /*****************************************************************************/ diff -r a3dbd6bc8fce -r e4b4b5a85e75 master/slave.c --- a/master/slave.c Mon Mar 20 13:36:10 2006 +0000 +++ b/master/slave.c Mon Mar 20 15:28:25 2006 +0000 @@ -34,6 +34,7 @@ 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 @@ // 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 @@ // 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 @@ 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; } @@ -180,6 +186,81 @@ /*****************************************************************************/ /** + 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. \todo Funktioniert noch nicht... @@ -377,6 +458,8 @@ 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 @@ ;;; c-basic-offset:4 *** ;;; End: *** */ + diff -r a3dbd6bc8fce -r e4b4b5a85e75 master/slave.h --- a/master/slave.h Mon Mar 20 13:36:10 2006 +0000 +++ b/master/slave.h Mon Mar 20 15:28:25 2006 +0000 @@ -71,6 +71,7 @@ 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 @@ // 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 -r a3dbd6bc8fce -r e4b4b5a85e75 mini/mini.c --- a/mini/mini.c Mon Mar 20 13:36:10 2006 +0000 +++ b/mini/mini.c Mon Mar 20 15:28:25 2006 +0000 @@ -45,7 +45,7 @@ {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 @@ //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);