Domains, Warten beim Senden, 10kHz.
--- 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`
--- 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: ***
+*/
--- /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 <linux/module.h>
+
+#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: ***
+*/
--- /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: ***
+*/
--- 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
--- 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: ***
+*/
--- 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: ***
+*/
--- 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);
}
--- 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: ***
+*/
--- 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: ***
+*/
--- 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 */
--- 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 <linux/module.h>
#include <linux/delay.h>
@@ -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: ***
+*/
--- 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;
--- 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 <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/vmalloc.h>
+#include <linux/vmalloc.h>
#include <linux/fs.h> /* everything... */
#include <linux/proc_fs.h>
#include <linux/time.h>
@@ -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 <hm@igh-essen.com>");
MODULE_DESCRIPTION ("EtherCAT test environment");
@@ -470,18 +467,4 @@
module_init(init_module);
module_exit(cleanup_module);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+/*****************************************************************************/
--- 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