# HG changeset patch # User Florian Pose # Date 1247498308 0 # Node ID ed1a733efbc5b14164c9c1c13d8285c43a8f3a36 # Parent 5461fce4a2ea1ac2a79f651e92c793bb087346a1 Improved the callback mechanism. diff -r 5461fce4a2ea -r ed1a733efbc5 NEWS --- a/NEWS Fri Jul 10 10:40:05 2009 +0000 +++ b/NEWS Mon Jul 13 15:18:28 2009 +0000 @@ -12,6 +12,10 @@ library is licensed under LGPLv2. * Added distributed clocks support. * Added VoE mailbox protocol support. +* Improved the callback mechanism. ecrt_master_callbacks() now takes two + callback functions for sending and receiving datagrams. + ecrt_master_send_ext() is used to execute the sending of non-application + datagrams. * Separated datagram initialization from filling the payload with zeros. Introduced new method ec_datagram_zero() for that. * Added phy_read and phy_write commands to ethercat tool. diff -r 5461fce4a2ea -r ed1a733efbc5 TODO --- a/TODO Fri Jul 10 10:40:05 2009 +0000 +++ b/TODO Mon Jul 13 15:18:28 2009 +0000 @@ -24,8 +24,6 @@ * Remove byte-swapping functions from user space. * EoE: - Only execute one EoE handler per cycle. - - Replace locking callbacks. - - Allow EoE with userspace application. * Implement 'ethercat foe_read --output-file ...'. * Fix unloading problem of ec_e100 driver. * Use ec_datagram_zero() where possible. @@ -41,7 +39,6 @@ * Remove ecrt_domain_state()? * Check force_config flag before error. * Remove allow_scanning flag. -* Implement ecrt_master_slave() in kernel space. * Check for ioctl() interface version. * Improve application-triggered SDO transfers by moving the state machine into the SDO handlers. diff -r 5461fce4a2ea -r ed1a733efbc5 examples/dc_rtai/dc_rtai_sample.c --- a/examples/dc_rtai/dc_rtai_sample.c Fri Jul 10 10:40:05 2009 +0000 +++ b/examples/dc_rtai/dc_rtai_sample.c Mon Jul 13 15:18:28 2009 +0000 @@ -58,7 +58,6 @@ // EtherCAT static ec_master_t *master = NULL; static ec_master_state_t master_state = {}; -spinlock_t master_lock = SPIN_LOCK_UNLOCKED; static ec_domain_t *domain1 = NULL; static ec_domain_state_t domain1_state = {}; @@ -125,9 +124,9 @@ { ec_domain_state_t ds; - spin_lock(&master_lock); + rt_sem_wait(&master_sem); ecrt_domain_state(domain1, &ds); - spin_unlock(&master_lock); + rt_sem_signal(&master_sem); if (ds.working_counter != domain1_state.working_counter) printk(KERN_INFO PFX "Domain1: WC %u.\n", ds.working_counter); @@ -143,9 +142,9 @@ { ec_master_state_t ms; - spin_lock(&master_lock); + rt_sem_wait(&master_sem); ecrt_master_state(master, &ms); - spin_unlock(&master_lock); + rt_sem_signal(&master_sem); if (ms.slaves_responding != master_state.slaves_responding) printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding); @@ -239,21 +238,26 @@ /*****************************************************************************/ -int request_lock(void *data) +void send_callback(ec_master_t *master) { // too close to the next real time cycle: deny access... - if (get_cycles() - t_last_cycle > t_critical) return -1; - - // allow access - rt_sem_wait(&master_sem); - return 0; -} - -/*****************************************************************************/ - -void release_lock(void *data) -{ - rt_sem_signal(&master_sem); + if (get_cycles() - t_last_cycle <= t_critical) { + rt_sem_wait(&master_sem); + ecrt_master_send_ext(master); + rt_sem_signal(&master_sem); + } +} + +/*****************************************************************************/ + +void receive_callback(ec_master_t *master) +{ + // too close to the next real time cycle: deny access... + if (get_cycles() - t_last_cycle <= t_critical) { + rt_sem_wait(&master_sem); + ecrt_master_receive(master); + rt_sem_signal(&master_sem); + } } /*****************************************************************************/ @@ -277,7 +281,7 @@ goto out_return; } - ecrt_master_callbacks(master, request_lock, release_lock, NULL); + ecrt_master_callbacks(master, send_callback, receive_callback); printk(KERN_INFO PFX "Registering domain...\n"); if (!(domain1 = ecrt_master_create_domain(master))) { diff -r 5461fce4a2ea -r ed1a733efbc5 examples/mini/mini.c --- a/examples/mini/mini.c Fri Jul 10 10:40:05 2009 +0000 +++ b/examples/mini/mini.c Mon Jul 13 15:18:28 2009 +0000 @@ -29,7 +29,7 @@ #include #include -#include +#include #include #include @@ -54,7 +54,7 @@ // EtherCAT static ec_master_t *master = NULL; static ec_master_state_t master_state = {}; -spinlock_t master_lock = SPIN_LOCK_UNLOCKED; +struct semaphore master_sem; static ec_domain_t *domain1 = NULL; static ec_domain_state_t domain1_state = {}; @@ -192,9 +192,9 @@ { ec_domain_state_t ds; - spin_lock(&master_lock); + down(&master_sem); ecrt_domain_state(domain1, &ds); - spin_unlock(&master_lock); + up(&master_sem); if (ds.working_counter != domain1_state.working_counter) printk(KERN_INFO PFX "Domain1: WC %u.\n", ds.working_counter); @@ -210,9 +210,9 @@ { ec_master_state_t ms; - spin_lock(&master_lock); + down(&master_sem); ecrt_master_state(master, &ms); - spin_unlock(&master_lock); + up(&master_sem); if (ms.slaves_responding != master_state.slaves_responding) printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding); @@ -230,9 +230,9 @@ { ec_slave_config_state_t s; - spin_lock(&master_lock); + down(&master_sem); ecrt_slave_config_state(sc_ana_in, &s); - spin_unlock(&master_lock); + up(&master_sem); if (s.al_state != sc_ana_in_state.al_state) printk(KERN_INFO PFX "AnaIn: State 0x%02X.\n", s.al_state); @@ -300,10 +300,10 @@ void cyclic_task(unsigned long data) { // receive process data - spin_lock(&master_lock); + down(&master_sem); ecrt_master_receive(master); ecrt_domain_process(domain1); - spin_unlock(&master_lock); + up(&master_sem); // check process data state (optional) check_domain1_state(); @@ -336,10 +336,10 @@ EC_WRITE_U8(domain1_pd + off_dig_out, blink ? 0x06 : 0x09); // send process data - spin_lock(&master_lock); + down(&master_sem); ecrt_domain_queue(domain1); ecrt_master_send(master); - spin_unlock(&master_lock); + up(&master_sem); // restart timer timer.expires += HZ / FREQUENCY; @@ -348,17 +348,20 @@ /*****************************************************************************/ -int request_lock(void *data) -{ - spin_lock(&master_lock); - return 0; // access allowed -} - -/*****************************************************************************/ - -void release_lock(void *data) -{ - spin_unlock(&master_lock); +void send_callback(ec_master_t *master) +{ + down(&master_sem); + ecrt_master_send_ext(master); + up(&master_sem); +} + +/*****************************************************************************/ + +void receive_callback(ec_master_t *master) +{ + down(&master_sem); + ecrt_master_receive(master); + up(&master_sem); } /*****************************************************************************/ @@ -382,7 +385,8 @@ goto out_return; } - ecrt_master_callbacks(master, request_lock, release_lock, NULL); + init_MUTEX(&master_sem); + ecrt_master_callbacks(master, send_callback, receive_callback); printk(KERN_INFO PFX "Registering domain...\n"); if (!(domain1 = ecrt_master_create_domain(master))) { diff -r 5461fce4a2ea -r ed1a733efbc5 examples/rtai/rtai_sample.c --- a/examples/rtai/rtai_sample.c Fri Jul 10 10:40:05 2009 +0000 +++ b/examples/rtai/rtai_sample.c Mon Jul 13 15:18:28 2009 +0000 @@ -59,7 +59,6 @@ // EtherCAT static ec_master_t *master = NULL; static ec_master_state_t master_state = {}; -spinlock_t master_lock = SPIN_LOCK_UNLOCKED; static ec_domain_t *domain1 = NULL; static ec_domain_state_t domain1_state = {}; @@ -146,9 +145,9 @@ { ec_domain_state_t ds; - spin_lock(&master_lock); + rt_sem_wait(&master_sem); ecrt_domain_state(domain1, &ds); - spin_unlock(&master_lock); + rt_sem_signal(&master_sem); if (ds.working_counter != domain1_state.working_counter) printk(KERN_INFO PFX "Domain1: WC %u.\n", ds.working_counter); @@ -164,9 +163,9 @@ { ec_master_state_t ms; - spin_lock(&master_lock); + rt_sem_wait(&master_sem); ecrt_master_state(master, &ms); - spin_unlock(&master_lock); + rt_sem_signal(&master_sem); if (ms.slaves_responding != master_state.slaves_responding) printk(KERN_INFO PFX "%u slave(s).\n", ms.slaves_responding); @@ -184,9 +183,9 @@ { ec_slave_config_state_t s; - spin_lock(&master_lock); + rt_sem_wait(&master_sem); ecrt_slave_config_state(sc_ana_in, &s); - spin_unlock(&master_lock); + rt_sem_signal(&master_sem); if (s.al_state != sc_ana_in_state.al_state) printk(KERN_INFO PFX "AnaIn: State 0x%02X.\n", s.al_state); @@ -244,21 +243,26 @@ /*****************************************************************************/ -int request_lock(void *data) +void send_callback(ec_master_t *master) { // too close to the next real time cycle: deny access... - if (get_cycles() - t_last_cycle > t_critical) return -1; - - // allow access - rt_sem_wait(&master_sem); - return 0; -} - -/*****************************************************************************/ - -void release_lock(void *data) -{ - rt_sem_signal(&master_sem); + if (get_cycles() - t_last_cycle <= t_critical) { + rt_sem_wait(&master_sem); + ecrt_master_send_ext(master); + rt_sem_signal(&master_sem); + } +} + +/*****************************************************************************/ + +void receive_callback(ec_master_t *master) +{ + // too close to the next real time cycle: deny access... + if (get_cycles() - t_last_cycle <= t_critical) { + rt_sem_wait(&master_sem); + ecrt_master_receive(master); + rt_sem_signal(&master_sem); + } } /*****************************************************************************/ @@ -277,7 +281,6 @@ t_critical = cpu_khz * 1000 / FREQUENCY - cpu_khz * INHIBIT_TIME / 1000; - master = ecrt_request_master(0); if (IS_ERR(master)) { ret = PTR_ERR(master); @@ -285,7 +288,7 @@ goto out_return; } - ecrt_master_callbacks(master, request_lock, release_lock, NULL); + ecrt_master_callbacks(master, send_callback, receive_callback); printk(KERN_INFO PFX "Registering domain...\n"); if (!(domain1 = ecrt_master_create_domain(master))) { diff -r 5461fce4a2ea -r ed1a733efbc5 include/ecrt.h --- a/include/ecrt.h Fri Jul 10 10:40:05 2009 +0000 +++ b/include/ecrt.h Mon Jul 13 15:18:28 2009 +0000 @@ -42,24 +42,27 @@ * Changes in version 1.5: * * - Added the distributed clocks feature and the respective method - * ecrt_slave_config_dc() to configure a slave for cyclic - * operation, and ecrt_master_application_time(), - * ecrt_master_sync_reference_clock() and ecrt_master_sync_slave_clocks() - * for offset and drift compensation. The EC_TIMEVAL2NANO() macro can be - * used for epoch time conversion. + * ecrt_slave_config_dc() to configure a slave for cyclic operation, and + * ecrt_master_application_time(), ecrt_master_sync_reference_clock() and + * ecrt_master_sync_slave_clocks() for offset and drift compensation. The + * EC_TIMEVAL2NANO() macro can be used for epoch time conversion. + * - Improved the callback mechanism. ecrt_master_callbacks() now takes two + * callback functions for sending and receiving datagrams. + * ecrt_master_send_ext() is used to execute the sending of non-application + * datagrams. * - Added ecrt_open_master() and ecrt_master_reserve() separation for * userspace. * - Added ecrt_master() userspace interface, to get information about a * master. + * - Added ecrt_master_slave() to get information about a certain slave. + * - Added ecrt_slave_sdo_upload() and ecrt_slave_sdo_download() methods to + * let an application transfer SDOs before activating the master. * - Changed the meaning of the negative return values of * ecrt_slave_config_reg_pdo_entry() and ecrt_slave_config_sdo*(). * - Imlemented the Vendor-specific over EtherCAT mailbox protocol. See * ecrt_slave_config_create_voe_handler(). * - Renamed ec_sdo_request_state_t to ec_request_state_t, because it is also * used by VoE handlers. - * - Added ecrt_master_slave() to get information about a certain slave. - * - Added ecrt_slave_sdo_upload() and ecrt_slave_sdo_download() methods to - * let an application transfer SDOs before activating the master. * - Removed 'const' from argument of ecrt_sdo_request_state(), because the * userspace library has to modify object internals. * - Added 64-bit data access macros. @@ -442,21 +445,23 @@ /** Sets the locking callbacks. * - * For concurrent master access, the application has to provide a locking - * mechanism (see section FIXME in the docs). The method takes two function - * pointers and a data value as its parameters. The arbitrary \a cb_data value - * will be passed as argument on every callback. Asynchronous master access - * (like EoE processing) is only possible if the callbacks have been set. - * - * The request_cb function must return zero, to allow another instance - * (an EoE process for example) to access the master. Non-zero means, - * that access is currently forbidden. + * For concurrent master access, i. e. if other instances than the application + * want to send and receive datagrams on the bus, the application has to + * provide a callback mechanism. This method takes two function pointers as + * its parameters. Asynchronous master access (like EoE processing) is only + * possible if the callbacks have been set. + * + * The task of the send callback (\a request_cb) is to decide, if the bus is + * currently accessible. In this case, it can call the ecrt_master_send_ext() + * method. + * + * The task of the receive callback (\a receive_cb) is to decide, if a call to + * ecrt_master_receive() is allowed and to execute it respectively. */ void ecrt_master_callbacks( ec_master_t *master, /**< EtherCAT master */ - int (*request_cb)(void *), /**< Lock request function. */ - void (*release_cb)(void *), /**< Lock release function. */ - void *cb_data /**< Arbitrary user data. */ + void (*send_cb)(ec_master_t *), /**< Datagram sending callback. */ + void (*receive_cb)(ec_master_t *) /**< Receive callback. */ ); #endif /* __KERNEL__ */ @@ -591,6 +596,15 @@ ec_master_t *master /**< EtherCAT master. */ ); +/** Sends non-application datagrams. + * + * This method has to be called in the send callback function passed via + * ecrt_master_callbacks() to allow the sending of non-application datagrams. + */ +void ecrt_master_send_ext( + ec_master_t *master /**< EtherCAT master. */ + ); + /** Reads the current master state. * * Stores the master state information in the given \a state structure. diff -r 5461fce4a2ea -r ed1a733efbc5 master/cdev.c --- a/master/cdev.c Fri Jul 10 10:40:05 2009 +0000 +++ b/master/cdev.c Mon Jul 13 15:18:28 2009 +0000 @@ -1621,6 +1621,9 @@ } } + ecrt_master_callbacks(master, ec_master_internal_send_cb, + ec_master_internal_receive_cb); + ret = ecrt_master_activate(master); if (ret < 0) return ret; diff -r 5461fce4a2ea -r ed1a733efbc5 master/ethernet.c --- a/master/ethernet.c Fri Jul 10 10:40:05 2009 +0000 +++ b/master/ethernet.c Mon Jul 13 15:18:28 2009 +0000 @@ -324,7 +324,7 @@ void ec_eoe_queue(ec_eoe_t *eoe /**< EoE handler */) { if (eoe->queue_datagram) { - ec_master_queue_datagram(eoe->slave->master, &eoe->datagram); + ec_master_queue_datagram_ext(eoe->slave->master, &eoe->datagram); eoe->queue_datagram = 0; } } diff -r 5461fce4a2ea -r ed1a733efbc5 master/master.c --- a/master/master.c Fri Jul 10 10:40:05 2009 +0000 +++ b/master/master.c Mon Jul 13 15:18:28 2009 +0000 @@ -146,6 +146,9 @@ INIT_LIST_HEAD(&master->datagram_queue); master->datagram_index = 0; + INIT_LIST_HEAD(&master->ext_datagram_queue); + init_MUTEX(&master->ext_queue_sem); + INIT_LIST_HEAD(&master->domains); master->debug_level = debug_level; @@ -163,9 +166,10 @@ #endif init_MUTEX(&master->io_sem); - master->request_cb = NULL; - master->release_cb = NULL; - master->cb_data = NULL; + master->send_cb = NULL; + master->receive_cb = NULL; + master->app_send_cb = NULL; + master->app_receive_cb = NULL; INIT_LIST_HEAD(&master->sii_requests); init_waitqueue_head(&master->sii_queue); @@ -375,22 +379,27 @@ /*****************************************************************************/ -/** Internal locking callback. - */ -int ec_master_request_cb(void *data /**< callback data */) -{ - ec_master_t *master = (ec_master_t *) data; +/** Internal sending callback. + */ +void ec_master_internal_send_cb( + ec_master_t *master /**< EtherCAT master. */ + ) +{ down(&master->io_sem); - return 0; -} - -/*****************************************************************************/ - -/** Internal unlocking callback. - */ -void ec_master_release_cb(void *data /**< callback data */) -{ - ec_master_t *master = (ec_master_t *) data; + ecrt_master_send_ext(master); + up(&master->io_sem); +} + +/*****************************************************************************/ + +/** Internal receiving callback. + */ +void ec_master_internal_receive_cb( + ec_master_t *master /**< EtherCAT master. */ + ) +{ + down(&master->io_sem); + ecrt_master_receive(master); up(&master->io_sem); } @@ -462,9 +471,8 @@ if (master->debug_level) EC_DBG("ORPHANED -> IDLE.\n"); - master->request_cb = ec_master_request_cb; - master->release_cb = ec_master_release_cb; - master->cb_data = master; + master->send_cb = ec_master_internal_send_cb; + master->receive_cb = ec_master_internal_receive_cb; master->phase = EC_IDLE; ret = ec_master_thread_start(master, ec_master_idle_thread, @@ -564,9 +572,8 @@ #endif master->phase = EC_OPERATION; - master->ext_request_cb = NULL; - master->ext_release_cb = NULL; - master->ext_cb_data = NULL; + master->app_send_cb = NULL; + master->app_receive_cb = NULL; return ret; out_allow: @@ -597,9 +604,8 @@ #endif ec_master_thread_stop(master); - master->request_cb = ec_master_request_cb; - master->release_cb = ec_master_release_cb; - master->cb_data = master; + master->send_cb = ec_master_internal_send_cb; + master->receive_cb = ec_master_internal_receive_cb; down(&master->master_sem); ec_master_clear_domains(master); @@ -646,9 +652,10 @@ /** Places a datagram in the datagram queue. */ -void ec_master_queue_datagram(ec_master_t *master, /**< EtherCAT master */ - ec_datagram_t *datagram /**< datagram */ - ) +void ec_master_queue_datagram( + ec_master_t *master, /**< EtherCAT master */ + ec_datagram_t *datagram /**< datagram */ + ) { ec_datagram_t *queued_datagram; @@ -669,6 +676,20 @@ /*****************************************************************************/ +/** Places a datagram in the non-application datagram queue. + */ +void ec_master_queue_datagram_ext( + ec_master_t *master, /**< EtherCAT master */ + ec_datagram_t *datagram /**< datagram */ + ) +{ + down(&master->ext_queue_sem); + list_add_tail(&datagram->queue, &master->ext_datagram_queue); + up(&master->ext_queue_sem); +} + +/*****************************************************************************/ + /** Sends the datagrams in the queue. * * \return 0 in case of success, else < 0 @@ -1048,8 +1069,8 @@ if (list_empty(&master->eoe_handlers)) return; - if (!master->request_cb || !master->release_cb) { - EC_WARN("No EoE processing because of missing locking callbacks!\n"); + if (!master->send_cb || !master->receive_cb) { + EC_WARN("No EoE processing because of missing callbacks!\n"); return; } @@ -1109,11 +1130,7 @@ goto schedule; // receive datagrams - if (master->request_cb(master->cb_data)) - goto schedule; - - ecrt_master_receive(master); - master->release_cb(master->cb_data); + master->receive_cb(master); // actual EoE processing sth_to_send = 0; @@ -1128,15 +1145,13 @@ } if (sth_to_send) { - // send datagrams - if (master->request_cb(master->cb_data)) { - goto schedule; - } list_for_each_entry(eoe, &master->eoe_handlers, list) { ec_eoe_queue(eoe); } - ecrt_master_send(master); - master->release_cb(master->cb_data); + // (try to) send datagrams + down(&master->ext_queue_sem); + master->send_cb(master); + up(&master->ext_queue_sem); } schedule: @@ -1641,9 +1656,9 @@ master->injection_seq_fsm = 0; master->injection_seq_rt = 0; - master->request_cb = master->ext_request_cb; - master->release_cb = master->ext_release_cb; - master->cb_data = master->ext_cb_data; + + master->send_cb = master->app_send_cb; + master->receive_cb = master->app_receive_cb; ret = ec_master_thread_start(master, ec_master_operation_thread, "EtherCAT-OP"); @@ -1735,6 +1750,21 @@ /*****************************************************************************/ +void ecrt_master_send_ext(ec_master_t *master) +{ + ec_datagram_t *datagram, *next; + + list_for_each_entry_safe(datagram, next, &master->ext_datagram_queue, + queue) { + list_del(&datagram->queue); + ec_master_queue_datagram(master, datagram); + } + + ecrt_master_send(master); +} + +/*****************************************************************************/ + /** Same as ecrt_master_slave_config(), but with ERR_PTR() return value. */ ec_slave_config_t *ecrt_master_slave_config_err(ec_master_t *master, @@ -1805,17 +1835,16 @@ /*****************************************************************************/ -void ecrt_master_callbacks(ec_master_t *master, int (*request_cb)(void *), - void (*release_cb)(void *), void *cb_data) +void ecrt_master_callbacks(ec_master_t *master, + void (*send_cb)(ec_master_t *), void (*receive_cb)(ec_master_t *)) { if (master->debug_level) - EC_DBG("ecrt_master_callbacks(master = 0x%x, request_cb = 0x%x, " - " release_cb = 0x%x, cb_data = 0x%x)\n", (u32) master, - (u32) request_cb, (u32) release_cb, (u32) cb_data); - - master->ext_request_cb = request_cb; - master->ext_release_cb = release_cb; - master->ext_cb_data = cb_data; + EC_DBG("ecrt_master_callbacks(master = 0x%x, send_cb = 0x%x, " + " receive_cb = 0x%x)\n", (u32) master, (u32) send_cb, + (u32) receive_cb); + + master->app_send_cb = send_cb; + master->app_receive_cb = receive_cb; } /*****************************************************************************/ @@ -1862,6 +1891,7 @@ EXPORT_SYMBOL(ecrt_master_create_domain); EXPORT_SYMBOL(ecrt_master_activate); EXPORT_SYMBOL(ecrt_master_send); +EXPORT_SYMBOL(ecrt_master_send_ext); EXPORT_SYMBOL(ecrt_master_receive); EXPORT_SYMBOL(ecrt_master_callbacks); EXPORT_SYMBOL(ecrt_master_slave_config); diff -r 5461fce4a2ea -r ed1a733efbc5 master/master.h --- a/master/master.h Fri Jul 10 10:40:05 2009 +0000 +++ b/master/master.h Mon Jul 13 15:18:28 2009 +0000 @@ -145,6 +145,11 @@ struct list_head datagram_queue; /**< Datagram queue. */ uint8_t datagram_index; /**< Current datagram index. */ + struct list_head ext_datagram_queue; /**< Queue for non-application + datagrams. */ + struct semaphore ext_queue_sem; /**< Semaphore protecting the \a + ext_datagram_queue. */ + struct list_head domains; /**< List of domains. */ unsigned int debug_level; /**< Master debug level. */ @@ -160,12 +165,13 @@ #endif struct semaphore io_sem; /**< Semaphore used in \a IDLE phase. */ - int (*request_cb)(void *); /**< Lock request callback. */ - void (*release_cb)(void *); /**< Lock release callback. */ - void *cb_data; /**< Data parameter of locking callbacks. */ - int (*ext_request_cb)(void *); /**< External lock request callback. */ - void (*ext_release_cb)(void *); /**< External lock release callback. */ - void *ext_cb_data; /**< Data parameter of external locking callbacks. */ + + void (*send_cb)(ec_master_t *); /**< Current send datagrams callback. */ + void (*receive_cb)(ec_master_t *); /**< Current receive datagrams callback. */ + void (*app_send_cb)(ec_master_t *); /**< Application's send datagrams + callback. */ + void (*app_receive_cb)(ec_master_t *); /**< Application's receive datagrams + callback. */ struct list_head sii_requests; /**< SII write requests. */ wait_queue_head_t sii_queue; /**< Wait queue for SII @@ -208,6 +214,7 @@ // datagram IO void ec_master_receive_datagrams(ec_master_t *, const uint8_t *, size_t); void ec_master_queue_datagram(ec_master_t *, ec_datagram_t *); +void ec_master_queue_datagram_ext(ec_master_t *, ec_datagram_t *); // misc. void ec_master_attach_slave_configs(ec_master_t *); @@ -240,6 +247,9 @@ void ec_master_calc_dc(ec_master_t *); -/*****************************************************************************/ - -#endif +void ec_master_internal_send_cb(ec_master_t *); +void ec_master_internal_receive_cb(ec_master_t *); + +/*****************************************************************************/ + +#endif