External domain memory.

This commit is contained in:
Florian Pose 2008-02-21 15:49:02 +00:00
parent 69f702dc92
commit 7db358b508
8 changed files with 321 additions and 182 deletions

1
TODO
View File

@ -10,7 +10,6 @@ Version 1.4.0:
* Realtime interface changes:
- SDO access.
- External memory for domains.
* Mailbox handler
* Read PDO mapping via CoE during bus scan.
* SDO write access in sysfs.

View File

@ -46,6 +46,7 @@
//#define KBUS
#define PDOS
#define MAPPING
#define EXTERNAL_MEMORY
/*****************************************************************************/
@ -74,19 +75,34 @@ const ec_pdo_entry_info_t el3162_channel2[] = {
{0x3102, 2, 16} // value
};
const ec_pdo_info_t mapping[] = {
const ec_pdo_info_t el3162_mapping[] = {
{EC_DIR_INPUT, 0x1A00, 2, el3162_channel1},
{EC_DIR_INPUT, 0x1A01, 2, el3162_channel2},
};
const ec_pdo_entry_info_t el2004_channels[] = {
{0x3001, 1, 1}, // Value 1
{0x3001, 2, 1}, // Value 2
{0x3001, 3, 1}, // Value 3
{0x3001, 4, 1} // Value 4
};
const ec_pdo_info_t el2004_mapping[] = {
{EC_DIR_OUTPUT, 0x1600, 1, &el2004_channels[0]},
{EC_DIR_OUTPUT, 0x1601, 1, &el2004_channels[1]},
{EC_DIR_OUTPUT, 0x1602, 1, &el2004_channels[2]},
{EC_DIR_OUTPUT, 0x1603, 1, &el2004_channels[3]},
};
#endif
#ifdef PDOS
static uint8_t off_ana_in;
//static uint8_t off_ana_out;
static uint8_t *pd; /**< Process data. */
static unsigned int off_ana_in;
static unsigned int off_dig_out;
const static ec_pdo_entry_reg_t domain1_regs[] = {
{0, 1, Beckhoff_EL3162, 0x3101, 2, &off_ana_in},
//{0, 2, Beckhoff_EL4102, 0x3001, 1, &off_ana_out},
{0, 3, Beckhoff_EL2004, 0x3001, 1, &off_dig_out},
{}
};
#endif
@ -105,8 +121,7 @@ void run(unsigned long data)
spin_unlock(&master_lock);
// process data
// k_pos = EC_READ_U32(r_ssi);
//EC_WRITE_U8(r_dig_out, blink ? 0x0F : 0x00);
EC_WRITE_U8(pd + off_dig_out, blink ? 0x0F : 0x00);
if (counter) {
counter--;
@ -176,6 +191,9 @@ int __init init_mini_module(void)
#ifdef MAPPING
ec_slave_config_t *sc;
#endif
#ifdef EXTERNAL_MEMORY
unsigned int size;
#endif
printk(KERN_INFO PFX "Starting...\n");
@ -199,7 +217,17 @@ int __init init_mini_module(void)
goto out_release_master;
}
if (ecrt_slave_config_mapping(sc, 2, mapping)) {
if (ecrt_slave_config_mapping(sc, 2, el3162_mapping)) {
printk(KERN_ERR PFX "Failed to configure Pdo mapping.\n");
goto out_release_master;
}
if (!(sc = ecrt_master_slave_config(master, 0, 3, Beckhoff_EL2004))) {
printk(KERN_ERR PFX "Failed to get slave configuration.\n");
goto out_release_master;
}
if (ecrt_slave_config_mapping(sc, 4, el2004_mapping)) {
printk(KERN_ERR PFX "Failed to configure Pdo mapping.\n");
goto out_release_master;
}
@ -213,12 +241,32 @@ int __init init_mini_module(void)
}
#endif
#ifdef EXTERNAL_MEMORY
if ((size = ecrt_domain_size(domain1))) {
if (!(pd = (uint8_t *) kmalloc(size, GFP_KERNEL))) {
printk(KERN_ERR PFX "Failed to allocate %u bytes of process data"
" memory!\n", size);
goto out_release_master;
}
ecrt_domain_external_memory(domain1, pd);
}
#endif
printk(KERN_INFO PFX "Activating master...\n");
if (ecrt_master_activate(master)) {
printk(KERN_ERR PFX "Failed to activate master!\n");
#ifdef EXTERNAL_MEMORY
goto out_free_process_data;
#else
goto out_release_master;
#endif
}
#ifndef EXTERNAL_MEMORY
// Get internal process data for domain
pd = ecrt_domain_data(domain1);
#endif
printk(KERN_INFO PFX "Starting cyclic sample thread.\n");
init_timer(&timer);
timer.function = run;
@ -228,10 +276,14 @@ int __init init_mini_module(void)
printk(KERN_INFO PFX "Started.\n");
return 0;
out_release_master:
#ifdef EXTERNAL_MEMORY
out_free_process_data:
kfree(pd);
#endif
out_release_master:
printk(KERN_ERR PFX "Releasing master...\n");
ecrt_release_master(master);
out_return:
out_return:
printk(KERN_ERR PFX "Failed to load. Aborting.\n");
return -1;
}
@ -243,6 +295,11 @@ void __exit cleanup_mini_module(void)
printk(KERN_INFO PFX "Stopping...\n");
del_timer_sync(&timer);
#ifdef EXTERNAL_MEMORY
kfree(pd);
#endif
printk(KERN_INFO PFX "Releasing master...\n");
ecrt_release_master(master);

View File

@ -55,13 +55,14 @@
* ecrt_slave_config_state().
* - Process data memory for a domain can now be allocated externally. This
* offers the possibility to use a shared-memory-region. Therefore,
* added the domain methods ecrt_domain_size() and ecrt_domain_memory().
* added the domain methods ecrt_domain_size() and
* ecrt_domain_external_memory().
* - Replaced the process data pointers in the Pdo entry registration
* functions with a process data offset, that is now returned by
* ecrt_slave_config_reg_pdo_entry(). This was necessary for the external
* domain memory. An additional advantage is, that the returned offset value
* is directly usable. The domain's process data offset can be retrieved
* with ecrt_domain_data().
* is directly usable. If the domain's process data is allocated internally,
* the start address can be retrieved with ecrt_domain_data().
* - Replaced ecrt_slave_pdo_mapping/add/clear() with
* ecrt_slave_config_mapping() that is now able to specify Pdo mapping and
* Pdo configuration. Pdo entries mapped in this way can now immediately be
@ -241,7 +242,7 @@ typedef struct {
uint32_t product_code; /**< Slave product code. */
uint16_t index; /**< Pdo entry index. */
uint8_t subindex; /**< Pdo entry subindex. */
uint8_t *offset; /**< Pointer to a variable to store the Pdo's
unsigned int *offset; /**< Pointer to a variable to store the Pdo's
offset in the process data. */
} ec_pdo_entry_reg_t;
@ -503,21 +504,32 @@ size_t ecrt_domain_size(
ec_domain_t *domain /**< Domain. */
);
/** Provide memory to store the domain's process data.
/** Provide external memory to store the domain's process data.
*
* Call this after all Pdo entries have been registered. Since interface
* version 1.4, you'll have to provide an external memory for the domain
* process data.
* Call this after all Pdo entries have been registered and before activating
* the master.
*
* The size of the allocated memory must be at least the return value of
* ecrt_domain_size(), after all Pdo entries have been registered.
* The size of the allocated memory must be at least ecrt_domain_size(), after
* all Pdo entries have been registered.
*/
void ecrt_domain_memory(
void ecrt_domain_external_memory(
ec_domain_t *domain, /**< Domain. */
uint8_t *memory /**< Address of the memory to store the process
data in. */
);
/** Returns the domain's process data.
*
* If external memory was provided with ecrt_domain_external_memory(), the
* returned pointer will contain the address of that memory. Otherwise it will
* point to the internally allocated memory.
*
* \return Pointer to the process data memory.
*/
uint8_t *ecrt_domain_data(
ec_domain_t *domain /**< Domain. */
);
/** Processes received datagrams.
*
* \todo doc

View File

@ -63,20 +63,19 @@
/*****************************************************************************/
/**
Datagram constructor.
*/
/** Constructor.
*/
void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
INIT_LIST_HEAD(&datagram->queue); // mark as unqueued
datagram->type = EC_DATAGRAM_NONE;
memset(datagram->address, 0x00, EC_ADDR_LEN);
datagram->data = NULL;
datagram->data_origin = EC_ORIG_INTERNAL;
datagram->mem_size = 0;
datagram->data_size = 0;
datagram->index = 0x00;
datagram->working_counter = 0x00;
datagram->working_counter = 0x0000;
datagram->state = EC_DATAGRAM_INIT;
datagram->cycles_sent = 0;
datagram->jiffies_sent = 0;
@ -84,33 +83,37 @@ void ec_datagram_init(ec_datagram_t *datagram /**< EtherCAT datagram */)
datagram->jiffies_received = 0;
datagram->skip_count = 0;
datagram->stats_output_jiffies = 0;
datagram->name[0] = 0x00;
memset(datagram->name, 0x00, EC_DATAGRAM_NAME_SIZE);
}
/*****************************************************************************/
/**
Datagram destructor.
*/
/** Destructor.
*/
void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
if (datagram->data) kfree(datagram->data);
if (datagram->data_origin == EC_ORIG_INTERNAL && datagram->data)
kfree(datagram->data);
}
/*****************************************************************************/
/**
Allocates datagram data memory.
If the allocated memory is already larger than requested, nothing ist done.
\return 0 in case of success, else < 0
*/
/** Allocates internal payload memory.
*
* If the allocated memory is already larger than requested, nothing ist done.
*
* \attention If external payload memory has been provided, no range checking
* is done!
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_prealloc(ec_datagram_t *datagram, /**< EtherCAT datagram */
size_t size /**< New size in bytes */
)
size_t size /**< New size in bytes */
)
{
if (size <= datagram->mem_size) return 0;
if (datagram->data_origin == EC_ORIG_EXTERNAL
|| size <= datagram->mem_size)
return 0;
if (datagram->data) {
kfree(datagram->data);
@ -129,12 +132,12 @@ int ec_datagram_prealloc(ec_datagram_t *datagram, /**< EtherCAT datagram */
/*****************************************************************************/
/**
Initializes an EtherCAT NPRD datagram.
Node-adressed physical read.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT NPRD datagram.
*
* Node-adressed physical read.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_nprd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t node_address,
@ -157,12 +160,12 @@ int ec_datagram_nprd(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT NPWR datagram.
Node-adressed physical write.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT NPWR datagram.
*
* Node-adressed physical write.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_npwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t node_address,
@ -185,12 +188,12 @@ int ec_datagram_npwr(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT APRD datagram.
Autoincrement physical read.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT APRD datagram.
*
* Autoincrement physical read.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_aprd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t ring_position,
@ -210,12 +213,12 @@ int ec_datagram_aprd(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT APWR datagram.
Autoincrement physical write.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT APWR datagram.
*
* Autoincrement physical write.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_apwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t ring_position,
@ -235,12 +238,12 @@ int ec_datagram_apwr(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT BRD datagram.
Broadcast read.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT BRD datagram.
*
* Broadcast read.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_brd(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t offset,
@ -258,12 +261,12 @@ int ec_datagram_brd(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT BWR datagram.
Broadcast write.
\return 0 in case of success, else < 0
*/
/** Initializes an EtherCAT BWR datagram.
*
* Broadcast write.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_bwr(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint16_t offset,
@ -281,20 +284,24 @@ int ec_datagram_bwr(ec_datagram_t *datagram,
/*****************************************************************************/
/**
Initializes an EtherCAT LRW datagram.
Logical read write.
\return 0 in case of success, else < 0
*/
int ec_datagram_lrw(ec_datagram_t *datagram,
/**< EtherCAT datagram */
uint32_t offset,
/**< logical address */
size_t data_size
/**< number of bytes to read/write */
)
/** Initializes an EtherCAT LRW datagram.
*
* Logical read write.
*
* \attention It is assumed, that the external memory is at least \a data_size
* bytes large.
*
* \return 0 in case of success, else < 0
*/
int ec_datagram_lrw(
ec_datagram_t *datagram, /**< EtherCAT datagram */
uint32_t offset, /**< Logical address. */
size_t data_size, /**< Number of bytes to read/write. */
uint8_t *external_memory /**< Pointer to the memory to use. */
)
{
datagram->data = external_memory;
datagram->data_origin = EC_ORIG_EXTERNAL;
EC_FUNC_HEADER;
datagram->type = EC_DATAGRAM_LRW;
EC_WRITE_U32(datagram->address, offset);
@ -303,11 +310,10 @@ int ec_datagram_lrw(ec_datagram_t *datagram,
/*****************************************************************************/
/**
* Evaluates the working counter of a single-cast datagram.
/** Evaluates the working counter of a single-cast datagram.
*
* Outputs an error message.
*/
void ec_datagram_print_wc_error(
const ec_datagram_t *datagram /**< EtherCAT datagram */
)
@ -323,10 +329,8 @@ void ec_datagram_print_wc_error(
/*****************************************************************************/
/**
* Outputs datagram statistics at most every second.
/** Outputs datagram statistics at most every second.
*/
void ec_datagram_output_stats(
ec_datagram_t *datagram
)

View File

@ -54,66 +54,58 @@
/*****************************************************************************/
/**
EtherCAT datagram type.
*/
typedef enum
{
EC_DATAGRAM_NONE = 0x00, /**< Dummy */
EC_DATAGRAM_APRD = 0x01, /**< Auto-increment physical read */
EC_DATAGRAM_APWR = 0x02, /**< Auto-increment physical write */
EC_DATAGRAM_NPRD = 0x04, /**< Node-addressed physical read */
EC_DATAGRAM_NPWR = 0x05, /**< Node-addressed physical write */
EC_DATAGRAM_BRD = 0x07, /**< Broadcast read */
EC_DATAGRAM_BWR = 0x08, /**< Broadcast write */
EC_DATAGRAM_LRW = 0x0C /**< Logical read/write */
}
ec_datagram_type_t;
/**
EtherCAT datagram state.
*/
typedef enum
{
EC_DATAGRAM_INIT, /**< new datagram */
EC_DATAGRAM_QUEUED, /**< datagram queued for sending */
EC_DATAGRAM_SENT, /**< datagram has been sent (still in the queue) */
EC_DATAGRAM_RECEIVED, /**< datagram has been received (dequeued) */
EC_DATAGRAM_TIMED_OUT, /**< datagram timed out (dequeued) */
EC_DATAGRAM_ERROR /**< error while sending/receiving (dequeued) */
}
ec_datagram_state_t;
/** EtherCAT datagram type.
*/
typedef enum {
EC_DATAGRAM_NONE = 0x00, /**< Dummy. */
EC_DATAGRAM_APRD = 0x01, /**< Auto-increment physical read. */
EC_DATAGRAM_APWR = 0x02, /**< Auto-increment physical write. */
EC_DATAGRAM_NPRD = 0x04, /**< Node-addressed physical read. */
EC_DATAGRAM_NPWR = 0x05, /**< Node-addressed physical write. */
EC_DATAGRAM_BRD = 0x07, /**< Broadcast read. */
EC_DATAGRAM_BWR = 0x08, /**< Broadcast write. */
EC_DATAGRAM_LRW = 0x0C /**< Logical read/write. */
} ec_datagram_type_t;
/*****************************************************************************/
/**
EtherCAT datagram.
*/
/** EtherCAT datagram state.
*/
typedef enum {
EC_DATAGRAM_INIT, /**< Initial state of a new datagram. */
EC_DATAGRAM_QUEUED, /**< Queued for sending. */
EC_DATAGRAM_SENT, /**< Sent (still in the queue). */
EC_DATAGRAM_RECEIVED, /**< Received (dequeued). */
EC_DATAGRAM_TIMED_OUT, /**< Timed out (dequeued). */
EC_DATAGRAM_ERROR /**< Error while sending/receiving (dequeued). */
} ec_datagram_state_t;
typedef struct
{
struct list_head list; /**< needed by domain datagram lists */
struct list_head queue; /**< master datagram queue item */
struct list_head sent; /**< master list item for sent datagrams */
ec_datagram_type_t type; /**< datagram type (APRD, BWR, etc) */
uint8_t address[EC_ADDR_LEN]; /**< recipient address */
uint8_t *data; /**< datagram data */
size_t mem_size; /**< datagram \a data memory size */
size_t data_size; /**< size of the data in \a data */
uint8_t index; /**< datagram index (set by master) */
uint16_t working_counter; /**< working counter */
ec_datagram_state_t state; /**< datagram state */
cycles_t cycles_sent; /**< time, the datagram was sent */
unsigned long jiffies_sent; /**< jiffies, when the datagram was sent */
cycles_t cycles_received; /**< time, when the datagram was received */
unsigned long jiffies_received; /**< jiffies the datagram was received */
unsigned int skip_count; /**< number of requeues when not yet received */
unsigned long stats_output_jiffies; /**< last statistics output */
char name[EC_DATAGRAM_NAME_SIZE]; /**< description of the datagram */
}
ec_datagram_t;
/*****************************************************************************/
/** EtherCAT datagram.
*/
typedef struct {
struct list_head list; /**< Needed by domain datagram lists. */
struct list_head queue; /**< Master datagram queue item. */
struct list_head sent; /**< Master list item for sent datagrams. */
ec_datagram_type_t type; /**< Datagram type (APRD, BWR, etc.). */
uint8_t address[EC_ADDR_LEN]; /**< Recipient address. */
uint8_t *data; /**< Datagram payload. */
ec_origin_t data_origin; /**< Origin of the \a data memory. */
size_t mem_size; /**< Datagram \a data memory size. */
size_t data_size; /**< Size of the data in \a data. */
uint8_t index; /**< Index (set by master). */
uint16_t working_counter; /**< Working counter. */
ec_datagram_state_t state; /**< State. */
cycles_t cycles_sent; /**< Time, when the datagram was sent. */
unsigned long jiffies_sent; /**< Jiffies, when the datagram was sent. */
cycles_t cycles_received; /**< Time, when the datagram was received. */
unsigned long jiffies_received; /**< Jiffies, when the datagram was
received. */
unsigned int skip_count; /**< Number of requeues when not yet received. */
unsigned long stats_output_jiffies; /**< Last statistics output. */
char name[EC_DATAGRAM_NAME_SIZE]; /**< Description of the datagram. */
} ec_datagram_t;
/*****************************************************************************/
@ -127,7 +119,7 @@ int ec_datagram_aprd(ec_datagram_t *, uint16_t, uint16_t, size_t);
int ec_datagram_apwr(ec_datagram_t *, uint16_t, uint16_t, size_t);
int ec_datagram_brd(ec_datagram_t *, uint16_t, size_t);
int ec_datagram_bwr(ec_datagram_t *, uint16_t, size_t);
int ec_datagram_lrw(ec_datagram_t *, uint32_t, size_t);
int ec_datagram_lrw(ec_datagram_t *, uint32_t, size_t, uint8_t *);
void ec_datagram_print_wc_error(const ec_datagram_t *);
void ec_datagram_output_stats(ec_datagram_t *datagram);

View File

@ -49,6 +49,7 @@
/*****************************************************************************/
void ec_domain_clear(struct kobject *);
void ec_domain_clear_data(ec_domain_t *);
ssize_t ec_show_domain_attribute(struct kobject *, struct attribute *, char *);
/*****************************************************************************/
@ -90,7 +91,9 @@ int ec_domain_init(
domain->master = master;
domain->index = index;
domain->data_size = 0;
domain->base_address = 0;
domain->data = NULL;
domain->data_origin = EC_ORIG_INTERNAL;
domain->logical_base_address = 0L;
domain->working_counter = 0xFFFFFFFF;
domain->notify_jiffies = 0;
domain->working_counter_changes = 0;
@ -158,19 +161,36 @@ void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
kfree(datagram);
}
ec_domain_clear_data(domain);
kfree(domain);
}
/*****************************************************************************/
/** Frees internally allocated memory.
*/
void ec_domain_clear_data(
ec_domain_t *domain /**< EtherCAT domain. */
)
{
if (domain->data_origin == EC_ORIG_INTERNAL && domain->data)
kfree(domain->data);
domain->data = NULL;
domain->data_origin = EC_ORIG_INTERNAL;
}
/*****************************************************************************/
/** Allocates a domain datagram and appends it to the list.
*
* \return 0 in case of success, else < 0
*/
int ec_domain_add_datagram(
ec_domain_t *domain, /**< EtherCAT domain. */
uint32_t offset, /**< Logical offset. */
size_t data_size /**< Size of the data. */
uint32_t logical_offset, /**< Logical offset. */
size_t data_size, /**< Size of the data. */
uint8_t *data /**< Process data. */
)
{
ec_datagram_t *datagram;
@ -182,9 +202,9 @@ int ec_domain_add_datagram(
ec_datagram_init(datagram);
snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
"domain%u-%u", domain->index, offset);
"domain%u-%u", domain->index, logical_offset);
if (ec_datagram_lrw(datagram, offset, data_size)) {
if (ec_datagram_lrw(datagram, logical_offset, data_size, data)) {
kfree(datagram);
return -1;
}
@ -200,6 +220,8 @@ int ec_domain_add_datagram(
* This allocates the necessary datagrams and writes the correct logical
* addresses to every configured FMMU.
*
* \todo Check for FMMUs that do not fit into any datagram.
*
* \retval 0 in case of success
* \retval <0 on failure.
*/
@ -209,17 +231,26 @@ int ec_domain_finish(
)
{
uint32_t datagram_offset;
size_t datagram_data_size;
size_t datagram_size;
unsigned int datagram_count, i;
ec_slave_config_t *sc;
ec_fmmu_config_t *fmmu;
domain->base_address = base_address;
domain->logical_base_address = base_address;
// Cycle through all domain FMMUS, add the logical base address and assign
// as many PDO entries as possible to the datagrams.
datagram_offset = base_address;
datagram_data_size = 0;
if (domain->data_size && domain->data_origin == EC_ORIG_INTERNAL) {
if (!(domain->data =
(uint8_t *) kmalloc(domain->data_size, GFP_KERNEL))) {
EC_ERR("Failed to allocate %u bytes internal memory for"
" domain %u!\n", domain->data_size, domain->index);
return -1;
}
}
// Cycle through all domain FMMUS, correct the logical base addresses and
// set up the datagrams to carry the process data.
datagram_offset = 0;
datagram_size = 0;
datagram_count = 0;
list_for_each_entry(sc, &domain->master->configs, list) {
for (i = 0; i < sc->used_fmmus; i++) {
@ -227,28 +258,36 @@ int ec_domain_finish(
if (fmmu->domain != domain)
continue;
// Correct logical FMMU address
fmmu->logical_start_address += base_address;
if (datagram_data_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
if (ec_domain_add_datagram(domain, datagram_offset,
datagram_data_size)) return -1;
datagram_offset += datagram_data_size;
datagram_data_size = 0;
// If the current FMMU's data do not fit in the current datagram,
// allocate a new one.
if (datagram_size + fmmu->data_size > EC_MAX_DATA_SIZE) {
if (ec_domain_add_datagram(domain,
domain->logical_base_address + datagram_offset,
datagram_size, domain->data + datagram_offset))
return -1;
datagram_offset += datagram_size;
datagram_size = 0;
datagram_count++;
}
datagram_data_size += fmmu->data_size;
datagram_size += fmmu->data_size;
}
}
// allocate last datagram
if (datagram_data_size) {
if (ec_domain_add_datagram(domain, datagram_offset,
datagram_data_size))
// allocate last datagram, if data are left
if (datagram_size) {
if (ec_domain_add_datagram(domain,
domain->logical_base_address + datagram_offset,
datagram_size, domain->data + datagram_offset))
return -1;
datagram_count++;
}
EC_INFO("Domain %u with logical offset %u contains %u bytes in %u"
" datagram%s.\n", domain->index, domain->base_address,
" datagram%s.\n", domain->index, domain->logical_base_address,
domain->data_size, datagram_count, datagram_count == 1 ? "" : "s");
return 0;
}
@ -302,6 +341,30 @@ int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain,
/*****************************************************************************/
size_t ecrt_domain_size(ec_domain_t *domain)
{
return domain->data_size;
}
/*****************************************************************************/
void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
{
ec_domain_clear_data(domain);
domain->data = mem;
domain->data_origin = EC_ORIG_EXTERNAL;
}
/*****************************************************************************/
uint8_t *ecrt_domain_data(ec_domain_t *domain)
{
return domain->data;
}
/*****************************************************************************/
void ecrt_domain_process(ec_domain_t *domain)
{
unsigned int working_counter_sum;
@ -364,8 +427,9 @@ void ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
/** \cond */
EXPORT_SYMBOL(ecrt_domain_reg_pdo_entry_list);
//EXPORT_SYMBOL(ecrt_domain_size);
//EXPORT_SYMBOL(ecrt_domain_memory);
EXPORT_SYMBOL(ecrt_domain_size);
EXPORT_SYMBOL(ecrt_domain_external_memory);
EXPORT_SYMBOL(ecrt_domain_data);
EXPORT_SYMBOL(ecrt_domain_process);
EXPORT_SYMBOL(ecrt_domain_queue);
EXPORT_SYMBOL(ecrt_domain_state);

View File

@ -60,11 +60,14 @@ struct ec_domain
{
struct kobject kobj; /**< kobject. */
struct list_head list; /**< List item. */
unsigned int index; /**< Index (just a number). */
ec_master_t *master; /**< EtherCAT master owning the domain. */
unsigned int index; /**< Index (just a number). */
size_t data_size; /**< Size of the process data. */
uint8_t *data; /**< Memory for the process data. */
ec_origin_t data_origin; /**< Origin of the \a data memory. */
struct list_head datagrams; /**< Datagrams for process data exchange. */
uint32_t base_address; /**< Logical offset address of the process data. */
uint32_t logical_base_address; /**< Logical offset address of the
process data. */
unsigned int working_counter; /**< Last working counter value. */
unsigned int state; /**< Error state. */
unsigned int working_counter_changes; /**< Working counter changes

View File

@ -179,7 +179,7 @@ int ec_mac_is_zero(const uint8_t *);
/*****************************************************************************/
/** Code - Message pair.
/** Code/Message pair.
*
* Some EtherCAT datagrams support reading a status code to display a certain
* message. This type allows to map a code to a message string.
@ -187,8 +187,7 @@ int ec_mac_is_zero(const uint8_t *);
typedef struct {
uint32_t code; /**< Code. */
const char *message; /**< Message belonging to \a code. */
}
ec_code_msg_t;
} ec_code_msg_t;
/*****************************************************************************/
@ -204,6 +203,15 @@ ec_request_state_t;
/*****************************************************************************/
/** Origin type.
*/
typedef enum {
EC_ORIG_INTERNAL, /**< Internal. */
EC_ORIG_EXTERNAL /**< External. */
} ec_origin_t;
/*****************************************************************************/
typedef struct ec_slave ec_slave_t; /**< \see ec_slave. */
typedef struct ec_sdo ec_sdo_t; /**< \see ec_sdo */