Domains, Warten beim Senden, 10kHz.

This commit is contained in:
Florian Pose 2006-01-05 13:39:39 +00:00
parent b691a914b6
commit 3b3b3b1ed1
15 changed files with 623 additions and 548 deletions

View File

@ -18,7 +18,7 @@ obj-m := 8139too-ecat.o ecat-master.o
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`

View File

@ -131,6 +131,8 @@ int EtherCAT_device_assign(EtherCAT_device_t *ecd,
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 @@ int EtherCAT_device_open(EtherCAT_device_t *ecd)
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 @@ int EtherCAT_device_receive(EtherCAT_device_t *ecd,
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 @@ int EtherCAT_device_receive(EtherCAT_device_t *ecd,
/*****************************************************************************/
/**
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_open);
EXPORT_SYMBOL(EtherCAT_device_close);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***
;;; End: ***
*/

56
drivers/ec_domain.c Normal file
View File

@ -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: ***
*/

51
drivers/ec_domain.h Normal file
View File

@ -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: ***
*/

View File

@ -18,6 +18,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 @@ EtherCAT_state_t;
/*****************************************************************************/
typedef struct EtherCAT_master EtherCAT_master_t;
/*****************************************************************************/
#endif

View File

@ -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_init(EtherCAT_master_t *master)
void EtherCAT_master_clear(EtherCAT_master_t *master)
{
// Remove all slaves
EtherCAT_clear_slaves(master);
unsigned int i;
if (master->process_data) {
kfree(master->process_data);
master->process_data = NULL;
// Remove domains
for (i = 0; i < master->domain_count; i++) {
EtherCAT_domain_clear(master->domains + i);
}
master->process_data_length = 0;
master->domain_count = 0;
}
/*****************************************************************************/
@ -82,14 +79,12 @@ int EtherCAT_master_open(EtherCAT_master_t *master,
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 @@ int EtherCAT_simple_send(EtherCAT_master_t *master,
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 @@ int EtherCAT_simple_send(EtherCAT_master_t *master,
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 @@ int EtherCAT_simple_receive(EtherCAT_master_t *master,
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 @@ int EtherCAT_simple_receive(EtherCAT_master_t *master,
| (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 @@ int EtherCAT_simple_receive(EtherCAT_master_t *master,
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 @@ int EtherCAT_check_slaves(EtherCAT_master_t *master,
{
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 @@ int EtherCAT_check_slaves(EtherCAT_master_t *master,
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 @@ int EtherCAT_check_slaves(EtherCAT_master_t *master,
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 @@ int EtherCAT_check_slaves(EtherCAT_master_t *master,
}
// Get base data
cur->type = cmd.data[0];
cur->revision = cmd.data[1];
cur->build = cmd.data[2] | (cmd.data[3] << 8);
@ -515,62 +522,81 @@ int EtherCAT_check_slaves(EtherCAT_master_t *master,
cur->vendor_id, cur->product_code, i);
return -1;
}
// 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++;
}
}
length = 0;
for (i = 0; i < slave_count; i++)
// Calculate domain sizes
offset = 0;
for (i = 0; i < master->domain_count; i++)
{
length += slaves[i].desc->data_length;
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;
}
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;
return 0;
}
/*****************************************************************************/
/**
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 @@ int EtherCAT_read_slave_information(EtherCAT_master_t *master,
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 @@ int EtherCAT_read_slave_information(EtherCAT_master_t *master,
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 @@ int EtherCAT_read_slave_information(EtherCAT_master_t *master,
}
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 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
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 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Resetting SMs -"
" Slave %04X did not respond!\n",
slave->station_address);
return -2;
return -1;
}
}
@ -823,7 +849,7 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting SM0 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -3;
return -1;
}
}
@ -839,7 +865,7 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting SM1 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -2;
return -1;
}
}
}
@ -848,18 +874,24 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
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 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting FMMU0 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -2;
return -1;
}
}
@ -891,7 +923,7 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting SM0 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -3;
return -1;
}
}
@ -907,7 +939,7 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting SM1 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -3;
return -1;
}
}
}
@ -924,7 +956,7 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
printk(KERN_ERR "EtherCAT: Setting SM2 -"
" Slave %04X did not respond!\n",
slave->station_address);
return -3;
return -1;
}
}
@ -940,19 +972,19 @@ int EtherCAT_activate_slave(EtherCAT_master_t *master,
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,157 +1013,80 @@ int EtherCAT_deactivate_slave(EtherCAT_master_t *master,
/*****************************************************************************/
/**
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)
int EtherCAT_process_data_cycle(EtherCAT_master_t *master,
unsigned int domain)
{
unsigned int i;
unsigned int i, tries;
EtherCAT_domain_t *dom = NULL;
for (i = 0; i < master->slave_count; i++)
{
if (unlikely(EtherCAT_activate_slave(master,
&master->slaves[i]) < 0))
return -1;
for (i = 0; i < master->domain_count; i++) {
if (master->domains[i].number == domain) {
dom = master->domains + i;
break;
}
}
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");
if (unlikely(!dom)) {
printk(KERN_ERR "EtherCAT: No such domain: %i!\n", domain);
return -1;
}
return 0;
}
EtherCAT_command_logical_read_write(&dom->command,
dom->logical_offset, dom->data_size,
dom->data);
/*****************************************************************************/
/**
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;
EtherCAT_device_call_isr(master->dev);
tries_left = 20;
while (unlikely(master->dev->state == ECAT_DS_SENT
&& tries_left))
{
udelay(1);
EtherCAT_device_call_isr(master->dev);
tries_left--;
if (unlikely(EtherCAT_simple_send(master, &dom->command) < 0)) {
printk(KERN_ERR "EtherCAT: Could not send process data command!\n");
return -1;
}
if (unlikely(!tries_left))
{
udelay(3);
#if 1
// Warten
tries = 0;
EtherCAT_device_call_isr(master->dev);
while (unlikely(master->dev->state == ECAT_DS_SENT && tries < 100)) {
udelay(1);
EtherCAT_device_call_isr(master->dev);
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;
}
/*****************************************************************************/
/**
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.
@ -1171,11 +1126,15 @@ EXPORT_SYMBOL(EtherCAT_master_init);
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: ***
*/

View File

@ -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 @@ typedef struct
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_send(EtherCAT_master_t *, EtherCAT_command_t *);
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 @@ void output_debug_data(const EtherCAT_master_t *);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***
;;; End: ***
*/

View File

@ -239,7 +239,7 @@ EtherCAT_master_t *EtherCAT_request(int index)
/*****************************************************************************/
/**
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 @@ void EtherCAT_release(EtherCAT_master_t *master)
}
}
printk(KERN_WARNING "EtherCAT: Master %X was never reserved!\n",
printk(KERN_WARNING "EtherCAT: Master %X was never requested!\n",
(unsigned int) master);
}

View File

@ -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 @@ void EtherCAT_slave_init(EtherCAT_slave_t *slave)
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 @@ int EtherCAT_read_value(EtherCAT_slave_t *slave,
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 @@ int EtherCAT_read_value(EtherCAT_slave_t *slave,
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 @@ void EtherCAT_write_value(EtherCAT_slave_t *slave,
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 @@ void EtherCAT_write_value(EtherCAT_slave_t *slave,
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_write_value);
EXPORT_SYMBOL(EtherCAT_read_value);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***
;;; End: ***
*/

View File

@ -42,20 +42,21 @@ typedef struct
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 @@ void EtherCAT_write_value(EtherCAT_slave_t *, unsigned int, int);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***
;;; End: ***
*/

View File

@ -57,8 +57,8 @@ typedef struct slave_desc
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 */

View File

@ -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 @@ static EtherCAT_slave_t ecat_slaves[] =
{
#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_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),
ECAT_INIT_SLAVE(Beckhoff_EL4102),
ECAT_INIT_SLAVE(Beckhoff_EL4102),
ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
ECAT_INIT_SLAVE(Beckhoff_EL4102, 1),
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_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 int next2004(int *wrap)
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 @@ static void run(unsigned long data)
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 @@ static void run(unsigned long data)
}
}
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 (klemme >= 0)
EtherCAT_write_value(&ecat_slaves[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
// 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 @@ static void run(unsigned long data)
*
* 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 @@ int __init init_module()
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 @@ int __init init_module()
*
* 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_init(init_module);
module_exit(cleanup_module);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -130,7 +130,6 @@ void msr_jitter_run(unsigned int hz) {
int i,hit;
static int firstrun = 1;
static int counter = 0;
static unsigned long k,j = 0;
unsigned int dt,jitter;

View File

@ -1,43 +1,23 @@
/**************************************************************************************************
*
* msr_module.c
*
* Kernelmodul f<EFBFBD>ür 2.6 Kernel zur Me<EFBFBD>ßdatenerfassung, Steuerung und Regelung
* Zeitgeber ist der Timerinterrupt (tq)
*
* Autor: Wilhelm Hagemeister
*
* (C) Copyright IgH 2002
* Ingenieurgemeinschaft IgH
* Heinz-B<EFBFBD>ä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<EFBFBD>ür 2.6 Kernel zur Me<EFBFBD>ßdatenerfassung, Steuerung und Regelung.
* Zeitgeber ist der Timerinterrupt (tq)
*
* Autor: Wilhelm Hagemeister
*
* (C) Copyright IgH 2002
* Ingenieurgemeinschaft IgH
* Heinz-B<EFBFBD>ä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");
#define TSC2US(T) ((unsigned long) (T) * 1000UL / cpu_khz)
/*--external functions---------------------------------------------------------------------------*/
/*--external data--------------------------------------------------------------------------------*/
/*--external data------------------------------------------------------------*/
#define HZREDUCTION (MSR_ABTASTFREQUENZ/HZ)
@ -99,12 +76,10 @@ extern struct msr_char_buf *msr_kanal_puffer;
extern int proc_abtastfrequenz;
/*--public data----------------------------------------------------------------------------------*/
/*--local data-----------------------------------------------------------------------------------*/
//struct timer_list timer;
/*--local data---------------------------------------------------------------*/
extern struct timeval process_time;
struct timeval msr_time_increment; // Increment per Interrupt
extern struct timeval process_time;
struct timeval msr_time_increment; // Increment per Interrupt
//adeos
@ -116,55 +91,51 @@ static EtherCAT_master_t *ecat_master = NULL;
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)
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 1
#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 @@ int dig1;
*
*****************************************************************************/
static int next2004(int *wrap)
{
static int i = 0;
@ -228,23 +197,17 @@ static void msr_controller_run(void)
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 @@ static void msr_controller_run(void)
}
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 @@ static void msr_controller_run(void)
// Prozessdaten schreiben
rdtscl(k);
EtherCAT_write_process_data(ecat_master);
firstrun = 0;
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;
debug_counter++;
}
/*
***************************************************************************************************
*
* Function: msr_run(_interrupt)
*
* Beschreibung: Routine wird zyklisch im Timerinterrupt ausgef<EFBFBD>ührt
* (hier mu<EFBFBD>ß alles rein, was Echtzeit ist ...)
*
* Parameter: Zeiger auf msr_data
*
* R<EFBFBD>ückgabe:
*
* Status: exp
*
***************************************************************************************************
*/
/******************************************************************************
*
* Function: msr_run(_interrupt)
*
* Beschreibung: Routine wird zyklisch im Timerinterrupt ausgef<EFBFBD>ührt
* (hier mu<EFBFBD>ß alles rein, was Echtzeit ist ...)
*
* Parameter: Zeiger auf msr_data
*
* R<EFBFBD>ückgabe:
*
* Status: exp
*
*****************************************************************************/
void msr_run(unsigned irq)
{
static int counter = 0;
#ifdef USE_MSR_LIB
@ -318,45 +311,40 @@ void msr_run(unsigned irq)
#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);
ipipe_tune_timer(1000000000UL/MSR_ABTASTFREQUENZ,0);
}
/*
*******************************************************************************
*
* Function: msr_register_channels
*
* Beschreibung: KanŽäle registrieren
*
* Parameter:
*
* RŽückgabe:
*
* Status: exp
*
*******************************************************************************
*/
/******************************************************************************
*
* Function: msr_register_channels
*
* Beschreibung: KanŽäle registrieren
*
* Parameter:
*
* RŽückgabe:
*
* Status: exp
*
*****************************************************************************/
int msr_globals_register(void)
{
@ -364,23 +352,23 @@ int msr_globals_register(void)
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 @@ int __init init_module()
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 @@ int __init init_module()
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 @@ void __exit cleanup_module()
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 @@ void __exit cleanup_module()
#endif
}
/*****************************************************************************/
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>");
MODULE_DESCRIPTION ("EtherCAT test environment");
@ -470,18 +467,4 @@ MODULE_DESCRIPTION ("EtherCAT test environment");
module_init(init_module);
module_exit(cleanup_module);
/*****************************************************************************/

View File

@ -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<02>ä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<02>äle in [HZ]*/
#endif