Translated all comments and documentation to english language.

This commit is contained in:
Florian Pose 2006-04-20 13:31:31 +00:00
parent 09ac0b540f
commit 91c739da77
27 changed files with 1114 additions and 1381 deletions

View File

@ -9,7 +9,7 @@
ifneq ($(KERNELRELEASE),)
#------------------------------------------------------------------------------
# kbuild section
# kbuild section
obj-m := master/ devices/
@ -18,7 +18,7 @@ obj-m := master/ devices/
else
#------------------------------------------------------------------------------
# default section
# default section
ifneq ($(wildcard ethercat.conf),)
include ethercat.conf

View File

@ -2,14 +2,15 @@
*
* 8 1 3 9 t o o . c
*
* EtherCAT-Treiber für RTL8139-kompatible Netzwerkkarten.
* EtherCAT driver for RTL8139-compatible NICs.
*
* Autoren: Wilhelm Hagemeister, Florian Pose
* Authors: Florian Pose <fp@igh-essen.com>
* Wilhelm Hagemeister <hm@igh-essen.com>
*
* $Date$
* $Author$
*
* (C) Copyright IgH 2005
* (C) Copyright IgH 2006
* Ingenieurgemeinschaft IgH
* Heinz-Bäcker Str. 34
* D-45356 Essen
@ -112,7 +113,6 @@
#define DRV_NAME "8139too_ec"
#define DRV_VERSION "0.9.27"
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@ -644,8 +644,10 @@ struct rtl8139_private {
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
MODULE_AUTHOR ("Wilhelm Hagemeister <hm@igh-essen.com>, Florian Pose <fp@igh-essen.com>");
MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver with EtherCAT functionality");
MODULE_AUTHOR("Wilhelm Hagemeister <hm@igh-essen.com>,"
" Florian Pose <fp@igh-essen.com>");
MODULE_DESCRIPTION("RealTek RTL-8139 Fast Ethernet"
" driver with EtherCAT functionality");
MODULE_LICENSE("GPL");
MODULE_VERSION(COMPILE_INFO);
@ -664,8 +666,10 @@ MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
module_param(ec_device_index, int, -1);
module_param(ec_device_master_index, int, 0);
MODULE_PARM_DESC(ec_device_index, "Index of the device reserved for EtherCAT.");
MODULE_PARM_DESC(ec_device_master_index, "Index of the EtherCAT master to register the device.");
MODULE_PARM_DESC(ec_device_index,
"Index of the device reserved for EtherCAT.");
MODULE_PARM_DESC(ec_device_master_index,
"Index of the EtherCAT master to register the device.");
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1082,12 +1086,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* EtherCAT-Karten nicht beim Stack anmelden. */
if (dev != rtl_ec_net_dev)
{
DPRINTK("About to register device named %s (%p)...\n", dev->name, dev);
i = register_netdev (dev);
if (i) goto err_out;
if (dev != rtl_ec_net_dev) {
DPRINTK("About to register device named %s (%p)...\n",
dev->name, dev);
i = register_netdev (dev);
if (i) goto err_out;
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1181,9 +1184,8 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
unregister_netdev (dev);
if (dev != rtl_ec_net_dev) {
unregister_netdev (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1394,11 +1396,11 @@ static int rtl8139_open (struct net_device *dev)
printk(KERN_DEBUG "%s: open\n", dev->name);
#endif
if (dev != rtl_ec_net_dev)
{
retval = request_irq(dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
if (retval)
return retval;
if (dev != rtl_ec_net_dev) {
retval = request_irq(dev->irq, rtl8139_interrupt,
SA_SHIRQ, dev->name, dev);
if (retval)
return retval;
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1411,9 +1413,8 @@ static int rtl8139_open (struct net_device *dev)
{
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
free_irq(dev->irq, dev);
if (dev != rtl_ec_net_dev) {
free_irq(dev->irq, dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1436,20 +1437,18 @@ static int rtl8139_open (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
netif_start_queue (dev);
if (dev != rtl_ec_net_dev) {
netif_start_queue (dev);
if (netif_msg_ifup(tp))
{
printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d"
" GP Pins %2.2x %s-duplex.\n",
dev->name, pci_resource_start (tp->pci_dev, 1),
dev->irq, RTL_R8 (MediaStatus),
tp->mii.full_duplex ? "full" : "half");
}
if (netif_msg_ifup(tp)) {
printk(KERN_DEBUG "%s: rtl8139_open() ioaddr %#lx IRQ %d"
" GP Pins %2.2x %s-duplex.\n",
dev->name, pci_resource_start (tp->pci_dev, 1),
dev->irq, RTL_R8 (MediaStatus),
tp->mii.full_duplex ? "full" : "half");
}
rtl8139_start_thread(dev);
rtl8139_start_thread(dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1536,10 +1535,9 @@ static void rtl8139_hw_start (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16 (IntrMask, rtl8139_intr_mask);
if (dev != rtl_ec_net_dev) {
/* Enable all known interrupts by setting the interrupt mask. */
RTL_W16 (IntrMask, rtl8139_intr_mask);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1805,32 +1803,29 @@ static void rtl8139_tx_timeout (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
spin_lock(&tp->rx_lock);
if (dev != rtl_ec_net_dev) {
spin_lock(&tp->rx_lock);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0x0000);
/* Stop a shared interrupt from scavenging while we are. */
spin_lock_irqsave (&tp->lock, flags);
rtl8139_tx_clear (tp);
spin_unlock_irqrestore (&tp->lock, flags);
/* Stop a shared interrupt from scavenging while we are. */
spin_lock_irqsave (&tp->lock, flags);
rtl8139_tx_clear (tp);
spin_unlock_irqrestore (&tp->lock, flags);
/* ...and finally, reset everything */
/* ...and finally, reset everything */
if (netif_running(dev))
{
rtl8139_hw_start (dev);
netif_wake_queue (dev);
}
if (netif_running(dev)) {
rtl8139_hw_start (dev);
netif_wake_queue (dev);
}
spin_unlock(&tp->rx_lock);
spin_unlock(&tp->rx_lock);
}
else
{
rtl8139_tx_clear (tp);
rtl8139_hw_start(dev);
else {
rtl8139_tx_clear (tp);
rtl8139_hw_start(dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1864,9 +1859,8 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
return 0;
}
if (dev != rtl_ec_net_dev)
{
spin_lock_irq(&tp->lock);
if (dev != rtl_ec_net_dev) {
spin_lock_irq(&tp->lock);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -1881,8 +1875,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
if (dev != rtl_ec_net_dev) {
if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx)
netif_stop_queue (dev);
@ -1972,9 +1965,8 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
netif_wake_queue (dev);
if (dev != rtl_ec_net_dev) {
netif_wake_queue (dev);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2184,42 +2176,41 @@ no_early_rx:
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
skb = dev_alloc_skb(pkt_size + 2);
if (dev != rtl_ec_net_dev) {
/* Malloc up new buffer, compatible with net-2e. */
/* Omit the four octet CRC from the length. */
skb = dev_alloc_skb(pkt_size + 2);
if (likely(skb)) {
skb->dev = dev;
skb_reserve (skb, 2); /* 16 byte align the IP fields. */
if (likely(skb)) {
skb->dev = dev;
skb_reserve (skb, 2); /* 16 byte align the IP fields. */
#if RX_BUF_IDX == 3
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
wrap_copy(skb, rx_ring, ring_offset+4, pkt_size);
#else
eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
#endif
skb_put (skb, pkt_size);
skb_put (skb, pkt_size);
skb->protocol = eth_type_trans (skb, dev);
skb->protocol = eth_type_trans (skb, dev);
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
netif_receive_skb (skb);
} else {
if (net_ratelimit())
printk (KERN_WARNING
"%s: Memory squeeze, dropping packet.\n",
dev->name);
tp->stats.rx_dropped++;
}
netif_receive_skb (skb);
} else {
if (net_ratelimit())
printk (KERN_WARNING
"%s: Memory squeeze, dropping packet.\n",
dev->name);
tp->stats.rx_dropped++;
}
}
else
{
ecdev_receive(rtl_ec_dev,
&rx_ring[ring_offset + 4] + ETH_HLEN,
pkt_size - ETH_HLEN);
&rx_ring[ring_offset + 4] + ETH_HLEN,
pkt_size - ETH_HLEN);
dev->last_rx = jiffies;
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
@ -2347,18 +2338,16 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev)
{
status = RTL_R16 (IntrStatus);
if (dev == rtl_ec_net_dev) {
status = RTL_R16 (IntrStatus);
}
else
{
spin_lock(&tp->lock);
else {
spin_lock(&tp->lock);
status = RTL_R16 (IntrStatus);
status = RTL_R16 (IntrStatus);
if (unlikely((status & rtl8139_intr_mask) == 0))
goto out;
if (unlikely((status & rtl8139_intr_mask) == 0))
goto out;
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2371,13 +2360,12 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
/* close possible race's with dev_close */
if (unlikely(!netif_running(dev))) {
RTL_W16 (IntrMask, 0);
goto out;
}
if (dev != rtl_ec_net_dev) {
/* close possible race's with dev_close */
if (unlikely(!netif_running(dev))) {
RTL_W16 (IntrMask, 0);
goto out;
}
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2399,19 +2387,17 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
if (status & RxAckBits)
{
if (dev != rtl_ec_net_dev)
{
/* Polling vormerken */
if (netif_rx_schedule_prep(dev)) {
RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
__netif_rx_schedule (dev);
if (dev != rtl_ec_net_dev) {
/* Mark for polling */
if (netif_rx_schedule_prep(dev)) {
RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
__netif_rx_schedule (dev);
}
}
else {
/* EtherCAT device: Just receive all frames */
rtl8139_rx(dev, tp, 100); // FIXME
}
}
else
{
/* Beim EtherCAT-Device einfach alle Frames empfangen */
rtl8139_rx(dev, tp, 100); // FIXME
}
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2429,9 +2415,8 @@ irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
out:
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
spin_unlock (&tp->lock);
if (dev != rtl_ec_net_dev) {
spin_unlock (&tp->lock);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2463,52 +2448,50 @@ static int rtl8139_close (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev != rtl_ec_net_dev)
{
netif_stop_queue(dev);
if (tp->thr_pid >= 0) {
tp->time_to_die = 1;
wmb();
ret = kill_proc (tp->thr_pid, SIGTERM, 1);
if (ret) {
printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
return ret;
}
wait_for_completion (&tp->thr_exited);
if (dev != rtl_ec_net_dev) {
netif_stop_queue(dev);
if (tp->thr_pid >= 0) {
tp->time_to_die = 1;
wmb();
ret = kill_proc (tp->thr_pid, SIGTERM, 1);
if (ret) {
printk (KERN_ERR "%s: unable to signal thread\n", dev->name);
return ret;
}
wait_for_completion (&tp->thr_exited);
}
if (netif_msg_ifdown(tp))
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
dev->name, RTL_R16 (IntrStatus));
if (netif_msg_ifdown(tp))
printk(KERN_DEBUG "%s: Shutting down ethercard, status was 0x%4.4x.\n",
dev->name, RTL_R16 (IntrStatus));
spin_lock_irqsave (&tp->lock, flags);
spin_lock_irqsave (&tp->lock, flags);
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
spin_unlock_irqrestore (&tp->lock, flags);
spin_unlock_irqrestore (&tp->lock, flags);
synchronize_irq (dev->irq); /* racy, but that's ok here */
free_irq (dev->irq, dev);
synchronize_irq (dev->irq); /* racy, but that's ok here */
free_irq (dev->irq, dev);
}
else
{
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
else {
/* Stop the chip's Tx and Rx DMA processes. */
RTL_W8 (ChipCmd, 0);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0);
/* Disable interrupts by clearing the interrupt mask. */
RTL_W16 (IntrMask, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
/* Update the error counts. */
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2729,7 +2712,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || !netif_running(dev))
return -EINVAL;
return -EINVAL;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2749,12 +2732,11 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || netif_running(dev))
{
spin_lock_irqsave (&tp->lock, flags);
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
spin_unlock_irqrestore (&tp->lock, flags);
if (dev == rtl_ec_net_dev || netif_running(dev)) {
spin_lock_irqsave (&tp->lock, flags);
tp->stats.rx_missed_errors += RTL_R32 (RxMissed);
RTL_W32 (RxMissed, 0);
spin_unlock_irqrestore (&tp->lock, flags);
}
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2837,7 +2819,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || !netif_running (dev))
return 0;
return 0;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2870,7 +2852,7 @@ static int rtl8139_resume (struct pci_dev *pdev)
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
if (dev == rtl_ec_net_dev || !netif_running (dev))
return 0;
return 0;
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
@ -2942,23 +2924,23 @@ static int __init rtl8139_init_module (void)
static void __exit rtl8139_cleanup_module (void)
{
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/* EtherCAT >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
if (rtl_ec_net_dev) {
printk(KERN_INFO "Stopping device...\n");
ecdev_stop(ec_device_master_index);
printk(KERN_INFO "Unregistering device...\n");
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
if (rtl_ec_net_dev) {
printk(KERN_INFO "Stopping device...\n");
ecdev_stop(ec_device_master_index);
printk(KERN_INFO "Unregistering device...\n");
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
rtl_ec_dev = NULL;
}
pci_unregister_driver(&rtl8139_pci_driver);
pci_unregister_driver(&rtl8139_pci_driver);
printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n");
printk(KERN_INFO "RTL8139-EtherCAT module cleaned up.\n");
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
/* EtherCAT <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
}

View File

@ -1,8 +1,8 @@
/******************************************************************************
*
* Oeffentliche EtherCAT-Schnittstellen fuer EtherCAT-Geraetetreiber.
* EtherCAT interface for EtherCAT device drivers.
*
* $Id$
* $Id$
*
*****************************************************************************/

View File

@ -1,6 +1,6 @@
/******************************************************************************
*
* Oeffentliche EtherCAT-Schnittstellen fuer Echtzeitprozesse.
* EtherCAT realtime interface.
*
* $Id$
*

View File

@ -28,14 +28,14 @@ const ec_code_msg_t sdo_abort_messages[];
/*****************************************************************************/
/**
Liest 32 Bit eines CANopen-SDOs im Expedited-Modus aus einem Slave.
\return 0 wenn alles ok, < 0 bei Fehler
Reads 32 bit of a CANopen SDO in expedited mode.
\return 0 in case of success, else < 0
*/
int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint8_t *target /**< Speicher für 4 Bytes */
int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint8_t *target /**< 4-byte memory */
)
{
size_t rec_size;
@ -45,14 +45,14 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
EC_WRITE_U16(data, 0x2 << 12); // SDO request
EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer
| 0x2 << 5)); // initiate upload request
| 0x2 << 5)); // initiate upload request
EC_WRITE_U16(data + 3, sdo_index);
EC_WRITE_U8 (data + 5, sdo_subindex);
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
sdo_index, sdo_subindex, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
@ -60,9 +60,9 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
}
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
EC_READ_U8 (data + 2) >> 5 != 0x2 || // Upload response
EC_READ_U16(data + 3) != sdo_index || // Index
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
EC_READ_U16(data + 3) != sdo_index || // index
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
EC_ERR("Invalid SDO upload response at slave %i!\n",
slave->ring_position);
@ -77,14 +77,14 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Beschreibt ein CANopen-SDO eines Slaves im Expedited-Modus.
\return 0 wenn alles ok, < 0 bei Fehler
Writes a CANopen SDO using expedited mode.
\return 0 in case of success, else < 0
*/
int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
const uint8_t *sdo_data, /**< Neuer Wert */
int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
const uint8_t *sdo_data, /**< new value */
size_t size
)
{
@ -111,7 +111,7 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
sdo_index, sdo_subindex, size, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
@ -119,9 +119,9 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
}
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
EC_READ_U16(data + 3) != sdo_index || // Index
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
EC_READ_U8 (data + 2) >> 5 != 0x3 || // download response
EC_READ_U16(data + 3) != sdo_index || // index
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
sdo_index, sdo_subindex, size);
EC_ERR("Invalid SDO download response at slave %i!\n",
@ -136,15 +136,17 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Liest ein CANopen-SDO im "Normal-Modus" aus einem Slave.
\return 0 wenn alles ok, < 0 bei Fehler
Reads a CANopen SDO in normal mode.
\return 0 in case of success, else < 0
\todo size
*/
int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint8_t *target, /**< Speicher für gel. Wert */
size_t *size /**< Größe des Speichers */
int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint8_t *target, /**< memory for value */
size_t *size /**< target memory size */
)
{
uint8_t *data;
@ -161,7 +163,7 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
sdo_index, sdo_subindex, slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
@ -169,9 +171,9 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
}
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
EC_READ_U8 (data + 2) >> 5 != 0x2 || // Initiate upload response
EC_READ_U16(data + 3) != sdo_index || // Index
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
EC_READ_U8 (data + 2) >> 5 != 0x2 || // initiate upload response
EC_READ_U16(data + 3) != sdo_index || // index
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
EC_ERR("Invalid SDO upload response at slave %i!\n",
slave->ring_position);
@ -205,11 +207,11 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Lädt das gesamte SDO-Dictionary aus einem Slave.
\return 0, wenn alles ok, sonst < 0
Fetches the SDO dictionary of a slave.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
{
uint8_t *data;
size_t rec_size;
@ -223,7 +225,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
EC_WRITE_U8 (data + 3, 0x00);
EC_WRITE_U16(data + 4, 0x0000);
EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs!
EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
if (unlikely(ec_master_simple_io(slave->master, &slave->mbox_command))) {
EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position);
@ -235,7 +237,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
return -1;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // Error response
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("SDO information error response at slave %i!\n",
slave->ring_position);
ec_canopen_abort_msg(EC_READ_U32(data + 6));
@ -259,7 +261,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
sdo_count = (rec_size - 8) / 2;
for (i = 0; i < sdo_count; i++) {
sdo_index = EC_READ_U16(data + 8 + i * 2);
if (!sdo_index) continue; // Manchmal ist der Index 0... ???
if (!sdo_index) continue; // sometimes index is 0... ???
if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate memory for SDO!\n");
@ -278,7 +280,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
}
while (EC_READ_U8(data + 2) & 0x80);
// Alle Beschreibungen laden
// Fetch all SDO descriptions
if (ec_slave_fetch_sdo_descriptions(slave)) return -1;
return 0;
@ -287,11 +289,11 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Holt die Beschreibungen zu allen bereits bekannten SDOs.
\return 0, wenn alles ok, sonst < 0
Fetches the SDO descriptions for the known SDOs.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT slave */)
{
uint8_t *data;
size_t rec_size, name_size;
@ -308,7 +310,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("SDO information error response at slave %i while"
" fetching SDO 0x%04X!\n", slave->ring_position,
sdo->index);
@ -354,7 +356,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
return -1;
}
// Alle Entries (Subindizes) laden
// Fetch all entries (subindices)
if (ec_slave_fetch_sdo_entries(slave, sdo, EC_READ_U8(data + 10)))
return -1;
}
@ -365,13 +367,13 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Lädt alle Entries (Subindizes) zu einem SDO.
\return 0, wenn alles ok, sonst < 0
Fetches all entries (subindices) to an SDO.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
ec_sdo_t *sdo, /**< SDO */
uint8_t subindices /**< Anzahl Subindizes */
uint8_t subindices /**< number of subindices */
)
{
uint8_t *data;
@ -394,7 +396,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
EC_ERR("SDO information error response at slave %i while"
" fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
sdo->index, i);
@ -403,7 +405,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
}
if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
(EC_READ_U8(data + 2) & 0x7F) != 0x06 || // entry descr. response
(EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
EC_READ_U16(data + 6) != sdo->index || // SDO index
EC_READ_U8(data + 8) != i) { // SDO subindex
EC_ERR("Invalid entry description response at slave %i while"
@ -449,7 +451,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Gibt eine SDO-Abort-Meldung aus.
Outputs an SDO abort message.
*/
void ec_canopen_abort_msg(uint32_t abort_code)
@ -506,21 +508,20 @@ const ec_code_msg_t sdo_abort_messages[] = {
{}
};
/*****************************************************************************/
// Echtzeitschnittstelle
/*****************************************************************************/
/******************************************************************************
* Realtime interface
*****************************************************************************/
/**
Liest ein 8-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
Siehe ec_slave_sdo_read_exp()
\return 0 wenn alles ok, < 0 bei Fehler
Reads an 8-bit SDO in expedited mode.
See ec_slave_sdo_read_exp()
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint8_t *target /**< Speicher für gel. Wert */
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint8_t *target /**< memory for read value */
)
{
uint8_t data[4];
@ -532,15 +533,15 @@ int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Liest ein 16-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
Siehe ec_slave_sdo_read_exp()
\return 0 wenn alles ok, < 0 bei Fehler
Reads a 16-bit SDO in expedited mode.
See ec_slave_sdo_read_exp()
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint16_t *target /**< Speicher für gel. Wert */
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint16_t *target /**< memory for read value */
)
{
uint8_t data[4];
@ -552,15 +553,15 @@ int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Liest ein 32-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
Siehe ec_slave_sdo_read_exp()
\return 0 wenn alles ok, < 0 bei Fehler
Reads a 32-bit SDO in expedited mode.
See ec_slave_sdo_read_exp()
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint32_t *target /**< Speicher für gel. Wert */
int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint32_t *target /**< memory for read value */
)
{
uint8_t data[4];
@ -572,14 +573,14 @@ int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Beschreibt ein 8-Bit CANopen-SDO eines Slaves im Expedited-Modus.
\return 0 wenn alles ok, < 0 bei Fehler
Writes an 8-bit SDO in expedited mode.
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint8_t value /**< Neuer Wert */
int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint8_t value /**< new value */
)
{
return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1);
@ -588,14 +589,14 @@ int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Beschreibt ein 16-Bit CANopen-SDO eines Slaves im Expedited-Modus.
\return 0 wenn alles ok, < 0 bei Fehler
Writes a 16-bit SDO in expedited mode.
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint16_t value /**< Neuer Wert */
int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint16_t value /**< new value */
)
{
uint8_t data[2];
@ -606,14 +607,14 @@ int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Beschreibt ein 32-Bit CANopen-SDO eines Slaves im Expedited-Modus.
\return 0 wenn alles ok, < 0 bei Fehler
Writes a 32-bit SDO in expedited mode.
\return 0 in case of success, else < 0
*/
int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
uint16_t sdo_index, /**< SDO-Index */
uint8_t sdo_subindex, /**< SDO-Subindex */
uint32_t value /**< Neuer Wert */
int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT slave */
uint16_t sdo_index, /**< SDO index */
uint8_t sdo_subindex, /**< SDO subindex */
uint32_t value /**< new value */
)
{
uint8_t data[4];
@ -632,9 +633,3 @@ EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32);
EXPORT_SYMBOL(ecrt_slave_sdo_read);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* c o m m a n d . c
*
* Methoden für ein EtherCAT-Kommando.
* Methods of an EtherCAT command.
*
* $Id$
*
@ -31,7 +31,7 @@
/*****************************************************************************/
/**
EtherCAT-Kommando-Konstruktor.
Command constructor.
*/
void ec_command_init(ec_command_t *command)
@ -49,7 +49,7 @@ void ec_command_init(ec_command_t *command)
/*****************************************************************************/
/**
EtherCAT-Kommando-Destruktor.
Command destructor.
*/
void ec_command_clear(ec_command_t *command)
@ -60,7 +60,8 @@ void ec_command_clear(ec_command_t *command)
/*****************************************************************************/
/**
Alloziert Speicher.
Allocates command data memory.
\return 0 in case of success, else < 0
*/
int ec_command_prealloc(ec_command_t *command, size_t size)
@ -85,19 +86,19 @@ int ec_command_prealloc(ec_command_t *command, size_t size)
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-NPRD-Kommando.
Initializes an EtherCAT NPRD command.
Node-adressed physical read.
\return 0 in case of success, else < 0
*/
int ec_command_nprd(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t node_address,
/**< Adresse des Knotens (Slaves) */
/**< configured station address */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu lesenden Daten */
/**< number of bytes to read */
)
{
if (unlikely(node_address == 0x0000))
@ -113,19 +114,19 @@ int ec_command_nprd(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-NPWR-Kommando.
Initializes an EtherCAT NPWR command.
Node-adressed physical write.
\return 0 in case of success, else < 0
*/
int ec_command_npwr(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t node_address,
/**< Adresse des Knotens (Slaves) */
/**< configured station address */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu schreibenden Daten */
/**< number of bytes to write */
)
{
if (unlikely(node_address == 0x0000))
@ -141,19 +142,19 @@ int ec_command_npwr(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-APRD-Kommando.
Initializes an EtherCAT APRD command.
Autoincrement physical read.
\return 0 in case of success, else < 0
*/
int ec_command_aprd(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t ring_position,
/**< Position des Slaves im Bus */
/**< auto-increment position */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu lesenden Daten */
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
@ -166,19 +167,19 @@ int ec_command_aprd(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-APWR-Kommando.
Initializes an EtherCAT APWR command.
Autoincrement physical write.
\return 0 in case of success, else < 0
*/
int ec_command_apwr(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t ring_position,
/**< Position des Slaves im Bus */
/**< auto-increment position */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu schreibenden Daten */
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
@ -191,17 +192,17 @@ int ec_command_apwr(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-BRD-Kommando.
Initializes an EtherCAT BRD command.
Broadcast read.
\return 0 in case of success, else < 0
*/
int ec_command_brd(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu lesenden Daten */
/**< number of bytes to read */
)
{
EC_FUNC_HEADER;
@ -214,17 +215,17 @@ int ec_command_brd(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-BWR-Kommando.
Initializes an EtherCAT BWR command.
Broadcast write.
\return 0 in case of success, else < 0
*/
int ec_command_bwr(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint16_t offset,
/**< Physikalische Speicheradresse im Slave */
/**< physical memory address */
size_t data_size
/**< Länge der zu schreibenden Daten */
/**< number of bytes to write */
)
{
EC_FUNC_HEADER;
@ -237,17 +238,17 @@ int ec_command_bwr(ec_command_t *command,
/*****************************************************************************/
/**
Initialisiert ein EtherCAT-LRW-Kommando.
Initializes an EtherCAT LRW command.
Logical read write.
\return 0 in case of success, else < 0
*/
int ec_command_lrw(ec_command_t *command,
/**< EtherCAT-Rahmen */
/**< EtherCAT command */
uint32_t offset,
/**< Logische Startadresse */
/**< logical address */
size_t data_size
/**< Länge der zu lesenden/schreibenden Daten */
/**< number of bytes to read/write */
)
{
EC_FUNC_HEADER;
@ -257,9 +258,3 @@ int ec_command_lrw(ec_command_t *command,
}
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* c o m m a n d . h
*
* Struktur für ein EtherCAT-Kommando.
* EtherCAT command structure.
*
* $Id$
*
@ -18,7 +18,7 @@
/*****************************************************************************/
/**
EtherCAT-Kommando-Typ.
EtherCAT command type.
*/
typedef enum
@ -35,65 +35,57 @@ typedef enum
ec_command_type_t;
/**
EtherCAT-Kommando-Zustand.
EtherCAT command state.
*/
typedef enum
{
EC_CMD_INIT, /**< Neues Kommando */
EC_CMD_QUEUED, /**< Kommando in Warteschlange */
EC_CMD_SENT, /**< Kommando gesendet */
EC_CMD_RECEIVED, /**< Kommando empfangen */
EC_CMD_TIMEOUT, /**< Zeitgrenze überschritten */
EC_CMD_ERROR /**< Fehler beim Senden oder Empfangen */
EC_CMD_INIT, /**< new command */
EC_CMD_QUEUED, /**< command queued by master */
EC_CMD_SENT, /**< command has been sent */
EC_CMD_RECEIVED, /**< command has been received */
EC_CMD_TIMEOUT, /**< command timed out */
EC_CMD_ERROR /**< error while sending/receiving */
}
ec_command_state_t;
/*****************************************************************************/
/**
EtherCAT-Adresse.
Im EtherCAT-Kommando sind 4 Bytes für die Adresse reserviert, die je nach
Kommandotyp, eine andere Bedeutung haben können: Bei Autoinkrementbefehlen
sind die ersten zwei Bytes die (negative) Autoinkrement-Adresse, bei Knoten-
adressierten Befehlen entsprechen sie der Knotenadresse. Das dritte und
vierte Byte entspricht in diesen Fällen der physikalischen Speicheradresse
auf dem Slave. Bei einer logischen Adressierung entsprechen alle vier Bytes
der logischen Adresse.
EtherCAT address.
*/
typedef union
{
struct
{
uint16_t slave; /**< Adresse des Slaves (Ringposition oder Knoten) */
uint16_t mem; /**< Physikalische Speicheradresse im Slave */
uint16_t slave; /**< configured or autoincrement address */
uint16_t mem; /**< physical memory address */
}
physical; /**< Physikalische Adresse */
physical; /**< physical address */
uint32_t logical; /**< Logische Adresse */
uint32_t logical; /**< logical address */
}
ec_address_t;
/*****************************************************************************/
/**
EtherCAT-Kommando.
EtherCAT command
*/
typedef struct
{
struct list_head list; /**< Kommando-Listeneintrag */
struct list_head queue; /**< Master-Kommando-Queue */
ec_command_type_t type; /**< Typ des Kommandos (APRD, NPWR, etc) */
ec_address_t address; /**< Adresse des/der Empfänger */
uint8_t *data; /**< Kommandodaten */
size_t mem_size; /**< Größe des Speichers */
size_t data_size; /**< Länge der zu sendenden und/oder empfangenen Daten */
uint8_t index; /**< Kommando-Index, wird vom Master beim Senden gesetzt. */
uint16_t working_counter; /**< Working-Counter */
ec_command_state_t state; /**< Zustand */
struct list_head list; /**< needed by domain command lists */
struct list_head queue; /**< master command queue item */
ec_command_type_t type; /**< command type (APRD, BWR, etc) */
ec_address_t address; /**< receipient address */
uint8_t *data; /**< command data */
size_t mem_size; /**< command \a data memory size */
size_t data_size; /**< size of the data in \a data */
uint8_t index; /**< command index (set by master) */
uint16_t working_counter; /**< working counter */
ec_command_state_t state; /**< command state */
}
ec_command_t;
@ -113,9 +105,3 @@ int ec_command_lrw(ec_command_t *, uint32_t, size_t);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* d e v i c e . c
*
* Methoden für ein EtherCAT-Gerät.
* EtherCAT device methods.
*
* $Id$
*
@ -20,16 +20,15 @@
/*****************************************************************************/
/**
EtherCAT-Geräte-Konstuktor.
\return 0 wenn alles ok, < 0 bei Fehler (zu wenig Speicher)
Device constructor.
\return 0 in case of success, else < 0
*/
int ec_device_init(ec_device_t *device, /**< EtherCAT-Gerät */
ec_master_t *master, /**< Zugehöriger Master */
struct net_device *net_dev, /**< Net-Device */
ec_isr_t isr, /**< Adresse der ISR */
struct module *module /**< Modul-Adresse */
int ec_device_init(ec_device_t *device, /**< EtherCAT device */
ec_master_t *master, /**< master owning the device */
struct net_device *net_dev, /**< net_device structure */
ec_isr_t isr, /**< pointer to device's ISR */
struct module *module /**< pointer to the owning module */
)
{
struct ethhdr *eth;
@ -49,7 +48,7 @@ int ec_device_init(ec_device_t *device, /**< EtherCAT-Ger
device->tx_skb->dev = net_dev;
// Ethernet-II-Header hinzufuegen
// add Ethernet-II-header
skb_reserve(device->tx_skb, ETH_HLEN);
eth = (struct ethhdr *) skb_push(device->tx_skb, ETH_HLEN);
eth->h_proto = htons(0x88A4);
@ -62,13 +61,10 @@ int ec_device_init(ec_device_t *device, /**< EtherCAT-Ger
/*****************************************************************************/
/**
EtherCAT-Geräte-Destuktor.
Gibt den dynamisch allozierten Speicher des
EtherCAT-Gerätes (den Sende-Socket-Buffer) wieder frei.
EtherCAT device destuctor.
*/
void ec_device_clear(ec_device_t *device /**< EtherCAT-Gerät */)
void ec_device_clear(ec_device_t *device /**< EtherCAT device */)
{
if (device->open) ec_device_close(device);
if (device->tx_skb) dev_kfree_skb(device->tx_skb);
@ -77,17 +73,11 @@ void ec_device_clear(ec_device_t *device /**< EtherCAT-Ger
/*****************************************************************************/
/**
Führt die open()-Funktion des Netzwerktreibers aus.
Dies entspricht einem "ifconfig up". Vorher wird der Zeiger
auf das EtherCAT-Gerät auf Gültigkeit geprüft und der
Gerätezustand zurückgesetzt.
\return 0 bei Erfolg, < 0: Ungültiger Zeiger, oder open()
fehlgeschlagen
Opens the EtherCAT device.
\return 0 in case of success, else < 0
*/
int ec_device_open(ec_device_t *device /**< EtherCAT-Gerät */)
int ec_device_open(ec_device_t *device /**< EtherCAT device */)
{
unsigned int i;
@ -101,7 +91,7 @@ int ec_device_open(ec_device_t *device /**< EtherCAT-Ger
return 0;
}
// Device could have received frames before
// device could have received frames before
for (i = 0; i < 4; i++) ec_device_call_isr(device);
device->link_state = 0;
@ -114,13 +104,11 @@ int ec_device_open(ec_device_t *device /**< EtherCAT-Ger
/*****************************************************************************/
/**
Führt die stop()-Funktion des net_devices aus.
\return 0 bei Erfolg, < 0: Kein Gerät zum Schließen oder
Schließen fehlgeschlagen.
Stops the EtherCAT device.
\return 0 in case of success, else < 0
*/
int ec_device_close(ec_device_t *device /**< EtherCAT-Gerät */)
int ec_device_close(ec_device_t *device /**< EtherCAT device */)
{
if (!device->dev) {
EC_ERR("No device to close!\n");
@ -140,12 +128,11 @@ int ec_device_close(ec_device_t *device /**< EtherCAT-Ger
/*****************************************************************************/
/**
Liefert einen Zeiger auf den Sende-Speicher.
\return Zeiger auf den Speicher, in den die Frame-Daten sollen.
Returns a pointer to the device's transmit memory.
\return pointer to the TX socket buffer
*/
uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT-Gerät */)
uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */)
{
return device->tx_skb->data + ETH_HLEN;
}
@ -153,21 +140,19 @@ uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT-Ger
/*****************************************************************************/
/**
Sendet den Inhalt des Socket-Buffers.
Schneidet den Inhalt des Socket-Buffers auf die (nun bekannte) Größe zu,
fügt den Ethernet-II-Header an und ruft die start_xmit()-Funktion der
Netzwerkkarte auf.
Sends the content of the transmit socket buffer.
Cuts the socket buffer content to the (now known) size, and calls the
start_xmit() function of the assigned net_device.
*/
void ec_device_send(ec_device_t *device, /**< EtherCAT-Gerät */
size_t size /**< Größe der zu sendenden Daten */
void ec_device_send(ec_device_t *device, /**< EtherCAT device */
size_t size /**< number of bytes to send */
)
{
if (unlikely(!device->link_state)) // Link down
return;
// Framegröße auf (jetzt bekannte) Länge abschneiden
// set the right length for the data
device->tx_skb->len = ETH_HLEN + size;
if (unlikely(device->master->debug_level > 1)) {
@ -175,36 +160,33 @@ void ec_device_send(ec_device_t *device, /**< EtherCAT-Ger
ec_print_data(device->tx_skb->data + ETH_HLEN, size);
}
// Senden einleiten
// start sending
device->dev->hard_start_xmit(device->tx_skb, device->dev);
}
/*****************************************************************************/
/**
Ruft die Interrupt-Routine der Netzwerkkarte auf.
Calls the interrupt service routine of the assigned net_device.
*/
void ec_device_call_isr(ec_device_t *device /**< EtherCAT-Gerät */)
void ec_device_call_isr(ec_device_t *device /**< EtherCAT device */)
{
if (likely(device->isr)) device->isr(0, device->dev, NULL);
}
/******************************************************************************
*
* Treiberschnittstelle
*
* Device interface
*****************************************************************************/
/**
Nimmt einen Empfangenen Rahmen entgegen.
Kopiert die empfangenen Daten in den Receive-Buffer.
Accepts a received frame.
Forwards the received data to the master.
*/
void ecdev_receive(ec_device_t *device, /**< EtherCAT-Gerät */
const void *data, /**< Zeiger auf empfangene Daten */
size_t size /**< Größe der empfangenen Daten */
void ecdev_receive(ec_device_t *device, /**< EtherCAT device */
const void *data, /**< pointer to receibed data */
size_t size /**< number of bytes received */
)
{
if (unlikely(device->master->debug_level > 1)) {
@ -218,11 +200,11 @@ void ecdev_receive(ec_device_t *device, /**< EtherCAT-Ger
/*****************************************************************************/
/**
Setzt einen neuen Verbindungszustand.
Sets a new link state.
*/
void ecdev_link_state(ec_device_t *device, /**< EtherCAT-Gerät */
uint8_t state /**< Verbindungszustand */
void ecdev_link_state(ec_device_t *device, /**< EtherCAT device */
uint8_t state /**< new link state */
)
{
if (unlikely(!device)) {
@ -242,9 +224,3 @@ EXPORT_SYMBOL(ecdev_receive);
EXPORT_SYMBOL(ecdev_link_state);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* d e v i c e . h
*
* Struktur für ein EtherCAT-Gerät.
* EtherCAT device structure.
*
* $Id$
*
@ -20,23 +20,21 @@
/*****************************************************************************/
/**
EtherCAT-Gerät.
EtherCAT device.
Ein EtherCAT-Gerät ist eine Netzwerkkarte, die vom
EtherCAT-Master dazu verwendet wird, um Frames zu senden
und zu empfangen.
An EtherCAT device is a network interface card, that is owned by an
EtherCAT master to send and receive EtherCAT frames with.
*/
struct ec_device
{
ec_master_t *master; /**< EtherCAT-Master */
struct net_device *dev; /**< Zeiger auf das reservierte net_device */
uint8_t open; /**< Das net_device ist geoeffnet. */
struct sk_buff *tx_skb; /**< Zeiger auf Transmit-Socketbuffer */
ec_isr_t isr; /**< Adresse der ISR */
struct module *module; /**< Zeiger auf das Modul, das das Gerät zur
Verfügung stellt. */
uint8_t link_state; /**< Verbindungszustand */
ec_master_t *master; /**< EtherCAT master */
struct net_device *dev; /**< pointer to the assigned net_device */
uint8_t open; /**< true, if the net_device has been opened */
struct sk_buff *tx_skb; /**< transmit socket buffer */
ec_isr_t isr; /**< pointer to the device's interrupt service routine */
struct module *module; /**< pointer to the device's owning module */
uint8_t link_state; /**< device link state */
};
/*****************************************************************************/
@ -55,9 +53,3 @@ void ec_device_send(ec_device_t *, size_t);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* d o m a i n . c
*
* Methoden für Gruppen von EtherCAT-Slaves.
* EtherCAT domain methods.
*
* $Id$
*
@ -40,12 +40,13 @@ static struct kobj_type ktype_ec_domain = {
/*****************************************************************************/
/**
Konstruktor einer EtherCAT-Domäne.
Domain constructor.
\return 0 in case of success, else < 0
*/
int ec_domain_init(ec_domain_t *domain, /**< Domäne */
ec_master_t *master, /**< Zugehöriger Master */
unsigned int index /**< Domänen-Index */
int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
ec_master_t *master, /**< owning master */
unsigned int index /**< domain index */
)
{
domain->master = master;
@ -57,7 +58,7 @@ int ec_domain_init(ec_domain_t *domain, /**< Dom
INIT_LIST_HEAD(&domain->field_regs);
INIT_LIST_HEAD(&domain->commands);
// Init kobject and add it to the hierarchy
// init kobject and add it to the hierarchy
memset(&domain->kobj, 0x00, sizeof(struct kobject));
kobject_init(&domain->kobj);
domain->kobj.ktype = &ktype_ec_domain;
@ -73,10 +74,10 @@ int ec_domain_init(ec_domain_t *domain, /**< Dom
/*****************************************************************************/
/**
Destruktor einer EtherCAT-Domäne.
Domain destructor.
*/
void ec_domain_clear(struct kobject *kobj /**< Kobject der Domäne */)
void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
{
ec_command_t *command, *next;
ec_domain_t *domain;
@ -98,16 +99,16 @@ void ec_domain_clear(struct kobject *kobj /**< Kobject der Dom
/*****************************************************************************/
/**
Registriert ein Feld in einer Domäne.
\return 0 bei Erfolg, < 0 bei Fehler
Registeres a data field in a domain.
\return 0 in case of success, else < 0
*/
int ec_domain_reg_field(ec_domain_t *domain, /**< Domäne */
ec_slave_t *slave, /**< Slave */
const ec_sync_t *sync, /**< Sync-Manager */
uint32_t field_offset, /**< Datenfeld-Offset */
void **data_ptr /**< Adresse des Prozessdatenzeigers */
int ec_domain_reg_field(ec_domain_t *domain, /**< EtherCAT domain */
ec_slave_t *slave, /**< slave */
const ec_sync_t *sync, /**< sync manager */
uint32_t field_offset, /**< data field offset */
void **data_ptr /**< pointer to the process data
pointer */
)
{
ec_field_reg_t *field_reg;
@ -136,10 +137,10 @@ int ec_domain_reg_field(ec_domain_t *domain, /**< Dom
/*****************************************************************************/
/**
Gibt die Liste der registrierten Datenfelder frei.
Clears the list of the registered data fields.
*/
void ec_domain_clear_field_regs(ec_domain_t *domain)
void ec_domain_clear_field_regs(ec_domain_t *domain /**< EtherCAT domain */)
{
ec_field_reg_t *field_reg, *next;
@ -152,12 +153,13 @@ void ec_domain_clear_field_regs(ec_domain_t *domain)
/*****************************************************************************/
/**
Alloziert ein Prozessdatenkommando und fügt es in die Liste ein.
Allocates a process data command and appends it to the list.
\return 0 in case of success, else < 0
*/
int ec_domain_add_command(ec_domain_t *domain, /**< Domäne */
uint32_t offset, /**< Logisches Offset */
size_t data_size /**< Größe der Kommando-Daten */
int ec_domain_add_command(ec_domain_t *domain, /**< EtherCAT domain */
uint32_t offset, /**< logical offset */
size_t data_size /**< size of the command data */
)
{
ec_command_t *command;
@ -181,15 +183,14 @@ int ec_domain_add_command(ec_domain_t *domain, /**< Dom
/*****************************************************************************/
/**
Erzeugt eine Domäne.
Reserviert den Speicher einer Domäne, berechnet die logischen Adressen der
FMMUs und setzt die Prozessdatenzeiger der registrierten Felder.
\return 0 bei Erfolg, < 0 bei Fehler
Creates a domain.
Reserves domain memory, calculates the logical addresses of the
corresponding FMMUs and sets the process data pointer of the registered
data fields.
\return 0 in case of success, else < 0
*/
int ec_domain_alloc(ec_domain_t *domain, /**< Domäne */
int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
uint32_t base_address /**< Logische Basisadresse */
)
{
@ -276,30 +277,33 @@ int ec_domain_alloc(ec_domain_t *domain, /**< Dom
/*****************************************************************************/
/**
Gibt die Anzahl der antwortenden Slaves aus.
Sets the number of responding slaves and outputs it on demand.
This number isn't really the number of responding slaves, but the sum of
the working counters of all domain commands. Some slaves increase the
working counter by 2, some by 1.
*/
void ec_domain_response_count(ec_domain_t *domain, /**< Domäne */
unsigned int count /**< Neue Anzahl */
void ec_domain_response_count(ec_domain_t *domain, /**< EtherCAT domain */
unsigned int count /**< new WC sum */
)
{
if (count != domain->response_count) {
domain->response_count = count;
EC_INFO("Domain %i working counter change: %i\n", domain->index, count);
EC_INFO("Domain %i working counter change: %i\n", domain->index,
count);
}
}
/*****************************************************************************/
/**
Formatiert Attribut-Daten für lesenden Zugriff im SysFS
\return Anzahl Bytes im Speicher
Formats attribute data for SysFS reading.
\return number of bytes to read
*/
ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< KObject */
struct attribute *attr, /**< Attribut */
char *buffer /**< Speicher für die Daten */
ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< kobject */
struct attribute *attr, /**< attribute */
char *buffer /**< memory to store data in */
)
{
ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj);
@ -312,43 +316,39 @@ ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< KObject */
}
/******************************************************************************
*
* Echtzeitschnittstelle
*
* Realtime interface
*****************************************************************************/
/**
Registriert ein Datenfeld innerhalb einer Domäne.
- Ist \a data_ptr NULL, so wird der Slave nur auf den Typ überprüft.
- Wenn \a field_count 0 ist, wird angenommen, dass 1 Feld registriert werden
soll.
- Wenn \a field_count größer als 1 ist, wird angenommen, dass \a data_ptr
auf ein entsprechend großes Array zeigt.
\return Zeiger auf den Slave bei Erfolg, sonst NULL
Registers a data field in a domain.
- If \a data_ptr is NULL, the slave is only checked against its type.
- If \a field_count is 0, it is assumed that one data field is to be
registered.
- If \a field_count is greater then 1, it is assumed that \a data_ptr
is an array of the respective size.
\return pointer to the slave on success, else NULL
*/
ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
/**< Domäne */
/**< EtherCAT domain */
const char *address,
/**< ASCII-Addresse des Slaves,
siehe ecrt_master_get_slave() */
/**< ASCII address of the slave,
see ecrt_master_get_slave() */
const char *vendor_name,
/**< Herstellername */
/**< vendor name */
const char *product_name,
/**< Produktname */
/**< product name */
void **data_ptr,
/**< Adresse des Zeigers auf die
Prozessdaten */
/**< address of the process data
pointer */
const char *field_name,
/**< Name des Datenfeldes */
/**< data field name */
unsigned int field_index,
/**< Gibt an, ab welchem Feld mit
Typ \a field_type gezählt
werden soll. */
/**< offset of data fields with
\a field_type */
unsigned int field_count
/**< Anzahl Felder selben Typs */
/**< number of data fields (with
the same type) to register */
)
{
ec_slave_t *slave;
@ -361,7 +361,7 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
master = domain->master;
// Adresse übersetzen
// translate address
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
if (!(type = slave->type)) {
@ -379,7 +379,7 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
}
if (!data_ptr) {
// Wenn data_ptr NULL, Slave als registriert ansehen (nicht warnen).
// data_ptr is NULL => mark slave as "registered" (do not warn)
slave->registered = 1;
}
@ -415,17 +415,15 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
/*****************************************************************************/
/**
Registriert eine ganze Liste von Datenfeldern innerhalb einer Domäne.
Achtung: Die Liste muss mit einer NULL-Struktur ({}) abgeschlossen sein!
\return 0 bei Erfolg, sonst < 0
Registeres a bunch of data fields.
Caution! The list has to be terminated with a NULL structure ({})!
\return 0 in case of success, else < 0
*/
int ecrt_domain_register_field_list(ec_domain_t *domain,
/**< Domäne */
/**< EtherCAT domain */
const ec_field_init_t *fields
/**< Array mit Datenfeldern */
/**< array of data field registrations */
)
{
const ec_field_init_t *field;
@ -444,10 +442,10 @@ int ecrt_domain_register_field_list(ec_domain_t *domain,
/*****************************************************************************/
/**
Setzt Prozessdaten-Kommandos in die Warteschlange des Masters.
Places all process data commands in the masters command queue.
*/
void ecrt_domain_queue(ec_domain_t *domain /**< Domäne */)
void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
{
ec_command_t *command;
@ -459,10 +457,10 @@ void ecrt_domain_queue(ec_domain_t *domain /**< Dom
/*****************************************************************************/
/**
Verarbeitet empfangene Prozessdaten.
Processes received process data.
*/
void ecrt_domain_process(ec_domain_t *domain /**< Domäne */)
void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
{
unsigned int working_counter_sum;
ec_command_t *command;
@ -481,12 +479,11 @@ void ecrt_domain_process(ec_domain_t *domain /**< Dom
/*****************************************************************************/
/**
Gibt den Status einer Domäne zurück.
\return 0 wenn alle Kommandos empfangen wurden, sonst -1.
Returns the state of a domain.
\return 0 if all commands were received, else -1.
*/
int ecrt_domain_state(ec_domain_t *domain /**< Domäne */)
int ecrt_domain_state(ec_domain_t *domain /**< EtherCAT domain */)
{
ec_command_t *command;
@ -506,9 +503,3 @@ EXPORT_SYMBOL(ecrt_domain_process);
EXPORT_SYMBOL(ecrt_domain_state);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* d o m a i n . h
*
* Struktur für eine Gruppe von EtherCAT-Slaves.
* EtherCAT domain structure.
*
* $Id$
*
@ -21,39 +21,38 @@
/*****************************************************************************/
/**
Datenfeld-Konfiguration.
Data field registration type.
*/
typedef struct
{
struct list_head list;
ec_slave_t *slave;
const ec_sync_t *sync;
uint32_t field_offset;
void **data_ptr;
struct list_head list; /**< list item */
ec_slave_t *slave; /**< slave */
const ec_sync_t *sync; /**< sync manager */
uint32_t field_offset; /**< data field offset */
void **data_ptr; /**< pointer to process data pointer(s) */
}
ec_field_reg_t;
/*****************************************************************************/
/**
EtherCAT-Domäne
Verwaltet die Prozessdaten und das hierfür nötige Kommando einer bestimmten
Menge von Slaves.
EtherCAT domain.
Handles the process data and the therefore needed commands of a certain
group of slaves.
*/
struct ec_domain
{
struct kobject kobj; /**< Kobject der Domäne */
struct list_head list; /**< Listenkopf */
unsigned int index; /**< Domänen-Index */
ec_master_t *master; /**< EtherCAT-Master, zu der die Domäne gehört. */
size_t data_size; /**< Größe der Prozessdaten */
struct list_head commands; /**< EtherCAT-Kommandos für die Prozessdaten */
uint32_t base_address; /**< Logische Basisaddresse der Domain */
unsigned int response_count; /**< Anzahl antwortender Slaves */
struct list_head field_regs; /**< Liste der Datenfeldregistrierungen */
struct kobject kobj; /**< kobject */
struct list_head list; /**< list item */
unsigned int index; /**< domain index (just a number) */
ec_master_t *master; /**< EtherCAT master owning the domain */
size_t data_size; /**< size of the process data */
struct list_head commands; /**< process data commands */
uint32_t base_address; /**< logical offset address of the process data */
unsigned int response_count; /**< number of responding slaves */
struct list_head field_regs; /**< data field registrations */
};
/*****************************************************************************/
@ -65,9 +64,3 @@ int ec_domain_alloc(ec_domain_t *, uint32_t);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -117,9 +117,3 @@ void ec_eoe_print(const ec_eoe_t *eoe)
}
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -43,9 +43,3 @@ void ec_eoe_run(ec_eoe_t *);
void ec_eoe_print(const ec_eoe_t *);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* g l o b a l s . h
*
* Globale Definitionen und Makros für das EtherCAT-Protokoll.
* Global definitions and macros.
*
* $Id$
*
@ -16,21 +16,20 @@
/*****************************************************************************/
// EtherCAT-Protokoll
#define EC_MAX_FRAME_SIZE 1500 /**< Maximale Größe eines EtherCAT-Frames ohne
Ethernet-II-Header und -Prüfsumme */
#define EC_MIN_FRAME_SIZE 46 /** Minimale Größe, s. o. */
#define EC_FRAME_HEADER_SIZE 2 /**< Größe des EtherCAT-Frame-Headers */
#define EC_COMMAND_HEADER_SIZE 10 /**< Größe eines EtherCAT-Kommando-Headers */
#define EC_COMMAND_FOOTER_SIZE 2 /**< Größe eines EtherCAT-Kommando-Footers */
#define EC_SYNC_SIZE 8 /**< Größe einer Sync-Manager-Konfigurationsseite */
#define EC_FMMU_SIZE 16 /**< Größe einer FMMU-Konfigurationsseite */
#define EC_MAX_FMMUS 16 /**< Maximale Anzahl FMMUs pro Slave */
#define EC_MAX_FRAME_SIZE 1500 /**< maximum size of an EtherCAT frame (without
header and CRC) */
#define EC_MIN_FRAME_SIZE 46 /** ... minimum size */
#define EC_FRAME_HEADER_SIZE 2 /**< size of an EtherCAT frame header */
#define EC_COMMAND_HEADER_SIZE 10 /**< size of an EtherCAT command header */
#define EC_COMMAND_FOOTER_SIZE 2 /**< size of an EtherCAT command footer */
#define EC_SYNC_SIZE 8 /**< size of a sync manager configuration page */
#define EC_FMMU_SIZE 16 /**< size of an FMMU configuration page */
#define EC_MAX_FMMUS 16 /**< maximum number of FMMUs per slave */
#define EC_MAX_DATA_SIZE (EC_MAX_FRAME_SIZE \
- EC_FRAME_HEADER_SIZE \
- EC_COMMAND_HEADER_SIZE \
- EC_COMMAND_FOOTER_SIZE) /**< Maximale Datengröße
bei einem Kommando pro
Frame */
- EC_COMMAND_FOOTER_SIZE) /**< maximum data size of a
single command */
/*****************************************************************************/
@ -59,16 +58,15 @@ extern void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
/*****************************************************************************/
/**
Code - Message Pair.
Code - Message pair.
Some EtherCAT commands support reading a status code to display a certain
message. This type allows to map a code to a message string.
*/
typedef struct
{
uint32_t code; /**< Code */
const char *message; /**< Message belonging to \a code */
uint32_t code; /**< code */
const char *message; /**< message belonging to \a code */
}
ec_code_msg_t;
@ -76,8 +74,3 @@ ec_code_msg_t;
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* m a i l b o x . c
*
* Mailbox-Funktionen
* Mailbox functionality.
*
* $Id$
*
@ -18,12 +18,13 @@
/*****************************************************************************/
/**
Bereitet ein Mailbox-Send-Kommando vor.
*/
Prepares a mailbox-send command.
\return pointer to mailbox command data
*/
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
uint8_t type, /**< Mailbox-Protokoll */
size_t size /**< Datengröße */
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< slave */
uint8_t type, /**< mailbox protocol */
size_t size /**< size of the data */
)
{
ec_command_t *command = &slave->mbox_command;
@ -46,10 +47,10 @@ uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
slave->sii_rx_mailbox_size))
return NULL;
EC_WRITE_U16(command->data, size); // Mailbox service data length
EC_WRITE_U16(command->data + 2, slave->station_address); // Station address
EC_WRITE_U8 (command->data + 4, 0x00); // Channel & priority
EC_WRITE_U8 (command->data + 5, type); // Underlying protocol type
EC_WRITE_U16(command->data, size); // mailbox service data length
EC_WRITE_U16(command->data + 2, slave->station_address); // station address
EC_WRITE_U8 (command->data + 4, 0x00); // hhannel & priority
EC_WRITE_U8 (command->data + 5, type); // underlying protocol type
return command->data + 6;
}
@ -57,14 +58,15 @@ uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
/*****************************************************************************/
/**
Bereitet ein Kommando zum Abfragen des Mailbox-Zustandes vor.
*/
Prepares a command for checking the mailbox state.
\return 0 in case of success, else < 0
*/
int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< Slave */)
int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< slave */)
{
ec_command_t *command = &slave->mbox_command;
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
// FIXME: second sync manager?
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
return -1;
@ -74,10 +76,11 @@ int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< Slave */)
/*****************************************************************************/
/**
Liest den Mailbox-Zustand aus einem empfangenen Kommando.
*/
Processes a mailbox state checking command.
\return 0 in case of success, else < 0
*/
int ec_slave_mbox_check(const ec_slave_t *slave /**< Slave */)
int ec_slave_mbox_check(const ec_slave_t *slave /**< slave */)
{
return EC_READ_U8(slave->mbox_command.data + 5) & 8 ? 1 : 0;
}
@ -85,10 +88,11 @@ int ec_slave_mbox_check(const ec_slave_t *slave /**< Slave */)
/*****************************************************************************/
/**
Bereitet ein Kommando zum Laden von Daten von der Mailbox vor.
*/
Prepares a command to fetch mailbox data.
\return 0 in case of success, else < 0
*/
int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< Slave */)
int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< slave */)
{
ec_command_t *command = &slave->mbox_command;
@ -101,12 +105,13 @@ int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< Slave */)
/*****************************************************************************/
/**
Verarbeitet empfangene Mailbox-Daten.
*/
Processes received mailbox data.
\return pointer to the received data
*/
uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< Slave */
uint8_t type, /**< Protokoll */
size_t *size /**< Größe der empfangenen Daten */
uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< slave */
uint8_t type, /**< expected mailbox protocol */
size_t *size /**< size of the received data */
)
{
ec_command_t *command = &slave->mbox_command;
@ -132,12 +137,12 @@ uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< Slave */
/*****************************************************************************/
/**
Sendet und wartet auf den Empfang eines Mailbox-Kommandos.
*/
Sends a mailbox command and waits for its reception.
\return pointer to the received data
*/
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< Slave */
size_t *size /**< Größe der gelesenen
Daten */
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< slave */
size_t *size /**< size of the received data */
)
{
uint8_t type;
@ -158,13 +163,13 @@ uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< Slave */
/*****************************************************************************/
/**
Wartet auf den Empfang eines Mailbox-Kommandos.
*/
Waits for the reception of a mailbox command.
\return pointer to the received data
*/
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< Slave */
uint8_t type, /**< Protokoll */
size_t *size /**< Größe der gelesenen
Daten */
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< slave */
uint8_t type, /**< expected protocol */
size_t *size /**< received data size */
)
{
cycles_t start, end, timeout;
@ -186,7 +191,7 @@ uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< Slave */
end = get_cycles();
if (ec_slave_mbox_check(slave))
break; // Proceed with receiving data
break; // proceed with receiving data
if ((end - start) >= timeout) {
EC_ERR("Mailbox check - Slave %i timed out.\n",

View File

@ -2,7 +2,7 @@
*
* m a i l b o x . h
*
* Mailbox-Funktionen.
* Mailbox functionality.
*
* $Id$
*
@ -27,9 +27,3 @@ uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *, uint8_t, size_t *);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* m a s t e r . c
*
* Methoden für einen EtherCAT-Master.
* EtherCAT master methods.
*
* $Id$
*
@ -27,6 +27,7 @@
void ec_master_freerun(unsigned long);
ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *);
void ec_master_process_watch_command(ec_master_t *);
/*****************************************************************************/
@ -53,11 +54,12 @@ static struct kobj_type ktype_ec_master = {
/*****************************************************************************/
/**
Konstruktor des EtherCAT-Masters.
Master constructor.
\return 0 in case of success, else < 0
*/
int ec_master_init(ec_master_t *master, /**< EtherCAT-Master */
unsigned int index /**< Master-Index */
int ec_master_init(ec_master_t *master, /**< EtherCAT master */
unsigned int index /**< master index */
)
{
EC_INFO("Initializing master %i.\n", index);
@ -71,7 +73,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT-Master */
INIT_LIST_HEAD(&master->domains);
INIT_LIST_HEAD(&master->eoe_slaves);
// Init kobject and add it to the hierarchy
// init kobject and add it to the hierarchy
memset(&master->kobj, 0x00, sizeof(struct kobject));
kobject_init(&master->kobj);
master->kobj.ktype = &ktype_ec_master;
@ -81,7 +83,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT-Master */
return -1;
}
// Init freerun timer
// init freerun timer
init_timer(&master->freerun_timer);
master->freerun_timer.function = ec_master_freerun;
master->freerun_timer.data = (unsigned long) master;
@ -96,13 +98,12 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
/**
Destruktor eines EtherCAT-Masters.
Entfernt alle Kommandos aus der Liste, löscht den Zeiger
auf das Slave-Array und gibt die Prozessdaten frei.
Master destructor.
Removes all pending commands, clears the slave list, clears all domains
and frees the device.
*/
void ec_master_clear(struct kobject *kobj /**< KObject des Masters */)
void ec_master_clear(struct kobject *kobj /**< kobject of the master */)
{
ec_master_t *master = container_of(kobj, ec_master_t, kobj);
@ -126,15 +127,12 @@ void ec_master_clear(struct kobject *kobj /**< KObject des Masters */)
/*****************************************************************************/
/**
Setzt den Master zurück in den Ausgangszustand.
Bei einem "release" sollte immer diese Funktion aufgerufen werden,
da sonst Slave-Liste, Domains, etc. weiter existieren.
Resets the master.
Note: This function has to be called, everytime ec_master_release() is
called, to free the slave list, domains etc.
*/
void ec_master_reset(ec_master_t *master
/**< Zeiger auf den zurückzusetzenden Master */
)
void ec_master_reset(ec_master_t *master /**< EtherCAT master */)
{
ec_slave_t *slave, *next_s;
ec_command_t *command, *next_c;
@ -143,7 +141,7 @@ void ec_master_reset(ec_master_t *master
ec_master_freerun_stop(master);
// Alle Slaves entfernen
// remove all slaves
list_for_each_entry_safe(slave, next_s, &master->slaves, list) {
list_del(&slave->list);
kobject_del(&slave->kobj);
@ -151,20 +149,20 @@ void ec_master_reset(ec_master_t *master
}
master->slave_count = 0;
// Kommando-Warteschlange leeren
// empty command queue
list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
list_del_init(&command->queue);
command->state = EC_CMD_ERROR;
}
// Domain-Liste leeren
// clear domains
list_for_each_entry_safe(domain, next_d, &master->domains, list) {
list_del(&domain->list);
kobject_del(&domain->kobj);
kobject_put(&domain->kobj);
}
// EOE-Liste leeren
// clear EoE objects
list_for_each_entry_safe(eoe, next_eoe, &master->eoe_slaves, list) {
list_del(&eoe->list);
ec_eoe_clear(eoe);
@ -191,16 +189,16 @@ void ec_master_reset(ec_master_t *master
/*****************************************************************************/
/**
Stellt ein Kommando in die Warteschlange.
Places a command in the command queue.
*/
void ec_master_queue_command(ec_master_t *master, /**< EtherCAT-Master */
ec_command_t *command /**< Kommando */
void ec_master_queue_command(ec_master_t *master, /**< EtherCAT master */
ec_command_t *command /**< command */
)
{
ec_command_t *queued_command;
// Ist das Kommando schon in der Warteschlange?
// check, if the command is already queued
list_for_each_entry(queued_command, &master->command_queue, queue) {
if (queued_command == command) {
command->state = EC_CMD_QUEUED;
@ -217,12 +215,11 @@ void ec_master_queue_command(ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
/**
Sendet die Kommandos in der Warteschlange.
\return 0 bei Erfolg, sonst < 0
Sends the commands in the queue.
\return 0 in case of success, else < 0
*/
void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
void ec_master_send_commands(ec_master_t *master /**< EtherCAT master */)
{
ec_command_t *command;
size_t command_size;
@ -239,17 +236,17 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
}
do {
// Zeiger auf Socket-Buffer holen
// fetch pointer to transmit socket buffer
frame_data = ec_device_tx_data(master->device);
cur_data = frame_data + EC_FRAME_HEADER_SIZE;
follows_word = NULL;
more_commands_waiting = 0;
// Aktuellen Frame mit Kommandos füllen
// fill current frame with commands
list_for_each_entry(command, &master->command_queue, queue) {
if (command->state != EC_CMD_QUEUED) continue;
// Passt das aktuelle Kommando noch in den aktuellen Rahmen?
// does the current command fit in the frame?
command_size = EC_COMMAND_HEADER_SIZE + command->data_size
+ EC_COMMAND_FOOTER_SIZE;
if (cur_data - frame_data + command_size > EC_MAX_FRAME_SIZE) {
@ -263,7 +260,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
if (unlikely(master->debug_level > 0))
EC_DBG("adding command 0x%02X\n", command->index);
// Command-Following-Flag im letzten Kommando setzen
// set "command following" flag in previous frame
if (follows_word)
EC_WRITE_U16(follows_word, EC_READ_U16(follows_word) | 0x8000);
@ -281,7 +278,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
cur_data += command->data_size;
// EtherCAT command footer
EC_WRITE_U16(cur_data, 0x0000); // Working counter
EC_WRITE_U16(cur_data, 0x0000); // reset working counter
cur_data += EC_COMMAND_FOOTER_SIZE;
}
@ -295,14 +292,14 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
EC_WRITE_U16(frame_data, ((cur_data - frame_data
- EC_FRAME_HEADER_SIZE) & 0x7FF) | 0x1000);
// Rahmen auffüllen
// pad frame
while (cur_data - frame_data < EC_MIN_FRAME_SIZE)
EC_WRITE_U8(cur_data++, 0x00);
if (unlikely(master->debug_level > 0))
EC_DBG("frame size: %i\n", cur_data - frame_data);
// Send frame
// send frame
ec_device_send(master->device, cur_data - frame_data);
frame_count++;
}
@ -319,16 +316,14 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
/**
Processes a received frame.
This function is called by the network driver for every received frame.
\return 0 bei Erfolg, sonst < 0
\return 0 in case of success, else < 0
*/
void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
const uint8_t *frame_data, /**< Empfangene Daten */
size_t size /**< Anzahl empfangene Datenbytes */
)
void ec_master_receive(ec_master_t *master, /**< EtherCAT master */
const uint8_t *frame_data, /**< received data */
size_t size /**< size of the received data */
)
{
size_t frame_size, data_size;
uint8_t command_type, command_index;
@ -344,7 +339,7 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
cur_data = frame_data;
// Länge des gesamten Frames prüfen
// check length of entire frame
frame_size = EC_READ_U16(cur_data) & 0x07FF;
cur_data += EC_FRAME_HEADER_SIZE;
@ -356,7 +351,7 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
cmd_follows = 1;
while (cmd_follows) {
// Kommando-Header auswerten
// process command header
command_type = EC_READ_U8 (cur_data);
command_index = EC_READ_U8 (cur_data + 1);
data_size = EC_READ_U16(cur_data + 6) & 0x07FF;
@ -370,7 +365,7 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
return;
}
// Suche passendes Kommando in der Liste
// search for matching command in the queue
matched = 0;
list_for_each_entry(command, &master->command_queue, queue) {
if (command->state == EC_CMD_SENT
@ -382,7 +377,7 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
}
}
// Kein passendes Kommando in der Liste gefunden
// no matching command was found
if (!matched) {
master->stats.unmatched++;
ec_master_output_stats(master);
@ -390,15 +385,15 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
continue;
}
// Empfangene Daten in Kommando-Datenspeicher kopieren
// copy received data in the command memory
memcpy(command->data, cur_data, data_size);
cur_data += data_size;
// Working-Counter setzen
// set the command's working counter
command->working_counter = EC_READ_U16(cur_data);
cur_data += EC_COMMAND_FOOTER_SIZE;
// Kommando aus der Warteschlange entfernen
// dequeue the received command
command->state = EC_CMD_RECEIVED;
list_del_init(&command->queue);
}
@ -407,16 +402,13 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
/**
Sendet ein einzelnes Kommando und wartet auf den Empfang.
Wenn der Slave nicht antwortet, wird das Kommando
nochmals gesendet.
\return 0 bei Erfolg, sonst < 0
Sends a single command and waits for its reception.
If the slave doesn't respond, the command is sent again.
\return 0 in case of success, else < 0
*/
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
ec_command_t *command /**< Kommando */
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT master */
ec_command_t *command /**< command */
)
{
unsigned int response_tries_left;
@ -441,7 +433,7 @@ int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
return -1;
}
// Keine direkte Antwort. Dem Slave Zeit lassen...
// no direct response, wait a little bit...
udelay(100);
if (unlikely(--response_tries_left)) {
@ -454,15 +446,12 @@ int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
/**
Durchsucht den EtherCAT-Bus nach Slaves.
Erstellt ein Array mit allen Slave-Informationen die für den
weiteren Betrieb notwendig sind.
\return 0 bei Erfolg, sonst < 0
Scans the EtherCAT bus for slaves.
Creates a list of slave structures for further processing.
\return 0 in case of success, else < 0
*/
int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */)
{
ec_slave_t *slave, *next;
ec_slave_ident_t *ident;
@ -479,7 +468,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
command = &master->simple_command;
// Determine number of slaves on bus
// determine number of slaves on bus
if (ec_command_brd(command, 0x0000, 4)) return -1;
if (unlikely(ec_master_simple_io(master, command))) return -1;
master->slave_count = command->working_counter;
@ -487,7 +476,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
if (!master->slave_count) return 0;
// Init slaves
// init slaves
for (i = 0; i < master->slave_count; i++) {
if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate slave %i!\n", i);
@ -510,10 +499,10 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
current_coupler_index = 0x3FFF;
coupler_subindex = 0;
// For every slave on the bus
// for every slave on the bus
list_for_each_entry(slave, &master->slaves, list) {
// Write station address
// write station address
if (ec_command_apwr(command, slave->ring_position, 0x0010,
sizeof(uint16_t))) goto out_free;
EC_WRITE_U16(command->data, slave->station_address);
@ -523,10 +512,10 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
goto out_free;
}
// Fetch all slave information
// fetch all slave information
if (ec_slave_fetch(slave)) goto out_free;
// Search for identification in "database"
// search for identification in "database"
ident = slave_idents;
while (ident->type) {
if (unlikely(ident->vendor_id == slave->sii_vendor_id
@ -554,7 +543,7 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
slave->coupler_subindex = coupler_subindex;
coupler_subindex++;
// Does the slave support EoE?
// does the slave support EoE?
if (slave->sii_mailbox_protocols & EC_MBOX_EOE) {
if (!(eoe = (ec_eoe_t *) kmalloc(sizeof(ec_eoe_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate EoE-Object.\n");
@ -580,15 +569,12 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Statistik-Ausgaben während des zyklischen Betriebs.
Diese Funktion sorgt dafür, dass Statistiken während des zyklischen
Betriebs bei Bedarf, aber nicht zu oft ausgegeben werden.
Die Ausgabe erfolgt gesammelt höchstens einmal pro Sekunde.
Output statistics in cyclic mode.
This function outputs statistical data on demand, but not more often than
necessary. The output happens at most once a second.
*/
void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */)
void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
{
cycles_t t_now = get_cycles();
@ -620,7 +606,7 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Starts Free-Run mode.
Starts the Free-Run mode.
*/
void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
@ -636,6 +622,15 @@ void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
master->mode = EC_MASTER_MODE_FREERUN;
if (master->watch_command.state == EC_CMD_INIT) {
if (ec_command_brd(&master->watch_command, 0x130, 2)) {
EC_ERR("Failed to allocate watchdog command!\n");
return;
}
}
ecrt_master_prepare_async_io(master);
master->freerun_timer.expires = jiffies + 10;
add_timer(&master->freerun_timer);
}
@ -643,7 +638,7 @@ void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */)
/*****************************************************************************/
/**
Stops Free-Run mode.
Stops the Free-Run mode.
*/
void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
@ -662,11 +657,19 @@ void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */)
Free-Run mode function.
*/
void ec_master_freerun(unsigned long data)
void ec_master_freerun(unsigned long data /**< private timer data = master */)
{
ec_master_t *master = (ec_master_t *) data;
// nop
ecrt_master_async_receive(master);
// watchdog command
ec_master_process_watch_command(master);
ec_master_queue_command(master, &master->watch_command);
master->slave_count = master->watch_command.working_counter;
ecrt_master_async_send(master);
master->freerun_timer.expires += HZ;
add_timer(&master->freerun_timer);
@ -675,22 +678,19 @@ void ec_master_freerun(unsigned long data)
/*****************************************************************************/
/**
Wandelt eine ASCII-kodierte Bus-Adresse in einen Slave-Zeiger.
Gültige Adress-Strings sind Folgende:
- \a "X" = der X. Slave im Bus,
- \a "X:Y" = der Y. Slave hinter dem X. Buskoppler,
- \a "#X" = der Slave mit dem Alias X,
- \a "#X:Y" = der Y. Slave hinter dem Buskoppler mit dem Alias X.
X und Y fangen immer bei 0 an und können auch hexadezimal oder oktal
angegeben werden (mit entsprechendem Prefix).
\return Zeiger auf Slave bei Erfolg, sonst NULL
Translates an ASCII coded bus-address to a slave pointer.
These are the valid addressing schemes:
- \a "X" = the X. slave on the bus,
- \a "X:Y" = the Y. slave after the X. branch (bus coupler),
- \a "#X" = the slave with alias X,
- \a "#X:Y" = the Y. slave after the branch (bus coupler) with alias X.
X and Y are zero-based indices and may be provided in hexadecimal or octal
notation (with respective prefix).
\return pointer to the slave on success, else NULL
*/
ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
const char *address /**< Address-String */
const char *address /**< address string */
)
{
unsigned long first, second;
@ -785,14 +785,12 @@ ec_slave_t *ecrt_master_get_slave(const ec_master_t *master, /**< Master */
/*****************************************************************************/
/**
Initialisiert eine Sync-Manager-Konfigurationsseite.
Der mit \a data referenzierte Speicher muss mindestens EC_SYNC_SIZE Bytes
groß sein.
Initializes a sync manager configuration page.
The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes.
*/
void ec_sync_config(const ec_sync_t *sync, /**< Sync-Manager */
uint8_t *data /**> Zeiger auf Konfigurationsspeicher */
void ec_sync_config(const ec_sync_t *sync, /**< sync manager */
uint8_t *data /**> configuration memory */
)
{
EC_WRITE_U16(data, sync->physical_start_address);
@ -805,14 +803,12 @@ void ec_sync_config(const ec_sync_t *sync, /**< Sync-Manager */
/*****************************************************************************/
/**
Initialisiert eine Sync-Manager-Konfigurationsseite mit EEPROM-Daten.
Der mit \a data referenzierte Speicher muss mindestens EC_SYNC_SIZE Bytes
groß sein.
Initializes a sync manager configuration page with EEPROM data.
The referenced memory (\a data) must be at least EC_SYNC_SIZE bytes.
*/
void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< Sync-Manager */
uint8_t *data /**> Zeiger auf Konfig.-Speicher */
void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< sync manager */
uint8_t *data /**> configuration memory */
)
{
EC_WRITE_U16(data, sync->physical_start_address);
@ -825,38 +821,35 @@ void ec_eeprom_sync_config(const ec_eeprom_sync_t *sync, /**< Sync-Manager */
/*****************************************************************************/
/**
Initialisiert eine FMMU-Konfigurationsseite.
Der mit \a data referenzierte Speicher muss mindestens EC_FMMU_SIZE Bytes
groß sein.
Initializes an FMMU configuration page.
The referenced memory (\a data) must be at least EC_FMMU_SIZE bytes.
*/
void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< Sync-Manager */
uint8_t *data /**> Zeiger auf Konfigurationsspeicher */
void ec_fmmu_config(const ec_fmmu_t *fmmu, /**< FMMU */
uint8_t *data /**> configuration memory */
)
{
EC_WRITE_U32(data, fmmu->logical_start_address);
EC_WRITE_U16(data + 4, fmmu->sync->size);
EC_WRITE_U8 (data + 6, 0x00); // Logical start bit
EC_WRITE_U8 (data + 7, 0x07); // Logical end bit
EC_WRITE_U8 (data + 6, 0x00); // logical start bit
EC_WRITE_U8 (data + 7, 0x07); // logical end bit
EC_WRITE_U16(data + 8, fmmu->sync->physical_start_address);
EC_WRITE_U8 (data + 10, 0x00); // Physical start bit
EC_WRITE_U8 (data + 10, 0x00); // physical start bit
EC_WRITE_U8 (data + 11, (fmmu->sync->control_byte & 0x04) ? 0x02 : 0x01);
EC_WRITE_U16(data + 12, 0x0001); // Enable
EC_WRITE_U16(data + 14, 0x0000); // res.
EC_WRITE_U16(data + 12, 0x0001); // enable
EC_WRITE_U16(data + 14, 0x0000); // reserved
}
/*****************************************************************************/
/**
Formatiert Attribut-Daten für lesenden Zugriff im SysFS
\return Anzahl Bytes im Speicher
Formats attribute data for SysFS read access.
\return number of bytes to read
*/
ssize_t ec_show_master_attribute(struct kobject *kobj, /**< KObject */
struct attribute *attr, /**< Attribut */
char *buffer /**< Speicher für die Daten */
ssize_t ec_show_master_attribute(struct kobject *kobj, /**< kobject */
struct attribute *attr, /**< attribute */
char *buffer /**< memory to store data */
)
{
ec_master_t *master = container_of(kobj, ec_master_t, kobj);
@ -881,11 +874,11 @@ ssize_t ec_show_master_attribute(struct kobject *kobj, /**< KObject */
/*****************************************************************************/
/**
Gibt Überwachungsinformationen aus.
Processes the watchdog command.
*/
void ec_master_process_watch_command(ec_master_t *master
/**< EtherCAT-Master */
/**< EtherCAT master */
)
{
unsigned int first;
@ -926,18 +919,15 @@ void ec_master_process_watch_command(ec_master_t *master
}
/******************************************************************************
*
* Echtzeitschnittstelle
*
* Realtime interface
*****************************************************************************/
/**
Erstellt eine neue Domäne.
\return Zeiger auf die Domäne bei Erfolg, sonst NULL.
Creates a domain.
\return pointer to new domain on success, else NULL
*/
ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< Master */)
ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< master */)
{
ec_domain_t *domain, *last_domain;
unsigned int index;
@ -975,16 +965,14 @@ ec_domain_t *ecrt_master_create_domain(ec_master_t *master /**< Master */)
/*****************************************************************************/
/**
Konfiguriert alle Slaves und setzt den Operational-Zustand.
Führt die komplette Konfiguration und Aktivierunge aller registrierten
Slaves durch. Setzt Sync-Manager und FMMUs, führt die entsprechenden
Zustandsübergänge durch, bis der Slave betriebsbereit ist.
\return 0 bei Erfolg, sonst < 0
Configures all slaves and leads them to the OP state.
Does the complete configuration and activation for all slaves. Sets sync
managers and FMMUs, and does the appropriate transitions, until the slave
is operational.
\return 0 in case of success, else < 0
*/
int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
{
unsigned int j;
ec_slave_t *slave;
@ -998,12 +986,14 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
command = &master->simple_command;
if (ec_command_brd(&master->watch_command, 0x130, 2)) {
EC_ERR("Failed to allocate watchdog command!\n");
return -1;
if (master->watch_command.state == EC_CMD_INIT) {
if (ec_command_brd(&master->watch_command, 0x130, 2)) {
EC_ERR("Failed to allocate watchdog command!\n");
return -1;
}
}
// Domains erstellen
// allocate all domains
domain_offset = 0;
list_for_each_entry(domain, &master->domains, list) {
if (ec_domain_alloc(domain, domain_offset)) {
@ -1013,22 +1003,22 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
domain_offset += domain->data_size;
}
// Slaves aktivieren
// configure and activate slaves
list_for_each_entry(slave, &master->slaves, list) {
// Change state to INIT
// change state to INIT
if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_INIT)))
return -1;
// Check if slave was registered...
// check for slave registration
type = slave->type;
if (!type)
EC_WARN("Slave %i has unknown type!\n", slave->ring_position);
// Check and reset CRC fault counters
// check and reset CRC fault counters
ec_slave_check_crc(slave);
// Resetting FMMUs
// reset FMMUs
if (slave->base_fmmu_count) {
if (ec_command_npwr(command, slave->station_address, 0x0600,
EC_FMMU_SIZE * slave->base_fmmu_count))
@ -1041,7 +1031,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
}
}
// Resetting Sync Manager channels
// reset sync managers
if (slave->base_sync_count) {
if (ec_command_npwr(command, slave->station_address, 0x0800,
EC_SYNC_SIZE * slave->base_sync_count))
@ -1054,10 +1044,8 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
}
}
// Set Sync Managers
// Known slave type, take type's SM information
if (type) {
// configure sync managers
if (type) { // known slave type, take type's SM information
for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++) {
sync = type->sync_managers[j];
if (ec_command_npwr(command, slave->station_address,
@ -1071,11 +1059,8 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
}
}
}
// Unknown slave type, but has mailbox
else if (slave->sii_mailbox_protocols) {
// Does the device supply SM configurations in its EEPROM?
else if (slave->sii_mailbox_protocols) { // unknown type, but mailbox
// does the device supply SM configurations in its EEPROM?
if (!list_empty(&slave->eeprom_syncs)) {
list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
EC_INFO("Sync manager %i...\n", eeprom_sync->index);
@ -1091,9 +1076,7 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
}
}
}
// No sync manager information; guess mailbox settings
else {
else { // no sync manager information; guess mailbox settings
mbox_sync.physical_start_address =
slave->sii_rx_mailbox_offset;
mbox_sync.length = slave->sii_rx_mailbox_size;
@ -1126,21 +1109,21 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
slave->ring_position);
}
// Change state to PREOP
// change state to PREOP
if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_PREOP)))
return -1;
// Stop activation here for slaves without type
// stop activation here for slaves without type
if (!type) continue;
// Slaves that are not registered are only brought into PREOP
// slaves that are not registered are only brought into PREOP
// state -> nice blinking and mailbox communication possible
if (!slave->registered && !slave->type->special) {
EC_WARN("Slave %i was not registered!\n", slave->ring_position);
continue;
}
// Set FMMUs
// configure FMMUs
for (j = 0; j < slave->fmmu_count; j++) {
fmmu = &slave->fmmus[j];
if (ec_command_npwr(command, slave->station_address,
@ -1154,11 +1137,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
}
}
// Change state to SAVEOP
// change state to SAVEOP
if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_SAVEOP)))
return -1;
// Change state to OP
// change state to OP
if (unlikely(ec_slave_state_change(slave, EC_SLAVE_STATE_OP)))
return -1;
}
@ -1172,10 +1155,10 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Setzt alle Slaves zurück in den Init-Zustand.
Resets all slaves to INIT state.
*/
void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */)
void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */)
{
ec_slave_t *slave;
@ -1189,14 +1172,12 @@ void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Lädt die SDO-Dictionaries aller Slaves.
Slaves, die kein CoE unterstützen, werden ausgelassen.
\return 0 wenn alles ok, sonst < 0
Fetches the SDO dictionaries of all slaves.
Slaves that do not support the CoE protocol are left out.
\return 0 in case of success, else < 0
*/
int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */)
int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT master */)
{
ec_slave_t *slave;
@ -1216,27 +1197,26 @@ int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Sendet und empfängt Kommandos synchron.
Sends queued commands and waits for their reception.
*/
void ecrt_master_sync_io(ec_master_t *master)
void ecrt_master_sync_io(ec_master_t *master /**< EtherCAT master */)
{
ec_command_t *command, *n;
unsigned int commands_sent;
cycles_t t_start, t_end, t_timeout;
// Kommandos senden
// send commands
ecrt_master_async_send(master);
t_start = get_cycles(); // Sendezeit nehmen
t_start = get_cycles(); // measure io time
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
while (1) // Aktiv auf Empfang warten
{
while (1) { // active waiting
ec_device_call_isr(master->device);
t_end = get_cycles(); // Aktuelle Zeit nehmen
if (t_end - t_start >= t_timeout) break; // Timeout
t_end = get_cycles(); // take current time
if (t_end - t_start >= t_timeout) break; // timeout!
commands_sent = 0;
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
@ -1249,7 +1229,7 @@ void ecrt_master_sync_io(ec_master_t *master)
if (!commands_sent) break;
}
// Zeit abgelaufen. Alle verbleibenden Kommandos entfernen.
// timeout; dequeue all commands
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
switch (command->state) {
case EC_CMD_SENT:
@ -1272,46 +1252,46 @@ void ecrt_master_sync_io(ec_master_t *master)
/*****************************************************************************/
/**
Sendet Kommandos asynchron.
Asynchronous sending of commands.
*/
void ecrt_master_async_send(ec_master_t *master)
void ecrt_master_async_send(ec_master_t *master /**< EtherCAT master */)
{
ec_command_t *command, *n;
if (unlikely(!master->device->link_state)) {
// Link DOWN, keines der Kommandos kann gesendet werden.
// link is down, no command can be sent
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
command->state = EC_CMD_ERROR;
list_del_init(&command->queue);
}
// Device-Zustand abfragen
// query link state
ec_device_call_isr(master->device);
return;
}
// Rahmen senden
// send frames
ec_master_send_commands(master);
}
/*****************************************************************************/
/**
Empfängt Kommandos asynchron.
Asynchronous receiving of commands.
*/
void ecrt_master_async_receive(ec_master_t *master)
void ecrt_master_async_receive(ec_master_t *master /**< EtherCAT master */)
{
ec_command_t *command, *next;
ec_device_call_isr(master->device);
// Alle empfangenen Kommandos aus der Liste entfernen
// dequeue all received commands
list_for_each_entry_safe(command, next, &master->command_queue, queue)
if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue);
// Alle verbleibenden Kommandos entfernen.
// dequeue all remaining commands
list_for_each_entry_safe(command, next, &master->command_queue, queue) {
switch (command->state) {
case EC_CMD_SENT:
@ -1330,28 +1310,26 @@ void ecrt_master_async_receive(ec_master_t *master)
/*****************************************************************************/
/**
Bereitet Synchronen Datenverkehr vor.
Fürgt einmal die Kommandos aller Domains zur Warteschlange hinzu, sendet
diese ab und wartet so lange, bis diese anschließend problemlos empfangen
werden können.
Prepares synchronous IO.
Queues all domain commands and sends them. Then waits a certain time, so
that ecrt_master_sasync_receive() can be called securely.
*/
void ecrt_master_prepare_async_io(ec_master_t *master)
void ecrt_master_prepare_async_io(ec_master_t *master /**< EtherCAT master */)
{
ec_domain_t *domain;
cycles_t t_start, t_end, t_timeout;
// Kommandos aller Domains in die Warteschlange setzen
// queue commands of all domains
list_for_each_entry(domain, &master->domains, list)
ecrt_domain_queue(domain);
ecrt_master_async_send(master);
t_start = get_cycles(); // Sendezeit nehmen
t_start = get_cycles(); // take sending time
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
// Aktiv warten!
// active waiting
while (1) {
t_end = get_cycles();
if (t_end - t_start >= t_timeout) break;
@ -1361,15 +1339,15 @@ void ecrt_master_prepare_async_io(ec_master_t *master)
/*****************************************************************************/
/**
Führt Routinen im zyklischen Betrieb aus.
Does all cyclic master work.
*/
void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */)
void ecrt_master_run(ec_master_t *master /**< EtherCAT master */)
{
// Statistiken ausgeben
// output statistics
ec_master_output_stats(master);
// Watchdog-Kommando
// watchdog command
ec_master_process_watch_command(master);
ec_master_queue_command(master, &master->watch_command);
@ -1380,16 +1358,14 @@ void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Setzt die Debug-Ebene des Masters.
Folgende Debug-Level sind definiert:
- 1: Nur Positionsmarken in bestimmten Funktionen
- 2: Komplette Frame-Inhalte
Sets the debug level of the master.
The following levels are valid:
- 1: only output positions marks and basic data
- 2: additional frame data output
*/
void ecrt_master_debug(ec_master_t *master, /**< EtherCAT-Master */
int level /**< Debug-Level */
void ecrt_master_debug(ec_master_t *master, /**< EtherCAT master */
int level /**< debug level */
)
{
if (level != master->debug_level) {
@ -1401,16 +1377,15 @@ void ecrt_master_debug(ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
/**
Gibt alle Informationen zum Master aus.
Outputs all master information.
Verbosity:
0 - Nur Slavetypen und Adressen
1 - mit EEPROM-Informationen
>1 - mit SDO-Dictionaries
- 0: Only slave types and positions
- 1: with EEPROM contents
- >1: with SDO dictionaries
*/
void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */
unsigned int verbosity /**< Geschwätzigkeit */
void ecrt_master_print(const ec_master_t *master, /**< EtherCAT master */
unsigned int verbosity /**< verbosity level */
)
{
ec_slave_t *slave;
@ -1433,7 +1408,11 @@ void ecrt_master_print(const ec_master_t *master, /**< EtherCAT-Master */
/*****************************************************************************/
void ec_master_run_eoe(ec_master_t *master /**< EtherCAT-Master */)
/**
Does the Ethernet-over-EtherCAT processing.
*/
void ec_master_run_eoe(ec_master_t *master /**< EtherCAT master */)
{
ec_eoe_t *eoe;
@ -1458,9 +1437,3 @@ EXPORT_SYMBOL(ecrt_master_print);
EXPORT_SYMBOL(ecrt_master_get_slave);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* m a s t e r . h
*
* Struktur für einen EtherCAT-Master.
* EtherCAT master structure.
*
* $Id$
*
@ -35,61 +35,59 @@ ec_master_mode_t;
/*****************************************************************************/
/**
EtherCAT-Rahmen-Statistiken.
Cyclic EtherCAT statistics.
*/
typedef struct
{
unsigned int timeouts; /**< Kommando-Timeouts */
unsigned int delayed; /**< Verzögerte Kommandos */
unsigned int corrupted; /**< Verfälschte Rahmen */
unsigned int unmatched; /**< Unpassende Kommandos */
unsigned int eoe_errors; /**< Ethernet-over-EtherCAT Fehler */
cycles_t t_last; /**< Timestamp-Counter bei der letzten Ausgabe */
unsigned int timeouts; /**< command timeouts */
unsigned int delayed; /**< delayed commands */
unsigned int corrupted; /**< corrupted frames */
unsigned int unmatched; /**< unmatched commands */
unsigned int eoe_errors; /**< Ethernet-over-EtherCAT errors */
cycles_t t_last; /**< time of last output */
}
ec_stats_t;
/*****************************************************************************/
/**
EtherCAT-Master
Verwaltet die EtherCAT-Slaves und kommuniziert mit
dem zugewiesenen EtherCAT-Gerät.
EtherCAT-Master.
Manages slaves, domains and IO.
*/
struct ec_master
{
struct list_head list; /**< Noetig fuer Master-Liste */
struct kobject kobj; /**< Kernel-Object */
unsigned int index; /**< Master-Index */
struct list_head slaves; /**< Liste der Slaves auf dem Bus */
unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */
ec_device_t *device; /**< EtherCAT-Gerät */
struct list_head command_queue; /**< Kommando-Warteschlange */
uint8_t command_index; /**< Aktueller Kommando-Index */
struct list_head domains; /**< Liste der Prozessdatendomänen */
ec_command_t simple_command; /**< Kommando für Initialisierungsphase */
ec_command_t watch_command; /**< Kommando zum Überwachen der Slaves */
unsigned int slaves_responding; /**< Anzahl antwortender Slaves */
ec_slave_state_t slave_states; /**< Zustände der antwortenden Slaves */
int debug_level; /**< Debug-Level im Master-Code */
ec_stats_t stats; /**< Rahmen-Statistiken */
unsigned int timeout; /**< Timeout für synchronen Datenaustausch */
struct list_head eoe_slaves; /**< Ethernet over EtherCAT Slaves */
unsigned int reserved; /**< Master durch Echtzeitprozess reserviert */
struct timer_list freerun_timer; /**< Timer fuer Free-Run-Modus. */
ec_master_mode_t mode; /**< Modus des Masters */
struct list_head list; /**< list item */
struct kobject kobj; /**< kobject */
unsigned int index; /**< master index */
struct list_head slaves; /**< list of slaves on the bus */
unsigned int slave_count; /**< number of slaves on the bus */
ec_device_t *device; /**< EtherCAT device */
struct list_head command_queue; /**< command queue */
uint8_t command_index; /**< current command index */
struct list_head domains; /**< list of domains */
ec_command_t simple_command; /**< command structure for initialization */
ec_command_t watch_command; /**< command for watching the slaves */
unsigned int slaves_responding; /**< number of responding slaves */
ec_slave_state_t slave_states; /**< states of the responding slaves */
int debug_level; /**< master debug level */
ec_stats_t stats; /**< cyclic statistics */
unsigned int timeout; /**< timeout in synchronous IO */
struct list_head eoe_slaves; /**< Ethernet-over-EtherCAT slaves */
unsigned int reserved; /**< true, if the master is reserved for RT */
struct timer_list freerun_timer; /**< timer object for free run mode */
ec_master_mode_t mode; /**< master mode */
};
/*****************************************************************************/
// Master creation and deletion
// master creation and deletion
int ec_master_init(ec_master_t *, unsigned int);
void ec_master_clear(struct kobject *);
void ec_master_reset(ec_master_t *);
// Free-Run
// free run
void ec_master_freerun_start(ec_master_t *);
void ec_master_freerun_stop(ec_master_t *);
@ -98,10 +96,10 @@ void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
void ec_master_queue_command(ec_master_t *, ec_command_t *);
int ec_master_simple_io(ec_master_t *, ec_command_t *);
// Slave management
// slave management
int ec_master_bus_scan(ec_master_t *);
// Misc
// misc.
void ec_master_debug(const ec_master_t *);
void ec_master_output_stats(ec_master_t *);
void ec_master_run_eoe(ec_master_t *);
@ -109,9 +107,3 @@ void ec_master_run_eoe(ec_master_t *);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,9 +2,9 @@
*
* m o d u l e . c
*
* EtherCAT-Master-Treiber
* EtherCAT master driver module.
*
* Autoren: Wilhelm Hagemeister, Florian Pose
* Author: Florian Pose <fp@igh-essen.com>
*
* $Id$
*
@ -50,18 +50,14 @@ MODULE_LICENSE("GPL");
MODULE_VERSION(COMPILE_INFO);
module_param(ec_master_count, int, 1);
MODULE_PARM_DESC(ec_master_count, "Number of EtherCAT master to initialize.");
MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize");
/*****************************************************************************/
/**
Init-Funktion des EtherCAT-Master-Treibermodules
Initialisiert soviele Master, wie im Parameter ec_master_count
angegeben wurde (Default ist 1).
\return 0 wenn alles ok, < 0 bei ungültiger Anzahl Master
oder zu wenig Speicher.
Module initialization.
Initializes \a ec_master_count masters.
\return 0 on success, else < 0
*/
int __init ec_init_module(void)
@ -115,9 +111,8 @@ int __init ec_init_module(void)
/*****************************************************************************/
/**
Cleanup-Funktion des EtherCAT-Master-Treibermoduls
Entfernt alle Master-Instanzen.
Module cleanup.
Clears all master instances.
*/
void __exit ec_cleanup_module(void)
@ -142,7 +137,7 @@ void __exit ec_cleanup_module(void)
\returns pointer to master
*/
ec_master_t *ec_find_master(unsigned int master_index)
ec_master_t *ec_find_master(unsigned int master_index /**< master index */)
{
ec_master_t *master;
@ -155,26 +150,19 @@ ec_master_t *ec_find_master(unsigned int master_index)
}
/******************************************************************************
*
* Treiberschnittstelle
*
* Device interface
*****************************************************************************/
/**
Registeriert das EtherCAT-Geraet fuer einen EtherCAT-Master.
\return 0 wenn alles ok, oder < 0 wenn bereits ein Gerät registriert
oder das Geraet nicht geöffnet werden konnte.
Registeres an EtherCAT device for a certain master.
\return 0 on success, else < 0
*/
ec_device_t *ecdev_register(unsigned int master_index,
/**< Index des EtherCAT-Masters */
struct net_device *net_dev,
/**< net_device des EtherCAT-Gerätes */
ec_isr_t isr,
/**< Interrupt-Service-Routine */
struct module *module
/**< Zeiger auf das Modul */
ec_device_t *ecdev_register(unsigned int master_index, /**< master index */
struct net_device *net_dev, /**< net_device of
the device */
ec_isr_t isr, /**< interrupt service routine */
struct module *module /**< pointer to the module */
)
{
ec_master_t *master;
@ -218,13 +206,11 @@ ec_device_t *ecdev_register(unsigned int master_index,
/*****************************************************************************/
/**
Hebt die Registrierung eines EtherCAT-Gerätes auf.
Unregisteres an EtherCAT device.
*/
void ecdev_unregister(unsigned int master_index,
/**< Index des EtherCAT-Masters */
ec_device_t *device
/**< EtherCAT-Geraet */
void ecdev_unregister(unsigned int master_index, /**< master index */
ec_device_t *device /**< EtherCAT device */
)
{
ec_master_t *master;
@ -244,12 +230,10 @@ void ecdev_unregister(unsigned int master_index,
/*****************************************************************************/
/**
Starts the master.
Starts the master associated with the device.
*/
int ecdev_start(unsigned int master_index
/**< Index des EtherCAT-Masters */
)
int ecdev_start(unsigned int master_index /**< master index */)
{
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return -1;
@ -266,12 +250,10 @@ int ecdev_start(unsigned int master_index
/*****************************************************************************/
/**
Stops the master.
Stops the master associated with the device.
*/
void ecdev_stop(unsigned int master_index
/**< Index des EtherCAT-Masters */
)
void ecdev_stop(unsigned int master_index /**< master index */)
{
ec_master_t *master;
if (!(master = ec_find_master(master_index))) return;
@ -283,21 +265,16 @@ void ecdev_stop(unsigned int master_index
}
/******************************************************************************
*
* Echtzeitschnittstelle
*
* Realtime interface
*****************************************************************************/
/**
Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät.
Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck.
\return Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
Reserves an EtherCAT master for realtime operation.
\return pointer to reserved master, or NULL on error
*/
ec_master_t *ecrt_request_master(unsigned int master_index
/**< EtherCAT-Master-Index */
/**< master index */
)
{
ec_master_t *master;
@ -351,10 +328,10 @@ ec_master_t *ecrt_request_master(unsigned int master_index
/*****************************************************************************/
/**
Gibt einen zuvor angeforderten EtherCAT-Master wieder frei.
Releases a reserved EtherCAT master.
*/
void ecrt_release_master(ec_master_t *master /**< EtherCAT-Master */)
void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
{
EC_INFO("Releasing master %i...\n", master->index);
@ -378,10 +355,12 @@ void ecrt_release_master(ec_master_t *master /**< EtherCAT-Master */)
/*****************************************************************************/
/**
Gibt Frame-Inhalte zwecks Debugging aus.
Outputs frame contents for debugging purposes.
*/
void ec_print_data(const uint8_t *data, size_t size)
void ec_print_data(const uint8_t *data, /**< pointer to data */
size_t size /**< number of bytes to output */
)
{
unsigned int i;
@ -399,12 +378,12 @@ void ec_print_data(const uint8_t *data, size_t size)
/*****************************************************************************/
/**
Gibt Frame-Inhalte zwecks Debugging aus, differentiell.
Outputs frame contents and differences for debugging purposes.
*/
void ec_print_data_diff(const uint8_t *d1, /**< Daten 1 */
const uint8_t *d2, /**< Daten 2 */
size_t size /** Anzahl Bytes */
void ec_print_data_diff(const uint8_t *d1, /**< first data */
const uint8_t *d2, /**< second data */
size_t size /** number of bytes to output */
)
{
unsigned int i;
@ -434,9 +413,3 @@ EXPORT_SYMBOL(ecrt_request_master);
EXPORT_SYMBOL(ecrt_release_master);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* s l a v e . c
*
* Methoden für einen EtherCAT-Slave.
* EtherCAT slave methods.
*
* $Id$
*
@ -63,13 +63,14 @@ const ec_code_msg_t al_status_messages[];
/*****************************************************************************/
/**
EtherCAT-Slave-Konstruktor.
Slave constructor.
\return 0 in case of success, else < 0
*/
int ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
ec_master_t *master, /**< EtherCAT-Master */
uint16_t ring_position, /**< Ringposition */
uint16_t station_address /**< Programmierte Adresse */
int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
ec_master_t *master, /**< EtherCAT master */
uint16_t ring_position, /**< ring position */
uint16_t station_address /**< station address to configure */
)
{
unsigned int i;
@ -77,7 +78,7 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
slave->ring_position = ring_position;
slave->station_address = station_address;
// Init kobject and add it to the hierarchy
// init kobject and add it to the hierarchy
memset(&slave->kobj, 0x00, sizeof(struct kobject));
kobject_init(&slave->kobj);
slave->kobj.ktype = &ktype_ec_slave;
@ -133,10 +134,10 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
EtherCAT-Slave-Destruktor.
Slave destructor.
*/
void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */)
void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
{
ec_slave_t *slave;
ec_eeprom_string_t *string, *next_str;
@ -148,24 +149,24 @@ void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */)
slave = container_of(kobj, ec_slave_t, kobj);
// Alle Strings freigeben
// free all string objects
list_for_each_entry_safe(string, next_str, &slave->eeprom_strings, list) {
list_del(&string->list);
kfree(string);
}
// Alle Sync-Manager freigeben
// free all sync managers
list_for_each_entry_safe(sync, next_sync, &slave->eeprom_syncs, list) {
list_del(&sync->list);
kfree(sync);
}
// Alle PDOs freigeben
// free all PDOs
list_for_each_entry_safe(pdo, next_pdo, &slave->eeprom_pdos, list) {
list_del(&pdo->list);
if (pdo->name) kfree(pdo->name);
// Alle Entries innerhalb eines PDOs freigeben
// free all PDO entries
list_for_each_entry_safe(entry, next_ent, &pdo->entries, list) {
list_del(&entry->list);
if (entry->name) kfree(entry->name);
@ -179,12 +180,12 @@ void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */)
if (slave->eeprom_group) kfree(slave->eeprom_group);
if (slave->eeprom_desc) kfree(slave->eeprom_desc);
// Alle SDOs freigeben
// free all SDOs
list_for_each_entry_safe(sdo, next_sdo, &slave->sdo_dictionary, list) {
list_del(&sdo->list);
if (sdo->name) kfree(sdo->name);
// Alle Entries freigeben
// free all SDO entries
list_for_each_entry_safe(en, next_en, &sdo->entries, list) {
list_del(&en->list);
kfree(en);
@ -198,12 +199,11 @@ void ec_slave_clear(struct kobject *kobj /**< KObject des Slaves */)
/*****************************************************************************/
/**
Liest alle benötigten Informationen aus einem Slave.
\return 0 wenn alles ok, < 0 bei Fehler.
Reads all necessary information from a slave.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT slave */)
{
ec_command_t *command;
unsigned int i;
@ -211,7 +211,7 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
command = &slave->master->simple_command;
// Read base data
// read base data
if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1;
if (unlikely(ec_master_simple_io(slave->master, command))) {
EC_ERR("Reading base data from slave %i failed!\n",
@ -228,7 +228,7 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
if (slave->base_fmmu_count > EC_MAX_FMMUS)
slave->base_fmmu_count = EC_MAX_FMMUS;
// Read DL status
// read data link status
if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1;
if (unlikely(ec_master_simple_io(slave->master, command))) {
EC_ERR("Reading DL status from slave %i failed!\n",
@ -243,7 +243,7 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
}
// Read EEPROM data
// read EEPROM data
if (ec_slave_sii_read16(slave, 0x0004, &slave->sii_alias))
return -1;
if (ec_slave_sii_read32(slave, 0x0008, &slave->sii_vendor_id))
@ -276,18 +276,16 @@ int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Liest 16 Bit aus dem Slave-Information-Interface
eines EtherCAT-Slaves.
\return 0 bei Erfolg, sonst < 0
Reads 16 bit from the slave information interface (SII).
\return 0 in case of success, else < 0
*/
int ec_slave_sii_read16(ec_slave_t *slave,
/**< EtherCAT-Slave */
/**< EtherCAT slave */
uint16_t offset,
/**< Adresse des zu lesenden SII-Registers */
/**< address of the SII register to read */
uint16_t *target
/**< Speicher für Wert (16-Bit) */
/**< target memory */
)
{
ec_command_t *command;
@ -295,7 +293,7 @@ int ec_slave_sii_read16(ec_slave_t *slave,
command = &slave->master->simple_command;
// Initiate read operation
// initiate read operation
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
EC_WRITE_U8 (command->data, 0x00); // read-only access
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
@ -305,10 +303,6 @@ int ec_slave_sii_read16(ec_slave_t *slave,
return -1;
}
// Der Slave legt die Informationen des Slave-Information-Interface
// in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
// den Status auslesen, bis das Bit weg ist.
start = get_cycles();
timeout = (cycles_t) 100 * cpu_khz; // 100ms
@ -326,6 +320,7 @@ int ec_slave_sii_read16(ec_slave_t *slave,
end = get_cycles();
// check for "busy bit"
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
*target = EC_READ_U16(command->data + 6);
return 0;
@ -341,18 +336,16 @@ int ec_slave_sii_read16(ec_slave_t *slave,
/*****************************************************************************/
/**
Liest 32 Bit aus dem Slave-Information-Interface
eines EtherCAT-Slaves.
\return 0 bei Erfolg, sonst < 0
Reads 32 bit from the slave information interface (SII).
\return 0 in case of success, else < 0
*/
int ec_slave_sii_read32(ec_slave_t *slave,
/**< EtherCAT-Slave */
/**< EtherCAT slave */
uint16_t offset,
/**< Adresse des zu lesenden SII-Registers */
/**< address of the SII register to read */
uint32_t *target
/**< Speicher für Wert (32-Bit) */
/**< target memory */
)
{
ec_command_t *command;
@ -360,7 +353,7 @@ int ec_slave_sii_read32(ec_slave_t *slave,
command = &slave->master->simple_command;
// Initiate read operation
// initiate read operation
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
EC_WRITE_U8 (command->data, 0x00); // read-only access
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
@ -370,10 +363,6 @@ int ec_slave_sii_read32(ec_slave_t *slave,
return -1;
}
// Der Slave legt die Informationen des Slave-Information-Interface
// in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
// den Status auslesen, bis das Bit weg ist.
start = get_cycles();
timeout = (cycles_t) 100 * cpu_khz; // 100ms
@ -391,6 +380,7 @@ int ec_slave_sii_read32(ec_slave_t *slave,
end = get_cycles();
// check "busy bit"
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
*target = EC_READ_U32(command->data + 6);
return 0;
@ -406,18 +396,16 @@ int ec_slave_sii_read32(ec_slave_t *slave,
/*****************************************************************************/
/**
Schreibt 16 Bit Daten in das Slave-Information-Interface
eines EtherCAT-Slaves.
\return 0 bei Erfolg, sonst < 0
Writes 16 bit of data to the slave information interface (SII).
\return 0 in case of success, else < 0
*/
int ec_slave_sii_write16(ec_slave_t *slave,
/**< EtherCAT-Slave */
/**< EtherCAT slave */
uint16_t offset,
/**< Adresse des zu lesenden SII-Registers */
/**< address of the SII register to write */
uint16_t value
/**< Zu schreibender Wert */
/**< new value */
)
{
ec_command_t *command;
@ -428,7 +416,7 @@ int ec_slave_sii_write16(ec_slave_t *slave,
EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n",
slave->ring_position, offset, value);
// Initiate write operation
// initiate write operation
if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1;
EC_WRITE_U8 (command->data, 0x01); // enable write access
EC_WRITE_U8 (command->data + 1, 0x02); // request write operation
@ -439,10 +427,6 @@ int ec_slave_sii_write16(ec_slave_t *slave,
return -1;
}
// Der Slave legt die Informationen des Slave-Information-Interface
// in das Datenregister und löscht daraufhin ein Busy-Bit. Solange
// den Status auslesen, bis das Bit weg ist.
start = get_cycles();
timeout = (cycles_t) 100 * cpu_khz; // 100ms
@ -460,6 +444,7 @@ int ec_slave_sii_write16(ec_slave_t *slave,
end = get_cycles();
// check "busy bit"
if (likely((EC_READ_U8(command->data + 1) & 0x82) == 0)) {
if (EC_READ_U8(command->data + 1) & 0x40) {
EC_ERR("SII-write failed!\n");
@ -481,12 +466,11 @@ int ec_slave_sii_write16(ec_slave_t *slave,
/*****************************************************************************/
/**
Holt Daten aus dem EEPROM.
\return 0, wenn alles ok, sonst < 0
Fetches data from slave's EEPROM.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT-Slave */)
int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT slave */)
{
uint16_t word_offset, cat_type, word_count;
uint32_t value;
@ -507,13 +491,13 @@ int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT-Slave */)
goto out_free;
}
// Last category?
// last category?
if ((value & 0xFFFF) == 0xFFFF) break;
cat_type = value & 0x7FFF;
word_count = (value >> 16) & 0xFFFF;
// Fetch category data
// fetch category data
for (i = 0; i < word_count; i++) {
if (ec_slave_sii_read32(slave, word_offset + 2 + i, &value)) {
EC_ERR("Unable to read category data word %i.\n", i);
@ -574,13 +558,12 @@ int ec_slave_fetch_categories(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Holt die Daten einer String-Kategorie.
\return 0 wenn alles ok, sonst < 0
Fetches data from a STRING category.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT-Slave */
const uint8_t *data /**< Kategoriedaten */
int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data /**< category data */
)
{
unsigned int string_count, i;
@ -592,7 +575,7 @@ int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT-Slave */
offset = 1;
for (i = 0; i < string_count; i++) {
size = data[offset];
// Speicher für String-Objekt und Daten in einem Rutsch allozieren
// allocate memory for string structure and data at a single blow
if (!(string = (ec_eeprom_string_t *)
kmalloc(sizeof(ec_eeprom_string_t) + size + 1, GFP_KERNEL))) {
EC_ERR("Failed to allocate string memory.\n");
@ -613,11 +596,12 @@ int ec_slave_fetch_strings(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Holt die Daten einer General-Kategorie.
Fetches data from a GENERAL category.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT-Slave */
const uint8_t *data /**< Kategorie-Daten */
int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data /**< category data */
)
{
unsigned int i;
@ -630,7 +614,8 @@ int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT-Slave */
return -1;
for (i = 0; i < 4; i++)
slave->sii_physical_layer[i] = (data[4] & (0x03 << (i * 2))) >> (i * 2);
slave->sii_physical_layer[i] =
(data[4] & (0x03 << (i * 2))) >> (i * 2);
return 0;
}
@ -638,18 +623,19 @@ int ec_slave_fetch_general(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Holt die Daten einer Sync-Manager-Kategorie.
Fetches data from a SYNC MANAGER category.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT-Slave */
const uint8_t *data, /**< Kategorie-Daten */
size_t word_count /**< Anzahl Words */
int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< category data */
size_t word_count /**< number of words */
)
{
unsigned int sync_count, i;
ec_eeprom_sync_t *sync;
sync_count = word_count / 4; // Sync-Manager-Strunktur ist 4 Worte lang
sync_count = word_count / 4; // sync manager struct is 4 words long
for (i = 0; i < sync_count; i++, data += 8) {
if (!(sync = (ec_eeprom_sync_t *)
@ -673,13 +659,14 @@ int ec_slave_fetch_sync(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Holt die Daten einer TXPDO-Kategorie.
Fetches data from a [RT]XPDO category.
\return 0 in case of success, else < 0
*/
int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT-Slave */
const uint8_t *data, /**< Kategorie-Daten */
size_t word_count, /**< Anzahl Worte */
ec_pdo_type_t pdo_type /**< PDO-Typ */
int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< category data */
size_t word_count, /**< number of words */
ec_pdo_type_t pdo_type /**< PDO type */
)
{
ec_eeprom_pdo_t *pdo;
@ -733,7 +720,8 @@ int ec_slave_fetch_pdo(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Durchsucht die temporären Strings und dupliziert den gefundenen String.
Searches the string list for an index and allocates a new string.
\return 0 in case of success, else < 0
*/
int ec_slave_locate_string(ec_slave_t *slave, unsigned int index, char **ptr)
@ -778,13 +766,11 @@ int ec_slave_locate_string(ec_slave_t *slave, unsigned int index, char **ptr)
/*****************************************************************************/
/**
Bestätigt einen Fehler beim Zustandswechsel.
Acknowledges an error after a state transition.
*/
void ec_slave_state_ack(ec_slave_t *slave,
/**< Slave, dessen Zustand geändert werden soll */
uint8_t state
/**< Alter Zustand */
void ec_slave_state_ack(ec_slave_t *slave, /**< EtherCAT slave */
uint8_t state /**< previous state */
)
{
ec_command_t *command;
@ -805,7 +791,7 @@ void ec_slave_state_ack(ec_slave_t *slave,
while (1)
{
udelay(100); // Dem Slave etwas Zeit lassen...
udelay(100); // wait a little bit...
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
return;
@ -835,12 +821,11 @@ void ec_slave_state_ack(ec_slave_t *slave,
/**
Reads the AL status code of a slave and displays it.
If the AL status code is not supported, or if no error occurred (both
resulting in code=0), nothing is displayed.
*/
void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT-Slave */)
void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT slave */)
{
ec_command_t *command;
uint16_t code;
@ -871,15 +856,12 @@ void ec_slave_read_al_status_code(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Ändert den Zustand eines Slaves.
\return 0 bei Erfolg, sonst < 0
Does a state transition.
\return 0 in case of success, else < 0
*/
int ec_slave_state_change(ec_slave_t *slave,
/**< Slave, dessen Zustand geändert werden soll */
uint8_t state
/**< Neuer Zustand */
int ec_slave_state_change(ec_slave_t *slave, /**< EtherCAT slave */
uint8_t state /**< new state */
)
{
ec_command_t *command;
@ -900,7 +882,7 @@ int ec_slave_state_change(ec_slave_t *slave,
while (1)
{
udelay(100); // Dem Slave etwas Zeit lassen...
udelay(100); // wait a little bit
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
return -1;
@ -912,7 +894,7 @@ int ec_slave_state_change(ec_slave_t *slave,
end = get_cycles();
if (unlikely(EC_READ_U8(command->data) & 0x10)) { // State change error
if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error
EC_ERR("Failed to set state 0x%02X - Slave %i refused state change"
" (code 0x%02X)!\n", state, slave->ring_position,
EC_READ_U8(command->data));
@ -922,10 +904,8 @@ int ec_slave_state_change(ec_slave_t *slave,
return -1;
}
if (likely(EC_READ_U8(command->data) == (state & 0x0F))) {
// State change successful
return 0;
}
if (likely(EC_READ_U8(command->data) == (state & 0x0F)))
return 0; // state change successful
if (unlikely((end - start) >= timeout)) {
EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n",
@ -938,31 +918,30 @@ int ec_slave_state_change(ec_slave_t *slave,
/*****************************************************************************/
/**
Merkt eine FMMU-Konfiguration vor.
Die FMMU wird so konfiguriert, dass sie den gesamten Datenbereich des
entsprechenden Sync-Managers abdeckt. Für jede Domäne werden separate
FMMUs konfiguriert.
Wenn die entsprechende FMMU bereits konfiguriert ist, wird dies als
Erfolg zurückgegeben.
\return 0 bei Erfolg, sonst < 0
Prepares an FMMU configuration.
Configuration data for the FMMU is saved in the slave structure and is
written to the slave in ecrt_master_activate().
The FMMU configuration is done in a way, that the complete data range
of the corresponding sync manager is covered. Seperate FMMUs arce configured
for each domain.
If the FMMU configuration is already prepared, the function returns with
success.
\return 0 in case of success, else < 0
*/
int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT-Slave */
const ec_domain_t *domain, /**< Domäne */
const ec_sync_t *sync /**< Sync-Manager */
int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT slave */
const ec_domain_t *domain, /**< domain */
const ec_sync_t *sync /**< sync manager */
)
{
unsigned int i;
// FMMU schon vorgemerkt?
// FMMU configuration already prepared?
for (i = 0; i < slave->fmmu_count; i++)
if (slave->fmmus[i].domain == domain && slave->fmmus[i].sync == sync)
return 0;
// Neue FMMU reservieren...
// reserve new FMMU...
if (slave->fmmu_count >= slave->base_fmmu_count) {
EC_ERR("Slave %i FMMU limit reached!\n", slave->ring_position);
@ -981,16 +960,15 @@ int ec_slave_prepare_fmmu(ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Gibt alle Informationen über einen EtherCAT-Slave aus.
Outputs all information about a certain slave.
Verbosity:
0 - Nur Slavetypen und Adressen
1 - mit EEPROM-Informationen
>1 - mit SDO-Dictionaries
- 0: Only slave types and addresses
- 1: with EEPROM information
- >1: with SDO dictionaries
*/
void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT-Slave */
unsigned int verbosity /**< Geschwätzigkeit */
void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT slave */
unsigned int verbosity /**< verbosity level */
)
{
ec_eeprom_sync_t *sync;
@ -1146,12 +1124,11 @@ void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT-Slave */
/*****************************************************************************/
/**
Gibt die Zählerstände der CRC-Fault-Counter aus und setzt diese zurück.
\return 0 bei Erfolg, sonst < 0
Outputs the values of the CRC faoult counters and resets them.
\return 0 in case of success, else < 0
*/
int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT slave */)
{
ec_command_t *command;
@ -1164,8 +1141,7 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
return -1;
}
// No CRC faults.
if (!EC_READ_U32(command->data)) return 0;
if (!EC_READ_U32(command->data)) return 0; // no CRC faults
if (EC_READ_U8(command->data))
EC_WARN("%3i RX-error%s on slave %i, channel A.\n",
@ -1188,7 +1164,7 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
EC_READ_U8(command->data + 3) == 1 ? "" : "s",
slave->ring_position);
// Reset CRC counters
// reset CRC counters
if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1;
EC_WRITE_U32(command->data, 0x00000000);
if (unlikely(ec_master_simple_io(slave->master, command))) {
@ -1203,12 +1179,12 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
/*****************************************************************************/
/**
Schreibt den "Configured station alias".
\return 0, wenn alles ok, sonst < 0
Writes the "configured station alias" to the slave's EEPROM.
\return 0 in case of success, else < 0
*/
int ecrt_slave_write_alias(ec_slave_t *slave, /** EtherCAT-Slave */
uint16_t alias /** Neuer Alias */
int ecrt_slave_write_alias(ec_slave_t *slave, /** EtherCAT slave */
uint16_t alias /** new alias */
)
{
return ec_slave_sii_write16(slave, 0x0004, alias);
@ -1217,14 +1193,13 @@ int ecrt_slave_write_alias(ec_slave_t *slave, /** EtherCAT-Slave */
/*****************************************************************************/
/**
Formatiert Attribut-Daten für lesenden Zugriff im SysFS
\return Anzahl Bytes im Speicher
Formats attribute data for SysFS read access.
\return number of bytes to read
*/
ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< KObject */
struct attribute *attr, /**< Attribut */
char *buffer /**< Speicher für die Daten */
ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
struct attribute *attr, /**< attribute */
char *buffer /**< memory to store data */
)
{
ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj);
@ -1287,10 +1262,3 @@ const ec_code_msg_t al_status_messages[] = {
EXPORT_SYMBOL(ecrt_slave_write_alias);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* s l a v e . h
*
* Struktur für einen EtherCAT-Slave.
* EtherCAT stave structure.
*
* $Id$
*
@ -21,30 +21,30 @@
/*****************************************************************************/
/**
Zustand eines EtherCAT-Slaves.
State of an EtherCAT slave.
*/
typedef enum
{
EC_SLAVE_STATE_UNKNOWN = 0x00,
/**< Status unbekannt */
/**< unknown state */
EC_SLAVE_STATE_INIT = 0x01,
/**< Init-Zustand (Keine Mailbox-Kommunikation, Kein I/O) */
/**< INIT state (no mailbox communication, no IO) */
EC_SLAVE_STATE_PREOP = 0x02,
/**< Pre-Operational (Mailbox-Kommunikation, Kein I/O) */
/**< PREOP state (mailbox communication, no IO) */
EC_SLAVE_STATE_SAVEOP = 0x04,
/**< Save-Operational (Mailbox-Kommunikation und Input Update) */
/**< SAVEOP (mailbox communication and input update) */
EC_SLAVE_STATE_OP = 0x08,
/**< Operational, (Mailbox-Kommunikation und Input/Output Update) */
/**< OP (mailbox communication and input/output update) */
EC_ACK = 0x10
/**< Acknoledge-Bit beim Zustandswechsel (kein eigener Zustand) */
/**< Acknoledge bit (no state) */
}
ec_slave_state_t;
/*****************************************************************************/
/**
Unterstützte Mailbox-Protokolle.
Supported mailbox protocols.
*/
enum
@ -60,124 +60,124 @@ enum
/*****************************************************************************/
/**
FMMU-Konfiguration.
FMMU configuration.
*/
typedef struct
{
const ec_domain_t *domain;
const ec_sync_t *sync;
uint32_t logical_start_address;
const ec_domain_t *domain; /**< domain */
const ec_sync_t *sync; /**< sync manager */
uint32_t logical_start_address; /**< logical start address */
}
ec_fmmu_t;
/*****************************************************************************/
/**
String im EEPROM eines EtherCAT-Slaves.
String object (EEPROM).
*/
typedef struct
{
struct list_head list;
size_t size;
char *data;
struct list_head list; /**< list item */
size_t size; /**< size in bytes */
char *data; /**< string data */
}
ec_eeprom_string_t;
/*****************************************************************************/
/**
Sync-Manager-Konfiguration laut EEPROM.
Sync manager configuration (EEPROM).
*/
typedef struct
{
struct list_head list;
unsigned int index;
uint16_t physical_start_address;
uint16_t length;
uint8_t control_register;
uint8_t enable;
struct list_head list; /**< list item */
unsigned int index; /**< sync manager index */
uint16_t physical_start_address; /**< physical start address */
uint16_t length; /**< data length in bytes */
uint8_t control_register; /**< control register value */
uint8_t enable; /**< enable bit */
}
ec_eeprom_sync_t;
/*****************************************************************************/
/**
PDO-Typ.
PDO type.
*/
typedef enum
{
EC_RX_PDO,
EC_TX_PDO
EC_RX_PDO, /**< Reveive PDO */
EC_TX_PDO /**< Transmit PDO */
}
ec_pdo_type_t;
/*****************************************************************************/
/**
PDO-Beschreibung im EEPROM.
PDO description (EEPROM).
*/
typedef struct
{
struct list_head list;
ec_pdo_type_t type;
uint16_t index;
uint8_t sync_manager;
char *name;
struct list_head entries;
struct list_head list; /**< list item */
ec_pdo_type_t type; /**< PDO type */
uint16_t index; /**< PDO index */
uint8_t sync_manager; /**< assigned sync manager */
char *name; /**< PDO name */
struct list_head entries; /**< entry list */
}
ec_eeprom_pdo_t;
/*****************************************************************************/
/**
PDO-Entry-Beschreibung im EEPROM.
PDO entry description (EEPROM).
*/
typedef struct
{
struct list_head list;
uint16_t index;
uint8_t subindex;
char *name;
uint8_t bit_length;
struct list_head list; /**< list item */
uint16_t index; /**< PDO index */
uint8_t subindex; /**< entry subindex */
char *name; /**< entry name */
uint8_t bit_length; /**< entry length in bit */
}
ec_eeprom_pdo_entry_t;
/*****************************************************************************/
/**
CANopen-SDO.
CANopen SDO.
*/
typedef struct
{
struct list_head list;
uint16_t index;
struct list_head list; /**< list item */
uint16_t index; /**< SDO index */
//uint16_t type;
uint8_t object_code;
char *name;
struct list_head entries;
uint8_t object_code; /**< object code */
char *name; /**< SDO name */
struct list_head entries; /**< entry list */
}
ec_sdo_t;
/*****************************************************************************/
/**
CANopen-SDO-Entry.
CANopen SDO entry.
*/
typedef struct
{
struct list_head list;
uint8_t subindex;
uint16_t data_type;
uint16_t bit_length;
char *name;
struct list_head list; /**< list item */
uint8_t subindex; /**< entry subindex */
uint16_t data_type; /**< entry data type */
uint16_t bit_length; /**< entry length in bit */
char *name; /**< entry name */
}
ec_sdo_entry_t;
@ -189,69 +189,68 @@ ec_sdo_entry_t;
struct ec_slave
{
struct list_head list; /**< Noetig fuer Slave-Liste im Master */
struct kobject kobj; /**< Kernel-Object */
ec_master_t *master; /**< EtherCAT-Master, zu dem der Slave gehört. */
struct list_head list; /**< list item */
struct kobject kobj; /**< kobject */
ec_master_t *master; /**< master owning the slave */
// Addresses
uint16_t ring_position; /**< Position des Slaves im Bus */
uint16_t station_address; /**< Konfigurierte Slave-Adresse */
uint16_t coupler_index; /**< Letzter Buskoppler */
uint16_t coupler_subindex; /**< Index hinter letztem Buskoppler */
// addresses
uint16_t ring_position; /**< ring position */
uint16_t station_address; /**< configured station address */
uint16_t coupler_index; /**< index of the last bus coupler */
uint16_t coupler_subindex; /**< index of this slave after last coupler */
// Base data
uint8_t base_type; /**< Slave-Typ */
uint8_t base_revision; /**< Revision */
uint16_t base_build; /**< Build-Nummer */
uint16_t base_fmmu_count; /**< Anzahl unterstützter FMMUs */
uint16_t base_sync_count; /**< Anzahl unterstützter Sync-Manager */
// base data
uint8_t base_type; /**< slave type */
uint8_t base_revision; /**< revision */
uint16_t base_build; /**< build number */
uint16_t base_fmmu_count; /**< number of supported FMMUs */
uint16_t base_sync_count; /**< number of supported sync managers */
// Data link status
uint8_t dl_link[4]; /**< Verbindung erkannt */
uint8_t dl_loop[4]; /**< Loop geschlossen */
uint8_t dl_signal[4]; /**< Signal an RX-Seite erkannt */
// data link status
uint8_t dl_link[4]; /**< link detected */
uint8_t dl_loop[4]; /**< loop closed */
uint8_t dl_signal[4]; /**< detected signal on RX port */
// Slave information interface
uint16_t sii_alias; /**< Configured station alias */
uint32_t sii_vendor_id; /**< Identifikationsnummer des Herstellers */
uint32_t sii_product_code; /**< Herstellerspezifischer Produktcode */
uint32_t sii_revision_number; /**< Revisionsnummer */
uint32_t sii_serial_number; /**< Seriennummer der Klemme */
uint16_t sii_rx_mailbox_offset; /**< Adresse der Mailbox (Master->Slave) */
uint16_t sii_rx_mailbox_size; /**< Adresse der Mailbox (Master->Slave) */
uint16_t sii_tx_mailbox_offset; /**< Adresse der Mailbox (Slave->Master) */
uint16_t sii_tx_mailbox_size; /**< Adresse der Mailbox (Slave->Master) */
uint16_t sii_mailbox_protocols; /**< Unterstützte Mailbox-Protokolle */
uint8_t sii_physical_layer[4]; /**< Uebertragungsarten der Ports */
// slave information interface
uint16_t sii_alias; /**< configured station alias */
uint32_t sii_vendor_id; /**< vendor id */
uint32_t sii_product_code; /**< vendor's product code */
uint32_t sii_revision_number; /**< revision number */
uint32_t sii_serial_number; /**< serial number */
uint16_t sii_rx_mailbox_offset; /**< mailbox address (master to slave) */
uint16_t sii_rx_mailbox_size; /**< mailbox size (master to slave) */
uint16_t sii_tx_mailbox_offset; /**< mailbox address (slave to master) */
uint16_t sii_tx_mailbox_size; /**< mailbox size (slave to master) */
uint16_t sii_mailbox_protocols; /**< supported mailbox protocols */
uint8_t sii_physical_layer[4]; /**< port media */
const ec_slave_type_t *type; /**< Zeiger auf die Beschreibung
des Slave-Typs */
const ec_slave_type_t *type; /**< pointer to slave type object */
uint8_t registered; /**< Der Slave wurde registriert */
uint8_t registered; /**< true, if slave has been registered */
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU-Konfigurationen */
uint8_t fmmu_count; /**< Wieviele FMMUs schon benutzt sind. */
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU configurations */
uint8_t fmmu_count; /**< number of FMMUs used */
struct list_head eeprom_strings; /**< Strings im EEPROM */
struct list_head eeprom_syncs; /**< Syncmanager-Konfigurationen (EEPROM) */
struct list_head eeprom_pdos; /**< PDO-Beschreibungen im EEPROM */
struct list_head eeprom_strings; /**< EEPROM STRING categories */
struct list_head eeprom_syncs; /**< EEPROM SYNC MANAGER categories */
struct list_head eeprom_pdos; /**< EEPROM [RT]XPDO categories */
char *eeprom_name; /**< Slave-Name laut Hersteller */
char *eeprom_group; /**< Slave-Beschreibung laut Hersteller */
char *eeprom_desc; /**< Slave-Beschreibung laut Hersteller */
char *eeprom_name; /**< slave name acc. to EEPROM */
char *eeprom_group; /**< slave group acc. to EEPROM */
char *eeprom_desc; /**< slave description acc. to EEPROM */
struct list_head sdo_dictionary; /**< SDO-Verzeichnis des Slaves */
struct list_head sdo_dictionary; /**< SDO directory list */
ec_command_t mbox_command; /**< Kommando für Mailbox-Kommunikation */
ec_command_t mbox_command; /**< mailbox command */
};
/*****************************************************************************/
// Slave construction/destruction
// slave construction/destruction
int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t);
void ec_slave_clear(struct kobject *);
// Slave control
// slave control
int ec_slave_fetch(ec_slave_t *);
int ec_slave_sii_read16(ec_slave_t *, uint16_t, uint16_t *);
int ec_slave_sii_read32(ec_slave_t *, uint16_t, uint32_t *);
@ -260,19 +259,13 @@ int ec_slave_state_change(ec_slave_t *, uint8_t);
int ec_slave_prepare_fmmu(ec_slave_t *, const ec_domain_t *,
const ec_sync_t *);
// CANopen over EtherCAT
// CoE
int ec_slave_fetch_sdo_list(ec_slave_t *);
// Misc
// misc.
void ec_slave_print(const ec_slave_t *, unsigned int);
int ec_slave_check_crc(ec_slave_t *);
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* t y p e s . c
*
* EtherCAT-Slave-Typen.
* EtherCAT slave descriptions.
*
* $Id$
*
@ -18,36 +18,34 @@
const ec_sync_t mailbox_sm0 = {0x1800, 246, 0x26, {NULL}};
const ec_sync_t mailbox_sm1 = {0x18F6, 246, 0x22, {NULL}};
/*****************************************************************************/
/* Klemmen-Objekte */
/*****************************************************************************/
/******************************************************************************
* slave objects
*****************************************************************************/
const ec_slave_type_t Beckhoff_EK1100 = {
"Beckhoff", "EK1100", "Bus Coupler", EC_TYPE_BUS_COUPLER,
{NULL} // Keine Sync-Manager
{NULL} // no sync managers
};
/*****************************************************************************/
const ec_slave_type_t Beckhoff_EK1110 = {
"Beckhoff", "EK1110", "Extension terminal", EC_TYPE_NORMAL,
{NULL} // Keine Sync-Manager
{NULL} // no sync managers
};
/*****************************************************************************/
const ec_slave_type_t Beckhoff_BK1120 = {
"Beckhoff", "BK1120", "KBUS Coupler", EC_TYPE_NORMAL,
{NULL} // Keine Sync-Manager
{NULL} // no sync managers
};
/*****************************************************************************/
const ec_field_t el1014_in = {"InputValue", 1};
const ec_sync_t el1014_sm0 = { // Inputs
const ec_sync_t el1014_sm0 = { // inputs
0x1000, 1, 0x00,
{&el1014_in, NULL}
};
@ -195,15 +193,10 @@ const ec_slave_type_t TR_Electronic_LinEnc2 = {
/*****************************************************************************/
/**
Beziehung zwischen Identifikationsnummern und Klemmen-Objekt.
Diese Tabelle stellt die Beziehungen zwischen bestimmten Kombinationen
aus Vendor-IDs und Product-Codes und der entsprechenden Klemme her.
Neue Klemmen müssen hier eingetragen werden.
Mapping between vendor IDs and product codes <=> slave objects.
*/
ec_slave_ident_t slave_idents[] =
{
ec_slave_ident_t slave_idents[] = {
{0x00000002, 0x03F63052, &Beckhoff_EL1014},
{0x00000002, 0x044C2C52, &Beckhoff_EK1100},
{0x00000002, 0x04562C52, &Beckhoff_EK1110},
@ -222,9 +215,3 @@ ec_slave_ident_t slave_idents[] =
};
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
*
* t y p e s . h
*
* EtherCAT-Slave-Typen.
* EtherCAT slave types.
*
* $Id$
*
@ -23,27 +23,27 @@
/*****************************************************************************/
/**
Besondere Slaves.
Special slaves.
*/
typedef enum
{
EC_TYPE_NORMAL,
EC_TYPE_BUS_COUPLER,
EC_TYPE_EOE
EC_TYPE_NORMAL, /**< no special slave */
EC_TYPE_BUS_COUPLER, /**< slave is a bus coupler */
EC_TYPE_EOE /**< slave is an EoE switch */
}
ec_special_type_t;
/*****************************************************************************/
/**
Prozessdatenfeld.
Process data field.
*/
typedef struct
{
const char *name;
size_t size;
const char *name; /**< field name */
size_t size; /**< field size in bytes */
}
ec_field_t;
@ -55,60 +55,45 @@ ec_field_t;
typedef struct
{
uint16_t physical_start_address;
uint16_t size;
uint8_t control_byte;
const ec_field_t *fields[EC_MAX_FIELDS];
uint16_t physical_start_address; /**< physical start address */
uint16_t size; /**< size in bytes */
uint8_t control_byte; /**< control register value */
const ec_field_t *fields[EC_MAX_FIELDS]; /**< field array */
}
ec_sync_t;
/*****************************************************************************/
/**
Beschreibung eines EtherCAT-Slave-Typs.
Diese Beschreibung dient zur Konfiguration einer bestimmten
Slave-Art. Sie enthält die Konfigurationsdaten für die
Slave-internen Sync-Manager und FMMUs.
Slave description type.
*/
typedef struct ec_slave_type
{
const char *vendor_name; /**< Name des Herstellers */
const char *product_name; /**< Name des Slaves-Typs */
const char *description; /**< Genauere Beschreibung des Slave-Typs */
ec_special_type_t special; /**< Spezieller Slave-Typ */
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< Sync-Manager
Konfigurationen */
const char *vendor_name; /**< vendor name*/
const char *product_name; /**< product name */
const char *description; /**< free description */
ec_special_type_t special; /**< special slave type? */
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< sync managers */
}
ec_slave_type_t;
/*****************************************************************************/
/**
Identifikation eines Slave-Typs.
Diese Struktur wird zur 1:n-Zuordnung von Hersteller- und
Produktcodes zu den einzelnen Slave-Typen verwendet.
Slave type identification.
*/
typedef struct slave_ident
typedef struct
{
uint32_t vendor_id; /**< Hersteller-Code */
uint32_t product_code; /**< Herstellerspezifischer Produktcode */
const ec_slave_type_t *type; /**< Zeiger auf den entsprechenden Typ */
uint32_t vendor_id; /**< vendor id */
uint32_t product_code; /**< product code */
const ec_slave_type_t *type; /**< associated slave description object */
}
ec_slave_ident_t;
extern ec_slave_ident_t slave_idents[]; /**< Statisches Array der
Slave-Identifikationen */
extern ec_slave_ident_t slave_idents[]; /**< array with slave descriptions */
/*****************************************************************************/
#endif
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -2,7 +2,7 @@
#
# Makefile
#
# Minimales EtherCAT-Modul
# Minimal EtherCAT module.
#
# $Id$
#
@ -11,7 +11,7 @@
ifneq ($(KERNELRELEASE),)
#----------------------------------------------------------------
# Kbuild-Abschnitt
# kbuild section
#----------------------------------------------------------------
obj-m := ec_mini.o
@ -23,7 +23,7 @@ ec_mini-objs := mini.o
else
#----------------------------------------------------------------
# Default-Abschnitt
# default section
#----------------------------------------------------------------
ifneq ($(wildcard ethercat.conf),)

View File

@ -2,7 +2,7 @@
*
* m i n i . c
*
* Minimalmodul für EtherCAT
* Minimal module for EtherCAT.
*
* $Id$
*
@ -12,31 +12,28 @@
#include <linux/delay.h>
#include <linux/timer.h>
#include "../include/ecrt.h" // Echtzeitschnittstelle
#include "../include/ecrt.h" // EtherCAT realtime interface
#define ASYNC
#define FREQUENCY 100
/*****************************************************************************/
#define ABTASTFREQUENZ 100
struct timer_list timer;
/*****************************************************************************/
// EtherCAT
ec_master_t *master = NULL;
ec_domain_t *domain1 = NULL;
// Datenfelder
// data fields
//void *r_ssi_input, *r_ssi_status, *r_4102[3];
// Kanäle
// channels
uint32_t k_pos;
uint8_t k_stat;
ec_field_init_t domain1_fields[] = {
{NULL, "1", "Beckhoff", "EL5001", "InputValue", 0},
{NULL, "1", "Beckhoff", "EL5001", "InputValue", 0},
{NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0},
{}
};
@ -48,22 +45,22 @@ void run(unsigned long data)
static unsigned int counter = 0;
#ifdef ASYNC
// Empfangen
// receive
ecrt_master_async_receive(master);
ecrt_domain_process(domain1);
#else
// Senden und empfangen
// send and receive
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_sync_io(master);
ecrt_domain_process(domain1);
#endif
// Prozessdaten verarbeiten
// process data
//k_pos = EC_READ_U32(r_ssi);
#ifdef ASYNC
// Senden
// send
ecrt_domain_queue(domain1);
ecrt_master_run(master);
ecrt_master_async_send(master);
@ -73,13 +70,13 @@ void run(unsigned long data)
counter--;
}
else {
counter = ABTASTFREQUENZ;
counter = FREQUENCY;
//printk(KERN_INFO "k_pos = %i\n", k_pos);
//printk(KERN_INFO "k_stat = 0x%02X\n", k_stat);
}
// Timer neu starten
timer.expires += HZ / ABTASTFREQUENZ;
// restart timer
timer.expires += HZ / FREQUENCY;
add_timer(&timer);
}
@ -153,14 +150,14 @@ int __init init_mini_module(void)
#endif
#ifdef ASYNC
// Einmal senden und warten...
// send once and wait...
ecrt_master_prepare_async_io(master);
#endif
printk("Starting cyclic sample thread.\n");
init_timer(&timer);
timer.function = run;
timer.expires = jiffies + 10; // Das erste Mal sofort feuern
timer.expires = jiffies + 10;
add_timer(&timer);
printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n");
@ -203,8 +200,3 @@ module_exit(cleanup_mini_module);
/*****************************************************************************/
/* Emacs-Konfiguration
;;; Local Variables: ***
;;; c-basic-offset:4 ***
;;; End: ***
*/

View File

@ -1,6 +1,6 @@
#------------------------------------------------------------------------------
#
# Makefile Echtzeitmodule
# Makefile
#
# $Id$
#
@ -9,7 +9,7 @@
ifneq ($(KERNELRELEASE),)
#------------------------------------------------------------------------------
# Kbuild-Abschnitt
# kbuild section
#------------------------------------------------------------------------------
ifneq ($(wildcard $(src)/rt.conf),)
@ -44,7 +44,7 @@ EXTRA_CFLAGS := -I$(src)/rt_lib/msr-include -D_SIMULATION \
else
#------------------------------------------------------------------------------
# Default-Abschnitt
# default section
#------------------------------------------------------------------------------
ifneq ($(wildcard rt.conf),)

View File

@ -2,14 +2,6 @@
#------------------------------------------------------------
#
# (C) Copyright
# Diese Software ist geistiges Eigentum der
# Ingenieurgemeinschaft IgH. Sie darf von
# Toyota Motorsport GmbH
# beliebig kopiert und veraendert werden.
# Die Weitergabe an Dritte ist untersagt.
# Dieser Urhebrrechtshinweis muss erhalten
# bleiben.
#
# Ingenieurgemeinschaft IgH
# Heinz-Baecker-Strasse 34
# D-45356 Essen
@ -20,13 +12,13 @@
#
#------------------------------------------------------------
#
# Multithreaded Server
# Multithreaded Server
# according to the example from "Programming Perl"
# this code is improved according to the example from
# perldoc perlipc, so now safely being usable under Perl 5.8
# this code is improved according to the example from
# perldoc perlipc, so now safely being usable under Perl 5.8
# (see note (*))
#
# works with read/write on a device-file
# works with read/write on a device-file
#
# $Revision: 1.1 $
# $Date: 2004/10/01 16:00:42 $
@ -40,9 +32,9 @@ BEGIN { $ENV{PATH} = '/opt/msr/bin:/usr/bin:/bin' }
use Socket;
use Carp;
use FileHandle;
use Getopt::Std;
use Getopt::Std;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Sys::Syslog qw(:DEFAULT setlogsock);
use vars qw (
$self $pid $dolog $port $dev %opts $selfbase
@ -53,25 +45,25 @@ use vars qw (
# Do logging to local syslogd by unix-domain socket instead of inetd
setlogsock("unix");
setlogsock("unix");
# Prototypes and some little Tools
sub spawn;
sub logmsg {
sub logmsg {
my ($level, $debug, @text) = @_;
syslog("daemon|$level", @text) if $debug > $dolog;
# print STDERR "daemon|$level", @text, "\n" if $dolog;
}
sub out {
my $waitpid = wait;
my $waitpid = wait;
logmsg("notice", 2, "$waitpid exited");
unlink "$selfbase.pid";
exit 0;
}
sub help {
print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n";
exit;
print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n";
exit;
}
# Process Options
@ -81,7 +73,7 @@ sub help {
"p" => 2345,
"d" => "/dev/msr"
);
getopts("lhp:d:", \%opts);
help if $opts{"h"};
@ -94,7 +86,7 @@ $port = $opts{"p"};
$dev = $opts{"d"};
$blksize = 1024; # try to write as much bytes
$instdir = "/opt/msr";
$authfile = "$instdir/etc/hosts.auth";
$authfile = "$instdir/etc/hosts.auth";
# Start logging
openlog($self, 'pid');
@ -127,12 +119,12 @@ setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
or die "setsocketopt: $!";
bind (Server, sockaddr_in($port, INADDR_ANY))
or die "bind: $!";
listen (Server, SOMAXCONN)
listen (Server, SOMAXCONN)
or die "listen: $!";
%authhosts = ();
# get authorized hosts
open (AUTH, $authfile)
open (AUTH, $authfile)
or logmsg ("notice", 2, "Could not read allowed hosts file: $authfile");
while (<AUTH>) {
chomp;
@ -176,26 +168,26 @@ while ( 1 ) {
my $name = lc gethostbyaddr($iaddr, AF_INET);
my $ipaddr = inet_ntoa($iaddr);
my $n = 0;
# tell about the requesting client
logmsg ("info", 2, "Connection from >$ipaddr< ($name) at port $port");
spawn sub {
my ($head, $hlen, $pos, $pegel, $typ, $siz, $nch, $nrec, $dat, $i, $j, $n, $llen);
my ($watchpegel, $shmpegel);
my ($rin, $rout, $in, $line, $data_requested, $oversample);
my (@channels);
# to use stdio on writing to Client
Client->autoflush();
# Open Device
# Open Device
sysopen (DEV, "$dev", O_RDWR | O_NONBLOCK, 0666) or die("can't open $dev");
# Bitmask to check for input on stdin
$rin = "";
vec($rin, fileno(Client), 1) = 1;
vec($rin, fileno(Client), 1) = 1;
# check for authorized hosts
my $access = 'deny';
$access = 'allow' if $authhosts{$ipaddr};
@ -208,14 +200,14 @@ while ( 1 ) {
$len -= $written;
$offset += $written;
}
while ( 1 ) {
$in = select ($rout=$rin, undef, undef, 0.0); # poll client
# look for any Input from Client
if ($in) {
# exit on EOF
$len = sysread (Client, $line, $blksize) or exit;
logmsg("info", 0, "got $len bytes: \"$line\"");
logmsg("info", 0, "got $len bytes: \"$line\"");
$offset = 0;
# copy request to device
while ($len) {
@ -239,11 +231,11 @@ while ( 1 ) {
sub spawn {
my $coderef = shift;
unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
confess "usage: spawn CODEREF";
}
my $pid;
my $pid;
if (!defined($pid = fork)) {
logmsg ("notice", 2, "fork failed: $!");
return;
@ -258,15 +250,3 @@ sub spawn {
# STDOUT->autoflush();
exit &$coderef();
}