From 9c317024a50647b97febd6d401c20bdfe0259320 Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Fri, 18 Nov 2005 09:51:50 +0000 Subject: [PATCH] Code zum Senden/Empfangen mehrerer Kommandos in einem Frame vorerst ganz entfernt. --- drivers/ec_command.c | 1 - drivers/ec_command.h | 5 - drivers/ec_device.c | 2 + drivers/ec_master.c | 1176 ++++++++---------------------------------- drivers/ec_master.h | 83 +-- drivers/ec_types.c | 2 +- 6 files changed, 231 insertions(+), 1038 deletions(-) diff --git a/drivers/ec_command.c b/drivers/ec_command.c index a4d26528..d18b5120 100644 --- a/drivers/ec_command.c +++ b/drivers/ec_command.c @@ -30,7 +30,6 @@ void EtherCAT_command_init(EtherCAT_command_t *cmd) cmd->type = ECAT_CMD_NONE; cmd->address.logical = 0x00000000; cmd->data_length = 0; - //cmd->next = NULL; cmd->state = ECAT_CS_READY; cmd->index = 0; cmd->working_counter = 0; diff --git a/drivers/ec_command.h b/drivers/ec_command.h index 030ed576..7e6f3b6d 100644 --- a/drivers/ec_command.h +++ b/drivers/ec_command.h @@ -69,11 +69,6 @@ typedef struct EtherCAT_command EtherCAT_address_t address; /**< Adresse des/der Empfänger */ unsigned int data_length; /**< Länge der zu sendenden und/oder empfangenen Daten */ -#if 0 - struct EtherCAT_command *next; /**< (Für den Master) Zeiger auf nächstes Kommando - in der Liste */ -#endif - EtherCAT_command_state_t state; /**< Zustand des Kommandos (bereit, gesendet, etc...) */ unsigned char index; /**< Kommando-Index, mit der das Kommando gesendet wurde (wird vom Master beim Senden gesetzt. */ diff --git a/drivers/ec_device.c b/drivers/ec_device.c index f8d94540..02aefe31 100644 --- a/drivers/ec_device.c +++ b/drivers/ec_device.c @@ -17,6 +17,8 @@ #include "ec_device.h" #include "ec_dbg.h" +extern void rtl8139_interrupt(int, void *, struct pt_regs *); + /***************************************************************/ /** diff --git a/drivers/ec_master.c b/drivers/ec_master.c index 6457aacb..d8b078ef 100644 --- a/drivers/ec_master.c +++ b/drivers/ec_master.c @@ -34,8 +34,6 @@ int EtherCAT_master_init(EtherCAT_master_t *master, EtherCAT_device_t *dev) { - unsigned int i; - if (!dev) { EC_DBG(KERN_ERR "EtherCAT: Master init without device!\n"); @@ -44,24 +42,13 @@ int EtherCAT_master_init(EtherCAT_master_t *master, master->slaves = NULL; master->slave_count = 0; - //master->first_command = NULL; - //master->process_data_command = NULL; master->dev = dev; master->command_index = 0x00; master->tx_data_length = 0; master->process_data = NULL; master->process_data_length = 0; - //master->cmd_ring_index = 0; master->debug_level = 0; -#if 0 - for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++) - { - EtherCAT_command_init(&master->cmd_ring[i]); - master->cmd_reserved[i] = 0; - } -#endif - return 0; } @@ -78,14 +65,6 @@ int EtherCAT_master_init(EtherCAT_master_t *master, void EtherCAT_master_clear(EtherCAT_master_t *master) { -#if 0 - // Remove all pending commands - while (master->first_command) - { - EtherCAT_remove_command(master, master->first_command); - } -#endif - // Remove all slaves EtherCAT_clear_slaves(master); @@ -100,6 +79,223 @@ void EtherCAT_master_clear(EtherCAT_master_t *master) /***************************************************************/ +/** + Sendet ein einzelnes Kommando in einem Frame und + wartet auf dessen Empfang. + + @param master EtherCAT-Master + @param cmd Kommando zum Senden/Empfangen + + @return 0 bei Erfolg, sonst < 0 +*/ + +int EtherCAT_simple_send_receive(EtherCAT_master_t *master, + EtherCAT_command_t *cmd) +{ + unsigned int tries_left; + + if (EtherCAT_simple_send(master, cmd) < 0) return -1; + + tries_left = 100; + while (cmd->state == ECAT_CS_SENT && tries_left) + { + udelay(10); + EtherCAT_device_call_isr(master->dev); + tries_left--; + } + + if (EtherCAT_simple_receive(master, cmd) < 0) return -1; + + return 0; +} + +/***************************************************************/ + +/** + Sendet ein einzelnes Kommando in einem Frame. + + @param master EtherCAT-Master + @param cmd Kommando zum Senden + + @return 0 bei Erfolg, sonst < 0 +*/ + +int EtherCAT_simple_send(EtherCAT_master_t *master, + EtherCAT_command_t *cmd) +{ + unsigned int length, framelength, i; + + if (master->debug_level > 0) + { + EC_DBG(KERN_DEBUG "EtherCAT_send_receive_command\n"); + } + + if (cmd->state != ECAT_CS_READY) + { + EC_DBG(KERN_WARNING "EtherCAT_send_receive_command: Command not in ready state!\n"); + } + + length = cmd->data_length + 12; + framelength = length + 2; + if (framelength < 46) framelength = 46; + + if (master->debug_level > 0) + { + EC_DBG(KERN_DEBUG "Frame length: %i\n", framelength); + } + + master->tx_data[0] = length & 0xFF; + master->tx_data[1] = ((length & 0x700) >> 8) | 0x10; + + cmd->index = master->command_index; + master->command_index = (master->command_index + 1) % 0x0100; + + if (master->debug_level > 0) + { + EC_DBG(KERN_DEBUG "Sending command index %i\n", cmd->index); + } + + cmd->state = ECAT_CS_SENT; + + master->tx_data[2 + 0] = cmd->type; + master->tx_data[2 + 1] = cmd->index; + master->tx_data[2 + 2] = cmd->address.raw[0]; + master->tx_data[2 + 3] = cmd->address.raw[1]; + master->tx_data[2 + 4] = cmd->address.raw[2]; + master->tx_data[2 + 5] = cmd->address.raw[3]; + master->tx_data[2 + 6] = cmd->data_length & 0xFF; + master->tx_data[2 + 7] = (cmd->data_length & 0x700) >> 8; + master->tx_data[2 + 8] = 0x00; + master->tx_data[2 + 9] = 0x00; + + if (cmd->type == ECAT_CMD_APWR + || cmd->type == ECAT_CMD_NPWR + || cmd->type == ECAT_CMD_BWR + || cmd->type == ECAT_CMD_LRW) // Write + { + for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = cmd->data[i]; + } + else // Read + { + for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = 0x00; + } + + master->tx_data[2 + 10 + cmd->data_length] = 0x00; + master->tx_data[2 + 11 + cmd->data_length] = 0x00; + + // Pad with zeros + for (i = cmd->data_length + 12 + 2; i < 46; i++) master->tx_data[i] = 0x00; + + master->tx_data_length = framelength; + + if (master->debug_level > 0) + { + EC_DBG(KERN_DEBUG "device send...\n"); + } + + // Send frame + if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0) + { + EC_DBG(KERN_ERR "EtherCAT: Could not send!\n"); + return -1; + } + + if (master->debug_level > 0) + { + EC_DBG(KERN_DEBUG "EtherCAT_send done.\n"); + } + + return 0; +} + +/***************************************************************/ + +/** + Wartet auf den Empfang eines einzeln gesendeten + Kommandos. + + @param master EtherCAT-Master + @param cmd Gesendetes Kommando + + @return 0 bei Erfolg, sonst < 0 +*/ + +int EtherCAT_simple_receive(EtherCAT_master_t *master, + EtherCAT_command_t *cmd) +{ + unsigned int rx_data_length, length; + unsigned char command_type, command_index; + + rx_data_length = EtherCAT_device_receive(master->dev, master->rx_data, + ECAT_FRAME_BUFFER_SIZE); + + if (rx_data_length < 2) + { + EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete EtherCAT header!\n"); + EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); + output_debug_data(master->tx_data, master->tx_data_length); + EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); + output_debug_data(master->rx_data, rx_data_length); + return -1; + } + + // Länge des gesamten Frames prüfen + length = ((master->rx_data[1] & 0x07) << 8) | (master->rx_data[0] & 0xFF); + + if (length > rx_data_length) + { + EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (length does not match)!\n"); + EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); + output_debug_data(master->tx_data, master->tx_data_length); + EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); + output_debug_data(master->rx_data, rx_data_length); + return -1; + } + + command_type = master->rx_data[2]; + command_index = master->rx_data[2 + 1]; + length = (master->rx_data[2 + 6] & 0xFF) | ((master->rx_data[2 + 7] & 0x07) << 8); + + if (rx_data_length - 2 < length + 12) + { + EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command data!\n"); + EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); + output_debug_data(master->tx_data, master->tx_data_length); + EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); + output_debug_data(master->rx_data, rx_data_length); + return -1; + } + + if (cmd->state == ECAT_CS_SENT + && cmd->type == command_type + && cmd->index == command_index + && cmd->data_length == length) + { + cmd->state = ECAT_CS_RECEIVED; + + // Empfangene Daten in Kommandodatenspeicher kopieren + memcpy(cmd->data, master->rx_data + 2 + 10, length); + + // Working-Counter setzen + cmd->working_counter = ((master->rx_data[length + 2 + 10] & 0xFF) + | ((master->rx_data[length + 2 + 11] & 0xFF) << 8)); + } + else + { + EC_DBG(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n"); + EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); + output_debug_data(master->tx_data, master->tx_data_length); + EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); + output_debug_data(master->rx_data, rx_data_length); + } + + master->dev->state = ECAT_DS_READY; + + return 0; +} + +/***************************************************************/ + /** Überprüft die angeschlossenen Slaves. @@ -394,944 +590,6 @@ int EtherCAT_read_slave_information(EtherCAT_master_t *master, return 0; } -#if 0 -/***************************************************************/ - -/** - Führt ein asynchrones Senden und Empfangen aus. - - Sendet alle wartenden Kommandos und wartet auf die - entsprechenden Antworten. - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_async_send_receive(EtherCAT_master_t *master) -{ - unsigned int wait_cycles; - int i; - - // Send all commands - - for (i = 0; i < ECAT_NUM_RETRIES; i++) - { - if (EtherCAT_send(master) < 0) - { - return -1; - } - - // Wait until something is received or an error has occurred - - wait_cycles = 10; - EtherCAT_device_call_isr(master->dev); - - while (master->dev->state == ECAT_DS_SENT && wait_cycles) - { - udelay(1000); - wait_cycles--; - EtherCAT_device_call_isr(master->dev); - } - - //EC_DBG("Master async send: tries %d",tries_left); - - if (!wait_cycles) - { - EC_DBG(KERN_ERR "EtherCAT: Asynchronous receive timeout.\n"); - continue; - } - - if (master->dev->state != ECAT_DS_RECEIVED) - { - EC_DBG(KERN_ERR "EtherCAT: Asyncronous send error. State %i\n", master->dev->state); - continue; - } - - // Receive all commands - if (EtherCAT_receive(master) < 0) - { - // Noch mal versuchen - master->dev->state = ECAT_DS_READY; - EC_DBG("Retry Asynchronous send/recieve: %d", i); - continue; - } - - return 0; // Erfolgreich - } - - return -1; -} - -/***************************************************************/ - -/** - Sendet alle wartenden Kommandos. - - Errechnet erst die benötigte Gesamt-Rahmenlänge, und erstellt - dann alle Kommando-Bytefolgen im statischen Sendespeicher. - Danach wird die Sendefunktion des EtherCAT-Gerätes aufgerufen. - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_send(EtherCAT_master_t *master) -{ - unsigned int i, length, framelength, pos; - EtherCAT_command_t *cmd; - int cmdcnt = 0; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "EtherCAT_send, first_command = %X\n", (int) master->first_command); - } - - length = 0; - for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) - { - if (cmd->state != ECAT_CS_READY) continue; - length += cmd->data_length + 12; - cmdcnt++; - } - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "%i commands to send.\n", cmdcnt); - } - - if (length == 0) - { - EC_DBG(KERN_WARNING "EtherCAT: Nothing to send...\n"); - return 0; - } - - framelength = length + 2; - if (framelength < 46) framelength = 46; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "framelength: %i\n", framelength); - } - - master->tx_data[0] = length & 0xFF; - master->tx_data[1] = ((length & 0x700) >> 8) | 0x10; - pos = 2; - - for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) - { - if (cmd->state != ECAT_CS_READY) continue; - - cmd->index = master->command_index; - master->command_index = (master->command_index + 1) % 0x0100; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "Sending command index %i\n", cmd->index); - } - - cmd->state = ECAT_CS_SENT; - - master->tx_data[pos + 0] = cmd->type; - master->tx_data[pos + 1] = cmd->index; - - master->tx_data[pos + 2] = cmd->address.raw[0]; - master->tx_data[pos + 3] = cmd->address.raw[1]; - master->tx_data[pos + 4] = cmd->address.raw[2]; - master->tx_data[pos + 5] = cmd->address.raw[3]; - - master->tx_data[pos + 6] = cmd->data_length & 0xFF; - master->tx_data[pos + 7] = (cmd->data_length & 0x700) >> 8; - - if (cmd->next) master->tx_data[pos + 7] |= 0x80; - - master->tx_data[pos + 8] = 0x00; - master->tx_data[pos + 9] = 0x00; - - if (cmd->type == ECAT_CMD_APWR - || cmd->type == ECAT_CMD_NPWR - || cmd->type == ECAT_CMD_BWR - || cmd->type == ECAT_CMD_LRW) // Write - { - for (i = 0; i < cmd->data_length; i++) master->tx_data[pos + 10 + i] = cmd->data[i]; - } - else // Read - { - for (i = 0; i < cmd->data_length; i++) master->tx_data[pos + 10 + i] = 0x00; - } - - master->tx_data[pos + 10 + cmd->data_length] = 0x00; - master->tx_data[pos + 11 + cmd->data_length] = 0x00; - - pos += 12 + cmd->data_length; - } - - // Pad with zeros - while (pos < 46) master->tx_data[pos++] = 0x00; - - master->tx_data_length = framelength; - -#ifdef DEBUG_SEND_RECEIVE - EC_DBG(KERN_DEBUG "\n"); - EC_DBG(KERN_DEBUG ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"); - EC_DBG(KERN_DEBUG); - for (i = 0; i < framelength; i++) - { - EC_DBG("%02X ", master->tx_data[i]); - - if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG); - } - EC_DBG("\n"); - EC_DBG(KERN_DEBUG "-----------------------------------------------\n"); -#endif - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "device send...\n"); - } - - // Send frame - if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0) - { - EC_DBG(KERN_ERR "EtherCAT: Could not send!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, framelength); - return -1; - } - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "EtherCAT_send done.\n"); - } - - return 0; -} - -/***************************************************************/ - -/** - Holt alle empfangenen Kommandos vom EtherCAT-Gerät. - - Kopiert einen empfangenen Rahmen vom EtherCAT-Gerät - in den Statischen Empfangsspeicher und ordnet dann - allen gesendeten Kommandos ihre Antworten zu. - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_receive(EtherCAT_master_t *master) -{ - EtherCAT_command_t *cmd; - unsigned int length, pos, found, rx_data_length; - unsigned int command_follows, command_type, command_index; - - // Copy received data into master buffer (with locking) - rx_data_length = EtherCAT_device_receive(master->dev, master->rx_data, - ECAT_FRAME_BUFFER_SIZE); - -#ifdef DEBUG_SEND_RECEIVE - for (i = 0; i < rx_data_length; i++) - { - if (master->rx_data[i] == master->tx_data[i]) EC_DBG(" "); - else EC_DBG("%02X ", master->rx_data[i]); - if ((i + 1) % 16 == 0) EC_DBG("\n" KERN_DEBUG); - } - EC_DBG("\n"); - EC_DBG(KERN_DEBUG "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); - EC_DBG(KERN_DEBUG "\n"); -#endif - - if (rx_data_length < 2) - { - EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (illegal length)!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - // Länge des gesamten Frames prüfen - length = ((master->rx_data[1] & 0x07) << 8) | (master->rx_data[0] & 0xFF); - - if (length > rx_data_length) - { - EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (length does not match)!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - pos = 2; // LibPCAP: 16 - command_follows = 1; - while (command_follows) - { - if (pos + 10 > rx_data_length) - { - EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command header!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - command_type = master->rx_data[pos]; - command_index = master->rx_data[pos + 1]; - length = (master->rx_data[pos + 6] & 0xFF) - | ((master->rx_data[pos + 7] & 0x07) << 8); - command_follows = master->rx_data[pos + 7] & 0x80; - - if (pos + length + 12 > rx_data_length) - { - EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command data!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - found = 0; - - for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) - { - if (cmd->state == ECAT_CS_SENT - && cmd->type == command_type - && cmd->index == command_index - && cmd->data_length == length) - { - found = 1; - cmd->state = ECAT_CS_RECEIVED; - - // Empfangene Daten in Kommandodatenspeicher kopieren - memcpy(cmd->data, master->rx_data + pos + 10, length); - - // Working-Counter setzen - cmd->working_counter = (master->rx_data[pos + length + 10] & 0xFF) - | ((master->rx_data[pos + length + 11] & 0xFF) << 8); - } - } - - if (!found) - { - EC_DBG(KERN_WARNING "EtherCAT: WARNING - Command not assigned!\n"); - } - - pos += length + 12; - } - - for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) - { - if (cmd->state == ECAT_CS_SENT) - { - EC_DBG(KERN_WARNING "EtherCAT: WARNING - One command received no response!\n"); - } - } - - master->dev->state = ECAT_DS_READY; - - return 0; -} -#endif - -/***************************************************************/ - -/** - Sendet ein einzelnes Kommando in einem Frame und - wartet auf dessen Empfang. - - @param master EtherCAT-Master - @param cmd Kommando zum Senden/Empfangen - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_simple_send_receive(EtherCAT_master_t *master, - EtherCAT_command_t *cmd) -{ - unsigned int tries_left; - - if (EtherCAT_simple_send(master, cmd) < 0) return -1; - - tries_left = 100; - while (cmd->state == ECAT_CS_SENT && tries_left) - { - udelay(10); - EtherCAT_device_call_isr(master->dev); - tries_left--; - } - - if (EtherCAT_simple_receive(master, cmd) < 0) return -1; - - return 0; -} - -/***************************************************************/ - -/** - Sendet ein einzelnes Kommando in einem Frame. - - @param master EtherCAT-Master - @param cmd Kommando zum Senden - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_simple_send(EtherCAT_master_t *master, - EtherCAT_command_t *cmd) -{ - unsigned int length, framelength, i; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "EtherCAT_send_receive_command\n"); - } - - if (cmd->state != ECAT_CS_READY) - { - EC_DBG(KERN_WARNING "EtherCAT_send_receive_command: Command not in ready state!\n"); - } - - length = cmd->data_length + 12; - framelength = length + 2; - if (framelength < 46) framelength = 46; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "Frame length: %i\n", framelength); - } - - master->tx_data[0] = length & 0xFF; - master->tx_data[1] = ((length & 0x700) >> 8) | 0x10; - - cmd->index = master->command_index; - master->command_index = (master->command_index + 1) % 0x0100; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "Sending command index %i\n", cmd->index); - } - - cmd->state = ECAT_CS_SENT; - - master->tx_data[2 + 0] = cmd->type; - master->tx_data[2 + 1] = cmd->index; - master->tx_data[2 + 2] = cmd->address.raw[0]; - master->tx_data[2 + 3] = cmd->address.raw[1]; - master->tx_data[2 + 4] = cmd->address.raw[2]; - master->tx_data[2 + 5] = cmd->address.raw[3]; - master->tx_data[2 + 6] = cmd->data_length & 0xFF; - master->tx_data[2 + 7] = (cmd->data_length & 0x700) >> 8; - master->tx_data[2 + 8] = 0x00; - master->tx_data[2 + 9] = 0x00; - - if (cmd->type == ECAT_CMD_APWR - || cmd->type == ECAT_CMD_NPWR - || cmd->type == ECAT_CMD_BWR - || cmd->type == ECAT_CMD_LRW) // Write - { - for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = cmd->data[i]; - } - else // Read - { - for (i = 0; i < cmd->data_length; i++) master->tx_data[2 + 10 + i] = 0x00; - } - - master->tx_data[2 + 10 + cmd->data_length] = 0x00; - master->tx_data[2 + 11 + cmd->data_length] = 0x00; - - // Pad with zeros - for (i = cmd->data_length + 12 + 2; i < 46; i++) master->tx_data[i] = 0x00; - - master->tx_data_length = framelength; - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "device send...\n"); - } - - // Send frame - if (EtherCAT_device_send(master->dev, master->tx_data, framelength) != 0) - { - EC_DBG(KERN_ERR "EtherCAT: Could not send!\n"); - return -1; - } - - if (master->debug_level > 0) - { - EC_DBG(KERN_DEBUG "EtherCAT_send done.\n"); - } - - return 0; -} - -/***************************************************************/ - -/** - Wartet auf den Empfang eines einzeln gesendeten - Kommandos. - - @param master EtherCAT-Master - @param cmd Gesendetes Kommando - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_simple_receive(EtherCAT_master_t *master, - EtherCAT_command_t *cmd) -{ - unsigned int rx_data_length, length; - unsigned char command_type, command_index; - - rx_data_length = EtherCAT_device_receive(master->dev, master->rx_data, - ECAT_FRAME_BUFFER_SIZE); - - if (rx_data_length < 2) - { - EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete EtherCAT header!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - // Länge des gesamten Frames prüfen - length = ((master->rx_data[1] & 0x07) << 8) | (master->rx_data[0] & 0xFF); - - if (length > rx_data_length) - { - EC_DBG(KERN_ERR "EtherCAT: Received corrupted frame (length does not match)!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - command_type = master->rx_data[2]; - command_index = master->rx_data[2 + 1]; - length = (master->rx_data[2 + 6] & 0xFF) | ((master->rx_data[2 + 7] & 0x07) << 8); - - if (rx_data_length - 2 < length + 12) - { - EC_DBG(KERN_ERR "EtherCAT: Received frame with incomplete command data!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - return -1; - } - - if (cmd->state == ECAT_CS_SENT - && cmd->type == command_type - && cmd->index == command_index - && cmd->data_length == length) - { - cmd->state = ECAT_CS_RECEIVED; - - // Empfangene Daten in Kommandodatenspeicher kopieren - memcpy(cmd->data, master->rx_data + 2 + 10, length); - - // Working-Counter setzen - cmd->working_counter = ((master->rx_data[length + 2 + 10] & 0xFF) - | ((master->rx_data[length + 2 + 11] & 0xFF) << 8)); - } - else - { - EC_DBG(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n"); - EC_DBG(KERN_DEBUG "EtherCAT: tx_data content:\n"); - output_debug_data(master->tx_data, master->tx_data_length); - EC_DBG(KERN_DEBUG "EtherCAT: rx_data content:\n"); - output_debug_data(master->rx_data, rx_data_length); - } - - master->dev->state = ECAT_DS_READY; - - return 0; -} - -/***************************************************************/ - -#if 0 - -#define ECAT_FUNC_HEADER \ - EtherCAT_command_t *cmd; \ - if ((cmd = alloc_cmd(master)) == NULL) \ - { \ - EC_DBG(KERN_ERR "EtherCAT: Out of memory while creating command!\n"); \ - return NULL; \ - } \ - EtherCAT_command_init(cmd) - -#define ECAT_FUNC_WRITE_FOOTER \ - cmd->data_length = length; \ - memcpy(cmd->data, data, length); \ - if (add_command(master, cmd) < 0) return NULL; \ - return cmd - -#define ECAT_FUNC_READ_FOOTER \ - cmd->data_length = length; \ - if (add_command(master, cmd) < 0) return NULL; \ - return cmd - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-NPRD-Kommando. - - Alloziert ein "node-adressed physical read"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param node_address Adresse des Knotens (Slaves) - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu lesenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_read(EtherCAT_master_t *master, - unsigned short node_address, - unsigned short offset, - unsigned int length) -{ - if (node_address == 0x0000) - EC_DBG(KERN_WARNING "EtherCAT: Using node address 0x0000!\n"); - - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_NPRD; - cmd->address.phy.dev.node = node_address; - cmd->address.phy.mem = offset; - - ECAT_FUNC_READ_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-NPWR-Kommando. - - Alloziert ein "node-adressed physical write"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param node_address Adresse des Knotens (Slaves) - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu schreibenden Daten - @param data Zeiger auf Speicher mit zu schreibenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_write(EtherCAT_master_t *master, - unsigned short node_address, - unsigned short offset, - unsigned int length, - const unsigned char *data) -{ - if (node_address == 0x0000) - EC_DBG(KERN_WARNING "WARNING: Using node address 0x0000!\n"); - - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_NPWR; - cmd->address.phy.dev.node = node_address; - cmd->address.phy.mem = offset; - - ECAT_FUNC_WRITE_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-APRD-Kommando. - - Alloziert ein "autoincerement physical read"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param ring_position (Negative) Position des Slaves im Bus - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu lesenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_position_read(EtherCAT_master_t *master, - short ring_position, - unsigned short offset, - unsigned int length) -{ - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_APRD; - cmd->address.phy.dev.pos = ring_position; - cmd->address.phy.mem = offset; - - ECAT_FUNC_READ_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-APWR-Kommando. - - Alloziert ein "autoincrement physical write"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param ring_position (Negative) Position des Slaves im Bus - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu schreibenden Daten - @param data Zeiger auf Speicher mit zu schreibenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_position_write(EtherCAT_master_t *master, - short ring_position, - unsigned short offset, - unsigned int length, - const unsigned char *data) -{ - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_APWR; - cmd->address.phy.dev.pos = ring_position; - cmd->address.phy.mem = offset; - - ECAT_FUNC_WRITE_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-BRD-Kommando. - - Alloziert ein "broadcast read"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu lesenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_broadcast_read(EtherCAT_master_t *master, - unsigned short offset, - unsigned int length) -{ - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_BRD; - cmd->address.phy.dev.node = 0x0000; - cmd->address.phy.mem = offset; - - ECAT_FUNC_READ_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-BWR-Kommando. - - Alloziert ein "broadcast write"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param offset Physikalische Speicheradresse im Slave - @param length Länge der zu schreibenden Daten - @param data Zeiger auf Speicher mit zu schreibenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_broadcast_write(EtherCAT_master_t *master, - unsigned short offset, - unsigned int length, - const unsigned char *data) -{ - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_BWR; - cmd->address.phy.dev.node = 0x0000; - cmd->address.phy.mem = offset; - - ECAT_FUNC_WRITE_FOOTER; -} - -/***************************************************************/ - -/** - Erstellt ein EtherCAT-LRW-Kommando. - - Alloziert ein "logical read write"-Kommando - und fügt es in die Liste des Masters ein. - - @param master EtherCAT-Master - @param offset Logische Speicheradresse - @param length Länge der zu lesenden/schreibenden Daten - @param data Zeiger auf Speicher mit zu lesenden/schreibenden Daten - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *EtherCAT_logical_read_write(EtherCAT_master_t *master, - unsigned int offset, - unsigned int length, - unsigned char *data) -{ - ECAT_FUNC_HEADER; - - cmd->type = ECAT_CMD_LRW; - cmd->address.logical = offset; - - ECAT_FUNC_WRITE_FOOTER; -} - -/***************************************************************/ - -/** - Alloziert ein neues Kommando aus dem Kommandoring. - - Durchsucht den Kommandoring nach einem freien Kommando, - reserviert es und gibt dessen Adresse zurück. - - @param master EtherCAT-Master - - @return Adresse des Kommandos bei Erfolg, sonst NULL -*/ - -EtherCAT_command_t *alloc_cmd(EtherCAT_master_t *master) -{ - int j; - - for (j = 0; j < ECAT_COMMAND_RING_SIZE; j++) // Einmal rum suchen - { - // Solange suchen, bis freies Kommando gefunden - if (master->cmd_reserved[master->cmd_ring_index] == 0) - { - master->cmd_reserved[master->cmd_ring_index] = 1; // Belegen - - if (master->debug_level) - { - EC_DBG(KERN_DEBUG "Allocating command %i (addr %X).\n", - master->cmd_ring_index, - (int) &master->cmd_ring[master->cmd_ring_index]); - } - - return &master->cmd_ring[master->cmd_ring_index]; - } - - if (master->debug_level) - { - EC_DBG(KERN_DEBUG "Command %i (addr %X) is reserved...\n", - master->cmd_ring_index, - (int) &master->cmd_ring[master->cmd_ring_index]); - } - - master->cmd_ring_index++; - master->cmd_ring_index %= ECAT_COMMAND_RING_SIZE; - } - - EC_DBG(KERN_WARNING "EtherCAT: Command ring full!\n"); - - return NULL; // Nix gefunden -} - -/***************************************************************/ - -/** - Fügt ein Kommando in die Liste des Masters ein. - - @param master EtherCAT-Master - @param cmd Zeiger auf das einzufügende Kommando -*/ - -int add_command(EtherCAT_master_t *master, - EtherCAT_command_t *new_cmd) -{ - EtherCAT_command_t *cmd, **last_cmd; - - for (cmd = master->first_command; cmd != NULL; cmd = cmd->next) - { - if (cmd == new_cmd) - { - EC_DBG(KERN_WARNING "EtherCAT: Trying to add a command" - " that is already in the list!\n"); - return -1; - } - } - - // Find the address of the last pointer in the list - last_cmd = &(master->first_command); - while (*last_cmd) last_cmd = &(*last_cmd)->next; - - // Let this pointer point to the new command - *last_cmd = new_cmd; - - return 0; -} - -/***************************************************************/ - -/** - Entfernt ein Kommando aus der Liste und gibt es frei. - - Prüft erst, ob das Kommando in der Liste des Masters - ist. Wenn ja, wird es entfernt und die Reservierung wird - aufgehoben. - - @param master EtherCAT-Master - @param rem_cmd Zeiger auf das zu entfernende Kommando - - @return 0 bei Erfolg, sonst < 0 -*/ - -void EtherCAT_remove_command(EtherCAT_master_t *master, - EtherCAT_command_t *rem_cmd) -{ - EtherCAT_command_t **last_cmd; - int i; - - last_cmd = &master->first_command; - while (*last_cmd) - { - if (*last_cmd == rem_cmd) - { - *last_cmd = rem_cmd->next; - EtherCAT_command_clear(rem_cmd); - - // Reservierung des Kommandos aufheben - for (i = 0; i < ECAT_COMMAND_RING_SIZE; i++) - { - if (&master->cmd_ring[i] == rem_cmd) - { - master->cmd_reserved[i] = 0; - return; - } - } - - EC_DBG(KERN_WARNING "EtherCAT: Could not remove command reservation!\n"); - return; - } - - last_cmd = &(*last_cmd)->next; - } - - EC_DBG(KERN_WARNING "EtherCAT: Trying to remove non-existent command!\n"); -} -#endif - /***************************************************************/ /** diff --git a/drivers/ec_master.h b/drivers/ec_master.h index edee987c..3b65a9db 100644 --- a/drivers/ec_master.h +++ b/drivers/ec_master.h @@ -31,10 +31,6 @@ typedef struct mit Slave-Informationen */ unsigned int slave_count; /**< Anzahl der Slaves in slaves */ -#if 0 - EtherCAT_command_t *first_command; /**< Zeiger auf das erste - Kommando in der Liste */ -#endif EtherCAT_command_t process_data_command; /**< Kommando zum Senden und Empfangen der Prozessdaten */ @@ -52,12 +48,6 @@ typedef struct unsigned char *process_data; /**< Zeiger auf Speicher mit Prozessdaten */ unsigned int process_data_length; /**< Länge der Prozessdaten */ -#if 0 - EtherCAT_command_t cmd_ring[ECAT_COMMAND_RING_SIZE]; /**< Statischer Kommandoring */ - int cmd_reserved[ECAT_COMMAND_RING_SIZE]; /**< Reservierungsflags für die Kommandos */ - unsigned int cmd_ring_index; /**< Index des nächsten Kommandos im Ring */ -#endif - int debug_level; /**< Debug-Level im Master-Code */ } EtherCAT_master_t; @@ -68,81 +58,30 @@ EtherCAT_master_t; int EtherCAT_master_init(EtherCAT_master_t *, EtherCAT_device_t *); void EtherCAT_master_clear(EtherCAT_master_t *); -// Slave management -int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *, unsigned int); -void EtherCAT_clear_slaves(EtherCAT_master_t *); -int EtherCAT_activate_slave(EtherCAT_master_t *, EtherCAT_slave_t *); -int EtherCAT_deactivate_slave(EtherCAT_master_t *, EtherCAT_slave_t *); -int EtherCAT_activate_all_slaves(EtherCAT_master_t *); -int EtherCAT_deactivate_all_slaves(EtherCAT_master_t *); - // Sending and receiving -#if 0 -int EtherCAT_async_send_receive(EtherCAT_master_t *); -int EtherCAT_send(EtherCAT_master_t *); -int EtherCAT_receive(EtherCAT_master_t *); -#endif int EtherCAT_simple_send_receive(EtherCAT_master_t *, EtherCAT_command_t *); int EtherCAT_simple_send(EtherCAT_master_t *, EtherCAT_command_t *); int EtherCAT_simple_receive(EtherCAT_master_t *, EtherCAT_command_t *); -int EtherCAT_write_process_data(EtherCAT_master_t *); -int EtherCAT_read_process_data(EtherCAT_master_t *); -void EtherCAT_clear_process_data(EtherCAT_master_t *); - -/***************************************************************/ - -// Slave information interface +// Slave management +int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *, unsigned int); +void EtherCAT_clear_slaves(EtherCAT_master_t *); int EtherCAT_read_slave_information(EtherCAT_master_t *, unsigned short int, unsigned short int, unsigned int *); - -// EtherCAT commands -#if 0 -EtherCAT_command_t *EtherCAT_read(EtherCAT_master_t *, - unsigned short, - unsigned short, - unsigned int); -EtherCAT_command_t *EtherCAT_write(EtherCAT_master_t *, - unsigned short, - unsigned short, - unsigned int, - const unsigned char *); -EtherCAT_command_t *EtherCAT_position_read(EtherCAT_master_t *, - short, - unsigned short, - unsigned int); -EtherCAT_command_t *EtherCAT_position_write(EtherCAT_master_t *, - short, - unsigned short, - unsigned int, - const unsigned char *); -EtherCAT_command_t *EtherCAT_broadcast_read(EtherCAT_master_t *, - unsigned short, - unsigned int); -EtherCAT_command_t *EtherCAT_broadcast_write(EtherCAT_master_t *, - unsigned short, - unsigned int, - const unsigned char *); -EtherCAT_command_t *EtherCAT_logical_read_write(EtherCAT_master_t *, - unsigned int, - unsigned int, - unsigned char *); - -void EtherCAT_remove_command(EtherCAT_master_t *, EtherCAT_command_t *); -#endif - -// Slave states +int EtherCAT_activate_slave(EtherCAT_master_t *, EtherCAT_slave_t *); +int EtherCAT_deactivate_slave(EtherCAT_master_t *, EtherCAT_slave_t *); +int EtherCAT_activate_all_slaves(EtherCAT_master_t *); +int EtherCAT_deactivate_all_slaves(EtherCAT_master_t *); int EtherCAT_state_change(EtherCAT_master_t *, EtherCAT_slave_t *, unsigned char); -/***************************************************************/ +// Process data +int EtherCAT_write_process_data(EtherCAT_master_t *); +int EtherCAT_read_process_data(EtherCAT_master_t *); +void EtherCAT_clear_process_data(EtherCAT_master_t *); // Private functions -#if 0 -EtherCAT_command_t *alloc_cmd(EtherCAT_master_t *); -int add_command(EtherCAT_master_t *, EtherCAT_command_t *); -#endif void set_byte(unsigned char *, unsigned int, unsigned char); void set_word(unsigned char *, unsigned int, unsigned int); void output_debug_data(unsigned char *, unsigned int); diff --git a/drivers/ec_types.c b/drivers/ec_types.c index 5db77407..9729c952 100644 --- a/drivers/ec_types.c +++ b/drivers/ec_types.c @@ -143,7 +143,7 @@ EtherCAT_slave_desc_t Beckhoff_EL5001[] = unsigned int slave_idents_count = 7; -struct slave_ident slave_idents[] = +struct slave_ident slave_idents[] = { {0x00000002, 0x03F63052, Beckhoff_EL1014}, {0x00000002, 0x044C2C52, Beckhoff_EK1100}, -- GitLab