[etherlab-users] [etherlab-dev] Using EtherCAT EoE and Build Errors
Thomas Bitsky, Jr.
tbj at automateddesign.com
Fri Aug 17 15:14:33 CEST 2012
For reference, I was able to get EoE working without hang-up by installing
rt preempt and rebuilding the EtherCAT Master. Many thanks to Matthieu and
Frank for all you help and tips.
Attached is the C code I used, if anyone is interested (or a newcomer
reading this in the archives). I'll copy and paste the relevant parts
below. Almost all of it is pulled from an example somewhere.
#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>
#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 2000
...
...
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);
}
struct timespec lastCycle_;
struct timespec lastSend_;
struct timespec lastRead_;
struct timespec interval;
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_);
...
...
// 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;
if (timespec_compare(&delta, &interval) > 0)
{
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;
if (timespec_compare(&delta, &interval) > 0)
{
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;
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
*/
...
...
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
On Wed, Aug 15, 2012 at 8:47 PM, Matthieu Bec <mbec at gmto.org> wrote:
> indeed, though the FAQ says
>
> >Supports any realtime environment through independent architecture.
> > RTAI, Xenomai, RT-Preempt, etc.
> > Operation possible without any realtime extension at all.
>
> I am not sure about the second statement or how to make it work. Always
> had better luck with real-time extensions and never looked back. RT-Preempt
> is easy to setup and kind of transparent. vanilla kernel was giving me (if
> I recall correctly) similar semaphores vs. spinlocks issue as you pointed
> earlier
>
> Matthieu
>
>
> On 08/15/12 17:53, Thomas Bitsky, Jr. wrote:
>
>> 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 <mbec at gmto.org
>> <mailto:mbec at 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>
>> <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 <http://automateddesign.com>
>> P: 630-783-1150 <tel:630-783-1150> F: 630-783-1159 <tel:630-783-1159> M:
>> 630-632-6679 <tel:630-632-6679>
>>
>>
>>
>> ______________________________**_________________
>> etherlab-dev mailing list
>> etherlab-dev at etherlab.org
>> http://lists.etherlab.org/**mailman/listinfo/etherlab-dev<http://lists.etherlab.org/mailman/listinfo/etherlab-dev>
>>
>> i
>
> --
> Matthieu Bec GMTO Corp.
> cell: +1 626 354 9367 P.O. Box 90933
> phone: +1 626 204 0527 Pasadena, CA 91109-0933
>
>
--
Thomas C. Bitsky Jr.
Lead Developer and Application Engineer
ADC | automateddesign.com
P: 630-783-1150 F: 630-783-1159 M: 630-632-6679
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20120817/44f1c0fc/attachment-0005.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 2369topology.h
Type: text/x-chdr
Size: 10051 bytes
Desc: not available
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20120817/44f1c0fc/attachment-0005.h>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile
Type: application/octet-stream
Size: 250 bytes
Desc: not available
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20120817/44f1c0fc/attachment-0005.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: rt-durability.c
Type: text/x-csrc
Size: 20416 bytes
Desc: not available
URL: <http://lists.etherlab.org/pipermail/etherlab-users/attachments/20120817/44f1c0fc/attachment-0005.c>
More information about the Etherlab-users
mailing list