This commit is contained in:
Dominik Staubli
2010-01-21 11:10:22 +01:00
21 changed files with 2233 additions and 822 deletions
+42
View File
@@ -32,6 +32,48 @@ devices/e1000/Kbuild
devices/e1000/Makefile
devices/e1000/Makefile.in
devices/modules.order
documentation/ethercat_doc.aux
documentation/ethercat_doc.idx
documentation/ethercat_doc.lof
documentation/ethercat_doc.log
documentation/ethercat_doc.lot
documentation/ethercat_doc.nlo
documentation/ethercat_doc.out
documentation/ethercat_doc.pdf
documentation/ethercat_doc.toc
documentation/external
documentation/graphs/fsm_change.pdf
documentation/graphs/fsm_change.ps
documentation/graphs/fsm_eoe.pdf
documentation/graphs/fsm_eoe.ps
documentation/graphs/fsm_master.pdf
documentation/graphs/fsm_master.ps
documentation/graphs/fsm_pdo_conf.pdf
documentation/graphs/fsm_pdo_conf.ps
documentation/graphs/fsm_pdo_entry_conf.pdf
documentation/graphs/fsm_pdo_entry_conf.ps
documentation/graphs/fsm_pdo_entry_read.pdf
documentation/graphs/fsm_pdo_entry_read.ps
documentation/graphs/fsm_pdo_read.pdf
documentation/graphs/fsm_pdo_read.ps
documentation/graphs/fsm_sii.pdf
documentation/graphs/fsm_sii.ps
documentation/graphs/fsm_slave_conf.pdf
documentation/graphs/fsm_slave_conf.ps
documentation/graphs/fsm_slave_scan.pdf
documentation/graphs/fsm_slave_scan.ps
documentation/images/app-config.pdf
documentation/images/architecture.pdf
documentation/images/attach.pdf
documentation/images/dc.pdf
documentation/images/fmmus.pdf
documentation/images/fsm-coedown.pdf
documentation/images/fsm-eoe.pdf
documentation/images/interrupt.pdf
documentation/images/master-locks.pdf
documentation/images/masters.pdf
documentation/images/phases.pdf
documentation/images/statetrans.pdf
examples/Kbuild
examples/Makefile
examples/Makefile.in
+8 -5
View File
@@ -14,13 +14,16 @@ General Features:
- Runs as kernel module for Linux 2.6.
- Multiple masters possible on one machine.
* EtherCAT-capable versions of standard Linux drivers for wide-spread
Ethernet devices.
- Interrupt-less operation of Ethernet devices.
- Easy implementation of additional Ethernet drivers through common device
interface.
* Native EtherCAT-capable versions of standard Linux drivers for wide-spread
Ethernet devices, as well as a generic driver for all chips supported by the
Linux kernel.
- Interrupt-less operation of Ethernet devices when using native drivers.
- Easy implementation of additional native Ethernet drivers through common
device interface.
- Operation possible with any device supported by the standard drivers,
including PCMCIA devices.
- For any other hardware, the generic driver can be used. It uses the lower
layers of the Linux network stack.
* Supports any realtime environment through independent architecture.
- RTAI, Xenomai, RT-Preempt, etc.
+31 -33
View File
@@ -10,6 +10,37 @@ vim700: spelllang=en spell
Version 1.5.0:
* Fix link detection in generic driver.
* Remove byte-swapping functions from user space.
* Implement 'ethercat foe_read --output-file ...'.
* Use ec_datagram_zero() wherever possible.
* Fix arguments of reg_read.
* Number layout for reg_read.
* Finish library implementation.
* Rescan command.
* Document ec_fsm_foe members.
* Implement identifier parameter for cstruct command.
* Implement sync delimiter for cstruct command.
* Change SDO index at runtime for SDO request.
* Output skipped datagrams again.
* Output warning on unmatched slave configuration.
* Output warning when send_ext() is called in illegal context.
* Output hexadecimal values in 'ethercat xml'.
* Add native drivers from 2.6.24 up to 2.6.31.
Future issues:
* Implement ecrt_slave_config_request_state().
* Implement CompleteAccess for command-line tool.
* Implement CompleteAccess for SDO uploads.
* Check for Enable SDO Complete Access flag.
* Remove default buffer size in SDO upload.
* Improve application-triggered SDO transfers by moving the state machine into
the SDO handlers.
* Check for ioctl() interface version.
* Remove allow_scanning flag.
* Override sync manager size?
* Show Record / Array / List type of SDOs.
* Distributed clocks:
- Check 32/64 bit operations.
- Use vendor correction factors when calculating transmission delays.
@@ -20,39 +51,6 @@ Version 1.5.0:
"System Time" register instead of using the application time.
- Check if register 0x0980 is working, to avoid clearing it when
configuring.
* Remove byte-swapping functions from user space.
* Implement 'ethercat foe_read --output-file ...'.
* Use ec_datagram_zero() where possible.
* Fix arguments of reg_read.
* Number layout for reg_read.
* Show Record / Array / List type of SDOs.
* Finish library implementation.
* Rescan command.
* Override sync manager size?
* Check force_config flag before error.
* Remove allow_scanning flag.
* Check for ioctl() interface version.
* Improve application-triggered SDO transfers by moving the state machine into
the SDO handlers.
* Document ec_fsm_foe members.
* Test KBUILD_EXTRA_SYMBOLS.
* Remove default buffer size in SDO upload.
* Check for Enable SDO Complete Access flag.
* Implement CompleteAccess for command-line tool.
* Implement CompleteAccess for SDO uploads.
* Implement identifier parameter for cstruct command.
* Implement sync delimiter for cstruct command.
* Change SDO index at runtime for SDO request.
* Implement ecrt_slave_config_request_state().
* Output skipped datagrams again.
* Output warning on unmatched slave configuration.
* ec_direction_t default
* Send_ext context warn
* XML hex
* r8169
Future issues:
* Mailbox protocol handlers.
* Mailbox state machine using toggle bits.
* External memory for SDO transfers.
+24
View File
@@ -474,6 +474,30 @@ if test "x${cycles}" = "x1"; then
AC_DEFINE([EC_HAVE_CYCLES], [1], [Use CPU timestamp counter])
fi
#------------------------------------------------------------------------------
# High-resolution timer support
#------------------------------------------------------------------------------
AC_ARG_ENABLE([hrtimer],
AS_HELP_STRING([--enable-hrtimer],
[Use high-resolution timer for scheduling (default: no)]),
[
case "${enableval}" in
yes) hrtimer=1
;;
no) hrtimer=0
;;
*) AC_MSG_ERROR([Invalid value for --enable-hrtimer])
;;
esac
],
[hrtimer=0]
)
if test "x${hrtimer}" = "x1"; then
AC_DEFINE([EC_USE_HRTIMER], [1], [Use hrtimer for scheduling])
fi
#------------------------------------------------------------------------------
# Command-line tool
#-----------------------------------------------------------------------------
+13 -12
View File
@@ -70,16 +70,16 @@ struct list_head generic_devices;
typedef struct {
struct list_head list;
struct net_device *netdev;
struct net_device *used_netdev;
struct socket *socket;
struct net_device *used_netdev;
struct socket *socket;
ec_device_t *ecdev;
uint8_t *rx_buf;
} ec_gen_device_t;
typedef struct {
struct list_head list;
struct net_device *netdev;
char name[IFNAMSIZ];
struct net_device *netdev;
char name[IFNAMSIZ];
int ifindex;
uint8_t dev_addr[ETH_ALEN];
} ec_gen_interface_desc_t;
@@ -202,7 +202,7 @@ int ec_gen_device_create_socket(
int ret;
struct sockaddr_ll sa;
dev->rx_buf = kmalloc(EC_GEN_RX_BUF_SIZE, GFP_KERNEL);
dev->rx_buf = kmalloc(EC_GEN_RX_BUF_SIZE, GFP_KERNEL);
if (!dev->rx_buf) {
return -ENOMEM;
}
@@ -242,8 +242,8 @@ int ec_gen_device_offer(
{
int ret = 0;
dev->used_netdev = desc->netdev;
memcpy(dev->netdev->dev_addr, desc->dev_addr, ETH_ALEN);
dev->used_netdev = desc->netdev;
memcpy(dev->netdev->dev_addr, desc->dev_addr, ETH_ALEN);
dev->ecdev = ecdev_offer(dev->netdev, ec_gen_poll, THIS_MODULE);
if (dev->ecdev) {
@@ -254,7 +254,7 @@ int ec_gen_device_offer(
ecdev_withdraw(dev->ecdev);
dev->ecdev = NULL;
} else {
ecdev_set_link(dev->ecdev, netif_carrier_ok(dev->used_netdev)); // FIXME
ecdev_set_link(dev->ecdev, netif_carrier_ok(dev->used_netdev)); // FIXME
ret = 1;
}
}
@@ -296,7 +296,7 @@ int ec_gen_device_start_xmit(
size_t len = skb->len;
int ret;
ecdev_set_link(dev->ecdev,netif_carrier_ok(dev->used_netdev));
ecdev_set_link(dev->ecdev, netif_carrier_ok(dev->used_netdev));
iov.iov_base = skb->data;
iov.iov_len = len;
@@ -319,8 +319,9 @@ void ec_gen_device_poll(
struct kvec iov;
int ret, budget = 10; // FIXME
ecdev_set_link(dev->ecdev,netif_carrier_ok(dev->used_netdev));
do {
ecdev_set_link(dev->ecdev, netif_carrier_ok(dev->used_netdev));
do {
iov.iov_base = dev->rx_buf;
iov.iov_len = EC_GEN_RX_BUF_SIZE;
memset(&msg, 0, sizeof(msg));
@@ -414,7 +415,7 @@ int __init ec_gen_init_module(void)
goto out_err;
}
strncpy(desc->name, netdev->name, IFNAMSIZ);
desc->netdev = netdev;
desc->netdev = netdev;
desc->ifindex = netdev->ifindex;
memcpy(desc->dev_addr, netdev->dev_addr, ETH_ALEN);
list_add_tail(&desc->list, &descs);
File diff suppressed because it is too large Load Diff
+11 -4
View File
@@ -6,7 +6,6 @@
FIGS := \
app-config.fig \
architecture.fig \
attach.fig \
dc.fig \
fmmus.fig \
@@ -18,14 +17,22 @@ FIGS := \
phases.fig \
statetrans.fig
PDFS = $(FIGS:.fig=.pdf)
FIGPDFS = $(FIGS:.fig=.pdf)
all: $(PDFS)
SVGS := \
architecture.svg
SVGPDFS = $(SVGS:.svg=.pdf)
all: $(FIGPDFS) $(SVGPDFS)
%.pdf: %.fig
fig2dev -L pdf -z A4 -p xxx -c $< $@
%.pdf: %.svg
inkscape --export-pdf=$@ $<
clean:
@rm -rv $(PDFS)
@rm -rv $(FIGPDFS) $(SVGPDFS)
#-----------------------------------------------------------------------------
-176
View File
@@ -1,176 +0,0 @@
#FIG 3.2
Portrait
Center
Metric
A4
100.00
Single
-2
1200 2
5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 7245.000 5985.000 6975 5985 7245 5715 7515 5985
6 5085 7965 5850 8820
2 3 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 8
5175 7965 5760 7965 5760 8775 5175 8775 5175 8415 5085 8415
5085 7965 5175 7965
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
5490 8190 5670 8190 5670 8370 5490 8370 5490 8190
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
5310 8505 5400 8505 5400 8595 5310 8595 5310 8505
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8055 5085 8055
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8145 5085 8145
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8190 5085 8190
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8280 5085 8280
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8235 5085 8235
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8100 5085 8100
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8010 5085 8010
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8325 5085 8325
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5175 8370 5085 8370
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
5850 8775 5085 8775 5085 8815 5850 8815 5850 8775
-6
6 6435 7965 7200 8820
2 3 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 8
6525 7965 7110 7965 7110 8775 6525 8775 6525 8415 6435 8415
6435 7965 6525 7965
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
6840 8190 7020 8190 7020 8370 6840 8370 6840 8190
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
6660 8505 6750 8505 6750 8595 6660 8595 6660 8505
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8055 6435 8055
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8145 6435 8145
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8190 6435 8190
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8280 6435 8280
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8235 6435 8235
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8100 6435 8100
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8010 6435 8010
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8325 6435 8325
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
6525 8370 6435 8370
2 2 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 5
7200 8775 6435 8775 6435 8815 7200 8815 7200 8775
-6
6 4905 5445 5985 6030
5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5445.000 5985.000 4950 5985 5445 5490 5940 5985
4 1 0 50 -1 16 10 0.0000 4 120 465 5445 5760 Device\001
4 1 0 50 -1 16 10 0.0000 4 120 615 5445 5925 Interface\001
-6
6 3870 4275 4500 5355
5 1 0 1 0 7 50 -1 20 0.000 0 0 0 0 3958.125 4815.000 3915 4320 4455 4815 3915 5310
4 1 0 49 -1 16 10 4.7124 4 150 765 4162 4822 Application\001
4 1 0 49 -1 16 10 4.7124 4 120 615 3997 4822 Interface\001
-6
6 5205 2648 6480 3293
5 1 0 1 0 7 50 -1 -1 0.000 0 0 0 0 5842.000 2655.000 6472 2655 5842 3285 5212 2655
4 1 0 50 -1 16 12 0.0000 4 135 600 5842 3105 Device\001
4 1 0 50 -1 16 12 0.0000 4 135 825 5842 2880 Character\001
-6
6 3870 945 4500 2025
5 1 0 1 0 7 49 -1 -1 0.000 0 0 0 0 3958.125 1485.000 3915 990 4455 1485 3915 1980
4 1 0 48 -1 16 10 4.7124 4 150 765 4162 1492 Application\001
4 1 0 48 -1 16 10 4.7124 4 120 615 3997 1492 Interface\001
-6
6 2160 855 3420 2115
1 3 0 1 0 7 50 -1 20 0.000 1 0.0000 2790 1485 585 585 2790 1485 3375 1485
4 1 0 49 -1 16 12 0.0000 4 180 945 2790 1665 Application\001
4 1 0 49 -1 16 12 0.0000 4 180 885 2790 1440 Userspace\001
-6
1 4 0 1 0 7 50 -1 -1 0.000 1 0.0000 2484 4871 459 459 2025 4860 2944 4882
1 2 0 1 0 7 50 -1 -1 0.000 1 0.0000 5445 4815 810 495 4635 4320 6255 5310
1 4 0 1 0 7 50 -1 -1 4.000 1 0.0000 7058 1658 495 495 7553 2153 6563 1163
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5445 7965 5445 7425
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
6795 7965 6795 7425
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5445 6885 5445 5985
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
5535 8820 5625 8820 5625 8910 5535 8910 5535 8820
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6885 8820 6975 8820 6975 8910 6885 8910 6885 8820
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
7245 6885 7245 5985
2 4 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 5
7605 7605 7605 6345 4635 6345 4635 7605 7605 7605
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
4905 6885 5985 6885 5985 7425 4905 7425 4905 6885
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
6255 6885 7335 6885 7335 7425 6255 7425 6255 6885
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
5445 5490 5445 5310
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
4635 4815 4455 4815
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
3915 4815 3465 4815
2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5
7605 3645 6885 3645 6885 5985 7605 5985 7605 3645
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
1575 7785 7785 7785
2 4 0 1 0 7 50 -1 -1 0.000 0 0 9 0 0 5
1755 5985 1755 3645 3465 3645 3465 5985 1755 5985
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
7785 8280 7785 2205
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
1575 8280 1575 2205
2 4 0 1 0 7 50 -1 -1 0.000 0 0 8 0 0 5
6435 5985 6435 3645 3915 3645 3915 5985 6435 5985
2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
7785 2655 1575 2655
2 1 0 1 0 7 50 -1 -1 4.000 0 0 -1 0 0 2
5850 3285 5850 3645
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
3915 1485 3375 1485
2 4 0 1 0 7 50 -1 20 0.000 0 0 7 0 0 5
5040 2250 3915 2250 3915 720 5040 720 5040 2250
3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
5580 8910 5355 9045 4770 9090
0.000 -1.000 0.000
3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
6931 8910 6390 9270 4770 9450
0.000 -1.000 0.000
3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
6570 1665 6120 1890 5985 2655
0.000 -1.000 0.000
3 2 0 1 0 7 50 -1 -1 0.000 0 0 0 3
5040 1485 5580 1800 5715 2655
0.000 -1.000 0.000
4 1 0 50 -1 16 10 0.0000 4 150 750 5445 7200 net_device\001
4 1 0 50 -1 16 10 0.0000 4 150 750 6795 7200 net_device\001
4 2 0 50 -1 12 10 0.0000 4 105 810 5355 6210 ecdev_*()\001
4 1 0 50 -1 16 12 0.0000 4 135 1545 6345 6570 EtherCAT Network\001
4 1 0 50 -1 16 12 0.0000 4 135 1200 6345 6750 Driver Module\001
4 0 0 50 -1 16 12 0.0000 4 135 2130 4005 3870 EtherCAT Master Module\001
4 1 0 50 -1 16 12 1.5708 4 135 1200 7290 4815 Network Stack\001
4 2 0 50 -1 16 12 0.0000 4 135 810 4725 9135 EtherCAT\001
4 2 0 50 -1 16 12 0.0000 4 135 690 4725 9495 Ethernet\001
4 2 0 50 -1 16 12 0.0000 4 135 315 4995 8100 NIC\001
4 2 0 50 -1 16 12 0.0000 4 135 315 6345 8100 NIC\001
4 0 0 50 -1 16 12 0.0000 4 135 810 1665 8010 Hardware\001
4 2 0 50 -1 12 10 4.7124 4 105 720 3645 4725 ecrt_*()\001
4 0 0 50 -1 16 12 0.0000 4 180 945 1845 3870 Application\001
4 0 0 50 -1 16 12 0.0000 4 135 630 1845 4095 Module\001
4 1 0 50 -1 16 12 0.0000 4 135 390 2475 4950 Task\001
4 0 0 50 -1 16 12 0.0000 4 180 1050 1665 2880 Kernelspace\001
4 0 0 50 -1 16 12 0.0000 4 180 885 1665 2565 Userspace\001
4 1 0 50 -1 16 12 4.7124 4 135 870 4635 1530 libethercat\001
4 2 0 50 -1 12 10 4.7124 4 105 720 3645 1395 ecrt_*()\001
4 2 0 50 -1 12 10 0.0000 4 105 810 7155 6210 netif_*()\001
4 1 0 50 -1 16 12 0.0000 4 135 735 5445 4905 Master 0\001
4 1 0 50 -1 16 12 0.0000 4 135 360 7065 1845 Tool\001
4 1 0 50 -1 16 12 0.0000 4 135 765 7065 1620 'ethercat'\001
File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 44 KiB

+8 -1
View File
@@ -27,12 +27,19 @@
#
#------------------------------------------------------------------------------
SUBDIRS =
if ENABLE_USERLIB
SUBDIRS = \
SUBDIRS += \
dc_user \
user
endif
if ENABLE_TTY
SUBDIRS += \
tty
endif
DIST_SUBDIRS = \
dc_rtai \
dc_user \
+5 -1
View File
@@ -33,7 +33,11 @@
obj-m := ec_tty_example.o
ec_tty_example-objs := tty.o
ec_tty_example-objs := \
serial.o \
tty.o
CFLAGS_tty.o := -I$(src)
KBUILD_EXTRA_SYMBOLS := \
@abs_top_builddir@/Module.symvers \
+5 -2
View File
@@ -31,10 +31,13 @@
#
#------------------------------------------------------------------------------
EXTRA_DIST = \
Kbuild.in \
noinst_HEADERS = \
serial.h \
tty.c
EXTRA_DIST = \
Kbuild.in
BUILT_SOURCES = \
Kbuild
+455
View File
@@ -0,0 +1,455 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* The IgH EtherCAT Master is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* ---
*
* The license mentioned above concerns the source code only. Using the
* EtherCAT technology and brand is only permitted in compliance with the
* industrial property and similar rights of Beckhoff Automation GmbH.
*
*****************************************************************************/
#include <linux/module.h>
#include <linux/err.h>
#include "../../include/ecrt.h" // EtherCAT realtime interface
#include "../../include/ectty.h" // EtherCAT TTY interface
/*****************************************************************************/
// Optional features
#define PFX "ec_tty_example: "
/*****************************************************************************/
#define VendorIdBeckhoff 0x00000002
#define ProductCodeBeckhoffEL6002 0x17723052
#define Beckhoff_EL6002 VendorIdBeckhoff, ProductCodeBeckhoffEL6002
typedef enum {
SER_REQUEST_INIT,
SER_WAIT_FOR_INIT_RESPONSE,
SER_READY
} serial_state_t;
typedef struct {
struct list_head list;
ec_tty_t *tty;
ec_slave_config_t *sc;
size_t max_tx_data_size;
size_t max_rx_data_size;
u8 *tx_data;
u8 tx_data_size;
serial_state_t state;
u8 tx_request_toggle;
u8 tx_accepted_toggle;
u8 rx_request_toggle;
u8 rx_accepted_toggle;
u16 control;
u32 off_ctrl;
u32 off_tx;
u32 off_status;
u32 off_rx;
} el6002_t;
LIST_HEAD(handlers);
/*****************************************************************************/
/* Beckhoff EL6002
* Vendor ID: 0x00000002
* Product code: 0x17723052
* Revision number: 0x00100000
*/
ec_pdo_entry_info_t el6002_pdo_entries[] = {
{0x7001, 0x01, 16}, /* Ctrl */
{0x7000, 0x11, 8}, /* Data Out 0 */
{0x7000, 0x12, 8}, /* Data Out 1 */
{0x7000, 0x13, 8}, /* Data Out 2 */
{0x7000, 0x14, 8}, /* Data Out 3 */
{0x7000, 0x15, 8}, /* Data Out 4 */
{0x7000, 0x16, 8}, /* Data Out 5 */
{0x7000, 0x17, 8}, /* Data Out 6 */
{0x7000, 0x18, 8}, /* Data Out 7 */
{0x7000, 0x19, 8}, /* Data Out 8 */
{0x7000, 0x1a, 8}, /* Data Out 9 */
{0x7000, 0x1b, 8}, /* Data Out 10 */
{0x7000, 0x1c, 8}, /* Data Out 11 */
{0x7000, 0x1d, 8}, /* Data Out 12 */
{0x7000, 0x1e, 8}, /* Data Out 13 */
{0x7000, 0x1f, 8}, /* Data Out 14 */
{0x7000, 0x20, 8}, /* Data Out 15 */
{0x7000, 0x21, 8}, /* Data Out 16 */
{0x7000, 0x22, 8}, /* Data Out 17 */
{0x7000, 0x23, 8}, /* Data Out 18 */
{0x7000, 0x24, 8}, /* Data Out 19 */
{0x7000, 0x25, 8}, /* Data Out 20 */
{0x7000, 0x26, 8}, /* Data Out 21 */
{0x7011, 0x01, 16}, /* Ctrl */
{0x7010, 0x11, 8}, /* Data Out 0 */
{0x7010, 0x12, 8}, /* Data Out 1 */
{0x7010, 0x13, 8}, /* Data Out 2 */
{0x7010, 0x14, 8}, /* Data Out 3 */
{0x7010, 0x15, 8}, /* Data Out 4 */
{0x7010, 0x16, 8}, /* Data Out 5 */
{0x7010, 0x17, 8}, /* Data Out 6 */
{0x7010, 0x18, 8}, /* Data Out 7 */
{0x7010, 0x19, 8}, /* Data Out 8 */
{0x7010, 0x1a, 8}, /* Data Out 9 */
{0x7010, 0x1b, 8}, /* Data Out 10 */
{0x7010, 0x1c, 8}, /* Data Out 11 */
{0x7010, 0x1d, 8}, /* Data Out 12 */
{0x7010, 0x1e, 8}, /* Data Out 13 */
{0x7010, 0x1f, 8}, /* Data Out 14 */
{0x7010, 0x20, 8}, /* Data Out 15 */
{0x7010, 0x21, 8}, /* Data Out 16 */
{0x7010, 0x22, 8}, /* Data Out 17 */
{0x7010, 0x23, 8}, /* Data Out 18 */
{0x7010, 0x24, 8}, /* Data Out 19 */
{0x7010, 0x25, 8}, /* Data Out 20 */
{0x7010, 0x26, 8}, /* Data Out 21 */
{0x6001, 0x01, 16}, /* Status */
{0x6000, 0x11, 8}, /* Data In 0 */
{0x6000, 0x12, 8}, /* Data In 1 */
{0x6000, 0x13, 8}, /* Data In 2 */
{0x6000, 0x14, 8}, /* Data In 3 */
{0x6000, 0x15, 8}, /* Data In 4 */
{0x6000, 0x16, 8}, /* Data In 5 */
{0x6000, 0x17, 8}, /* Data In 6 */
{0x6000, 0x18, 8}, /* Data In 7 */
{0x6000, 0x19, 8}, /* Data In 8 */
{0x6000, 0x1a, 8}, /* Data In 9 */
{0x6000, 0x1b, 8}, /* Data In 10 */
{0x6000, 0x1c, 8}, /* Data In 11 */
{0x6000, 0x1d, 8}, /* Data In 12 */
{0x6000, 0x1e, 8}, /* Data In 13 */
{0x6000, 0x1f, 8}, /* Data In 14 */
{0x6000, 0x20, 8}, /* Data In 15 */
{0x6000, 0x21, 8}, /* Data In 16 */
{0x6000, 0x22, 8}, /* Data In 17 */
{0x6000, 0x23, 8}, /* Data In 18 */
{0x6000, 0x24, 8}, /* Data In 19 */
{0x6000, 0x25, 8}, /* Data In 20 */
{0x6000, 0x26, 8}, /* Data In 21 */
{0x6011, 0x01, 16}, /* Status */
{0x6010, 0x11, 8}, /* Data In 0 */
{0x6010, 0x12, 8}, /* Data In 1 */
{0x6010, 0x13, 8}, /* Data In 2 */
{0x6010, 0x14, 8}, /* Data In 3 */
{0x6010, 0x15, 8}, /* Data In 4 */
{0x6010, 0x16, 8}, /* Data In 5 */
{0x6010, 0x17, 8}, /* Data In 6 */
{0x6010, 0x18, 8}, /* Data In 7 */
{0x6010, 0x19, 8}, /* Data In 8 */
{0x6010, 0x1a, 8}, /* Data In 9 */
{0x6010, 0x1b, 8}, /* Data In 10 */
{0x6010, 0x1c, 8}, /* Data In 11 */
{0x6010, 0x1d, 8}, /* Data In 12 */
{0x6010, 0x1e, 8}, /* Data In 13 */
{0x6010, 0x1f, 8}, /* Data In 14 */
{0x6010, 0x20, 8}, /* Data In 15 */
{0x6010, 0x21, 8}, /* Data In 16 */
{0x6010, 0x22, 8}, /* Data In 17 */
{0x6010, 0x23, 8}, /* Data In 18 */
{0x6010, 0x24, 8}, /* Data In 19 */
{0x6010, 0x25, 8}, /* Data In 20 */
{0x6010, 0x26, 8}, /* Data In 21 */
};
ec_pdo_info_t el6002_pdos[] = {
{0x1604, 23, el6002_pdo_entries + 0}, /* COM RxPDO-Map Outputs Ch.1 */
{0x1605, 23, el6002_pdo_entries + 23}, /* COM RxPDO-Map Outputs Ch.2 */
{0x1a04, 23, el6002_pdo_entries + 46}, /* COM TxPDO-Map Inputs Ch.1 */
{0x1a05, 23, el6002_pdo_entries + 69}, /* COM TxPDO-Map Inputs Ch.2 */
};
ec_sync_info_t el6002_syncs[] = {
{0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
{1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
{2, EC_DIR_OUTPUT, 2, el6002_pdos + 0, EC_WD_DISABLE},
{3, EC_DIR_INPUT, 2, el6002_pdos + 2, EC_WD_DISABLE},
{0xff}
};
/****************************************************************************/
int el6002_init(el6002_t *ser, ec_master_t *master, u16 position,
ec_domain_t *domain)
{
int ret = 0;
ser->tty = ectty_create();
if (IS_ERR(ser->tty)) {
printk(KERN_ERR PFX "Failed to create tty.\n");
ret = PTR_ERR(ser->tty);
goto out_return;
}
ser->sc = NULL;
ser->max_tx_data_size = 22;
ser->max_rx_data_size = 22;
ser->tx_data = NULL;
ser->tx_data_size = 0;
ser->state = SER_REQUEST_INIT;
ser->tx_request_toggle = 0;
ser->rx_accepted_toggle = 0;
ser->control = 0x0000;
ser->off_ctrl = 0;
ser->off_tx = 0;
ser->off_status = 0;
ser->off_rx = 0;
if (!(ser->sc = ecrt_master_slave_config(
master, 0, position, Beckhoff_EL6002))) {
printk(KERN_ERR PFX "Failed to create slave configuration.\n");
ret = -EBUSY;
goto out_free_tty;
}
if (ecrt_slave_config_pdos(ser->sc, EC_END, el6002_syncs)) {
printk(KERN_ERR PFX "Failed to configure PDOs.\n");
ret = -ENOMEM;
goto out_free_tty;
}
ret = ecrt_slave_config_reg_pdo_entry(
ser->sc, 0x7001, 0x01, domain, NULL);
if (ret < 0) {
printk(KERN_ERR PFX "Failed to register PDO entry.\n");
goto out_free_tty;
}
ser->off_ctrl = ret;
ret = ecrt_slave_config_reg_pdo_entry(
ser->sc, 0x7000, 0x11, domain, NULL);
if (ret < 0) {
printk(KERN_ERR PFX "Failed to register PDO entry.\n");
goto out_free_tty;
}
ser->off_tx = ret;
ret = ecrt_slave_config_reg_pdo_entry(
ser->sc, 0x6001, 0x01, domain, NULL);
if (ret < 0) {
printk(KERN_ERR PFX "Failed to register PDO entry.\n");
goto out_free_tty;
}
ser->off_status = ret;
ret = ecrt_slave_config_reg_pdo_entry(
ser->sc, 0x6000, 0x11, domain, NULL);
if (ret < 0) {
printk(KERN_ERR PFX "Failed to register PDO entry.\n");
goto out_free_tty;
}
ser->off_rx = ret;
if (ser->max_tx_data_size > 0) {
ser->tx_data = kmalloc(ser->max_tx_data_size, GFP_KERNEL);
if (ser->tx_data == NULL) {
ret = -ENOMEM;
goto out_free_tty;
}
}
return 0;
out_free_tty:
ectty_free(ser->tty);
out_return:
return ret;
}
/****************************************************************************/
void el6002_clear(el6002_t *ser)
{
ectty_free(ser->tty);
if (ser->tx_data) {
kfree(ser->tx_data);
}
}
/****************************************************************************/
void el6002_run(el6002_t *ser, u8 *pd)
{
u16 status = EC_READ_U16(pd + ser->off_status);
u8 *rx_data = pd + ser->off_rx;
uint8_t tx_accepted_toggle, rx_request_toggle;
switch (ser->state) {
case SER_READY:
/* Send data */
tx_accepted_toggle = status & 0x0001;
if (tx_accepted_toggle != ser->tx_accepted_toggle) { // ready
ser->tx_data_size =
ectty_tx_data(ser->tty, ser->tx_data, ser->max_tx_data_size);
if (ser->tx_data_size) {
printk(KERN_INFO PFX "Sending %u bytes.\n", ser->tx_data_size);
ser->tx_request_toggle = !ser->tx_request_toggle;
ser->tx_accepted_toggle = tx_accepted_toggle;
}
}
/* Receive data */
rx_request_toggle = status & 0x0002;
if (rx_request_toggle != ser->rx_request_toggle) {
uint8_t rx_data_size = status >> 8;
ser->rx_request_toggle = rx_request_toggle;
printk(KERN_INFO PFX "Received %u bytes.\n", rx_data_size);
ectty_rx_data(ser->tty, rx_data, rx_data_size);
ser->rx_accepted_toggle = !ser->rx_accepted_toggle;
}
ser->control =
ser->tx_request_toggle |
ser->rx_accepted_toggle << 1 |
ser->tx_data_size << 8;
break;
case SER_REQUEST_INIT:
if (status & (1 << 2)) {
ser->control = 0x0000;
ser->state = SER_WAIT_FOR_INIT_RESPONSE;
} else {
ser->control = 1 << 2; // CW.2, request initialization
}
break;
case SER_WAIT_FOR_INIT_RESPONSE:
if (!(status & (1 << 2))) {
printk(KERN_INFO PFX "Init successful.\n");
ser->tx_accepted_toggle = 1;
ser->control = 0x0000;
ser->state = SER_READY;
}
break;
}
EC_WRITE_U16(pd + ser->off_ctrl, ser->control);
memcpy(pd + ser->off_tx, ser->tx_data, ser->tx_data_size);
}
/*****************************************************************************/
void run_serial_devices(u8 *pd)
{
el6002_t *ser;
list_for_each_entry(ser, &handlers, list) {
el6002_run(ser, pd);
}
}
/*****************************************************************************/
int create_serial_devices(ec_master_t *master, ec_domain_t *domain)
{
int i, ret;
ec_master_info_t master_info;
ec_slave_info_t slave_info;
el6002_t *ser, *next;
printk(KERN_INFO PFX "Registering serial devices...\n");
ret = ecrt_master(master, &master_info);
if (ret) {
printk(KERN_ERR PFX "Failed to obtain master information.\n");
goto out_return;
}
for (i = 0; i < master_info.slave_count; i++) {
ret = ecrt_master_get_slave(master, i, &slave_info);
if (ret) {
printk(KERN_ERR PFX "Failed to obtain slave information.\n");
goto out_free_handlers;
}
if (slave_info.vendor_id != VendorIdBeckhoff
|| slave_info.product_code != ProductCodeBeckhoffEL6002) {
continue;
}
printk(KERN_INFO PFX "Creating handler for serial device"
" at position %i\n", i);
ser = kmalloc(sizeof(*ser), GFP_KERNEL);
if (!ser) {
printk(KERN_ERR PFX "Failed to allocate serial device object.\n");
ret = -ENOMEM;
goto out_free_handlers;
}
ret = el6002_init(ser, master, i, domain);
if (ret) {
printk(KERN_ERR PFX "Failed to init serial device object.\n");
kfree(ser);
goto out_free_handlers;
}
list_add_tail(&ser->list, &handlers);
}
printk(KERN_INFO PFX "Finished.\n");
return 0;
out_free_handlers:
list_for_each_entry_safe(ser, next, &handlers, list) {
list_del(&ser->list);
el6002_clear(ser);
kfree(ser);
}
out_return:
return ret;
}
/*****************************************************************************/
void free_serial_devices(void)
{
el6002_t *ser, *next;
printk(KERN_INFO PFX "Cleaning up serial devices...\n");
list_for_each_entry_safe(ser, next, &handlers, list) {
list_del(&ser->list);
el6002_clear(ser);
kfree(ser);
}
printk(KERN_INFO PFX "Finished cleaning up serial devices.\n");
}
/*****************************************************************************/
+35
View File
@@ -0,0 +1,35 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* The IgH EtherCAT Master is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* ---
*
* The license mentioned above concerns the source code only. Using the
* EtherCAT technology and brand is only permitted in compliance with the
* industrial property and similar rights of Beckhoff Automation GmbH.
*
*****************************************************************************/
int create_serial_devices(ec_master_t *, ec_domain_t *);
void free_serial_devices(void);
void run_serial_devices(u8 *);
/*****************************************************************************/
+15 -307
View File
@@ -40,7 +40,8 @@
#endif
#include "../../include/ecrt.h" // EtherCAT realtime interface
#include "../../include/ectty.h" // EtherCAT TTY interface
#include "serial.h"
/*****************************************************************************/
@@ -70,264 +71,11 @@ static struct timer_list timer;
static uint8_t *domain1_pd; // process data memory
#define BusCouplerPos 0, 0
#define SerialPos 0, 1
#define Beckhoff_EK1100 0x00000002, 0x044c2c52
#define Beckhoff_EL6002 0x00000002, 0x17723052
// offsets for PDO entries
static unsigned int off_ctrl;
static unsigned int off_tx;
static unsigned int off_status;
static unsigned int off_rx;
const static ec_pdo_entry_reg_t domain1_regs[] = {
{SerialPos, Beckhoff_EL6002, 0x7001, 0x01, &off_ctrl},
{SerialPos, Beckhoff_EL6002, 0x7000, 0x11, &off_tx},
{SerialPos, Beckhoff_EL6002, 0x6001, 0x01, &off_status},
{SerialPos, Beckhoff_EL6002, 0x6000, 0x11, &off_rx},
{}
};
static unsigned int counter = 0;
typedef enum {
SER_REQUEST_INIT,
SER_WAIT_FOR_INIT_RESPONSE,
SER_READY
} serial_state_t;
typedef struct {
size_t max_tx_data_size;
size_t max_rx_data_size;
uint8_t *tx_data;
uint8_t tx_data_size;
serial_state_t state;
uint8_t tx_request_toggle;
uint8_t tx_accepted_toggle;
uint8_t rx_request_toggle;
uint8_t rx_accepted_toggle;
uint16_t control;
} serial_device_t;
static serial_device_t *ser = NULL;
static ec_tty_t *tty = NULL;
/*****************************************************************************/
/* Slave 1, "EL6002"
* Vendor ID: 0x00000002
* Product code: 0x17723052
* Revision number: 0x00100000
*/
ec_pdo_entry_info_t slave_1_pdo_entries[] = {
{0x7001, 0x01, 16}, /* Ctrl */
{0x7000, 0x11, 8}, /* Data Out 0 */
{0x7000, 0x12, 8}, /* Data Out 1 */
{0x7000, 0x13, 8}, /* Data Out 2 */
{0x7000, 0x14, 8}, /* Data Out 3 */
{0x7000, 0x15, 8}, /* Data Out 4 */
{0x7000, 0x16, 8}, /* Data Out 5 */
{0x7000, 0x17, 8}, /* Data Out 6 */
{0x7000, 0x18, 8}, /* Data Out 7 */
{0x7000, 0x19, 8}, /* Data Out 8 */
{0x7000, 0x1a, 8}, /* Data Out 9 */
{0x7000, 0x1b, 8}, /* Data Out 10 */
{0x7000, 0x1c, 8}, /* Data Out 11 */
{0x7000, 0x1d, 8}, /* Data Out 12 */
{0x7000, 0x1e, 8}, /* Data Out 13 */
{0x7000, 0x1f, 8}, /* Data Out 14 */
{0x7000, 0x20, 8}, /* Data Out 15 */
{0x7000, 0x21, 8}, /* Data Out 16 */
{0x7000, 0x22, 8}, /* Data Out 17 */
{0x7000, 0x23, 8}, /* Data Out 18 */
{0x7000, 0x24, 8}, /* Data Out 19 */
{0x7000, 0x25, 8}, /* Data Out 20 */
{0x7000, 0x26, 8}, /* Data Out 21 */
{0x7011, 0x01, 16}, /* Ctrl */
{0x7010, 0x11, 8}, /* Data Out 0 */
{0x7010, 0x12, 8}, /* Data Out 1 */
{0x7010, 0x13, 8}, /* Data Out 2 */
{0x7010, 0x14, 8}, /* Data Out 3 */
{0x7010, 0x15, 8}, /* Data Out 4 */
{0x7010, 0x16, 8}, /* Data Out 5 */
{0x7010, 0x17, 8}, /* Data Out 6 */
{0x7010, 0x18, 8}, /* Data Out 7 */
{0x7010, 0x19, 8}, /* Data Out 8 */
{0x7010, 0x1a, 8}, /* Data Out 9 */
{0x7010, 0x1b, 8}, /* Data Out 10 */
{0x7010, 0x1c, 8}, /* Data Out 11 */
{0x7010, 0x1d, 8}, /* Data Out 12 */
{0x7010, 0x1e, 8}, /* Data Out 13 */
{0x7010, 0x1f, 8}, /* Data Out 14 */
{0x7010, 0x20, 8}, /* Data Out 15 */
{0x7010, 0x21, 8}, /* Data Out 16 */
{0x7010, 0x22, 8}, /* Data Out 17 */
{0x7010, 0x23, 8}, /* Data Out 18 */
{0x7010, 0x24, 8}, /* Data Out 19 */
{0x7010, 0x25, 8}, /* Data Out 20 */
{0x7010, 0x26, 8}, /* Data Out 21 */
{0x6001, 0x01, 16}, /* Status */
{0x6000, 0x11, 8}, /* Data In 0 */
{0x6000, 0x12, 8}, /* Data In 1 */
{0x6000, 0x13, 8}, /* Data In 2 */
{0x6000, 0x14, 8}, /* Data In 3 */
{0x6000, 0x15, 8}, /* Data In 4 */
{0x6000, 0x16, 8}, /* Data In 5 */
{0x6000, 0x17, 8}, /* Data In 6 */
{0x6000, 0x18, 8}, /* Data In 7 */
{0x6000, 0x19, 8}, /* Data In 8 */
{0x6000, 0x1a, 8}, /* Data In 9 */
{0x6000, 0x1b, 8}, /* Data In 10 */
{0x6000, 0x1c, 8}, /* Data In 11 */
{0x6000, 0x1d, 8}, /* Data In 12 */
{0x6000, 0x1e, 8}, /* Data In 13 */
{0x6000, 0x1f, 8}, /* Data In 14 */
{0x6000, 0x20, 8}, /* Data In 15 */
{0x6000, 0x21, 8}, /* Data In 16 */
{0x6000, 0x22, 8}, /* Data In 17 */
{0x6000, 0x23, 8}, /* Data In 18 */
{0x6000, 0x24, 8}, /* Data In 19 */
{0x6000, 0x25, 8}, /* Data In 20 */
{0x6000, 0x26, 8}, /* Data In 21 */
{0x6011, 0x01, 16}, /* Status */
{0x6010, 0x11, 8}, /* Data In 0 */
{0x6010, 0x12, 8}, /* Data In 1 */
{0x6010, 0x13, 8}, /* Data In 2 */
{0x6010, 0x14, 8}, /* Data In 3 */
{0x6010, 0x15, 8}, /* Data In 4 */
{0x6010, 0x16, 8}, /* Data In 5 */
{0x6010, 0x17, 8}, /* Data In 6 */
{0x6010, 0x18, 8}, /* Data In 7 */
{0x6010, 0x19, 8}, /* Data In 8 */
{0x6010, 0x1a, 8}, /* Data In 9 */
{0x6010, 0x1b, 8}, /* Data In 10 */
{0x6010, 0x1c, 8}, /* Data In 11 */
{0x6010, 0x1d, 8}, /* Data In 12 */
{0x6010, 0x1e, 8}, /* Data In 13 */
{0x6010, 0x1f, 8}, /* Data In 14 */
{0x6010, 0x20, 8}, /* Data In 15 */
{0x6010, 0x21, 8}, /* Data In 16 */
{0x6010, 0x22, 8}, /* Data In 17 */
{0x6010, 0x23, 8}, /* Data In 18 */
{0x6010, 0x24, 8}, /* Data In 19 */
{0x6010, 0x25, 8}, /* Data In 20 */
{0x6010, 0x26, 8}, /* Data In 21 */
};
ec_pdo_info_t slave_1_pdos[] = {
{0x1604, 23, slave_1_pdo_entries + 0}, /* COM RxPDO-Map Outputs Ch.1 */
{0x1605, 23, slave_1_pdo_entries + 23}, /* COM RxPDO-Map Outputs Ch.2 */
{0x1a04, 23, slave_1_pdo_entries + 46}, /* COM TxPDO-Map Inputs Ch.1 */
{0x1a05, 23, slave_1_pdo_entries + 69}, /* COM TxPDO-Map Inputs Ch.2 */
};
ec_sync_info_t slave_1_syncs[] = {
{0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE},
{1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE},
{2, EC_DIR_OUTPUT, 2, slave_1_pdos + 0, EC_WD_DISABLE},
{3, EC_DIR_INPUT, 2, slave_1_pdos + 2, EC_WD_DISABLE},
{0xff}
};
/****************************************************************************/
int serial_init(serial_device_t *ser, size_t max_tx, size_t max_rx)
{
ser->max_tx_data_size = max_tx;
ser->max_rx_data_size = max_rx;
ser->tx_data = NULL;
ser->tx_data_size = 0;
ser->state = SER_REQUEST_INIT;
ser->tx_request_toggle = 0;
ser->rx_accepted_toggle = 0;
ser->control = 0x0000;
if (max_tx > 0) {
ser->tx_data = kmalloc(max_tx, GFP_KERNEL);
if (ser->tx_data == NULL) {
return -ENOMEM;
}
}
return 0;
}
/****************************************************************************/
void serial_clear(serial_device_t *ser)
{
if (ser->tx_data) {
kfree(ser->tx_data);
}
}
/****************************************************************************/
void serial_run(serial_device_t *ser, uint16_t status, uint8_t *rx_data)
{
uint8_t tx_accepted_toggle, rx_request_toggle;
switch (ser->state) {
case SER_READY:
/* Send data */
tx_accepted_toggle = status & 0x0001;
if (tx_accepted_toggle != ser->tx_accepted_toggle) { // ready
ser->tx_data_size =
ectty_tx_data(tty, ser->tx_data, ser->max_tx_data_size);
if (ser->tx_data_size) {
printk(KERN_INFO PFX "Sending %u bytes.\n", ser->tx_data_size);
ser->tx_request_toggle = !ser->tx_request_toggle;
ser->tx_accepted_toggle = tx_accepted_toggle;
}
}
/* Receive data */
rx_request_toggle = status & 0x0002;
if (rx_request_toggle != ser->rx_request_toggle) {
uint8_t rx_data_size = status >> 8;
ser->rx_request_toggle = rx_request_toggle;
printk(KERN_INFO PFX "Received %u bytes.\n", rx_data_size);
ectty_rx_data(tty, rx_data, rx_data_size);
ser->rx_accepted_toggle = !ser->rx_accepted_toggle;
}
ser->control =
ser->tx_request_toggle |
ser->rx_accepted_toggle << 1 |
ser->tx_data_size << 8;
break;
case SER_REQUEST_INIT:
if (status & (1 << 2)) {
ser->control = 0x0000;
ser->state = SER_WAIT_FOR_INIT_RESPONSE;
} else {
ser->control = 1 << 2; // CW.2, request initialization
}
break;
case SER_WAIT_FOR_INIT_RESPONSE:
if (!(status & (1 << 2))) {
printk(KERN_INFO PFX "Init successful.\n");
ser->tx_accepted_toggle = 1;
ser->control = 0x0000;
ser->state = SER_READY;
}
break;
}
}
/*****************************************************************************/
void check_domain1_state(void)
@@ -388,9 +136,7 @@ void cyclic_task(unsigned long data)
check_master_state();
}
serial_run(ser, EC_READ_U16(domain1_pd + off_status), domain1_pd + off_rx);
EC_WRITE_U16(domain1_pd + off_ctrl, ser->control);
memcpy(domain1_pd + off_tx, ser->tx_data, 22);
run_serial_devices(domain1_pd);
// send process data
down(&master_sem);
@@ -432,31 +178,11 @@ int __init init_mini_module(void)
printk(KERN_INFO PFX "Starting...\n");
ser = kmalloc(sizeof(*ser), GFP_KERNEL);
if (!ser) {
printk(KERN_ERR PFX "Failed to allocate serial device object.\n");
ret = -ENOMEM;
goto out_return;
}
ret = serial_init(ser, 22, 22);
if (ret) {
printk(KERN_ERR PFX "Failed to init serial device object.\n");
goto out_free_serial;
}
tty = ectty_create();
if (IS_ERR(tty)) {
printk(KERN_ERR PFX "Failed to create tty.\n");
ret = PTR_ERR(tty);
goto out_serial;
}
master = ecrt_request_master(0);
if (!master) {
ret = -EBUSY;
printk(KERN_ERR PFX "Requesting master 0 failed.\n");
goto out_tty;
ret = -EBUSY;
goto out_return;
}
sema_init(&master_sem, 1);
@@ -470,30 +196,18 @@ int __init init_mini_module(void)
// Create configuration for bus coupler
sc = ecrt_master_slave_config(master, BusCouplerPos, Beckhoff_EK1100);
if (!sc)
return -1;
if (!(sc = ecrt_master_slave_config(
master, SerialPos, Beckhoff_EL6002))) {
printk(KERN_ERR PFX "Failed to get slave configuration.\n");
return -1;
if (!sc) {
printk(KERN_ERR PFX "Failed to create slave config.\n");
ret = -ENOMEM;
goto out_release_master;
}
printk("Configuring PDOs...\n");
if (ecrt_slave_config_pdos(sc, EC_END, slave_1_syncs)) {
printk(KERN_ERR PFX "Failed to configure PDOs.\n");
return -1;
}
if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
printk(KERN_ERR PFX "PDO entry registration failed!\n");
return -1;
}
create_serial_devices(master, domain1);
printk(KERN_INFO PFX "Activating master...\n");
if (ecrt_master_activate(master)) {
printk(KERN_ERR PFX "Failed to activate master!\n");
goto out_release_master;
goto out_free_serial;
}
// Get internal process data for domain
@@ -508,15 +222,11 @@ int __init init_mini_module(void)
printk(KERN_INFO PFX "Started.\n");
return 0;
out_free_serial:
free_serial_devices();
out_release_master:
printk(KERN_ERR PFX "Releasing master...\n");
ecrt_release_master(master);
out_tty:
ectty_free(tty);
out_serial:
serial_clear(ser);
out_free_serial:
kfree(ser);
out_return:
printk(KERN_ERR PFX "Failed to load. Aborting.\n");
return ret;
@@ -530,13 +240,11 @@ void __exit cleanup_mini_module(void)
del_timer_sync(&timer);
free_serial_devices();
printk(KERN_INFO PFX "Releasing master...\n");
ecrt_release_master(master);
ectty_free(tty);
serial_clear(ser);
kfree(ser);
printk(KERN_INFO PFX "Unloading.\n");
}
+2 -6
View File
@@ -208,8 +208,6 @@ typedef struct {
/*****************************************************************************/
#ifndef __KERNEL__
/** Master information.
*
* This is used as an output parameter of ecrt_master().
@@ -246,8 +244,6 @@ typedef struct {
char name[EC_MAX_STRING_LENGTH]; /**< Name of the slave. */
} ec_slave_info_t;
#endif // #ifndef __KERNEL__
/*****************************************************************************/
/** Domain working counter interpretation.
@@ -539,8 +535,6 @@ ec_slave_config_t *ecrt_master_slave_config(
uint32_t product_code /**< Expected product code. */
);
#ifndef __KERNEL__
/** Obtains master information.
*
* No memory is allocated on the heap in
@@ -573,6 +567,8 @@ int ecrt_master_get_slave(
information */
);
#ifndef __KERNEL__
/** Returns the proposed configuration of a slave's sync manager.
*
* Fills a given ec_sync_info_t structure with the attributes of a sync
+1 -1
View File
@@ -156,7 +156,7 @@ int ecrt_master_get_slave(ec_master_t *master, uint16_t slave_position,
slave_info->error_flag = data.error_flag;
slave_info->sync_count = data.sync_count;
slave_info->sdo_count = data.sdo_count;
strncpy(slave_info->name, data.name, EC_IOCTL_STRING_SIZE);
strncpy(slave_info->name, data.name, EC_MAX_STRING_LENGTH);
return 0;
}
+7 -12
View File
@@ -770,19 +770,14 @@ void ec_fsm_slave_scan_state_regalias(
}
if (datagram->working_counter != 1) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_scan_state_error;
EC_ERR("Failed to read reg alias of slave %u: ",
fsm->slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
EC_WARN("Failed to read reg alias of slave %u.\n",
fsm->slave->ring_position);
} else {
slave->sii.alias = EC_READ_U16(datagram->data);
if (slave->master->debug_level)
EC_DBG("Alias of slave %u is %u.\n",
slave->ring_position,slave->sii.alias);
}
slave->sii.alias = EC_READ_U16(datagram->data);
if (slave->master->debug_level)
EC_DBG("Alias of slave %u is %u.\n",
slave->ring_position,slave->sii.alias);
if (slave->sii.mailbox_protocols & EC_MBOX_COE) {
ec_fsm_slave_scan_enter_preop(fsm);
} else {
+5 -2
View File
@@ -51,8 +51,11 @@
/** SDO injection timeout in microseconds. */
#define EC_SDO_INJECTION_TIMEOUT 10000
/** time to send a byte in nanoseconds. */
#define EC_BYTE_TRANSMITION_TIME 80
/** Time to send a byte in nanoseconds.
*
* t_ns = 1 / (100 MBit/s / 8 bit/byte) = 80 ns/byte
*/
#define EC_BYTE_TRANSMISSION_TIME_NS 80
/** Number of state machine retries on datagram timeout. */
#define EC_FSM_RETRIES 3
+240 -119
View File
File diff suppressed because it is too large Load Diff
+19
View File
@@ -40,6 +40,7 @@
#include <linux/tty_flip.h>
#include <linux/termios.h>
#include <linux/timer.h>
#include <linux/version.h>
#include "../master/globals.h"
#include "../include/ectty.h"
@@ -379,7 +380,11 @@ static int ec_tty_write(
/*****************************************************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
static int ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
#else
static void ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
#endif
{
ec_tty_t *t = (ec_tty_t *) tty->driver_data;
@@ -390,8 +395,14 @@ static void ec_tty_put_char(struct tty_struct *tty, unsigned char ch)
if (ec_tty_tx_space(t)) {
t->tx_buffer[t->tx_write_idx] = ch;
t->tx_write_idx = (t->tx_write_idx + 1) % EC_TTY_TX_BUFFER_SIZE;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
return 1;
#endif
} else {
printk(KERN_WARNING PFX "%s(): Dropped a byte!\n", __func__);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
return 0;
#endif
}
}
@@ -506,11 +517,19 @@ static void ec_tty_hangup(struct tty_struct *tty)
/*****************************************************************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
static int ec_tty_break(struct tty_struct *tty, int break_state)
#else
static void ec_tty_break(struct tty_struct *tty, int break_state)
#endif
{
#if EC_TTY_DEBUG >= 2
printk(KERN_INFO PFX "%s(break_state = %i).\n", __func__, break_state);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
return -EIO; // not implemented
#endif
}
/*****************************************************************************/