Dynamischer Kommandospeicher, Domain-Kommandos als Liste.
This commit is contained in:
parent
3db637131e
commit
8306f3e3c1
|
|
@ -61,6 +61,8 @@ void ecrt_master_async_send(ec_master_t *master);
|
|||
void ecrt_master_async_receive(ec_master_t *master);
|
||||
void ecrt_master_prepare_async_io(ec_master_t *master);
|
||||
|
||||
void ecrt_master_run(ec_master_t *master);
|
||||
|
||||
void ecrt_master_debug(ec_master_t *master, int level);
|
||||
void ecrt_master_print(const ec_master_t *master, unsigned int verbosity);
|
||||
|
||||
|
|
|
|||
|
|
@ -48,19 +48,21 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
uint8_t *target /**< Speicher für 4 Bytes */
|
||||
)
|
||||
{
|
||||
uint8_t data[0x20];
|
||||
size_t rec_size;
|
||||
uint8_t *data;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1;
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer
|
||||
| 0x2 << 5)); // initiate upload request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
|
||||
|
||||
rec_size = 0x20;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -97,7 +99,7 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
size_t size
|
||||
)
|
||||
{
|
||||
uint8_t data[0x0A];
|
||||
uint8_t *data;
|
||||
size_t rec_size;
|
||||
|
||||
if (size == 0 || size > 4) {
|
||||
|
|
@ -105,6 +107,7 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 0x0A))) return -1;
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 // size specified
|
||||
| 0x1 << 1 // expedited transfer
|
||||
|
|
@ -112,15 +115,14 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
| 0x1 << 5)); // initiate download request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
|
||||
memcpy(data + 6, sdo_data, size);
|
||||
if (size < 4) memset(data + 6 + size, 0x00, 4 - size);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Mailox senden und empfangen
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 0x0A)) return -1;
|
||||
|
||||
rec_size = 0x0A;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -158,19 +160,21 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
size_t *size /**< Größe des Speichers */
|
||||
)
|
||||
{
|
||||
uint8_t data[0x20];
|
||||
uint8_t *data;
|
||||
size_t rec_size, data_size;
|
||||
uint32_t complete_size;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 6))) return -1;
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, 0x2 << 5); // initiate upload request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 6)) return -1;
|
||||
|
||||
rec_size = 0x20;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
|
|
@ -222,23 +226,26 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
{
|
||||
uint8_t data[0xF0];
|
||||
uint8_t *data;
|
||||
size_t rec_size;
|
||||
unsigned int i, sdo_count;
|
||||
ec_sdo_t *sdo;
|
||||
uint16_t sdo_index;
|
||||
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 8))) return -1;
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x01); // Get OD List Request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, 0x0001); // Deliver all SDOs!
|
||||
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
rec_size = 0xF0;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size)) return -1;
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // Error response
|
||||
|
|
@ -290,21 +297,24 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
{
|
||||
uint8_t data[0xF0];
|
||||
uint8_t *data;
|
||||
size_t rec_size, name_size;
|
||||
ec_sdo_t *sdo;
|
||||
|
||||
list_for_each_entry(sdo, &slave->sdo_dictionary, list) {
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 8))) return -1;
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x03); // Get object description request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
EC_WRITE_U16(data + 4, 0x0000);
|
||||
EC_WRITE_U16(data + 6, sdo->index); // SDO index
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 8)) return -1;
|
||||
|
||||
rec_size = 0xF0;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size))
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
|
|
@ -370,12 +380,14 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
uint8_t subindices /**< Anzahl Subindizes */
|
||||
)
|
||||
{
|
||||
uint8_t data[0xF0];
|
||||
uint8_t *data;
|
||||
size_t rec_size, data_size;
|
||||
uint8_t i;
|
||||
ec_sdo_entry_t *entry;
|
||||
|
||||
for (i = 1; i <= subindices; i++) {
|
||||
if (!(data = ec_slave_prepare_mailbox_send(slave, 0x03, 10)))
|
||||
return -1;
|
||||
EC_WRITE_U16(data, 0x8 << 12); // SDO information
|
||||
EC_WRITE_U8 (data + 2, 0x05); // Get entry description request
|
||||
EC_WRITE_U8 (data + 3, 0x00);
|
||||
|
|
@ -383,11 +395,13 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
EC_WRITE_U16(data + 6, sdo->index); // SDO index
|
||||
EC_WRITE_U8 (data + 8, i); // SDO subindex
|
||||
EC_WRITE_U8 (data + 9, 0x00); // value info (no values)
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ec_slave_mailbox_send(slave, 0x03, data, 10)) return -1;
|
||||
|
||||
rec_size = 0xF0;
|
||||
if (ec_slave_mailbox_receive(slave, 0x03, data, &rec_size))
|
||||
if (!(data = ec_slave_mailbox_receive(slave, 0x03, &rec_size)))
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
|
|
|
|||
213
master/command.c
213
master/command.c
|
|
@ -17,17 +17,70 @@
|
|||
/*****************************************************************************/
|
||||
|
||||
#define EC_FUNC_HEADER \
|
||||
if (unlikely(ec_command_prealloc(command, data_size))) \
|
||||
return -1; \
|
||||
command->index = 0; \
|
||||
command->working_counter = 0; \
|
||||
command->state = EC_CMD_INIT;
|
||||
|
||||
#define EC_FUNC_WRITE_FOOTER \
|
||||
#define EC_FUNC_FOOTER \
|
||||
command->data_size = data_size; \
|
||||
memcpy(command->data, data, data_size);
|
||||
memset(command->data, 0x00, data_size); \
|
||||
return 0;
|
||||
|
||||
#define EC_FUNC_READ_FOOTER \
|
||||
command->data_size = data_size; \
|
||||
memset(command->data, 0x00, data_size);
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Konstruktor.
|
||||
*/
|
||||
|
||||
void ec_command_init(ec_command_t *command)
|
||||
{
|
||||
command->type = EC_CMD_NONE;
|
||||
command->address.logical = 0x00000000;
|
||||
command->data = NULL;
|
||||
command->mem_size = 0;
|
||||
command->data_size = 0;
|
||||
command->index = 0x00;
|
||||
command->working_counter = 0x00;
|
||||
command->state = EC_CMD_INIT;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Destruktor.
|
||||
*/
|
||||
|
||||
void ec_command_clear(ec_command_t *command)
|
||||
{
|
||||
if (command->data) kfree(command->data);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Alloziert Speicher.
|
||||
*/
|
||||
|
||||
int ec_command_prealloc(ec_command_t *command, size_t size)
|
||||
{
|
||||
if (size <= command->mem_size) return 0;
|
||||
|
||||
if (command->data) {
|
||||
kfree(command->data);
|
||||
command->data = NULL;
|
||||
command->mem_size = 0;
|
||||
}
|
||||
|
||||
if (!(command->data = kmalloc(size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %i bytes of command memory!\n", size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
command->mem_size = size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -37,26 +90,24 @@
|
|||
Node-adressed physical read.
|
||||
*/
|
||||
|
||||
void ec_command_init_nprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
int ec_command_nprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_NPRD;
|
||||
command->address.physical.slave = node_address;
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_READ_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -67,28 +118,24 @@ void ec_command_init_nprd(ec_command_t *command,
|
|||
Node-adressed physical write.
|
||||
*/
|
||||
|
||||
void ec_command_init_npwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size,
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
const uint8_t *data
|
||||
/**< Zeiger auf Speicher mit zu schreibenden Daten */
|
||||
)
|
||||
int ec_command_npwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
EC_WARN("Using node address 0x0000!\n");
|
||||
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_NPWR;
|
||||
command->address.physical.slave = node_address;
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_WRITE_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -99,23 +146,21 @@ void ec_command_init_npwr(ec_command_t *command,
|
|||
Autoincrement physical read.
|
||||
*/
|
||||
|
||||
void ec_command_init_aprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
int ec_command_aprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_APRD;
|
||||
command->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_READ_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -126,25 +171,21 @@ void ec_command_init_aprd(ec_command_t *command,
|
|||
Autoincrement physical write.
|
||||
*/
|
||||
|
||||
void ec_command_init_apwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size,
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
const uint8_t *data
|
||||
/**< Zeiger auf Speicher mit zu schreibenden Daten */
|
||||
)
|
||||
int ec_command_apwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_APWR;
|
||||
command->address.physical.slave = (int16_t) ring_position * (-1);
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_WRITE_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -155,21 +196,19 @@ void ec_command_init_apwr(ec_command_t *command,
|
|||
Broadcast read.
|
||||
*/
|
||||
|
||||
void ec_command_init_brd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
int ec_command_brd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_BRD;
|
||||
command->address.physical.slave = 0x0000;
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_READ_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -180,23 +219,19 @@ void ec_command_init_brd(ec_command_t *command,
|
|||
Broadcast write.
|
||||
*/
|
||||
|
||||
void ec_command_init_bwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size,
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
const uint8_t *data
|
||||
/**< Zeiger auf Speicher mit zu schreibenden Daten */
|
||||
)
|
||||
int ec_command_bwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_BWR;
|
||||
command->address.physical.slave = 0x0000;
|
||||
command->address.physical.mem = offset;
|
||||
|
||||
EC_FUNC_WRITE_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -207,22 +242,18 @@ void ec_command_init_bwr(ec_command_t *command,
|
|||
Logical read write.
|
||||
*/
|
||||
|
||||
void ec_command_init_lrw(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint32_t offset,
|
||||
/**< Logische Startadresse */
|
||||
size_t data_size,
|
||||
/**< Länge der zu lesenden/schreibenden Daten */
|
||||
uint8_t *data
|
||||
/**< Zeiger auf die Daten */
|
||||
)
|
||||
int ec_command_lrw(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
uint32_t offset,
|
||||
/**< Logische Startadresse */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden/schreibenden Daten */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
|
||||
command->type = EC_CMD_LRW;
|
||||
command->address.logical = offset;
|
||||
|
||||
EC_FUNC_WRITE_FOOTER;
|
||||
EC_FUNC_FOOTER;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ ec_address_t;
|
|||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list; /**< Nötig für Liste */
|
||||
struct list_head list; /**< Kommando-Listeneintrag */
|
||||
struct list_head queue; /**< Master-Kommando-Queue */
|
||||
ec_command_type_t type; /**< Typ des Kommandos (APRD, NPWR, etc) */
|
||||
ec_address_t address; /**< Adresse des/der Empfänger */
|
||||
uint8_t data[EC_MAX_DATA_SIZE]; /**< Kommandodaten */
|
||||
uint8_t *data; /**< Kommandodaten */
|
||||
size_t mem_size; /**< Größe des Speichers */
|
||||
size_t data_size; /**< Länge der zu sendenden und/oder empfangenen Daten */
|
||||
uint8_t index; /**< Kommando-Index, wird vom Master beim Senden gesetzt. */
|
||||
uint16_t working_counter; /**< Working-Counter */
|
||||
|
|
@ -97,15 +99,16 @@ ec_command_t;
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ec_command_init_nprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
void ec_command_init_npwr(ec_command_t *, uint16_t, uint16_t, size_t,
|
||||
const uint8_t *);
|
||||
void ec_command_init_aprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
void ec_command_init_apwr(ec_command_t *, uint16_t, uint16_t, size_t,
|
||||
const uint8_t *);
|
||||
void ec_command_init_brd(ec_command_t *, uint16_t, size_t);
|
||||
void ec_command_init_bwr(ec_command_t *, uint16_t, size_t, const uint8_t *);
|
||||
void ec_command_init_lrw(ec_command_t *, uint32_t, size_t, uint8_t *);
|
||||
void ec_command_init(ec_command_t *);
|
||||
void ec_command_clear(ec_command_t *);
|
||||
|
||||
int ec_command_nprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_npwr(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_aprd(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_apwr(ec_command_t *, uint16_t, uint16_t, size_t);
|
||||
int ec_command_brd(ec_command_t *, uint16_t, size_t);
|
||||
int ec_command_bwr(ec_command_t *, uint16_t, size_t);
|
||||
int ec_command_lrw(ec_command_t *, uint32_t, size_t);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
|
|||
152
master/domain.c
152
master/domain.c
|
|
@ -25,14 +25,12 @@ void ec_domain_init(ec_domain_t *domain, /**< Dom
|
|||
)
|
||||
{
|
||||
domain->master = master;
|
||||
domain->data = NULL;
|
||||
domain->data_size = 0;
|
||||
domain->commands = NULL;
|
||||
domain->command_count = 0;
|
||||
domain->base_address = 0;
|
||||
domain->response_count = 0xFFFFFFFF;
|
||||
|
||||
INIT_LIST_HEAD(&domain->field_regs);
|
||||
INIT_LIST_HEAD(&domain->commands);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -43,8 +41,12 @@ void ec_domain_init(ec_domain_t *domain, /**< Dom
|
|||
|
||||
void ec_domain_clear(ec_domain_t *domain /**< Domäne */)
|
||||
{
|
||||
if (domain->data) kfree(domain->data);
|
||||
if (domain->commands) kfree(domain->commands);
|
||||
ec_command_t *command, *next;
|
||||
|
||||
list_for_each_entry_safe(command, next, &domain->commands, list) {
|
||||
ec_command_clear(command);
|
||||
kfree(command);
|
||||
}
|
||||
|
||||
ec_domain_clear_field_regs(domain);
|
||||
}
|
||||
|
|
@ -66,8 +68,8 @@ int ec_domain_reg_field(ec_domain_t *domain, /**< Dom
|
|||
{
|
||||
ec_field_reg_t *field_reg;
|
||||
|
||||
if (!(field_reg = (ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t),
|
||||
GFP_KERNEL))) {
|
||||
if (!(field_reg =
|
||||
(ec_field_reg_t *) kmalloc(sizeof(ec_field_reg_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate field registration.\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -106,6 +108,35 @@ void ec_domain_clear_field_regs(ec_domain_t *domain)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Alloziert ein Prozessdatenkommando und fügt es in die Liste ein.
|
||||
*/
|
||||
|
||||
int ec_domain_add_command(ec_domain_t *domain, /**< Domäne */
|
||||
uint32_t offset, /**< Logisches Offset */
|
||||
size_t data_size /**< Größe der Kommando-Daten */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
|
||||
if (!(command = kmalloc(sizeof(ec_command_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate domain command!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ec_command_init(command);
|
||||
|
||||
if (ec_command_lrw(command, offset, data_size)) {
|
||||
kfree(command);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add_tail(&command->list, &domain->commands);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Erzeugt eine Domäne.
|
||||
|
||||
|
|
@ -122,19 +153,19 @@ int ec_domain_alloc(ec_domain_t *domain, /**< Dom
|
|||
ec_field_reg_t *field_reg;
|
||||
ec_slave_t *slave;
|
||||
ec_fmmu_t *fmmu;
|
||||
unsigned int i, j;
|
||||
uint32_t data_offset;
|
||||
|
||||
if (domain->data) {
|
||||
EC_ERR("Domain already allocated!\n");
|
||||
return -1;
|
||||
}
|
||||
unsigned int i, j, cmd_count;
|
||||
uint32_t field_off, field_off_cmd;
|
||||
uint32_t cmd_offset;
|
||||
size_t cmd_data_size;
|
||||
ec_command_t *command;
|
||||
|
||||
domain->base_address = base_address;
|
||||
|
||||
// Größe der Prozessdaten berechnen
|
||||
// und logische Adressen der FMMUs setzen
|
||||
// Größe der Prozessdaten berechnen und Kommandos allozieren
|
||||
domain->data_size = 0;
|
||||
cmd_offset = base_address;
|
||||
cmd_data_size = 0;
|
||||
cmd_count = 0;
|
||||
for (i = 0; i < domain->master->slave_count; i++) {
|
||||
slave = &domain->master->slaves[i];
|
||||
for (j = 0; j < slave->fmmu_count; j++) {
|
||||
|
|
@ -142,49 +173,57 @@ int ec_domain_alloc(ec_domain_t *domain, /**< Dom
|
|||
if (fmmu->domain == domain) {
|
||||
fmmu->logical_start_address = base_address + domain->data_size;
|
||||
domain->data_size += fmmu->sync->size;
|
||||
if (cmd_data_size + fmmu->sync->size > EC_MAX_DATA_SIZE) {
|
||||
if (ec_domain_add_command(domain, cmd_offset,
|
||||
cmd_data_size)) return -1;
|
||||
cmd_offset += cmd_data_size;
|
||||
cmd_data_size = 0;
|
||||
cmd_count++;
|
||||
}
|
||||
cmd_data_size += fmmu->sync->size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!domain->data_size) {
|
||||
// Letztes Kommando allozieren
|
||||
if (cmd_data_size) {
|
||||
if (ec_domain_add_command(domain, cmd_offset, cmd_data_size))
|
||||
return -1;
|
||||
cmd_count++;
|
||||
}
|
||||
|
||||
if (!cmd_count) {
|
||||
EC_WARN("Domain 0x%08X contains no data!\n", (u32) domain);
|
||||
ec_domain_clear_field_regs(domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Prozessdaten allozieren
|
||||
if (!(domain->data = kmalloc(domain->data_size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate domain data!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Prozessdaten mit Nullen vorbelegen
|
||||
memset(domain->data, 0x00, domain->data_size);
|
||||
|
||||
// Alle Prozessdatenzeiger setzen
|
||||
list_for_each_entry(field_reg, &domain->field_regs, list) {
|
||||
for (i = 0; i < field_reg->slave->fmmu_count; i++) {
|
||||
fmmu = &field_reg->slave->fmmus[i];
|
||||
if (fmmu->domain == domain && fmmu->sync == field_reg->sync) {
|
||||
data_offset = fmmu->logical_start_address - base_address
|
||||
+ field_reg->field_offset;
|
||||
*field_reg->data_ptr = domain->data + data_offset;
|
||||
field_off = fmmu->logical_start_address +
|
||||
field_reg->field_offset;
|
||||
// Kommando suchen
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
field_off_cmd = field_off - command->address.logical;
|
||||
if (field_off >= command->address.logical &&
|
||||
field_off_cmd < command->mem_size) {
|
||||
*field_reg->data_ptr = command->data + field_off_cmd;
|
||||
}
|
||||
}
|
||||
if (!field_reg->data_ptr) {
|
||||
EC_ERR("Failed to assign data pointer!\n");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Kommando-Array erzeugen
|
||||
domain->command_count = domain->data_size / EC_MAX_DATA_SIZE + 1;
|
||||
if (!(domain->commands = (ec_command_t *) kmalloc(sizeof(ec_command_t)
|
||||
* domain->command_count,
|
||||
GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate domain command array!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
EC_INFO("Domain %X - Allocated %i bytes in %i command(s)\n",
|
||||
(u32) domain, domain->data_size, domain->command_count);
|
||||
(u32) domain, domain->data_size, cmd_count);
|
||||
|
||||
ec_domain_clear_field_regs(domain);
|
||||
|
||||
|
|
@ -346,19 +385,10 @@ int ecrt_domain_register_field_list(ec_domain_t *domain,
|
|||
|
||||
void ecrt_domain_queue(ec_domain_t *domain /**< Domäne */)
|
||||
{
|
||||
unsigned int i;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
ec_command_t *command;
|
||||
|
||||
offset = 0;
|
||||
for (i = 0; i < domain->command_count; i++) {
|
||||
size = domain->data_size - offset;
|
||||
if (size > EC_MAX_DATA_SIZE) size = EC_MAX_DATA_SIZE;
|
||||
ec_command_init_lrw(domain->commands + i,
|
||||
domain->base_address + offset, size,
|
||||
domain->data + offset);
|
||||
ec_master_queue_command(domain->master, domain->commands + i);
|
||||
offset += size;
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
ec_master_queue_command(domain->master, command);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -370,27 +400,15 @@ void ecrt_domain_queue(ec_domain_t *domain /**< Dom
|
|||
|
||||
void ecrt_domain_process(ec_domain_t *domain /**< Domäne */)
|
||||
{
|
||||
unsigned int working_counter_sum, i;
|
||||
unsigned int working_counter_sum;
|
||||
ec_command_t *command;
|
||||
size_t size;
|
||||
off_t offset;
|
||||
|
||||
working_counter_sum = 0;
|
||||
|
||||
offset = 0;
|
||||
for (i = 0; i < domain->command_count; i++) {
|
||||
command = domain->commands + i;
|
||||
size = domain->data_size - offset;
|
||||
if (size > EC_MAX_DATA_SIZE) size = EC_MAX_DATA_SIZE;
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
if (command->state == EC_CMD_RECEIVED) {
|
||||
// Daten vom Kommando- in den Prozessdatenspeicher kopieren
|
||||
memcpy(domain->data + offset, command->data, size);
|
||||
working_counter_sum += command->working_counter;
|
||||
}
|
||||
else if (unlikely(domain->master->debug_level)) {
|
||||
EC_DBG("process data command not received!\n");
|
||||
}
|
||||
offset += size;
|
||||
}
|
||||
|
||||
ec_domain_response_count(domain, working_counter_sum);
|
||||
|
|
@ -406,11 +424,9 @@ void ecrt_domain_process(ec_domain_t *domain /**< Dom
|
|||
|
||||
int ecrt_domain_state(ec_domain_t *domain /**< Domäne */)
|
||||
{
|
||||
unsigned int i;
|
||||
ec_command_t *command;
|
||||
|
||||
for (i = 0; i < domain->command_count; i++) {
|
||||
command = domain->commands + i;
|
||||
list_for_each_entry(command, &domain->commands, list) {
|
||||
if (command->state != EC_CMD_RECEIVED) return -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,10 +46,8 @@ struct ec_domain
|
|||
{
|
||||
struct list_head list; /**< Listenkopf */
|
||||
ec_master_t *master; /**< EtherCAT-Master, zu der die Domäne gehört. */
|
||||
uint8_t *data; /**< Prozessdaten */
|
||||
size_t data_size; /**< Größe der Prozessdaten */
|
||||
ec_command_t *commands; /**< EtherCAT-Kommandos für die Prozessdaten */
|
||||
unsigned int command_count; /**< Anzahl allozierter Kommandos */
|
||||
struct list_head commands; /**< EtherCAT-Kommandos für die Prozessdaten */
|
||||
uint32_t base_address; /**< Logische Basisaddresse der Domain */
|
||||
unsigned int response_count; /**< Anzahl antwortender Slaves */
|
||||
struct list_head field_regs; /**< Liste der Datenfeldregistrierungen */
|
||||
|
|
|
|||
194
master/master.c
194
master/master.c
|
|
@ -33,9 +33,12 @@ void ec_master_init(ec_master_t *master /**< EtherCAT-Master */)
|
|||
master->slaves = NULL;
|
||||
master->device = NULL;
|
||||
|
||||
INIT_LIST_HEAD(&master->commands);
|
||||
INIT_LIST_HEAD(&master->command_queue);
|
||||
INIT_LIST_HEAD(&master->domains);
|
||||
|
||||
ec_command_init(&master->simple_command);
|
||||
ec_command_init(&master->watch_command);
|
||||
|
||||
ec_master_reset(master);
|
||||
}
|
||||
|
||||
|
|
@ -56,6 +59,9 @@ void ec_master_clear(ec_master_t *master /**< EtherCAT-Master */)
|
|||
ec_device_clear(master->device);
|
||||
kfree(master->device);
|
||||
}
|
||||
|
||||
ec_command_clear(&master->simple_command);
|
||||
ec_command_clear(&master->watch_command);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -72,8 +78,8 @@ void ec_master_reset(ec_master_t *master
|
|||
)
|
||||
{
|
||||
unsigned int i;
|
||||
ec_command_t *command, *next_command;
|
||||
ec_domain_t *domain, *next_domain;
|
||||
ec_command_t *command, *next_c;
|
||||
ec_domain_t *domain, *next_d;
|
||||
|
||||
// Alle Slaves entfernen
|
||||
if (master->slaves) {
|
||||
|
|
@ -86,13 +92,13 @@ void ec_master_reset(ec_master_t *master
|
|||
master->slave_count = 0;
|
||||
|
||||
// Kommando-Warteschlange leeren
|
||||
list_for_each_entry_safe(command, next_command, &master->commands, list) {
|
||||
list_for_each_entry_safe(command, next_c, &master->command_queue, queue) {
|
||||
command->state = EC_CMD_ERROR;
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
}
|
||||
|
||||
// Domain-Liste leeren
|
||||
list_for_each_entry_safe(domain, next_domain, &master->domains, list) {
|
||||
list_for_each_entry_safe(domain, next_d, &master->domains, list) {
|
||||
list_del(&domain->list);
|
||||
ec_domain_clear(domain);
|
||||
kfree(domain);
|
||||
|
|
@ -166,7 +172,7 @@ void ec_master_queue_command(ec_master_t *master, /**< EtherCAT-Master */
|
|||
ec_command_t *queued_command;
|
||||
|
||||
// Ist das Kommando schon in der Warteschlange?
|
||||
list_for_each_entry(queued_command, &master->commands, list) {
|
||||
list_for_each_entry(queued_command, &master->command_queue, queue) {
|
||||
if (queued_command == command) {
|
||||
command->state = EC_CMD_QUEUED;
|
||||
if (unlikely(master->debug_level))
|
||||
|
|
@ -175,7 +181,7 @@ void ec_master_queue_command(ec_master_t *master, /**< EtherCAT-Master */
|
|||
}
|
||||
}
|
||||
|
||||
list_add_tail(&command->list, &master->commands);
|
||||
list_add_tail(&command->queue, &master->command_queue);
|
||||
command->state = EC_CMD_QUEUED;
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +212,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
|
|||
follows_word = NULL;
|
||||
|
||||
// Aktuellen Frame mit Kommandos füllen
|
||||
list_for_each_entry(command, &master->commands, list) {
|
||||
list_for_each_entry(command, &master->command_queue, queue) {
|
||||
if (command->state != EC_CMD_QUEUED) continue;
|
||||
|
||||
// Passt das aktuelle Kommando noch in den aktuellen Rahmen?
|
||||
|
|
@ -238,7 +244,7 @@ void ec_master_send_commands(ec_master_t *master /**< EtherCAT-Master */)
|
|||
cur_data += command->data_size;
|
||||
|
||||
// EtherCAT command footer
|
||||
EC_WRITE_U16(cur_data, command->working_counter);
|
||||
EC_WRITE_U16(cur_data, 0x0000); // Working counter
|
||||
cur_data += EC_COMMAND_FOOTER_SIZE;
|
||||
}
|
||||
|
||||
|
|
@ -323,7 +329,7 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
|
|||
|
||||
// Suche passendes Kommando in der Liste
|
||||
matched = 0;
|
||||
list_for_each_entry(command, &master->commands, list) {
|
||||
list_for_each_entry(command, &master->command_queue, queue) {
|
||||
if (command->state == EC_CMD_SENT
|
||||
&& command->type == command_type
|
||||
&& command->index == command_index
|
||||
|
|
@ -349,9 +355,9 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
|
|||
command->working_counter = EC_READ_U16(cur_data);
|
||||
cur_data += EC_COMMAND_FOOTER_SIZE;
|
||||
|
||||
// Kommando aus der Liste entfernen
|
||||
// Kommando aus der Warteschlange entfernen
|
||||
command->state = EC_CMD_RECEIVED;
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -366,13 +372,13 @@ void ec_master_receive(ec_master_t *master, /**< EtherCAT-Master */
|
|||
\return 0 bei Erfolg, sonst < 0
|
||||
*/
|
||||
|
||||
int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
|
||||
ec_command_t *command /**< Kommando */
|
||||
)
|
||||
int ec_master_simple_io(ec_master_t *master /**< EtherCAT-Master */)
|
||||
{
|
||||
unsigned int response_tries_left;
|
||||
ec_command_t *command;
|
||||
|
||||
response_tries_left = 10;
|
||||
command = &master->simple_command;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
|
@ -415,21 +421,22 @@ int ec_master_simple_io(ec_master_t *master, /**< EtherCAT-Master */
|
|||
|
||||
int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
||||
{
|
||||
ec_command_t command;
|
||||
ec_slave_t *slave;
|
||||
ec_slave_ident_t *ident;
|
||||
unsigned int i;
|
||||
uint8_t data[2];
|
||||
ec_command_t *command;
|
||||
|
||||
if (master->slaves || master->slave_count) {
|
||||
EC_ERR("Slave scan already done!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
command = &master->simple_command;
|
||||
|
||||
// Determine number of slaves on bus
|
||||
ec_command_init_brd(&command, 0x0000, 4);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) return -1;
|
||||
master->slave_count = command.working_counter;
|
||||
if (ec_command_brd(command, 0x0000, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(master))) return -1;
|
||||
master->slave_count = command->working_counter;
|
||||
EC_INFO("Found %i slaves on bus.\n", master->slave_count);
|
||||
|
||||
if (!master->slave_count) return 0;
|
||||
|
|
@ -455,10 +462,10 @@ int ec_master_bus_scan(ec_master_t *master /**< EtherCAT-Master */)
|
|||
slave = master->slaves + i;
|
||||
|
||||
// Write station address
|
||||
EC_WRITE_U16(data, slave->station_address);
|
||||
ec_command_init_apwr(&command, slave->ring_position,
|
||||
0x0010, sizeof(uint16_t), data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_apwr(command, slave->ring_position,
|
||||
0x0010, sizeof(uint16_t))) return -1;
|
||||
EC_WRITE_U16(command->data, slave->station_address);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Writing station address failed on slave %i!\n", i);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -713,6 +720,8 @@ void ec_master_process_watch_command(ec_master_t *master
|
|||
{
|
||||
unsigned int first;
|
||||
|
||||
if (unlikely(master->watch_command.state == EC_CMD_INIT)) return;
|
||||
|
||||
first = 1;
|
||||
|
||||
if (master->watch_command.working_counter != master->slaves_responding ||
|
||||
|
|
@ -789,15 +798,21 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
{
|
||||
unsigned int i, j;
|
||||
ec_slave_t *slave;
|
||||
ec_command_t command;
|
||||
ec_command_t *command;
|
||||
const ec_sync_t *sync;
|
||||
const ec_slave_type_t *type;
|
||||
const ec_fmmu_t *fmmu;
|
||||
uint8_t data[256];
|
||||
uint32_t domain_offset;
|
||||
ec_domain_t *domain;
|
||||
ec_eeprom_sync_t *eeprom_sync;
|
||||
|
||||
command = &master->simple_command;
|
||||
|
||||
if (ec_command_brd(&master->watch_command, 0x130, 2)) {
|
||||
EC_ERR("Failed to allocate watchdog command!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Domains erstellen
|
||||
domain_offset = 0;
|
||||
list_for_each_entry(domain, &master->domains, list) {
|
||||
|
|
@ -826,10 +841,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
|
||||
// Resetting FMMUs
|
||||
if (slave->base_fmmu_count) {
|
||||
memset(data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count, data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0600,
|
||||
EC_FMMU_SIZE * slave->base_fmmu_count))
|
||||
return -1;
|
||||
memset(command->data, 0x00, EC_FMMU_SIZE * slave->base_fmmu_count);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Resetting FMMUs failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -838,10 +854,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
|
||||
// Resetting Sync Manager channels
|
||||
if (slave->base_sync_count) {
|
||||
memset(data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x0800,
|
||||
EC_SYNC_SIZE * slave->base_sync_count, data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0800,
|
||||
EC_SYNC_SIZE * slave->base_sync_count))
|
||||
return -1;
|
||||
memset(command->data, 0x00, EC_SYNC_SIZE * slave->base_sync_count);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Resetting sync managers failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -853,11 +870,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
for (j = 0; type->sync_managers[j] && j < EC_MAX_SYNC; j++)
|
||||
{
|
||||
sync = type->sync_managers[j];
|
||||
ec_sync_config(sync, data);
|
||||
ec_command_init_npwr(&command, slave->station_address,
|
||||
0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE,
|
||||
data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x0800 + j * EC_SYNC_SIZE, EC_SYNC_SIZE))
|
||||
return -1;
|
||||
ec_sync_config(sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -866,11 +883,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
}
|
||||
else if (slave->sii_mailbox_protocols) { // Unknown slave, has mailbox
|
||||
list_for_each_entry(eeprom_sync, &slave->eeprom_syncs, list) {
|
||||
ec_eeprom_sync_config(eeprom_sync, data);
|
||||
ec_command_init_npwr(&command, slave->station_address,
|
||||
0x800 + eeprom_sync->index * EC_SYNC_SIZE,
|
||||
EC_SYNC_SIZE, data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x800 + eeprom_sync->index * EC_SYNC_SIZE,
|
||||
EC_SYNC_SIZE)) return -1;
|
||||
ec_eeprom_sync_config(eeprom_sync, command->data);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Setting sync manager %i failed on slave %i!\n",
|
||||
eeprom_sync->index, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -896,12 +913,11 @@ int ecrt_master_activate(ec_master_t *master /**< EtherCAT-Master */)
|
|||
for (j = 0; j < slave->fmmu_count; j++)
|
||||
{
|
||||
fmmu = &slave->fmmus[j];
|
||||
|
||||
ec_fmmu_config(fmmu, data);
|
||||
ec_command_init_npwr(&command, slave->station_address,
|
||||
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE,
|
||||
data);
|
||||
if (unlikely(ec_master_simple_io(master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
0x0600 + j * EC_FMMU_SIZE, EC_FMMU_SIZE))
|
||||
return -1;
|
||||
ec_fmmu_config(fmmu, command->data);
|
||||
if (unlikely(ec_master_simple_io(master))) {
|
||||
EC_ERR("Setting FMMU %i failed on slave %i!\n",
|
||||
j, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -980,31 +996,17 @@ int ecrt_master_fetch_sdo_lists(ec_master_t *master /**< EtherCAT-Master */)
|
|||
|
||||
void ecrt_master_sync_io(ec_master_t *master)
|
||||
{
|
||||
ec_command_t *command, *next;
|
||||
ec_command_t *command, *n;
|
||||
unsigned int commands_sent;
|
||||
cycles_t t_start, t_end, t_timeout;
|
||||
|
||||
ec_master_output_stats(master);
|
||||
|
||||
if (unlikely(!master->device->link_state)) {
|
||||
// Link DOWN, keines der Kommandos kann gesendet werden.
|
||||
list_for_each_entry_safe(command, next, &master->commands, list) {
|
||||
command->state = EC_CMD_ERROR;
|
||||
list_del_init(&command->list);
|
||||
}
|
||||
|
||||
// Device-Zustand abfragen
|
||||
ec_device_call_isr(master->device);
|
||||
return;
|
||||
}
|
||||
|
||||
// Rahmen senden
|
||||
ec_master_send_commands(master);
|
||||
// Kommandos senden
|
||||
ecrt_master_async_send(master);
|
||||
|
||||
t_start = get_cycles(); // Sendezeit nehmen
|
||||
t_timeout = (cycles_t) master->timeout * (cpu_khz / 1000);
|
||||
|
||||
while (1)
|
||||
while (1) // Aktiv auf Empfang warten
|
||||
{
|
||||
ec_device_call_isr(master->device);
|
||||
|
||||
|
|
@ -1012,9 +1014,9 @@ void ecrt_master_sync_io(ec_master_t *master)
|
|||
if (t_end - t_start >= t_timeout) break; // Timeout
|
||||
|
||||
commands_sent = 0;
|
||||
list_for_each_entry_safe(command, next, &master->commands, list) {
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
if (command->state == EC_CMD_RECEIVED)
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
else if (command->state == EC_CMD_SENT)
|
||||
commands_sent++;
|
||||
}
|
||||
|
|
@ -1023,7 +1025,7 @@ void ecrt_master_sync_io(ec_master_t *master)
|
|||
}
|
||||
|
||||
// Zeit abgelaufen. Alle verbleibenden Kommandos entfernen.
|
||||
list_for_each_entry_safe(command, next, &master->commands, list) {
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
switch (command->state) {
|
||||
case EC_CMD_SENT:
|
||||
case EC_CMD_QUEUED:
|
||||
|
|
@ -1038,7 +1040,7 @@ void ecrt_master_sync_io(ec_master_t *master)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1050,15 +1052,13 @@ void ecrt_master_sync_io(ec_master_t *master)
|
|||
|
||||
void ecrt_master_async_send(ec_master_t *master)
|
||||
{
|
||||
ec_command_t *command, *next;
|
||||
|
||||
ec_master_output_stats(master);
|
||||
ec_command_t *command, *n;
|
||||
|
||||
if (unlikely(!master->device->link_state)) {
|
||||
// Link DOWN, keines der Kommandos kann gesendet werden.
|
||||
list_for_each_entry_safe(command, next, &master->commands, list) {
|
||||
list_for_each_entry_safe(command, n, &master->command_queue, queue) {
|
||||
command->state = EC_CMD_ERROR;
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
}
|
||||
|
||||
// Device-Zustand abfragen
|
||||
|
|
@ -1066,10 +1066,6 @@ void ecrt_master_async_send(ec_master_t *master)
|
|||
return;
|
||||
}
|
||||
|
||||
// Watch-Kommando hinzufügen
|
||||
ec_command_init_brd(&master->watch_command, 0x130, 2);
|
||||
ec_master_queue_command(master, &master->watch_command);
|
||||
|
||||
// Rahmen senden
|
||||
ec_master_send_commands(master);
|
||||
}
|
||||
|
|
@ -1087,12 +1083,11 @@ void ecrt_master_async_receive(ec_master_t *master)
|
|||
ec_device_call_isr(master->device);
|
||||
|
||||
// Alle empfangenen Kommandos aus der Liste entfernen
|
||||
list_for_each_entry_safe(command, next, &master->commands, list)
|
||||
if (command->state == EC_CMD_RECEIVED)
|
||||
list_del_init(&command->list);
|
||||
list_for_each_entry_safe(command, next, &master->command_queue, queue)
|
||||
if (command->state == EC_CMD_RECEIVED) list_del_init(&command->queue);
|
||||
|
||||
// Alle verbleibenden Kommandos entfernen.
|
||||
list_for_each_entry_safe(command, next, &master->commands, list) {
|
||||
list_for_each_entry_safe(command, next, &master->command_queue, queue) {
|
||||
switch (command->state) {
|
||||
case EC_CMD_SENT:
|
||||
case EC_CMD_QUEUED:
|
||||
|
|
@ -1103,14 +1098,8 @@ void ecrt_master_async_receive(ec_master_t *master)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
list_del_init(&command->list);
|
||||
list_del_init(&command->queue);
|
||||
}
|
||||
|
||||
// Watch-Kommando verarbeiten
|
||||
ec_master_process_watch_command(master);
|
||||
|
||||
// Statistiken ausgeben
|
||||
ec_master_output_stats(master);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -1128,7 +1117,7 @@ void ecrt_master_prepare_async_io(ec_master_t *master)
|
|||
ec_domain_t *domain;
|
||||
cycles_t t_start, t_end, t_timeout;
|
||||
|
||||
// Alle empfangenen Kommandos aus der Liste entfernen
|
||||
// Kommandos aller Domains in die Warteschlange setzen
|
||||
list_for_each_entry(domain, &master->domains, list)
|
||||
ecrt_domain_queue(domain);
|
||||
|
||||
|
|
@ -1146,6 +1135,22 @@ void ecrt_master_prepare_async_io(ec_master_t *master)
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Führt Routinen im zyklischen Betrieb aus.
|
||||
*/
|
||||
|
||||
void ecrt_master_run(ec_master_t *master /**< EtherCAT-Master */)
|
||||
{
|
||||
// Statistiken ausgeben
|
||||
ec_master_output_stats(master);
|
||||
|
||||
// Watchdog-Kommando
|
||||
ec_master_process_watch_command(master);
|
||||
ec_master_queue_command(master, &master->watch_command);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Setzt die Debug-Ebene des Masters.
|
||||
|
||||
|
|
@ -1198,6 +1203,7 @@ EXPORT_SYMBOL(ecrt_master_prepare_async_io);
|
|||
EXPORT_SYMBOL(ecrt_master_sync_io);
|
||||
EXPORT_SYMBOL(ecrt_master_async_send);
|
||||
EXPORT_SYMBOL(ecrt_master_async_receive);
|
||||
EXPORT_SYMBOL(ecrt_master_run);
|
||||
EXPORT_SYMBOL(ecrt_master_debug);
|
||||
EXPORT_SYMBOL(ecrt_master_print);
|
||||
EXPORT_SYMBOL(ecrt_master_get_slave);
|
||||
|
|
|
|||
|
|
@ -47,9 +47,10 @@ struct ec_master
|
|||
ec_slave_t *slaves; /**< Array von Slaves auf dem Bus */
|
||||
unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */
|
||||
ec_device_t *device; /**< EtherCAT-Gerät */
|
||||
struct list_head commands; /**< Kommando-Liste */
|
||||
struct list_head command_queue; /**< Kommando-Warteschlange */
|
||||
uint8_t command_index; /**< Aktueller Kommando-Index */
|
||||
struct list_head domains; /**< Liste der Prozessdatendomänen */
|
||||
ec_command_t simple_command; /**< Kommando für Initialisierungsphase */
|
||||
ec_command_t watch_command; /**< Kommando zum Überwachen der Slaves */
|
||||
unsigned int slaves_responding; /**< Anzahl antwortender Slaves */
|
||||
ec_slave_state_t slave_states; /**< Zustände der antwortenden Slaves */
|
||||
|
|
@ -68,7 +69,7 @@ void ec_master_reset(ec_master_t *);
|
|||
// IO
|
||||
void ec_master_receive(ec_master_t *, const uint8_t *, size_t);
|
||||
void ec_master_queue_command(ec_master_t *, ec_command_t *);
|
||||
int ec_master_simple_io(ec_master_t *, ec_command_t *);
|
||||
int ec_master_simple_io(ec_master_t *);
|
||||
|
||||
// Registration of devices
|
||||
int ec_master_open(ec_master_t *);
|
||||
|
|
|
|||
294
master/slave.c
294
master/slave.c
|
|
@ -141,36 +141,38 @@ void ec_slave_clear(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
|
||||
int ec_slave_fetch(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
{
|
||||
ec_command_t command;
|
||||
ec_command_t *command;
|
||||
unsigned int i;
|
||||
uint16_t dl_status;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
// Read base data
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x0000, 6);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0000, 6)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Reading base data from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
slave->base_type = EC_READ_U8 (command.data);
|
||||
slave->base_revision = EC_READ_U8 (command.data + 1);
|
||||
slave->base_build = EC_READ_U16(command.data + 2);
|
||||
slave->base_fmmu_count = EC_READ_U8 (command.data + 4);
|
||||
slave->base_sync_count = EC_READ_U8 (command.data + 5);
|
||||
slave->base_type = EC_READ_U8 (command->data);
|
||||
slave->base_revision = EC_READ_U8 (command->data + 1);
|
||||
slave->base_build = EC_READ_U16(command->data + 2);
|
||||
slave->base_fmmu_count = EC_READ_U8 (command->data + 4);
|
||||
slave->base_sync_count = EC_READ_U8 (command->data + 5);
|
||||
|
||||
if (slave->base_fmmu_count > EC_MAX_FMMUS)
|
||||
slave->base_fmmu_count = EC_MAX_FMMUS;
|
||||
|
||||
// Read DL status
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x0110, 2);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0110, 2)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Reading DL status from slave %i failed!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dl_status = EC_READ_U16(command.data);
|
||||
dl_status = EC_READ_U16(command->data);
|
||||
for (i = 0; i < 2; i++) {
|
||||
slave->dl_status_link[i] = dl_status & (1 << (4 + i)) ? 1 : 0;
|
||||
slave->dl_status_loop[i] = dl_status & (1 << (8 + i * 2)) ? 1 : 0;
|
||||
|
|
@ -224,18 +226,17 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
|||
/**< Speicher für Wert (16-Bit) */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[10];
|
||||
ec_command_t *command;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
// Initiate read operation
|
||||
|
||||
EC_WRITE_U8 (data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(data + 2, offset);
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x502, 6, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -251,8 +252,9 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
|||
{
|
||||
udelay(10);
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x502, 10);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -260,8 +262,8 @@ int ec_slave_sii_read16(ec_slave_t *slave,
|
|||
|
||||
end = get_cycles();
|
||||
|
||||
if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U16(command.data + 6);
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U16(command->data + 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -289,18 +291,17 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
|||
/**< Speicher für Wert (32-Bit) */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[10];
|
||||
ec_command_t *command;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
// Initiate read operation
|
||||
|
||||
EC_WRITE_U8 (data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(data + 2, offset);
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x502, 6, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 6)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x00); // read-only access
|
||||
EC_WRITE_U8 (command->data + 1, 0x01); // request read operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("SII-read failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -316,8 +317,9 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
|||
{
|
||||
udelay(10);
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x502, 10);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 10))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Getting SII-read status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -325,8 +327,8 @@ int ec_slave_sii_read32(ec_slave_t *slave,
|
|||
|
||||
end = get_cycles();
|
||||
|
||||
if (likely((EC_READ_U8(command.data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U32(command.data + 6);
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x81) == 0)) {
|
||||
*target = EC_READ_U32(command->data + 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -354,22 +356,21 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
|||
/**< Zu schreibender Wert */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[8];
|
||||
ec_command_t *command;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
EC_INFO("SII-write (slave %i, offset 0x%04X, value 0x%04X)\n",
|
||||
slave->ring_position, offset, value);
|
||||
|
||||
// Initiate write operation
|
||||
|
||||
EC_WRITE_U8 (data, 0x01); // enable write access
|
||||
EC_WRITE_U8 (data + 1, 0x02); // request write operation
|
||||
EC_WRITE_U32(data + 2, offset);
|
||||
EC_WRITE_U16(data + 6, value);
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x502, 8, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x502, 8)) return -1;
|
||||
EC_WRITE_U8 (command->data, 0x01); // enable write access
|
||||
EC_WRITE_U8 (command->data + 1, 0x02); // request write operation
|
||||
EC_WRITE_U32(command->data + 2, offset);
|
||||
EC_WRITE_U16(command->data + 6, value);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("SII-write failed on slave %i!\n", slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -385,8 +386,9 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
|||
{
|
||||
udelay(10);
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x502, 2);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x502, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Getting SII-write status failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -394,8 +396,8 @@ int ec_slave_sii_write16(ec_slave_t *slave,
|
|||
|
||||
end = get_cycles();
|
||||
|
||||
if (likely((EC_READ_U8(command.data + 1) & 0x82) == 0)) {
|
||||
if (EC_READ_U8(command.data + 1) & 0x40) {
|
||||
if (likely((EC_READ_U8(command->data + 1) & 0x82) == 0)) {
|
||||
if (EC_READ_U8(command->data + 1) & 0x40) {
|
||||
EC_ERR("SII-write failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -717,14 +719,14 @@ void ec_slave_state_ack(ec_slave_t *slave,
|
|||
/**< Alter Zustand */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[2];
|
||||
ec_command_t *command;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
EC_WRITE_U16(data, state | EC_ACK);
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x0120, 2, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return;
|
||||
EC_WRITE_U16(command->data, state | EC_ACK);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_WARN("State %02X acknowledge failed on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return;
|
||||
|
|
@ -737,8 +739,9 @@ void ec_slave_state_ack(ec_slave_t *slave,
|
|||
{
|
||||
udelay(100); // Dem Slave etwas Zeit lassen...
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x0130, 2);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
return;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_WARN("State %02X acknowledge checking failed on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return;
|
||||
|
|
@ -746,14 +749,14 @@ void ec_slave_state_ack(ec_slave_t *slave,
|
|||
|
||||
end = get_cycles();
|
||||
|
||||
if (unlikely(EC_READ_U8(command.data) != state)) {
|
||||
if (unlikely(EC_READ_U8(command->data) != state)) {
|
||||
EC_WARN("Could not acknowledge state %02X on slave %i (code"
|
||||
" %02X)!\n", state, slave->ring_position,
|
||||
EC_READ_U8(command.data));
|
||||
EC_READ_U8(command->data));
|
||||
return;
|
||||
}
|
||||
|
||||
if (likely(EC_READ_U8(command.data) == state)) {
|
||||
if (likely(EC_READ_U8(command->data) == state)) {
|
||||
EC_INFO("Acknowleged state %02X on slave %i.\n", state,
|
||||
slave->ring_position);
|
||||
return;
|
||||
|
|
@ -781,14 +784,14 @@ int ec_slave_state_change(ec_slave_t *slave,
|
|||
/**< Neuer Zustand */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[2];
|
||||
ec_command_t *command;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
EC_WRITE_U16(data, state);
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x0120, 2, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0120, 2)) return -1;
|
||||
EC_WRITE_U16(command->data, state);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Failed to set state %02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -801,8 +804,9 @@ int ec_slave_state_change(ec_slave_t *slave,
|
|||
{
|
||||
udelay(100); // Dem Slave etwas Zeit lassen...
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x0130, 2);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0130, 2))
|
||||
return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Failed to check state %02X on slave %i!\n",
|
||||
state, slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -810,15 +814,15 @@ int ec_slave_state_change(ec_slave_t *slave,
|
|||
|
||||
end = get_cycles();
|
||||
|
||||
if (unlikely(EC_READ_U8(command.data) & 0x10)) { // State change error
|
||||
if (unlikely(EC_READ_U8(command->data) & 0x10)) { // State change error
|
||||
EC_ERR("Could not set state %02X - Slave %i refused state change"
|
||||
" (code %02X)!\n", state, slave->ring_position,
|
||||
EC_READ_U8(command.data));
|
||||
ec_slave_state_ack(slave, EC_READ_U8(command.data) & 0x0F);
|
||||
EC_READ_U8(command->data));
|
||||
ec_slave_state_ack(slave, EC_READ_U8(command->data) & 0x0F);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (likely(EC_READ_U8(command.data) == (state & 0x0F))) {
|
||||
if (likely(EC_READ_U8(command->data) == (state & 0x0F))) {
|
||||
// State change successful
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1040,44 +1044,45 @@ void ec_slave_print(const ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
|
||||
int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
{
|
||||
ec_command_t command;
|
||||
uint8_t data[4];
|
||||
ec_command_t *command;
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x0300, 4);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
if (ec_command_nprd(command, slave->station_address, 0x0300, 4)) return -1;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_WARN("Reading CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// No CRC faults.
|
||||
if (!EC_READ_U32(command.data)) return 0;
|
||||
if (!EC_READ_U32(command->data)) return 0;
|
||||
|
||||
if (EC_READ_U8(command.data))
|
||||
if (EC_READ_U8(command->data))
|
||||
EC_WARN("%3i RX-error%s on slave %i, channel A.\n",
|
||||
EC_READ_U8(command.data),
|
||||
EC_READ_U8(command.data) == 1 ? "" : "s",
|
||||
EC_READ_U8(command->data),
|
||||
EC_READ_U8(command->data) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command.data + 1))
|
||||
if (EC_READ_U8(command->data + 1))
|
||||
EC_WARN("%3i invalid frame%s on slave %i, channel A.\n",
|
||||
EC_READ_U8(command.data + 1),
|
||||
EC_READ_U8(command.data + 1) == 1 ? "" : "s",
|
||||
EC_READ_U8(command->data + 1),
|
||||
EC_READ_U8(command->data + 1) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command.data + 2))
|
||||
if (EC_READ_U8(command->data + 2))
|
||||
EC_WARN("%3i RX-error%s on slave %i, channel B.\n",
|
||||
EC_READ_U8(command.data + 2),
|
||||
EC_READ_U8(command.data + 2) == 1 ? "" : "s",
|
||||
EC_READ_U8(command->data + 2),
|
||||
EC_READ_U8(command->data + 2) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
if (EC_READ_U8(command.data + 3))
|
||||
if (EC_READ_U8(command->data + 3))
|
||||
EC_WARN("%3i invalid frame%s on slave %i, channel B.\n",
|
||||
EC_READ_U8(command.data + 3),
|
||||
EC_READ_U8(command.data + 3) == 1 ? "" : "s",
|
||||
EC_READ_U8(command->data + 3),
|
||||
EC_READ_U8(command->data + 3) == 1 ? "" : "s",
|
||||
slave->ring_position);
|
||||
|
||||
// Reset CRC counters
|
||||
EC_WRITE_U32(data, 0x00000000);
|
||||
ec_command_init_npwr(&command, slave->station_address, 0x0300, 4, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_npwr(command, slave->station_address, 0x0300, 4)) return -1;
|
||||
EC_WRITE_U32(command->data, 0x00000000);
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_WARN("Resetting CRC fault counters failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
|
|
@ -1089,74 +1094,60 @@ int ec_slave_check_crc(ec_slave_t *slave /**< EtherCAT-Slave */)
|
|||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet ein Mailbox-Kommando.
|
||||
Bereitet ein Mailbox-Send-Kommando vor.
|
||||
*/
|
||||
|
||||
int ec_slave_mailbox_send(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint8_t type, /**< Unterliegendes Protokoll */
|
||||
const uint8_t *prot_data, /**< Protokoll-Daten */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Mailbox-Protokoll */
|
||||
size_t size /**< Datengröße */
|
||||
)
|
||||
{
|
||||
size_t total_size;
|
||||
uint8_t *data;
|
||||
ec_command_t command;
|
||||
ec_command_t *command;
|
||||
|
||||
if (unlikely(!slave->sii_mailbox_protocols)) {
|
||||
EC_ERR("Slave %i does not support mailbox communication!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
total_size = size + 6;
|
||||
if (unlikely(total_size > slave->sii_rx_mailbox_size)) {
|
||||
EC_ERR("Data size does not fit in mailbox!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(data = kmalloc(slave->sii_rx_mailbox_size, GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate %i bytes of memory for mailbox data!\n",
|
||||
slave->sii_rx_mailbox_size);
|
||||
return -1;
|
||||
}
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
memset(data, 0x00, slave->sii_rx_mailbox_size);
|
||||
EC_WRITE_U16(data, size); // Length of the Mailbox service data
|
||||
EC_WRITE_U16(data + 2, slave->station_address); // Station address
|
||||
EC_WRITE_U8 (data + 4, 0x00); // Channel & priority
|
||||
EC_WRITE_U8 (data + 5, type); // Underlying protocol type
|
||||
memcpy(data + 6, prot_data, size);
|
||||
if (ec_command_npwr(command, slave->station_address,
|
||||
slave->sii_rx_mailbox_offset,
|
||||
slave->sii_rx_mailbox_size)) return NULL;
|
||||
EC_WRITE_U16(command->data, size); // Mailbox service data length
|
||||
EC_WRITE_U16(command->data + 2, slave->station_address); // Station address
|
||||
EC_WRITE_U8 (command->data + 4, 0x00); // Channel & priority
|
||||
EC_WRITE_U8 (command->data + 5, type); // Underlying protocol type
|
||||
|
||||
ec_command_init_npwr(&command, slave->station_address,
|
||||
slave->sii_rx_mailbox_offset,
|
||||
slave->sii_rx_mailbox_size, data);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
EC_ERR("Mailbox sending failed on slave %i!\n", slave->ring_position);
|
||||
kfree(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
return 0;
|
||||
return command->data + 6;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet ein Mailbox-Kommando.
|
||||
Empfängt ein Mailbox-Kommando.
|
||||
*/
|
||||
|
||||
int ec_slave_mailbox_receive(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint8_t type, /**< Unterliegendes Protokoll */
|
||||
uint8_t *prot_data, /**< Protokoll-Daten */
|
||||
size_t *size /**< Datengröße des Puffers, später
|
||||
Größe der gelesenen Daten */
|
||||
)
|
||||
uint8_t *ec_slave_mailbox_receive(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
)
|
||||
{
|
||||
ec_command_t command;
|
||||
ec_command_t *command;
|
||||
size_t data_size;
|
||||
cycles_t start, end, timeout;
|
||||
|
||||
command = &slave->master->simple_command;
|
||||
|
||||
// Read "written bit" of Sync-Manager
|
||||
start = get_cycles();
|
||||
timeout = (cycles_t) 100 * cpu_khz; // 100ms
|
||||
|
|
@ -1164,59 +1155,54 @@ int ec_slave_mailbox_receive(ec_slave_t *slave, /**< EtherCAT-Slave */
|
|||
while (1)
|
||||
{
|
||||
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
|
||||
ec_command_init_nprd(&command, slave->station_address, 0x808, 8);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
|
||||
return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = get_cycles();
|
||||
|
||||
if (EC_READ_U8(command.data + 5) & 8)
|
||||
if (EC_READ_U8(command->data + 5) & 8)
|
||||
break; // Proceed with received data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
EC_ERR("Mailbox check - Slave %i timed out.\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
ec_command_init_nprd(&command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size);
|
||||
if (unlikely(ec_master_simple_io(slave->master, &command))) {
|
||||
if (ec_command_nprd(command, slave->station_address,
|
||||
slave->sii_tx_mailbox_offset,
|
||||
slave->sii_tx_mailbox_size)) return NULL;
|
||||
if (unlikely(ec_master_simple_io(slave->master))) {
|
||||
EC_ERR("Mailbox receiving failed on slave %i!\n",
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((EC_READ_U8(command.data + 5) & 0x0F) != type) {
|
||||
if ((EC_READ_U8(command->data + 5) & 0x0F) != type) {
|
||||
EC_ERR("Unexpected mailbox protocol 0x%02X (exp.: 0x%02X) at"
|
||||
" slave %i!\n", EC_READ_U8(command.data + 5), type,
|
||||
" slave %i!\n", EC_READ_U8(command->data + 5), type,
|
||||
slave->ring_position);
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unlikely(slave->master->debug_level) > 1)
|
||||
EC_DBG("Mailbox receive took %ius.\n", ((u32) (end - start) * 1000
|
||||
/ cpu_khz));
|
||||
|
||||
if ((data_size = EC_READ_U16(command.data)) > *size) {
|
||||
EC_ERR("Mailbox service data does not fit into buffer (%i > %i).\n",
|
||||
data_size, *size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data_size > slave->sii_tx_mailbox_size - 6) {
|
||||
if ((data_size = EC_READ_U16(command->data)) >
|
||||
slave->sii_tx_mailbox_size - 6) {
|
||||
EC_ERR("Currupt mailbox response detected!\n");
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(prot_data, command.data + 6, data_size);
|
||||
*size = data_size;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ int ec_slave_state_change(ec_slave_t *, uint8_t);
|
|||
int ec_slave_set_fmmu(ec_slave_t *, const ec_domain_t *, const ec_sync_t *);
|
||||
|
||||
// Mailbox
|
||||
int ec_slave_mailbox_send(ec_slave_t *, uint8_t, const uint8_t *, size_t);
|
||||
int ec_slave_mailbox_receive(ec_slave_t *, uint8_t, uint8_t *, size_t *);
|
||||
uint8_t *ec_slave_prepare_mailbox_send(ec_slave_t *, uint8_t, size_t);
|
||||
uint8_t *ec_slave_mailbox_receive(ec_slave_t *, uint8_t, size_t *);
|
||||
|
||||
// CANopen over EtherCAT
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *);
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ static void msr_controller_run(void)
|
|||
k_preio = (uint32_t) (get_cycles() - offset) * 1e6 / cpu_khz;
|
||||
|
||||
#ifdef ASYNC
|
||||
|
||||
// Empfangen
|
||||
ecrt_master_async_receive(master);
|
||||
ecrt_domain_process(domain1);
|
||||
|
|
@ -113,10 +114,14 @@ static void msr_controller_run(void)
|
|||
|
||||
// Senden
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_run(master);
|
||||
ecrt_master_async_send(master);
|
||||
#else
|
||||
|
||||
#else // ASYNC
|
||||
|
||||
// Senden und empfangen
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_run(master);
|
||||
ecrt_master_sync_io(master);
|
||||
ecrt_domain_process(domain1);
|
||||
|
||||
|
|
@ -184,9 +189,11 @@ void domain_entry(void)
|
|||
int __init init_rt_module(void)
|
||||
{
|
||||
struct ipipe_domain_attr attr; //ipipe
|
||||
#ifdef BLOCK1
|
||||
uint8_t string[20];
|
||||
size_t size;
|
||||
ec_slave_t *slave;
|
||||
#endif
|
||||
|
||||
// Als allererstes die RT-Lib initialisieren
|
||||
if (msr_rtlib_init(1, MSR_ABTASTFREQUENZ, 10, &msr_globals_register) < 0) {
|
||||
|
|
@ -286,8 +293,10 @@ int __init init_rt_module(void)
|
|||
ipipe_register_domain(&this_domain, &attr);
|
||||
return 0;
|
||||
|
||||
#ifdef BLOCK1
|
||||
out_deactivate:
|
||||
ecrt_master_deactivate(master);
|
||||
#endif
|
||||
out_release_master:
|
||||
ecrt_release_master(master);
|
||||
out_msr_cleanup:
|
||||
|
|
|
|||
Loading…
Reference in New Issue