52 void ec_master_run_eoe(void *); |
52 void ec_master_run_eoe(void *); |
53 #endif |
53 #endif |
54 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
54 ssize_t ec_show_master_attribute(struct kobject *, struct attribute *, char *); |
55 void ec_master_process_watch_command(ec_master_t *); |
55 void ec_master_process_watch_command(ec_master_t *); |
56 |
56 |
57 // state functions |
|
58 void ec_master_state_start(ec_master_t *); |
|
59 void ec_master_state_slave(ec_master_t *); |
|
60 void ec_master_state_finished(ec_master_t *); |
|
61 |
|
62 /*****************************************************************************/ |
57 /*****************************************************************************/ |
63 |
58 |
64 /** \cond */ |
59 /** \cond */ |
65 |
60 |
66 EC_SYSFS_READ_ATTR(slave_count); |
61 EC_SYSFS_READ_ATTR(slave_count); |
96 unsigned int index /**< master index */ |
91 unsigned int index /**< master index */ |
97 ) |
92 ) |
98 { |
93 { |
99 EC_INFO("Initializing master %i.\n", index); |
94 EC_INFO("Initializing master %i.\n", index); |
100 |
95 |
|
96 if (!(master->workqueue = create_singlethread_workqueue("EoE"))) { |
|
97 EC_ERR("Failed to create master workqueue.\n"); |
|
98 goto out_return; |
|
99 } |
|
100 |
|
101 if (ec_fsm_init(&master->fsm, master)) goto out_free_wq; |
|
102 |
101 master->index = index; |
103 master->index = index; |
102 master->device = NULL; |
104 master->device = NULL; |
103 master->reserved = 0; |
105 master->reserved = 0; |
104 |
|
105 INIT_LIST_HEAD(&master->slaves); |
106 INIT_LIST_HEAD(&master->slaves); |
106 INIT_LIST_HEAD(&master->command_queue); |
107 INIT_LIST_HEAD(&master->command_queue); |
107 INIT_LIST_HEAD(&master->domains); |
108 INIT_LIST_HEAD(&master->domains); |
108 INIT_LIST_HEAD(&master->eoe_slaves); |
109 INIT_LIST_HEAD(&master->eoe_slaves); |
109 |
|
110 ec_command_init(&master->simple_command); |
110 ec_command_init(&master->simple_command); |
111 ec_command_init(&master->watch_command); |
|
112 |
|
113 if (!(master->workqueue = create_singlethread_workqueue("EoE"))) { |
|
114 EC_ERR("Failed to create master workqueue.\n"); |
|
115 goto out_return; |
|
116 } |
|
117 |
|
118 // init freerun work |
|
119 INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master); |
111 INIT_WORK(&master->freerun_work, ec_master_freerun, (void *) master); |
120 |
112 |
121 // init eoe timer |
113 // init eoe timer |
122 #ifdef EOE_TIMER |
114 #ifdef EOE_TIMER |
123 init_timer(&master->eoe_timer); |
115 init_timer(&master->eoe_timer); |
131 memset(&master->kobj, 0x00, sizeof(struct kobject)); |
123 memset(&master->kobj, 0x00, sizeof(struct kobject)); |
132 kobject_init(&master->kobj); |
124 kobject_init(&master->kobj); |
133 master->kobj.ktype = &ktype_ec_master; |
125 master->kobj.ktype = &ktype_ec_master; |
134 if (kobject_set_name(&master->kobj, "ethercat%i", index)) { |
126 if (kobject_set_name(&master->kobj, "ethercat%i", index)) { |
135 EC_ERR("Failed to set kobj name.\n"); |
127 EC_ERR("Failed to set kobj name.\n"); |
136 goto out_kobj_put; |
128 kobject_put(&master->kobj); |
|
129 return -1; |
137 } |
130 } |
138 |
131 |
139 ec_master_reset(master); |
132 ec_master_reset(master); |
140 return 0; |
133 return 0; |
141 |
134 |
142 out_kobj_put: |
135 out_free_wq: |
143 kobject_put(&master->kobj); |
136 destroy_workqueue(master->workqueue); |
144 out_return: |
137 out_return: |
145 return -1; |
138 return -1; |
146 } |
139 } |
147 |
140 |
148 /*****************************************************************************/ |
141 /*****************************************************************************/ |
158 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
151 ec_master_t *master = container_of(kobj, ec_master_t, kobj); |
159 |
152 |
160 EC_INFO("Clearing master %i...\n", master->index); |
153 EC_INFO("Clearing master %i...\n", master->index); |
161 |
154 |
162 ec_master_reset(master); |
155 ec_master_reset(master); |
|
156 ec_fsm_clear(&master->fsm); |
|
157 ec_command_clear(&master->simple_command); |
|
158 destroy_workqueue(master->workqueue); |
163 |
159 |
164 if (master->device) { |
160 if (master->device) { |
165 ec_device_clear(master->device); |
161 ec_device_clear(master->device); |
166 kfree(master->device); |
162 kfree(master->device); |
167 } |
163 } |
168 |
164 |
169 ec_command_clear(&master->simple_command); |
|
170 ec_command_clear(&master->watch_command); |
|
171 |
|
172 destroy_workqueue(master->workqueue); |
|
173 |
|
174 EC_INFO("Master %i cleared.\n", master->index); |
165 EC_INFO("Master %i cleared.\n", master->index); |
175 } |
166 } |
176 |
167 |
177 /*****************************************************************************/ |
168 /*****************************************************************************/ |
178 |
169 |
182 called, to free the slave list, domains etc. |
173 called, to free the slave list, domains etc. |
183 */ |
174 */ |
184 |
175 |
185 void ec_master_reset(ec_master_t *master /**< EtherCAT master */) |
176 void ec_master_reset(ec_master_t *master /**< EtherCAT master */) |
186 { |
177 { |
187 ec_slave_t *slave, *next_s; |
|
188 ec_command_t *command, *next_c; |
178 ec_command_t *command, *next_c; |
189 ec_domain_t *domain, *next_d; |
179 ec_domain_t *domain, *next_d; |
190 ec_eoe_t *eoe, *next_eoe; |
180 ec_eoe_t *eoe, *next_eoe; |
191 |
181 |
192 // stop EoE processing |
182 // stop EoE processing |
199 #endif |
189 #endif |
200 |
190 |
201 // stop free-run mode |
191 // stop free-run mode |
202 ec_master_freerun_stop(master); |
192 ec_master_freerun_stop(master); |
203 |
193 |
204 // remove all slaves |
194 ec_master_clear_slaves(master); |
205 list_for_each_entry_safe(slave, next_s, &master->slaves, list) { |
|
206 list_del(&slave->list); |
|
207 kobject_del(&slave->kobj); |
|
208 kobject_put(&slave->kobj); |
|
209 } |
|
210 master->slave_count = 0; |
|
211 |
195 |
212 // empty command queue |
196 // empty command queue |
213 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
197 list_for_each_entry_safe(command, next_c, &master->command_queue, queue) { |
214 list_del_init(&command->queue); |
198 list_del_init(&command->queue); |
215 command->state = EC_CMD_ERROR; |
199 command->state = EC_CMD_ERROR; |
231 |
215 |
232 master->command_index = 0; |
216 master->command_index = 0; |
233 master->debug_level = 0; |
217 master->debug_level = 0; |
234 master->timeout = 500; // 500us |
218 master->timeout = 500; // 500us |
235 |
219 |
236 master->slaves_responding = 0; |
|
237 master->slave_states = EC_SLAVE_STATE_UNKNOWN; |
|
238 |
|
239 master->stats.timeouts = 0; |
220 master->stats.timeouts = 0; |
240 master->stats.delayed = 0; |
221 master->stats.delayed = 0; |
241 master->stats.corrupted = 0; |
222 master->stats.corrupted = 0; |
242 master->stats.unmatched = 0; |
223 master->stats.unmatched = 0; |
243 master->stats.t_last = 0; |
224 master->stats.t_last = 0; |
245 master->mode = EC_MASTER_MODE_IDLE; |
226 master->mode = EC_MASTER_MODE_IDLE; |
246 |
227 |
247 master->request_cb = NULL; |
228 master->request_cb = NULL; |
248 master->release_cb = NULL; |
229 master->release_cb = NULL; |
249 master->cb_data = NULL; |
230 master->cb_data = NULL; |
|
231 |
|
232 ec_fsm_reset(&master->fsm); |
|
233 } |
|
234 |
|
235 /*****************************************************************************/ |
|
236 |
|
237 /** |
|
238 Clears all slaves. |
|
239 */ |
|
240 |
|
241 void ec_master_clear_slaves(ec_master_t *master) |
|
242 { |
|
243 ec_slave_t *slave, *next_slave; |
|
244 |
|
245 list_for_each_entry_safe(slave, next_slave, &master->slaves, list) { |
|
246 list_del(&slave->list); |
|
247 kobject_del(&slave->kobj); |
|
248 kobject_put(&slave->kobj); |
|
249 } |
|
250 master->slave_count = 0; |
250 } |
251 } |
251 |
252 |
252 /*****************************************************************************/ |
253 /*****************************************************************************/ |
253 |
254 |
254 /** |
255 /** |
514 \return 0 in case of success, else < 0 |
515 \return 0 in case of success, else < 0 |
515 */ |
516 */ |
516 |
517 |
517 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */) |
518 int ec_master_bus_scan(ec_master_t *master /**< EtherCAT master */) |
518 { |
519 { |
519 ec_slave_t *slave, *next; |
520 ec_slave_t *slave; |
520 ec_slave_ident_t *ident; |
521 ec_slave_ident_t *ident; |
|
522 ec_command_t *command; |
521 unsigned int i; |
523 unsigned int i; |
522 ec_command_t *command; |
|
523 uint16_t coupler_index, coupler_subindex; |
524 uint16_t coupler_index, coupler_subindex; |
524 uint16_t reverse_coupler_index, current_coupler_index; |
525 uint16_t reverse_coupler_index, current_coupler_index; |
525 |
526 |
526 if (!list_empty(&master->slaves)) { |
527 if (!list_empty(&master->slaves)) { |
527 EC_ERR("Slave scan already done!\n"); |
528 EC_ERR("Slave scan already done!\n"); |
538 |
539 |
539 if (!master->slave_count) return 0; |
540 if (!master->slave_count) return 0; |
540 |
541 |
541 // init slaves |
542 // init slaves |
542 for (i = 0; i < master->slave_count; i++) { |
543 for (i = 0; i < master->slave_count; i++) { |
543 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { |
544 if (!(slave = |
|
545 (ec_slave_t *) kmalloc(sizeof(ec_slave_t), GFP_KERNEL))) { |
544 EC_ERR("Failed to allocate slave %i!\n", i); |
546 EC_ERR("Failed to allocate slave %i!\n", i); |
545 goto out_free; |
547 goto out_free; |
546 } |
548 } |
547 |
549 |
548 if (ec_slave_init(slave, master, i, i + 1)) goto out_free; |
550 if (ec_slave_init(slave, master, i, i + 1)) goto out_free; |
589 } |
591 } |
590 |
592 |
591 if (!slave->type) { |
593 if (!slave->type) { |
592 EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" |
594 EC_WARN("Unknown slave device (vendor 0x%08X, code 0x%08X) at" |
593 " position %i.\n", slave->sii_vendor_id, |
595 " position %i.\n", slave->sii_vendor_id, |
594 slave->sii_product_code, i); |
596 slave->sii_product_code, slave->ring_position); |
595 } |
597 } |
596 else if (slave->type->special == EC_TYPE_BUS_COUPLER) { |
598 else if (slave->type->special == EC_TYPE_BUS_COUPLER) { |
597 if (slave->sii_alias) |
599 if (slave->sii_alias) |
598 current_coupler_index = reverse_coupler_index--; |
600 current_coupler_index = reverse_coupler_index--; |
599 else |
601 else |
666 } |
664 } |
667 |
665 |
668 EC_INFO("Starting Free-Run mode.\n"); |
666 EC_INFO("Starting Free-Run mode.\n"); |
669 |
667 |
670 master->mode = EC_MASTER_MODE_FREERUN; |
668 master->mode = EC_MASTER_MODE_FREERUN; |
671 |
669 ec_fsm_reset(&master->fsm); |
672 if (master->watch_command.state == EC_CMD_INIT) { |
670 queue_delayed_work(master->workqueue, &master->freerun_work, HZ / 100); |
673 if (ec_command_brd(&master->watch_command, 0x130, 2)) { |
|
674 EC_ERR("Failed to allocate watchdog command!\n"); |
|
675 return; |
|
676 } |
|
677 } |
|
678 |
|
679 master->freerun_state = ec_master_state_start; |
|
680 |
|
681 ecrt_master_prepare_async_io(master); /** \todo necessary? */ |
|
682 |
|
683 queue_delayed_work(master->workqueue, &master->freerun_work, HZ); |
|
684 } |
671 } |
685 |
672 |
686 /*****************************************************************************/ |
673 /*****************************************************************************/ |
687 |
674 |
688 /** |
675 /** |
689 Stops the Free-Run mode. |
676 Stops the Free-Run mode. |
690 */ |
677 */ |
691 |
678 |
692 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
679 void ec_master_freerun_stop(ec_master_t *master /**< EtherCAT master */) |
693 { |
680 { |
694 ec_slave_t *slave, *next_slave; |
|
695 |
|
696 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
681 if (master->mode != EC_MASTER_MODE_FREERUN) return; |
697 |
682 |
698 EC_INFO("Stopping Free-Run mode.\n"); |
683 EC_INFO("Stopping Free-Run mode.\n"); |
699 |
684 |
700 if (!cancel_delayed_work(&master->freerun_work)) { |
685 if (!cancel_delayed_work(&master->freerun_work)) { |
701 flush_workqueue(master->workqueue); |
686 flush_workqueue(master->workqueue); |
702 } |
687 } |
703 |
688 |
704 // remove slaves |
689 ec_master_clear_slaves(master); |
705 list_for_each_entry_safe(slave, next_slave, &master->slaves, list) { |
|
706 list_del(&slave->list); |
|
707 kobject_del(&slave->kobj); |
|
708 kobject_put(&slave->kobj); |
|
709 } |
|
710 |
|
711 master->mode = EC_MASTER_MODE_IDLE; |
690 master->mode = EC_MASTER_MODE_IDLE; |
712 } |
691 } |
713 |
692 |
714 /*****************************************************************************/ |
693 /*****************************************************************************/ |
715 |
694 |
718 */ |
697 */ |
719 |
698 |
720 void ec_master_freerun(void *data /**< master pointer */) |
699 void ec_master_freerun(void *data /**< master pointer */) |
721 { |
700 { |
722 ec_master_t *master = (ec_master_t *) data; |
701 ec_master_t *master = (ec_master_t *) data; |
|
702 unsigned long delay; |
723 |
703 |
724 ecrt_master_async_receive(master); |
704 ecrt_master_async_receive(master); |
725 |
705 |
726 // watchdog command |
|
727 ec_master_process_watch_command(master); |
|
728 |
|
729 if (master->watch_command.working_counter != master->slave_count) { |
|
730 master->slave_count = master->watch_command.working_counter; |
|
731 EC_INFO("Freerun: Topology change detected.\n"); |
|
732 // reset freerun state machine |
|
733 master->freerun_state = ec_master_state_start; |
|
734 } |
|
735 |
|
736 ec_master_queue_command(master, &master->watch_command); |
|
737 |
|
738 // execute freerun state machine |
706 // execute freerun state machine |
739 master->freerun_state(master); |
707 ec_fsm_execute(&master->fsm); |
740 |
708 |
741 ecrt_master_async_send(master); |
709 ecrt_master_async_send(master); |
742 |
710 |
743 queue_delayed_work(master->workqueue, &master->freerun_work, HZ); |
711 delay = HZ / 100; |
744 } |
712 if (ec_fsm_idle(&master->fsm)) delay = HZ; |
745 |
713 queue_delayed_work(master->workqueue, &master->freerun_work, delay); |
746 /*****************************************************************************/ |
|
747 |
|
748 /** |
|
749 Free-Run state: Start. |
|
750 Processes new slave count. |
|
751 */ |
|
752 |
|
753 void ec_master_state_start(ec_master_t *master /**< EtherCAT master*/) |
|
754 { |
|
755 ec_slave_t *slave, *next_slave; |
|
756 unsigned int i; |
|
757 |
|
758 // remove slaves |
|
759 list_for_each_entry_safe(slave, next_slave, &master->slaves, list) { |
|
760 list_del(&slave->list); |
|
761 kobject_del(&slave->kobj); |
|
762 kobject_put(&slave->kobj); |
|
763 } |
|
764 |
|
765 if (!master->slave_count) { |
|
766 // no slaves present -> finish state machine. |
|
767 master->freerun_state = ec_master_state_finished; |
|
768 EC_INFO("Freerun: No slaves found.\n"); |
|
769 return; |
|
770 } |
|
771 |
|
772 // init slaves |
|
773 for (i = 0; i < master->slave_count; i++) { |
|
774 if (!(slave = (ec_slave_t *) kmalloc(sizeof(ec_slave_t), |
|
775 GFP_KERNEL))) { |
|
776 EC_ERR("Failed to allocate slave %i!\n", i); |
|
777 master->freerun_state = ec_master_state_finished; |
|
778 return; |
|
779 } |
|
780 |
|
781 if (ec_slave_init(slave, master, i, i + 1)) { |
|
782 master->freerun_state = ec_master_state_finished; |
|
783 return; |
|
784 } |
|
785 |
|
786 if (kobject_add(&slave->kobj)) { |
|
787 EC_ERR("Failed to add kobject.\n"); |
|
788 kobject_put(&slave->kobj); // free |
|
789 master->freerun_state = ec_master_state_finished; |
|
790 return; |
|
791 } |
|
792 |
|
793 list_add_tail(&slave->list, &master->slaves); |
|
794 } |
|
795 |
|
796 // begin scanning of slaves |
|
797 master->freerun_slave = list_entry(master->slaves.next, ec_slave_t, list); |
|
798 master->freerun_state = ec_master_state_slave; |
|
799 } |
|
800 |
|
801 /*****************************************************************************/ |
|
802 |
|
803 /** |
|
804 Free-Run state: Get Slave. |
|
805 Executes the sub-statemachine of a slave. |
|
806 */ |
|
807 |
|
808 void ec_master_state_slave(ec_master_t *master /**< EtherCAT master*/) |
|
809 { |
|
810 master->freerun_state = ec_master_state_finished; |
|
811 } |
|
812 |
|
813 /*****************************************************************************/ |
|
814 |
|
815 /** |
|
816 Free-Run state: Finished. |
|
817 End state of the state machine. Does nothing. |
|
818 */ |
|
819 |
|
820 void ec_master_state_finished(ec_master_t *master /**< EtherCAT master*/) |
|
821 { |
|
822 return; |
|
823 } |
714 } |
824 |
715 |
825 /*****************************************************************************/ |
716 /*****************************************************************************/ |
826 |
717 |
827 /** |
718 /** |
912 } |
803 } |
913 |
804 |
914 /*****************************************************************************/ |
805 /*****************************************************************************/ |
915 |
806 |
916 /** |
807 /** |
917 Processes the watchdog command. |
|
918 */ |
|
919 |
|
920 void ec_master_process_watch_command(ec_master_t *master |
|
921 /**< EtherCAT master */ |
|
922 ) |
|
923 { |
|
924 unsigned int first; |
|
925 |
|
926 if (unlikely(master->watch_command.state == EC_CMD_INIT)) return; |
|
927 |
|
928 first = 1; |
|
929 |
|
930 if (master->watch_command.working_counter != master->slaves_responding || |
|
931 master->watch_command.data[0] != master->slave_states) |
|
932 { |
|
933 master->slaves_responding = master->watch_command.working_counter; |
|
934 master->slave_states = master->watch_command.data[0]; |
|
935 |
|
936 EC_INFO("%i slave%s responding (", master->slaves_responding, |
|
937 master->slaves_responding == 1 ? "" : "s"); |
|
938 |
|
939 if (master->slave_states & EC_SLAVE_STATE_INIT) { |
|
940 printk("INIT"); |
|
941 first = 0; |
|
942 } |
|
943 if (master->slave_states & EC_SLAVE_STATE_PREOP) { |
|
944 if (!first) printk(", "); |
|
945 printk("PREOP"); |
|
946 first = 0; |
|
947 } |
|
948 if (master->slave_states & EC_SLAVE_STATE_SAVEOP) { |
|
949 if (!first) printk(", "); |
|
950 printk("SAVEOP"); |
|
951 first = 0; |
|
952 } |
|
953 if (master->slave_states & EC_SLAVE_STATE_OP) { |
|
954 if (!first) printk(", "); |
|
955 printk("OP"); |
|
956 } |
|
957 printk(")\n"); |
|
958 } |
|
959 } |
|
960 |
|
961 /*****************************************************************************/ |
|
962 |
|
963 /** |
|
964 Does the Ethernet-over-EtherCAT processing. |
808 Does the Ethernet-over-EtherCAT processing. |
965 */ |
809 */ |
966 |
810 |
967 #ifdef EOE_TIMER |
811 #ifdef EOE_TIMER |
968 void ec_master_run_eoe(unsigned long data /**< master pointer */) |
812 void ec_master_run_eoe(unsigned long data /**< master pointer */) |
1066 uint32_t domain_offset; |
910 uint32_t domain_offset; |
1067 ec_domain_t *domain; |
911 ec_domain_t *domain; |
1068 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
912 ec_eeprom_sync_t *eeprom_sync, mbox_sync; |
1069 |
913 |
1070 command = &master->simple_command; |
914 command = &master->simple_command; |
1071 |
|
1072 if (master->watch_command.state == EC_CMD_INIT) { |
|
1073 if (ec_command_brd(&master->watch_command, 0x130, 2)) { |
|
1074 EC_ERR("Failed to allocate watchdog command!\n"); |
|
1075 return -1; |
|
1076 } |
|
1077 } |
|
1078 |
915 |
1079 // allocate all domains |
916 // allocate all domains |
1080 domain_offset = 0; |
917 domain_offset = 0; |
1081 list_for_each_entry(domain, &master->domains, list) { |
918 list_for_each_entry(domain, &master->domains, list) { |
1082 if (ec_domain_alloc(domain, domain_offset)) { |
919 if (ec_domain_alloc(domain, domain_offset)) { |