[etherlab-users] [etherlab-dev] e1000e Limited to frame rate of 250/sec
Matthieu Bec
mbec at gmto.org
Thu Jul 4 00:02:40 CEST 2013
Hello Tom,
linux regular timers won't be any good:
> timer.expires += HZ / FREQUENCY;
HZ (CONFIG_HZ) is commonly <= 1000. Yours probably 250 and you just sleep 0
try linux "hrtimers" - there are plenty of resources to get some
examples, including the igh master itself (!)
Matthieu
On 7/3/13 2:25 PM, Thomas Bitsky Jr wrote:
> Hello, all.
>
>
>
> I’ve been working for a week on running the EtherCAT master 1.5.1 on an
> Intel Atom Desktop with two e1000e Intel cards. I need to get a frame
> rate of 2000/sec, but with both the generic driver and ec_e1000e driver,
> I can get no more than 250/sec. There are no errors or warning while
> running.
>
>
>
> The Operating System is Linux 2.6.33 with the RT PREMPT patch. I also
> tried running the generic driver on 3.2.46-rt67 with the same results.
>
>
>
> To get the network statistics, I type “ethercat master” at the command
> line. When the EtherCAT master starts up, it seems to burst at a
> massively fast frame rate, then quickly settle to 250/sec. Note that on
> three different machines, the results are the same, although I think
> they all have Intel NICs. When I start up the kernel module I wrote and
> the network goes into Operation, the speed results are unchanged.
>
>
>
> I know the e1000e driver can be slower than the 8139too driver, but
> 250/sec seems excessively slow and the fact that it’s ALWAYS 250
> regardless of driver or machine leads me to believe I’m doing something
> wrong. I’ve tried turning off the InterruptThrottleRate feature of the
> card (with both the e1000e and ec_e1000e driver), but with no effect.
>
>
>
> Below is the code that I’m using to run the test, which is based off the
> “mini” example. Can anyone tell me what I’m doing wrong, or if there is
> some feature in the e1000e driver that I need to disable?
>
>
>
> Thanks in advance,
>
> Tom
>
>
>
>
>
> #include<linux/version.h>
>
> #include<linux/module.h>
>
> #include<linux/timer.h>
>
> #include<linux/interrupt.h>
>
> #include<linux/err.h>
>
> #include<linux/semaphore.h>
>
> #include<linux/time.h>
>
>
>
> #ifLINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
>
> #include<linux/semaphore.h>
>
> #else
>
> #include<asm/semaphore.h>
>
> #endif
>
>
>
>
>
> #defineMY_PRIORITY (49) /* we use 49 as the PRREMPT_RT use 50
>
> as the priority of kernel tasklets
>
> and interrupt handler by default */
>
>
>
> #defineMAX_SAFE_STACK (8*1024) /* The maximum stack size which is
>
> guaranteed safe to access without
>
> faulting */
>
>
>
> // #define NSEC_PER_SEC (1000000000) /* The number of nsecs per sec. */
>
>
>
>
>
> #definePFX "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
>
> */
>
> #defineFREQUENCY 2000
>
> #defineINHIBIT_TIME 20
>
>
>
> // process data
>
> staticuint8_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.
>
> */
>
> #defineBeckhoff_EK1100 0x00000002, 0x044c2c52 // uint32_t
> vendor_id, uint32_t product_code
>
> #defineBeckhoff_EL1004 0x00000002, 0x03ec3052
>
> #defineBeckhoff_EL5101 0x00000002, 0x13ed3052
>
> #defineBeckhoff_EL2004 0x00000002, 0x07d43052
>
> #defineBeckhoff_EL6601 0x00000002, 0x19c93052
>
> #defineSMC_EX260SEC3 0x00000114, 0x01000003
>
> #defineBeckhoff_EP1809 0x00000002, 0x07114052
>
> #defineBeckhoff_EP2028 0x00000002, 0x07ec4052
>
> #defineBeckhoff_EP4174 0x00000002, 0x104e4052
>
>
>
>
>
> /*
>
> * Global variables for interacting with the EtherCAT master.
>
> */
>
> staticec_master_t *master = NULL;
>
> staticec_master_state_t master_state = {};
>
> structsemaphore master_sem;
>
>
>
>
>
>
>
> staticec_domain_t *domain = NULL;
>
> staticec_domain_state_t domain_state = {};
>
>
>
> // Timer
>
> staticstruct timer_list timer;
>
>
>
> structtimespec lastCycle_;
>
> structtimespec lastSend_;
>
> structtimespec lastRead_;
>
> structsched_param param;
>
> structtimespec interval; // = 50000; /* 50us*/
>
>
>
>
>
> structPdoOffset
>
> {
>
> unsigned int offset;
>
> unsigned int bitPosition;
>
> };
>
>
>
>
>
> staticstruct PdoOffset digInOffsets[255];
>
> staticstruct PdoOffset digOutOffsets[255];
>
> staticstruct PdoOffset analogInOffsets[255];
>
> staticstruct PdoOffset analogOutOffsets[255];
>
>
>
>
>
> conststatic 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
>
> staticunsigned 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);
>
>
>
>
>
> ktime_get_ts(&lastCycle_);
>
>
>
> // check process data state (optional)
>
> check_domain_state();
>
>
>
> if (counter)
>
> {
>
> counter--;
>
> }
>
> else
>
> {
>
> counter = FREQUENCY;
>
>
>
> // check for master state
>
> 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)
>
> {
>
>
>
> struct timespec delta = timespec_sub(lastCycle_, lastSend_);
>
> ec_master_t *m = NULL;
>
>
>
> printk(KERN_INFO PFX "send_callback");
>
>
>
> if (timespec_compare(&delta, &interval) > 0)
>
> {
>
>
>
> printk(KERN_INFO PFX "ecrt_master_send_ext");
>
> m = (ec_master_t *) cb_data;
>
> down(&master_sem);
>
> ecrt_master_send_ext(m);
>
> up(&master_sem);
>
>
>
> ktime_get_ts(&lastSend_);
>
> }
>
> }
>
>
>
> void
>
> receive_callback(void *cb_data)
>
> {
>
>
>
> struct timespec delta = timespec_sub(lastCycle_, lastRead_);
>
> ec_master_t *m = NULL;
>
>
>
> printk(KERN_INFO PFX "receive_callback");
>
>
>
> if (timespec_compare(&delta, &interval) > 0)
>
> {
>
>
>
> printk(KERN_INFO PFX "ecrt_master_receive");
>
> m = (ec_master_t *) cb_data;
>
>
>
> down(&master_sem);
>
> ecrt_master_receive(m);
>
> up(&master_sem);
>
>
>
> ktime_get_ts(&lastRead_);
>
> }
>
> }
>
>
>
> 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;
>
> }
>
>
>
>
>
> ktime_get_ts(&lastCycle_);
>
> ktime_get_ts(&lastSend_);
>
> ktime_get_ts(&lastRead_);
>
>
>
> // setup a comparison
>
> interval.tv_nsec = 50000;
>
>
>
>
>
> 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 <tbj at automateddesign.com>");
>
> MODULE_DESCRIPTION("Durability test environment");
>
>
>
> module_init(init_mini_module);
>
> module_exit(cleanup_mini_module);
>
>
>
>
>
> _______________________________________________
> etherlab-dev mailing list
> etherlab-dev at etherlab.org
> http://lists.etherlab.org/mailman/listinfo/etherlab-dev
>
--
Matthieu Bec GMTO Corp.
cell : +1 626 354 9367 P.O. Box 90933
phone: +1 626 204 0527 Pasadena, CA 91109-0933
More information about the Etherlab-users
mailing list