29 #include <linux/module.h> 40 #define DEBUG_REDUNDANCY 0 59 domain->
index = index;
85 list_for_each_entry_safe(datagram_pair, next_pair,
125 " Added %u bytes, total %zu.\n",
141 uint32_t logical_offset,
144 const unsigned int used[]
152 "Failed to allocate domain datagram pair!\n");
159 kfree(datagram_pair);
167 "Adding datagram pair with expected WC %u.\n",
193 for (; first_fmmu != cur_fmmu;
194 first_fmmu = list_entry(first_fmmu->
list.next,
197 if (first_fmmu->
sc == cur_fmmu->
sc 198 && first_fmmu->
dir == cur_fmmu->
dir) {
220 uint32_t base_address
223 uint32_t datagram_offset;
224 size_t datagram_size;
225 unsigned int datagram_count;
236 (uint8_t *) kmalloc(domain->
data_size, GFP_KERNEL))) {
238 " internal memory for domain %u!\n",
255 datagram_first_fmmu =
259 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
269 datagram_size, domain->
data + datagram_offset,
274 datagram_offset += datagram_size;
279 datagram_first_fmmu = fmmu;
285 datagram_used[fmmu->
dir]++;
296 datagram_size, domain->
data + datagram_offset,
304 " %zu byte, expected working counter %u.\n", domain->
index,
308 list_for_each_entry(datagram_pair, &domain->
datagram_pairs, list) {
312 " %zu byte, type %s.\n", datagram->
name,
327 unsigned int num = 0;
329 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
349 list_for_each_entry(fmmu, &domain->
fmmu_configs, list) {
360 #if EC_MAX_NUM_DEVICES > 1 365 uint8_t *send_buffer,
371 uint8_t *sent = send_buffer + offset;
372 uint8_t *recv = datagram->
data + offset;
375 for (i = 0; i < size; i++) {
376 if (recv[i] != sent[i]) {
398 "domain = 0x%p, regs = 0x%p)\n", domain, regs);
400 for (reg = regs; reg->
index; reg++) {
429 "domain = 0x%p, mem = 0x%p)\n", domain, mem);
452 uint16_t wc_sum[EC_MAX_NUM_DEVICES] = {}, wc_total;
454 #if EC_MAX_NUM_DEVICES > 1 455 uint16_t datagram_pair_wc, redundant_wc;
456 unsigned int datagram_offset;
459 unsigned int redundancy;
461 unsigned int dev_idx;
463 unsigned int wc_change;
471 #if EC_MAX_NUM_DEVICES > 1 477 #if EC_MAX_NUM_DEVICES > 1 480 uint32_t logical_datagram_address =
482 size_t datagram_size = main_datagram->
data_size;
486 main_datagram->
name, logical_datagram_address);
490 list_for_each_entry_from(fmmu, &domain->
fmmu_configs, list) {
499 logical_datagram_address + datagram_size) {
509 "input fmmu log=%u size=%u offset=%u\n",
522 if (data_changed(pair->send_buffer, main_datagram,
528 }
else if (data_changed(pair->send_buffer, backup_datagram,
534 memcpy(main_datagram->
data + datagram_offset,
535 backup_datagram->
data + datagram_offset,
537 }
else if (datagram_pair_wc ==
542 "no change but complete\n");
547 datagram_pair_wc = 0;
550 "no change and incomplete\n");
555 #endif // EC_MAX_NUM_DEVICES > 1 558 #if EC_MAX_NUM_DEVICES > 1 562 redundant_wc += wc_sum[dev_idx];
565 redundancy = redundant_wc > 0;
570 "Domain %u: Redundant link in use!\n",
574 "Domain %u: Redundant link unused again.\n",
596 wc_total += wc_sum[dev_idx];
609 " changed to %u/%u", domain->
index,
613 " changes - now %u/%u", domain->
index,
617 #if EC_MAX_NUM_DEVICES > 1 619 printk(KERN_CONT
" (");
625 printk(KERN_CONT
"+");
628 printk(KERN_CONT
")");
631 printk(KERN_CONT
".\n");
646 list_for_each_entry(datagram_pair, &domain->
datagram_pairs, list) {
648 #if EC_MAX_NUM_DEVICES > 1 650 memcpy(datagram_pair->send_buffer,
674 unsigned int dev_idx;
unsigned int working_counter
Value of the last working counter.
const ec_slave_config_t * sc
EtherCAT slave config.
uint8_t subindex
PDO entry subindex.
uint16_t position
Slave position.
size_t data_size
Size of the data in data.
size_t data_size
Size of the process data.
unsigned int expected_working_counter
Expectord working conter.
unsigned int redundancy_active
Redundant link is in use.
int ecrt_domain_reg_pdo_entry_list(ec_domain_t *domain, const ec_pdo_entry_reg_t *regs)
Registers a bunch of PDO entries for a domain.
uint16_t index
PDO entry index.
#define ec_master_num_devices(MASTER)
Number of Ethernet devices.
int ecrt_slave_config_reg_pdo_entry(ec_slave_config_t *sc, uint16_t index, uint8_t subindex, ec_domain_t *domain, unsigned int *bit_position)
Registers a PDO entry for process data exchange in a domain.
unsigned int data_size
Covered PDO size.
char name[EC_DATAGRAM_NAME_SIZE]
Description of the datagram.
ec_wc_state_t wc_state
Working counter interpretation.
void ecrt_domain_external_memory(ec_domain_t *domain, uint8_t *mem)
Provide external memory to store the domain's process data.
void ec_domain_clear_data(ec_domain_t *)
Frees internally allocated memory.
Global definitions and macros.
Some of the registered process data were exchanged.
EtherCAT master structure.
uint8_t * data
Memory for the process data.
uint8_t * ecrt_domain_data(const ec_domain_t *domain)
Returns the domain's process data.
uint16_t alias
Slave alias address.
#define EC_MASTER_DBG(master, level, fmt, args...)
Convenience macro for printing master-specific debug messages to syslog.
struct semaphore master_sem
Master semaphore.
uint32_t logical_start_address
Logical start address.
struct list_head list
List node used by domain.
unsigned int working_counter_changes
Working counter changes since last notification.
const ec_domain_t * domain
Domain.
uint32_t vendor_id
Slave vendor ID.
unsigned int * bit_position
Pointer to a variable to store a bit position (0-7) within the offset.
void ec_domain_clear(ec_domain_t *domain)
Domain destructor.
int ec_domain_finish(ec_domain_t *domain, uint32_t base_address)
Finishes a domain.
size_t ecrt_domain_size(const ec_domain_t *domain)
Returns the current size of the domain's process data.
unsigned int debug_level
Master debug level.
uint16_t ec_datagram_pair_process(ec_datagram_pair_t *pair, uint16_t wc_sum[])
Process received data.
ec_device_index_t
Master devices.
void ec_datagram_pair_clear(ec_datagram_pair_t *pair)
Datagram pair destructor.
unsigned int index
Index (just a number).
int ecrt_domain_queue(ec_domain_t *domain)
(Re-)queues all domain datagrams in the master's datagram queue.
#define EC_READ_U32(DATA)
Read a 32-bit unsigned value from EtherCAT data.
struct list_head fmmu_configs
FMMU configurations contained.
#define EC_MASTER_WARN(master, fmt, args...)
Convenience macro for printing master-specific warnings to syslog.
unsigned int ec_domain_fmmu_count(const ec_domain_t *domain)
Get the number of FMMU configurations of the domain.
#define EC_MASTER_ERR(master, fmt, args...)
Convenience macro for printing master-specific errors to syslog.
void ec_master_queue_datagram(ec_master_t *master, ec_datagram_t *datagram)
Places a datagram in the datagram queue.
Values read by the master.
int ecrt_domain_process(ec_domain_t *domain)
Determines the states of the domain's datagrams.
ec_origin_t data_origin
Origin of the data memory.
void ec_print_data(const uint8_t *, size_t)
Outputs frame contents for debugging purposes.
uint16_t working_counter[EC_MAX_NUM_DEVICES]
Last working counter values.
uint32_t logical_base_address
Logical offset address of the process data.
uint16_t expected_working_counter
Expected working counter.
unsigned int redundancy_active
Non-zero, if redundancy is in use.
int ec_datagram_pair_init(ec_datagram_pair_t *pair, ec_domain_t *domain, uint32_t logical_offset, uint8_t *data, size_t data_size, const unsigned int used[])
Datagram pair constructor.
void ec_domain_add_fmmu_config(ec_domain_t *domain, ec_fmmu_config_t *fmmu)
Adds an FMMU configuration to the domain.
struct list_head list
List header.
List record type for PDO entry mass-registration.
EtherCAT domain structure.
int ecrt_domain_state(const ec_domain_t *domain, ec_domain_state_t *state)
Reads the state of a domain.
No registered process data were exchanged.
All registered process data were exchanged.
EtherCAT datagram pair structure.
const char * ec_datagram_type_string(const ec_datagram_t *datagram)
Returns a string describing the datagram type.
uint8_t * data
Datagram payload.
EtherCAT slave configuration.
ec_datagram_t datagrams[EC_MAX_NUM_DEVICES]
Datagrams.
EtherCAT slave configuration structure.
ec_slave_config_t * ecrt_master_slave_config_err(ec_master_t *master, uint16_t alias, uint16_t position, uint32_t vendor_id, uint32_t product_code)
Same as ecrt_master_slave_config(), but with ERR_PTR() return value.
unsigned int * offset
Pointer to a variable to store the PDO entry's (byte-)offset in the process data. ...
uint8_t address[EC_ADDR_LEN]
Recipient address.
void ec_domain_init(ec_domain_t *domain, ec_master_t *master, unsigned int index)
Domain constructor.
ec_direction_t dir
FMMU direction.
Values written by the master.
struct list_head datagram_pairs
Datagrams pairs (main/backup) for process data exchange.
#define EC_MASTER_INFO(master, fmt, args...)
Convenience macro for printing master-specific information to syslog.
uint32_t product_code
Slave product code.
unsigned long notify_jiffies
Time of last notification.
int ec_domain_add_datagram_pair(ec_domain_t *domain, uint32_t logical_offset, size_t data_size, uint8_t *data, const unsigned int used[])
Allocates a domain datagram pair and appends it to the list.
int shall_count(const ec_fmmu_config_t *cur_fmmu, const ec_fmmu_config_t *first_fmmu)
Domain finish helper function.
ec_master_t * master
EtherCAT master owning the domain.
#define EC_MAX_DATA_SIZE
Resulting maximum data size of a single datagram in a frame.
const ec_fmmu_config_t * ec_domain_find_fmmu(const ec_domain_t *domain, unsigned int pos)
Get a certain FMMU configuration via its position in the list.