# HG changeset patch # User Florian Pose # Date 1136468379 0 # Node ID a22a202d0f42a7953af613f60cac0a5b60b046ad # Parent 42c66194c0c89a2c8198c62a631bdc1db86f473c Domains, Warten beim Senden, 10kHz. diff -r 42c66194c0c8 -r a22a202d0f42 drivers/Makefile --- a/drivers/Makefile Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/Makefile Thu Jan 05 13:39:39 2006 +0000 @@ -18,7 +18,7 @@ 8139too-ecat-objs := 8139too.o ecat-master-objs := ec_module.o ec_master.o ec_device.o ec_slave.o \ - ec_command.o ec_types.o + ec_command.o ec_types.o ec_domain.o REV = `svnversion $(src)` DATE = `date` diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_device.c --- a/drivers/ec_device.c Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_device.c Thu Jan 05 13:39:39 2006 +0000 @@ -131,6 +131,8 @@ int EtherCAT_device_open(EtherCAT_device_t *ecd) { + unsigned int i; + if (!ecd) { printk(KERN_ERR "EtherCAT: Trying to open a NULL device!\n"); return -1; @@ -141,6 +143,9 @@ return -1; } + // Device could have received frames before + for (i = 0; i < 4; i++) EtherCAT_device_call_isr(ecd); + // Reset old device state ecd->state = ECAT_DS_READY; ecd->tx_intr_cnt = 0; @@ -265,7 +270,7 @@ if (unlikely(ecd->rx_data_length > ECAT_FRAME_BUFFER_SIZE)) { if (likely(ecd->error_reported)) { printk(KERN_ERR "EtherCAT: receive - " - " Reveived frame too long (%i Bytes)!\n", + " Reveived frame is too long (%i Bytes)!\n", ecd->rx_data_length); ecd->error_reported = 1; } @@ -284,7 +289,7 @@ /*****************************************************************************/ /** - Ruft manuell die Interrupt-Routine der Netzwerkkarte auf. + Ruft die Interrupt-Routine der Netzwerkkarte auf. @param ecd EtherCAT-Gerät @@ -350,3 +355,9 @@ EXPORT_SYMBOL(EtherCAT_device_close); /*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_domain.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/ec_domain.c Thu Jan 05 13:39:39 2006 +0000 @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * e c _ d o m a i n . c + * + * Methoden für Gruppen von EtherCAT-Slaves. + * + * $Id$ + * + *****************************************************************************/ + +#include + +#include "ec_globals.h" +#include "ec_domain.h" + +/*****************************************************************************/ + +/** + Konstruktor einer EtherCAT-Domäne. + + @param pd Zeiger auf die zu initialisierende Domäne +*/ + +void EtherCAT_domain_init(EtherCAT_domain_t *dom) +{ + dom->number = 0; + dom->data = NULL; + dom->data_size = 0; + dom->logical_offset = 0; +} + +/*****************************************************************************/ + +/** + Destruktor eines Prozessdatenobjekts. + + @param dom Zeiger auf die zu löschenden Prozessdaten +*/ + +void EtherCAT_domain_clear(EtherCAT_domain_t *dom) +{ + if (dom->data) { + kfree(dom->data); + dom->data = NULL; + } + + dom->data_size = 0; +} + +/*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_domain.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/drivers/ec_domain.h Thu Jan 05 13:39:39 2006 +0000 @@ -0,0 +1,51 @@ +/****************************************************************************** + * + * e c _ d o m a i n . h + * + * Struktur für eine Gruppe von EtherCAT-Slaves. + * + * $Id$ + * + *****************************************************************************/ + +#ifndef _EC_DOMAIN_H_ +#define _EC_DOMAIN_H_ + +#include "ec_globals.h" +#include "ec_slave.h" +#include "ec_command.h" + +/*****************************************************************************/ + +/** + EtherCAT-Domäne + + Verwaltet die Prozessdaten und das hierfür nötige Kommando einer bestimmten + Menge von Slaves. +*/ + +typedef struct EtherCAT_domain +{ + unsigned int number; /*<< Domänen-Identifikation */ + EtherCAT_command_t command; /**< Kommando zum Senden und Empfangen der + Prozessdaten */ + unsigned char *data; /**< Zeiger auf Speicher mit Prozessdaten */ + unsigned int data_size; /**< Größe des Prozessdatenspeichers */ + unsigned int logical_offset; /**< Logische Basisaddresse */ +} +EtherCAT_domain_t; + +/*****************************************************************************/ + +void EtherCAT_domain_init(EtherCAT_domain_t *); +void EtherCAT_domain_clear(EtherCAT_domain_t *); + +/*****************************************************************************/ + +#endif + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_globals.h --- a/drivers/ec_globals.h Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_globals.h Thu Jan 05 13:39:39 2006 +0000 @@ -19,6 +19,11 @@ #define ECAT_FRAME_BUFFER_SIZE 1500 /** + Maximale Anzahl der Prozessdatendomänen in einem Master +*/ +#define ECAT_MAX_DOMAINS 10 + +/** NULL-Define, falls noch nicht definiert. */ @@ -69,4 +74,8 @@ /*****************************************************************************/ +typedef struct EtherCAT_master EtherCAT_master_t; + +/*****************************************************************************/ + #endif diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_master.c --- a/drivers/ec_master.c Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_master.c Thu Jan 05 13:39:39 2006 +0000 @@ -22,22 +22,20 @@ /** Konstruktor des EtherCAT-Masters. - @param master Zeiger auf den zu initialisierenden - EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 (= dev ist NULL) + @param master Zeiger auf den zu initialisierenden EtherCAT-Master */ void EtherCAT_master_init(EtherCAT_master_t *master) { - master->slaves = NULL; - master->slave_count = 0; master->dev = NULL; master->command_index = 0x00; master->tx_data_length = 0; - master->process_data = NULL; - master->process_data_length = 0; + master->rx_data_length = 0; + master->domain_count = 0; master->debug_level = 0; + master->tx_time = 0; + master->rx_time = 0; + master->rx_tries = 0; } /*****************************************************************************/ @@ -53,15 +51,14 @@ void EtherCAT_master_clear(EtherCAT_master_t *master) { - // Remove all slaves - EtherCAT_clear_slaves(master); - - if (master->process_data) { - kfree(master->process_data); - master->process_data = NULL; - } - - master->process_data_length = 0; + unsigned int i; + + // Remove domains + for (i = 0; i < master->domain_count; i++) { + EtherCAT_domain_clear(master->domains + i); + } + + master->domain_count = 0; } /*****************************************************************************/ @@ -82,14 +79,12 @@ EtherCAT_device_t *device) { if (!master || !device) { - printk(KERN_ERR "EtherCAT: Illegal parameters" - " for master_open()!\n"); + printk(KERN_ERR "EtherCAT: Illegal parameters for master_open()!\n"); return -1; } if (master->dev) { - printk(KERN_ERR "EtherCAT: Master already" - " has a device.\n"); + printk(KERN_ERR "EtherCAT: Master already has a device.\n"); return -1; } @@ -197,8 +192,7 @@ framelength = length + 2; if (unlikely(framelength > ECAT_FRAME_BUFFER_SIZE)) { - printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", - framelength); + printk(KERN_ERR "EtherCAT: Frame too long (%i)!\n", framelength); return -1; } @@ -256,6 +250,9 @@ printk(KERN_DEBUG "device send...\n"); } + // Zeit nehmen + rdtscl(master->tx_time); + // Send frame if (unlikely(EtherCAT_device_send(master->dev, master->tx_data, @@ -297,8 +294,8 @@ master->rx_data_length = (unsigned int) ret; if (unlikely(master->rx_data_length < 2)) { - printk(KERN_ERR "EtherCAT: Received frame with" - " incomplete EtherCAT header!\n"); + printk(KERN_ERR "EtherCAT: Received frame with incomplete" + " EtherCAT header!\n"); output_debug_data(master); return -1; } @@ -308,8 +305,8 @@ | (master->rx_data[0] & 0xFF); if (unlikely(length > master->rx_data_length)) { - printk(KERN_ERR "EtherCAT: Received corrupted" - " frame (length does not match)!\n"); + printk(KERN_ERR "EtherCAT: Received corrupted frame (length does" + " not match)!\n"); output_debug_data(master); return -1; } @@ -337,8 +334,9 @@ 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)); + cmd->working_counter + = ((master->rx_data[length + 2 + 10] & 0xFF) + | ((master->rx_data[length + 2 + 11] & 0xFF) << 8)); } else { @@ -374,8 +372,17 @@ { EtherCAT_command_t cmd; EtherCAT_slave_t *cur; - unsigned int i, j, found, length, pos; + unsigned int i, j, found, size, offset; unsigned char data[2]; + EtherCAT_domain_t *dom; + + // Clear domains + for (i = 0; i < master->domain_count; i++) { + printk(KERN_DEBUG "EtherCAT: Clearing domain %i!\n", + master->domains[i].number); + EtherCAT_domain_clear(master->domains + i); + } + master->domain_count = 0; if (unlikely(!slave_count)) { printk(KERN_ERR "EtherCAT: No slaves in list!\n"); @@ -394,8 +401,8 @@ cmd.working_counter, slave_count); return -1; } - else - printk("EtherCAT: Found all %i slaves.\n", slave_count); + + printk("EtherCAT: Found all %i slaves.\n", slave_count); // For every slave in the list for (i = 0; i < slave_count; i++) @@ -403,8 +410,7 @@ cur = &slaves[i]; if (unlikely(!cur->desc)) { - printk(KERN_ERR "EtherCAT: Slave %i has" - " no description.\n", i); + printk(KERN_ERR "EtherCAT: Slave %i has no description.\n", i); return -1; } @@ -443,6 +449,7 @@ } // Get base data + cur->type = cmd.data[0]; cur->revision = cmd.data[1]; cur->build = cmd.data[2] | (cmd.data[3] << 8); @@ -515,42 +522,75 @@ cur->vendor_id, cur->product_code, i); return -1; } - } - - length = 0; - for (i = 0; i < slave_count; i++) - { - length += slaves[i].desc->data_length; - } - - if (unlikely((master->process_data = (unsigned char *) - kmalloc(sizeof(unsigned char) - * length, GFP_KERNEL)) == NULL)) { - printk(KERN_ERR "EtherCAT: Could not allocate %i" - " bytes for process data.\n", length); - return -1; - } - - master->process_data_length = length; - memset(master->process_data, 0x00, length); - - pos = 0; - for (i = 0; i < slave_count; i++) - { - slaves[i].process_data = master->process_data + pos; - slaves[i].logical_address0 = pos; - - printk(KERN_DEBUG "EtherCAT: Slave %i -" - " Address 0x%X, \"%s %s\", s/n %u\n", - i, pos, slaves[i].desc->vendor_name, - slaves[i].desc->product_name, - slaves[i].serial_number); - - pos += slaves[i].desc->data_length; - } - - master->slaves = slaves; - master->slave_count = slave_count; + + // Check, if process data domain already exists... + found = 0; + for (j = 0; j < master->domain_count; j++) { + if (cur->domain == master->domains[j].number) { + found = 1; + } + } + + // Create process data domain + if (!found) { + if (master->domain_count + 1 >= ECAT_MAX_DOMAINS) { + printk(KERN_ERR "EtherCAT: Too many domains!\n"); + return -1; + } + + EtherCAT_domain_init(&master->domains[master->domain_count]); + master->domains[master->domain_count].number = cur->domain; + master->domain_count++; + } + } + + // Calculate domain sizes + offset = 0; + for (i = 0; i < master->domain_count; i++) + { + dom = master->domains + i; + + dom->logical_offset = offset; + + // For every slave in the list + size = 0; + for (j = 0; j < slave_count; j++) { + if (slaves[j].domain == dom->number) { + size += slaves[j].desc->process_data_size; + } + } + + if (size > ECAT_FRAME_BUFFER_SIZE - 14) { + printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n", + dom->number, size, ECAT_FRAME_BUFFER_SIZE - 14); + return -1; + } + + if (!(dom->data = (unsigned char *) kmalloc(sizeof(unsigned char) + * size, GFP_KERNEL))) { + printk(KERN_ERR "EtherCAT: Could not allocate" + " %i bytes of domain data.\n", size); + return -1; + } + + dom->data_size = size; + memset(dom->data, 0x00, size); + + printk(KERN_INFO "EtherCAT: Domain %i: %i Bytes of process data.\n", + dom->number, size); + + // Set logical addresses and data pointers of domain slaves + size = 0; + for (j = 0; j < slave_count; j++) { + if (slaves[j].domain == dom->number) { + slaves[j].process_data = dom->data + size; + slaves[j].logical_address = dom->logical_offset + size; + size += slaves[j].desc->process_data_size; + } + } + + offset += size; + } return 0; } @@ -558,20 +598,6 @@ /*****************************************************************************/ /** - Entfernt den Zeiger auf das Slave-Array. - - @param master EtherCAT-Master -*/ - -void EtherCAT_clear_slaves(EtherCAT_master_t *master) -{ - master->slaves = NULL; - master->slave_count = 0; -} - -/*****************************************************************************/ - -/** Liest Daten aus dem Slave-Information-Interface eines EtherCAT-Slaves. @@ -605,12 +631,12 @@ EtherCAT_command_write(&cmd, node_address, 0x502, 6, data); if (unlikely(EtherCAT_simple_send_receive(master, &cmd) < 0)) - return -3; + return -1; if (unlikely(cmd.working_counter != 1)) { - printk(KERN_ERR "EtherCAT: SII-read - Slave" - " %04X did not respond!\n", node_address); - return -4; + printk(KERN_ERR "EtherCAT: SII-read - Slave %04X did not respond!\n", + node_address); + return -1; } // Der Slave legt die Informationen des Slave-Information-Interface @@ -625,12 +651,12 @@ EtherCAT_command_read(&cmd, node_address, 0x502, 10); if (unlikely(EtherCAT_simple_send_receive(master, &cmd) != 0)) - return -3; + return -1; if (unlikely(cmd.working_counter != 1)) { printk(KERN_ERR "EtherCAT: SII-read status -" " Slave %04X did not respond!\n", node_address); - return -4; + return -1; } if (likely((cmd.data[1] & 0x81) == 0)) { @@ -642,8 +668,8 @@ } if (unlikely(!tries_left)) { - printk(KERN_WARNING "EtherCAT: SSI-read." - " Slave %04X timed out!\n", node_address); + printk(KERN_WARNING "EtherCAT: SSI-read. Slave %04X timed out!\n", + node_address); return -1; } @@ -784,7 +810,7 @@ printk(KERN_ERR "EtherCAT: Resetting FMMUs -" " Slave %04X did not respond!\n", slave->station_address); - return -2; + return -1; } // Resetting Sync Manager channels @@ -803,7 +829,7 @@ printk(KERN_ERR "EtherCAT: Resetting SMs -" " Slave %04X did not respond!\n", slave->station_address); - return -2; + return -1; } } @@ -823,7 +849,7 @@ printk(KERN_ERR "EtherCAT: Setting SM0 -" " Slave %04X did not respond!\n", slave->station_address); - return -3; + return -1; } } @@ -839,7 +865,7 @@ printk(KERN_ERR "EtherCAT: Setting SM1 -" " Slave %04X did not respond!\n", slave->station_address); - return -2; + return -1; } } } @@ -848,18 +874,24 @@ if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_PREOP) != 0)) - return -5; + return -1; // Set FMMU's if (desc->fmmu0) { + if (unlikely(!slave->process_data)) { + printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any" + " process data object!\n", slave->station_address); + return -1; + } + memcpy(fmmu, desc->fmmu0, 16); - fmmu[0] = slave->logical_address0 & 0x000000FF; - fmmu[1] = (slave->logical_address0 & 0x0000FF00) >> 8; - fmmu[2] = (slave->logical_address0 & 0x00FF0000) >> 16; - fmmu[3] = (slave->logical_address0 & 0xFF000000) >> 24; + fmmu[0] = slave->logical_address & 0x000000FF; + fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8; + fmmu[2] = (slave->logical_address & 0x00FF0000) >> 16; + fmmu[3] = (slave->logical_address & 0xFF000000) >> 24; EtherCAT_command_write(&cmd, slave->station_address, 0x0600, 16, fmmu); @@ -871,7 +903,7 @@ printk(KERN_ERR "EtherCAT: Setting FMMU0 -" " Slave %04X did not respond!\n", slave->station_address); - return -2; + return -1; } } @@ -891,7 +923,7 @@ printk(KERN_ERR "EtherCAT: Setting SM0 -" " Slave %04X did not respond!\n", slave->station_address); - return -3; + return -1; } } @@ -907,7 +939,7 @@ printk(KERN_ERR "EtherCAT: Setting SM1 -" " Slave %04X did not respond!\n", slave->station_address); - return -3; + return -1; } } } @@ -924,7 +956,7 @@ printk(KERN_ERR "EtherCAT: Setting SM2 -" " Slave %04X did not respond!\n", slave->station_address); - return -3; + return -1; } } @@ -940,19 +972,19 @@ printk(KERN_ERR "EtherCAT: Setting SM3 -" " Slave %04X did not respond!\n", slave->station_address); - return -3; + return -1; } } // Change state to SAVEOP if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_SAVEOP) != 0)) - return -12; + return -1; // Change state to OP if (unlikely(EtherCAT_state_change(master, slave, ECAT_STATE_OP) != 0)) - return -13; + return -1; return 0; } @@ -981,137 +1013,74 @@ /*****************************************************************************/ /** - Aktiviert alle Slaves. - - @see EtherCAT_activate_slave + Sendet und empfängt Prozessdaten der angegebenen Domäne @param master EtherCAT-Master + domain Domäne @return 0 bei Erfolg, sonst < 0 */ -int EtherCAT_activate_all_slaves(EtherCAT_master_t *master) -{ - unsigned int i; - - for (i = 0; i < master->slave_count; i++) - { - if (unlikely(EtherCAT_activate_slave(master, - &master->slaves[i]) < 0)) - return -1; - } - - return 0; -} - -/*****************************************************************************/ - -/** - Deaktiviert alle Slaves. - - @see EtherCAT_deactivate_slave - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_deactivate_all_slaves(EtherCAT_master_t *master) -{ - unsigned int i; - int ret = 0; - - for (i = 0; i < master->slave_count; i++) - { - if (unlikely(EtherCAT_deactivate_slave(master, - &master->slaves[i]) < 0)) - ret = -1; - } - - return ret; -} - -/*****************************************************************************/ - -/** - Sendet alle Prozessdaten an die Slaves. - - Erstellt ein "logical read write"-Kommando mit den - Prozessdaten des Masters und sendet es an den Bus. - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_write_process_data(EtherCAT_master_t *master) -{ - EtherCAT_command_logical_read_write(&master->process_data_command, - 0, master->process_data_length, - master->process_data); - - if (unlikely(EtherCAT_simple_send(master, - &master->process_data_command) < 0)) - { - printk(KERN_ERR "EtherCAT: Could not send" - " process data command!\n"); - return -1; - } - - return 0; -} - -/*****************************************************************************/ - -/** - Empfängt alle Prozessdaten von den Slaves. - - Empfängt ein zuvor gesendetes "logical read write"-Kommando - und kopiert die empfangenen daten in den Prozessdatenspeicher - des Masters. - - @param master EtherCAT-Master - - @return 0 bei Erfolg, sonst < 0 -*/ - -int EtherCAT_read_process_data(EtherCAT_master_t *master) -{ - unsigned int tries_left; - +int EtherCAT_process_data_cycle(EtherCAT_master_t *master, + unsigned int domain) +{ + unsigned int i, tries; + EtherCAT_domain_t *dom = NULL; + + for (i = 0; i < master->domain_count; i++) { + if (master->domains[i].number == domain) { + dom = master->domains + i; + break; + } + } + + if (unlikely(!dom)) { + printk(KERN_ERR "EtherCAT: No such domain: %i!\n", domain); + return -1; + } + + EtherCAT_command_logical_read_write(&dom->command, + dom->logical_offset, dom->data_size, + dom->data); + + if (unlikely(EtherCAT_simple_send(master, &dom->command) < 0)) { + printk(KERN_ERR "EtherCAT: Could not send process data command!\n"); + return -1; + } + + udelay(3); + +#if 1 + // Warten + tries = 0; EtherCAT_device_call_isr(master->dev); - - tries_left = 20; - while (unlikely(master->dev->state == ECAT_DS_SENT - && tries_left)) - { + while (unlikely(master->dev->state == ECAT_DS_SENT && tries < 100)) { udelay(1); EtherCAT_device_call_isr(master->dev); - tries_left--; - } - - if (unlikely(!tries_left)) - { + tries++; + } + + rdtscl(master->rx_time); + master->rx_tries = tries; + + if (unlikely(tries == 100)) { printk(KERN_ERR "EtherCAT: Timeout while receiving process data!\n"); return -1; } - if (unlikely(EtherCAT_simple_receive(master, - &master->process_data_command) < 0)) - { + if (unlikely(EtherCAT_simple_receive(master, &dom->command) < 0)) { printk(KERN_ERR "EtherCAT: Could not receive cyclic command!\n"); return -1; } - if (unlikely(master->process_data_command.state != ECAT_CS_RECEIVED)) - { + if (unlikely(dom->command.state != ECAT_CS_RECEIVED)) { printk(KERN_WARNING "EtherCAT: Process data command not received!\n"); return -1; } - // Daten von Kommando in Prozessdaten des Master kopieren - memcpy(master->process_data, master->process_data_command.data, - master->process_data_length); + // Daten vom Kommando in den Prozessdatenspeicher kopieren + memcpy(dom->data, dom->command.data, dom->data_size); +#endif return 0; } @@ -1119,20 +1088,6 @@ /*****************************************************************************/ /** - Verwirft das zuletzt gesendete Prozessdatenkommando. - - @param master EtherCAT-Master -*/ - -void EtherCAT_clear_process_data(EtherCAT_master_t *master) -{ - EtherCAT_device_call_isr(master->dev); - master->dev->state = ECAT_DS_READY; -} - -/*****************************************************************************/ - -/** Gibt Frame-Inhalte zwecks Debugging aus. @param master EtherCAT-Master @@ -1171,11 +1126,15 @@ EXPORT_SYMBOL(EtherCAT_master_clear); EXPORT_SYMBOL(EtherCAT_master_open); EXPORT_SYMBOL(EtherCAT_master_close); -EXPORT_SYMBOL(EtherCAT_read_process_data); -EXPORT_SYMBOL(EtherCAT_write_process_data); EXPORT_SYMBOL(EtherCAT_check_slaves); -EXPORT_SYMBOL(EtherCAT_activate_all_slaves); -EXPORT_SYMBOL(EtherCAT_clear_process_data); -EXPORT_SYMBOL(EtherCAT_deactivate_all_slaves); - -/*****************************************************************************/ +EXPORT_SYMBOL(EtherCAT_activate_slave); +EXPORT_SYMBOL(EtherCAT_deactivate_slave); +EXPORT_SYMBOL(EtherCAT_process_data_cycle); + +/*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_master.h --- a/drivers/ec_master.h Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_master.h Thu Jan 05 13:39:39 2006 +0000 @@ -14,6 +14,7 @@ #include "ec_device.h" #include "ec_slave.h" #include "ec_command.h" +#include "ec_domain.h" /*****************************************************************************/ @@ -24,19 +25,10 @@ dem zugewiesenen EtherCAT-Gerät. */ -typedef struct +struct EtherCAT_master { - EtherCAT_slave_t *slaves; /**< Zeiger auf statischen Speicher - mit Slave-Informationen */ - unsigned int slave_count; /**< Anzahl der Slaves in slaves */ - - EtherCAT_command_t process_data_command; /**< Kommando zum Senden und - Empfangen der Prozessdaten */ - EtherCAT_device_t *dev; /**< Zeiger auf das zugewiesene EtherCAT-Gerät */ - unsigned char command_index; /**< Aktueller Kommando-Index */ - unsigned char tx_data[ECAT_FRAME_BUFFER_SIZE]; /**< Statischer Speicher für zu sendende Daten */ unsigned int tx_data_length; /**< Länge der Daten im Sendespeicher */ @@ -44,13 +36,13 @@ eine Kopie des Rx-Buffers im EtherCAT-Gerät */ unsigned int rx_data_length; /**< Länge der Daten im Empfangsspeicher */ - - unsigned char *process_data; /**< Zeiger auf Speicher mit Prozessdaten */ - unsigned int process_data_length; /**< Länge der Prozessdaten */ - + EtherCAT_domain_t domains[ECAT_MAX_DOMAINS]; /** Prozessdatendomänen */ + unsigned int domain_count; int debug_level; /**< Debug-Level im Master-Code */ -} -EtherCAT_master_t; + unsigned long tx_time; /**< Zeit des letzten Sendens */ + unsigned long rx_time; /**< Zeit des letzten Empfangs */ + unsigned int rx_tries; /**< Anzahl Warteschleifen beim letzen Enpfang */ +}; /*****************************************************************************/ @@ -68,22 +60,17 @@ int EtherCAT_simple_receive(EtherCAT_master_t *, EtherCAT_command_t *); // 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 *); +int EtherCAT_check_slaves(EtherCAT_master_t *, EtherCAT_slave_t *, + unsigned int); +int EtherCAT_read_slave_information(EtherCAT_master_t *, unsigned short int, + unsigned short int, unsigned int *); 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); +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 *); +int EtherCAT_process_data_cycle(EtherCAT_master_t *, unsigned int); // Private functions void output_debug_data(const EtherCAT_master_t *); @@ -91,3 +78,9 @@ /*****************************************************************************/ #endif + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_module.c --- a/drivers/ec_module.c Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_module.c Thu Jan 05 13:39:39 2006 +0000 @@ -239,7 +239,7 @@ /*****************************************************************************/ /** - Gibt einen zuvor reservierten EtherCAT-Master wieder frei. + Gibt einen zuvor angeforderten EtherCAT-Master wieder frei. @param master Zeiger auf den freizugebenden EtherCAT-Master. */ @@ -267,7 +267,7 @@ } } - printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n", + printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n", (unsigned int) master); } diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_slave.c --- a/drivers/ec_slave.c Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_slave.c Thu Jan 05 13:39:39 2006 +0000 @@ -20,6 +20,9 @@ Initialisiert einen EtherCAT-Slave. + ACHTUNG! Dieser Konstruktor wird quasi nie aufgerufen. Bitte immer das + Makro ECAT_INIT_SLAVE() in ec_slave.h anpassen! + @param slave Zeiger auf den zu initialisierenden Slave */ @@ -35,9 +38,11 @@ slave->revision_number = 0; slave->serial_number = 0; slave->desc = NULL; - slave->logical_address0 = 0; + slave->logical_address = 0; slave->current_state = ECAT_STATE_UNKNOWN; slave->requested_state = ECAT_STATE_UNKNOWN; + slave->process_data = NULL; + slave->domain = 0; slave->error_reported = 0; } @@ -97,7 +102,7 @@ return 0; } - if (unlikely(channel >= slave->desc->channels)) { + if (unlikely(channel >= slave->desc->channel_count)) { if (likely(slave->error_reported)) { printk(KERN_WARNING "EtherCAT: Reading failed on slave %4X (addr %0X)" " - Type (%s %s) has no channel %i.\n", @@ -109,6 +114,16 @@ return 0; } + if (unlikely(!slave->process_data)) { + if (likely(slave->error_reported)) { + printk(KERN_WARNING "EtherCAT: Reading failed on slave %4X (addr %0X)" + " - Slave does not belong to any process data object!\n", + slave->station_address, (unsigned int) slave); + slave->error_reported = 1; + } + return 0; + } + if (unlikely(slave->error_reported)) slave->error_reported = 0; @@ -156,7 +171,7 @@ return; } - if (unlikely(channel >= slave->desc->channels)) { + if (unlikely(channel >= slave->desc->channel_count)) { if (likely(slave->error_reported)) { printk(KERN_WARNING "EtherCAT: Writing failed on slave %4X (addr %0X)" " - Type (%s %s) has no channel %i.\n", @@ -168,6 +183,16 @@ return; } + if (unlikely(!slave->process_data)) { + if (likely(slave->error_reported)) { + printk(KERN_WARNING "EtherCAT: Writing failed on slave %4X (addr %0X)" + " - Slave does not belong to any process data object!\n", + slave->station_address, (unsigned int) slave); + slave->error_reported = 1; + } + return; + } + if (unlikely(slave->error_reported)) slave->error_reported = 0; @@ -180,3 +205,9 @@ EXPORT_SYMBOL(EtherCAT_read_value); /*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_slave.h --- a/drivers/ec_slave.h Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_slave.h Thu Jan 05 13:39:39 2006 +0000 @@ -42,20 +42,21 @@ const EtherCAT_slave_desc_t *desc; /**< Zeiger auf die Beschreibung des Slave-Typs */ - unsigned int logical_address0; /**< Konfigurierte, logische adresse */ + unsigned int logical_address; /**< Konfigurierte, logische adresse */ EtherCAT_state_t current_state; /**< Aktueller Zustand */ EtherCAT_state_t requested_state; /**< Angeforderter Zustand */ unsigned char *process_data; /**< Zeiger auf den Speicherbereich - im Prozessdatenspeicher des Masters */ - int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet. */ + innerhalb eines Prozessdatenobjekts */ + unsigned int domain; /**< Prozessdatendomäne */ + int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet */ } EtherCAT_slave_t; -#define ECAT_INIT_SLAVE(TYPE) {0, 0, 0, 0, 0, 0, 0, 0, 0, \ - TYPE, 0, ECAT_STATE_UNKNOWN, \ - ECAT_STATE_UNKNOWN, NULL} +#define ECAT_INIT_SLAVE(TYPE, DOMAIN) {0, 0, 0, 0, 0, 0, 0, 0, 0, \ + TYPE, 0, ECAT_STATE_UNKNOWN, \ + ECAT_STATE_UNKNOWN, NULL, DOMAIN, 0} /*****************************************************************************/ @@ -69,3 +70,9 @@ /*****************************************************************************/ #endif + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:2 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 drivers/ec_types.h --- a/drivers/ec_types.h Fri Dec 23 08:23:35 2005 +0000 +++ b/drivers/ec_types.h Thu Jan 05 13:39:39 2006 +0000 @@ -57,8 +57,8 @@ const unsigned char *fmmu0; /**< Konfigurationsdaten der ersten FMMU */ - const unsigned int data_length; /**< Länge der Prozessdaten in Bytes */ - const unsigned int channels; /**< Anzahl der Kanäle */ + const unsigned int process_data_size; /**< Länge der Prozessdaten in Bytes */ + const unsigned int channel_count; /**< Anzahl der Kanäle */ int (*read) (unsigned char *, unsigned int); /**< Funktion zum Dekodieren und Lesen der Kanaldaten */ diff -r 42c66194c0c8 -r a22a202d0f42 mini/ec_mini.c --- a/mini/ec_mini.c Fri Dec 23 08:23:35 2005 +0000 +++ b/mini/ec_mini.c Thu Jan 05 13:39:39 2006 +0000 @@ -6,7 +6,7 @@ * * $Id$ * - ******************************************************************************/ + *****************************************************************************/ #include #include @@ -17,12 +17,12 @@ #include "../drivers/ec_types.h" #include "../drivers/ec_module.h" -/******************************************************************************/ +/*****************************************************************************/ // Auskommentieren, wenn keine zyklischen Daten erwuenscht #define ECAT_CYCLIC_DATA -/******************************************************************************/ +/*****************************************************************************/ static EtherCAT_master_t *ecat_master = NULL; @@ -30,52 +30,52 @@ { #if 0 // Block 1 - ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL3102), + ECAT_INIT_SLAVE(Beckhoff_EK1100, 1), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + + ECAT_INIT_SLAVE(Beckhoff_EL4102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 1), + + ECAT_INIT_SLAVE(Beckhoff_EL3162, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 1), #endif #if 1 // Block 2 - ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), + ECAT_INIT_SLAVE(Beckhoff_EK1100, 1), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), // Block 3 - ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014) + ECAT_INIT_SLAVE(Beckhoff_EK1100, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1) #endif }; @@ -136,7 +136,7 @@ static void run(unsigned long data) { - static int ms = 0; + static int ms = 0; static int cnt = 0; static unsigned long int k = 0; static int firstrun = 1; @@ -149,37 +149,7 @@ ms++; ms %= 1000; -#if 0 - ecat_tx_delay = ((unsigned int) (100000 / HZ) * (ecat_master->dev->tx_time-k)) - / (current_cpu_data.loops_per_jiffy / 10); - ecat_rx_delay = ((unsigned int) (100000 / HZ) * (ecat_master->dev->rx_time-k)) - / (current_cpu_data.loops_per_jiffy / 10); - - rx_intr = ecat_master->dev->rx_intr_cnt; - tx_intr = ecat_master->dev->tx_intr_cnt; - total_intr = ecat_master->dev->intr_cnt; -#endif - - // Prozessdaten lesen - if (!firstrun) - { - EtherCAT_read_process_data(ecat_master); - - // Daten lesen und skalieren -// value = EtherCAT_read_value(&ecat_master->slaves[5], 0) / 3276; //.7; FIXME kein FP im Kernel ohne Schutz !! -// dig1 = EtherCAT_read_value(&ecat_master->slaves[3], 0); - } - else - klemme = next2004(&wrap); - - -#if 0 - // Daten schreiben - EtherCAT_write_value(&ecat_master->slaves[4], 0, ms > 500 ? 1 : 0); - EtherCAT_write_value(&ecat_master->slaves[4], 1, ms > 500 ? 0 : 1); - EtherCAT_write_value(&ecat_master->slaves[4], 2, ms > 500 ? 0 : 1); - EtherCAT_write_value(&ecat_master->slaves[4], 3, ms > 500 ? 1 : 0); -#endif + if (firstrun) klemme = next2004(&wrap); if (cnt++ > 20) { @@ -198,20 +168,12 @@ } } - if (klemme >= 0) { - EtherCAT_write_value(&ecat_master->slaves[klemme], kanal,up_down); - //printk("ECAT write: Klemme: %d, Kanal: %d, Wert: %d\n",klemme,kanal,up_down); - } - -#if 0 - EtherCAT_write_value(&ecat_master->slaves[13], 1, ms > 500 ? 0 : 1); - EtherCAT_write_value(&ecat_master->slaves[14], 2, ms > 500 ? 0 : 1); - EtherCAT_write_value(&ecat_master->slaves[15], 3, ms > 500 ? 1 : 0); -#endif - - // Prozessdaten schreiben + if (klemme >= 0) + EtherCAT_write_value(&ecat_slaves[klemme], kanal, up_down); + + // Prozessdaten lesen und schreiben rdtscl(k); - EtherCAT_write_process_data(ecat_master); + EtherCAT_process_data_cycle(ecat_master, 1); firstrun = 0; timer.expires += HZ / 1000; @@ -224,10 +186,12 @@ * * Function: init * - ******************************************************************************/ + *****************************************************************************/ int __init init_module() { + unsigned int i; + printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n"); if ((ecat_master = EtherCAT_request(0)) == NULL) { @@ -237,17 +201,19 @@ printk("Checking EtherCAT slaves.\n"); - if (EtherCAT_check_slaves(ecat_master, ecat_slaves, ECAT_SLAVES_COUNT) != 0) { + if (EtherCAT_check_slaves(ecat_master, ecat_slaves, + ECAT_SLAVES_COUNT) != 0) { printk(KERN_ERR "EtherCAT: Could not init slaves!\n"); goto out_release_master; } printk("Activating all EtherCAT slaves.\n"); - if (EtherCAT_activate_all_slaves(ecat_master) != 0) - { - printk(KERN_ERR "EtherCAT: Could not activate slaves!\n"); - goto out_release_master; + for (i = 0; i < ECAT_SLAVES_COUNT; i++) { + if (EtherCAT_activate_slave(ecat_master, &ecat_slaves[i]) != 0) { + printk(KERN_ERR "EtherCAT: Could not activate slave %i!\n", i); + goto out_release_master; + } } #ifdef ECAT_CYCLIC_DATA @@ -279,21 +245,25 @@ * * Function: cleanup * - ******************************************************************************/ + *****************************************************************************/ void __exit cleanup_module() { + unsigned int i; + printk(KERN_INFO "=== Stopping Minimal EtherCAT environment... ===\n"); if (ecat_master) { #ifdef ECAT_CYCLIC_DATA del_timer_sync(&timer); - EtherCAT_clear_process_data(ecat_master); #endif // ECAT_CYCLIC_DATA printk(KERN_INFO "Deactivating slaves.\n"); - EtherCAT_deactivate_all_slaves(ecat_master); + + for (i = 0; i < ECAT_SLAVES_COUNT; i++) { + EtherCAT_deactivate_slave(ecat_master, &ecat_slaves[i]); + } EtherCAT_release(ecat_master); } @@ -311,3 +281,9 @@ module_exit(cleanup_module); /*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:4 *** +;;; End: *** +*/ diff -r 42c66194c0c8 -r a22a202d0f42 rt/msr_jitter.c --- a/rt/msr_jitter.c Fri Dec 23 08:23:35 2005 +0000 +++ b/rt/msr_jitter.c Thu Jan 05 13:39:39 2006 +0000 @@ -130,7 +130,6 @@ int i,hit; static int firstrun = 1; - static int counter = 0; static unsigned long k,j = 0; unsigned int dt,jitter; diff -r 42c66194c0c8 -r a22a202d0f42 rt/msr_module.c --- a/rt/msr_module.c Fri Dec 23 08:23:35 2005 +0000 +++ b/rt/msr_module.c Thu Jan 05 13:39:39 2006 +0000 @@ -1,43 +1,23 @@ -/************************************************************************************************** -* -* msr_module.c -* -* Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung -* Zeitgeber ist der Timerinterrupt (tq) -* -* Autor: Wilhelm Hagemeister -* -* (C) Copyright IgH 2002 -* Ingenieurgemeinschaft IgH -* Heinz-Bäcker Str. 34 -* D-45356 Essen -* Tel.: +49 201/61 99 31 -* Fax.: +49 201/61 98 36 -* E-mail: hm@igh-essen.com -* -* -* $RCSfile: msr_module.c,v $ -* $Revision: 1.1 $ -* $Author: hm $ -* $Date: 2005/11/14 20:32:57 $ -* $State: Exp $ -* -* -* $Log: msr_module.c,v $ -* Revision 1.1 2005/11/14 20:32:57 hm -* Initial revision -* -* Revision 1.13 2005/06/17 11:35:13 hm -* *** empty log message *** -* -* -* Hello Emacs: -*- c-basic-offset: 2; -*- -* -**************************************************************************************************/ - - -/*--includes-------------------------------------------------------------------------------------*/ - +/****************************************************************************** + * + * msr_module.c + * + * Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung. + * Zeitgeber ist der Timerinterrupt (tq) + * + * Autor: Wilhelm Hagemeister + * + * (C) Copyright IgH 2002 + * Ingenieurgemeinschaft IgH + * Heinz-Bäcker Str. 34 + * D-45356 Essen + * Tel.: +49 201/61 99 31 + * Fax.: +49 201/61 98 36 + * E-mail: hm@igh-essen.com + * + * $Id$ + * + *****************************************************************************/ #ifndef __KERNEL__ # define __KERNEL__ @@ -51,7 +31,7 @@ #include #include -#include +#include #include /* everything... */ #include #include @@ -84,12 +64,9 @@ #include "msr_jitter.h" -MODULE_AUTHOR("Wilhelm Hagemeister, Ingenieurgemeinschaft IgH"); -MODULE_LICENSE("GPL"); - -/*--external functions---------------------------------------------------------------------------*/ - -/*--external data--------------------------------------------------------------------------------*/ +#define TSC2US(T) ((unsigned long) (T) * 1000UL / cpu_khz) + +/*--external data------------------------------------------------------------*/ #define HZREDUCTION (MSR_ABTASTFREQUENZ/HZ) @@ -99,12 +76,10 @@ extern int proc_abtastfrequenz; -/*--public data----------------------------------------------------------------------------------*/ -/*--local data-----------------------------------------------------------------------------------*/ -//struct timer_list timer; - -extern struct timeval process_time; -struct timeval msr_time_increment; // Increment per Interrupt +/*--local data---------------------------------------------------------------*/ + +extern struct timeval process_time; +struct timeval msr_time_increment; // Increment per Interrupt //adeos @@ -116,55 +91,51 @@ static EtherCAT_slave_t ecat_slaves[] = { - - #if 1 // Block 1 - ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), + ECAT_INIT_SLAVE(Beckhoff_EK1100, 0), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 0), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 0), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 0), // Block 2 - ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL2004), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014), - ECAT_INIT_SLAVE(Beckhoff_EL1014) -#endif - -#if 1 + ECAT_INIT_SLAVE(Beckhoff_EK1100, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL2004, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1), + ECAT_INIT_SLAVE(Beckhoff_EL1014, 1) +#endif + +#if 0 // Block 3 - ,ECAT_INIT_SLAVE(Beckhoff_EK1100), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3162), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL3102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4102), - ECAT_INIT_SLAVE(Beckhoff_EL4132) - - + ,ECAT_INIT_SLAVE(Beckhoff_EK1100, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3162, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL3102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL4102, 2), + ECAT_INIT_SLAVE(Beckhoff_EL4132, 2) #endif }; @@ -183,8 +154,6 @@ * *****************************************************************************/ - - static int next2004(int *wrap) { static int i = 0; @@ -228,23 +197,17 @@ static int up_down = 0; int wrap = 0; + static unsigned int debug_counter = 0; + unsigned long t1, t2, t3, t4, t5, t6, t7; + static unsigned long lt = 0; + unsigned int tr1, tr2; + + rdtscl(t1); // Prozessdaten lesen msr_jitter_run(MSR_ABTASTFREQUENZ); - if (!firstrun) - { - EtherCAT_read_process_data(ecat_master); - - // Daten lesen und skalieren -#ifdef USE_MSR_LIB - value = EtherCAT_read_value(&ecat_master->slaves[5], 0) / 3276.0; - dig1 = EtherCAT_read_value(&ecat_master->slaves[2], 0); -#endif - } - else - klemme = next2004(&wrap); - + if (firstrun) klemme = next2004(&wrap); ms++; ms %= 1000; @@ -266,8 +229,7 @@ } if (klemme >= 0) { - EtherCAT_write_value(&ecat_master->slaves[klemme], kanal,up_down); - //printk("ECAT write: Klemme: %d, Kanal: %d, Wert: %d\n",klemme,kanal,up_down); + EtherCAT_write_value(&ecat_slaves[klemme], kanal, up_down); } #if 0 @@ -278,32 +240,63 @@ // Prozessdaten schreiben rdtscl(k); - EtherCAT_write_process_data(ecat_master); + rdtscl(t2); + + EtherCAT_process_data_cycle(ecat_master, 0); + + t3 = ecat_master->tx_time; + t4 = ecat_master->rx_time; + tr1 = ecat_master->rx_tries; + + EtherCAT_process_data_cycle(ecat_master, 1); + + t5 = ecat_master->tx_time; + t6 = ecat_master->rx_time; + tr2 = ecat_master->rx_tries; + + //EtherCAT_process_data_cycle(ecat_master, 2); + + // Daten lesen und skalieren +#ifdef USE_MSR_LIB + value = EtherCAT_read_value(&ecat_slaves[5], 0) / 3276.0; + dig1 = EtherCAT_read_value(&ecat_slaves[2], 0); +#endif + + rdtscl(t7); + + if (debug_counter == MSR_ABTASTFREQUENZ) { + printk(KERN_DEBUG "%lu: %luŽµs + %luŽµs + %luŽµs + %luŽµs + %luŽµs +" + " %luŽµs = %luŽµs (%u %u)\n", + TSC2US(t1 - lt), + TSC2US(t2 - t1), TSC2US(t3 - t2), TSC2US(t4 - t3), + TSC2US(t5 - t4), TSC2US(t6 - t5), TSC2US(t7 - t6), + TSC2US(t7 - t1), tr1, tr2); + debug_counter = 0; + } + + lt = t1; + firstrun = 0; - -} - -/* -*************************************************************************************************** -* -* Function: msr_run(_interrupt) -* -* Beschreibung: Routine wird zyklisch im Timerinterrupt ausgeführt -* (hier muß alles rein, was Echtzeit ist ...) -* -* Parameter: Zeiger auf msr_data -* -* Rückgabe: -* -* Status: exp -* -*************************************************************************************************** -*/ - + debug_counter++; +} + +/****************************************************************************** + * + * Function: msr_run(_interrupt) + * + * Beschreibung: Routine wird zyklisch im Timerinterrupt ausgeführt + * (hier muß alles rein, was Echtzeit ist ...) + * + * Parameter: Zeiger auf msr_data + * + * Rückgabe: + * + * Status: exp + * + *****************************************************************************/ void msr_run(unsigned irq) { - static int counter = 0; #ifdef USE_MSR_LIB @@ -318,45 +311,40 @@ #endif /* und wieder in die Timerliste eintragen */ /* und neu in die Taskqueue eintragen */ -// timer.expires += 1; -// add_timer(&timer); + //timer.expires += 1; + //add_timer(&timer); ipipe_control_irq(irq,0,IPIPE_ENABLE_MASK); //Interrupt bestŽätigen if(counter++ > HZREDUCTION) { ipipe_propagate_irq(irq); //und weiterreichen counter = 0; } - - -} - -void domain_entry (void) { - printk("Domain %s started.\n", ipipe_current_domain->name); - +} + +void domain_entry (void) +{ + printk("Domain %s started.\n", ipipe_current_domain->name); ipipe_get_sysinfo(&sys_info); ipipe_virtualize_irq(ipipe_current_domain,sys_info.archdep.tmirq, &msr_run, NULL, IPIPE_HANDLE_MASK); - ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0); - -} - -/* -******************************************************************************* -* -* Function: msr_register_channels -* -* Beschreibung: KanŽäle registrieren -* -* Parameter: -* -* RŽückgabe: -* -* Status: exp -* -******************************************************************************* -*/ + ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0); +} + +/****************************************************************************** + * + * Function: msr_register_channels + * + * Beschreibung: KanŽäle registrieren + * + * Parameter: + * + * RŽückgabe: + * + * Status: exp + * + *****************************************************************************/ int msr_globals_register(void) { @@ -364,23 +352,23 @@ msr_reg_kanal("/value", "V", &value, TDBL); msr_reg_kanal("/dig1", "", &dig1, TINT); #endif -/* msr_reg_kanal("/Taskinfo/Ecat/TX-Delay","us",&ecat_tx_delay,TUINT); - msr_reg_kanal("/Taskinfo/Ecat/RX-Delay","us",&ecat_rx_delay,TUINT); - msr_reg_kanal("/Taskinfo/Ecat/TX-Cnt","",&tx_intr,TUINT); - msr_reg_kanal("/Taskinfo/Ecat/RX-Cnt","",&rx_intr,TUINT); - msr_reg_kanal("/Taskinfo/Ecat/Total-Cnt","",&total_intr,TUINT); -*/ +#if 0 + msr_reg_kanal("/Taskinfo/Ecat/TX-Delay","us",&ecat_tx_delay,TUINT); + msr_reg_kanal("/Taskinfo/Ecat/RX-Delay","us",&ecat_rx_delay,TUINT); + msr_reg_kanal("/Taskinfo/Ecat/TX-Cnt","",&tx_intr,TUINT); + msr_reg_kanal("/Taskinfo/Ecat/RX-Cnt","",&rx_intr,TUINT); + msr_reg_kanal("/Taskinfo/Ecat/Total-Cnt","",&total_intr,TUINT); +#endif return 0; } - -/**************************************************************************************************** +/****************************************************************************** * the init/clean material - ****************************************************************************************************/ - + *****************************************************************************/ int __init init_module() { + unsigned int i; struct ipipe_domain_attr attr; //ipipe // Als allererstes die RT-lib initialisieren @@ -409,9 +397,10 @@ printk("Activating all EtherCAT slaves.\n"); - if (EtherCAT_activate_all_slaves(ecat_master) != 0) { - printk(KERN_ERR "EtherCAT: Could not activate slaves!\n"); - goto out_release_master; + for (i = 0; i < ECAT_SLAVES_COUNT; i++) { + if (EtherCAT_activate_slave(ecat_master, ecat_slaves + i) < 0) { + goto out_release_master; + } } do_gettimeofday(&process_time); @@ -436,11 +425,12 @@ return -1; } - -//**************************************************************************** +/*****************************************************************************/ + void __exit cleanup_module() - -{ +{ + unsigned int i; + msr_print_info("msk_modul: unloading..."); ipipe_tune_timer(1000000000UL/HZ,0); //alten Timertakt wieder herstellen @@ -450,9 +440,14 @@ if (ecat_master) { - EtherCAT_clear_process_data(ecat_master); printk(KERN_INFO "Deactivating slaves.\n"); - EtherCAT_deactivate_all_slaves(ecat_master); + + for (i = 0; i < ECAT_SLAVES_COUNT; i++) { + if (EtherCAT_deactivate_slave(ecat_master, ecat_slaves + i) < 0) { + printk(KERN_WARNING "Warning - Could not deactivate slave!\n"); + } + } + EtherCAT_release(ecat_master); } @@ -463,6 +458,8 @@ #endif } +/*****************************************************************************/ + MODULE_LICENSE("GPL"); MODULE_AUTHOR ("Wilhelm Hagemeister "); MODULE_DESCRIPTION ("EtherCAT test environment"); @@ -470,18 +467,4 @@ module_init(init_module); module_exit(cleanup_module); - - - - - - - - - - - - - - - +/*****************************************************************************/ diff -r 42c66194c0c8 -r a22a202d0f42 rt/msr_param.h --- a/rt/msr_param.h Fri Dec 23 08:23:35 2005 +0000 +++ b/rt/msr_param.h Thu Jan 05 13:39:39 2006 +0000 @@ -1,6 +1,6 @@ #ifndef _MSR_PARAM_H_ #define _MSR_PARAM_H_ -#define MSR_ABTASTFREQUENZ 20000 //FIXME nur für den Simulator, der virtuelle 10 Mal schneller läuft ....HZ /* Abtastrate der Kan%/1€Œiso8859-15äle in [HZ]*/ +#define MSR_ABTASTFREQUENZ 10000 //FIXME nur für den Simulator, der virtuelle 10 Mal schneller läuft ....HZ /* Abtastrate der Kan%/1€Œiso8859-15äle in [HZ]*/ #endif