I'm not sure if this is a problem in my source code or a bug in the code relating to synchronization.
So, my problem has become this: I can successfully use EoE when the EtherCAT network is not operational. I can successfully use the EtherCAT network in Operation if the virtual EoE interface is down, but if I put the EtherCAT network into Operation and use the callbacks to handle EoE, the entire computer locks up. For reference: EtherCAT version: stable-1.5 System: Linux laptop14 2.6.32-42-generic-pae #95-Ubuntu SMP Wed Jul 25 16:13:09 UTC 2012 i686 GNU/Linux I am not using any real-time extensions. GCC: 4.4 The problem could very well be in my source code, although I've matched it closely to the EtherLAB examples. Once the virtual EoE interface goes up, the kernel log is filling with the errors I mentioned before: [ 2687.384659] [ 2687.384665] Pid: 0, comm: swapper Tainted: P W (2.6.32-42-generic-pae #95-Ubuntu) Latitude E6510 [ 2687.384672] EIP: 0060:[<c03ac336>] EFLAGS: 00000202 CPU: 3 [ 2687.384680] EIP is at acpi_idle_enter_bm+0x275/0x2a4 [ 2687.384684] EAX: c088eb4c EBX: 00000ee7 ECX: 00000000 EDX: 03036000 [ 2687.384689] ESI: 00000000 EDI: f6e404cc EBP: f74cbf78 ESP: f74cbf50 [ 2687.384694] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 2687.384698] CR0: 8005003b CR2: b94c0004 CR3: 00799000 CR4: 000006f0 [ 2687.384703] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 2687.384707] DR6: ffff0ff0 DR7: 00000400 [ 2687.384710] Call Trace: [ 2687.384719] [<c04ca54a>] cpuidle_idle_call+0x7a/0x100 [ 2687.384727] [<c01085a4>] cpu_idle+0x94/0xd0 [ 2687.384735] [<c05b31b7>] start_secondary+0xc4/0xc6 [ 2687.393250] BUG: scheduling while atomic: swapper/0/0x10000100 [ 2687.393256] Modules linked in: durability ec_generic ec_e1000 ec_8139too ec_master mii michael_mic arc4 binfmt_misc snd_hda_codec_idt The notable parts of my code are the callback: void send_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; down(&master_sem); ecrt_master_send_ext(m); up(&master_sem); } void receive_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; down(&master_sem); ecrt_master_receive(m); up(&master_sem); } If they are not in the program and activated by ecrt_master_callbacks, then there is no lock-up. Of course, EoE doesn't work. Once I put them in, the system hangs in about 30 seconds or less. I can't see any obvious reason for this: it looks like dead lock. I added traces and watched the kernel log viewer; I think it's locking up in ecrt_master_send_ext and not returning. In any case, I've been working on this for five days. If anyone can shine some light on what I'm doing wrong, or how I can fix this, I'd appreciate it. Thanks again! Tom On Wed, Aug 15, 2012 at 1:02 PM, Matthieu Bec <m...@gmto.org> wrote: > > # ifconfig eoe0s7 192.168.127.10 >> # ifconfig eoe0s7 up >> >> Is there any way to make this happen automatically on startup? In >> /etc/network, I created a file called ifcg-eoe0s7 and put in: >> >> IPADDRESS=192.168.127.10/24 <http://192.168.127.10/24> >> STARTMODE=auto >> >> But it must not be working because the virtual interface doesn't even >> have an IP Address until I give it one manually. >> > > on fedora: > > # ifup eoe0s7 > > best consult the ubuntu forums. > -- Thomas C. Bitsky Jr. Lead Developer and Application Engineer ADC | automateddesign.com P: 630-783-1150 F: 630-783-1159 M: 630-632-6679
/* Master 0, Slave 1, "EL1004" * Vendor ID: 0x00000002 * Product code: 0x03ec3052 * Revision number: 0x00100000 */ ec_pdo_entry_info_t slave_1_pdo_entries[] = { {0x6000, 0x01, 1}, /* Input */ {0x6010, 0x01, 1}, /* Input */ {0x6020, 0x01, 1}, /* Input */ {0x6030, 0x01, 1}, /* Input */ }; ec_pdo_info_t slave_1_pdos[] = { {0x1a00, 1, slave_1_pdo_entries + 0}, /* Channel 1 */ {0x1a01, 1, slave_1_pdo_entries + 1}, /* Channel 2 */ {0x1a02, 1, slave_1_pdo_entries + 2}, /* Channel 3 */ {0x1a03, 1, slave_1_pdo_entries + 3}, /* Channel 4 */ }; ec_sync_info_t slave_1_syncs[] = { {0, EC_DIR_INPUT, 4, slave_1_pdos + 0, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave 2, "EL1004" * Vendor ID: 0x00000002 * Product code: 0x03ec3052 * Revision number: 0x00100000 */ ec_pdo_entry_info_t slave_2_pdo_entries[] = { {0x6000, 0x01, 1}, /* Input */ {0x6010, 0x01, 1}, /* Input */ {0x6020, 0x01, 1}, /* Input */ {0x6030, 0x01, 1}, /* Input */ }; ec_pdo_info_t slave_2_pdos[] = { {0x1a00, 1, slave_2_pdo_entries + 0}, /* Channel 1 */ {0x1a01, 1, slave_2_pdo_entries + 1}, /* Channel 2 */ {0x1a02, 1, slave_2_pdo_entries + 2}, /* Channel 3 */ {0x1a03, 1, slave_2_pdo_entries + 3}, /* Channel 4 */ }; ec_sync_info_t slave_2_syncs[] = { {0, EC_DIR_INPUT, 4, slave_2_pdos + 0, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave 3, "EL1004" * Vendor ID: 0x00000002 * Product code: 0x03ec3052 * Revision number: 0x00100000 */ ec_pdo_entry_info_t slave_3_pdo_entries[] = { {0x6000, 0x01, 1}, /* Input */ {0x6010, 0x01, 1}, /* Input */ {0x6020, 0x01, 1}, /* Input */ {0x6030, 0x01, 1}, /* Input */ }; ec_pdo_info_t slave_3_pdos[] = { {0x1a00, 1, slave_3_pdo_entries + 0}, /* Channel 1 */ {0x1a01, 1, slave_3_pdo_entries + 1}, /* Channel 2 */ {0x1a02, 1, slave_3_pdo_entries + 2}, /* Channel 3 */ {0x1a03, 1, slave_3_pdo_entries + 3}, /* Channel 4 */ }; ec_sync_info_t slave_3_syncs[] = { {0, EC_DIR_INPUT, 4, slave_3_pdos + 0, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave 4, "EL5101" * Vendor ID: 0x00000002 * Product code: 0x13ed3052 * Revision number: 0x03fc0000 */ ec_pdo_entry_info_t slave_4_pdo_entries[] = { {0x7010, 0x01, 1}, /* Enable latch C */ {0x7010, 0x02, 1}, /* Enable latch extern on pos */ {0x7010, 0x03, 1}, /* Set counter */ {0x7010, 0x04, 1}, /* Enable latch extern on neg */ {0x0000, 0x00, 4}, /* Gap */ {0x0000, 0x00, 8}, /* Gap */ {0x7010, 0x11, 16}, /* Set counter value */ {0x6010, 0x01, 1}, /* Latch C valid */ {0x6010, 0x02, 1}, /* Latch extern valid */ {0x6010, 0x03, 1}, /* Set counter done */ {0x6010, 0x04, 1}, /* Counter underflow */ {0x6010, 0x05, 1}, /* Counter overflow */ {0x6010, 0x06, 1}, /* Status of input status */ {0x6010, 0x07, 1}, /* Open circuit */ {0x6010, 0x08, 1}, /* Extrapolation stall */ {0x6010, 0x09, 1}, /* Status of input A */ {0x6010, 0x0a, 1}, /* Status of input B */ {0x6010, 0x0b, 1}, /* Status of input C */ {0x6010, 0x0c, 1}, /* Status of input gate */ {0x6010, 0x0d, 1}, /* Status of extern latch */ {0x1c32, 0x20, 1}, /* Sync error */ {0x1803, 0x07, 1}, /* TxPDO State */ {0x1803, 0x09, 1}, /* TxPDO Toggle */ {0x6010, 0x11, 16}, /* Counter value */ {0x6010, 0x12, 16}, /* Latch value */ }; ec_pdo_info_t slave_4_pdos[] = { {0x1602, 7, slave_4_pdo_entries + 0}, /* ENC RxPDO-Map Control compact */ {0x1a03, 18, slave_4_pdo_entries + 7}, /* ENC TxPDO-Map Status compact */ }; ec_sync_info_t slave_4_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 1, slave_4_pdos + 0, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 1, slave_4_pdos + 1, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave 5, "EL2004" * Vendor ID: 0x00000002 * Product code: 0x07d43052 * Revision number: 0x00100000 */ ec_pdo_entry_info_t slave_5_pdo_entries[] = { {0x7000, 0x01, 1}, /* Output */ {0x7010, 0x01, 1}, /* Output */ {0x7020, 0x01, 1}, /* Output */ {0x7030, 0x01, 1}, /* Output */ }; ec_pdo_info_t slave_5_pdos[] = { {0x1600, 1, slave_5_pdo_entries + 0}, /* Channel 1 */ {0x1601, 1, slave_5_pdo_entries + 1}, /* Channel 2 */ {0x1602, 1, slave_5_pdo_entries + 2}, /* Channel 3 */ {0x1603, 1, slave_5_pdo_entries + 3}, /* Channel 4 */ }; ec_sync_info_t slave_5_syncs[] = { {0, EC_DIR_OUTPUT, 4, slave_5_pdos + 0, EC_WD_ENABLE}, {0xff} }; /* Master 0, Slave 6, "EL2004" * Vendor ID: 0x00000002 * Product code: 0x07d43052 * Revision number: 0x00100000 */ ec_pdo_entry_info_t slave_6_pdo_entries[] = { {0x7000, 0x01, 1}, /* Output */ {0x7010, 0x01, 1}, /* Output */ {0x7020, 0x01, 1}, /* Output */ {0x7030, 0x01, 1}, /* Output */ }; ec_pdo_info_t slave_6_pdos[] = { {0x1600, 1, slave_6_pdo_entries + 0}, /* Channel 1 */ {0x1601, 1, slave_6_pdo_entries + 1}, /* Channel 2 */ {0x1602, 1, slave_6_pdo_entries + 2}, /* Channel 3 */ {0x1603, 1, slave_6_pdo_entries + 3}, /* Channel 4 */ }; ec_sync_info_t slave_6_syncs[] = { {0, EC_DIR_OUTPUT, 4, slave_6_pdos + 0, EC_WD_ENABLE}, {0xff} }; /* Master 0, Slave 7, "EL6601" * Vendor ID: 0x00000002 * Product code: 0x19c93052 * Revision number: 0x00120000 */ ec_sync_info_t slave_7_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave 8, "EX260-SEC3" * Vendor ID: 0x00000114 * Product code: 0x01000003 * Revision number: 0x00010002 */ ec_pdo_entry_info_t slave_8_pdo_entries[] = { {0x3101, 0x01, 8}, /* Output */ {0x3101, 0x02, 8}, /* Output */ }; ec_pdo_info_t slave_8_pdos[] = { {0x1600, 1, slave_8_pdo_entries + 0}, /* Byte 0 */ {0x1601, 1, slave_8_pdo_entries + 1}, /* Byte 1 */ }; ec_sync_info_t slave_8_syncs[] = { {0, EC_DIR_OUTPUT, 1, slave_8_pdos + 0, EC_WD_ENABLE}, {1, EC_DIR_OUTPUT, 1, slave_8_pdos + 1, EC_WD_ENABLE}, {0xff} }; /* Master 0, Slave 9, "EP1809-0022" * Vendor ID: 0x00000002 * Product code: 0x07114052 * Revision number: 0x00110016 */ ec_pdo_entry_info_t slave_9_pdo_entries[] = { {0x6000, 0x01, 1}, /* Input */ {0x6010, 0x01, 1}, /* Input */ {0x6020, 0x01, 1}, /* Input */ {0x6030, 0x01, 1}, /* Input */ {0x6040, 0x01, 1}, /* Input */ {0x6050, 0x01, 1}, /* Input */ {0x6060, 0x01, 1}, /* Input */ {0x6070, 0x01, 1}, /* Input */ {0x6080, 0x01, 1}, /* Input */ {0x6090, 0x01, 1}, /* Input */ {0x60a0, 0x01, 1}, /* Input */ {0x60b0, 0x01, 1}, /* Input */ {0x60c0, 0x01, 1}, /* Input */ {0x60d0, 0x01, 1}, /* Input */ {0x60e0, 0x01, 1}, /* Input */ {0x60f0, 0x01, 1}, /* Input */ }; ec_pdo_info_t slave_9_pdos[] = { {0x1a00, 1, slave_9_pdo_entries + 0}, /* Channel 1 */ {0x1a01, 1, slave_9_pdo_entries + 1}, /* Channel 2 */ {0x1a02, 1, slave_9_pdo_entries + 2}, /* Channel 3 */ {0x1a03, 1, slave_9_pdo_entries + 3}, /* Channel 4 */ {0x1a04, 1, slave_9_pdo_entries + 4}, /* Channel 5 */ {0x1a05, 1, slave_9_pdo_entries + 5}, /* Channel 6 */ {0x1a06, 1, slave_9_pdo_entries + 6}, /* Channel 7 */ {0x1a07, 1, slave_9_pdo_entries + 7}, /* Channel 8 */ {0x1a08, 1, slave_9_pdo_entries + 8}, /* Channel 9 */ {0x1a09, 1, slave_9_pdo_entries + 9}, /* Channel 10 */ {0x1a0a, 1, slave_9_pdo_entries + 10}, /* Channel 11 */ {0x1a0b, 1, slave_9_pdo_entries + 11}, /* Channel 12 */ {0x1a0c, 1, slave_9_pdo_entries + 12}, /* Channel 13 */ {0x1a0d, 1, slave_9_pdo_entries + 13}, /* Channel 14 */ {0x1a0e, 1, slave_9_pdo_entries + 14}, /* Channel 15 */ {0x1a0f, 1, slave_9_pdo_entries + 15}, /* Channel 16 */ }; ec_sync_info_t slave_9_syncs[] = { {0, EC_DIR_INPUT, 16, slave_9_pdos + 0, EC_WD_DISABLE}, {0xff} }; /* Master 0, Slave a, "EP2028-0002" * Vendor ID: 0x00000002 * Product code: 0x07ec4052 * Revision number: 0x00110002 */ ec_pdo_entry_info_t slave_10_pdo_entries[] = { {0x7000, 0x01, 1}, /* Output */ {0x7010, 0x01, 1}, /* Output */ {0x7020, 0x01, 1}, /* Output */ {0x7030, 0x01, 1}, /* Output */ {0x7040, 0x01, 1}, /* Output */ {0x7050, 0x01, 1}, /* Output */ {0x7060, 0x01, 1}, /* Output */ {0x7070, 0x01, 1}, /* Output */ }; ec_pdo_info_t slave_10_pdos[] = { {0x1600, 1, slave_10_pdo_entries + 0}, /* Channel 1 */ {0x1601, 1, slave_10_pdo_entries + 1}, /* Channel 2 */ {0x1602, 1, slave_10_pdo_entries + 2}, /* Channel 3 */ {0x1603, 1, slave_10_pdo_entries + 3}, /* Channel 4 */ {0x1604, 1, slave_10_pdo_entries + 4}, /* Channel 5 */ {0x1605, 1, slave_10_pdo_entries + 5}, /* Channel 6 */ {0x1606, 1, slave_10_pdo_entries + 6}, /* Channel 7 */ {0x1607, 1, slave_10_pdo_entries + 7}, /* Channel 8 */ }; ec_sync_info_t slave_10_syncs[] = { {0, EC_DIR_OUTPUT, 8, slave_10_pdos + 0, EC_WD_ENABLE}, {0xff} }; /* Master 0, Slave b, "EP4174-0002" * Vendor ID: 0x00000002 * Product code: 0x104e4052 * Revision number: 0x00100002 */ ec_pdo_entry_info_t slave_11_pdo_entries[] = { {0x7000, 0x11, 16}, /* Analog output */ {0x7010, 0x11, 16}, /* Analog output */ {0x7020, 0x11, 16}, /* Analog output */ {0x7030, 0x11, 16}, /* Analog output */ }; ec_pdo_info_t slave_11_pdos[] = { {0x1600, 1, slave_11_pdo_entries + 0}, /* AO RxPDO-Map Ch.1 */ {0x1601, 1, slave_11_pdo_entries + 1}, /* AO RxPDO-Map Ch.2 */ {0x1602, 1, slave_11_pdo_entries + 2}, /* AO RxPDO-Map Ch.3 */ {0x1603, 1, slave_11_pdo_entries + 3}, /* AO RxPDO-Map Ch.4 */ }; ec_sync_info_t slave_11_syncs[] = { {0, EC_DIR_OUTPUT, 0, NULL, EC_WD_DISABLE}, {1, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {2, EC_DIR_OUTPUT, 4, slave_11_pdos + 0, EC_WD_DISABLE}, {3, EC_DIR_INPUT, 0, NULL, EC_WD_DISABLE}, {0xff} };
/* * durability.c * Thomas C. Bitsky Jr. * 2012 08 12 * * A test kernel module using EtherLab EtherCAT master. * * NOTE: * - You need to copy Module.symvers from the ethercat directory into * the src dictory of this project. * - Building this project requires using "Kbuild," which means a different format * for the Makefile. * * */ #include <linux/version.h> #include <linux/module.h> #include <linux/timer.h> #include <linux/interrupt.h> #include <linux/err.h> #include <linux/semaphore.h> #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) #include <linux/semaphore.h> #else #include <asm/semaphore.h> #endif #define PFX "durability.c: " #include "/home/tbj/srcroot/ethercat/include/ecrt.h" // EtherCAT realtime interface /* * Import the bus topology generated by EtherLAB */ #include "2369topology.h" /* * Application Parameters */ #define FREQUENCY 100 // process data static uint8_t *processData = NULL; /* * macros for any of the hardware on the network. * Use # ethercat slaves to see this info * You can also use # ethercat cstruct > topology.h to generate a slave header. * The vendor id and product code for each slave will be listed in comments in that file. */ #define Beckhoff_EK1100 0x00000002, 0x044c2c52 // uint32_t vendor_id, uint32_t product_code #define Beckhoff_EL1004 0x00000002, 0x03ec3052 #define Beckhoff_EL5101 0x00000002, 0x13ed3052 #define Beckhoff_EL2004 0x00000002, 0x07d43052 #define Beckhoff_EL6601 0x00000002, 0x19c93052 #define SMC_EX260SEC3 0x00000114, 0x01000003 #define Beckhoff_EP1809 0x00000002, 0x07114052 #define Beckhoff_EP2028 0x00000002, 0x07ec4052 #define Beckhoff_EP4174 0x00000002, 0x104e4052 /* * Global variables for interacting with the EtherCAT master. */ static ec_master_t *master = NULL; static ec_master_state_t master_state = {}; struct semaphore master_sem; static ec_domain_t *domain = NULL; static ec_domain_state_t domain_state = {}; // Timer static struct timer_list timer; struct PdoOffset { unsigned int offset; unsigned int bitPosition; }; static struct PdoOffset digInOffsets[255]; static struct PdoOffset digOutOffsets[255]; static struct PdoOffset analogInOffsets[255]; static struct PdoOffset analogOutOffsets[255]; const static ec_pdo_entry_reg_t domain_regs[] = { {0,1, Beckhoff_EL1004, 0x6000, 1, &digInOffsets[0].offset, &digInOffsets[0].bitPosition}, {0,1, Beckhoff_EL1004, 0x6010, 1, &digInOffsets[1].offset, &digInOffsets[1].bitPosition}, {0,1, Beckhoff_EL1004, 0x6020, 1, &digInOffsets[2].offset, &digInOffsets[2].bitPosition}, {0,1, Beckhoff_EL1004, 0x6030, 1, &digInOffsets[3].offset, &digInOffsets[3].bitPosition}, {0,2, Beckhoff_EL1004, 0x6000, 1, &digInOffsets[4].offset, &digInOffsets[4].bitPosition}, {0,2, Beckhoff_EL1004, 0x6010, 1, &digInOffsets[5].offset, &digInOffsets[5].bitPosition}, {0,2, Beckhoff_EL1004, 0x6020, 1, &digInOffsets[6].offset, &digInOffsets[6].bitPosition}, {0,2, Beckhoff_EL1004, 0x6030, 1, &digInOffsets[7].offset, &digInOffsets[7].bitPosition}, {0,3, Beckhoff_EL1004, 0x6000, 1, &digInOffsets[8].offset, &digInOffsets[8].bitPosition}, {0,3, Beckhoff_EL1004, 0x6010, 1, &digInOffsets[9].offset, &digInOffsets[9].bitPosition}, {0,3, Beckhoff_EL1004, 0x6020, 1, &digInOffsets[10].offset, &digInOffsets[10].bitPosition}, {0,3, Beckhoff_EL1004, 0x6030, 1, &digInOffsets[11].offset, &digInOffsets[11].bitPosition}, {0,9, Beckhoff_EP1809, 0x6000, 1, &digInOffsets[12].offset, &digInOffsets[12].bitPosition}, {0,9, Beckhoff_EP1809, 0x6010, 1, &digInOffsets[13].offset, &digInOffsets[13].bitPosition}, {0,9, Beckhoff_EP1809, 0x6020, 1, &digInOffsets[14].offset, &digInOffsets[14].bitPosition}, {0,9, Beckhoff_EP1809, 0x6030, 1, &digInOffsets[15].offset, &digInOffsets[15].bitPosition}, {0,9, Beckhoff_EP1809, 0x6040, 1, &digInOffsets[16].offset, &digInOffsets[16].bitPosition}, {0,9, Beckhoff_EP1809, 0x6050, 1, &digInOffsets[17].offset, &digInOffsets[17].bitPosition}, {0,9, Beckhoff_EP1809, 0x6060, 1, &digInOffsets[18].offset, &digInOffsets[18].bitPosition}, {0,9, Beckhoff_EP1809, 0x6070, 1, &digInOffsets[19].offset, &digInOffsets[19].bitPosition}, {0,9, Beckhoff_EP1809, 0x6080, 1, &digInOffsets[20].offset, &digInOffsets[20].bitPosition}, {0,9, Beckhoff_EP1809, 0x6090, 1, &digInOffsets[21].offset, &digInOffsets[21].bitPosition}, {0,9, Beckhoff_EP1809, 0x60A0, 1, &digInOffsets[22].offset, &digInOffsets[22].bitPosition}, {0,9, Beckhoff_EP1809, 0x60B0, 1, &digInOffsets[23].offset, &digInOffsets[23].bitPosition}, {0,9, Beckhoff_EP1809, 0x60C0, 1, &digInOffsets[24].offset, &digInOffsets[24].bitPosition}, {0,9, Beckhoff_EP1809, 0x60D0, 1, &digInOffsets[25].offset, &digInOffsets[25].bitPosition}, {0,9, Beckhoff_EP1809, 0x60E0, 1, &digInOffsets[26].offset, &digInOffsets[26].bitPosition}, {0,9, Beckhoff_EP1809, 0x60F0, 1, &digInOffsets[27].offset, &digInOffsets[27].bitPosition}, {0,4, Beckhoff_EL5101, 0x6010, 0x11, &analogInOffsets[0].offset, &analogInOffsets[0].bitPosition}, {0,5, Beckhoff_EL2004, 0x7000, 1, &digOutOffsets[0].offset, &digOutOffsets[0].bitPosition}, {0,5, Beckhoff_EL2004, 0x7010, 1, &digOutOffsets[1].offset, &digOutOffsets[1].bitPosition}, {0,5, Beckhoff_EL2004, 0x7020, 1, &digOutOffsets[2].offset, &digOutOffsets[2].bitPosition}, {0,5, Beckhoff_EL2004, 0x7030, 1, &digOutOffsets[3].offset, &digOutOffsets[3].bitPosition}, {0,6, Beckhoff_EL2004, 0x7000, 1, &digOutOffsets[4].offset, &digOutOffsets[4].bitPosition}, {0,6, Beckhoff_EL2004, 0x7010, 1, &digOutOffsets[5].offset, &digOutOffsets[5].bitPosition}, {0,6, Beckhoff_EL2004, 0x7020, 1, &digOutOffsets[6].offset, &digOutOffsets[6].bitPosition}, {0,6, Beckhoff_EL2004, 0x7030, 1, &digOutOffsets[7].offset, &digOutOffsets[7].bitPosition}, {0,10, Beckhoff_EP2028, 0x7000, 1, &digOutOffsets[8].offset, &digOutOffsets[8].bitPosition}, {0,10, Beckhoff_EP2028, 0x7010, 1, &digOutOffsets[9].offset, &digOutOffsets[9].bitPosition}, {0,10, Beckhoff_EP2028, 0x7020, 1, &digOutOffsets[10].offset, &digOutOffsets[10].bitPosition}, {0,10, Beckhoff_EP2028, 0x7030, 1, &digOutOffsets[11].offset, &digOutOffsets[11].bitPosition}, {0,10, Beckhoff_EP2028, 0x7040, 1, &digOutOffsets[12].offset, &digOutOffsets[12].bitPosition}, {0,10, Beckhoff_EP2028, 0x7050, 1, &digOutOffsets[13].offset, &digOutOffsets[13].bitPosition}, {0,10, Beckhoff_EP2028, 0x7060, 1, &digOutOffsets[14].offset, &digOutOffsets[14].bitPosition}, {0,10, Beckhoff_EP2028, 0x7070, 1, &digOutOffsets[15].offset, &digOutOffsets[15].bitPosition}, // Encoder card registers for setting the counter {0,4, Beckhoff_EL5101, 0x7010, 0x03, &analogOutOffsets[0].offset, &analogOutOffsets[0].bitPosition}, {0,4, Beckhoff_EL5101, 0x7010, 0x11, &analogOutOffsets[1].offset, &analogOutOffsets[1].bitPosition}, // The bits of two bytes covers the valves on the block {0,8, SMC_EX260SEC3, 0x3101, 0x01, &analogOutOffsets[2].offset, &analogOutOffsets[2].bitPosition}, {0,8, SMC_EX260SEC3, 0x3101, 0x02, &analogOutOffsets[3].offset, &analogOutOffsets[3].bitPosition}, {0,11, Beckhoff_EP4174, 0x7000, 0x11, &analogOutOffsets[4].offset, &analogOutOffsets[4].bitPosition}, {0,11, Beckhoff_EP4174, 0x7010, 0x11, &analogOutOffsets[5].offset, &analogOutOffsets[5].bitPosition}, {0,11, Beckhoff_EP4174, 0x7020, 0x11, &analogOutOffsets[6].offset, &analogOutOffsets[6].bitPosition}, {0,11, Beckhoff_EP4174, 0x7030, 0x11, &analogOutOffsets[7].offset, &analogOutOffsets[7].bitPosition}, {} }; // process variables static unsigned int counter = 0; /* * Check and report on the state of the domain. */ void check_domain_state(void) { ec_domain_state_t ds; down(&master_sem); ecrt_domain_state(domain, &ds); up(&master_sem); if (ds.working_counter != domain_state.working_counter) printk(KERN_INFO PFX "Domain: WC %u.\n", ds.working_counter); if (ds.wc_state != domain_state.wc_state) printk(KERN_INFO PFX "Domain: State %u.\n", ds.wc_state); domain_state = ds; } /* * Check and report on the state of the master service. */ void check_master_state(void) { ec_master_state_t ms; down(&master_sem); ecrt_master_state(master, &ms); up(&master_sem); if (ms.slaves_responding != master_state.slaves_responding) printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding); if (ms.al_states != master_state.al_states) printk(KERN_INFO PFX "AL states: 0x%02X.\n", ms.al_states); if (ms.link_up != master_state.link_up) printk(KERN_INFO PFX "Link is %s.\n", ms.link_up ? "up" : "down"); master_state = ms; } void check_slave_config_states(void) { /* ec_slave_config_state_t s; ecrt_slave_config_state(sc_ana_in, &s); if (s.al_state != sc_ana_in_state.al_state) printk(KERN_ERR PFX "AnaIn: State 0x%02X.\n", s.al_state); if (s.online != sc_ana_in_state.online) printk(KERN_ERR PFX "AnaIn: %s.\n", s.online ? "online" : "offline"); if (s.operational != sc_ana_in_state.operational) printk(KERN_ERR PFX "AnaIn: %soperational.\n", s.operational ? "" : "Not "); */ } void cyclic_task(unsigned long data) { // receive process data down(&master_sem); ecrt_master_receive(master); ecrt_domain_process(domain); up(&master_sem); // check process data state (optional) check_domain_state(); if (counter) { counter--; } else { // do this at 1 Hz counter = FREQUENCY; // check for master state (optional) check_master_state(); } // send process data down(&master_sem); ecrt_domain_queue(domain); ecrt_master_send(master); up(&master_sem); // restart timer timer.expires += HZ / FREQUENCY; add_timer(&timer); } void send_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; down(&master_sem); ecrt_master_send_ext(m); up(&master_sem); } void receive_callback(void *cb_data) { ec_master_t *m = (ec_master_t *) cb_data; down(&master_sem); ecrt_master_receive(m); up(&master_sem); } int __init init_mini_module(void) { ec_slave_config_t *sc; int ret = -1; /* * Requests an EtherCAT master for realtime operation. * Before an application can access an EtherCAT master, it has to reserve one for exclusive use. * In userspace, this is a convenience function for ecrt_open_master() and ecrt_master_reserve(). * This function has to be the first function an application has to call to use EtherCAT. * The function takes the index of the master as its argument. * The first master has index 0, the n-th master has index n - 1. * The number of masters has to be specified when loading the master module. */ master = ecrt_request_master(0); if (!master) { printk(KERN_INFO PFX "Could not connect to the master service. Exiting.\n\n"); ret = -EBUSY; goto out_return; } sema_init(&master_sem, 1); ecrt_master_callbacks( master, // pointer to master send_callback, // fp to send ext callback receive_callback, // fp to receive callback master); // parameter to callback /* * Creates a new process data domain. * For process data exchange, at least one process data domain is needed. * This method creates a new process data domain and returns a pointer to the new domain object. * This object can be used for registering PDOs and exchanging them in cyclic operation. */ domain = ecrt_master_create_domain(master); if (!domain) { printk(KERN_INFO PFX "Could not create a domain on the master. Exiting.\n\n"); goto out_release_master; } /* * Register the slaves on the master * Doing the method this way means the registration will work whether or * not the computer is connected to the network. */ // Main Rack, Slot 1 if (!(sc = ecrt_master_slave_config( master, 0,1, // Bus position Beckhoff_EL1004 // Slave type ))) { printk(KERN_INFO PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_1_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 2 if (!(sc = ecrt_master_slave_config( master, 0,2, // Bus position Beckhoff_EL1004 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_2_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 3 if (!(sc = ecrt_master_slave_config( master, 0,3, // Bus position Beckhoff_EL1004 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_3_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 4 if (!(sc = ecrt_master_slave_config( master, 0,4, // Bus position Beckhoff_EL5101 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_4_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 5 if (!(sc = ecrt_master_slave_config( master, 0,5, // Bus position Beckhoff_EL2004 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_5_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 6 if (!(sc = ecrt_master_slave_config( master, 0,6, // Bus position Beckhoff_EL2004 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_6_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Main Rack, Slot 7 if (!(sc = ecrt_master_slave_config( master, 0,7, // Bus position Beckhoff_EL6601 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_7_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // SMC EtherCAT Manifold, Slave 8, "EX260-SEC3" if (!(sc = ecrt_master_slave_config( master, 0,8, // Bus position SMC_EX260SEC3 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_8_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // EP1809 Input Fieldbox, Slave 9, if (!(sc = ecrt_master_slave_config( master, 0,9, // Bus position Beckhoff_EP1809 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_9_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // EP2028 Input Fieldbox, Slave 10, if (!(sc = ecrt_master_slave_config( master, 0,10, // Bus position Beckhoff_EP2028 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_10_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // EP4174 Input Fieldbox, Slave 11, if (!(sc = ecrt_master_slave_config( master, 0,11, // Bus position Beckhoff_EP4174 // Slave type ))) { printk(KERN_ERR PFX "Failed to get slave configuration.\n"); ret = -ENOMEM; goto out_release_master; } if (ecrt_slave_config_pdos(sc, EC_END, slave_11_syncs)) { printk(KERN_ERR PFX "Failed to configure PDOs.\n"); ret = -ENOMEM; goto out_release_master; } // Create configuration for bus coupler sc = ecrt_master_slave_config(master, 0,0, Beckhoff_EK1100); if (!sc) { ret = -ENOMEM; goto out_release_master; } /* * Registers a bunch of PDO entries for a domain. */ printk(KERN_ERR PFX "\nAttempting to register PDOs on domain...\n"); if (ecrt_domain_reg_pdo_entry_list(domain, domain_regs)) { printk(KERN_ERR PFX "PDO entry registration failed!\n"); ret = -EBUSY; goto out_release_master; } /* * Finishes the configuration phase and prepares for cyclic operation. * This function tells the master that the configuration phase is finished and the realtime operation will begin. * The function allocates internal memory for the domains and calculates the logical FMMU addresses for domain members. * It tells the master state machine that the bus configuration is now to be applied */ if (ecrt_master_activate(master)) { ret = -EBUSY; goto out_release_master;; } /* * Returns the domain's process data. */ if (!(processData = ecrt_domain_data(domain))) { ret = -EBUSY; goto out_release_master; } printk(KERN_INFO PFX "Starting cyclic thread.\n"); init_timer(&timer); timer.function = cyclic_task; timer.expires = jiffies + 10; add_timer(&timer); printk(KERN_INFO PFX "Durability Service Started.\n"); return 0; out_release_master: printk(KERN_ERR PFX "Releasing master...\n"); ecrt_release_master(master); out_return: printk(KERN_ERR PFX "Failed to load. Aborting.\n"); return ret; } // main void __exit cleanup_mini_module(void) { printk(KERN_INFO PFX "Stopping...\n"); del_timer_sync(&timer); printk(KERN_INFO PFX "Releasing master...\n"); ecrt_release_master(master); printk(KERN_INFO PFX "Unloading.\n"); } /*****************************************************************************/ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Thomas Bitsky <t...@automateddesign.com>"); MODULE_DESCRIPTION("Durability test environment"); module_init(init_mini_module); module_exit(cleanup_mini_module);
Makefile
Description: Binary data
_______________________________________________ etherlab-users mailing list etherlab-users@etherlab.org http://lists.etherlab.org/mailman/listinfo/etherlab-users