Mit neuer Schnittstelle wieder lauffähig.

This commit is contained in:
Florian Pose 2006-01-20 13:32:31 +00:00
parent b0443360ec
commit 5fb6877412
12 changed files with 263 additions and 446 deletions

View File

@ -2982,7 +2982,7 @@ static int __init rtl8139_init_module (void)
out_ec_dev:
if (rtl_ec_dev) {
printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
EtherCAT_dev_unregister(ec_device_master_index);
EtherCAT_dev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
@ -2998,14 +2998,14 @@ static void __exit rtl8139_cleanup_module (void)
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
pci_unregister_driver(&rtl8139_pci_driver);
if (rtl_ec_dev) {
printk(KERN_INFO "Unregistering RTL8139-EtherCAT device...\n");
EtherCAT_dev_unregister(ec_device_master_index);
EtherCAT_dev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
pci_unregister_driver(&rtl8139_pci_driver);
printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n");
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/

View File

@ -32,7 +32,7 @@ ec_device_t *EtherCAT_dev_register(unsigned int, struct net_device *,
irqreturn_t (*)(int, void *,
struct pt_regs *),
struct module *);
void EtherCAT_dev_unregister(unsigned int);
void EtherCAT_dev_unregister(unsigned int, ec_device_t *);
int EtherCAT_dev_is_ec(ec_device_t *, struct net_device *);
void EtherCAT_dev_state(ec_device_t *, ec_device_state_t);
int EtherCAT_dev_receive(ec_device_t *, void *, unsigned int);

View File

@ -14,22 +14,71 @@
struct ec_master;
typedef struct ec_master ec_master_t;
struct ec_slave_type;
typedef struct ec_slave_type ec_slave_type_t;
struct ec_slave;
typedef struct ec_slave ec_slave_t;
/*****************************************************************************/
ec_master_t *EtherCAT_rt_request_master(unsigned int master_index);
void EtherCAT_rt_release_master(ec_master_t *master);
void *EtherCAT_rt_register_slave(ec_master_t *master, unsigned int slave_index,
const char *vendor_name,
const char *product_name);
ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master,
unsigned int slave_index,
const char *vendor_name,
const char *product_name,
unsigned int domain);
int EtherCAT_rt_activate_slaves(ec_master_t *master);
int EtherCAT_rt_deactivate_slaves(ec_master_t *master);
int EtherCAT_rt_domain_cycle(ec_master_t *master, unsigned int domain,
unsigned int timeout_us);
int EtherCAT_rt_exchange_io(ec_master_t *master, unsigned int domain,
unsigned int timeout_us);
/*****************************************************************************/
/**
EtherCAT-Slave
*/
struct ec_slave
{
// Base data
unsigned char base_type; /**< Slave-Typ */
unsigned char base_revision; /**< Revision */
unsigned short base_build; /**< Build-Nummer */
// Addresses
short ring_position; /**< (Negative) Position des Slaves im Bus */
unsigned short station_address; /**< Konfigurierte Slave-Adresse */
// Slave information interface
unsigned int sii_vendor_id; /**< Identifikationsnummer des Herstellers */
unsigned int sii_product_code; /**< Herstellerspezifischer Produktcode */
unsigned int sii_revision_number; /**< Revisionsnummer */
unsigned int sii_serial_number; /**< Seriennummer der Klemme */
const ec_slave_type_t *type; /**< Zeiger auf die Beschreibung
des Slave-Typs */
unsigned int logical_address; /**< Konfigurierte, logische Adresse */
void *process_data; /**< Zeiger auf den Speicherbereich
innerhalb eines Prozessdatenobjekts */
void *private_data; /**< Zeiger auf privaten Datenbereich */
int (*configure)(ec_slave_t *); /**< Zeiger auf die Funktion zur
Konfiguration */
unsigned char registered; /**< Der Slave wurde registriert */
unsigned int domain; /**< Prozessdatendomäne */
int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet */
};
/*****************************************************************************/

View File

@ -14,8 +14,11 @@
#include <linux/slab.h>
#include <linux/delay.h>
#include "../include/EtherCAT_rt.h"
#include "globals.h"
#include "master.h"
#include "slave.h"
#include "types.h"
#include "device.h"
#include "command.h"
@ -26,8 +29,7 @@
int ec_simple_send(ec_master_t *, ec_command_t *);
int ec_simple_receive(ec_master_t *, ec_command_t *);
void ec_output_debug_data(const ec_master_t *);
int ec_read_slave_information(ec_master_t *, unsigned short, unsigned short,
unsigned int *);
int ec_sii_read(ec_master_t *, unsigned short, unsigned short, unsigned int *);
void ec_output_lost_frames(ec_master_t *);
/*****************************************************************************/
@ -354,7 +356,7 @@ int ec_simple_receive(ec_master_t *master, ec_command_t *cmd)
int ec_scan_for_slaves(ec_master_t *master)
{
ec_command_t cmd;
ec_slave_t *cur;
ec_slave_t *slave;
unsigned int i, j;
unsigned char data[2];
@ -380,53 +382,71 @@ int ec_scan_for_slaves(ec_master_t *master)
// For every slave in the list
for (i = 0; i < master->bus_slaves_count; i++)
{
cur = master->bus_slaves + i;
slave = master->bus_slaves + i;
ec_slave_init(cur);
ec_slave_init(slave);
// Read base data
// Set ring position
slave->ring_position = -i;
slave->station_address = i + 1;
ec_command_read(&cmd, cur->station_address, 0x0000, 4);
// Write station address
data[0] = slave->station_address & 0x00FF;
data[1] = (slave->station_address & 0xFF00) >> 8;
ec_command_position_write(&cmd, slave->ring_position, 0x0010, 2, data);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
if (unlikely(cmd.working_counter != 1)) {
printk(KERN_ERR "EtherCAT: Slave %i did not respond"
" while reading base data!\n", i);
printk(KERN_ERR "EtherCAT: Slave %i did not repond while writing"
" station address!\n", i);
return -1;
}
// Read base data
ec_command_read(&cmd, slave->station_address, 0x0000, 4);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
if (unlikely(cmd.working_counter != 1)) {
printk(KERN_ERR "EtherCAT: Slave %i did not respond while reading base"
" data!\n", i);
return -1;
}
// Get base data
cur->type = cmd.data[0];
cur->revision = cmd.data[1];
cur->build = cmd.data[2] | (cmd.data[3] << 8);
slave->base_type = cmd.data[0];
slave->base_revision = cmd.data[1];
slave->base_build = cmd.data[2] | (cmd.data[3] << 8);
// Read identification from "Slave Information Interface" (SII)
if (unlikely(ec_read_slave_information(master, cur->station_address,
0x0008, &cur->vendor_id) != 0)) {
if (unlikely(ec_sii_read(master, slave->station_address, 0x0008,
&slave->sii_vendor_id) != 0)) {
printk(KERN_ERR "EtherCAT: Could not read SII vendor id!\n");
return -1;
}
if (unlikely(ec_read_slave_information(master, cur->station_address,
0x000A, &cur->product_code) != 0)) {
if (unlikely(ec_sii_read(master, slave->station_address, 0x000A,
&slave->sii_product_code) != 0)) {
printk(KERN_ERR "EtherCAT: Could not read SII product code!\n");
return -1;
}
if (unlikely(ec_read_slave_information(master, cur->station_address,
0x000C,
&cur->revision_number) != 0)) {
if (unlikely(ec_sii_read(master, slave->station_address, 0x000C,
&slave->sii_revision_number) != 0)) {
printk(KERN_ERR "EtherCAT: Could not read SII revision number!\n");
return -1;
}
if (unlikely(ec_read_slave_information(master, cur->station_address,
0x000E,
&cur->serial_number) != 0)) {
if (unlikely(ec_sii_read(master, slave->station_address, 0x000E,
&slave->sii_serial_number) != 0)) {
printk(KERN_ERR "EtherCAT: Could not read SII serial number!\n");
return -1;
}
@ -435,37 +455,18 @@ int ec_scan_for_slaves(ec_master_t *master)
for (j = 0; j < slave_ident_count; j++)
{
if (unlikely(slave_idents[j].vendor_id == cur->vendor_id
&& slave_idents[j].product_code == cur->product_code))
if (unlikely(slave_idents[j].vendor_id == slave->sii_vendor_id
&& slave_idents[j].product_code == slave->sii_product_code))
{
cur->desc = slave_idents[j].desc;
slave->type = slave_idents[j].type;
break;
}
}
if (unlikely(!cur->desc)) {
if (unlikely(!slave->type)) {
printk(KERN_ERR "EtherCAT: Unknown slave device (vendor %X, code %X) at "
" position %i.\n", cur->vendor_id, cur->product_code, i);
return -1;
}
// Set ring position
cur->ring_position = -i;
cur->station_address = i + 1;
// Write station address
data[0] = cur->station_address & 0x00FF;
data[1] = (cur->station_address & 0xFF00) >> 8;
ec_command_position_write(&cmd, cur->ring_position, 0x0010, 2, data);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
if (unlikely(cmd.working_counter != 1)) {
printk(KERN_ERR "EtherCAT: Slave %i did not repond"
" while writing station address!\n", i);
" position %i.\n", slave->sii_vendor_id, slave->sii_product_code,
i);
return -1;
}
}
@ -488,10 +489,8 @@ int ec_scan_for_slaves(ec_master_t *master)
@return 0 bei Erfolg, sonst < 0
*/
int ec_read_slave_information(ec_master_t *master,
unsigned short int node_address,
unsigned short int offset,
unsigned int *target)
int ec_sii_read(ec_master_t *master, unsigned short int node_address,
unsigned short int offset, unsigned int *target)
{
ec_command_t cmd;
unsigned char data[10];
@ -588,14 +587,12 @@ int ec_state_change(ec_master_t *master, ec_slave_t *slave,
}
if (unlikely(cmd.working_counter != 1)) {
printk(KERN_ERR "EtherCAT: Could not set state %02X - Device \"%s %s\""
" (%d) did not respond!\n", state_and_ack, slave->desc->vendor_name,
slave->desc->product_name, slave->ring_position * (-1));
printk(KERN_ERR "EtherCAT: Could not set state %02X - Device %i (%s %s)"
" did not respond!\n", state_and_ack, slave->ring_position * (-1),
slave->type->vendor_name, slave->type->product_name);
return -1;
}
slave->requested_state = state_and_ack & 0x0F;
tries_left = 100;
while (likely(tries_left))
{
@ -635,8 +632,6 @@ int ec_state_change(ec_master_t *master, ec_slave_t *slave,
return -1;
}
slave->current_state = state_and_ack & 0x0F;
return 0;
}
@ -711,11 +706,14 @@ void ec_output_lost_frames(ec_master_t *master)
@return 0 bei Erfolg, sonst < 0
*/
void *EtherCAT_rt_register_slave(ec_master_t *master, unsigned int bus_index,
const char *vendor_name,
const char *product_name, unsigned int domain)
ec_slave_t *EtherCAT_rt_register_slave(ec_master_t *master,
unsigned int bus_index,
const char *vendor_name,
const char *product_name,
unsigned int domain)
{
ec_slave_t *slave;
const ec_slave_type_t *type;
ec_domain_t *dom;
unsigned int j;
@ -727,16 +725,18 @@ void *EtherCAT_rt_register_slave(ec_master_t *master, unsigned int bus_index,
slave = master->bus_slaves + bus_index;
if (slave->process_data) {
if (slave->registered) {
printk(KERN_ERR "EtherCAT: Slave %i is already registered!\n", bus_index);
return NULL;
}
if (strcmp(vendor_name, slave->desc->vendor_name) ||
strcmp(product_name, slave->desc->product_name)) {
type = slave->type;
if (strcmp(vendor_name, type->vendor_name) ||
strcmp(product_name, type->product_name)) {
printk(KERN_ERR "Invalid Slave Type! Requested: \"%s %s\", present: \"%s"
"%s\".\n", vendor_name, product_name, slave->desc->vendor_name,
slave->desc->product_name);
" %s\".\n", vendor_name, product_name, type->vendor_name,
type->product_name);
return NULL;
}
@ -762,17 +762,18 @@ void *EtherCAT_rt_register_slave(ec_master_t *master, unsigned int bus_index,
master->domain_count++;
}
if (dom->data_size + slave->desc->process_data_size > EC_FRAME_SIZE - 14) {
if (dom->data_size + type->process_data_size > EC_FRAME_SIZE - 14) {
printk(KERN_ERR "EtherCAT: Oversized domain %i: %i / %i Bytes!\n",
dom->number, dom->data_size + slave->desc->process_data_size,
dom->number, dom->data_size + type->process_data_size,
EC_FRAME_SIZE - 14);
return NULL;
}
slave->process_data = dom->data + dom->data_size;
dom->data_size += slave->desc->process_data_size;
dom->data_size += type->process_data_size;
slave->registered = 1;
return slave->process_data;
return slave;
}
/*****************************************************************************/
@ -795,14 +796,14 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
unsigned int i;
ec_slave_t *slave;
ec_command_t cmd;
const ec_slave_desc_t *desc;
const ec_slave_type_t *type;
unsigned char fmmu[16];
unsigned char data[256];
for (i = 0; i < master->bus_slaves_count; i++)
{
slave = master->bus_slaves + i;
desc = slave->desc;
type = slave->type;
if (unlikely(ec_state_change(master, slave, EC_SLAVE_STATE_INIT) != 0))
return -1;
@ -824,7 +825,7 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
// Resetting Sync Manager channels
if (desc->type != EC_NOSYNC_SLAVE)
if (type->features != EC_NOSYNC_SLAVE)
{
memset(data, 0x00, 256);
@ -840,14 +841,21 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
}
}
// Check if slave was registered...
if (!slave->registered) {
printk(KERN_INFO "EtherCAT: Slave %i (%s %s) was not registered.\n",
i, type->vendor_name, type->product_name);
continue;
}
// Init Mailbox communication
if (desc->type == EC_MAILBOX_SLAVE)
if (type->features == EC_MAILBOX_SLAVE)
{
if (desc->sm0)
if (type->sm0)
{
ec_command_write(&cmd, slave->station_address, 0x0800, 8,
desc->sm0);
ec_command_write(&cmd, slave->station_address, 0x0800, 8, type->sm0);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -859,10 +867,9 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
}
}
if (desc->sm1)
if (type->sm1)
{
ec_command_write(&cmd, slave->station_address, 0x0808, 8,
desc->sm1);
ec_command_write(&cmd, slave->station_address, 0x0808, 8, type->sm1);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -883,7 +890,7 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
// Set FMMU's
if (desc->fmmu0)
if (type->fmmu0)
{
if (unlikely(!slave->process_data)) {
printk(KERN_ERR "EtherCAT: Warning - Slave %04X is not assigned to any"
@ -891,7 +898,7 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
return -1;
}
memcpy(fmmu, desc->fmmu0, 16);
memcpy(fmmu, type->fmmu0, 16);
fmmu[0] = slave->logical_address & 0x000000FF;
fmmu[1] = (slave->logical_address & 0x0000FF00) >> 8;
@ -912,12 +919,11 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
// Set Sync Managers
if (desc->type != EC_MAILBOX_SLAVE)
if (type->features != EC_MAILBOX_SLAVE)
{
if (desc->sm0)
if (type->sm0)
{
ec_command_write(&cmd, slave->station_address, 0x0800, 8,
desc->sm0);
ec_command_write(&cmd, slave->station_address, 0x0800, 8, type->sm0);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -929,10 +935,9 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
}
}
if (desc->sm1)
if (type->sm1)
{
ec_command_write(&cmd, slave->station_address, 0x0808, 8,
desc->sm1);
ec_command_write(&cmd, slave->station_address, 0x0808, 8, type->sm1);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -945,9 +950,9 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
}
}
if (desc->sm2)
if (type->sm2)
{
ec_command_write(&cmd, slave->station_address, 0x0810, 8, desc->sm2);
ec_command_write(&cmd, slave->station_address, 0x0810, 8, type->sm2);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -959,9 +964,9 @@ int EtherCAT_rt_activate_slaves(ec_master_t *master)
}
}
if (desc->sm3)
if (type->sm3)
{
ec_command_write(&cmd, slave->station_address, 0x0818, 8, desc->sm3);
ec_command_write(&cmd, slave->station_address, 0x0818, 8, type->sm3);
if (unlikely(ec_simple_send_receive(master, &cmd) < 0))
return -1;
@ -1024,8 +1029,8 @@ int EtherCAT_rt_deactivate_slaves(ec_master_t *master)
@return 0 bei Erfolg, sonst < 0
*/
int EtherCAT_rt_domain_cycle(ec_master_t *master, unsigned int domain,
unsigned int timeout_us)
int EtherCAT_rt_exchange_io(ec_master_t *master, unsigned int domain,
unsigned int timeout_us)
{
unsigned int i;
ec_domain_t *dom;
@ -1103,7 +1108,7 @@ int EtherCAT_rt_domain_cycle(ec_master_t *master, unsigned int domain,
EXPORT_SYMBOL(EtherCAT_rt_register_slave);
EXPORT_SYMBOL(EtherCAT_rt_activate_slaves);
EXPORT_SYMBOL(EtherCAT_rt_deactivate_slaves);
EXPORT_SYMBOL(EtherCAT_rt_domain_cycle);
EXPORT_SYMBOL(EtherCAT_rt_exchange_io);
/*****************************************************************************/

View File

@ -25,7 +25,7 @@
dem zugewiesenen EtherCAT-Gerät.
*/
typedef struct ec_master
struct ec_master
{
ec_slave_t *bus_slaves; /**< Array von Slaves auf dem Bus */
unsigned int bus_slaves_count; /**< Anzahl Slaves auf dem Bus */
@ -46,8 +46,7 @@ typedef struct ec_master
unsigned int frames_lost; /**< Anzahl verlorene Frames */
unsigned long t_lost_output; /*<< Timer-Ticks bei der letzten Ausgabe von
verlorenen Frames */
}
ec_master_t;
};
/*****************************************************************************/

View File

@ -168,6 +168,7 @@ ec_device_t *EtherCAT_dev_register(unsigned int master_index,
struct module *module)
{
ec_device_t *ecd;
ec_master_t *master;
if (master_index >= ec_master_count) {
printk(KERN_ERR "EtherCAT: Master %i does not exist!\n", master_index);
@ -179,13 +180,15 @@ ec_device_t *EtherCAT_dev_register(unsigned int master_index,
return NULL;
}
if (ec_masters[master_index].device_registered) {
master = ec_masters + master_index;
if (master->device_registered) {
printk(KERN_ERR "EtherCAT: Master %i already has a device!\n",
master_index);
return NULL;
}
ecd = &ec_masters[master_index].device;
ecd = &master->device;
if (ec_device_init(ecd) < 0) {
return NULL;
@ -197,6 +200,8 @@ ec_device_t *EtherCAT_dev_register(unsigned int master_index,
ecd->isr = isr;
ecd->module = module;
master->device_registered = 1;
return ecd;
}
@ -209,15 +214,24 @@ ec_device_t *EtherCAT_dev_register(unsigned int master_index,
@param device Das EtherCAT-Geraet
*/
void EtherCAT_dev_unregister(unsigned int master_index)
void EtherCAT_dev_unregister(unsigned int master_index, ec_device_t *ecd)
{
ec_master_t *master;
if (master_index >= ec_master_count) {
printk(KERN_WARNING "EtherCAT: Master %i does not exist!\n", master_index);
return;
}
ec_masters[master_index].device_registered = 0;
ec_device_clear(&ec_masters[master_index].device);
master = ec_masters + master_index;
if (!master->device_registered || &master->device != ecd) {
printk(KERN_ERR "EtherCAT: Unable to unregister device!\n");
return;
}
master->device_registered = 0;
ec_device_clear(ecd);
}
/******************************************************************************
@ -235,7 +249,7 @@ void EtherCAT_dev_unregister(unsigned int master_index)
@returns Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
*/
ec_master_t *EtherCAT_rt_request_master(int index)
ec_master_t *EtherCAT_rt_request_master(unsigned int index)
{
ec_master_t *master;
@ -334,3 +348,9 @@ EXPORT_SYMBOL(EtherCAT_rt_request_master);
EXPORT_SYMBOL(EtherCAT_rt_release_master);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***
;;; End: ***
*/

View File

@ -28,171 +28,27 @@
void ec_slave_init(ec_slave_t *slave)
{
slave->type = 0;
slave->revision = 0;
slave->build = 0;
slave->base_type = 0;
slave->base_revision = 0;
slave->base_build = 0;
slave->ring_position = 0;
slave->station_address = 0;
slave->vendor_id = 0;
slave->product_code = 0;
slave->revision_number = 0;
slave->serial_number = 0;
slave->desc = NULL;
slave->sii_vendor_id = 0;
slave->sii_product_code = 0;
slave->sii_revision_number = 0;
slave->sii_serial_number = 0;
slave->type = NULL;
slave->logical_address = 0;
slave->current_state = EC_SLAVE_STATE_UNKNOWN;
slave->requested_state = EC_SLAVE_STATE_UNKNOWN;
slave->process_data = NULL;
slave->private_data = NULL;
slave->configure = NULL;
slave->registered = 0;
slave->domain = 0;
slave->error_reported = 0;
}
/*****************************************************************************/
#if 0
/**
Liest einen bestimmten Kanal des Slaves als Integer-Wert.
Prüft zuerst, ob der entsprechende Slave eine
bekannte Beschreibung besitzt, ob dort eine
read()-Funktion hinterlegt ist und ob die angegebene
Kanalnummer gültig ist. Wenn ja, wird der dekodierte
Wert zurückgegeben, sonst ist der Wert 0.
@param slave EtherCAT-Slave
@param channel Kanalnummer
@return Gelesener Wert bzw. 0
*/
int EtherCAT_read_value(EtherCAT_slave_t *slave,
unsigned int channel)
{
if (unlikely(!slave->desc)) {
if (likely(slave->error_reported)) {
printk(KERN_WARNING "EtherCAT: Reading failed on slave %04X (addr %0X)"
" - Slave has no description.\n",
slave->station_address, (unsigned int) slave);
slave->error_reported = 1;
}
return 0;
}
if (unlikely(!slave->desc->read)) {
if (likely(slave->error_reported)) {
printk(KERN_WARNING "EtherCAT: Reading failed on slave %04X (addr %0X)"
" - Slave type (%s %s) has no read method.\n",
slave->station_address, (unsigned int) slave,
slave->desc->vendor_name, slave->desc->product_name);
slave->error_reported = 1;
}
return 0;
}
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",
slave->station_address, (unsigned int) slave,
slave->desc->vendor_name, slave->desc->product_name,
channel);
slave->error_reported = 1;
}
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;
return slave->desc->read(slave->process_data, channel);
}
/*****************************************************************************/
/**
Schreibt einen bestimmten Kanal des Slaves als Integer-Wert .
Prüft zuerst, ob der entsprechende Slave eine
bekannte Beschreibung besitzt, ob dort eine
write()-Funktion hinterlegt ist und ob die angegebene
Kanalnummer gültig ist. Wenn ja, wird der Wert entsprechend
kodiert und geschrieben.
@param slave EtherCAT-Slave
@param channel Kanalnummer
@param value Zu schreibender Wert
*/
void EtherCAT_write_value(EtherCAT_slave_t *slave,
unsigned int channel,
int value)
{
if (unlikely(!slave->desc)) {
if (likely(slave->error_reported)) {
printk(KERN_WARNING "EtherCAT: Writing failed on slave %04X (addr %0X)"
" - Slave has no description.\n",
slave->station_address, (unsigned int) slave);
slave->error_reported = 1;
}
return;
}
if (unlikely(!slave->desc->write)) {
if (likely(slave->error_reported)) {
printk(KERN_WARNING "EtherCAT: Writing failed on slave %04X (addr %0X)"
" - Type (%s %s) has no write method.\n",
slave->station_address, (unsigned int) slave,
slave->desc->vendor_name, slave->desc->product_name);
slave->error_reported = 1;
}
return;
}
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",
slave->station_address, (unsigned int) slave,
slave->desc->vendor_name, slave->desc->product_name,
channel);
slave->error_reported = 1;
}
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;
slave->desc->write(slave->process_data, channel, value);
}
/*****************************************************************************/
EXPORT_SYMBOL(EtherCAT_write_value);
EXPORT_SYMBOL(EtherCAT_read_value);
#endif
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:2 ***

View File

@ -15,59 +15,13 @@
/*****************************************************************************/
/**
EtherCAT-Slave
Achtung: Bei Änderungen dieser Struktur immer das Define
ECAT_INIT_SLAVE anpassen!
*/
typedef struct
{
// Base data
unsigned char type; /**< Slave-Typ */
unsigned char revision; /**< Revision */
unsigned short build; /**< Build-Nummer */
// Addresses
short ring_position; /**< (Negative) Position des Slaves im Bus */
unsigned short station_address; /**< Konfigurierte Slave-Adresse */
// Slave information interface
unsigned int vendor_id; /**< Identifikationsnummer des Herstellers */
unsigned int product_code; /**< Herstellerspezifischer Produktcode */
unsigned int revision_number; /**< Revisionsnummer */
unsigned int serial_number; /**< Seriennummer der Klemme */
const ec_slave_desc_t *desc; /**< Zeiger auf die Beschreibung
des Slave-Typs */
unsigned int logical_address; /**< Konfigurierte, logische adresse */
ec_slave_state_t current_state; /**< Aktueller Zustand */
ec_slave_state_t requested_state; /**< Angeforderter Zustand */
unsigned char *process_data; /**< Zeiger auf den Speicherbereich
innerhalb eines Prozessdatenobjekts */
unsigned int domain; /**< Prozessdatendomäne */
int error_reported; /**< Ein Zugriffsfehler wurde bereits gemeldet */
}
ec_slave_t;
#define EC_INIT_SLAVE(TYPE, DOMAIN) {0, 0, 0, 0, 0, 0, 0, 0, 0, \
TYPE, 0, ECAT_STATE_UNKNOWN, \
EC_STATE_UNKNOWN, NULL, DOMAIN, 0}
// ec_slave_t ist in EtherCAT_rt.h ...
/*****************************************************************************/
// Slave construction and deletion
void ec_slave_init(ec_slave_t *);
#if 0
int EtherCAT_read_value(EtherCAT_slave_t *, unsigned int);
void EtherCAT_write_value(EtherCAT_slave_t *, unsigned int, int);
#endif
/*****************************************************************************/
#endif

View File

@ -45,116 +45,60 @@ unsigned char fmmu0_41xx[] = {0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x07,
/*****************************************************************************/
/* Lese- und Schreibfunktionen */
int read_1014(unsigned char *data, unsigned int channel)
{
return (data[0] >> channel) & 0x01;
}
void write_2004(unsigned char *data, unsigned int channel, int value)
{
if (value) {
data[0] |= (1 << channel);
}
else {
data[0] &= ~(1 << channel);
}
}
int read_31xx(unsigned char *data, unsigned int channel)
{
return (short int) ((data[channel * 3 + 2] << 8) | data[channel * 3 + 1]);
}
void write_41xx(unsigned char *data, unsigned int channel, int value)
{
data[channel * 3 + 1] = (value & 0xFF00) >> 8;
data[channel * 3 + 2] = value & 0xFF;
}
/*****************************************************************************/
/* Klemmen-Objekte */
ec_slave_desc_t Beckhoff_EK1100[] =
ec_slave_type_t Beckhoff_EK1100[] =
{{
"Beckhoff", "EK1100", "Bus Coupler",
EC_NOSYNC_SLAVE,
NULL, NULL, NULL, NULL,
NULL,
0, 0,
NULL, NULL
EC_NOSYNC_SLAVE, NULL, NULL, NULL, NULL, NULL, 0
}};
ec_slave_desc_t Beckhoff_EL1014[] =
ec_slave_type_t Beckhoff_EK1110[] =
{{
"Beckhoff", "EK1110", "Extension terminal",
EC_NOSYNC_SLAVE, NULL, NULL, NULL, NULL, NULL, 0
}};
ec_slave_type_t Beckhoff_EL1014[] =
{{
"Beckhoff", "EL1014", "4x Digital Input",
EC_SIMPLE_SLAVE,
sm0_1014, NULL, NULL, NULL,
fmmu0_1014,
1, 4,
read_1014, NULL
EC_SIMPLE_SLAVE, sm0_1014, NULL, NULL, NULL, fmmu0_1014, 1
}};
ec_slave_desc_t Beckhoff_EL2004[] =
ec_slave_type_t Beckhoff_EL2004[] =
{{
"Beckhoff", "EL2004", "4x Digital Output",
EC_SIMPLE_SLAVE,
sm0_2004, NULL, NULL, NULL,
fmmu0_2004,
1, 4,
NULL, write_2004
EC_SIMPLE_SLAVE, sm0_2004, NULL, NULL, NULL, fmmu0_2004, 1
}};
ec_slave_desc_t Beckhoff_EL3102[] =
ec_slave_type_t Beckhoff_EL3102[] =
{{
"Beckhoff", "EL3102", "2x Analog Input diff.",
EC_MAILBOX_SLAVE,
sm0_multi, sm1_multi, sm2_31xx, sm3_31xx,
fmmu0_31xx,
6, 2,
read_31xx, NULL
EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_31xx, sm3_31xx, fmmu0_31xx, 6
}};
ec_slave_desc_t Beckhoff_EL3162[] =
ec_slave_type_t Beckhoff_EL3162[] =
{{
"Beckhoff", "EL3162", "2x Analog Input",
EC_MAILBOX_SLAVE,
sm0_multi, sm1_multi, sm2_31xx, sm3_31xx,
fmmu0_31xx,
6, 2,
read_31xx, NULL
EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_31xx, sm3_31xx, fmmu0_31xx, 6
}};
ec_slave_desc_t Beckhoff_EL4102[] =
ec_slave_type_t Beckhoff_EL4102[] =
{{
"Beckhoff", "EL4102", "2x Analog Output",
EC_MAILBOX_SLAVE,
sm0_multi, sm1_multi, sm2_41xx, NULL,
fmmu0_41xx,
4, 2,
NULL, write_41xx
EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_41xx, NULL, fmmu0_41xx, 4
}};
ec_slave_desc_t Beckhoff_EL4132[] =
ec_slave_type_t Beckhoff_EL4132[] =
{{
"Beckhoff", "EL4132", "2x Analog Output diff.",
EC_MAILBOX_SLAVE,
sm0_multi, sm1_multi, sm2_41xx, NULL,
fmmu0_41xx,
4, 2,
NULL, write_41xx
EC_MAILBOX_SLAVE, sm0_multi, sm1_multi, sm2_41xx, NULL, fmmu0_41xx, 4
}};
ec_slave_desc_t Beckhoff_EL5001[] =
ec_slave_type_t Beckhoff_EL5001[] =
{{
"Beckhoff", "EL5001", "SSI-Interface",
EC_SIMPLE_SLAVE,
NULL, NULL, NULL, NULL, // Noch nicht eingepflegt...
NULL,
0, 0,
NULL, NULL
"Beckhoff", "EL5001", "SSI-Interface", // Noch nicht eingepflegt...
EC_SIMPLE_SLAVE, NULL, NULL, NULL, NULL, NULL, 0
}};
/*****************************************************************************/
@ -171,6 +115,7 @@ ec_slave_ident_t slave_idents[] =
{
{0x00000002, 0x03F63052, Beckhoff_EL1014},
{0x00000002, 0x044C2C52, Beckhoff_EK1100},
{0x00000002, 0x04562C52, Beckhoff_EK1110},
{0x00000002, 0x07D43052, Beckhoff_EL2004},
{0x00000002, 0x0C1E3052, Beckhoff_EL3102},
{0x00000002, 0x0C5A3052, Beckhoff_EL3162},

View File

@ -11,12 +11,14 @@
#ifndef _EC_TYPES_H_
#define _EC_TYPES_H_
#include "../include/EtherCAT_rt.h"
/*****************************************************************************/
/**
Typ eines EtherCAT-Slaves.
Features eines EtherCAT-Slaves.
Dieser Typ muss für die Konfiguration bekannt sein. Der
Diese Angabe muss für die Konfiguration bekannt sein. Der
Master entscheidet danach, ober bspw. Mailboxes konfigurieren,
oder Sync-Manager setzen soll.
*/
@ -25,7 +27,7 @@ typedef enum
{
EC_SIMPLE_SLAVE, EC_MAILBOX_SLAVE, EC_NOSYNC_SLAVE
}
ec_slave_type_t;
ec_slave_features_t;
/*****************************************************************************/
@ -37,13 +39,13 @@ ec_slave_type_t;
Slave-internen Sync-Manager und FMMU's.
*/
typedef struct slave_desc
struct ec_slave_type
{
const char *vendor_name; /**< Name des Herstellers */
const char *product_name; /**< Name des Slaves-Typs */
const char *product_desc; /**< Genauere Beschreibung des Slave-Typs */
const ec_slave_type_t type; /**< Art des Slave-Typs */
ec_slave_features_t features; /**< Features des Slave-Typs */
const unsigned char *sm0; /**< Konfigurationsdaten des
ersten Sync-Managers */
@ -57,16 +59,8 @@ typedef struct slave_desc
const unsigned char *fmmu0; /**< Konfigurationsdaten
der ersten FMMU */
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 */
void (*write) (unsigned char *, unsigned int, int); /**< Funktion zum
Kodieren und Schreiben
der Kanaldaten */
}
ec_slave_desc_t;
unsigned int process_data_size; /**< Länge der Prozessdaten in Bytes */
};
/*****************************************************************************/
@ -79,10 +73,9 @@ ec_slave_desc_t;
typedef struct slave_ident
{
const unsigned int vendor_id; /**< Hersteller-Code */
const unsigned int product_code; /**< Herstellerspezifischer Produktcode */
const ec_slave_desc_t *desc; /**< Zeiger auf den dazugehörigen
Slave-Typ */
unsigned int vendor_id; /**< Hersteller-Code */
unsigned int product_code; /**< Herstellerspezifischer Produktcode */
const ec_slave_type_t *type; /**< Zeiger auf den entsprechenden Slave-Typ */
}
ec_slave_ident_t;

View File

@ -59,7 +59,7 @@ static void run(unsigned long data)
// Prozessdaten lesen und schreiben
rdtscl(k);
EtherCAT_rt_domain_cycle(master, 1, 100);
EtherCAT_rt_exchange_io(master, 1, 100);
firstrun = 0;
timer.expires += HZ / 1000;

View File

@ -55,23 +55,23 @@ ec_master_t *master = NULL;
static unsigned int ecat_bus_time = 0;
static unsigned int ecat_timeouts = 0;
#if 0
static ec_slave_t slaves[] =
{
// Block 1
ECAT_INIT_SLAVE(Beckhoff_EK1100, 0),
ECAT_INIT_SLAVE(Beckhoff_EL3102, 0)
};
#endif
ec_slave_t *s_controller;
ec_slave_t *s_analog_in;
#define ECAT_SLAVES_COUNT (sizeof(ecat_slaves) / sizeof(EtherCAT_slave_t))
#define USE_MSR_LIB
#ifdef USE_MSR_LIB
double value;
int dig1;
#endif
/*****************************************************************************/
static int register_slaves(void)
{
s_controller = EtherCAT_rt_register_slave(master, 0,
"Beckhoff", "EK1100", 0);
s_analog_in = EtherCAT_rt_register_slave(master, 1,
"Beckhoff", "EL3102", 0);
return !s_controller || !s_analog_in;
}
/******************************************************************************
*
@ -93,7 +93,7 @@ static void msr_controller_run(void)
#endif
// Prozessdaten lesen und schreiben
EtherCAT_rt_domain_cycle(master, 0, 40);
EtherCAT_rt_exchange_io(master, 0, 40);
#if 0
if (debug_counter == 0) {
@ -126,12 +126,10 @@ void msr_run(unsigned irq)
{
static int counter = 0;
#ifdef USE_MSR_LIB
// Schreibe Kanal1 von Klemme X auf 1
timeval_add(&process_time, &process_time, &msr_time_increment);
MSR_ADEOS_INTERRUPT_CODE(msr_controller_run(); msr_write_kanal_list(););
#else
msr_controller_run();
#endif
ipipe_control_irq(irq,0,IPIPE_ENABLE_MASK); //Interrupt bestŽätigen
if (counter++ > HZREDUCTION) {
@ -169,10 +167,8 @@ void domain_entry(void)
int msr_globals_register(void)
{
#ifdef USE_MSR_LIB
msr_reg_kanal("/value", "V", &value, TDBL);
msr_reg_kanal("/dig1", "", &dig1, TINT);
#endif
msr_reg_kanal("/Taskinfo/EtherCAT/BusTime", "us", &ecat_bus_time, TUINT);
msr_reg_kanal("/Taskinfo/EtherCAT/Timeouts", "", &ecat_timeouts, TUINT);
@ -189,29 +185,25 @@ int __init init_rt_module(void)
struct ipipe_domain_attr attr; //ipipe
// Als allererstes die RT-lib initialisieren
#ifdef USE_MSR_LIB
if (msr_rtlib_init(1,MSR_ABTASTFREQUENZ,10,&msr_globals_register) < 0) {
msr_print_warn("msr_modul: can't initialize rtlib!");
goto out_return;
}
#endif
msr_jitter_init();
printk(KERN_INFO "=== Starting EtherCAT environment... ===\n");
if ((master = EtherCAT_rt_request_master(0)) == NULL) {
printk(KERN_ERR "EtherCAT master 0 not available!\n");
printk(KERN_ERR "Error requesting master 0!\n");
goto out_msr_cleanup;
}
#if 0
printk("Checking EtherCAT slaves.\n");
if (EtherCAT_check_slaves(master, ecat_slaves, ECAT_SLAVES_COUNT) != 0) {
printk("Registering EtherCAT slaves.\n");
if (register_slaves()) {
printk(KERN_ERR "EtherCAT: Could not init slaves!\n");
goto out_release_master;
}
#endif
printk("Activating all EtherCAT slaves.\n");
@ -266,9 +258,7 @@ void __exit cleanup_rt_module(void)
printk(KERN_INFO "=== EtherCAT environment stopped. ===\n");
}
#ifdef USE_MSR_LIB
msr_rtlib_cleanup();
#endif
}
/*****************************************************************************/
@ -281,3 +271,9 @@ module_init(init_rt_module);
module_exit(cleanup_rt_module);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/