Implemented CompleteAccess for SDO downloads.
This commit is contained in:
parent
454d502ada
commit
10c7501851
1
NEWS
1
NEWS
|
|
@ -61,6 +61,7 @@ Changes since 1.4.0:
|
|||
* Added 'ethercat eoe' command to display Ethernet over EtherCAT statistics.
|
||||
* Added 'ethercat cstruct' command to output PDO information in C language.
|
||||
* Significantly improved EoE bandwidth by running EoE processing in a kthread.
|
||||
* Implemented CompleteAccess for SDO downloads.
|
||||
|
||||
Changes in 1.4.0:
|
||||
|
||||
|
|
|
|||
3
TODO
3
TODO
|
|
@ -47,6 +47,9 @@ Version 1.5.0:
|
|||
* Document ec_fsm_foe members.
|
||||
* Test KBUILD_EXTRA_SYMBOLS.
|
||||
* Remove default buffer size in SDO upload.
|
||||
* Check for Enable SDO Complete Access flag.
|
||||
* Implement CompleteAccess for command-line tool.
|
||||
* Implement CompleteAccess for SDO uploads.
|
||||
|
||||
Future issues:
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@
|
|||
* - Added watchdog configuration (method ecrt_slave_config_watchdog(),
|
||||
* #ec_watchdog_mode_t, \a watchdog_mode parameter in ec_sync_info_t and
|
||||
* ecrt_slave_config_sync_manager()).
|
||||
* - Added ecrt_slave_config_complete_sdo() method to download an SDO during
|
||||
* configuration via CompleteAccess.
|
||||
* - Added ecrt_open_master() and ecrt_master_reserve() separation for
|
||||
* userspace.
|
||||
* - Added bus information interface (methods ecrt_master(),
|
||||
|
|
@ -1032,6 +1034,23 @@ int ecrt_slave_config_sdo32(
|
|||
uint32_t value /**< Value to set. */
|
||||
);
|
||||
|
||||
/** Add configuration data for a complete SDO.
|
||||
*
|
||||
* The SDO data are transferred via CompleteAccess. Data for the first
|
||||
* subindex (0) have to be included.
|
||||
*
|
||||
* \see ecrt_slave_config_sdo().
|
||||
*
|
||||
* \retval 0 Success.
|
||||
* \retval <0 Error code.
|
||||
*/
|
||||
int ecrt_slave_config_complete_sdo(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
uint16_t index, /**< Index of the SDO to configure. */
|
||||
const uint8_t *data, /**< Pointer to the data. */
|
||||
size_t size /**< Size of the \a data. */
|
||||
);
|
||||
|
||||
/** Create an SDO request to exchange SDOs during realtime operation.
|
||||
*
|
||||
* The created SDO request object is freed automatically when the master is
|
||||
|
|
|
|||
|
|
@ -294,6 +294,29 @@ int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index,
|
|||
data.subindex = subindex;
|
||||
data.data = sdo_data;
|
||||
data.size = size;
|
||||
data.complete_access = 0;
|
||||
|
||||
if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
|
||||
fprintf(stderr, "Failed to configure SDO.\n");
|
||||
return -1; // FIXME
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
|
||||
const uint8_t *sdo_data, size_t size)
|
||||
{
|
||||
ec_ioctl_sc_sdo_t data;
|
||||
|
||||
data.config_index = sc->index;
|
||||
data.index = index;
|
||||
data.subindex = 0;
|
||||
data.data = sdo_data;
|
||||
data.size = size;
|
||||
data.complete_access = 1;
|
||||
|
||||
if (ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data) == -1) {
|
||||
fprintf(stderr, "Failed to configure SDO.\n");
|
||||
|
|
|
|||
|
|
@ -1434,7 +1434,8 @@ int ec_cdev_ioctl_config_sdo(
|
|||
data.index = req->index;
|
||||
data.subindex = req->subindex;
|
||||
data.size = req->data_size;
|
||||
memcpy(&data.data, req->data, min((u32) data.size, (u32) 4));
|
||||
memcpy(&data.data, req->data,
|
||||
min((u32) data.size, (u32) EC_MAX_SDO_DATA_SIZE));
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
|
|
@ -2120,8 +2121,12 @@ int ec_cdev_ioctl_sc_sdo(
|
|||
|
||||
up(&master->master_sem); // FIXME
|
||||
|
||||
ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
|
||||
data.size);
|
||||
if (data.complete_access) {
|
||||
ret = ecrt_slave_config_complete_sdo(sc, data.index, sdo_data, data.size);
|
||||
} else {
|
||||
ret = ecrt_slave_config_sdo(sc, data.index, data.subindex, sdo_data,
|
||||
data.size);
|
||||
}
|
||||
kfree(sdo_data);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1074,8 +1074,14 @@ void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
uint8_t size;
|
||||
|
||||
if (fsm->slave->master->debug_level) {
|
||||
EC_DBG("Downloading SDO 0x%04X:%02X to slave %u.\n",
|
||||
request->index, request->subindex, slave->ring_position);
|
||||
char subidxstr[10];
|
||||
if (request->complete_access) {
|
||||
subidxstr[0] = 0x00;
|
||||
} else {
|
||||
sprintf(subidxstr, ":%02X", request->subindex);
|
||||
}
|
||||
EC_DBG("Downloading SDO 0x%04X%s to slave %u.\n",
|
||||
request->index, subidxstr, slave->ring_position);
|
||||
ec_print_data(request->data, request->data_size);
|
||||
}
|
||||
|
||||
|
|
@ -1097,9 +1103,11 @@ void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x3 // size specified, expedited
|
||||
| size << 2
|
||||
| ((request->complete_access ? 1 : 0) << 4)
|
||||
| 0x1 << 5)); // Download request
|
||||
EC_WRITE_U16(data + 3, request->index);
|
||||
EC_WRITE_U8 (data + 5, request->subindex);
|
||||
EC_WRITE_U8 (data + 5,
|
||||
request->complete_access ? 0x00 : request->subindex);
|
||||
memcpy(data + 6, request->data, request->data_size);
|
||||
memset(data + 6 + request->data_size, 0x00, 4 - request->data_size);
|
||||
|
||||
|
|
@ -1110,7 +1118,7 @@ void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
}
|
||||
else { // request->data_size > 4, use normal transfer type
|
||||
if (slave->configured_rx_mailbox_size < 6 + 10 + request->data_size) {
|
||||
EC_ERR("SDO fragmenting not supported yet!\n");
|
||||
EC_ERR("SDO fragmenting not supported yet!\n"); // FIXME
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
return;
|
||||
}
|
||||
|
|
@ -1124,9 +1132,11 @@ void ec_fsm_coe_down_start(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 // size indicator, normal
|
||||
| ((request->complete_access ? 1 : 0) << 4)
|
||||
| 0x1 << 5)); // Download request
|
||||
EC_WRITE_U16(data + 3, request->index);
|
||||
EC_WRITE_U8 (data + 5, request->subindex);
|
||||
EC_WRITE_U8 (data + 5,
|
||||
request->complete_access ? 0x00 : request->subindex);
|
||||
EC_WRITE_U32(data + 6, request->data_size);
|
||||
memcpy(data + 10, request->data, request->data_size);
|
||||
|
||||
|
|
@ -1311,12 +1321,18 @@ void ec_fsm_coe_down_response(ec_fsm_coe_t *fsm /**< finite state machine */)
|
|||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
|
||||
char subidxstr[10];
|
||||
fsm->state = ec_fsm_coe_error;
|
||||
EC_ERR("SDO download 0x%04X:%02X (%u bytes) aborted on slave %u.\n",
|
||||
request->index, request->subindex, request->data_size,
|
||||
slave->ring_position);
|
||||
if (request->complete_access) {
|
||||
subidxstr[0] = 0x00;
|
||||
} else {
|
||||
sprintf(subidxstr, ":%02X", request->subindex);
|
||||
}
|
||||
EC_ERR("SDO download 0x%04X%s (%u bytes) aborted on slave %u.\n",
|
||||
request->index, subidxstr, request->data_size,
|
||||
slave->ring_position);
|
||||
if (rec_size < 10) {
|
||||
EC_ERR("Incomplete Abort command:\n");
|
||||
EC_ERR("Incomplete abort command:\n");
|
||||
ec_print_data(data, rec_size);
|
||||
} else {
|
||||
fsm->request->abort_code = EC_READ_U32(data + 6);
|
||||
|
|
|
|||
|
|
@ -438,6 +438,11 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Maximum size for displayed SDO data.
|
||||
* \todo Make this dynamic.
|
||||
*/
|
||||
#define EC_MAX_SDO_DATA_SIZE 1024
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
|
|
@ -447,7 +452,7 @@ typedef struct {
|
|||
uint16_t index;
|
||||
uint8_t subindex;
|
||||
uint32_t size;
|
||||
uint8_t data[4];
|
||||
uint8_t data[EC_MAX_SDO_DATA_SIZE];
|
||||
} ec_ioctl_config_sdo_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -505,6 +510,7 @@ typedef struct {
|
|||
uint8_t subindex;
|
||||
const uint8_t *data;
|
||||
size_t size;
|
||||
uint8_t complete_access;
|
||||
} ec_ioctl_sc_sdo_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ void ec_sdo_request_init(
|
|||
ec_sdo_request_t *req /**< SDO request. */
|
||||
)
|
||||
{
|
||||
req->complete_access = 0;
|
||||
req->data = NULL;
|
||||
req->mem_size = 0;
|
||||
req->data_size = 0;
|
||||
|
|
@ -88,6 +89,7 @@ int ec_sdo_request_copy(
|
|||
const ec_sdo_request_t *other /**< Other SDO request to copy from. */
|
||||
)
|
||||
{
|
||||
req->complete_access = other->complete_access;
|
||||
req->index = other->index;
|
||||
req->subindex = other->subindex;
|
||||
return ec_sdo_request_copy_data(req, other->data, other->data_size);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ struct ec_sdo_request {
|
|||
uint8_t *data; /**< Pointer to SDO data. */
|
||||
size_t mem_size; /**< Size of SDO data memory. */
|
||||
size_t data_size; /**< Size of SDO data. */
|
||||
uint8_t complete_access; /**< SDO shall be transferred completely. */
|
||||
uint32_t issue_timeout; /**< Maximum time in ms, the processing of the
|
||||
request may take. */
|
||||
uint32_t response_timeout; /**< Maximum time in ms, the transfer is
|
||||
|
|
|
|||
|
|
@ -794,6 +794,48 @@ int ecrt_slave_config_sdo32(ec_slave_config_t *sc, uint16_t index,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index,
|
||||
const uint8_t *data, size_t size)
|
||||
{
|
||||
ec_slave_t *slave = sc->slave;
|
||||
ec_sdo_request_t *req;
|
||||
int ret;
|
||||
|
||||
if (sc->master->debug_level)
|
||||
EC_DBG("ecrt_slave_config_complete_sdo(sc = 0x%x, index = 0x%04X, "
|
||||
"data = 0x%x, size = %u)\n", (u32) sc,
|
||||
index, (u32) data, size);
|
||||
|
||||
if (slave && !(slave->sii.mailbox_protocols & EC_MBOX_COE)) {
|
||||
EC_ERR("Slave %u does not support CoE!\n", slave->ring_position);
|
||||
return -EPROTONOSUPPORT; // protocol not supported
|
||||
}
|
||||
|
||||
if (!(req = (ec_sdo_request_t *)
|
||||
kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate memory for SDO configuration!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ec_sdo_request_init(req);
|
||||
ec_sdo_request_address(req, index, 0);
|
||||
req->complete_access = 1;
|
||||
|
||||
ret = ec_sdo_request_copy_data(req, data, size);
|
||||
if (ret < 0) {
|
||||
ec_sdo_request_clear(req);
|
||||
kfree(req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
list_add_tail(&req->list, &sc->sdo_configs);
|
||||
up(&sc->master->master_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Same as ecrt_slave_config_create_sdo_request(), but with ERR_PTR() return
|
||||
* value.
|
||||
*/
|
||||
|
|
@ -923,6 +965,7 @@ EXPORT_SYMBOL(ecrt_slave_config_sdo);
|
|||
EXPORT_SYMBOL(ecrt_slave_config_sdo8);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sdo16);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sdo32);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_complete_sdo);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler);
|
||||
EXPORT_SYMBOL(ecrt_slave_config_state);
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ void CommandConfig::showDetailedConfigs(
|
|||
)
|
||||
{
|
||||
ConfigList::const_iterator configIter;
|
||||
unsigned int j, k, l;
|
||||
unsigned int i, j, k, l;
|
||||
ec_ioctl_slave_t slave;
|
||||
ec_ioctl_config_pdo_t pdo;
|
||||
ec_ioctl_config_pdo_entry_t entry;
|
||||
|
|
@ -217,26 +217,23 @@ void CommandConfig::showDetailedConfigs(
|
|||
<< hex << setfill('0')
|
||||
<< setw(4) << sdo.index << ":"
|
||||
<< setw(2) << (unsigned int) sdo.subindex
|
||||
<< ", " << dec << sdo.size << " byte: " << hex;
|
||||
<< ", " << dec << sdo.size << " byte" << endl;
|
||||
|
||||
switch (sdo.size) {
|
||||
case 1:
|
||||
cout << "0x" << setw(2)
|
||||
<< (unsigned int) *(uint8_t *) &sdo.data;
|
||||
break;
|
||||
case 2:
|
||||
cout << "0x" << setw(4)
|
||||
<< le16_to_cpup(&sdo.data);
|
||||
break;
|
||||
case 4:
|
||||
cout << "0x" << setw(8)
|
||||
<< le32_to_cpup(&sdo.data);
|
||||
break;
|
||||
default:
|
||||
cout << "???";
|
||||
cout << " " << hex;
|
||||
for (i = 0; i < min((uint32_t) sdo.size,
|
||||
(uint32_t) EC_MAX_SDO_DATA_SIZE); i++) {
|
||||
cout << setw(2) << (unsigned int) sdo.data[i];
|
||||
if ((i + 1) % 16 == 0 && i < sdo.size - 1) {
|
||||
cout << endl << " ";
|
||||
} else {
|
||||
cout << " ";
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
if (sdo.size > EC_MAX_SDO_DATA_SIZE) {
|
||||
cout << " ..." << endl;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cout << " None." << endl;
|
||||
|
|
|
|||
Loading…
Reference in New Issue