Translated all comments and documentation to english language.
This commit is contained in:
parent
09ac0b540f
commit
91c739da77
4
Makefile
4
Makefile
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 <<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Oeffentliche EtherCAT-Schnittstellen fuer EtherCAT-Geraetetreiber.
|
||||
* EtherCAT interface for EtherCAT device drivers.
|
||||
*
|
||||
* $Id$
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/******************************************************************************
|
||||
*
|
||||
* Oeffentliche EtherCAT-Schnittstellen fuer Echtzeitprozesse.
|
||||
* EtherCAT realtime interface.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
|
|
|
|||
195
master/canopen.c
195
master/canopen.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
102
master/device.c
102
master/device.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
163
master/domain.c
163
master/domain.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -117,9 +117,3 @@ void ec_eoe_print(const ec_eoe_t *eoe)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
439
master/master.c
439
master/master.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
103
master/module.c
103
master/module.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
272
master/slave.c
272
master/slave.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
||||
|
|
|
|||
203
master/slave.h
203
master/slave.h
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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),)
|
||||
|
|
|
|||
38
mini/mini.c
38
mini/mini.c
|
|
@ -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: ***
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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),)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue