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 "globals.h"
00042 #include "master.h"
00043 #include "mailbox.h"
00044 #include "fsm_coe.h"
00045
00046
00047
00048 void ec_fsm_coe_dict_start(ec_fsm_coe_t *);
00049 void ec_fsm_coe_dict_request(ec_fsm_coe_t *);
00050 void ec_fsm_coe_dict_check(ec_fsm_coe_t *);
00051 void ec_fsm_coe_dict_response(ec_fsm_coe_t *);
00052 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *);
00053 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *);
00054 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *);
00055 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *);
00056 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *);
00057 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *);
00058
00059 void ec_fsm_coe_down_start(ec_fsm_coe_t *);
00060 void ec_fsm_coe_down_request(ec_fsm_coe_t *);
00061 void ec_fsm_coe_down_check(ec_fsm_coe_t *);
00062 void ec_fsm_coe_down_response(ec_fsm_coe_t *);
00063
00064 void ec_fsm_coe_up_start(ec_fsm_coe_t *);
00065 void ec_fsm_coe_up_request(ec_fsm_coe_t *);
00066 void ec_fsm_coe_up_check(ec_fsm_coe_t *);
00067 void ec_fsm_coe_up_response(ec_fsm_coe_t *);
00068 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *);
00069 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *);
00070 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *);
00071
00072 void ec_fsm_coe_end(ec_fsm_coe_t *);
00073 void ec_fsm_coe_error(ec_fsm_coe_t *);
00074
00075
00076
00084 const ec_code_msg_t sdo_abort_messages[] = {
00085 {0x05030000, "Toggle bit not changed"},
00086 {0x05040000, "SDO protocol timeout"},
00087 {0x05040001, "Client/Server command specifier not valid or unknown"},
00088 {0x05040005, "Out of memory"},
00089 {0x06010000, "Unsupported access to an object"},
00090 {0x06010001, "Attempt to read a write-only object"},
00091 {0x06010002, "Attempt to write a read-only object"},
00092 {0x06020000, "This object does not exist in the object directory"},
00093 {0x06040041, "The object cannot be mapped into the PDO"},
00094 {0x06040042, "The number and length of the objects to be mapped would"
00095 " exceed the PDO length"},
00096 {0x06040043, "General parameter incompatibility reason"},
00097 {0x06040047, "Gerneral internal incompatibility in device"},
00098 {0x06060000, "Access failure due to a hardware error"},
00099 {0x06070010, "Data type does not match, length of service parameter does"
00100 " not match"},
00101 {0x06070012, "Data type does not match, length of service parameter too"
00102 " high"},
00103 {0x06070013, "Data type does not match, length of service parameter too"
00104 " low"},
00105 {0x06090011, "Subindex does not exist"},
00106 {0x06090030, "Value range of parameter exceeded"},
00107 {0x06090031, "Value of parameter written too high"},
00108 {0x06090032, "Value of parameter written too low"},
00109 {0x06090036, "Maximum value is less than minimum value"},
00110 {0x08000000, "General error"},
00111 {0x08000020, "Data cannot be transferred or stored to the application"},
00112 {0x08000021, "Data cannot be transferred or stored to the application"
00113 " because of local control"},
00114 {0x08000022, "Data cannot be transferred or stored to the application"
00115 " because of the present device state"},
00116 {0x08000023, "Object dictionary dynamic generation fails or no object"
00117 " dictionary is present"},
00118 {}
00119 };
00120
00121
00122
00127 void ec_canopen_abort_msg(uint32_t abort_code)
00128 {
00129 const ec_code_msg_t *abort_msg;
00130
00131 for (abort_msg = sdo_abort_messages; abort_msg->code; abort_msg++) {
00132 if (abort_msg->code == abort_code) {
00133 EC_ERR("SDO abort message 0x%08X: \"%s\".\n",
00134 abort_msg->code, abort_msg->message);
00135 return;
00136 }
00137 }
00138
00139 EC_ERR("Unknown SDO abort code 0x%08X.\n", abort_code);
00140 }
00141
00142
00143
00148 void ec_fsm_coe_init(ec_fsm_coe_t *fsm,
00149 ec_datagram_t *datagram
00150 )
00151 {
00152 fsm->state = NULL;
00153 fsm->datagram = datagram;
00154 }
00155
00156
00157
00162 void ec_fsm_coe_clear(ec_fsm_coe_t *fsm )
00163 {
00164 }
00165
00166
00167
00172 void ec_fsm_coe_dictionary(ec_fsm_coe_t *fsm,
00173 ec_slave_t *slave
00174 )
00175 {
00176 fsm->slave = slave;
00177 fsm->state = ec_fsm_coe_dict_start;
00178 }
00179
00180
00181
00186 void ec_fsm_coe_download(ec_fsm_coe_t *fsm,
00187 ec_slave_t *slave,
00188 ec_sdo_data_t *sdodata
00189 )
00190 {
00191 fsm->slave = slave;
00192 fsm->sdodata = sdodata;
00193 fsm->state = ec_fsm_coe_down_start;
00194 }
00195
00196
00197
00202 void ec_fsm_coe_upload(ec_fsm_coe_t *fsm,
00203 ec_slave_t *slave,
00204 ec_sdo_request_t *request
00205 )
00206 {
00207 fsm->slave = slave;
00208 fsm->request = request;
00209 fsm->state = ec_fsm_coe_up_start;
00210 }
00211
00212
00213
00219 int ec_fsm_coe_exec(ec_fsm_coe_t *fsm )
00220 {
00221 fsm->state(fsm);
00222
00223 return fsm->state != ec_fsm_coe_end && fsm->state != ec_fsm_coe_error;
00224 }
00225
00226
00227
00233 int ec_fsm_coe_success(ec_fsm_coe_t *fsm )
00234 {
00235 return fsm->state == ec_fsm_coe_end;
00236 }
00237
00238
00239
00240
00241
00246 void ec_fsm_coe_dict_start(ec_fsm_coe_t *fsm )
00247 {
00248 ec_datagram_t *datagram = fsm->datagram;
00249 ec_slave_t *slave = fsm->slave;
00250 uint8_t *data;
00251
00252 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00253 fsm->state = ec_fsm_coe_error;
00254 return;
00255 }
00256
00257 EC_WRITE_U16(data, 0x8 << 12);
00258 EC_WRITE_U8 (data + 2, 0x01);
00259 EC_WRITE_U8 (data + 3, 0x00);
00260 EC_WRITE_U16(data + 4, 0x0000);
00261 EC_WRITE_U16(data + 6, 0x0001);
00262
00263 ec_master_queue_datagram(fsm->slave->master, datagram);
00264 fsm->state = ec_fsm_coe_dict_request;
00265 }
00266
00267
00268
00273 void ec_fsm_coe_dict_request(ec_fsm_coe_t *fsm )
00274 {
00275 ec_datagram_t *datagram = fsm->datagram;
00276 ec_slave_t *slave = fsm->slave;
00277
00278 if (datagram->state != EC_DATAGRAM_RECEIVED
00279 || datagram->working_counter != 1) {
00280 fsm->state = ec_fsm_coe_error;
00281 EC_ERR("Reception of CoE dictionary request failed on slave %i.\n",
00282 slave->ring_position);
00283 return;
00284 }
00285
00286 fsm->cycles_start = datagram->cycles_sent;
00287
00288 ec_slave_mbox_prepare_check(slave, datagram);
00289 ec_master_queue_datagram(fsm->slave->master, datagram);
00290 fsm->state = ec_fsm_coe_dict_check;
00291 }
00292
00293
00294
00299 void ec_fsm_coe_dict_check(ec_fsm_coe_t *fsm )
00300 {
00301 ec_datagram_t *datagram = fsm->datagram;
00302 ec_slave_t *slave = fsm->slave;
00303
00304 if (datagram->state != EC_DATAGRAM_RECEIVED
00305 || datagram->working_counter != 1) {
00306 fsm->state = ec_fsm_coe_error;
00307 EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00308 slave->ring_position);
00309 return;
00310 }
00311
00312 if (!ec_slave_mbox_check(datagram)) {
00313 if (datagram->cycles_received
00314 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00315 fsm->state = ec_fsm_coe_error;
00316 EC_ERR("Timeout while checking SDO dictionary on slave %i.\n",
00317 slave->ring_position);
00318 return;
00319 }
00320
00321 ec_slave_mbox_prepare_check(slave, datagram);
00322 ec_master_queue_datagram(fsm->slave->master, datagram);
00323 return;
00324 }
00325
00326
00327 ec_slave_mbox_prepare_fetch(slave, datagram);
00328 ec_master_queue_datagram(fsm->slave->master, datagram);
00329 fsm->state = ec_fsm_coe_dict_response;
00330 }
00331
00332
00333
00338 void ec_fsm_coe_dict_response(ec_fsm_coe_t *fsm )
00339 {
00340 ec_datagram_t *datagram = fsm->datagram;
00341 ec_slave_t *slave = fsm->slave;
00342 uint8_t *data, mbox_prot;
00343 size_t rec_size;
00344 unsigned int sdo_count, i;
00345 uint16_t sdo_index;
00346 ec_sdo_t *sdo;
00347
00348 if (datagram->state != EC_DATAGRAM_RECEIVED
00349 || datagram->working_counter != 1) {
00350 fsm->state = ec_fsm_coe_error;
00351 EC_ERR("Reception of CoE dictionary response failed on slave %i.\n",
00352 slave->ring_position);
00353 return;
00354 }
00355
00356 if (!(data = ec_slave_mbox_fetch(slave, datagram,
00357 &mbox_prot, &rec_size))) {
00358 fsm->state = ec_fsm_coe_error;
00359 return;
00360 }
00361
00362 if (mbox_prot != 0x03) {
00363 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00364 fsm->state = ec_fsm_coe_error;
00365 return;
00366 }
00367
00368 if (EC_READ_U16(data) >> 12 == 0x8 &&
00369 (EC_READ_U8(data + 2) & 0x7F) == 0x07) {
00370 EC_ERR("SDO information error response at slave %i!\n",
00371 slave->ring_position);
00372 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00373 fsm->state = ec_fsm_coe_error;
00374 return;
00375 }
00376
00377 if (EC_READ_U16(data) >> 12 != 0x8 ||
00378 (EC_READ_U8 (data + 2) & 0x7F) != 0x02) {
00379 EC_ERR("Invalid SDO list response at slave %i!\n",
00380 slave->ring_position);
00381 ec_print_data(data, rec_size);
00382 fsm->state = ec_fsm_coe_error;
00383 return;
00384 }
00385
00386 if (rec_size < 8) {
00387 EC_ERR("Invalid data size!\n");
00388 ec_print_data(data, rec_size);
00389 fsm->state = ec_fsm_coe_error;
00390 return;
00391 }
00392
00393 sdo_count = (rec_size - 8) / 2;
00394
00395 for (i = 0; i < sdo_count; i++) {
00396 sdo_index = EC_READ_U16(data + 8 + i * 2);
00397 if (!sdo_index) {
00398 if (slave->master->debug_level)
00399 EC_WARN("SDO dictionary of slave %i contains index 0x0000.\n",
00400 slave->ring_position);
00401 continue;
00402 }
00403
00404 if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_ATOMIC))) {
00405 EC_ERR("Failed to allocate memory for SDO!\n");
00406 fsm->state = ec_fsm_coe_error;
00407 return;
00408 }
00409
00410 if (ec_sdo_init(sdo, sdo_index, slave)) {
00411 EC_ERR("Failed to init SDO!\n");
00412 fsm->state = ec_fsm_coe_error;
00413 return;
00414 }
00415
00416 list_add_tail(&sdo->list, &slave->sdo_dictionary);
00417 }
00418
00419 if (EC_READ_U8(data + 2) & 0x80) {
00420 fsm->cycles_start = datagram->cycles_sent;
00421 ec_slave_mbox_prepare_check(slave, datagram);
00422 ec_master_queue_datagram(fsm->slave->master, datagram);
00423 fsm->state = ec_fsm_coe_dict_check;
00424 return;
00425 }
00426
00427 if (list_empty(&slave->sdo_dictionary)) {
00428
00429 fsm->state = ec_fsm_coe_end;
00430 return;
00431 }
00432
00433
00434 fsm->sdo = list_entry(slave->sdo_dictionary.next, ec_sdo_t, list);
00435
00436 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00437 fsm->state = ec_fsm_coe_error;
00438 return;
00439 }
00440
00441 EC_WRITE_U16(data, 0x8 << 12);
00442 EC_WRITE_U8 (data + 2, 0x03);
00443 EC_WRITE_U8 (data + 3, 0x00);
00444 EC_WRITE_U16(data + 4, 0x0000);
00445 EC_WRITE_U16(data + 6, fsm->sdo->index);
00446
00447 ec_master_queue_datagram(fsm->slave->master, datagram);
00448 fsm->state = ec_fsm_coe_dict_desc_request;
00449 }
00450
00451
00452
00457 void ec_fsm_coe_dict_desc_request(ec_fsm_coe_t *fsm )
00458 {
00459 ec_datagram_t *datagram = fsm->datagram;
00460 ec_slave_t *slave = fsm->slave;
00461
00462 if (datagram->state != EC_DATAGRAM_RECEIVED
00463 || datagram->working_counter != 1) {
00464 fsm->state = ec_fsm_coe_error;
00465 EC_ERR("Reception of CoE SDO description"
00466 " request failed on slave %i.\n", slave->ring_position);
00467 return;
00468 }
00469
00470 fsm->cycles_start = datagram->cycles_sent;
00471
00472 ec_slave_mbox_prepare_check(slave, datagram);
00473 ec_master_queue_datagram(fsm->slave->master, datagram);
00474 fsm->state = ec_fsm_coe_dict_desc_check;
00475 }
00476
00477
00478
00483 void ec_fsm_coe_dict_desc_check(ec_fsm_coe_t *fsm )
00484 {
00485 ec_datagram_t *datagram = fsm->datagram;
00486 ec_slave_t *slave = fsm->slave;
00487
00488 if (datagram->state != EC_DATAGRAM_RECEIVED
00489 || datagram->working_counter != 1) {
00490 fsm->state = ec_fsm_coe_error;
00491 EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00492 slave->ring_position);
00493 return;
00494 }
00495
00496 if (!ec_slave_mbox_check(datagram)) {
00497 if (datagram->cycles_received
00498 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00499 fsm->state = ec_fsm_coe_error;
00500 EC_ERR("Timeout while checking SDO description on slave %i.\n",
00501 slave->ring_position);
00502 return;
00503 }
00504
00505 ec_slave_mbox_prepare_check(slave, datagram);
00506 ec_master_queue_datagram(fsm->slave->master, datagram);
00507 return;
00508 }
00509
00510
00511 ec_slave_mbox_prepare_fetch(slave, datagram);
00512 ec_master_queue_datagram(fsm->slave->master, datagram);
00513 fsm->state = ec_fsm_coe_dict_desc_response;
00514 }
00515
00516
00517
00522 void ec_fsm_coe_dict_desc_response(ec_fsm_coe_t *fsm)
00524 {
00525 ec_datagram_t *datagram = fsm->datagram;
00526 ec_slave_t *slave = fsm->slave;
00527 ec_sdo_t *sdo = fsm->sdo;
00528 uint8_t *data, mbox_prot;
00529 size_t rec_size, name_size;
00530
00531 if (datagram->state != EC_DATAGRAM_RECEIVED
00532 || datagram->working_counter != 1) {
00533 fsm->state = ec_fsm_coe_error;
00534 EC_ERR("Reception of CoE SDO description"
00535 "response failed on slave %i.\n", slave->ring_position);
00536 return;
00537 }
00538
00539 if (!(data = ec_slave_mbox_fetch(slave, datagram,
00540 &mbox_prot, &rec_size))) {
00541 fsm->state = ec_fsm_coe_error;
00542 return;
00543 }
00544
00545 if (mbox_prot != 0x03) {
00546 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00547 fsm->state = ec_fsm_coe_error;
00548 return;
00549 }
00550
00551 if (EC_READ_U16(data) >> 12 == 0x8 &&
00552 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
00553 EC_ERR("SDO information error response at slave %i while"
00554 " fetching SDO 0x%04X!\n", slave->ring_position,
00555 sdo->index);
00556 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00557 fsm->state = ec_fsm_coe_error;
00558 return;
00559 }
00560
00561 if (EC_READ_U16(data) >> 12 != 0x8 ||
00562 (EC_READ_U8 (data + 2) & 0x7F) != 0x04 ||
00563 EC_READ_U16(data + 6) != sdo->index) {
00564 EC_ERR("Invalid object description response at slave %i while"
00565 " fetching SDO 0x%04X!\n", slave->ring_position,
00566 sdo->index);
00567 ec_print_data(data, rec_size);
00568 fsm->state = ec_fsm_coe_error;
00569 return;
00570 }
00571
00572 if (rec_size < 12) {
00573 EC_ERR("Invalid data size!\n");
00574 ec_print_data(data, rec_size);
00575 fsm->state = ec_fsm_coe_error;
00576 return;
00577 }
00578
00579 sdo->subindices = EC_READ_U8(data + 10);
00580 sdo->object_code = EC_READ_U8(data + 11);
00581
00582 name_size = rec_size - 12;
00583 if (name_size) {
00584 if (!(sdo->name = kmalloc(name_size + 1, GFP_ATOMIC))) {
00585 EC_ERR("Failed to allocate SDO name!\n");
00586 fsm->state = ec_fsm_coe_error;
00587 return;
00588 }
00589
00590 memcpy(sdo->name, data + 12, name_size);
00591 sdo->name[name_size] = 0;
00592 }
00593
00594 if (EC_READ_U8(data + 2) & 0x80) {
00595 EC_ERR("Fragment follows (not implemented)!\n");
00596 fsm->state = ec_fsm_coe_error;
00597 return;
00598 }
00599
00600
00601
00602 fsm->subindex = 0;
00603
00604 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
00605 fsm->state = ec_fsm_coe_error;
00606 return;
00607 }
00608
00609 EC_WRITE_U16(data, 0x8 << 12);
00610 EC_WRITE_U8 (data + 2, 0x05);
00611 EC_WRITE_U8 (data + 3, 0x00);
00612 EC_WRITE_U16(data + 4, 0x0000);
00613 EC_WRITE_U16(data + 6, sdo->index);
00614 EC_WRITE_U8 (data + 8, fsm->subindex);
00615 EC_WRITE_U8 (data + 9, 0x00);
00616
00617 ec_master_queue_datagram(fsm->slave->master, datagram);
00618 fsm->state = ec_fsm_coe_dict_entry_request;
00619 }
00620
00621
00622
00627 void ec_fsm_coe_dict_entry_request(ec_fsm_coe_t *fsm)
00629 {
00630 ec_datagram_t *datagram = fsm->datagram;
00631 ec_slave_t *slave = fsm->slave;
00632
00633 if (datagram->state != EC_DATAGRAM_RECEIVED
00634 || datagram->working_counter != 1) {
00635 fsm->state = ec_fsm_coe_error;
00636 EC_ERR("Reception of CoE SDO entry request failed on slave %i.\n",
00637 slave->ring_position);
00638 return;
00639 }
00640
00641 fsm->cycles_start = datagram->cycles_sent;
00642
00643 ec_slave_mbox_prepare_check(slave, datagram);
00644 ec_master_queue_datagram(fsm->slave->master, datagram);
00645 fsm->state = ec_fsm_coe_dict_entry_check;
00646 }
00647
00648
00649
00654 void ec_fsm_coe_dict_entry_check(ec_fsm_coe_t *fsm)
00656 {
00657 ec_datagram_t *datagram = fsm->datagram;
00658 ec_slave_t *slave = fsm->slave;
00659
00660 if (datagram->state != EC_DATAGRAM_RECEIVED
00661 || datagram->working_counter != 1) {
00662 fsm->state = ec_fsm_coe_error;
00663 EC_ERR("Reception of CoE mailbox check datagram failed on slave %i.\n",
00664 slave->ring_position);
00665 return;
00666 }
00667
00668 if (!ec_slave_mbox_check(datagram)) {
00669 if (datagram->cycles_received
00670 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00671 fsm->state = ec_fsm_coe_error;
00672 EC_ERR("Timeout while checking SDO entry on slave %i.\n",
00673 slave->ring_position);
00674 return;
00675 }
00676
00677 ec_slave_mbox_prepare_check(slave, datagram);
00678 ec_master_queue_datagram(fsm->slave->master, datagram);
00679 return;
00680 }
00681
00682
00683 ec_slave_mbox_prepare_fetch(slave, datagram);
00684 ec_master_queue_datagram(fsm->slave->master, datagram);
00685 fsm->state = ec_fsm_coe_dict_entry_response;
00686 }
00687
00688
00689
00694 void ec_fsm_coe_dict_entry_response(ec_fsm_coe_t *fsm)
00696 {
00697 ec_datagram_t *datagram = fsm->datagram;
00698 ec_slave_t *slave = fsm->slave;
00699 ec_sdo_t *sdo = fsm->sdo;
00700 uint8_t *data, mbox_prot;
00701 size_t rec_size, data_size;
00702 ec_sdo_entry_t *entry;
00703
00704 if (datagram->state != EC_DATAGRAM_RECEIVED
00705 || datagram->working_counter != 1) {
00706 fsm->state = ec_fsm_coe_error;
00707 EC_ERR("Reception of CoE SDO description"
00708 " response failed on slave %i.\n", slave->ring_position);
00709 return;
00710 }
00711
00712 if (!(data = ec_slave_mbox_fetch(slave, datagram,
00713 &mbox_prot, &rec_size))) {
00714 fsm->state = ec_fsm_coe_error;
00715 return;
00716 }
00717
00718 if (mbox_prot != 0x03) {
00719 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00720 fsm->state = ec_fsm_coe_error;
00721 return;
00722 }
00723
00724 if (EC_READ_U16(data) >> 12 == 0x8 &&
00725 (EC_READ_U8 (data + 2) & 0x7F) == 0x07) {
00726 EC_ERR("SDO information error response at slave %i while"
00727 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00728 sdo->index, fsm->subindex);
00729 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00730 fsm->state = ec_fsm_coe_error;
00731 return;
00732 }
00733
00734 if (EC_READ_U16(data) >> 12 != 0x8 ||
00735 (EC_READ_U8(data + 2) & 0x7F) != 0x06 ||
00736 EC_READ_U16(data + 6) != sdo->index ||
00737 EC_READ_U8(data + 8) != fsm->subindex) {
00738 EC_ERR("Invalid entry description response at slave %i while"
00739 " fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
00740 sdo->index, fsm->subindex);
00741 ec_print_data(data, rec_size);
00742 fsm->state = ec_fsm_coe_error;
00743 return;
00744 }
00745
00746 if (rec_size < 16) {
00747 EC_ERR("Invalid data size!\n");
00748 ec_print_data(data, rec_size);
00749 fsm->state = ec_fsm_coe_error;
00750 return;
00751 }
00752
00753 data_size = rec_size - 16;
00754
00755 if (!(entry = (ec_sdo_entry_t *)
00756 kmalloc(sizeof(ec_sdo_entry_t), GFP_ATOMIC))) {
00757 EC_ERR("Failed to allocate entry!\n");
00758 fsm->state = ec_fsm_coe_error;
00759 return;
00760 }
00761
00762 if (ec_sdo_entry_init(entry, fsm->subindex, sdo)) {
00763 EC_ERR("Failed to init entry!\n");
00764 fsm->state = ec_fsm_coe_error;
00765 return;
00766 }
00767
00768 entry->data_type = EC_READ_U16(data + 10);
00769 entry->bit_length = EC_READ_U16(data + 12);
00770
00771 if (data_size) {
00772 uint8_t *desc;
00773 if (!(desc = kmalloc(data_size + 1, GFP_ATOMIC))) {
00774 EC_ERR("Failed to allocate SDO entry name!\n");
00775 fsm->state = ec_fsm_coe_error;
00776 return;
00777 }
00778 memcpy(desc, data + 16, data_size);
00779 desc[data_size] = 0;
00780 entry->description = desc;
00781 }
00782
00783 list_add_tail(&entry->list, &sdo->entries);
00784
00785 if (fsm->subindex < sdo->subindices) {
00786 fsm->subindex++;
00787
00788 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
00789 fsm->state = ec_fsm_coe_error;
00790 return;
00791 }
00792
00793 EC_WRITE_U16(data, 0x8 << 12);
00794 EC_WRITE_U8 (data + 2, 0x05);
00795 EC_WRITE_U8 (data + 3, 0x00);
00796 EC_WRITE_U16(data + 4, 0x0000);
00797 EC_WRITE_U16(data + 6, sdo->index);
00798 EC_WRITE_U8 (data + 8, fsm->subindex);
00799 EC_WRITE_U8 (data + 9, 0x00);
00800
00801 ec_master_queue_datagram(fsm->slave->master, datagram);
00802 fsm->state = ec_fsm_coe_dict_entry_request;
00803 return;
00804 }
00805
00806
00807 if (fsm->sdo->list.next != &slave->sdo_dictionary) {
00808 fsm->sdo = list_entry(fsm->sdo->list.next, ec_sdo_t, list);
00809
00810 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 8))) {
00811 fsm->state = ec_fsm_coe_error;
00812 return;
00813 }
00814
00815 EC_WRITE_U16(data, 0x8 << 12);
00816 EC_WRITE_U8 (data + 2, 0x03);
00817 EC_WRITE_U8 (data + 3, 0x00);
00818 EC_WRITE_U16(data + 4, 0x0000);
00819 EC_WRITE_U16(data + 6, fsm->sdo->index);
00820
00821 ec_master_queue_datagram(fsm->slave->master, datagram);
00822 fsm->state = ec_fsm_coe_dict_desc_request;
00823 return;
00824 }
00825
00826 fsm->state = ec_fsm_coe_end;
00827 }
00828
00829
00830
00831
00832
00837 void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm )
00838 {
00839 ec_datagram_t *datagram = fsm->datagram;
00840 ec_slave_t *slave = fsm->slave;
00841 ec_sdo_data_t *sdodata = fsm->sdodata;
00842 uint8_t *data;
00843
00844 if (fsm->slave->master->debug_level)
00845 EC_DBG("Downloading SDO 0x%04X:%i to slave %i.\n",
00846 sdodata->index, sdodata->subindex, slave->ring_position);
00847
00848 if (slave->sii_rx_mailbox_size < 6 + 10 + sdodata->size) {
00849 EC_ERR("SDO fragmenting not supported yet!\n");
00850 fsm->state = ec_fsm_coe_error;
00851 return;
00852 }
00853
00854 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
00855 sdodata->size + 10))) {
00856 fsm->state = ec_fsm_coe_error;
00857 return;
00858 }
00859
00860 EC_WRITE_U16(data, 0x2 << 12);
00861 EC_WRITE_U8 (data + 2, (0x1
00862 | 0x1 << 5));
00863 EC_WRITE_U16(data + 3, sdodata->index);
00864 EC_WRITE_U8 (data + 5, sdodata->subindex);
00865 EC_WRITE_U32(data + 6, sdodata->size);
00866 memcpy(data + 10, sdodata->data, sdodata->size);
00867
00868 ec_master_queue_datagram(fsm->slave->master, datagram);
00869 fsm->state = ec_fsm_coe_down_request;
00870 }
00871
00872
00873
00878 void ec_fsm_coe_down_request(ec_fsm_coe_t *fsm )
00879 {
00880 ec_datagram_t *datagram = fsm->datagram;
00881 ec_slave_t *slave = fsm->slave;
00882
00883 if (datagram->state != EC_DATAGRAM_RECEIVED
00884 || datagram->working_counter != 1) {
00885 fsm->state = ec_fsm_coe_error;
00886 EC_ERR("Reception of CoE download request failed.\n");
00887 return;
00888 }
00889
00890 fsm->cycles_start = datagram->cycles_sent;
00891
00892 ec_slave_mbox_prepare_check(slave, datagram);
00893 ec_master_queue_datagram(fsm->slave->master, datagram);
00894 fsm->state = ec_fsm_coe_down_check;
00895 }
00896
00897
00898
00903 void ec_fsm_coe_down_check(ec_fsm_coe_t *fsm )
00904 {
00905 ec_datagram_t *datagram = fsm->datagram;
00906 ec_slave_t *slave = fsm->slave;
00907
00908 if (datagram->state != EC_DATAGRAM_RECEIVED
00909 || datagram->working_counter != 1) {
00910 fsm->state = ec_fsm_coe_error;
00911 EC_ERR("Reception of CoE mailbox check datagram failed.\n");
00912 return;
00913 }
00914
00915 if (!ec_slave_mbox_check(datagram)) {
00916 if (datagram->cycles_received
00917 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
00918 fsm->state = ec_fsm_coe_error;
00919 EC_ERR("Timeout while checking SDO configuration on slave %i.\n",
00920 slave->ring_position);
00921 return;
00922 }
00923
00924 ec_slave_mbox_prepare_check(slave, datagram);
00925 ec_master_queue_datagram(fsm->slave->master, datagram);
00926 return;
00927 }
00928
00929
00930 ec_slave_mbox_prepare_fetch(slave, datagram);
00931 ec_master_queue_datagram(fsm->slave->master, datagram);
00932 fsm->state = ec_fsm_coe_down_response;
00933 }
00934
00935
00936
00941 void ec_fsm_coe_down_response(ec_fsm_coe_t *fsm )
00942 {
00943 ec_datagram_t *datagram = fsm->datagram;
00944 ec_slave_t *slave = fsm->slave;
00945 uint8_t *data, mbox_prot;
00946 size_t rec_size;
00947 ec_sdo_data_t *sdodata = fsm->sdodata;
00948
00949 if (datagram->state != EC_DATAGRAM_RECEIVED
00950 || datagram->working_counter != 1) {
00951 fsm->state = ec_fsm_coe_error;
00952 EC_ERR("Reception of CoE download response failed.\n");
00953 return;
00954 }
00955
00956 if (!(data = ec_slave_mbox_fetch(slave, datagram,
00957 &mbox_prot, &rec_size))) {
00958 fsm->state = ec_fsm_coe_error;
00959 return;
00960 }
00961
00962 if (mbox_prot != 0x03) {
00963 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
00964 fsm->state = ec_fsm_coe_error;
00965 return;
00966 }
00967
00968 if (rec_size < 6) {
00969 fsm->state = ec_fsm_coe_error;
00970 EC_ERR("Received data is too small (%i bytes):\n", rec_size);
00971 ec_print_data(data, rec_size);
00972 return;
00973 }
00974
00975 if (EC_READ_U16(data) >> 12 == 0x2 &&
00976 EC_READ_U8 (data + 2) >> 5 == 0x4) {
00977 fsm->state = ec_fsm_coe_error;
00978 EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
00979 sdodata->index, sdodata->subindex, sdodata->size,
00980 slave->ring_position);
00981 if (rec_size < 10) {
00982 EC_ERR("Incomplete Abort command:\n");
00983 ec_print_data(data, rec_size);
00984 }
00985 else
00986 ec_canopen_abort_msg(EC_READ_U32(data + 6));
00987 return;
00988 }
00989
00990 if (EC_READ_U16(data) >> 12 != 0x3 ||
00991 EC_READ_U8 (data + 2) >> 5 != 0x3 ||
00992 EC_READ_U16(data + 3) != sdodata->index ||
00993 EC_READ_U8 (data + 5) != sdodata->subindex) {
00994 fsm->state = ec_fsm_coe_error;
00995 EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
00996 sdodata->index, sdodata->subindex, sdodata->size);
00997 EC_ERR("Invalid SDO download response at slave %i!\n",
00998 slave->ring_position);
00999 ec_print_data(data, rec_size);
01000 return;
01001 }
01002
01003 fsm->state = ec_fsm_coe_end;
01004 }
01005
01006
01007
01012 void ec_fsm_coe_up_start(ec_fsm_coe_t *fsm )
01013 {
01014 ec_datagram_t *datagram = fsm->datagram;
01015 ec_slave_t *slave = fsm->slave;
01016 ec_master_t *master = slave->master;
01017 ec_sdo_request_t *request = fsm->request;
01018 ec_sdo_t *sdo = request->sdo;
01019 ec_sdo_entry_t *entry = request->entry;
01020 uint8_t *data;
01021
01022 if (master->debug_level)
01023 EC_DBG("Uploading SDO 0x%04X:%i from slave %i.\n",
01024 sdo->index, entry->subindex, slave->ring_position);
01025
01026 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10))) {
01027 fsm->state = ec_fsm_coe_error;
01028 return;
01029 }
01030
01031 EC_WRITE_U16(data, 0x2 << 12);
01032 EC_WRITE_U8 (data + 2, 0x2 << 5);
01033 EC_WRITE_U16(data + 3, sdo->index);
01034 EC_WRITE_U8 (data + 5, entry->subindex);
01035 memset(data + 6, 0x00, 4);
01036
01037 if (master->debug_level) {
01038 EC_DBG("Upload request:\n");
01039 ec_print_data(data, 10);
01040 }
01041
01042 ec_master_queue_datagram(fsm->slave->master, datagram);
01043 fsm->state = ec_fsm_coe_up_request;
01044 }
01045
01046
01047
01052 void ec_fsm_coe_up_request(ec_fsm_coe_t *fsm )
01053 {
01054 ec_datagram_t *datagram = fsm->datagram;
01055 ec_slave_t *slave = fsm->slave;
01056
01057 if (datagram->state != EC_DATAGRAM_RECEIVED
01058 || datagram->working_counter != 1) {
01059 fsm->state = ec_fsm_coe_error;
01060 EC_ERR("Reception of CoE upload request failed.\n");
01061 return;
01062 }
01063
01064 fsm->cycles_start = datagram->cycles_sent;
01065
01066 ec_slave_mbox_prepare_check(slave, datagram);
01067 ec_master_queue_datagram(fsm->slave->master, datagram);
01068 fsm->state = ec_fsm_coe_up_check;
01069 }
01070
01071
01072
01077 void ec_fsm_coe_up_check(ec_fsm_coe_t *fsm )
01078 {
01079 ec_datagram_t *datagram = fsm->datagram;
01080 ec_slave_t *slave = fsm->slave;
01081
01082 if (datagram->state != EC_DATAGRAM_RECEIVED
01083 || datagram->working_counter != 1) {
01084 fsm->state = ec_fsm_coe_error;
01085 EC_ERR("Reception of CoE mailbox check datagram failed.\n");
01086 return;
01087 }
01088
01089 if (!ec_slave_mbox_check(datagram)) {
01090 if (datagram->cycles_received
01091 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
01092 fsm->state = ec_fsm_coe_error;
01093 EC_ERR("Timeout while checking SDO upload on slave %i.\n",
01094 slave->ring_position);
01095 return;
01096 }
01097
01098 ec_slave_mbox_prepare_check(slave, datagram);
01099 ec_master_queue_datagram(fsm->slave->master, datagram);
01100 return;
01101 }
01102
01103
01104 ec_slave_mbox_prepare_fetch(slave, datagram);
01105 ec_master_queue_datagram(fsm->slave->master, datagram);
01106 fsm->state = ec_fsm_coe_up_response;
01107 }
01108
01109
01110
01115 void ec_fsm_coe_up_response(ec_fsm_coe_t *fsm )
01116 {
01117 ec_datagram_t *datagram = fsm->datagram;
01118 ec_slave_t *slave = fsm->slave;
01119 ec_master_t *master = slave->master;
01120 uint8_t *data, mbox_prot;
01121 size_t rec_size, data_size;
01122 ec_sdo_request_t *request = fsm->request;
01123 ec_sdo_t *sdo = request->sdo;
01124 ec_sdo_entry_t *entry = request->entry;
01125 uint32_t complete_size;
01126 unsigned int expedited, size_specified;
01127
01128 if (datagram->state != EC_DATAGRAM_RECEIVED
01129 || datagram->working_counter != 1) {
01130 fsm->state = ec_fsm_coe_error;
01131 EC_ERR("Reception of CoE upload response failed.\n");
01132 return;
01133 }
01134
01135 if (!(data = ec_slave_mbox_fetch(slave, datagram,
01136 &mbox_prot, &rec_size))) {
01137 fsm->state = ec_fsm_coe_error;
01138 return;
01139 }
01140
01141 if (master->debug_level) {
01142 EC_DBG("Upload response:\n");
01143 ec_print_data(data, rec_size);
01144 }
01145
01146 if (mbox_prot != 0x03) {
01147 EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
01148 fsm->state = ec_fsm_coe_error;
01149 return;
01150 }
01151
01152 if (rec_size < 10) {
01153 EC_ERR("Received currupted SDO upload response!\n");
01154 ec_print_data(data, rec_size);
01155 fsm->state = ec_fsm_coe_error;
01156 return;
01157 }
01158
01159 if (EC_READ_U16(data) >> 12 == 0x2 &&
01160 EC_READ_U8 (data + 2) >> 5 == 0x4) {
01161 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
01162 sdo->index, entry->subindex, slave->ring_position);
01163 ec_canopen_abort_msg(EC_READ_U32(data + 6));
01164 fsm->state = ec_fsm_coe_error;
01165 return;
01166 }
01167
01168 if (EC_READ_U16(data) >> 12 != 0x3 ||
01169 EC_READ_U8 (data + 2) >> 5 != 0x2 ||
01170 EC_READ_U16(data + 3) != sdo->index ||
01171 EC_READ_U8 (data + 5) != entry->subindex) {
01172 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo->index, entry->subindex);
01173 EC_ERR("Invalid SDO upload response at slave %i!\n",
01174 slave->ring_position);
01175 ec_print_data(data, rec_size);
01176 fsm->state = ec_fsm_coe_error;
01177 return;
01178 }
01179
01180 data_size = rec_size - 10;
01181 expedited = EC_READ_U8(data + 2) & 0x02;
01182
01183 if (expedited) {
01184 size_specified = EC_READ_U8(data + 2) & 0x01;
01185 if (size_specified) {
01186 complete_size = 4 - ((EC_READ_U8(data + 2) & 0x0C) >> 2);
01187 }
01188 else {
01189 complete_size = 4;
01190 }
01191 }
01192 else {
01193 complete_size = EC_READ_U32(data + 6);
01194 }
01195
01196 if (request->data) {
01197 kfree(request->data);
01198 request->data = NULL;
01199 }
01200 request->size = 0;
01201
01202 if (complete_size) {
01203 if (!(request->data = (uint8_t *)
01204 kmalloc(complete_size + 1, GFP_ATOMIC))) {
01205 EC_ERR("Failed to allocate %i bytes of SDO data!\n",
01206 complete_size);
01207 fsm->state = ec_fsm_coe_error;
01208 return;
01209 }
01210 request->data[complete_size] = 0x00;
01211 }
01212
01213 if (expedited) {
01214 memcpy(request->data, data + 6, complete_size);
01215 request->size = complete_size;
01216 }
01217 else {
01218 memcpy(request->data, data + 10, data_size);
01219 request->size = data_size;
01220 fsm->toggle = 0;
01221
01222 if (data_size < complete_size) {
01223 EC_WARN("SDO data incomplete (%i / %i).\n",
01224 data_size, complete_size);
01225
01226 if (!(data = ec_slave_mbox_prepare_send(slave, datagram,
01227 0x03, 3))) {
01228 fsm->state = ec_fsm_coe_error;
01229 return;
01230 }
01231
01232 EC_WRITE_U16(data, 0x2 << 12);
01233 EC_WRITE_U8 (data + 2, (fsm->toggle << 4
01234 | 0x3 << 5));
01235
01236 if (master->debug_level) {
01237 EC_DBG("Upload segment request:\n");
01238 ec_print_data(data, 3);
01239 }
01240
01241 ec_master_queue_datagram(fsm->slave->master, datagram);
01242 fsm->state = ec_fsm_coe_up_seg_request;
01243 return;
01244 }
01245 }
01246
01247 fsm->state = ec_fsm_coe_end;
01248 }
01249
01250
01251
01256 void ec_fsm_coe_up_seg_request(ec_fsm_coe_t *fsm )
01257 {
01258 ec_datagram_t *datagram = fsm->datagram;
01259 ec_slave_t *slave = fsm->slave;
01260
01261 if (datagram->state != EC_DATAGRAM_RECEIVED
01262 || datagram->working_counter != 1) {
01263 fsm->state = ec_fsm_coe_error;
01264 EC_ERR("Reception of CoE upload segment request failed.\n");
01265 return;
01266 }
01267
01268 fsm->cycles_start = datagram->cycles_sent;
01269
01270 ec_slave_mbox_prepare_check(slave, datagram);
01271 ec_master_queue_datagram(fsm->slave->master, datagram);
01272 fsm->state = ec_fsm_coe_up_seg_check;
01273 }
01274
01275
01276
01281 void ec_fsm_coe_up_seg_check(ec_fsm_coe_t *fsm )
01282 {
01283 ec_datagram_t *datagram = fsm->datagram;
01284 ec_slave_t *slave = fsm->slave;
01285
01286 if (datagram->state != EC_DATAGRAM_RECEIVED
01287 || datagram->working_counter != 1) {
01288 fsm->state = ec_fsm_coe_error;
01289 EC_ERR("Reception of CoE mailbox check datagram failed.\n");
01290 return;
01291 }
01292
01293 if (!ec_slave_mbox_check(datagram)) {
01294 if (datagram->cycles_received
01295 - fsm->cycles_start >= (cycles_t) 100 * cpu_khz) {
01296 fsm->state = ec_fsm_coe_error;
01297 EC_ERR("Timeout while checking SDO upload segment on slave %i.\n",
01298 slave->ring_position);
01299 return;
01300 }
01301
01302 ec_slave_mbox_prepare_check(slave, datagram);
01303 ec_master_queue_datagram(fsm->slave->master, datagram);
01304 return;
01305 }
01306
01307
01308 ec_slave_mbox_prepare_fetch(slave, datagram);
01309 ec_master_queue_datagram(fsm->slave->master, datagram);
01310 fsm->state = ec_fsm_coe_up_seg_response;
01311 }
01312
01313
01314
01319 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm )
01320 {
01321 ec_datagram_t *datagram = fsm->datagram;
01322 ec_slave_t *slave = fsm->slave;
01323 ec_master_t *master = slave->master;
01324 uint8_t *data, mbox_prot;
01325 size_t rec_size, data_size;
01326 ec_sdo_request_t *request = fsm->request;
01327 ec_sdo_t *sdo = request->sdo;
01328 ec_sdo_entry_t *entry = request->entry;
01329 uint32_t seg_size;
01330 unsigned int last_segment;
01331
01332 if (datagram->state != EC_DATAGRAM_RECEIVED
01333 || datagram->working_counter != 1) {
01334 fsm->state = ec_fsm_coe_error;
01335 EC_ERR("Reception of CoE upload segment response failed.\n");
01336 return;
01337 }
01338
01339 if (!(data = ec_slave_mbox_fetch(slave, datagram,
01340 &mbox_prot, &rec_size))) {
01341 fsm->state = ec_fsm_coe_error;
01342 return;
01343 }
01344
01345 if (master->debug_level) {
01346 EC_DBG("Upload segment response:\n");
01347 ec_print_data(data, rec_size);
01348 }
01349
01350 if (mbox_prot != 0x03) {
01351 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
01352 fsm->state = ec_fsm_coe_error;
01353 return;
01354 }
01355
01356 if (rec_size < 10) {
01357 EC_ERR("Received currupted SDO upload segment response!\n");
01358 ec_print_data(data, rec_size);
01359 fsm->state = ec_fsm_coe_error;
01360 return;
01361 }
01362
01363 if (EC_READ_U16(data) >> 12 == 0x2 &&
01364 EC_READ_U8 (data + 2) >> 5 == 0x4) {
01365 EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
01366 sdo->index, entry->subindex, slave->ring_position);
01367 ec_canopen_abort_msg(EC_READ_U32(data + 6));
01368 fsm->state = ec_fsm_coe_error;
01369 return;
01370 }
01371
01372 if (EC_READ_U16(data) >> 12 != 0x3 ||
01373 EC_READ_U8 (data + 2) >> 5 != 0x0) {
01374 EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo->index, entry->subindex);
01375 EC_ERR("Invalid SDO upload segment response at slave %i!\n",
01376 slave->ring_position);
01377 ec_print_data(data, rec_size);
01378 fsm->state = ec_fsm_coe_error;
01379 return;
01380 }
01381
01382 last_segment = EC_READ_U8(data + 2) & 0x01;
01383 seg_size = (EC_READ_U8(data + 2) & 0xE) >> 1;
01384 data_size = rec_size - 10;
01385
01386 if (data_size != seg_size) {
01387 EC_WARN("SDO segment data invalid (%i / %i)"
01388 " - Fragmenting not implemented.\n",
01389 data_size, seg_size);
01390 }
01391
01392 memcpy(request->data + request->size, data + 10, data_size);
01393 request->size += data_size;
01394
01395 if (!last_segment) {
01396 fsm->toggle = !fsm->toggle;
01397
01398 if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {
01399 fsm->state = ec_fsm_coe_error;
01400 return;
01401 }
01402
01403 EC_WRITE_U16(data, 0x2 << 12);
01404 EC_WRITE_U8 (data + 2, (fsm->toggle << 4
01405 | 0x3 << 5));
01406
01407 if (master->debug_level) {
01408 EC_DBG("Upload segment request:\n");
01409 ec_print_data(data, 3);
01410 }
01411
01412 ec_master_queue_datagram(fsm->slave->master, datagram);
01413 fsm->state = ec_fsm_coe_up_seg_request;
01414 return;
01415 }
01416
01417 fsm->state = ec_fsm_coe_end;
01418 }
01419
01420
01421
01426 void ec_fsm_coe_error(ec_fsm_coe_t *fsm )
01427 {
01428 }
01429
01430
01431
01436 void ec_fsm_coe_end(ec_fsm_coe_t *fsm )
01437 {
01438 }
01439
01440