53 #include "datagram.h" |
53 #include "datagram.h" |
54 #include "ethernet.h" |
54 #include "ethernet.h" |
55 |
55 |
56 /*****************************************************************************/ |
56 /*****************************************************************************/ |
57 |
57 |
58 void ec_master_freerun(void *); |
58 void ec_master_idle(void *); |
59 void ec_master_eoe_run(unsigned long); |
59 void ec_master_eoe_run(unsigned long); |
60 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
60 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
61 ssize_t ec_store_master_attribute(struct kobject *, struct attribute *, |
61 ssize_t ec_store_master_attribute(struct kobject *, struct attribute *, |
62 const char *, size_t); |
62 const char *, size_t); |
63 |
63 |
114 INIT_LIST_HEAD(&master->slaves); |
114 INIT_LIST_HEAD(&master->slaves); |
115 INIT_LIST_HEAD(&master->datagram_queue); |
115 INIT_LIST_HEAD(&master->datagram_queue); |
116 INIT_LIST_HEAD(&master->domains); |
116 INIT_LIST_HEAD(&master->domains); |
117 INIT_LIST_HEAD(&master->eoe_handlers); |
117 INIT_LIST_HEAD(&master->eoe_handlers); |
118 ec_datagram_init(&master->simple_datagram); |
118 ec_datagram_init(&master->simple_datagram); |
119 INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master); |
119 INIT_WORK(&master->idle_work, ec_master_idle, (void *) master); |
120 init_timer(&master->eoe_timer); |
120 init_timer(&master->eoe_timer); |
121 master->eoe_timer.function = ec_master_eoe_run; |
121 master->eoe_timer.function = ec_master_eoe_run; |
122 master->eoe_timer.data = (unsigned long) master; |
122 master->eoe_timer.data = (unsigned long) master; |
123 master->internal_lock = SPIN_LOCK_UNLOCKED; |
123 master->internal_lock = SPIN_LOCK_UNLOCKED; |
124 master->eoe_running = 0; |
124 master->eoe_running = 0; |
216 { |
216 { |
217 ec_datagram_t *datagram, *next_c; |
217 ec_datagram_t *datagram, *next_c; |
218 ec_domain_t *domain, *next_d; |
218 ec_domain_t *domain, *next_d; |
219 |
219 |
220 ec_master_eoe_stop(master); |
220 ec_master_eoe_stop(master); |
221 ec_master_freerun_stop(master); |
221 ec_master_idle_stop(master); |
222 ec_master_clear_slaves(master); |
222 ec_master_clear_slaves(master); |
223 |
223 |
224 // empty datagram queue |
224 // empty datagram queue |
225 list_for_each_entry_safe(datagram, next_c, |
225 list_for_each_entry_safe(datagram, next_c, |
226 &master->datagram_queue, queue) { |
226 &master->datagram_queue, queue) { |
673 } |
673 } |
674 |
674 |
675 /*****************************************************************************/ |
675 /*****************************************************************************/ |
676 |
676 |
677 /** |
677 /** |
678 Starts the Free-Run mode. |
678 Starts the Idle mode. |
679 */ |
679 */ |
680 |
680 |
681 void ec_master_freerun_start(ec_master_t *master /**< EtherCAT master */) |
681 void ec_master_idle_start(ec_master_t *master /**< EtherCAT master */) |
682 { |
682 { |
683 if (master->mode == EC_MASTER_MODE_FREERUN) return; |
683 if (master->mode == EC_MASTER_MODE_IDLE) return; |
684 |
684 |
685 if (master->mode == EC_MASTER_MODE_RUNNING) { |
685 if (master->mode == EC_MASTER_MODE_RUNNING) { |
686 EC_ERR("ec_master_freerun_start: Master already running!\n"); |
686 EC_ERR("ec_master_idle_start: Master already running!\n"); |
687 return; |
687 return; |
688 } |
688 } |
689 |
689 |
690 EC_INFO("Starting Free-Run mode.\n"); |
690 EC_INFO("Starting Idle mode.\n"); |
691 |
691 |
692 master->mode = EC_MASTER_MODE_FREERUN; |
692 master->mode = EC_MASTER_MODE_IDLE; |
693 ec_fsm_reset(&master->fsm); |
693 ec_fsm_reset(&master->fsm); |
694 queue_delayed_work(master->workqueue, &master->freerun_work, 1); |
694 queue_delayed_work(master->workqueue, &master->idle_work, 1); |
695 } |
695 } |
696 |
696 |
697 /*****************************************************************************/ |
697 /*****************************************************************************/ |
698 |
698 |
699 /** |
699 /** |
700 Stops the Free-Run mode. |
700 Stops the Idle mode. |
701 */ |
701 */ |
702 |
702 |
703 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
703 void ec_master_idle_stop(ec_master_t *master /**< EtherCAT master */) |
704 { |
704 { |
705 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
705 if (master->mode != EC_MASTER_MODE_IDLE) return; |
706 |
706 |
707 ec_master_eoe_stop(master); |
707 ec_master_eoe_stop(master); |
708 |
708 |
709 EC_INFO("Stopping Free-Run mode.\n"); |
709 EC_INFO("Stopping Idle mode.\n"); |
710 master->mode = EC_MASTER_MODE_ORPHANED; |
710 master->mode = EC_MASTER_MODE_ORPHANED; // this is important for the |
711 |
711 // IDLE work function to not |
712 if (!cancel_delayed_work(&master->freerun_work)) { |
712 // queue itself again |
|
713 |
|
714 if (!cancel_delayed_work(&master->idle_work)) { |
713 flush_workqueue(master->workqueue); |
715 flush_workqueue(master->workqueue); |
714 } |
716 } |
715 |
717 |
716 ec_master_clear_slaves(master); |
718 ec_master_clear_slaves(master); |
717 } |
719 } |
718 |
720 |
719 /*****************************************************************************/ |
721 /*****************************************************************************/ |
720 |
722 |
721 /** |
723 /** |
722 Free-Run mode function. |
724 Idle mode function. |
723 */ |
725 */ |
724 |
726 |
725 void ec_master_freerun(void *data /**< master pointer */) |
727 void ec_master_idle(void *data /**< master pointer */) |
726 { |
728 { |
727 ec_master_t *master = (ec_master_t *) data; |
729 ec_master_t *master = (ec_master_t *) data; |
728 |
730 |
729 // aquire master lock |
731 // aquire master lock |
730 spin_lock_bh(&master->internal_lock); |
732 spin_lock_bh(&master->internal_lock); |
737 ecrt_master_async_send(master); |
739 ecrt_master_async_send(master); |
738 |
740 |
739 // release master lock |
741 // release master lock |
740 spin_unlock_bh(&master->internal_lock); |
742 spin_unlock_bh(&master->internal_lock); |
741 |
743 |
742 if (master->mode == EC_MASTER_MODE_FREERUN) |
744 if (master->mode == EC_MASTER_MODE_IDLE) |
743 queue_delayed_work(master->workqueue, &master->freerun_work, 1); |
745 queue_delayed_work(master->workqueue, &master->idle_work, 1); |
744 } |
746 } |
745 |
747 |
746 /*****************************************************************************/ |
748 /*****************************************************************************/ |
747 |
749 |
748 /** |
750 /** |
843 } |
845 } |
844 else if (attr == &attr_mode) { |
846 else if (attr == &attr_mode) { |
845 switch (master->mode) { |
847 switch (master->mode) { |
846 case EC_MASTER_MODE_ORPHANED: |
848 case EC_MASTER_MODE_ORPHANED: |
847 return sprintf(buffer, "ORPHANED\n"); |
849 return sprintf(buffer, "ORPHANED\n"); |
848 case EC_MASTER_MODE_FREERUN: |
850 case EC_MASTER_MODE_IDLE: |
849 return sprintf(buffer, "FREERUN\n"); |
851 return sprintf(buffer, "IDLE\n"); |
850 case EC_MASTER_MODE_RUNNING: |
852 case EC_MASTER_MODE_RUNNING: |
851 return sprintf(buffer, "RUNNING\n"); |
853 return sprintf(buffer, "RUNNING\n"); |
852 } |
854 } |
853 } |
855 } |
854 else if (attr == &attr_debug_level) { |
856 else if (attr == &attr_debug_level) { |