# HG changeset patch # User Florian Pose # Date 1203608942 0 # Node ID ec4ef8911824dfa1885984a7b5a94a244f697581 # Parent 1feddbd6560893504ad6f9403cda6c6b95344d68 External domain memory. diff -r 1feddbd65608 -r ec4ef8911824 TODO --- 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. diff -r 1feddbd65608 -r ec4ef8911824 examples/mini/mini.c --- 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); diff -r 1feddbd65608 -r ec4ef8911824 include/ecrt.h --- 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 diff -r 1feddbd65608 -r ec4ef8911824 master/datagram.c --- 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 ) diff -r 1feddbd65608 -r ec4ef8911824 master/datagram.h --- 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); diff -r 1feddbd65608 -r ec4ef8911824 master/domain.c --- 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); diff -r 1feddbd65608 -r ec4ef8911824 master/domain.h --- 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 diff -r 1feddbd65608 -r ec4ef8911824 master/globals.h --- 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 */