diff --git a/master/ethernet.c b/master/ethernet.c index f8f31927ed735a3bdc57aa6ffec9973c33af4992..a30899405f45477a0e7af93ce4e71e4f3d924b11 100644 --- a/master/ethernet.c +++ b/master/ethernet.c @@ -99,6 +99,7 @@ int ec_eoe_init( eoe->slave = slave; ec_datagram_init(&eoe->datagram); + eoe->queue_datagram = 0; eoe->state = ec_eoe_state_rx_start; eoe->opened = 0; eoe->rx_skb = NULL; @@ -283,7 +284,7 @@ int ec_eoe_send(ec_eoe_t *eoe /**< EoE handler */) (eoe->tx_frame_number & 0x0F) << 12)); memcpy(data + 4, eoe->tx_frame->skb->data + eoe->tx_offset, current_size); - ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); + eoe->queue_datagram = 1; eoe->tx_offset += current_size; eoe->tx_fragment_number++; @@ -300,6 +301,10 @@ void ec_eoe_run(ec_eoe_t *eoe /**< EoE handler */) { if (!eoe->opened) return; + // if the datagram was not sent, or is not yet received, skip this cycle + if (eoe->queue_datagram || eoe->datagram.state == EC_DATAGRAM_SENT) + return; + // call state function eoe->state(eoe); @@ -311,11 +316,26 @@ void ec_eoe_run(ec_eoe_t *eoe /**< EoE handler */) eoe->tx_counter = 0; eoe->rate_jiffies = jiffies; } + ec_datagram_output_stats(&eoe->datagram); } /*****************************************************************************/ +/** + * Queues the datagram, if necessary. + */ + +void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */) +{ + if (eoe->queue_datagram) { + ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); + eoe->queue_datagram = 0; + } +} + +/*****************************************************************************/ + /** Returns the state of the device. \return 1 if the device is "up", 0 if it is "down" @@ -343,7 +363,7 @@ void ec_eoe_state_rx_start(ec_eoe_t *eoe /**< EoE handler */) return; ec_slave_mbox_prepare_check(eoe->slave, &eoe->datagram); - ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); + eoe->queue_datagram = 1; eoe->state = ec_eoe_state_rx_check; } @@ -369,7 +389,7 @@ void ec_eoe_state_rx_check(ec_eoe_t *eoe /**< EoE handler */) } ec_slave_mbox_prepare_fetch(eoe->slave, &eoe->datagram); - ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); + eoe->queue_datagram = 1; eoe->state = ec_eoe_state_rx_fetch; } diff --git a/master/ethernet.h b/master/ethernet.h index c0f32847631b29414061a2530469c9e92e70a7ba..ab497289f09968aa19ffded0e29d5bbb6e4b8f99 100644 --- a/master/ethernet.h +++ b/master/ethernet.h @@ -74,6 +74,7 @@ struct ec_eoe struct list_head list; /**< list item */ ec_slave_t *slave; /**< pointer to the corresponding slave */ ec_datagram_t datagram; /**< datagram */ + unsigned int queue_datagram; /**< the datagram is ready for queuing */ void (*state)(ec_eoe_t *); /**< state function for the state machine */ struct net_device *dev; /**< net_device for virtual ethernet device */ struct net_device_stats stats; /**< device statistics */ @@ -102,6 +103,7 @@ struct ec_eoe int ec_eoe_init(ec_eoe_t *, ec_slave_t *); void ec_eoe_clear(ec_eoe_t *); void ec_eoe_run(ec_eoe_t *); +void ec_eoe_queue(ec_eoe_t *); int ec_eoe_is_open(const ec_eoe_t *); /*****************************************************************************/ diff --git a/master/master.c b/master/master.c index 1442edc6c5c47949234a1d30f80fc06018508e6e..f5268a0c44993156111dfb7541f21c7e84fd7c61 100644 --- a/master/master.c +++ b/master/master.c @@ -1162,7 +1162,6 @@ void ec_master_eoe_run(unsigned long data /**< master pointer */) cycles_t cycles_start, cycles_end; unsigned long restart_jiffies; - list_for_each_entry(eoe, &master->eoe_handlers, list) { if (ec_eoe_is_open(eoe)) { none_open = 0; @@ -1172,11 +1171,11 @@ void ec_master_eoe_run(unsigned long data /**< master pointer */) if (none_open) goto queue_timer; - if (master->request_cb(master->cb_data)) goto queue_timer; - // receive datagrams + if (master->request_cb(master->cb_data)) goto queue_timer; cycles_start = get_cycles(); ecrt_master_receive(master); + master->release_cb(master->cb_data); // actual EoE processing list_for_each_entry(eoe, &master->eoe_handlers, list) { @@ -1184,10 +1183,15 @@ void ec_master_eoe_run(unsigned long data /**< master pointer */) } // send datagrams + if (master->request_cb(master->cb_data)) { + goto queue_timer; + } + list_for_each_entry(eoe, &master->eoe_handlers, list) { + ec_eoe_queue(eoe); + } ecrt_master_send(master); - cycles_end = get_cycles(); - master->release_cb(master->cb_data); + cycles_end = get_cycles(); master->eoe_cycle_times[master->eoe_cycle_time_pos] = (u32) (cycles_end - cycles_start) * 1000 / cpu_khz; @@ -1197,7 +1201,7 @@ void ec_master_eoe_run(unsigned long data /**< master pointer */) queue_timer: restart_jiffies = HZ / EC_EOE_FREQUENCY; if (!restart_jiffies) restart_jiffies = 1; - master->eoe_timer.expires += restart_jiffies; + master->eoe_timer.expires = jiffies + restart_jiffies; add_timer(&master->eoe_timer); } #endif