fp@73: /****************************************************************************** fp@73: * fp@73: * f r a m e . c fp@73: * fp@73: * Methoden für einen EtherCAT-Frame. fp@73: * fp@73: * $Id$ fp@73: * fp@73: *****************************************************************************/ fp@73: fp@73: #include fp@73: #include fp@73: fp@73: #include "frame.h" fp@73: #include "master.h" fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: #define EC_FUNC_HEADER \ fp@73: frame->master = master; \ fp@73: frame->state = ec_frame_ready; \ fp@73: frame->index = 0; \ fp@73: frame->working_counter = 0; fp@73: fp@73: #define EC_FUNC_WRITE_FOOTER \ fp@73: frame->data_length = length; \ fp@73: memcpy(frame->data, data, length); fp@73: fp@73: #define EC_FUNC_READ_FOOTER \ fp@73: frame->data_length = length; fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-NPRD-Kommando. fp@73: fp@73: Node-adressed physical read. fp@73: */ fp@73: fp@73: void ec_frame_init_nprd(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t node_address, fp@73: /**< Adresse des Knotens (Slaves) */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length fp@73: /**< Länge der zu lesenden Daten */ fp@73: ) fp@73: { fp@73: if (unlikely(node_address == 0x0000)) fp@73: printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n"); fp@73: fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_nprd; fp@73: frame->address.physical.slave = node_address; fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_READ_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-NPWR-Kommando. fp@73: fp@73: Node-adressed physical write. fp@73: */ fp@73: fp@73: void ec_frame_init_npwr(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t node_address, fp@73: /**< Adresse des Knotens (Slaves) */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length, fp@73: /**< Länge der zu schreibenden Daten */ fp@73: const uint8_t *data fp@73: /**< Zeiger auf Speicher mit zu schreibenden Daten */ fp@73: ) fp@73: { fp@73: if (unlikely(node_address == 0x0000)) fp@73: printk(KERN_WARNING "EtherCAT: Warning - Using node address 0x0000!\n"); fp@73: fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_npwr; fp@73: frame->address.physical.slave = node_address; fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_WRITE_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-APRD-Kommando. fp@73: fp@73: Autoincrement physical read. fp@73: */ fp@73: fp@73: void ec_frame_init_aprd(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t ring_position, fp@73: /**< Position des Slaves im Bus */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length fp@73: /**< Länge der zu lesenden Daten */ fp@73: ) fp@73: { fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_aprd; fp@73: frame->address.physical.slave = (int16_t) ring_position * (-1); fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_READ_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-APWR-Kommando. fp@73: fp@73: Autoincrement physical write. fp@73: */ fp@73: fp@73: void ec_frame_init_apwr(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t ring_position, fp@73: /**< Position des Slaves im Bus */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length, fp@73: /**< Länge der zu schreibenden Daten */ fp@73: const uint8_t *data fp@73: /**< Zeiger auf Speicher mit zu schreibenden Daten */ fp@73: ) fp@73: { fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_apwr; fp@73: frame->address.physical.slave = (int16_t) ring_position * (-1); fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_WRITE_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-BRD-Kommando. fp@73: fp@73: Broadcast read. fp@73: */ fp@73: fp@73: void ec_frame_init_brd(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length fp@73: /**< Länge der zu lesenden Daten */ fp@73: ) fp@73: { fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_brd; fp@73: frame->address.physical.slave = 0x0000; fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_READ_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-BWR-Kommando. fp@73: fp@73: Broadcast write. fp@73: */ fp@73: fp@73: void ec_frame_init_bwr(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint16_t offset, fp@73: /**< Physikalische Speicheradresse im Slave */ fp@73: unsigned int length, fp@73: /**< Länge der zu schreibenden Daten */ fp@73: const uint8_t *data fp@73: /**< Zeiger auf Speicher mit zu schreibenden Daten */ fp@73: ) fp@73: { fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_bwr; fp@73: frame->address.physical.slave = 0x0000; fp@73: frame->address.physical.mem = offset; fp@73: fp@73: EC_FUNC_WRITE_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Initialisiert ein EtherCAT-LRW-Kommando. fp@73: fp@73: Logical read write. fp@73: */ fp@73: fp@73: void ec_frame_init_lrw(ec_frame_t *frame, fp@73: /**< EtherCAT-Rahmen */ fp@73: ec_master_t *master, fp@73: /**< EtherCAT-Master */ fp@73: uint32_t offset, fp@73: /**< Logische Startadresse */ fp@73: unsigned int length, fp@73: /**< Länge der zu lesenden/schreibenden Daten */ fp@73: uint8_t *data fp@73: /**< Zeiger auf die Daten */ fp@73: ) fp@73: { fp@73: EC_FUNC_HEADER; fp@73: fp@73: frame->type = ec_frame_type_lrw; fp@73: frame->address.logical = offset; fp@73: fp@73: EC_FUNC_WRITE_FOOTER; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Sendet einen einzelnen EtherCAT-Rahmen. fp@73: fp@73: \return 0 bei Erfolg, sonst < 0 fp@73: */ fp@73: fp@73: int ec_frame_send(ec_frame_t *frame /**< Rahmen zum Senden */) fp@73: { fp@73: unsigned int command_size, frame_size, i; fp@73: uint8_t *data; fp@73: fp@73: if (unlikely(frame->master->debug_level > 0)) { fp@73: printk(KERN_DEBUG "EtherCAT: ec_frame_send\n"); fp@73: } fp@73: fp@73: if (unlikely(frame->state != ec_frame_ready)) { fp@73: printk(KERN_WARNING "EtherCAT: Frame not in \"ready\" state!\n"); fp@73: } fp@73: fp@73: command_size = frame->data_length + EC_COMMAND_HEADER_SIZE fp@73: + EC_COMMAND_FOOTER_SIZE; fp@73: frame_size = command_size + EC_FRAME_HEADER_SIZE; fp@73: fp@73: if (unlikely(frame_size > EC_MAX_FRAME_SIZE)) { fp@73: printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", frame_size); fp@73: return -1; fp@73: } fp@73: fp@73: if (frame_size < EC_MIN_FRAME_SIZE) frame_size = EC_MIN_FRAME_SIZE; fp@73: fp@73: if (unlikely(frame->master->debug_level > 0)) { fp@73: printk(KERN_DEBUG "EtherCAT: Frame length: %i\n", frame_size); fp@73: } fp@73: fp@73: frame->index = frame->master->command_index; fp@73: frame->master->command_index = (frame->master->command_index + 1) % 0x0100; fp@73: fp@73: if (unlikely(frame->master->debug_level > 0)) { fp@73: printk(KERN_DEBUG "EtherCAT: Sending command index 0x%X\n", fp@73: frame->index); fp@73: } fp@73: fp@73: frame->state = ec_frame_sent; fp@73: fp@73: // Zeiger auf Socket-Buffer holen fp@73: data = ec_device_prepare(&frame->master->device); fp@73: fp@73: // EtherCAT frame header fp@73: data[0] = command_size & 0xFF; fp@73: data[1] = ((command_size & 0x700) >> 8) | 0x10; fp@73: data += EC_FRAME_HEADER_SIZE; fp@73: fp@73: // EtherCAT command header fp@73: data[0] = frame->type; fp@73: data[1] = frame->index; fp@73: data[2] = frame->address.raw[0]; fp@73: data[3] = frame->address.raw[1]; fp@73: data[4] = frame->address.raw[2]; fp@73: data[5] = frame->address.raw[3]; fp@73: data[6] = frame->data_length & 0xFF; fp@73: data[7] = (frame->data_length & 0x700) >> 8; fp@73: data[8] = 0x00; fp@73: data[9] = 0x00; fp@73: data += EC_COMMAND_HEADER_SIZE; fp@73: fp@73: if (likely(frame->type == ec_frame_type_apwr // Write commands fp@73: || frame->type == ec_frame_type_npwr fp@73: || frame->type == ec_frame_type_bwr fp@73: || frame->type == ec_frame_type_lrw)) { fp@73: memcpy(data, frame->data, frame->data_length); fp@73: } fp@73: else { // Read commands fp@73: memset(data, 0x00, frame->data_length); fp@73: } fp@73: fp@73: // EtherCAT command footer fp@73: data += frame->data_length; fp@73: data[0] = frame->working_counter & 0xFF; fp@73: data[1] = (frame->working_counter & 0xFF00) >> 8; fp@73: data += EC_COMMAND_FOOTER_SIZE; fp@73: fp@73: // Pad with zeros fp@73: for (i = EC_FRAME_HEADER_SIZE + EC_COMMAND_HEADER_SIZE fp@73: + frame->data_length + EC_COMMAND_FOOTER_SIZE; fp@73: i < EC_MIN_FRAME_SIZE; i++) { fp@73: *data++ = 0x00; fp@73: } fp@73: fp@73: // Send frame fp@73: ec_device_send(&frame->master->device, frame_size); fp@73: fp@73: return 0; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Empfängt einen gesendeten Rahmen. fp@73: fp@73: \return 0 bei Erfolg, sonst < 0 fp@73: */ fp@73: fp@73: int ec_frame_receive(ec_frame_t *frame /**< Gesendeter Rahmen */) fp@73: { fp@73: unsigned int received_length, frame_length, data_length; fp@73: uint8_t *data; fp@73: uint8_t command_type, command_index; fp@73: ec_device_t *device; fp@73: fp@73: if (unlikely(frame->state != ec_frame_sent)) { fp@73: printk(KERN_ERR "EtherCAT: Frame was not sent!\n"); fp@73: return -1; fp@73: } fp@73: fp@73: device = &frame->master->device; fp@73: fp@73: if (!(received_length = ec_device_received(device))) return -1; fp@73: fp@73: device->state = EC_DEVICE_STATE_READY; fp@73: fp@73: if (unlikely(received_length < EC_FRAME_HEADER_SIZE)) { fp@73: printk(KERN_ERR "EtherCAT: Received frame with incomplete EtherCAT" fp@73: " frame header!\n"); fp@73: ec_frame_print(frame); fp@73: return -1; fp@73: } fp@73: fp@73: data = ec_device_data(device); fp@73: fp@73: // Länge des gesamten Frames prüfen fp@73: frame_length = (data[0] & 0xFF) | ((data[1] & 0x07) << 8); fp@73: fp@73: if (unlikely(frame_length > received_length)) { fp@73: printk(KERN_ERR "EtherCAT: Received corrupted frame (length does" fp@73: " not match)!\n"); fp@73: ec_frame_print(frame); fp@73: return -1; fp@73: } fp@73: fp@73: // Command header fp@73: data += EC_FRAME_HEADER_SIZE; fp@73: command_type = data[0]; fp@73: command_index = data[1]; fp@73: data_length = (data[6] & 0xFF) | ((data[7] & 0x07) << 8); fp@73: fp@73: if (unlikely(EC_FRAME_HEADER_SIZE + EC_COMMAND_HEADER_SIZE fp@73: + data_length + EC_COMMAND_FOOTER_SIZE > received_length)) { fp@73: printk(KERN_ERR "EtherCAT: Received frame with incomplete command" fp@73: " data!\n"); fp@73: ec_frame_print(frame); fp@73: return -1; fp@73: } fp@73: fp@73: if (unlikely(frame->type != command_type fp@73: || frame->index != command_index fp@73: || frame->data_length != data_length)) fp@73: { fp@73: printk(KERN_WARNING "EtherCAT: WARNING - Send/Receive anomaly!\n"); fp@73: ec_frame_print(frame); fp@73: ec_device_call_isr(device); // Empfangenes "vergessen" fp@73: return -1; fp@73: } fp@73: fp@73: frame->state = ec_frame_received; fp@73: fp@73: // Empfangene Daten in Kommandodatenspeicher kopieren fp@73: data += EC_COMMAND_HEADER_SIZE; fp@73: memcpy(frame->data, data, data_length); fp@73: data += data_length; fp@73: fp@73: // Working-Counter setzen fp@73: frame->working_counter = (data[0] & 0xFF) | ((data[1] & 0xFF) << 8); fp@73: fp@73: if (unlikely(frame->master->debug_level > 1)) { fp@73: ec_frame_print(frame); fp@73: } fp@73: fp@73: return 0; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Sendet einen einzeln Rahmen und wartet auf dessen Empfang. fp@73: fp@73: \return 0 bei Erfolg, sonst < 0 fp@73: */ fp@73: fp@73: int ec_frame_send_receive(ec_frame_t *frame fp@73: /**< Rahmen zum Senden/Empfangen */ fp@73: ) fp@73: { fp@73: unsigned int tries_left; fp@73: fp@73: if (unlikely(ec_frame_send(frame) < 0)) { fp@73: printk(KERN_ERR "EtherCAT: Frame sending failed!\n"); fp@73: return -1; fp@73: } fp@73: fp@73: tries_left = 20; fp@73: do fp@73: { fp@73: udelay(1); fp@73: ec_device_call_isr(&frame->master->device); fp@73: tries_left--; fp@73: } fp@73: while (unlikely(!ec_device_received(&frame->master->device) fp@73: && tries_left)); fp@73: fp@73: if (unlikely(!tries_left)) { fp@73: printk(KERN_ERR "EtherCAT: Frame timeout!\n"); fp@73: return -1; fp@73: } fp@73: fp@73: if (unlikely(ec_frame_receive(frame) < 0)) { fp@73: printk(KERN_ERR "EtherCAT: Frame receiving failed!\n"); fp@73: return -1; fp@73: } fp@73: fp@73: return 0; fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /** fp@73: Gibt Frame-Inhalte zwecks Debugging aus. fp@73: */ fp@73: fp@73: void ec_frame_print(const ec_frame_t *frame /**< EtherCAT-Frame */) fp@73: { fp@73: unsigned int i; fp@73: fp@73: printk(KERN_DEBUG "EtherCAT: Frame contents (%i Bytes):\n", fp@73: frame->data_length); fp@73: fp@73: printk(KERN_DEBUG); fp@73: for (i = 0; i < frame->data_length; i++) fp@73: { fp@73: printk("%02X ", frame->data[i]); fp@73: if ((i + 1) % 16 == 0) printk("\n" KERN_DEBUG); fp@73: } fp@73: printk("\n"); fp@73: } fp@73: fp@73: /*****************************************************************************/ fp@73: fp@73: /* Emacs-Konfiguration fp@73: ;;; Local Variables: *** fp@73: ;;; c-basic-offset:4 *** fp@73: ;;; End: *** fp@73: */