# HG changeset patch # User Florian Pose # Date 1144058614 0 # Node ID fdc24bf62f80b98db015dc8971734a4c35bbe68d # Parent f6c4f38b699f9194ffab4f9c2487a2f02a2d9aec Dynamischer Kommandospeicher, Domain-Kommandos als Liste. diff -r f6c4f38b699f -r fdc24bf62f80 include/ecrt.h --- a/include/ecrt.h Sun Apr 02 09:26:56 2006 +0000 +++ b/include/ecrt.h Mon Apr 03 10:03:34 2006 +0000 @@ -61,6 +61,8 @@ void ecrt_master_async_receive(ec_master_t *master); void ecrt_master_prepare_async_io(ec_master_t *master); +void ecrt_master_run(ec_master_t *master); + void ecrt_master_debug(ec_master_t *master, int level); void ecrt_master_print(const ec_master_t *master, unsigned int verbosity); diff -r f6c4f38b699f -r fdc24bf62f80 master/canopen.c --- a/master/canopen.c Sun Apr 02 09:26:56 2006 +0000 +++ b/master/canopen.c Mon Apr 03 10:03:34 2006 +0000 @@ -48,19 +48,21 @@ uint8_t *target /**< Speicher für 4 Bytes */ ) { - uint8_t data[0x20]; size_t rec_size; - + uint8_t *data; + + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1; EC_WRITE_U16(data, 0x2 << 12); // SDO request EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer | 0x2 << 5)); // initiate upload request EC_WRITE_U16(data + 3, sdo_index); EC_WRITE_U8 (data + 5, sdo_subindex); - - if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; - - rec_size = 0x20; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position); + return -1; + } + + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1; if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request @@ -97,7 +99,7 @@ size_t size ) { - uint8_t data[0x0A]; + uint8_t *data; size_t rec_size; if (size == 0 || size > 4) { @@ -105,6 +107,7 @@ return -1; } + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 0x0A))) return -1; EC_WRITE_U16(data, 0x2 << 12); // SDO request EC_WRITE_U8 (data + 2, (0x1 // size specified | 0x1 << 1 // expedited transfer @@ -112,15 +115,14 @@ | 0x1 << 5)); // initiate download request EC_WRITE_U16(data + 3, sdo_index); EC_WRITE_U8 (data + 5, sdo_subindex); - memcpy(data + 6, sdo_data, size); if (size < 4) memset(data + 6 + size, 0x00, 4 - size); - - // Mailox senden und empfangen - if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1; - - rec_size = 0x0A; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position); + return -1; + } + + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1; if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request @@ -158,19 +160,21 @@ size_t *size /**< Größe des Speichers */ ) { - uint8_t data[0x20]; + uint8_t *data; size_t rec_size, data_size; uint32_t complete_size; + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1; EC_WRITE_U16(data, 0x2 << 12); // SDO request EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request EC_WRITE_U16(data + 3, sdo_index); EC_WRITE_U8 (data + 5, sdo_subindex); - - if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1; - - rec_size = 0x20; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position); + return -1; + } + + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1; if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request @@ -222,23 +226,26 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */) { - uint8_t data[0xF0]; + uint8_t *data; size_t rec_size; unsigned int i, sdo_count; ec_sdo_t *sdo; uint16_t sdo_index; + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 8))) return -1; EC_WRITE_U16(data, 0x8 << 12); // SDO information EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request EC_WRITE_U8 (data + 3, 0x00); EC_WRITE_U16(data + 4, 0x0000); EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs! - - if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position); + return -1; + } do { - rec_size = 0xF0; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1; + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) + return -1; if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // Error response @@ -290,21 +297,24 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */) { - uint8_t data[0xF0]; + uint8_t *data; size_t rec_size, name_size; ec_sdo_t *sdo; list_for_each_entry(sdo, &slave->sdo_dictionary, list) { + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 8))) return -1; EC_WRITE_U16(data, 0x8 << 12); // SDO information EC_WRITE_U8 (data + 2, 0x03); // Get object description request EC_WRITE_U8 (data + 3, 0x00); EC_WRITE_U16(data + 4, 0x0000); EC_WRITE_U16(data + 6, sdo->index); // SDO index - - if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1; - - rec_size = 0xF0; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", + slave->ring_position); + return -1; + } + + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1; if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information @@ -370,12 +380,14 @@ uint8_t subindices /**< Anzahl Subindizes */ ) { - uint8_t data[0xF0]; + uint8_t *data; size_t rec_size, data_size; uint8_t i; ec_sdo_entry_t *entry; for (i = 1; i <= subindices; i++) { + if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 10))) + return -1; EC_WRITE_U16(data, 0x8 << 12); // SDO information EC_WRITE_U8 (data + 2, 0x05); // Get entry description request EC_WRITE_U8 (data + 3, 0x00); @@ -383,11 +395,13 @@ EC_WRITE_U16(data + 6, sdo->index); // SDO index EC_WRITE_U8 (data + 8, i); // SDO subindex EC_WRITE_U8 (data + 9, 0x00); // value info (no values) - - if (ec_slave_mailbox_send(slave, 0x03, data, 10)) return -1; - - rec_size = 0xF0; - if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) + if (unlikely(ec_master_simple_io(slave->master))) { + EC_ERR("Mailbox sending failed on slave %i!\n", + slave->ring_position); + return -1; + } + + if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1; if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information diff -r f6c4f38b699f -r fdc24bf62f80 master/command.c --- a/master/command.c Sun Apr 02 09:26:56 2006 +0000 +++ b/master/command.c Mon Apr 03 10:03:34 2006 +0000 @@ -17,17 +17,70 @@ /*****************************************************************************/ #define EC_FUNC_HEADER \ + if (unlikely(ec_command_prealloc(command, data_size))) \ + return -1; \ command->index = 0; \ command->working_counter = 0; \ command->state = EC_CMD_INIT; -#define EC_FUNC_WRITE_FOOTER \ +#define EC_FUNC_FOOTER \ command->data_size = data_size; \ - memcpy(command->data, data, data_size); - -#define EC_FUNC_READ_FOOTER \ - command->data_size = data_size; \ - memset(command->data, 0x00, data_size); + memset(command->data, 0x00, data_size); \ + return 0; + +/*****************************************************************************/ + +/** + EtherCAT-Kommando-Konstruktor. +*/ + +void ec_command_init(ec_command_t *command) +{ + command->type = EC_CMD_NONE; + command->address.logical = 0x00000000; + command->data = NULL; + command->mem_size = 0; + command->data_size = 0; + command->index = 0x00; + command->working_counter = 0x00; + command->state = EC_CMD_INIT; +} + +/*****************************************************************************/ + +/** + EtherCAT-Kommando-Destruktor. +*/ + +void ec_command_clear(ec_command_t *command) +{ + if (command->data) kfree(command->data); +} + +/*****************************************************************************/ + +/** + Alloziert Speicher. +*/ + +int ec_command_prealloc(ec_command_t *command, size_t size) +{ + if (size <= command->mem_size) return 0; + + if (command->data) { + kfree(command->data); + command->data = NULL; + command->mem_size = 0; + } + + if (!(command->data = kmalloc(size, GFP_KERNEL))) { + EC_ERR("Failed to allocate %i bytes of command memory!\n", size); + return -1; + } + + command->mem_size = size; + return 0; +} /*****************************************************************************/ @@ -37,26 +90,24 @@ Node-adressed physical read. */ -void ec_command_init_nprd(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t node_address, - /**< Adresse des Knotens (Slaves) */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size - /**< Länge der zu lesenden Daten */ - ) +int ec_command_nprd(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t node_address, + /**< Adresse des Knotens (Slaves) */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu lesenden Daten */ + ) { if (unlikely(node_address == 0x0000)) EC_WARN("Using node address 0x0000!\n"); EC_FUNC_HEADER; - command->type = EC_CMD_NPRD; command->address.physical.slave = node_address; command->address.physical.mem = offset; - - EC_FUNC_READ_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -67,28 +118,24 @@ Node-adressed physical write. */ -void ec_command_init_npwr(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t node_address, - /**< Adresse des Knotens (Slaves) */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size, - /**< Länge der zu schreibenden Daten */ - const uint8_t *data - /**< Zeiger auf Speicher mit zu schreibenden Daten */ - ) +int ec_command_npwr(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t node_address, + /**< Adresse des Knotens (Slaves) */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu schreibenden Daten */ + ) { if (unlikely(node_address == 0x0000)) EC_WARN("Using node address 0x0000!\n"); EC_FUNC_HEADER; - command->type = EC_CMD_NPWR; command->address.physical.slave = node_address; command->address.physical.mem = offset; - - EC_FUNC_WRITE_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -99,23 +146,21 @@ Autoincrement physical read. */ -void ec_command_init_aprd(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t ring_position, - /**< Position des Slaves im Bus */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size - /**< Länge der zu lesenden Daten */ - ) -{ - EC_FUNC_HEADER; - +int ec_command_aprd(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t ring_position, + /**< Position des Slaves im Bus */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu lesenden Daten */ + ) +{ + EC_FUNC_HEADER; command->type = EC_CMD_APRD; command->address.physical.slave = (int16_t) ring_position * (-1); command->address.physical.mem = offset; - - EC_FUNC_READ_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -126,25 +171,21 @@ Autoincrement physical write. */ -void ec_command_init_apwr(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t ring_position, - /**< Position des Slaves im Bus */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size, - /**< Länge der zu schreibenden Daten */ - const uint8_t *data - /**< Zeiger auf Speicher mit zu schreibenden Daten */ - ) -{ - EC_FUNC_HEADER; - +int ec_command_apwr(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t ring_position, + /**< Position des Slaves im Bus */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu schreibenden Daten */ + ) +{ + EC_FUNC_HEADER; command->type = EC_CMD_APWR; command->address.physical.slave = (int16_t) ring_position * (-1); command->address.physical.mem = offset; - - EC_FUNC_WRITE_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -155,21 +196,19 @@ Broadcast read. */ -void ec_command_init_brd(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size - /**< Länge der zu lesenden Daten */ - ) -{ - EC_FUNC_HEADER; - +int ec_command_brd(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu lesenden Daten */ + ) +{ + EC_FUNC_HEADER; command->type = EC_CMD_BRD; command->address.physical.slave = 0x0000; command->address.physical.mem = offset; - - EC_FUNC_READ_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -180,23 +219,19 @@ Broadcast write. */ -void ec_command_init_bwr(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint16_t offset, - /**< Physikalische Speicheradresse im Slave */ - size_t data_size, - /**< Länge der zu schreibenden Daten */ - const uint8_t *data - /**< Zeiger auf Speicher mit zu schreibenden Daten */ - ) -{ - EC_FUNC_HEADER; - +int ec_command_bwr(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint16_t offset, + /**< Physikalische Speicheradresse im Slave */ + size_t data_size + /**< Länge der zu schreibenden Daten */ + ) +{ + EC_FUNC_HEADER; command->type = EC_CMD_BWR; command->address.physical.slave = 0x0000; command->address.physical.mem = offset; - - EC_FUNC_WRITE_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ @@ -207,22 +242,18 @@ Logical read write. */ -void ec_command_init_lrw(ec_command_t *command, - /**< EtherCAT-Rahmen */ - uint32_t offset, - /**< Logische Startadresse */ - size_t data_size, - /**< Länge der zu lesenden/schreibenden Daten */ - uint8_t *data - /**< Zeiger auf die Daten */ - ) -{ - EC_FUNC_HEADER; - +int ec_command_lrw(ec_command_t *command, + /**< EtherCAT-Rahmen */ + uint32_t offset, + /**< Logische Startadresse */ + size_t data_size + /**< Länge der zu lesenden/schreibenden Daten */ + ) +{ + EC_FUNC_HEADER; command->type = EC_CMD_LRW; command->address.logical = offset; - - EC_FUNC_WRITE_FOOTER; + EC_FUNC_FOOTER; } /*****************************************************************************/ diff -r f6c4f38b699f -r fdc24bf62f80 master/command.h --- a/master/command.h Sun Apr 02 09:26:56 2006 +0000 +++ b/master/command.h Mon Apr 03 10:03:34 2006 +0000 @@ -84,10 +84,12 @@ typedef struct { - struct list_head list; /**< Nötig für Liste */ + struct list_head list; /**< Kommando-Listeneintrag */ + struct list_head queue; /**< Master-Kommando-Queue */ ec_command_type_t type; /**< Typ des Kommandos (APRD, NPWR, etc) */ ec_address_t address; /**< Adresse des/der Empfänger */ - uint8_t data[EC_MAX_DATA_SIZE]; /**< Kommandodaten */ + uint8_t *data; /**< Kommandodaten */ + size_t mem_size; /**< Größe des Speichers */ size_t data_size; /**< Länge der zu sendenden und/oder empfangenen Daten */ uint8_t index; /**< Kommando-Index, wird vom Master beim Senden gesetzt. */ uint16_t working_counter; /**< Working-Counter */ @@ -97,15 +99,16 @@ /*****************************************************************************/ -void ec_command_init_nprd(ec_command_t *, uint16_t, uint16_t, size_t); -void ec_command_init_npwr(ec_command_t *, uint16_t, uint16_t, size_t, - const uint8_t *); -void ec_command_init_aprd(ec_command_t *, uint16_t, uint16_t, size_t); -void ec_command_init_apwr(ec_command_t *, uint16_t, uint16_t, size_t, - const uint8_t *); -void ec_command_init_brd(ec_command_t *, uint16_t, size_t); -void ec_command_init_bwr(ec_command_t *, uint16_t, size_t, const uint8_t *); -void ec_command_init_lrw(ec_command_t *, uint32_t, size_t, uint8_t *); +void ec_command_init(ec_command_t *); +void ec_command_clear(ec_command_t *); + +int ec_command_nprd(ec_command_t *, uint16_t, uint16_t, size_t); +int ec_command_npwr(ec_command_t *, uint16_t, uint16_t, size_t); +int ec_command_aprd(ec_command_t *, uint16_t, uint16_t, size_t); +int ec_command_apwr(ec_command_t *, uint16_t, uint16_t, size_t); +int ec_command_brd(ec_command_t *, uint16_t, size_t); +int ec_command_bwr(ec_command_t *, uint16_t, size_t); +int ec_command_lrw(ec_command_t *, uint32_t, size_t); /*****************************************************************************/ diff -r f6c4f38b699f -r fdc24bf62f80 master/domain.c --- a/master/domain.c Sun Apr 02 09:26:56 2006 +0000 +++ b/master/domain.c Mon Apr 03 10:03:34 2006 +0000 @@ -25,14 +25,12 @@ ) { domain->master = master; - domain->data = NULL; domain->data_size = 0; - domain->commands = NULL; - domain->command_count = 0; domain->base_address = 0; domain->response_count = 0xFFFFFFFF; INIT_LIST_HEAD(&domain->field_regs); + INIT_LIST_HEAD(&domain->commands); } /*****************************************************************************/ @@ -43,8 +41,12 @@ void ec_domain_clear(ec_domain_t *domain /**< Domäne */) { - if (domain->data) kfree(domain->data); - if (domain->commands) kfree(domain->commands); + ec_command_t *command, *next; + + list_for_each_entry_safe(command, next, &domain->commands, list) { + ec_command_clear(command); + kfree(command); + } ec_domain_clear_field_regs(domain); } @@ -66,8 +68,8 @@ { ec_field_reg_t *field_reg; - if (!(field_reg = (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t), - GFP_KERNEL))) { + if (!(field_reg = + (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t), GFP_KERNEL))) { EC_ERR("Failed to allocate field registration.\n"); return -1; } @@ -107,6 +109,35 @@ /*****************************************************************************/ /** + Alloziert ein Prozessdatenkommando und fügt es in die Liste ein. +*/ + +int ec_domain_add_command(ec_domain_t *domain, /**< Domäne */ + uint32_t offset, /**< Logisches Offset */ + size_t data_size /**< Größe der Kommando-Daten */ + ) +{ + ec_command_t *command; + + if (!(command = kmalloc(sizeof(ec_command_t), GFP_KERNEL))) { + EC_ERR("Failed to allocate domain command!\n"); + return -1; + } + + ec_command_init(command); + + if (ec_command_lrw(command, offset, data_size)) { + kfree(command); + return -1; + } + + list_add_tail(&command->list, &domain->commands); + return 0; +} + +/*****************************************************************************/ + +/** Erzeugt eine Domäne. Reserviert den Speicher einer Domäne, berechnet die logischen Adressen der @@ -122,19 +153,19 @@ ec_field_reg_t *field_reg; ec_slave_t *slave; ec_fmmu_t *fmmu; - unsigned int i, j; - uint32_t data_offset; - - if (domain->data) { - EC_ERR("Domain already allocated!\n"); - return -1; - } + unsigned int i, j, cmd_count; + uint32_t field_off, field_off_cmd; + uint32_t cmd_offset; + size_t cmd_data_size; + ec_command_t *command; domain->base_address = base_address; - // Größe der Prozessdaten berechnen - // und logische Adressen der FMMUs setzen + // Größe der Prozessdaten berechnen und Kommandos allozieren domain->data_size = 0; + cmd_offset = base_address; + cmd_data_size = 0; + cmd_count = 0; for (i = 0; i < domain->master->slave_count; i++) { slave = &domain->master->slaves[i]; for (j = 0; j < slave->fmmu_count; j++) { @@ -142,49 +173,57 @@ if (fmmu->domain == domain) { fmmu->logical_start_address = base_address + domain->data_size; domain->data_size += fmmu->sync->size; + if (cmd_data_size + fmmu->sync->size > EC_MAX_DATA_SIZE) { + if (ec_domain_add_command(domain, cmd_offset, + cmd_data_size)) return -1; + cmd_offset += cmd_data_size; + cmd_data_size = 0; + cmd_count++; + } + cmd_data_size += fmmu->sync->size; } } } - if (!domain->data_size) { + // Letztes Kommando allozieren + if (cmd_data_size) { + if (ec_domain_add_command(domain, cmd_offset, cmd_data_size)) + return -1; + cmd_count++; + } + + if (!cmd_count) { EC_WARN("Domain 0x%08X contains no data!\n", (u32) domain); ec_domain_clear_field_regs(domain); return 0; } - // Prozessdaten allozieren - if (!(domain->data = kmalloc(domain->data_size, GFP_KERNEL))) { - EC_ERR("Failed to allocate domain data!\n"); - return -1; - } - - // Prozessdaten mit Nullen vorbelegen - memset(domain->data, 0x00, domain->data_size); - // Alle Prozessdatenzeiger setzen list_for_each_entry(field_reg, &domain->field_regs, list) { for (i = 0; i < field_reg->slave->fmmu_count; i++) { fmmu = &field_reg->slave->fmmus[i]; if (fmmu->domain == domain && fmmu->sync == field_reg->sync) { - data_offset = fmmu->logical_start_address - base_address - + field_reg->field_offset; - *field_reg->data_ptr = domain->data + data_offset; + field_off = fmmu->logical_start_address + + field_reg->field_offset; + // Kommando suchen + list_for_each_entry(command, &domain->commands, list) { + field_off_cmd = field_off - command->address.logical; + if (field_off >= command->address.logical && + field_off_cmd < command->mem_size) { + *field_reg->data_ptr = command->data + field_off_cmd; + } + } + if (!field_reg->data_ptr) { + EC_ERR("Failed to assign data pointer!\n"); + return -1; + } break; } } } - // Kommando-Array erzeugen - domain->command_count = domain->data_size / EC_MAX_DATA_SIZE + 1; - if (!(domain->commands = (ec_command_t *) kmalloc(sizeof(ec_command_t) - * domain->command_count, - GFP_KERNEL))) { - EC_ERR("Failed to allocate domain command array!\n"); - return -1; - } - EC_INFO("Domain %X - Allocated %i bytes in %i command(s)\n", - (u32) domain, domain->data_size, domain->command_count); + (u32) domain, domain->data_size, cmd_count); ec_domain_clear_field_regs(domain); @@ -346,19 +385,10 @@ void ecrt_domain_queue(ec_domain_t *domain /**< Domäne */) { - unsigned int i; - size_t size; - off_t offset; - - offset = 0; - for (i = 0; i < domain->command_count; i++) { - size = domain->data_size - offset; - if (size > EC_MAX_DATA_SIZE) size = EC_MAX_DATA_SIZE; - ec_command_init_lrw(domain->commands + i, - domain->base_address + offset, size, - domain->data + offset); - ec_master_queue_command(domain->master, domain->commands + i); - offset += size; + ec_command_t *command; + + list_for_each_entry(command, &domain->commands, list) { + ec_master_queue_command(domain->master, command); } } @@ -370,27 +400,15 @@ void ecrt_domain_process(ec_domain_t *domain /**< Domäne */) { - unsigned int working_counter_sum, i; + unsigned int working_counter_sum; ec_command_t *command; - size_t size; - off_t offset; working_counter_sum = 0; - offset = 0; - for (i = 0; i < domain->command_count; i++) { - command = domain->commands + i; - size = domain->data_size - offset; - if (size > EC_MAX_DATA_SIZE) size = EC_MAX_DATA_SIZE; + list_for_each_entry(command, &domain->commands, list) { if (command->state == EC_CMD_RECEIVED) { - // Daten vom Kommando- in den Prozessdatenspeicher kopieren - memcpy(domain->data + offset, command->data, size); working_counter_sum += command->working_counter; } - else if (unlikely(domain->master->debug_level)) { - EC_DBG("process data command not received!\n"); - } - offset += size; } ec_domain_response_count(domain, working_counter_sum); @@ -406,11 +424,9 @@ int ecrt_domain_state(ec_domain_t *domain /**< Domäne */) { - unsigned int i; ec_command_t *command; - for (i = 0; i < domain->command_count; i++) { - command = domain->commands + i; + list_for_each_entry(command, &domain->commands, list) { if (command->state != EC_CMD_RECEIVED) return -1; } diff -r f6c4f38b699f -r fdc24bf62f80 master/domain.h --- a/master/domain.h Sun Apr 02 09:26:56 2006 +0000 +++ b/master/domain.h Mon Apr 03 10:03:34 2006 +0000 @@ -46,10 +46,8 @@ { struct list_head list; /**< Listenkopf */ ec_master_t *master; /**< EtherCAT-Master, zu der die Domäne gehört. */ - uint8_t *data; /**< Prozessdaten */ size_t data_size; /**< Größe der Prozessdaten */ - ec_command_t *commands; /**< EtherCAT-Kommandos für die Prozessdaten */ - unsigned int command_count; /**< Anzahl allozierter Kommandos */ + struct list_head commands; /**< EtherCAT-Kommandos für die Prozessdaten */ uint32_t base_address; /**< Logische Basisaddresse der Domain */ unsigned int response_count; /**< Anzahl antwortender Slaves */ struct list_head field_regs; /**< Liste der Datenfeldregistrierungen */ diff -r f6c4f38b699f -r fdc24bf62f80 master/master.c --- a/master/master.c Sun Apr 02 09:26:56 2006 +0000 +++ b/master/master.c Mon Apr 03 10:03:34 2006 +0000 @@ -33,9 +33,12 @@ master->slaves = NULL; master->device = NULL; - INIT_LIST_HEAD(&master->commands); + INIT_LIST_HEAD(&master->command_queue); INIT_LIST_HEAD(&master->domains); + ec_command_init(&master->simple_command); + ec_command_init(&master->watch_command); + ec_master_reset(master); } @@ -56,6 +59,9 @@ ec_device_clear(master->device); kfree(master->device); } + + ec_command_clear(&master->simple_command); + ec_command_clear(&master->watch_command); } /*****************************************************************************/ @@ -72,8 +78,8 @@ ) { unsigned int i; - ec_command_t *command, *next_command; - ec_domain_t *domain, *next_domain; + ec_command_t *command, *next_c; + ec_domain_t *domain, *next_d; // Alle Slaves entfernen if (master->slaves) { @@ -86,13 +92,13 @@ master->slave_count = 0; // Kommando-Warteschlange leeren - list_for_each_entry_safe(command, next_command, &master->commands, list) { + list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { command->state = EC_CMD_ERROR; - list_del_init(&command->list); + list_del_init(&command->queue); } // Domain-Liste leeren - list_for_each_entry_safe(domain, next_domain, &master->domains, list) { + list_for_each_entry_safe(domain, next_d, &master->domains, list) { list_del(&domain->list); ec_domain_clear(domain); kfree(domain); @@ -166,7 +172,7 @@ ec_command_t *queued_command; // Ist das Kommando schon in der Warteschlange? - list_for_each_entry(queued_command, &master->commands, list) { + list_for_each_entry(queued_command, &master->command_queue, queue) { if (queued_command == command) { command->state = EC_CMD_QUEUED; if (unlikely(master->debug_level)) @@ -175,7 +181,7 @@ } } - list_add_tail(&command->list, &master->commands); + list_add_tail(&command->queue, &master->command_queue); command->state = EC_CMD_QUEUED; } @@ -206,7 +212,7 @@ follows_word = NULL; // Aktuellen Frame mit Kommandos füllen - list_for_each_entry(command, &master->commands, list) { + list_for_each_entry(command, &master->command_queue, queue) { if (command->state != EC_CMD_QUEUED) continue; // Passt das aktuelle Kommando noch in den aktuellen Rahmen? @@ -238,7 +244,7 @@ cur_data += command->data_size; // EtherCAT command footer - EC_WRITE_U16(cur_data, command->working_counter); + EC_WRITE_U16(cur_data, 0x0000); // Working counter cur_data += EC_COMMAND_FOOTER_SIZE; } @@ -323,7 +329,7 @@ // Suche passendes Kommando in der Liste matched = 0; - list_for_each_entry(command, &master->commands, list) { + list_for_each_entry(command, &master->command_queue, queue) { if (command->state == EC_CMD_SENT && command->type == command_type && command->index == command_index @@ -349,9 +355,9 @@ command->working_counter = EC_READ_U16(cur_data); cur_data += EC_COMMAND_FOOTER_SIZE; - // Kommando aus der Liste entfernen + // Kommando aus der Warteschlange entfernen command->state = EC_CMD_RECEIVED; - list_del_init(&command->list); + list_del_init(&command->queue); } } @@ -366,13 +372,13 @@ \return 0 bei Erfolg, sonst < 0 */ -int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */ - ec_command_t *command /**< Kommando */ - ) +int ec_master_simple_io(ec_master_t *master /**< EtherCAT-Master */) { unsigned int response_tries_left; + ec_command_t *command; response_tries_left = 10; + command = &master->simple_command; while (1) { @@ -415,21 +421,22 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */) { - ec_command_t command; ec_slave_t *slave; ec_slave_ident_t *ident; unsigned int i; - uint8_t data[2]; + ec_command_t *command; if (master->slaves || master->slave_count) { EC_ERR("Slave scan already done!\n"); return -1; } + command = &master->simple_command; + // Determine number of slaves on bus - ec_command_init_brd(&command, 0x0000, 4); - if (unlikely(ec_master_simple_io(master, &command))) return -1; - master->slave_count = command.working_counter; + if (ec_command_brd(command, 0x0000, 4)) return -1; + if (unlikely(ec_master_simple_io(master))) return -1; + master->slave_count = command->working_counter; EC_INFO("Found %i slaves on bus.\n", master->slave_count); if (!master->slave_count) return 0; @@ -455,10 +462,10 @@ slave = master->slaves + i; // Write station address - EC_WRITE_U16(data, slave->station_address); - ec_command_init_apwr(&command, slave->ring_position, - 0x0010, sizeof(uint16_t), data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_apwr(command, slave->ring_position, + 0x0010, sizeof(uint16_t))) return -1; + EC_WRITE_U16(command->data, slave->station_address); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Writing station address failed on slave %i!\n", i); return -1; } @@ -713,6 +720,8 @@ { unsigned int first; + if (unlikely(master->watch_command.state == EC_CMD_INIT)) return; + first = 1; if (master->watch_command.working_counter != master->slaves_responding || @@ -789,15 +798,21 @@ { unsigned int i, j; ec_slave_t *slave; - ec_command_t command; + ec_command_t *command; const ec_sync_t *sync; const ec_slave_type_t *type; const ec_fmmu_t *fmmu; - uint8_t data[256]; uint32_t domain_offset; ec_domain_t *domain; ec_eeprom_sync_t *eeprom_sync; + command = &master->simple_command; + + if (ec_command_brd(&master->watch_command, 0x130, 2)) { + EC_ERR("Failed to allocate watchdog command!\n"); + return -1; + } + // Domains erstellen domain_offset = 0; list_for_each_entry(domain, &master->domains, list) { @@ -826,10 +841,11 @@ // Resetting FMMUs if (slave->base_fmmu_count) { - memset(data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); - ec_command_init_npwr(&command, slave->station_address, 0x0600, - EC_FMMU_SIZE * slave->base_fmmu_count, data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_npwr(command, slave->station_address, 0x0600, + EC_FMMU_SIZE * slave->base_fmmu_count)) + return -1; + memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Resetting FMMUs failed on slave %i!\n", slave->ring_position); return -1; @@ -838,10 +854,11 @@ // Resetting Sync Manager channels if (slave->base_sync_count) { - memset(data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); - ec_command_init_npwr(&command, slave->station_address, 0x0800, - EC_SYNC_SIZE * slave->base_sync_count, data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_npwr(command, slave->station_address, 0x0800, + EC_SYNC_SIZE * slave->base_sync_count)) + return -1; + memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Resetting sync managers failed on slave %i!\n", slave->ring_position); return -1; @@ -853,11 +870,11 @@ for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) { sync = type->sync_managers[j]; - ec_sync_config(sync, data); - ec_command_init_npwr(&command, slave->station_address, - 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE, - data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_npwr(command, slave->station_address, + 0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE)) + return -1; + ec_sync_config(sync, command->data); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Setting sync manager %i failed on slave %i!\n", j, slave->ring_position); return -1; @@ -866,11 +883,11 @@ } else if (slave->sii_mailbox_protocols) { // Unknown slave, has mailbox list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) { - ec_eeprom_sync_config(eeprom_sync, data); - ec_command_init_npwr(&command, slave->station_address, - 0x800 + eeprom_sync->index * EC_SYNC_SIZE, - EC_SYNC_SIZE, data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_npwr(command, slave->station_address, + 0x800 + eeprom_sync->index * EC_SYNC_SIZE, + EC_SYNC_SIZE)) return -1; + ec_eeprom_sync_config(eeprom_sync, command->data); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Setting sync manager %i failed on slave %i!\n", eeprom_sync->index, slave->ring_position); return -1; @@ -896,12 +913,11 @@ for (j = 0; j < slave->fmmu_count; j++) { fmmu = &slave->fmmus[j]; - - ec_fmmu_config(fmmu, data); - ec_command_init_npwr(&command, slave->station_address, - 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE, - data); - if (unlikely(ec_master_simple_io(master, &command))) { + if (ec_command_npwr(command, slave->station_address, + 0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE)) + return -1; + ec_fmmu_config(fmmu, command->data); + if (unlikely(ec_master_simple_io(master))) { EC_ERR("Setting FMMU %i failed on slave %i!\n", j, slave->ring_position); return -1; @@ -980,31 +996,17 @@ void ecrt_master_sync_io(ec_master_t *master) { - ec_command_t *command, *next; + ec_command_t *command, *n; unsigned int commands_sent; cycles_t t_start, t_end, t_timeout; - ec_master_output_stats(master); - - if (unlikely(!master->device->link_state)) { - // Link DOWN, keines der Kommandos kann gesendet werden. - list_for_each_entry_safe(command, next, &master->commands, list) { - command->state = EC_CMD_ERROR; - list_del_init(&command->list); - } - - // Device-Zustand abfragen - ec_device_call_isr(master->device); - return; - } - - // Rahmen senden - ec_master_send_commands(master); + // Kommandos senden + ecrt_master_async_send(master); t_start = get_cycles(); // Sendezeit nehmen t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000); - while (1) + while (1) // Aktiv auf Empfang warten { ec_device_call_isr(master->device); @@ -1012,9 +1014,9 @@ if (t_end - t_start >= t_timeout) break; // Timeout commands_sent = 0; - list_for_each_entry_safe(command, next, &master->commands, list) { + list_for_each_entry_safe(command, n, &master->command_queue, queue) { if (command->state == EC_CMD_RECEIVED) - list_del_init(&command->list); + list_del_init(&command->queue); else if (command->state == EC_CMD_SENT) commands_sent++; } @@ -1023,7 +1025,7 @@ } // Zeit abgelaufen. Alle verbleibenden Kommandos entfernen. - list_for_each_entry_safe(command, next, &master->commands, list) { + list_for_each_entry_safe(command, n, &master->command_queue, queue) { switch (command->state) { case EC_CMD_SENT: case EC_CMD_QUEUED: @@ -1038,7 +1040,7 @@ default: break; } - list_del_init(&command->list); + list_del_init(&command->queue); } } @@ -1050,15 +1052,13 @@ void ecrt_master_async_send(ec_master_t *master) { - ec_command_t *command, *next; - - ec_master_output_stats(master); + ec_command_t *command, *n; if (unlikely(!master->device->link_state)) { // Link DOWN, keines der Kommandos kann gesendet werden. - list_for_each_entry_safe(command, next, &master->commands, list) { + list_for_each_entry_safe(command, n, &master->command_queue, queue) { command->state = EC_CMD_ERROR; - list_del_init(&command->list); + list_del_init(&command->queue); } // Device-Zustand abfragen @@ -1066,10 +1066,6 @@ return; } - // Watch-Kommando hinzufügen - ec_command_init_brd(&master->watch_command, 0x130, 2); - ec_master_queue_command(master, &master->watch_command); - // Rahmen senden ec_master_send_commands(master); } @@ -1087,12 +1083,11 @@ ec_device_call_isr(master->device); // Alle empfangenen Kommandos aus der Liste entfernen - list_for_each_entry_safe(command, next, &master->commands, list) - if (command->state == EC_CMD_RECEIVED) - list_del_init(&command->list); + list_for_each_entry_safe(command, next, &master->command_queue, queue) + if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue); // Alle verbleibenden Kommandos entfernen. - list_for_each_entry_safe(command, next, &master->commands, list) { + list_for_each_entry_safe(command, next, &master->command_queue, queue) { switch (command->state) { case EC_CMD_SENT: case EC_CMD_QUEUED: @@ -1103,14 +1098,8 @@ default: break; } - list_del_init(&command->list); - } - - // Watch-Kommando verarbeiten - ec_master_process_watch_command(master); - - // Statistiken ausgeben - ec_master_output_stats(master); + list_del_init(&command->queue); + } } /*****************************************************************************/ @@ -1128,7 +1117,7 @@ ec_domain_t *domain; cycles_t t_start, t_end, t_timeout; - // Alle empfangenen Kommandos aus der Liste entfernen + // Kommandos aller Domains in die Warteschlange setzen list_for_each_entry(domain, &master->domains, list) ecrt_domain_queue(domain); @@ -1147,6 +1136,22 @@ /*****************************************************************************/ /** + Führt Routinen im zyklischen Betrieb aus. +*/ + +void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */) +{ + // Statistiken ausgeben + ec_master_output_stats(master); + + // Watchdog-Kommando + ec_master_process_watch_command(master); + ec_master_queue_command(master, &master->watch_command); +} + +/*****************************************************************************/ + +/** Setzt die Debug-Ebene des Masters. Folgende Debug-Level sind definiert: @@ -1198,6 +1203,7 @@ EXPORT_SYMBOL(ecrt_master_sync_io); EXPORT_SYMBOL(ecrt_master_async_send); EXPORT_SYMBOL(ecrt_master_async_receive); +EXPORT_SYMBOL(ecrt_master_run); EXPORT_SYMBOL(ecrt_master_debug); EXPORT_SYMBOL(ecrt_master_print); EXPORT_SYMBOL(ecrt_master_get_slave); diff -r f6c4f38b699f -r fdc24bf62f80 master/master.h --- a/master/master.h Sun Apr 02 09:26:56 2006 +0000 +++ b/master/master.h Mon Apr 03 10:03:34 2006 +0000 @@ -47,9 +47,10 @@ ec_slave_t *slaves; /**< Array von Slaves auf dem Bus */ unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */ ec_device_t *device; /**< EtherCAT-Gerät */ - struct list_head commands; /**< Kommando-Liste */ + struct list_head command_queue; /**< Kommando-Warteschlange */ uint8_t command_index; /**< Aktueller Kommando-Index */ struct list_head domains; /**< Liste der Prozessdatendomänen */ + ec_command_t simple_command; /**< Kommando für Initialisierungsphase */ ec_command_t watch_command; /**< Kommando zum Überwachen der Slaves */ unsigned int slaves_responding; /**< Anzahl antwortender Slaves */ ec_slave_state_t slave_states; /**< Zustände der antwortenden Slaves */ @@ -68,7 +69,7 @@ // IO void ec_master_receive(ec_master_t *, const uint8_t *, size_t); void ec_master_queue_command(ec_master_t *, ec_command_t *); -int ec_master_simple_io(ec_master_t *, ec_command_t *); +int ec_master_simple_io(ec_master_t *); // Registration of devices int ec_master_open(ec_master_t *); diff -r f6c4f38b699f -r fdc24bf62f80 master/slave.c --- a/master/slave.c Sun Apr 02 09:26:56 2006 +0000 +++ b/master/slave.c Mon Apr 03 10:03:34 2006 +0000 @@ -141,36 +141,38 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */) { - ec_command_t command; + ec_command_t *command; unsigned int i; uint16_t dl_status; + command = &slave->master->simple_command; + // Read base data - ec_command_init_nprd(&command, slave->station_address, 0x0000, 6); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Reading base data from slave %i failed!\n", slave->ring_position); return -1; } - slave->base_type = EC_READ_U8 (command.data); - slave->base_revision = EC_READ_U8 (command.data + 1); - slave->base_build = EC_READ_U16(command.data + 2); - slave->base_fmmu_count = EC_READ_U8 (command.data + 4); - slave->base_sync_count = EC_READ_U8 (command.data + 5); + slave->base_type = EC_READ_U8 (command->data); + slave->base_revision = EC_READ_U8 (command->data + 1); + slave->base_build = EC_READ_U16(command->data + 2); + slave->base_fmmu_count = EC_READ_U8 (command->data + 4); + slave->base_sync_count = EC_READ_U8 (command->data + 5); if (slave->base_fmmu_count > EC_MAX_FMMUS) slave->base_fmmu_count = EC_MAX_FMMUS; // Read DL status - ec_command_init_nprd(&command, slave->station_address, 0x0110, 2); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Reading DL status from slave %i failed!\n", slave->ring_position); return -1; } - dl_status = EC_READ_U16(command.data); + dl_status = EC_READ_U16(command->data); for (i = 0; i < 2; i++) { slave->dl_status_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0; slave->dl_status_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0; @@ -224,18 +226,17 @@ /**< Speicher für Wert (16-Bit) */ ) { - ec_command_t command; - uint8_t data[10]; + ec_command_t *command; cycles_t start, end, timeout; + command = &slave->master->simple_command; + // Initiate read operation - - 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))) { + if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; + EC_WRITE_U8 (command->data, 0x00); // read-only access + EC_WRITE_U8 (command->data + 1, 0x01); // request read operation + EC_WRITE_U32(command->data + 2, offset); + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); return -1; } @@ -251,8 +252,9 @@ { udelay(10); - ec_command_init_nprd(&command, slave->station_address, 0x502, 10); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x502, 10)) + return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Getting SII-read status failed on slave %i!\n", slave->ring_position); return -1; @@ -260,8 +262,8 @@ end = get_cycles(); - if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) { - *target = EC_READ_U16(command.data + 6); + if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) { + *target = EC_READ_U16(command->data + 6); return 0; } @@ -289,18 +291,17 @@ /**< Speicher für Wert (32-Bit) */ ) { - ec_command_t command; - uint8_t data[10]; + ec_command_t *command; cycles_t start, end, timeout; + command = &slave->master->simple_command; + // Initiate read operation - - 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))) { + if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1; + EC_WRITE_U8 (command->data, 0x00); // read-only access + EC_WRITE_U8 (command->data + 1, 0x01); // request read operation + EC_WRITE_U32(command->data + 2, offset); + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("SII-read failed on slave %i!\n", slave->ring_position); return -1; } @@ -316,8 +317,9 @@ { udelay(10); - ec_command_init_nprd(&command, slave->station_address, 0x502, 10); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x502, 10)) + return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Getting SII-read status failed on slave %i!\n", slave->ring_position); return -1; @@ -325,8 +327,8 @@ end = get_cycles(); - if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) { - *target = EC_READ_U32(command.data + 6); + if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) { + *target = EC_READ_U32(command->data + 6); return 0; } @@ -354,22 +356,21 @@ /**< Zu schreibender Wert */ ) { - ec_command_t command; - uint8_t data[8]; + ec_command_t *command; cycles_t start, end, timeout; + command = &slave->master->simple_command; + 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))) { + if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1; + EC_WRITE_U8 (command->data, 0x01); // enable write access + EC_WRITE_U8 (command->data + 1, 0x02); // request write operation + EC_WRITE_U32(command->data + 2, offset); + EC_WRITE_U16(command->data + 6, value); + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("SII-write failed on slave %i!\n", slave->ring_position); return -1; } @@ -385,8 +386,9 @@ { udelay(10); - ec_command_init_nprd(&command, slave->station_address, 0x502, 2); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x502, 2)) + return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Getting SII-write status failed on slave %i!\n", slave->ring_position); return -1; @@ -394,8 +396,8 @@ end = get_cycles(); - if (likely((EC_READ_U8(command.data + 1) & 0x82) == 0)) { - if (EC_READ_U8(command.data + 1) & 0x40) { + 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; } @@ -717,14 +719,14 @@ /**< Alter Zustand */ ) { - ec_command_t command; - uint8_t data[2]; + ec_command_t *command; cycles_t start, end, timeout; - EC_WRITE_U16(data, state | EC_ACK); - - ec_command_init_npwr(&command, slave->station_address, 0x0120, 2, data); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + command = &slave->master->simple_command; + + if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return; + EC_WRITE_U16(command->data, state | EC_ACK); + if (unlikely(ec_master_simple_io(slave->master))) { EC_WARN("State %02X acknowledge failed on slave %i!\n", state, slave->ring_position); return; @@ -737,8 +739,9 @@ { udelay(100); // Dem Slave etwas Zeit lassen... - ec_command_init_nprd(&command, slave->station_address, 0x0130, 2); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) + return; + if (unlikely(ec_master_simple_io(slave->master))) { EC_WARN("State %02X acknowledge checking failed on slave %i!\n", state, slave->ring_position); return; @@ -746,14 +749,14 @@ end = get_cycles(); - if (unlikely(EC_READ_U8(command.data) != state)) { + if (unlikely(EC_READ_U8(command->data) != state)) { EC_WARN("Could not acknowledge state %02X on slave %i (code" " %02X)!\n", state, slave->ring_position, - EC_READ_U8(command.data)); + EC_READ_U8(command->data)); return; } - if (likely(EC_READ_U8(command.data) == state)) { + if (likely(EC_READ_U8(command->data) == state)) { EC_INFO("Acknowleged state %02X on slave %i.\n", state, slave->ring_position); return; @@ -781,14 +784,14 @@ /**< Neuer Zustand */ ) { - ec_command_t command; - uint8_t data[2]; + ec_command_t *command; cycles_t start, end, timeout; - EC_WRITE_U16(data, state); - - ec_command_init_npwr(&command, slave->station_address, 0x0120, 2, data); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + command = &slave->master->simple_command; + + if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1; + EC_WRITE_U16(command->data, state); + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Failed to set state %02X on slave %i!\n", state, slave->ring_position); return -1; @@ -801,8 +804,9 @@ { udelay(100); // Dem Slave etwas Zeit lassen... - ec_command_init_nprd(&command, slave->station_address, 0x0130, 2); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) + return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Failed to check state %02X on slave %i!\n", state, slave->ring_position); return -1; @@ -810,15 +814,15 @@ end = get_cycles(); - if (unlikely(EC_READ_U8(command.data) & 0x10)) { // State change error + if (unlikely(EC_READ_U8(command->data) & 0x10)) { // State change error EC_ERR("Could not set state %02X - Slave %i refused state change" " (code %02X)!\n", state, slave->ring_position, - EC_READ_U8(command.data)); - ec_slave_state_ack(slave, EC_READ_U8(command.data) & 0x0F); - return -1; - } - - if (likely(EC_READ_U8(command.data) == (state & 0x0F))) { + EC_READ_U8(command->data)); + ec_slave_state_ack(slave, EC_READ_U8(command->data) & 0x0F); + return -1; + } + + if (likely(EC_READ_U8(command->data) == (state & 0x0F))) { // State change successful return 0; } @@ -1040,44 +1044,45 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */) { - ec_command_t command; - uint8_t data[4]; - - ec_command_init_nprd(&command, slave->station_address, 0x0300, 4); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + ec_command_t *command; + + command = &slave->master->simple_command; + + if (ec_command_nprd(command, slave->station_address, 0x0300, 4)) return -1; + if (unlikely(ec_master_simple_io(slave->master))) { EC_WARN("Reading CRC fault counters failed on slave %i!\n", slave->ring_position); return -1; } // No CRC faults. - if (!EC_READ_U32(command.data)) return 0; - - if (EC_READ_U8(command.data)) + if (!EC_READ_U32(command->data)) return 0; + + if (EC_READ_U8(command->data)) EC_WARN("%3i RX-error%s on slave %i, channel A.\n", - EC_READ_U8(command.data), - EC_READ_U8(command.data) == 1 ? "" : "s", + EC_READ_U8(command->data), + EC_READ_U8(command->data) == 1 ? "" : "s", slave->ring_position); - if (EC_READ_U8(command.data + 1)) + if (EC_READ_U8(command->data + 1)) EC_WARN("%3i invalid frame%s on slave %i, channel A.\n", - EC_READ_U8(command.data + 1), - EC_READ_U8(command.data + 1) == 1 ? "" : "s", + EC_READ_U8(command->data + 1), + EC_READ_U8(command->data + 1) == 1 ? "" : "s", slave->ring_position); - if (EC_READ_U8(command.data + 2)) + if (EC_READ_U8(command->data + 2)) EC_WARN("%3i RX-error%s on slave %i, channel B.\n", - EC_READ_U8(command.data + 2), - EC_READ_U8(command.data + 2) == 1 ? "" : "s", + EC_READ_U8(command->data + 2), + EC_READ_U8(command->data + 2) == 1 ? "" : "s", slave->ring_position); - if (EC_READ_U8(command.data + 3)) + if (EC_READ_U8(command->data + 3)) EC_WARN("%3i invalid frame%s on slave %i, channel B.\n", - EC_READ_U8(command.data + 3), - EC_READ_U8(command.data + 3) == 1 ? "" : "s", + EC_READ_U8(command->data + 3), + EC_READ_U8(command->data + 3) == 1 ? "" : "s", slave->ring_position); // Reset CRC counters - EC_WRITE_U32(data, 0x00000000); - ec_command_init_npwr(&command, slave->station_address, 0x0300, 4, data); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1; + EC_WRITE_U32(command->data, 0x00000000); + if (unlikely(ec_master_simple_io(slave->master))) { EC_WARN("Resetting CRC fault counters failed on slave %i!\n", slave->ring_position); return -1; @@ -1089,74 +1094,60 @@ /*****************************************************************************/ /** - Sendet ein Mailbox-Kommando. + Bereitet ein Mailbox-Send-Kommando vor. */ -int ec_slave_mailbox_send(ec_slave_t *slave, /**< EtherCAT-Slave */ - uint8_t type, /**< Unterliegendes Protokoll */ - const uint8_t *prot_data, /**< Protokoll-Daten */ - size_t size /**< Datengröße */ - ) +uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *slave, /**< Slave */ + uint8_t type, /**< Mailbox-Protokoll */ + size_t size /**< Datengröße */ + ) { size_t total_size; - uint8_t *data; - ec_command_t command; + ec_command_t *command; if (unlikely(!slave->sii_mailbox_protocols)) { EC_ERR("Slave %i does not support mailbox communication!\n", slave->ring_position); - return -1; + return NULL; } total_size = size + 6; if (unlikely(total_size > slave->sii_rx_mailbox_size)) { EC_ERR("Data size does not fit in mailbox!\n"); - return -1; - } - - if (!(data = kmalloc(slave->sii_rx_mailbox_size, GFP_KERNEL))) { - EC_ERR("Failed to allocate %i bytes of memory for mailbox data!\n", - slave->sii_rx_mailbox_size); - return -1; - } - - memset(data, 0x00, slave->sii_rx_mailbox_size); - EC_WRITE_U16(data, size); // Length of the Mailbox service data - EC_WRITE_U16(data + 2, slave->station_address); // Station address - EC_WRITE_U8 (data + 4, 0x00); // Channel & priority - EC_WRITE_U8 (data + 5, type); // Underlying protocol type - memcpy(data + 6, prot_data, size); - - ec_command_init_npwr(&command, slave->station_address, - slave->sii_rx_mailbox_offset, - slave->sii_rx_mailbox_size, data); - if (unlikely(ec_master_simple_io(slave->master, &command))) { - EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position); - kfree(data); - return -1; - } - - kfree(data); - return 0; -} - -/*****************************************************************************/ - -/** - Sendet ein Mailbox-Kommando. + return NULL; + } + + command = &slave->master->simple_command; + + if (ec_command_npwr(command, slave->station_address, + slave->sii_rx_mailbox_offset, + slave->sii_rx_mailbox_size)) return NULL; + EC_WRITE_U16(command->data, size); // Mailbox service data length + EC_WRITE_U16(command->data + 2, slave->station_address); // Station address + EC_WRITE_U8 (command->data + 4, 0x00); // Channel & priority + EC_WRITE_U8 (command->data + 5, type); // Underlying protocol type + + return command->data + 6; +} + +/*****************************************************************************/ + +/** + Empfängt ein Mailbox-Kommando. */ -int ec_slave_mailbox_receive(ec_slave_t *slave, /**< EtherCAT-Slave */ - uint8_t type, /**< Unterliegendes Protokoll */ - uint8_t *prot_data, /**< Protokoll-Daten */ - size_t *size /**< Datengröße des Puffers, später - Größe der gelesenen Daten */ - ) -{ - ec_command_t command; +uint8_t *ec_slave_mailbox_receive(ec_slave_t *slave, /**< Slave */ + uint8_t type, /**< Protokoll */ + size_t *size /**< Größe der gelesenen + Daten */ + ) +{ + ec_command_t *command; size_t data_size; cycles_t start, end, timeout; + command = &slave->master->simple_command; + // Read "written bit" of Sync-Manager start = get_cycles(); timeout = (cycles_t) 100 * cpu_khz; // 100ms @@ -1164,59 +1155,54 @@ while (1) { // FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox? - ec_command_init_nprd(&command, slave->station_address, 0x808, 8); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, 0x808, 8)) + return NULL; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position); - return -1; + return NULL; } end = get_cycles(); - if (EC_READ_U8(command.data + 5) & 8) + if (EC_READ_U8(command->data + 5) & 8) break; // Proceed with received data if ((end - start) >= timeout) { EC_ERR("Mailbox check - Slave %i timed out.\n", slave->ring_position); - return -1; + return NULL; } udelay(100); } - ec_command_init_nprd(&command, slave->station_address, - slave->sii_tx_mailbox_offset, - slave->sii_tx_mailbox_size); - if (unlikely(ec_master_simple_io(slave->master, &command))) { + if (ec_command_nprd(command, slave->station_address, + slave->sii_tx_mailbox_offset, + slave->sii_tx_mailbox_size)) return NULL; + if (unlikely(ec_master_simple_io(slave->master))) { EC_ERR("Mailbox receiving failed on slave %i!\n", slave->ring_position); - return -1; - } - - if ((EC_READ_U8(command.data + 5) & 0x0F) != type) { + return NULL; + } + + if ((EC_READ_U8(command->data + 5) & 0x0F) != type) { EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at" - " slave %i!\n", EC_READ_U8(command.data + 5), type, + " slave %i!\n", EC_READ_U8(command->data + 5), type, slave->ring_position); - return -1; + return NULL; } if (unlikely(slave->master->debug_level) > 1) EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000 / cpu_khz)); - if ((data_size = EC_READ_U16(command.data)) > *size) { - EC_ERR("Mailbox service data does not fit into buffer (%i > %i).\n", - data_size, *size); - return -1; - } - - if (data_size > slave->sii_tx_mailbox_size - 6) { + if ((data_size = EC_READ_U16(command->data)) > + slave->sii_tx_mailbox_size - 6) { EC_ERR("Currupt mailbox response detected!\n"); - return -1; - } - - memcpy(prot_data, command.data + 6, data_size); + return NULL; + } + *size = data_size; return 0; } diff -r f6c4f38b699f -r fdc24bf62f80 master/slave.h --- a/master/slave.h Sun Apr 02 09:26:56 2006 +0000 +++ b/master/slave.h Mon Apr 03 10:03:34 2006 +0000 @@ -248,8 +248,8 @@ int ec_slave_set_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sync_t *); // Mailbox -int ec_slave_mailbox_send(ec_slave_t *, uint8_t, const uint8_t *, size_t); -int ec_slave_mailbox_receive(ec_slave_t *, uint8_t, uint8_t *, size_t *); +uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *, uint8_t, size_t); +uint8_t *ec_slave_mailbox_receive(ec_slave_t *, uint8_t, size_t *); // CANopen over EtherCAT int ec_slave_fetch_sdo_list(ec_slave_t *); diff -r f6c4f38b699f -r fdc24bf62f80 rt/msr_module.c --- a/rt/msr_module.c Sun Apr 02 09:26:56 2006 +0000 +++ b/rt/msr_module.c Mon Apr 03 10:03:34 2006 +0000 @@ -99,6 +99,7 @@ k_preio = (uint32_t) (get_cycles() - offset) * 1e6 / cpu_khz; #ifdef ASYNC + // Empfangen ecrt_master_async_receive(master); ecrt_domain_process(domain1); @@ -113,10 +114,14 @@ // Senden ecrt_domain_queue(domain1); + ecrt_master_run(master); ecrt_master_async_send(master); -#else + +#else // ASYNC + // Senden und empfangen ecrt_domain_queue(domain1); + ecrt_master_run(master); ecrt_master_sync_io(master); ecrt_domain_process(domain1); @@ -184,9 +189,11 @@ int __init init_rt_module(void) { struct ipipe_domain_attr attr; //ipipe +#ifdef BLOCK1 uint8_t string[20]; size_t size; ec_slave_t *slave; +#endif // Als allererstes die RT-Lib initialisieren if (msr_rtlib_init(1, MSR_ABTASTFREQUENZ, 10, &msr_globals_register) < 0) { @@ -286,8 +293,10 @@ ipipe_register_domain(&this_domain, &attr); return 0; +#ifdef BLOCK1 out_deactivate: ecrt_master_deactivate(master); +#endif out_release_master: ecrt_release_master(master); out_msr_cleanup: diff -r f6c4f38b699f -r fdc24bf62f80 todo.txt --- a/todo.txt Sun Apr 02 09:26:56 2006 +0000 +++ b/todo.txt Mon Apr 03 10:03:34 2006 +0000 @@ -3,8 +3,6 @@ $Id$ -- Kommandos mit dynamischem Speicher -- Master mit eigener State-Machine; run() bzw. in send() - Verteilen von empfangenen Mailbox-Daten? - Ethernet over EtherCAT (EoE) - Anzahl Frames, die die Karte Puffern kann