mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 11:51:45 +08:00
Interface changes for version 1.2, see NEWS file.
This commit is contained in:
21
NEWS
21
NEWS
@@ -4,6 +4,27 @@ $Id$
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Changes in version 1.2.0:
|
||||
|
||||
* Re-introduced ecrt_domain_queue() to allow datagram queuing apart
|
||||
from datagram processing. The queuing of a domain's datagrams is not
|
||||
done in ecrt_domain_process() any more!
|
||||
* Removed ecrt_master_deactivate(). Its functionality was moved into
|
||||
ecrt_master_release().
|
||||
* Removed ecrt_master_prepare(). Its functionality was moved into
|
||||
ecrt_master_activate().
|
||||
* Removed ecdev_start() and ecdev_stop(). Their functionality was moved into
|
||||
ecdev_register() and ecdev_unregister, respectively.
|
||||
* The data_ptr parameter of ecrt_domain_register_pdo(),
|
||||
ecrt_domain_register_pdo_list() and ecrt_domain_register_pdo_range() may
|
||||
not be NULL any more.
|
||||
* Removed ecrt_slave_pdo_size(). This function was deprecated long before.
|
||||
* Added frame counter to master info file.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Changes in version 1.1.1:
|
||||
|
||||
* State change FSM: Clearing of sync managers before PREOP.
|
||||
* Added modules_install make target.
|
||||
* Device modules for kernel 2.6.17.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# $Id$
|
||||
|
||||
set -x
|
||||
mkdir -p autoconf
|
||||
aclocal -I autoconf
|
||||
|
||||
@@ -2907,20 +2907,12 @@ static int __init rtl8139_init_module (void)
|
||||
printk(KERN_ERR "Failed to register EtherCAT device!\n");
|
||||
goto out_pci;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Starting EtherCAT device...\n");
|
||||
if (ecdev_start(ec_device_master_index)) {
|
||||
printk(KERN_ERR "Failed to start EtherCAT device!\n");
|
||||
goto out_unregister;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING "No EtherCAT device registered!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
|
||||
out_pci:
|
||||
pci_unregister_driver(&rtl8139_pci_driver);
|
||||
out_return:
|
||||
@@ -2937,8 +2929,6 @@ static void __exit rtl8139_cleanup_module (void)
|
||||
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
|
||||
|
||||
if (rtl_ec_net_dev) {
|
||||
printk(KERN_INFO "Stopping device...\n");
|
||||
ecdev_stop(ec_device_master_index);
|
||||
printk(KERN_INFO "Unregistering device...\n");
|
||||
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
|
||||
rtl_ec_dev = NULL;
|
||||
|
||||
@@ -2905,20 +2905,12 @@ static int __init rtl8139_init_module (void)
|
||||
printk(KERN_ERR "Failed to register EtherCAT device!\n");
|
||||
goto out_pci;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Starting EtherCAT device...\n");
|
||||
if (ecdev_start(ec_device_master_index)) {
|
||||
printk(KERN_ERR "Failed to start EtherCAT device!\n");
|
||||
goto out_unregister;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING "No EtherCAT device registered!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_unregister:
|
||||
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
|
||||
out_pci:
|
||||
pci_unregister_driver(&rtl8139_pci_driver);
|
||||
out_return:
|
||||
@@ -2935,8 +2927,6 @@ static void __exit rtl8139_cleanup_module (void)
|
||||
printk(KERN_INFO "Cleaning up RTL8139-EtherCAT module...\n");
|
||||
|
||||
if (rtl_ec_net_dev) {
|
||||
printk(KERN_INFO "Stopping device...\n");
|
||||
ecdev_stop(ec_device_master_index);
|
||||
printk(KERN_INFO "Unregistering device...\n");
|
||||
ecdev_unregister(ec_device_master_index, rtl_ec_dev);
|
||||
rtl_ec_dev = NULL;
|
||||
|
||||
@@ -71,9 +71,6 @@ ec_device_t *ecdev_register(unsigned int master_index,
|
||||
struct module *module);
|
||||
void ecdev_unregister(unsigned int master_index, ec_device_t *device);
|
||||
|
||||
int ecdev_start(unsigned int master_index);
|
||||
void ecdev_stop(unsigned int master_index);
|
||||
|
||||
/*****************************************************************************/
|
||||
// Device methods
|
||||
|
||||
|
||||
@@ -110,8 +110,6 @@ ec_domain_t *ecrt_master_create_domain(ec_master_t *master);
|
||||
|
||||
int ecrt_master_activate(ec_master_t *master);
|
||||
|
||||
void ecrt_master_prepare(ec_master_t *master);
|
||||
|
||||
void ecrt_master_send(ec_master_t *master);
|
||||
void ecrt_master_receive(ec_master_t *master);
|
||||
|
||||
|
||||
@@ -503,7 +503,6 @@ ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< kobject */
|
||||
|
||||
/**
|
||||
Registers a PDO in a domain.
|
||||
- If \a data_ptr is NULL, the slave is only validated.
|
||||
\return pointer to the slave on success, else NULL
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
@@ -537,8 +536,6 @@ ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
|
||||
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
|
||||
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
|
||||
|
||||
if (!data_ptr) return slave;
|
||||
|
||||
list_for_each_entry(pdo, &slave->sii_pdos, list) {
|
||||
list_for_each_entry(entry, &pdo->entries, list) {
|
||||
if (entry->index != pdo_index
|
||||
@@ -561,7 +558,7 @@ ec_slave_t *ecrt_domain_register_pdo(ec_domain_t *domain,
|
||||
|
||||
/**
|
||||
Registeres a bunch of data fields.
|
||||
Caution! The list has to be terminated with a NULL structure ({})!
|
||||
\attention The list has to be terminated with a NULL structure ({})!
|
||||
\return 0 in case of success, else < 0
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
@@ -590,7 +587,6 @@ int ecrt_domain_register_pdo_list(ec_domain_t *domain,
|
||||
|
||||
/**
|
||||
Registers a PDO range in a domain.
|
||||
- If \a data_ptr is NULL, the slave is only validated.
|
||||
\return pointer to the slave on success, else NULL
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
@@ -624,8 +620,6 @@ ec_slave_t *ecrt_domain_register_pdo_range(ec_domain_t *domain,
|
||||
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
|
||||
if (ec_slave_validate(slave, vendor_id, product_code)) return NULL;
|
||||
|
||||
if (!data_ptr) return slave;
|
||||
|
||||
if (ec_domain_reg_pdo_range(domain, slave,
|
||||
direction, offset, length, data_ptr)) {
|
||||
return NULL;
|
||||
|
||||
@@ -79,7 +79,6 @@ int ec_domain_init(ec_domain_t *, ec_master_t *, unsigned int);
|
||||
void ec_domain_destroy(ec_domain_t *);
|
||||
|
||||
int ec_domain_alloc(ec_domain_t *, uint32_t);
|
||||
void ec_domain_queue_datagrams(ec_domain_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
114
master/master.c
114
master/master.c
@@ -129,7 +129,6 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
|
||||
master->debug_level = 0;
|
||||
|
||||
master->stats.timeouts = 0;
|
||||
master->stats.starved = 0;
|
||||
master->stats.corrupted = 0;
|
||||
master->stats.skipped = 0;
|
||||
master->stats.unmatched = 0;
|
||||
@@ -711,11 +710,6 @@ void ec_master_output_stats(ec_master_t *master /**< EtherCAT master */)
|
||||
master->stats.timeouts == 1 ? "" : "s");
|
||||
master->stats.timeouts = 0;
|
||||
}
|
||||
if (master->stats.starved) {
|
||||
EC_WARN("%i datagram%s STARVED!\n", master->stats.starved,
|
||||
master->stats.starved == 1 ? "" : "s");
|
||||
master->stats.starved = 0;
|
||||
}
|
||||
if (master->stats.corrupted) {
|
||||
EC_WARN("%i frame%s CORRUPTED!\n", master->stats.corrupted,
|
||||
master->stats.corrupted == 1 ? "" : "s");
|
||||
@@ -1272,6 +1266,36 @@ int ec_master_measure_bus_time(ec_master_t *master)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prepares synchronous IO.
|
||||
Queues all domain datagrams and sends them. Then waits a certain time, so
|
||||
that ecrt_master_receive() can be called securely.
|
||||
*/
|
||||
|
||||
void ec_master_prepare(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_domain_t *domain;
|
||||
cycles_t cycles_start, cycles_end, cycles_timeout;
|
||||
|
||||
// queue datagrams of all domains
|
||||
list_for_each_entry(domain, &master->domains, list)
|
||||
ecrt_domain_queue(domain);
|
||||
|
||||
ecrt_master_send(master);
|
||||
|
||||
cycles_start = get_cycles();
|
||||
cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
|
||||
|
||||
// active waiting
|
||||
while (1) {
|
||||
udelay(100);
|
||||
cycles_end = get_cycles();
|
||||
if (cycles_end - cycles_start >= cycles_timeout) break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
@@ -1354,25 +1378,13 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT master */)
|
||||
}
|
||||
}
|
||||
|
||||
ec_master_prepare(master); // prepare asynchronous IO
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Resets all slaves to INIT state.
|
||||
This method is deprecated and will disappear in the next version
|
||||
of the realtime interface. The functionality is moved to
|
||||
ecrt_master_release().
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_master_deactivate(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sends queued datagrams and waits for their reception.
|
||||
*/
|
||||
@@ -1445,64 +1457,20 @@ void ecrt_master_receive(ec_master_t *master /**< EtherCAT master */)
|
||||
|
||||
// dequeue all datagrams that timed out
|
||||
list_for_each_entry_safe(datagram, next, &master->datagram_queue, queue) {
|
||||
switch (datagram->state) {
|
||||
case EC_DATAGRAM_QUEUED:
|
||||
if (master->device->cycles_isr
|
||||
- datagram->cycles_queued > cycles_timeout) {
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_DATAGRAM_TIMED_OUT;
|
||||
master->stats.starved++;
|
||||
ec_master_output_stats(master);
|
||||
}
|
||||
break;
|
||||
case EC_DATAGRAM_SENT:
|
||||
if (master->device->cycles_isr
|
||||
- datagram->cycles_sent > cycles_timeout) {
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_DATAGRAM_TIMED_OUT;
|
||||
master->stats.timeouts++;
|
||||
ec_master_output_stats(master);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (datagram->state != EC_DATAGRAM_SENT) continue;
|
||||
|
||||
if (master->device->cycles_isr - datagram->cycles_sent
|
||||
> cycles_timeout) {
|
||||
list_del_init(&datagram->queue);
|
||||
datagram->state = EC_DATAGRAM_TIMED_OUT;
|
||||
master->stats.timeouts++;
|
||||
ec_master_output_stats(master);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prepares synchronous IO.
|
||||
Queues all domain datagrams and sends them. Then waits a certain time, so
|
||||
that ecrt_master_receive() can be called securely.
|
||||
\ingroup RealtimeInterface
|
||||
*/
|
||||
|
||||
void ecrt_master_prepare(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
ec_domain_t *domain;
|
||||
cycles_t cycles_start, cycles_end, cycles_timeout;
|
||||
|
||||
// queue datagrams of all domains
|
||||
list_for_each_entry(domain, &master->domains, list)
|
||||
ec_domain_queue_datagrams(domain);
|
||||
|
||||
ecrt_master_send(master);
|
||||
|
||||
cycles_start = get_cycles();
|
||||
cycles_timeout = (cycles_t) EC_IO_TIMEOUT /* us */ * (cpu_khz / 1000);
|
||||
|
||||
// active waiting
|
||||
while (1) {
|
||||
udelay(100);
|
||||
cycles_end = get_cycles();
|
||||
if (cycles_end - cycles_start >= cycles_timeout) break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Does all cyclic master work.
|
||||
\ingroup RealtimeInterface
|
||||
@@ -1651,8 +1619,6 @@ void ecrt_master_callbacks(ec_master_t *master, /**< EtherCAT master */
|
||||
|
||||
EXPORT_SYMBOL(ecrt_master_create_domain);
|
||||
EXPORT_SYMBOL(ecrt_master_activate);
|
||||
EXPORT_SYMBOL(ecrt_master_deactivate);
|
||||
EXPORT_SYMBOL(ecrt_master_prepare);
|
||||
EXPORT_SYMBOL(ecrt_master_send);
|
||||
EXPORT_SYMBOL(ecrt_master_receive);
|
||||
EXPORT_SYMBOL(ecrt_master_run);
|
||||
|
||||
@@ -75,7 +75,6 @@ ec_master_mode_t;
|
||||
typedef struct
|
||||
{
|
||||
unsigned int timeouts; /**< datagram timeouts */
|
||||
unsigned int starved; /**< starved datagrams (not even sent) */
|
||||
unsigned int corrupted; /**< corrupted frames */
|
||||
unsigned int skipped; /**< skipped datagrams (the ones that were
|
||||
requeued when not yet received) */
|
||||
|
||||
@@ -311,9 +311,19 @@ ec_device_t *ecdev_register(unsigned int master_index, /**< master index */
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (ec_device_open(master->device)) {
|
||||
EC_ERR("Failed to open device!\n");
|
||||
goto out_clear;
|
||||
}
|
||||
|
||||
up(&master->device_sem);
|
||||
|
||||
ec_master_enter_idle_mode(master);
|
||||
|
||||
return master->device;
|
||||
|
||||
out_clear:
|
||||
ec_device_clear(master->device);
|
||||
out_free:
|
||||
kfree(master->device);
|
||||
master->device = NULL;
|
||||
@@ -342,6 +352,11 @@ void ecdev_unregister(unsigned int master_index, /**< master index */
|
||||
|
||||
if (!(master = ec_find_master(master_index))) return;
|
||||
|
||||
ec_master_leave_idle_mode(master);
|
||||
|
||||
if (ec_device_close(master->device))
|
||||
EC_WARN("Failed to close device!\n");
|
||||
|
||||
down(&master->device_sem);
|
||||
|
||||
if (!master->device || master->device != device) {
|
||||
@@ -357,51 +372,6 @@ void ecdev_unregister(unsigned int master_index, /**< master index */
|
||||
up(&master->device_sem);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Starts the master associated with the device.
|
||||
This function has to be called by the network device driver to tell the
|
||||
master that the device is ready to send and receive data. The master
|
||||
will enter the idle mode then.
|
||||
\ingroup DeviceInterface
|
||||
*/
|
||||
|
||||
int ecdev_start(unsigned int master_index /**< master index */)
|
||||
{
|
||||
ec_master_t *master;
|
||||
if (!(master = ec_find_master(master_index))) return -1;
|
||||
|
||||
if (ec_device_open(master->device)) {
|
||||
EC_ERR("Failed to open device!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_master_enter_idle_mode(master);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Stops the master associated with the device.
|
||||
Tells the master to stop using the device for frame IO. Has to be called
|
||||
before unregistering the device.
|
||||
\ingroup DeviceInterface
|
||||
*/
|
||||
|
||||
void ecdev_stop(unsigned int master_index /**< master index */)
|
||||
{
|
||||
ec_master_t *master;
|
||||
if (!(master = ec_find_master(master_index))) return;
|
||||
|
||||
ec_master_leave_idle_mode(master);
|
||||
|
||||
if (ec_device_close(master->device))
|
||||
EC_WARN("Failed to close device!\n");
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
@@ -495,8 +465,6 @@ module_exit(ec_cleanup_module);
|
||||
|
||||
EXPORT_SYMBOL(ecdev_register);
|
||||
EXPORT_SYMBOL(ecdev_unregister);
|
||||
EXPORT_SYMBOL(ecdev_start);
|
||||
EXPORT_SYMBOL(ecdev_stop);
|
||||
EXPORT_SYMBOL(ecrt_request_master);
|
||||
EXPORT_SYMBOL(ecrt_release_master);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user