00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00039
00040
00041 #include <linux/delay.h>
00042 #include <linux/slab.h>
00043 #include <linux/module.h>
00044
00045 #include "master.h"
00046 #include "mailbox.h"
00047
00048
00049
00050 void ec_canopen_abort_msg(uint32_t);
00051 int ec_slave_fetch_sdo_descriptions(ec_slave_t *, ec_datagram_t *);
00052 int ec_slave_fetch_sdo_entries(ec_slave_t *, ec_datagram_t *,
00053 ec_sdo_t *, uint8_t);
00054
00055
00056
00062 int ec_slave_sdo_read_exp(ec_slave_t *slave,
00063 uint16_t sdo_index,
00064 uint8_t sdo_subindex,
00065 uint8_t *target
00066 )
00067 {
00068 ec_datagram_t datagram;
00069 size_t rec_size;
00070 uint8_t *data;
00071
00072 ec_datagram_init(&datagram);
00073
00074 if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6)))
00075 goto err;
00076
00077 EC_WRITE_U16(data, 0x2 << 12);
00078 EC_WRITE_U8 (data + 2, (0x1 << 1
00079 | 0x2 << 5));
00080 EC_WRITE_U16(data + 3, sdo_index);
00081 EC_WRITE_U8 (data + 5, sdo_subindex);
00082
00083 if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
00084 goto err;
00085
00086 if (EC_READ_U16(data) >> 12 == 0x2 &&
00087 EC_READ_U8 (data + 2) >> 5 == 0x4) {
00088 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
00089 sdo_index, sdo_subindex, slave->ring_position);
00090 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00091 goto err;
00092 }
00093
00094 if (EC_READ_U16(data) >> 12 != 0x3 ||
00095 EC_READ_U8 (data + 2) >> 5 != 0x2 ||
00096 EC_READ_U16(data + 3) != sdo_index ||
00097 EC_READ_U8 (data + 5) != sdo_subindex) {
00098 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
00099 EC_ERR("Invalid SDO upload response at slave %i!\n",
00100 slave->ring_position);
00101 ec_print_data(data, rec_size);
00102 goto err;
00103 }
00104
00105 memcpy(target, data + 6, 4);
00106
00107 ec_datagram_clear(&datagram);
00108 return 0;
00109 err:
00110 ec_datagram_clear(&datagram);
00111 return -1;
00112 }
00113
00114
00115
00121 int ec_slave_sdo_write_exp(ec_slave_t *slave,
00122 uint16_t sdo_index,
00123 uint8_t sdo_subindex,
00124 const uint8_t *sdo_data,
00125 size_t size
00126 )
00127 {
00128 uint8_t *data;
00129 size_t rec_size;
00130 ec_datagram_t datagram;
00131
00132 ec_datagram_init(&datagram);
00133
00134 if (size == 0 || size > 4) {
00135 EC_ERR("Invalid data size!\n");
00136 goto err;
00137 }
00138
00139 if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 0x0A)))
00140 goto err;
00141
00142 EC_WRITE_U16(data, 0x2 << 12);
00143 EC_WRITE_U8 (data + 2, (0x1
00144 | 0x1 << 1
00145 | (4 - size) << 2
00146 | 0x1 << 5));
00147 EC_WRITE_U16(data + 3, sdo_index);
00148 EC_WRITE_U8 (data + 5, sdo_subindex);
00149 memcpy(data + 6, sdo_data, size);
00150 if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
00151
00152 if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
00153 goto err;
00154
00155 if (EC_READ_U16(data) >> 12 == 0x2 &&
00156 EC_READ_U8 (data + 2) >> 5 == 0x4) {
00157 EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
00158 sdo_index, sdo_subindex, size, slave->ring_position);
00159 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00160 return -1;
00161 }
00162
00163 if (EC_READ_U16(data) >> 12 != 0x3 ||
00164 EC_READ_U8 (data + 2) >> 5 != 0x3 ||
00165 EC_READ_U16(data + 3) != sdo_index ||
00166 EC_READ_U8 (data + 5) != sdo_subindex) {
00167 EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
00168 sdo_index, sdo_subindex, size);
00169 EC_ERR("Invalid SDO download response at slave %i!\n",
00170 slave->ring_position);
00171 ec_print_data(data, rec_size);
00172 return -1;
00173 }
00174
00175 ec_datagram_clear(&datagram);
00176 return 0;
00177 err:
00178 ec_datagram_clear(&datagram);
00179 return -1;
00180 }
00181
00182
00183
00191 int ecrt_slave_sdo_read(ec_slave_t *slave,
00192 uint16_t sdo_index,
00193 uint8_t sdo_subindex,
00194 uint8_t *target,
00195 size_t *size
00196 )
00197 {
00198 uint8_t *data;
00199 size_t rec_size, data_size;
00200 uint32_t complete_size;
00201 ec_datagram_t datagram;
00202
00203 ec_datagram_init(&datagram);
00204
00205 if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 6)))
00206 goto err;
00207
00208 EC_WRITE_U16(data, 0x2 << 12);
00209 EC_WRITE_U8 (data + 2, 0x2 << 5);
00210 EC_WRITE_U16(data + 3, sdo_index);
00211 EC_WRITE_U8 (data + 5, sdo_subindex);
00212
00213 if (!(data = ec_slave_mbox_simple_io(slave, &datagram, &rec_size)))
00214 goto err;
00215
00216 if (EC_READ_U16(data) >> 12 == 0x2 &&
00217 EC_READ_U8 (data + 2) >> 5 == 0x4) {
00218 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
00219 sdo_index, sdo_subindex, slave->ring_position);
00220 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00221 goto err;
00222 }
00223
00224 if (EC_READ_U16(data) >> 12 != 0x3 ||
00225 EC_READ_U8 (data + 2) >> 5 != 0x2 ||
00226 EC_READ_U16(data + 3) != sdo_index ||
00227 EC_READ_U8 (data + 5) != sdo_subindex) {
00228 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
00229 EC_ERR("Invalid SDO upload response at slave %i!\n",
00230 slave->ring_position);
00231 ec_print_data(data, rec_size);
00232 goto err;
00233 }
00234
00235 if (rec_size < 10) {
00236 EC_ERR("Received currupted SDO upload response!\n");
00237 ec_print_data(data, rec_size);
00238 goto err;
00239 }
00240
00241 if ((complete_size = EC_READ_U32(data + 6)) > *size) {
00242 EC_ERR("SDO data does not fit into buffer (%i / %i)!\n",
00243 complete_size, *size);
00244 goto err;
00245 }
00246
00247 data_size = rec_size - 10;
00248
00249 if (data_size != complete_size) {
00250 EC_ERR("SDO data incomplete - Fragmenting not implemented.\n");
00251 goto err;
00252 }
00253
00254 memcpy(target, data + 10, data_size);
00255
00256 ec_datagram_clear(&datagram);
00257 return 0;
00258 err:
00259 ec_datagram_clear(&datagram);
00260 return -1;
00261 }
00262
00263
00264
00270 int ec_slave_fetch_sdo_list(ec_slave_t *slave )
00271 {
00272 uint8_t *data;
00273 size_t rec_size;
00274 unsigned int i, sdo_count;
00275 ec_sdo_t *sdo;
00276 uint16_t sdo_index;
00277 ec_datagram_t datagram;
00278
00279 ec_datagram_init(&datagram);
00280
00281 if (!(data = ec_slave_mbox_prepare_send(slave, &datagram, 0x03, 8)))
00282 goto err;
00283
00284 EC_WRITE_U16(data, 0x8 << 12);
00285 EC_WRITE_U8 (data + 2, 0x01);
00286 EC_WRITE_U8 (data + 3, 0x00);
00287 EC_WRITE_U16(data + 4, 0x0000);
00288 EC_WRITE_U16(data + 6, 0x0001);
00289
00290 if (unlikely(ec_master_simple_io(slave->master, &datagram))) {
00291 EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position);
00292 goto err;
00293 }
00294
00295 do {
00296 if (!(data = ec_slave_mbox_simple_receive(slave, &datagram,
00297 0x03, &rec_size)))
00298 goto err;
00299
00300 if (EC_READ_U16(data) >> 12 == 0x8 &&
00301 (EC_READ_U8(data + 2) & 0x7F) == 0x07) {
00302 EC_ERR("SDO information error response at slave %i!\n",
00303 slave->ring_position);
00304 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00305 goto err;
00306 }
00307
00308 if (EC_READ_U16(data) >> 12 != 0x8 ||
00309 (EC_READ_U8 (data + 2) & 0x7F) != 0x02) {
00310 EC_ERR("Invalid SDO list response at slave %i!\n",
00311 slave->ring_position);
00312 ec_print_data(data, rec_size);
00313 goto err;
00314 }
00315
00316 if (rec_size < 8) {
00317 EC_ERR("Invalid data size!\n");
00318 ec_print_data(data, rec_size);
00319 goto err;
00320 }
00321
00322 sdo_count = (rec_size - 8) / 2;
00323 for (i = 0; i < sdo_count; i++) {
00324 sdo_index = EC_READ_U16(data + 8 + i * 2);
00325 if (!sdo_index) continue;
00326
00327 if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
00328 EC_ERR("Failed to allocate memory for SDO!\n");
00329 goto err;
00330 }
00331
00332
00333 sdo->index = sdo_index;
00334
00335 sdo->object_code = 0x00;
00336 sdo->name = NULL;
00337 INIT_LIST_HEAD(&sdo->entries);
00338
00339 list_add_tail(&sdo->list, &slave->sdo_dictionary);
00340 }
00341 }
00342 while (EC_READ_U8(data + 2) & 0x80);
00343
00344
00345 if (ec_slave_fetch_sdo_descriptions(slave, &datagram)) goto err;
00346
00347 ec_datagram_clear(&datagram);
00348 return 0;
00349 err:
00350 ec_datagram_clear(&datagram);
00351 return -1;
00352 }
00353
00354
00355
00361 int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave,
00362 ec_datagram_t *datagram
00363 )
00364 {
00365 uint8_t *data;
00366 size_t rec_size, name_size;
00367 ec_sdo_t *sdo;
00368
00369 list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
00370 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8)))
00371 return -1;
00372 EC_WRITE_U16(data, 0x8 << 12);
00373 EC_WRITE_U8 (data + 2, 0x03);
00374 EC_WRITE_U8 (data + 3, 0x00);
00375 EC_WRITE_U16(data + 4, 0x0000);
00376 EC_WRITE_U16(data + 6, sdo->index);
00377
00378 if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size)))
00379 return -1;
00380
00381 if (EC_READ_U16(data) >> 12 == 0x8 &&
00382 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
00383 EC_ERR("SDO information error response at slave %i while"
00384 " fetching SDO 0x%04X!\n", slave->ring_position,
00385 sdo->index);
00386 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00387 return -1;
00388 }
00389
00390 if (EC_READ_U16(data) >> 12 != 0x8 ||
00391 (EC_READ_U8 (data + 2) & 0x7F) != 0x04 ||
00392 EC_READ_U16(data + 6) != sdo->index) {
00393 EC_ERR("Invalid object description response at slave %i while"
00394 " fetching SDO 0x%04X!\n", slave->ring_position,
00395 sdo->index);
00396 ec_print_data(data, rec_size);
00397 return -1;
00398 }
00399
00400 if (rec_size < 12) {
00401 EC_ERR("Invalid data size!\n");
00402 ec_print_data(data, rec_size);
00403 return -1;
00404 }
00405
00406 #if 0
00407 EC_DBG("object desc response:\n");
00408 ec_print_data(data, rec_size);
00409 #endif
00410
00411
00412 sdo->object_code = EC_READ_U8(data + 11);
00413
00414 name_size = rec_size - 12;
00415 if (name_size) {
00416 if (!(sdo->name = kmalloc(name_size + 1, GFP_KERNEL))) {
00417 EC_ERR("Failed to allocate SDO name!\n");
00418 return -1;
00419 }
00420
00421 memcpy(sdo->name, data + 12, name_size);
00422 sdo->name[name_size] = 0;
00423 }
00424
00425 if (EC_READ_U8(data + 2) & 0x80) {
00426 EC_ERR("Fragment follows (not implemented)!\n");
00427 return -1;
00428 }
00429
00430
00431 if (ec_slave_fetch_sdo_entries(slave, datagram, sdo,
00432 EC_READ_U8(data + 10)))
00433 return -1;
00434 }
00435
00436 return 0;
00437 }
00438
00439
00440
00446 int ec_slave_fetch_sdo_entries(ec_slave_t *slave,
00447 ec_datagram_t *datagram,
00448 ec_sdo_t *sdo,
00449 uint8_t subindices
00450 )
00451 {
00452 uint8_t *data;
00453 size_t rec_size, data_size;
00454 uint8_t i;
00455 ec_sdo_entry_t *entry;
00456
00457 for (i = 1; i <= subindices; i++) {
00458 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10)))
00459 return -1;
00460
00461 EC_WRITE_U16(data, 0x8 << 12);
00462 EC_WRITE_U8 (data + 2, 0x05);
00463 EC_WRITE_U8 (data + 3, 0x00);
00464 EC_WRITE_U16(data + 4, 0x0000);
00465 EC_WRITE_U16(data + 6, sdo->index);
00466 EC_WRITE_U8 (data + 8, i);
00467 EC_WRITE_U8 (data + 9, 0x00);
00468
00469 if (!(data = ec_slave_mbox_simple_io(slave, datagram, &rec_size)))
00470 return -1;
00471
00472 if (EC_READ_U16(data) >> 12 == 0x8 &&
00473 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
00474 EC_ERR("SDO information error response at slave %i while"
00475 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00476 sdo->index, i);
00477 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00478 return -1;
00479 }
00480
00481 if (EC_READ_U16(data) >> 12 != 0x8 ||
00482 (EC_READ_U8(data + 2) & 0x7F) != 0x06 ||
00483 EC_READ_U16(data + 6) != sdo->index ||
00484 EC_READ_U8(data + 8) != i) {
00485 EC_ERR("Invalid entry description response at slave %i while"
00486 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00487 sdo->index, i);
00488 ec_print_data(data, rec_size);
00489 return -1;
00490 }
00491
00492 if (rec_size < 16) {
00493 EC_ERR("Invalid data size!\n");
00494 ec_print_data(data, rec_size);
00495 return -1;
00496 }
00497
00498 if (!EC_READ_U16(data + 12))
00499 continue;
00500
00501 data_size = rec_size - 16;
00502
00503 if (!(entry = (ec_sdo_entry_t *)
00504 kmalloc(sizeof(ec_sdo_entry_t) + data_size + 1, GFP_KERNEL))) {
00505 EC_ERR("Failed to allocate entry!\n");
00506 return -1;
00507 }
00508
00509 entry->subindex = i;
00510 entry->data_type = EC_READ_U16(data + 10);
00511 entry->bit_length = EC_READ_U16(data + 12);
00512
00513
00514 entry->name = (uint8_t *) entry + sizeof(ec_sdo_entry_t);
00515
00516 memcpy(entry->name, data + 16, data_size);
00517 entry->name[data_size] = 0;
00518
00519 list_add_tail(&entry->list, &sdo->entries);
00520 }
00521
00522 return 0;
00523 }
00524
00525
00526
00534 const ec_code_msg_t sdo_abort_messages[] = {
00535 {0x05030000, "Toggle bit not changed"},
00536 {0x05040000, "SDO protocol timeout"},
00537 {0x05040001, "Client/Server command specifier not valid or unknown"},
00538 {0x05040005, "Out of memory"},
00539 {0x06010000, "Unsupported access to an object"},
00540 {0x06010001, "Attempt to read a write-only object"},
00541 {0x06010002, "Attempt to write a read-only object"},
00542 {0x06020000, "This object does not exist in the object directory"},
00543 {0x06040041, "The object cannot be mapped into the PDO"},
00544 {0x06040042, "The number and length of the objects to be mapped would"
00545 " exceed the PDO length"},
00546 {0x06040043, "General parameter incompatibility reason"},
00547 {0x06040047, "Gerneral internal incompatibility in device"},
00548 {0x06060000, "Access failure due to a hardware error"},
00549 {0x06070010, "Data type does not match, length of service parameter does"
00550 " not match"},
00551 {0x06070012, "Data type does not match, length of service parameter too"
00552 " high"},
00553 {0x06070013, "Data type does not match, length of service parameter too"
00554 " low"},
00555 {0x06090011, "Subindex does not exist"},
00556 {0x06090030, "Value range of parameter exceeded"},
00557 {0x06090031, "Value of parameter written too high"},
00558 {0x06090032, "Value of parameter written too low"},
00559 {0x06090036, "Maximum value is less than minimum value"},
00560 {0x08000000, "General error"},
00561 {0x08000020, "Data cannot be transferred or stored to the application"},
00562 {0x08000021, "Data cannot be transferred or stored to the application"
00563 " because of local control"},
00564 {0x08000022, "Data cannot be transferred or stored to the application"
00565 " because of the present device state"},
00566 {0x08000023, "Object dictionary dynamic generation fails or no object"
00567 " dictionary is present"},
00568 {}
00569 };
00570
00571
00572
00577 void ec_canopen_abort_msg(uint32_t abort_code)
00578 {
00579 const ec_code_msg_t *abort_msg;
00580
00581 for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
00582 if (abort_msg->code == abort_code) {
00583 EC_ERR("SDO abort message 0x%08X: \"%s\".\n",
00584 abort_msg->code, abort_msg->message);
00585 return;
00586 }
00587 }
00588
00589 EC_ERR("Unknown SDO abort code 0x%08X.\n", abort_code);
00590 }
00591
00592
00593
00594
00595
00603 int ecrt_slave_sdo_read_exp8(ec_slave_t *slave,
00604 uint16_t sdo_index,
00605 uint8_t sdo_subindex,
00606 uint8_t *target
00607 )
00608 {
00609 uint8_t data[4];
00610 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
00611 *target = EC_READ_U8(data);
00612 return 0;
00613 }
00614
00615
00616
00624 int ecrt_slave_sdo_read_exp16(ec_slave_t *slave,
00625 uint16_t sdo_index,
00626 uint8_t sdo_subindex,
00627 uint16_t *target
00628 )
00629 {
00630 uint8_t data[4];
00631 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
00632 *target = EC_READ_U16(data);
00633 return 0;
00634 }
00635
00636
00637
00645 int ecrt_slave_sdo_read_exp32(ec_slave_t *slave,
00646 uint16_t sdo_index,
00647 uint8_t sdo_subindex,
00648 uint32_t *target
00649 )
00650 {
00651 uint8_t data[4];
00652 if (ec_slave_sdo_read_exp(slave, sdo_index, sdo_subindex, data)) return -1;
00653 *target = EC_READ_U32(data);
00654 return 0;
00655 }
00656
00657
00658
00665 int ecrt_slave_sdo_write_exp8(ec_slave_t *slave,
00666 uint16_t sdo_index,
00667 uint8_t sdo_subindex,
00668 uint8_t value
00669 )
00670 {
00671 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1);
00672 }
00673
00674
00675
00682 int ecrt_slave_sdo_write_exp16(ec_slave_t *slave,
00683 uint16_t sdo_index,
00684 uint8_t sdo_subindex,
00685 uint16_t value
00686 )
00687 {
00688 uint8_t data[2];
00689 EC_WRITE_U16(data, value);
00690 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 2);
00691 }
00692
00693
00694
00701 int ecrt_slave_sdo_write_exp32(ec_slave_t *slave,
00702 uint16_t sdo_index,
00703 uint8_t sdo_subindex,
00704 uint32_t value
00705 )
00706 {
00707 uint8_t data[4];
00708 EC_WRITE_U32(data, value);
00709 return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, data, 4);
00710 }
00711
00712
00713
00716 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp8);
00717 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp16);
00718 EXPORT_SYMBOL(ecrt_slave_sdo_read_exp32);
00719 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp8);
00720 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp16);
00721 EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32);
00722 EXPORT_SYMBOL(ecrt_slave_sdo_read);
00723
00726