6 * |
6 * |
7 * This file is part of the IgH EtherCAT Master. |
7 * This file is part of the IgH EtherCAT Master. |
8 * |
8 * |
9 * The IgH EtherCAT Master is free software; you can redistribute it |
9 * The IgH EtherCAT Master is free software; you can redistribute it |
10 * and/or modify it under the terms of the GNU General Public License |
10 * and/or modify it under the terms of the GNU General Public License |
11 * as published by the Free Software Foundation; version 2 of the License. |
11 * as published by the Free Software Foundation; either version 2 of the |
|
12 * License, or (at your option) any later version. |
12 * |
13 * |
13 * The IgH EtherCAT Master is distributed in the hope that it will be |
14 * The IgH EtherCAT Master is distributed in the hope that it will be |
14 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 * GNU General Public License for more details. |
17 * GNU General Public License for more details. |
17 * |
18 * |
18 * You should have received a copy of the GNU General Public License |
19 * You should have received a copy of the GNU General Public License |
19 * along with the IgH EtherCAT Master; if not, write to the Free Software |
20 * along with the IgH EtherCAT Master; if not, write to the Free Software |
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
21 * |
22 * |
|
23 * The right to use EtherCAT Technology is granted and comes free of |
|
24 * charge under condition of compatibility of product made by |
|
25 * Licensee. People intending to distribute/sell products based on the |
|
26 * code, have to sign an agreement to guarantee that products using |
|
27 * software based on IgH EtherCAT master stay compatible with the actual |
|
28 * EtherCAT specification (which are released themselves as an open |
|
29 * standard) as the (only) precondition to have the right to use EtherCAT |
|
30 * Technology, IP and trade marks. |
|
31 * |
22 *****************************************************************************/ |
32 *****************************************************************************/ |
23 |
33 |
24 /** |
34 /** |
25 \file |
35 \file |
26 EtherCAT slave methods. |
36 EtherCAT slave methods. |
36 #include "command.h" |
46 #include "command.h" |
37 #include "master.h" |
47 #include "master.h" |
38 |
48 |
39 /*****************************************************************************/ |
49 /*****************************************************************************/ |
40 |
50 |
|
51 extern const ec_code_msg_t al_status_messages[]; |
|
52 |
|
53 /*****************************************************************************/ |
|
54 |
41 int ec_slave_fetch_categories(ec_slave_t *); |
55 int ec_slave_fetch_categories(ec_slave_t *); |
42 int ec_slave_fetch_strings(ec_slave_t *, const uint8_t *); |
|
43 int ec_slave_fetch_general(ec_slave_t *, const uint8_t *); |
|
44 int ec_slave_fetch_sync(ec_slave_t *, const uint8_t *, size_t); |
|
45 int ec_slave_fetch_pdo(ec_slave_t *, const uint8_t *, size_t, ec_pdo_type_t); |
|
46 int ec_slave_locate_string(ec_slave_t *, unsigned int, char **); |
|
47 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *); |
56 ssize_t ec_show_slave_attribute(struct kobject *, struct attribute *, char *); |
|
57 ssize_t ec_store_slave_attribute(struct kobject *, struct attribute *, |
|
58 const char *, size_t); |
48 |
59 |
49 /*****************************************************************************/ |
60 /*****************************************************************************/ |
50 |
61 |
51 /** \cond */ |
62 /** \cond */ |
52 |
63 |
53 EC_SYSFS_READ_ATTR(ring_position); |
64 EC_SYSFS_READ_ATTR(ring_position); |
54 EC_SYSFS_READ_ATTR(coupler_address); |
65 EC_SYSFS_READ_ATTR(coupler_address); |
55 EC_SYSFS_READ_ATTR(vendor_name); |
66 EC_SYSFS_READ_ATTR(vendor_name); |
56 EC_SYSFS_READ_ATTR(product_name); |
67 EC_SYSFS_READ_ATTR(product_name); |
57 EC_SYSFS_READ_ATTR(product_desc); |
68 EC_SYSFS_READ_ATTR(product_desc); |
|
69 EC_SYSFS_READ_ATTR(sii_name); |
58 EC_SYSFS_READ_ATTR(type); |
70 EC_SYSFS_READ_ATTR(type); |
|
71 EC_SYSFS_READ_WRITE_ATTR(state); |
59 |
72 |
60 static struct attribute *def_attrs[] = { |
73 static struct attribute *def_attrs[] = { |
61 &attr_ring_position, |
74 &attr_ring_position, |
62 &attr_coupler_address, |
75 &attr_coupler_address, |
63 &attr_vendor_name, |
76 &attr_vendor_name, |
64 &attr_product_name, |
77 &attr_product_name, |
65 &attr_product_desc, |
78 &attr_product_desc, |
|
79 &attr_sii_name, |
66 &attr_type, |
80 &attr_type, |
|
81 &attr_state, |
67 NULL, |
82 NULL, |
68 }; |
83 }; |
69 |
84 |
70 static struct sysfs_ops sysfs_ops = { |
85 static struct sysfs_ops sysfs_ops = { |
71 .show = &ec_show_slave_attribute, |
86 .show = ec_show_slave_attribute, |
72 .store = NULL |
87 .store = ec_store_slave_attribute |
73 }; |
88 }; |
74 |
89 |
75 static struct kobj_type ktype_ec_slave = { |
90 static struct kobj_type ktype_ec_slave = { |
76 .release = ec_slave_clear, |
91 .release = ec_slave_clear, |
77 .sysfs_ops = &sysfs_ops, |
92 .sysfs_ops = &sysfs_ops, |
78 .default_attrs = def_attrs |
93 .default_attrs = def_attrs |
79 }; |
94 }; |
80 |
95 |
81 /** \endcond */ |
96 /** \endcond */ |
82 |
|
83 /*****************************************************************************/ |
|
84 |
|
85 const ec_code_msg_t al_status_messages[]; |
|
86 |
97 |
87 /*****************************************************************************/ |
98 /*****************************************************************************/ |
88 |
99 |
89 /** |
100 /** |
90 Slave constructor. |
101 Slave constructor. |
132 slave->sii_tx_mailbox_size = 0; |
143 slave->sii_tx_mailbox_size = 0; |
133 slave->sii_mailbox_protocols = 0; |
144 slave->sii_mailbox_protocols = 0; |
134 slave->type = NULL; |
145 slave->type = NULL; |
135 slave->registered = 0; |
146 slave->registered = 0; |
136 slave->fmmu_count = 0; |
147 slave->fmmu_count = 0; |
|
148 slave->eeprom_group = NULL; |
|
149 slave->eeprom_image = NULL; |
|
150 slave->eeprom_order = NULL; |
137 slave->eeprom_name = NULL; |
151 slave->eeprom_name = NULL; |
138 slave->eeprom_group = NULL; |
152 slave->requested_state = EC_SLAVE_STATE_UNKNOWN; |
139 slave->eeprom_desc = NULL; |
153 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
|
154 slave->state_error = 0; |
|
155 slave->online = 1; |
140 |
156 |
141 ec_command_init(&slave->mbox_command); |
157 ec_command_init(&slave->mbox_command); |
142 |
158 |
143 INIT_LIST_HEAD(&slave->eeprom_strings); |
159 INIT_LIST_HEAD(&slave->eeprom_strings); |
144 INIT_LIST_HEAD(&slave->eeprom_syncs); |
160 INIT_LIST_HEAD(&slave->eeprom_syncs); |
822 udelay(100); // wait a little bit... |
842 udelay(100); // wait a little bit... |
823 |
843 |
824 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
844 if (ec_command_nprd(command, slave->station_address, 0x0130, 2)) |
825 return; |
845 return; |
826 if (unlikely(ec_master_simple_io(slave->master, command))) { |
846 if (unlikely(ec_master_simple_io(slave->master, command))) { |
|
847 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
827 EC_WARN("Acknowledge checking failed on slave %i!\n", |
848 EC_WARN("Acknowledge checking failed on slave %i!\n", |
828 slave->ring_position); |
849 slave->ring_position); |
829 return; |
850 return; |
830 } |
851 } |
831 |
852 |
832 end = get_cycles(); |
853 end = get_cycles(); |
833 |
854 |
834 if (likely(EC_READ_U8(command->data) == state)) { |
855 if (likely(EC_READ_U8(command->data) == state)) { |
|
856 slave->current_state = state; |
835 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state, |
857 EC_INFO("Acknowleged state 0x%02X on slave %i.\n", state, |
836 slave->ring_position); |
858 slave->ring_position); |
837 return; |
859 return; |
838 } |
860 } |
839 |
861 |
840 if (unlikely((end - start) >= timeout)) { |
862 if (unlikely((end - start) >= timeout)) { |
|
863 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
841 EC_WARN("Failed to acknowledge state 0x%02X on slave %i" |
864 EC_WARN("Failed to acknowledge state 0x%02X on slave %i" |
842 " - Timeout!\n", state, slave->ring_position); |
865 " - Timeout!\n", state, slave->ring_position); |
843 return; |
866 return; |
844 } |
867 } |
845 } |
868 } |
895 ec_command_t *command; |
918 ec_command_t *command; |
896 cycles_t start, end, timeout; |
919 cycles_t start, end, timeout; |
897 |
920 |
898 command = &slave->master->simple_command; |
921 command = &slave->master->simple_command; |
899 |
922 |
|
923 slave->requested_state = state; |
|
924 |
900 if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1; |
925 if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1; |
901 EC_WRITE_U16(command->data, state); |
926 EC_WRITE_U16(command->data, state); |
902 if (unlikely(ec_master_simple_io(slave->master, command))) { |
927 if (unlikely(ec_master_simple_io(slave->master, command))) { |
903 EC_ERR("Failed to set state 0x%02X on slave %i!\n", |
928 EC_ERR("Failed to set state 0x%02X on slave %i!\n", |
904 state, slave->ring_position); |
929 state, slave->ring_position); |
924 |
950 |
925 if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error |
951 if (unlikely(EC_READ_U8(command->data) & 0x10)) { // state change error |
926 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
952 EC_ERR("Failed to set state 0x%02X - Slave %i refused state change" |
927 " (code 0x%02X)!\n", state, slave->ring_position, |
953 " (code 0x%02X)!\n", state, slave->ring_position, |
928 EC_READ_U8(command->data)); |
954 EC_READ_U8(command->data)); |
929 state = EC_READ_U8(command->data) & 0x0F; |
955 slave->current_state = EC_READ_U8(command->data); |
|
956 state = slave->current_state & 0x0F; |
930 ec_slave_read_al_status_code(slave); |
957 ec_slave_read_al_status_code(slave); |
931 ec_slave_state_ack(slave, state); |
958 ec_slave_state_ack(slave, state); |
932 return -1; |
959 return -1; |
933 } |
960 } |
934 |
961 |
935 if (likely(EC_READ_U8(command->data) == (state & 0x0F))) |
962 if (likely(EC_READ_U8(command->data) == (state & 0x0F))) { |
|
963 slave->current_state = state; |
936 return 0; // state change successful |
964 return 0; // state change successful |
|
965 } |
937 |
966 |
938 if (unlikely((end - start) >= timeout)) { |
967 if (unlikely((end - start) >= timeout)) { |
|
968 slave->current_state = EC_SLAVE_STATE_UNKNOWN; |
939 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
969 EC_ERR("Failed to check state 0x%02X of slave %i - Timeout!\n", |
940 state, slave->ring_position); |
970 state, slave->ring_position); |
941 return -1; |
971 return -1; |
942 } |
972 } |
943 } |
973 } |
1098 EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
1128 EC_INFO(" Vendor-ID: 0x%08X, Product code: 0x%08X\n", |
1099 slave->sii_vendor_id, slave->sii_product_code); |
1129 slave->sii_vendor_id, slave->sii_product_code); |
1100 EC_INFO(" Revision number: 0x%08X, Serial number: 0x%08X\n", |
1130 EC_INFO(" Revision number: 0x%08X, Serial number: 0x%08X\n", |
1101 slave->sii_revision_number, slave->sii_serial_number); |
1131 slave->sii_revision_number, slave->sii_serial_number); |
1102 |
1132 |
|
1133 if (slave->eeprom_group) |
|
1134 EC_INFO(" Group: %s\n", slave->eeprom_group); |
|
1135 if (slave->eeprom_image) |
|
1136 EC_INFO(" Image: %s\n", slave->eeprom_image); |
|
1137 if (slave->eeprom_order) |
|
1138 EC_INFO(" Order#: %s\n", slave->eeprom_order); |
1103 if (slave->eeprom_name) |
1139 if (slave->eeprom_name) |
1104 EC_INFO(" Name: %s\n", slave->eeprom_name); |
1140 EC_INFO(" Name: %s\n", slave->eeprom_name); |
1105 if (slave->eeprom_group) |
|
1106 EC_INFO(" Group: %s\n", slave->eeprom_group); |
|
1107 if (slave->eeprom_desc) |
|
1108 EC_INFO(" Description: %s\n", slave->eeprom_desc); |
|
1109 |
1141 |
1110 if (!list_empty(&slave->eeprom_syncs)) { |
1142 if (!list_empty(&slave->eeprom_syncs)) { |
1111 EC_INFO(" Sync-Managers:\n"); |
1143 EC_INFO(" Sync-Managers:\n"); |
1112 list_for_each_entry(sync, &slave->eeprom_syncs, list) { |
1144 list_for_each_entry(sync, &slave->eeprom_syncs, list) { |
1113 EC_INFO(" %i: 0x%04X, length %i, control 0x%02X, %s\n", |
1145 EC_INFO(" %i: 0x%04X, length %i, control 0x%02X, %s\n", |
1235 return sprintf(buffer, "%s\n", slave->type->product_name); |
1266 return sprintf(buffer, "%s\n", slave->type->product_name); |
1236 } |
1267 } |
1237 else if (attr == &attr_product_desc) { |
1268 else if (attr == &attr_product_desc) { |
1238 if (slave->type) |
1269 if (slave->type) |
1239 return sprintf(buffer, "%s\n", slave->type->description); |
1270 return sprintf(buffer, "%s\n", slave->type->description); |
|
1271 } |
|
1272 else if (attr == &attr_sii_name) { |
|
1273 if (slave->eeprom_name) |
|
1274 return sprintf(buffer, "%s\n", slave->eeprom_name); |
1240 } |
1275 } |
1241 else if (attr == &attr_type) { |
1276 else if (attr == &attr_type) { |
1242 if (slave->type) { |
1277 if (slave->type) { |
1243 if (slave->type->special == EC_TYPE_BUS_COUPLER) |
1278 if (slave->type->special == EC_TYPE_BUS_COUPLER) |
1244 return sprintf(buffer, "coupler\n"); |
1279 return sprintf(buffer, "coupler\n"); |
1245 else |
1280 else |
1246 return sprintf(buffer, "normal\n"); |
1281 return sprintf(buffer, "normal\n"); |
1247 } |
1282 } |
1248 } |
1283 } |
|
1284 else if (attr == &attr_state) { |
|
1285 switch (slave->current_state) { |
|
1286 case EC_SLAVE_STATE_INIT: |
|
1287 return sprintf(buffer, "INIT\n"); |
|
1288 case EC_SLAVE_STATE_PREOP: |
|
1289 return sprintf(buffer, "PREOP\n"); |
|
1290 case EC_SLAVE_STATE_SAVEOP: |
|
1291 return sprintf(buffer, "SAVEOP\n"); |
|
1292 case EC_SLAVE_STATE_OP: |
|
1293 return sprintf(buffer, "OP\n"); |
|
1294 default: |
|
1295 return sprintf(buffer, "UNKNOWN\n"); |
|
1296 } |
|
1297 } |
1249 |
1298 |
1250 return 0; |
1299 return 0; |
1251 } |
1300 } |
1252 |
1301 |
1253 /*****************************************************************************/ |
1302 /*****************************************************************************/ |
1254 |
1303 |
1255 /** |
1304 /** |
1256 Application layer status messages. |
1305 Formats attribute data for SysFS write access. |
1257 */ |
1306 \return number of bytes processed, or negative error code |
1258 |
1307 */ |
1259 const ec_code_msg_t al_status_messages[] = { |
1308 |
1260 {0x0001, "Unspecified error"}, |
1309 ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */ |
1261 {0x0011, "Invalud requested state change"}, |
1310 struct attribute *attr, /**< attribute */ |
1262 {0x0012, "Unknown requested state"}, |
1311 const char *buffer, /**< memory with data */ |
1263 {0x0013, "Bootstrap not supported"}, |
1312 size_t size /**< size of data to store */ |
1264 {0x0014, "No valid firmware"}, |
1313 ) |
1265 {0x0015, "Invalid mailbox configuration"}, |
1314 { |
1266 {0x0016, "Invalid mailbox configuration"}, |
1315 ec_slave_t *slave = container_of(kobj, ec_slave_t, kobj); |
1267 {0x0017, "Invalid sync manager configuration"}, |
1316 |
1268 {0x0018, "No valid inputs available"}, |
1317 if (attr == &attr_state) { |
1269 {0x0019, "No valid outputs"}, |
1318 if (!strcmp(buffer, "INIT\n")) { |
1270 {0x001A, "Synchronisation error"}, |
1319 slave->requested_state = EC_SLAVE_STATE_INIT; |
1271 {0x001B, "Sync manager watchdog"}, |
1320 slave->state_error = 0; |
1272 {0x0020, "Slave needs cold start"}, |
1321 return size; |
1273 {0x0021, "Slave needs INIT"}, |
1322 } |
1274 {0x0022, "Slave needs PREOP"}, |
1323 else if (!strcmp(buffer, "PREOP\n")) { |
1275 {0x0023, "Slave needs SAVEOP"}, |
1324 slave->requested_state = EC_SLAVE_STATE_PREOP; |
1276 {} |
1325 slave->state_error = 0; |
1277 }; |
1326 return size; |
|
1327 } |
|
1328 else if (!strcmp(buffer, "SAVEOP\n")) { |
|
1329 slave->requested_state = EC_SLAVE_STATE_SAVEOP; |
|
1330 slave->state_error = 0; |
|
1331 return size; |
|
1332 } |
|
1333 else if (!strcmp(buffer, "OP\n")) { |
|
1334 slave->requested_state = EC_SLAVE_STATE_OP; |
|
1335 slave->state_error = 0; |
|
1336 return size; |
|
1337 } |
|
1338 |
|
1339 EC_ERR("Failed to set slave state!\n"); |
|
1340 } |
|
1341 |
|
1342 return -EINVAL; |
|
1343 } |
1278 |
1344 |
1279 /****************************************************************************** |
1345 /****************************************************************************** |
1280 * Realtime interface |
1346 * Realtime interface |
1281 *****************************************************************************/ |
1347 *****************************************************************************/ |
1282 |
1348 |