1089 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
1095 EC_ERR("Slave %u does not support CoE!\n", slave->ring_position); |
1090 fsm->state = ec_fsm_coe_error; |
1096 fsm->state = ec_fsm_coe_error; |
1091 return; |
1097 return; |
1092 } |
1098 } |
1093 |
1099 |
|
1100 if (slave->configured_rx_mailbox_size < |
|
1101 EC_MBOX_HEADER_SIZE + EC_COE_DOWN_REQ_HEADER_SIZE) { |
|
1102 EC_ERR("Mailbox too small!\n"); |
|
1103 fsm->state = ec_fsm_coe_error; |
|
1104 return; |
|
1105 } |
|
1106 |
1094 if (request->data_size <= 4) { // use expedited transfer type |
1107 if (request->data_size <= 4) { // use expedited transfer type |
1095 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 10); |
1108 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
|
1109 EC_COE_DOWN_REQ_HEADER_SIZE); |
1096 if (IS_ERR(data)) { |
1110 if (IS_ERR(data)) { |
1097 fsm->state = ec_fsm_coe_error; |
1111 fsm->state = ec_fsm_coe_error; |
1098 return; |
1112 return; |
1099 } |
1113 } |
1100 |
1114 |
1101 size = 4 - request->data_size; |
1115 fsm->remaining = 0; |
|
1116 |
|
1117 data_set_size = 4 - request->data_size; |
1102 |
1118 |
1103 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1119 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1104 EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited |
1120 EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited |
1105 | size << 2 |
1121 | data_set_size << 2 |
1106 | ((request->complete_access ? 1 : 0) << 4) |
1122 | ((request->complete_access ? 1 : 0) << 4) |
1107 | 0x1 << 5)); // Download request |
1123 | 0x1 << 5)); // Download request |
1108 EC_WRITE_U16(data + 3, request->index); |
1124 EC_WRITE_U16(data + 3, request->index); |
1109 EC_WRITE_U8 (data + 5, |
1125 EC_WRITE_U8 (data + 5, |
1110 request->complete_access ? 0x00 : request->subindex); |
1126 request->complete_access ? 0x00 : request->subindex); |
1111 memcpy(data + 6, request->data, request->data_size); |
1127 memcpy(data + 6, request->data, request->data_size); |
1112 memset(data + 6 + request->data_size, 0x00, 4 - request->data_size); |
1128 memset(data + 6 + request->data_size, 0x00, 4 - request->data_size); |
1113 |
1129 |
1114 if (slave->master->debug_level) { |
1130 if (slave->master->debug_level) { |
1115 EC_DBG("Expedited download request:\n"); |
1131 EC_DBG("Expedited download request:\n"); |
1116 ec_print_data(data, 10); |
1132 ec_print_data(data, EC_COE_DOWN_REQ_HEADER_SIZE); |
1117 } |
1133 } |
1118 } |
1134 } |
1119 else { // request->data_size > 4, use normal transfer type |
1135 else { // request->data_size > 4, use normal transfer type |
1120 if (slave->configured_rx_mailbox_size < 6 + 10 + request->data_size) { |
1136 size_t data_size, |
1121 EC_ERR("SDO fragmenting not supported yet!\n"); // FIXME |
1137 max_data_size = |
1122 fsm->state = ec_fsm_coe_error; |
1138 slave->configured_rx_mailbox_size - EC_MBOX_HEADER_SIZE, |
1123 return; |
1139 required_data_size = |
|
1140 EC_COE_DOWN_REQ_HEADER_SIZE + request->data_size; |
|
1141 |
|
1142 if (max_data_size < required_data_size) { |
|
1143 // segmenting needed |
|
1144 data_size = max_data_size; |
|
1145 } else { |
|
1146 data_size = required_data_size; |
1124 } |
1147 } |
1125 |
1148 |
1126 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
1149 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
1127 request->data_size + 10); |
1150 data_size); |
1128 if (IS_ERR(data)) { |
1151 if (IS_ERR(data)) { |
1129 fsm->state = ec_fsm_coe_error; |
1152 fsm->state = ec_fsm_coe_error; |
1130 return; |
1153 return; |
1131 } |
1154 } |
1132 |
1155 |
|
1156 fsm->offset = 0; |
|
1157 fsm->remaining = request->data_size; |
|
1158 |
1133 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1159 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
1134 EC_WRITE_U8 (data + 2, (0x1 // size indicator, normal |
1160 EC_WRITE_U8(data + 2, |
1135 | ((request->complete_access ? 1 : 0) << 4) |
1161 0x1 // size indicator, normal |
1136 | 0x1 << 5)); // Download request |
1162 | ((request->complete_access ? 1 : 0) << 4) |
|
1163 | 0x1 << 5); // Download request |
1137 EC_WRITE_U16(data + 3, request->index); |
1164 EC_WRITE_U16(data + 3, request->index); |
1138 EC_WRITE_U8 (data + 5, |
1165 EC_WRITE_U8 (data + 5, |
1139 request->complete_access ? 0x00 : request->subindex); |
1166 request->complete_access ? 0x00 : request->subindex); |
1140 EC_WRITE_U32(data + 6, request->data_size); |
1167 EC_WRITE_U32(data + 6, request->data_size); |
1141 memcpy(data + 10, request->data, request->data_size); |
1168 |
|
1169 if (data_size > EC_COE_DOWN_REQ_HEADER_SIZE) { |
|
1170 size_t segment_size = data_size - EC_COE_DOWN_REQ_HEADER_SIZE; |
|
1171 memcpy(data + EC_COE_DOWN_REQ_HEADER_SIZE, |
|
1172 request->data, segment_size); |
|
1173 fsm->offset += segment_size; |
|
1174 fsm->remaining -= segment_size; |
|
1175 } |
1142 |
1176 |
1143 if (slave->master->debug_level) { |
1177 if (slave->master->debug_level) { |
1144 EC_DBG("Normal download request:\n"); |
1178 EC_DBG("Normal download request:\n"); |
1145 ec_print_data(data, 10 + request->data_size); |
1179 ec_print_data(data, data_size); |
1146 } |
1180 } |
1147 } |
1181 } |
1148 |
1182 |
1149 fsm->request->jiffies_sent = jiffies; |
1183 fsm->request->jiffies_sent = jiffies; |
1150 fsm->retries = EC_FSM_RETRIES; |
1184 fsm->retries = EC_FSM_RETRIES; |
1253 fsm->state = ec_fsm_coe_down_response; |
1287 fsm->state = ec_fsm_coe_down_response; |
1254 } |
1288 } |
1255 |
1289 |
1256 /*****************************************************************************/ |
1290 /*****************************************************************************/ |
1257 |
1291 |
|
1292 void ec_fsm_coe_down_prepare_segment_request( |
|
1293 ec_fsm_coe_t *fsm /**< finite state machine */ |
|
1294 ) |
|
1295 { |
|
1296 ec_datagram_t *datagram = fsm->datagram; |
|
1297 ec_slave_t *slave = fsm->slave; |
|
1298 ec_sdo_request_t *request = fsm->request; |
|
1299 size_t max_segment_size = |
|
1300 slave->configured_rx_mailbox_size |
|
1301 - EC_MBOX_HEADER_SIZE |
|
1302 - EC_COE_DOWN_SEG_REQ_HEADER_SIZE; |
|
1303 size_t segment_size, data_size; |
|
1304 uint8_t last_segment, seg_data_size, *data; |
|
1305 |
|
1306 if (fsm->remaining > max_segment_size) { |
|
1307 segment_size = max_segment_size; |
|
1308 last_segment = 0; |
|
1309 } else { |
|
1310 segment_size = fsm->remaining; |
|
1311 last_segment = 1; |
|
1312 } |
|
1313 |
|
1314 if (segment_size > EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
|
1315 seg_data_size = 0x00; |
|
1316 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE + segment_size; |
|
1317 } else { |
|
1318 seg_data_size = EC_COE_DOWN_SEG_MIN_DATA_SIZE - segment_size; |
|
1319 data_size = EC_COE_DOWN_SEG_REQ_HEADER_SIZE |
|
1320 + EC_COE_DOWN_SEG_MIN_DATA_SIZE; |
|
1321 } |
|
1322 |
|
1323 data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, |
|
1324 data_size); |
|
1325 if (IS_ERR(data)) { |
|
1326 fsm->state = ec_fsm_coe_error; |
|
1327 return; |
|
1328 } |
|
1329 |
|
1330 EC_WRITE_U16(data, 0x2 << 12); // SDO request |
|
1331 EC_WRITE_U8(data + 2, (last_segment ? 1 : 0) |
|
1332 | (seg_data_size << 1) |
|
1333 | (fsm->toggle << 4) |
|
1334 | (0x00 << 5)); // Download segment request |
|
1335 memcpy(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE, |
|
1336 request->data + fsm->offset, segment_size); |
|
1337 if (segment_size < EC_COE_DOWN_SEG_MIN_DATA_SIZE) { |
|
1338 memset(data + EC_COE_DOWN_SEG_REQ_HEADER_SIZE + segment_size, 0x00, |
|
1339 EC_COE_DOWN_SEG_MIN_DATA_SIZE - segment_size); |
|
1340 } |
|
1341 |
|
1342 fsm->offset += segment_size; |
|
1343 fsm->remaining -= segment_size; |
|
1344 |
|
1345 if (slave->master->debug_level) { |
|
1346 EC_DBG("Download segment request:\n"); |
|
1347 ec_print_data(data, data_size); |
|
1348 } |
|
1349 |
|
1350 fsm->state = ec_fsm_coe_down_seg_check; |
|
1351 } |
|
1352 |
|
1353 /*****************************************************************************/ |
|
1354 |
1258 /** |
1355 /** |
1259 CoE state: DOWN RESPONSE. |
1356 CoE state: DOWN RESPONSE. |
1260 \todo Timeout behavior |
1357 \todo Timeout behavior |
1261 */ |
1358 */ |
1262 |
1359 |
1355 fsm->retries = EC_FSM_RETRIES; |
1452 fsm->retries = EC_FSM_RETRIES; |
1356 fsm->state = ec_fsm_coe_down_check; |
1453 fsm->state = ec_fsm_coe_down_check; |
1357 return; |
1454 return; |
1358 } |
1455 } |
1359 |
1456 |
1360 fsm->state = ec_fsm_coe_end; // success |
1457 if (fsm->remaining) { // more segments to download |
|
1458 fsm->toggle = 0; |
|
1459 ec_fsm_coe_down_prepare_segment_request(fsm); |
|
1460 } else { |
|
1461 fsm->state = ec_fsm_coe_end; // success |
|
1462 } |
|
1463 } |
|
1464 |
|
1465 /*****************************************************************************/ |
|
1466 |
|
1467 /** |
|
1468 CoE state: DOWN SEG CHECK. |
|
1469 */ |
|
1470 |
|
1471 void ec_fsm_coe_down_seg_check(ec_fsm_coe_t *fsm /**< finite state machine */) |
|
1472 { |
|
1473 ec_datagram_t *datagram = fsm->datagram; |
|
1474 ec_slave_t *slave = fsm->slave; |
|
1475 |
|
1476 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
|
1477 return; |
|
1478 |
|
1479 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
|
1480 fsm->state = ec_fsm_coe_error; |
|
1481 EC_ERR("Failed to receive CoE mailbox check datagram for slave %u" |
|
1482 " (datagram state %u).\n", |
|
1483 slave->ring_position, datagram->state); |
|
1484 return; |
|
1485 } |
|
1486 |
|
1487 if (datagram->working_counter != 1) { |
|
1488 fsm->state = ec_fsm_coe_error; |
|
1489 EC_ERR("Reception of CoE mailbox segment check" |
|
1490 " datagram failed on slave %u: ", slave->ring_position); |
|
1491 ec_datagram_print_wc_error(datagram); |
|
1492 return; |
|
1493 } |
|
1494 |
|
1495 if (!ec_slave_mbox_check(datagram)) { |
|
1496 unsigned long diff_ms = |
|
1497 (datagram->jiffies_received - fsm->jiffies_start) * 1000 / HZ; |
|
1498 if (diff_ms >= fsm->request->response_timeout) { |
|
1499 fsm->state = ec_fsm_coe_error; |
|
1500 EC_ERR("Timeout while waiting for SDO download segment response " |
|
1501 "on slave %u.\n", slave->ring_position); |
|
1502 return; |
|
1503 } |
|
1504 |
|
1505 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
|
1506 fsm->retries = EC_FSM_RETRIES; |
|
1507 return; |
|
1508 } |
|
1509 |
|
1510 // Fetch response |
|
1511 ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail. |
|
1512 fsm->retries = EC_FSM_RETRIES; |
|
1513 fsm->state = ec_fsm_coe_down_seg_response; |
|
1514 } |
|
1515 |
|
1516 /*****************************************************************************/ |
|
1517 |
|
1518 /** |
|
1519 CoE state: DOWN SEG RESPONSE. |
|
1520 \todo Timeout behavior |
|
1521 */ |
|
1522 |
|
1523 void ec_fsm_coe_down_seg_response( |
|
1524 ec_fsm_coe_t *fsm /**< finite state machine */ |
|
1525 ) |
|
1526 { |
|
1527 ec_datagram_t *datagram = fsm->datagram; |
|
1528 ec_slave_t *slave = fsm->slave; |
|
1529 uint8_t *data, mbox_prot; |
|
1530 size_t rec_size; |
|
1531 ec_sdo_request_t *request = fsm->request; |
|
1532 |
|
1533 if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--) |
|
1534 return; // FIXME: request again? |
|
1535 |
|
1536 if (datagram->state != EC_DATAGRAM_RECEIVED) { |
|
1537 fsm->state = ec_fsm_coe_error; |
|
1538 EC_ERR("Failed to receive CoE download response datagram from" |
|
1539 " slave %u (datagram state %u).\n", |
|
1540 slave->ring_position, datagram->state); |
|
1541 return; |
|
1542 } |
|
1543 |
|
1544 if (datagram->working_counter != 1) { |
|
1545 fsm->state = ec_fsm_coe_error; |
|
1546 EC_ERR("Reception of CoE download response failed on slave %u: ", |
|
1547 slave->ring_position); |
|
1548 ec_datagram_print_wc_error(datagram); |
|
1549 return; |
|
1550 } |
|
1551 |
|
1552 data = ec_slave_mbox_fetch(slave, datagram, &mbox_prot, &rec_size); |
|
1553 if (IS_ERR(data)) { |
|
1554 fsm->state = ec_fsm_coe_error; |
|
1555 return; |
|
1556 } |
|
1557 |
|
1558 if (mbox_prot != 0x03) { // CoE |
|
1559 fsm->state = ec_fsm_coe_error; |
|
1560 EC_ERR("Received mailbox protocol 0x%02X as response.\n", mbox_prot); |
|
1561 return; |
|
1562 } |
|
1563 |
|
1564 if (ec_fsm_coe_check_emergency(fsm, data, rec_size)) { |
|
1565 // check for CoE response again |
|
1566 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
|
1567 fsm->retries = EC_FSM_RETRIES; |
|
1568 fsm->state = ec_fsm_coe_down_check; |
|
1569 return; |
|
1570 } |
|
1571 |
|
1572 if (slave->master->debug_level) { |
|
1573 EC_DBG("Download response:\n"); |
|
1574 ec_print_data(data, rec_size); |
|
1575 } |
|
1576 |
|
1577 if (rec_size < 6) { |
|
1578 fsm->state = ec_fsm_coe_error; |
|
1579 EC_ERR("Received data are too small (%zu bytes):\n", rec_size); |
|
1580 ec_print_data(data, rec_size); |
|
1581 return; |
|
1582 } |
|
1583 |
|
1584 if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request |
|
1585 EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request |
|
1586 char subidxstr[10]; |
|
1587 fsm->state = ec_fsm_coe_error; |
|
1588 if (request->complete_access) { |
|
1589 subidxstr[0] = 0x00; |
|
1590 } else { |
|
1591 sprintf(subidxstr, ":%02X", request->subindex); |
|
1592 } |
|
1593 EC_ERR("SDO download 0x%04X%s (%zu bytes) aborted on slave %u.\n", |
|
1594 request->index, subidxstr, request->data_size, |
|
1595 slave->ring_position); |
|
1596 if (rec_size < 10) { |
|
1597 EC_ERR("Incomplete abort command:\n"); |
|
1598 ec_print_data(data, rec_size); |
|
1599 } else { |
|
1600 fsm->request->abort_code = EC_READ_U32(data + 6); |
|
1601 ec_canopen_abort_msg(fsm->request->abort_code); |
|
1602 } |
|
1603 return; |
|
1604 } |
|
1605 |
|
1606 if (EC_READ_U16(data) >> 12 != 0x3 || |
|
1607 ((EC_READ_U8(data + 2) >> 5) != 0x01)) { // segment response |
|
1608 if (slave->master->debug_level) { |
|
1609 EC_DBG("Invalid SDO download response at slave %u! Retrying...\n", |
|
1610 slave->ring_position); |
|
1611 ec_print_data(data, rec_size); |
|
1612 } |
|
1613 // check for CoE response again |
|
1614 ec_slave_mbox_prepare_check(slave, datagram); // can not fail. |
|
1615 fsm->retries = EC_FSM_RETRIES; |
|
1616 fsm->state = ec_fsm_coe_down_seg_check; |
|
1617 return; |
|
1618 } |
|
1619 |
|
1620 if (((EC_READ_U8(data + 2) >> 4) & 0x01) != fsm->toggle) { |
|
1621 EC_ERR("Invalid toggle received during segmented download:\n"); |
|
1622 ec_print_data(data, rec_size); |
|
1623 fsm->state = ec_fsm_coe_error; |
|
1624 return; |
|
1625 } |
|
1626 |
|
1627 if (fsm->remaining) { // more segments to download |
|
1628 fsm->toggle = !fsm->toggle; |
|
1629 ec_fsm_coe_down_prepare_segment_request(fsm); |
|
1630 } else { |
|
1631 fsm->state = ec_fsm_coe_end; // success |
|
1632 } |
1361 } |
1633 } |
1362 |
1634 |
1363 /*****************************************************************************/ |
1635 /*****************************************************************************/ |
1364 |
1636 |
1365 /** |
1637 /** |