External domain memory.
--- a/TODO Thu Feb 21 12:43:55 2008 +0000
+++ b/TODO Thu Feb 21 15:49:02 2008 +0000
@@ -10,7 +10,6 @@
* Realtime interface changes:
- SDO access.
- - External memory for domains.
* Mailbox handler
* Read PDO mapping via CoE during bus scan.
* SDO write access in sysfs.
--- a/examples/mini/mini.c Thu Feb 21 12:43:55 2008 +0000
+++ b/examples/mini/mini.c Thu Feb 21 15:49:02 2008 +0000
@@ -46,6 +46,7 @@
//#define KBUS
#define PDOS
#define MAPPING
+#define EXTERNAL_MEMORY
/*****************************************************************************/
@@ -74,19 +75,34 @@
{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 @@
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 @@
#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 @@
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,11 +241,31 @@
}
#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");
- goto out_release_master;
- }
+#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);
@@ -228,10 +276,14 @@
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 @@
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);
--- a/include/ecrt.h Thu Feb 21 12:43:55 2008 +0000
+++ b/include/ecrt.h Thu Feb 21 15:49:02 2008 +0000
@@ -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 @@
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 @@
ec_domain_t *domain /**< Domain. */
);
-/** Provide 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.
- *
- * The size of the allocated memory must be at least the return value of
- * ecrt_domain_size(), after all Pdo entries have been registered.
- */
-void ecrt_domain_memory(
+/** Provide external memory to store the domain's 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 ecrt_domain_size(), after
+ * all Pdo entries have been registered.
+ */
+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
--- a/master/datagram.c Thu Feb 21 12:43:55 2008 +0000
+++ b/master/datagram.c Thu Feb 21 15:49:02 2008 +0000
@@ -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 @@
datagram->jiffies_received = 0;
datagram->skip_count = 0;
datagram->stats_output_jiffies = 0;
- datagram->name[0] = 0x00;
-}
-
-/*****************************************************************************/
-
-/**
- Datagram destructor.
-*/
-
+ memset(datagram->name, 0x00, EC_DATAGRAM_NAME_SIZE);
+}
+
+/*****************************************************************************/
+
+/** Destructor.
+ */
void ec_datagram_clear(ec_datagram_t *datagram /**< EtherCAT datagram */)
{
- if (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
-*/
-
+ if (datagram->data_origin == EC_ORIG_INTERNAL && datagram->data)
+ kfree(datagram->data);
+}
+
+/*****************************************************************************/
+
+/** 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 */
- )
-{
- if (size <= datagram->mem_size) return 0;
+ size_t size /**< New size in bytes */
+ )
+{
+ if (datagram->data_origin == EC_ORIG_EXTERNAL
+ || size <= datagram->mem_size)
+ return 0;
if (datagram->data) {
kfree(datagram->data);
@@ -129,12 +132,12 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- 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 @@
/*****************************************************************************/
-/**
- * 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 @@
/*****************************************************************************/
-/**
- * Outputs datagram statistics at most every second.
- */
-
+/** Outputs datagram statistics at most every second.
+ */
void ec_datagram_output_stats(
ec_datagram_t *datagram
)
--- a/master/datagram.h Thu Feb 21 12:43:55 2008 +0000
+++ b/master/datagram.h Thu Feb 21 15:49:02 2008 +0000
@@ -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_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);
--- a/master/domain.c Thu Feb 21 12:43:55 2008 +0000
+++ b/master/domain.c Thu Feb 21 15:49:02 2008 +0000
@@ -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 @@
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 @@
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 @@
ec_datagram_init(datagram);
snprintf(datagram->name, EC_DATAGRAM_NAME_SIZE,
- "domain%u-%u", domain->index, offset);
-
- if (ec_datagram_lrw(datagram, offset, data_size)) {
+ "domain%u-%u", domain->index, logical_offset);
+
+ if (ec_datagram_lrw(datagram, logical_offset, data_size, data)) {
kfree(datagram);
return -1;
}
@@ -200,6 +220,8 @@
* 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 @@
)
{
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;
-
- // 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;
+ domain->logical_base_address = base_address;
+
+ 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 @@
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;
- }
- }
-
- // allocate last datagram
- if (datagram_data_size) {
- if (ec_domain_add_datagram(domain, datagram_offset,
- datagram_data_size))
+
+ datagram_size += fmmu->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 @@
/*****************************************************************************/
+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 @@
/** \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);
--- a/master/domain.h Thu Feb 21 12:43:55 2008 +0000
+++ b/master/domain.h Thu Feb 21 15:49:02 2008 +0000
@@ -60,11 +60,14 @@
{
struct kobject kobj; /**< kobject. */
struct list_head list; /**< List item. */
+ ec_master_t *master; /**< EtherCAT master owning the domain. */
unsigned int index; /**< Index (just a number). */
- ec_master_t *master; /**< EtherCAT master owning the domain. */
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
--- a/master/globals.h Thu Feb 21 12:43:55 2008 +0000
+++ b/master/globals.h Thu Feb 21 15:49:02 2008 +0000
@@ -179,7 +179,7 @@
/*****************************************************************************/
-/** 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 @@
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 @@
/*****************************************************************************/
+/** 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 */