master/fsm_coe.c
changeset 854 f4f53be425ac
parent 834 0791aac03180
child 859 233e32f428e1
equal deleted inserted replaced
853:726326d0aef4 854:f4f53be425ac
   181 
   181 
   182 /**
   182 /**
   183    Starts to download an Sdo to a slave.
   183    Starts to download an Sdo to a slave.
   184 */
   184 */
   185 
   185 
   186 void ec_fsm_coe_download(ec_fsm_coe_t *fsm, /**< finite state machine */
   186 void ec_fsm_coe_download(
   187                          ec_slave_t *slave, /**< EtherCAT slave */
   187         ec_fsm_coe_t *fsm, /**< State machine. */
   188                          ec_sdo_data_t *sdodata /**< Sdo data object */
   188         ec_slave_t *slave, /**< EtherCAT slave. */
   189                          )
   189         ec_sdo_request_t *request /**< Sdo request. */
       
   190         )
   190 {
   191 {
   191     fsm->slave = slave;
   192     fsm->slave = slave;
   192     fsm->sdodata = sdodata;
   193     fsm->request = request;
   193     fsm->state = ec_fsm_coe_down_start;
   194     fsm->state = ec_fsm_coe_down_start;
   194 }
   195 }
   195 
   196 
   196 /*****************************************************************************/
   197 /*****************************************************************************/
   197 
   198 
   952 
   953 
   953 void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
   954 void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
   954 {
   955 {
   955     ec_datagram_t *datagram = fsm->datagram;
   956     ec_datagram_t *datagram = fsm->datagram;
   956     ec_slave_t *slave = fsm->slave;
   957     ec_slave_t *slave = fsm->slave;
   957     ec_sdo_data_t *sdodata = fsm->sdodata;
   958     ec_sdo_request_t *request = fsm->request;
   958     uint8_t *data;
   959     uint8_t *data;
   959 
   960 
   960     if (fsm->slave->master->debug_level)
   961     if (fsm->slave->master->debug_level)
   961         EC_DBG("Downloading Sdo 0x%04X:%i to slave %i.\n",
   962         EC_DBG("Downloading Sdo 0x%04X:%i to slave %i.\n",
   962                sdodata->index, sdodata->subindex, slave->ring_position);
   963                request->index, request->subindex, slave->ring_position);
   963 
   964 
   964     if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
   965     if (!(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
   965         EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
   966         EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
   966         fsm->state = ec_fsm_coe_error;
   967         fsm->state = ec_fsm_coe_error;
   967         return;
   968         return;
   968     }
   969     }
   969 
   970 
   970     if (slave->sii.rx_mailbox_size < 6 + 10 + sdodata->size) {
   971     if (slave->sii.rx_mailbox_size < 6 + 10 + request->data_size) {
   971         EC_ERR("Sdo fragmenting not supported yet!\n");
   972         EC_ERR("Sdo fragmenting not supported yet!\n");
   972         fsm->state = ec_fsm_coe_error;
   973         fsm->state = ec_fsm_coe_error;
   973         return;
   974         return;
   974     }
   975     }
   975 
   976 
   976     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
   977     if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03,
   977                                             sdodata->size + 10))) {
   978                                             request->data_size + 10))) {
   978         fsm->state = ec_fsm_coe_error;
   979         fsm->state = ec_fsm_coe_error;
   979         return;
   980         return;
   980     }
   981     }
   981 
   982 
   982     EC_WRITE_U16(data, 0x2 << 12); // Sdo request
   983     EC_WRITE_U16(data, 0x2 << 12); // Sdo request
   983     EC_WRITE_U8 (data + 2, (0x1 // size specified
   984     EC_WRITE_U8 (data + 2, (0x1 // size specified
   984                             | 0x1 << 5)); // Download request
   985                             | 0x1 << 5)); // Download request
   985     EC_WRITE_U16(data + 3, sdodata->index);
   986     EC_WRITE_U16(data + 3, request->index);
   986     EC_WRITE_U8 (data + 5, sdodata->subindex);
   987     EC_WRITE_U8 (data + 5, request->subindex);
   987     EC_WRITE_U32(data + 6, sdodata->size);
   988     EC_WRITE_U32(data + 6, request->data_size);
   988     memcpy(data + 10, sdodata->data, sdodata->size);
   989     memcpy(data + 10, request->data, request->data_size);
   989 
   990 
   990     fsm->retries = EC_FSM_RETRIES;
   991     fsm->retries = EC_FSM_RETRIES;
   991     fsm->state = ec_fsm_coe_down_request;
   992     fsm->state = ec_fsm_coe_down_request;
   992 }
   993 }
   993 
   994 
  1090 {
  1091 {
  1091     ec_datagram_t *datagram = fsm->datagram;
  1092     ec_datagram_t *datagram = fsm->datagram;
  1092     ec_slave_t *slave = fsm->slave;
  1093     ec_slave_t *slave = fsm->slave;
  1093     uint8_t *data, mbox_prot;
  1094     uint8_t *data, mbox_prot;
  1094     size_t rec_size;
  1095     size_t rec_size;
  1095     ec_sdo_data_t *sdodata = fsm->sdodata;
  1096     ec_sdo_request_t *request = fsm->request;
  1096 
  1097 
  1097     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
  1098     if (datagram->state == EC_DATAGRAM_TIMED_OUT && fsm->retries--)
  1098         return; // FIXME: request again?
  1099         return; // FIXME: request again?
  1099 
  1100 
  1100     if (datagram->state != EC_DATAGRAM_RECEIVED) {
  1101     if (datagram->state != EC_DATAGRAM_RECEIVED) {
  1134 
  1135 
  1135     if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
  1136     if (EC_READ_U16(data) >> 12 == 0x2 && // Sdo request
  1136         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
  1137         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
  1137         fsm->state = ec_fsm_coe_error;
  1138         fsm->state = ec_fsm_coe_error;
  1138         EC_ERR("Sdo download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
  1139         EC_ERR("Sdo download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
  1139                sdodata->index, sdodata->subindex, sdodata->size,
  1140                request->index, request->subindex, request->data_size,
  1140                slave->ring_position);
  1141                slave->ring_position);
  1141         if (rec_size < 10) {
  1142         if (rec_size < 10) {
  1142             EC_ERR("Incomplete Abort command:\n");
  1143             EC_ERR("Incomplete Abort command:\n");
  1143             ec_print_data(data, rec_size);
  1144             ec_print_data(data, rec_size);
  1144         }
  1145         }
  1147         return;
  1148         return;
  1148     }
  1149     }
  1149 
  1150 
  1150     if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
  1151     if (EC_READ_U16(data) >> 12 != 0x3 || // Sdo response
  1151         EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
  1152         EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
  1152         EC_READ_U16(data + 3) != sdodata->index || // index
  1153         EC_READ_U16(data + 3) != request->index || // index
  1153         EC_READ_U8 (data + 5) != sdodata->subindex) { // subindex
  1154         EC_READ_U8 (data + 5) != request->subindex) { // subindex
  1154         fsm->state = ec_fsm_coe_error;
  1155         fsm->state = ec_fsm_coe_error;
  1155         EC_ERR("Sdo download 0x%04X:%X (%i bytes) failed:\n",
  1156         EC_ERR("Sdo download 0x%04X:%X (%i bytes) failed:\n",
  1156                sdodata->index, sdodata->subindex, sdodata->size);
  1157                request->index, request->subindex, request->data_size);
  1157         EC_ERR("Invalid Sdo download response at slave %i!\n",
  1158         EC_ERR("Invalid Sdo download response at slave %i!\n",
  1158                slave->ring_position);
  1159                slave->ring_position);
  1159         ec_print_data(data, rec_size);
  1160         ec_print_data(data, rec_size);
  1160         return;
  1161         return;
  1161     }
  1162     }
  1365         else
  1366         else
  1366             EC_ERR("No abort message.\n");
  1367             EC_ERR("No abort message.\n");
  1367         fsm->state = ec_fsm_coe_error;
  1368         fsm->state = ec_fsm_coe_error;
  1368         return;
  1369         return;
  1369     }
  1370     }
  1370 
       
  1371     if (request->data) {
       
  1372         kfree(request->data);
       
  1373         request->data = NULL;
       
  1374     }
       
  1375     request->size = 0;
       
  1376 
  1371 
  1377     // normal or expedited?
  1372     // normal or expedited?
  1378     expedited = EC_READ_U8(data + 2) & 0x02;
  1373     expedited = EC_READ_U8(data + 2) & 0x02;
  1379 
  1374 
  1380     if (expedited) {
  1375     if (expedited) {
  1412             ec_print_data(data, rec_size);
  1407             ec_print_data(data, rec_size);
  1413             fsm->state = ec_fsm_coe_error;
  1408             fsm->state = ec_fsm_coe_error;
  1414             return;
  1409             return;
  1415         }
  1410         }
  1416 
  1411 
  1417         if (!(request->data = (uint8_t *)
  1412         if (ec_sdo_request_copy_data(request, data + 6, complete_size)) {
  1418                     kmalloc(complete_size + 1, GFP_ATOMIC))) {
  1413             fsm->state = ec_fsm_coe_error;
  1419             EC_ERR("Failed to allocate %i bytes of Sdo data!\n",
  1414             return;
  1420                     complete_size);
  1415         }
  1421             fsm->state = ec_fsm_coe_error;
       
  1422             return;
       
  1423         }
       
  1424         request->data[complete_size] = 0x00; // just to be sure...
       
  1425 
       
  1426         memcpy(request->data, data + 6, complete_size);
       
  1427         request->size = complete_size;
       
  1428 
       
  1429     } else { // normal
  1416     } else { // normal
  1430         if (rec_size < 10) {
  1417         if (rec_size < 10) {
  1431             EC_ERR("Received currupted Sdo normal upload"
  1418             EC_ERR("Received currupted Sdo normal upload"
  1432                     " response (only %u bytes)!\n", rec_size);
  1419                     " response (only %u bytes)!\n", rec_size);
  1433             ec_print_data(data, rec_size);
  1420             ec_print_data(data, rec_size);
  1456             ec_print_data(data, rec_size);
  1443             ec_print_data(data, rec_size);
  1457             fsm->state = ec_fsm_coe_error;
  1444             fsm->state = ec_fsm_coe_error;
  1458             return;
  1445             return;
  1459         }
  1446         }
  1460 
  1447 
  1461         if (!(request->data = (uint8_t *)
  1448         if (ec_sdo_request_alloc(request, complete_size)) {
  1462                     kmalloc(complete_size + 1, GFP_ATOMIC))) {
  1449             fsm->state = ec_fsm_coe_error;
  1463             EC_ERR("Failed to allocate %i bytes of Sdo data!\n",
  1450             return;
  1464                     complete_size);
  1451         }
  1465             fsm->state = ec_fsm_coe_error;
  1452 
  1466             return;
  1453         if (ec_sdo_request_copy_data(request, data + 10, data_size)) {
  1467         }
  1454             fsm->state = ec_fsm_coe_error;
  1468         request->data[complete_size] = 0x00; // just to be sure...
  1455             return;
  1469 
  1456         }
  1470         memcpy(request->data, data + 10, data_size);
  1457 
  1471         request->size = complete_size;
       
  1472         fsm->toggle = 0;
  1458         fsm->toggle = 0;
  1473 
  1459 
  1474         if (data_size < complete_size) {
  1460         if (data_size < complete_size) {
  1475             EC_WARN("Sdo data incomplete (%i / %i).\n",
  1461             EC_WARN("Sdo data incomplete (%i / %i).\n",
  1476                     data_size, complete_size);
  1462                     data_size, complete_size);
  1590 /*****************************************************************************/
  1576 /*****************************************************************************/
  1591 
  1577 
  1592 /**
  1578 /**
  1593    CoE state: UP RESPONSE.
  1579    CoE state: UP RESPONSE.
  1594    \todo Timeout behavior
  1580    \todo Timeout behavior
       
  1581    \todo Check for \a data_size exceeding \a complete_size.
  1595 */
  1582 */
  1596 
  1583 
  1597 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
  1584 void ec_fsm_coe_up_seg_response(ec_fsm_coe_t *fsm /**< finite state machine */)
  1598 {
  1585 {
  1599     ec_datagram_t *datagram = fsm->datagram;
  1586     ec_datagram_t *datagram = fsm->datagram;
  1675         EC_WARN("Sdo segment data invalid (%i / %i)"
  1662         EC_WARN("Sdo segment data invalid (%i / %i)"
  1676                 " - Fragmenting not implemented.\n",
  1663                 " - Fragmenting not implemented.\n",
  1677                 data_size, seg_size);
  1664                 data_size, seg_size);
  1678     }
  1665     }
  1679 
  1666 
  1680     memcpy(request->data + request->size, data + 10, data_size);
  1667     memcpy(request->data + request->data_size, data + 10, data_size);
  1681     request->size += data_size;
  1668     request->data_size += data_size;
  1682 
  1669 
  1683     if (!last_segment) {
  1670     if (!last_segment) {
  1684         fsm->toggle = !fsm->toggle;
  1671         fsm->toggle = !fsm->toggle;
  1685 
  1672 
  1686         if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {
  1673         if (!(data = ec_slave_mbox_prepare_send(slave, datagram, 0x03, 3))) {