mirror of
https://gitlab.com/etherlab.org/ethercat.git
synced 2026-02-06 11:51:45 +08:00
Translated all comments and documentation to english language.
This commit is contained in:
4
Makefile
4
Makefile
@@ -9,7 +9,7 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# kbuild section
|
||||
# kbuild section
|
||||
|
||||
obj-m := master/ devices/
|
||||
|
||||
@@ -18,7 +18,7 @@ obj-m := master/ devices/
|
||||
else
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# default section
|
||||
# default section
|
||||
|
||||
ifneq ($(wildcard ethercat.conf),)
|
||||
include ethercat.conf
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Oeffentliche EtherCAT-Schnittstellen fuer EtherCAT-Geraetetreiber.
|
||||
* EtherCAT interface for EtherCAT device drivers.
|
||||
*
|
||||
* $Id$
|
||||
* $Id$
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Oeffentliche EtherCAT-Schnittstellen fuer Echtzeitprozesse.
|
||||
* EtherCAT realtime interface.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
|
||||
195
master/canopen.c
195
master/canopen.c
@@ -28,14 +28,14 @@ const ec_code_msg_t sdo_abort_messages[];
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest 32 Bit eines CANopen-SDOs im Expedited-Modus aus einem Slave.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Reads 32 bit of a CANopen SDO in expedited mode.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint8_t *target /**< Speicher für 4 Bytes */
|
||||
int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint8_t *target /**< 4-byte memory */
|
||||
)
|
||||
{
|
||||
size_t rec_size;
|
||||
@@ -45,14 +45,14 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
|
||||
EC_WRITE_U16(data, 0x2 << 12); // SDO request
|
||||
EC_WRITE_U8 (data + 2, (0x1 << 1 // expedited transfer
|
||||
| 0x2 << 5)); // initiate upload request
|
||||
| 0x2 << 5)); // initiate upload request
|
||||
EC_WRITE_U16(data + 3, sdo_index);
|
||||
EC_WRITE_U8 (data + 5, sdo_subindex);
|
||||
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
|
||||
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
|
||||
sdo_index, sdo_subindex, slave->ring_position);
|
||||
ec_canopen_abort_msg(EC_READ_U32(data + 6));
|
||||
@@ -60,9 +60,9 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
}
|
||||
|
||||
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x2 || // Upload response
|
||||
EC_READ_U16(data + 3) != sdo_index || // Index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x2 || // upload response
|
||||
EC_READ_U16(data + 3) != sdo_index || // index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
|
||||
EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
|
||||
EC_ERR("Invalid SDO upload response at slave %i!\n",
|
||||
slave->ring_position);
|
||||
@@ -77,14 +77,14 @@ int ec_slave_sdo_read_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beschreibt ein CANopen-SDO eines Slaves im Expedited-Modus.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Writes a CANopen SDO using expedited mode.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
const uint8_t *sdo_data, /**< Neuer Wert */
|
||||
int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
const uint8_t *sdo_data, /**< new value */
|
||||
size_t size
|
||||
)
|
||||
{
|
||||
@@ -111,7 +111,7 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
|
||||
EC_ERR("SDO download 0x%04X:%X (%i bytes) aborted on slave %i.\n",
|
||||
sdo_index, sdo_subindex, size, slave->ring_position);
|
||||
ec_canopen_abort_msg(EC_READ_U32(data + 6));
|
||||
@@ -119,9 +119,9 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
}
|
||||
|
||||
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x3 || // Download response
|
||||
EC_READ_U16(data + 3) != sdo_index || // Index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x3 || // download response
|
||||
EC_READ_U16(data + 3) != sdo_index || // index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
|
||||
EC_ERR("SDO download 0x%04X:%X (%i bytes) failed:\n",
|
||||
sdo_index, sdo_subindex, size);
|
||||
EC_ERR("Invalid SDO download response at slave %i!\n",
|
||||
@@ -136,15 +136,17 @@ int ec_slave_sdo_write_exp(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest ein CANopen-SDO im "Normal-Modus" aus einem Slave.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Reads a CANopen SDO in normal mode.
|
||||
\return 0 in case of success, else < 0
|
||||
|
||||
\todo size
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint8_t *target, /**< Speicher für gel. Wert */
|
||||
size_t *size /**< Größe des Speichers */
|
||||
int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint8_t *target, /**< memory for value */
|
||||
size_t *size /**< target memory size */
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
@@ -161,7 +163,7 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x2 && // SDO request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // Abort SDO transfer request
|
||||
EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort SDO transfer request
|
||||
EC_ERR("SDO upload 0x%04X:%X aborted on slave %i.\n",
|
||||
sdo_index, sdo_subindex, slave->ring_position);
|
||||
ec_canopen_abort_msg(EC_READ_U32(data + 6));
|
||||
@@ -169,9 +171,9 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
}
|
||||
|
||||
if (EC_READ_U16(data) >> 12 != 0x3 || // SDO response
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x2 || // Initiate upload response
|
||||
EC_READ_U16(data + 3) != sdo_index || // Index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // Subindex
|
||||
EC_READ_U8 (data + 2) >> 5 != 0x2 || // initiate upload response
|
||||
EC_READ_U16(data + 3) != sdo_index || // index
|
||||
EC_READ_U8 (data + 5) != sdo_subindex) { // subindex
|
||||
EC_ERR("SDO upload 0x%04X:%X failed:\n", sdo_index, sdo_subindex);
|
||||
EC_ERR("Invalid SDO upload response at slave %i!\n",
|
||||
slave->ring_position);
|
||||
@@ -205,11 +207,11 @@ int ecrt_slave_sdo_read(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Lädt das gesamte SDO-Dictionary aus einem Slave.
|
||||
\return 0, wenn alles ok, sonst < 0
|
||||
Fetches the SDO dictionary of a slave.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t rec_size;
|
||||
@@ -223,7 +225,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
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!
|
||||
EC_WRITE_U16(data + 6, 0x0001); // deliver all SDOs!
|
||||
|
||||
if (unlikely(ec_master_simple_io(slave->master, &slave->mbox_command))) {
|
||||
EC_ERR("Mailbox checking failed on slave %i!\n", slave->ring_position);
|
||||
@@ -235,7 +237,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // Error response
|
||||
(EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
|
||||
EC_ERR("SDO information error response at slave %i!\n",
|
||||
slave->ring_position);
|
||||
ec_canopen_abort_msg(EC_READ_U32(data + 6));
|
||||
@@ -259,7 +261,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
sdo_count = (rec_size - 8) / 2;
|
||||
for (i = 0; i < sdo_count; i++) {
|
||||
sdo_index = EC_READ_U16(data + 8 + i * 2);
|
||||
if (!sdo_index) continue; // Manchmal ist der Index 0... ???
|
||||
if (!sdo_index) continue; // sometimes index is 0... ???
|
||||
|
||||
if (!(sdo = (ec_sdo_t *) kmalloc(sizeof(ec_sdo_t), GFP_KERNEL))) {
|
||||
EC_ERR("Failed to allocate memory for SDO!\n");
|
||||
@@ -278,7 +280,7 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
}
|
||||
while (EC_READ_U8(data + 2) & 0x80);
|
||||
|
||||
// Alle Beschreibungen laden
|
||||
// Fetch all SDO descriptions
|
||||
if (ec_slave_fetch_sdo_descriptions(slave)) return -1;
|
||||
|
||||
return 0;
|
||||
@@ -287,11 +289,11 @@ int ec_slave_fetch_sdo_list(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Holt die Beschreibungen zu allen bereits bekannten SDOs.
|
||||
\return 0, wenn alles ok, sonst < 0
|
||||
Fetches the SDO descriptions for the known SDOs.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT slave */)
|
||||
{
|
||||
uint8_t *data;
|
||||
size_t rec_size, name_size;
|
||||
@@ -308,7 +310,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
|
||||
EC_ERR("SDO information error response at slave %i while"
|
||||
" fetching SDO 0x%04X!\n", slave->ring_position,
|
||||
sdo->index);
|
||||
@@ -354,7 +356,7 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Alle Entries (Subindizes) laden
|
||||
// Fetch all entries (subindices)
|
||||
if (ec_slave_fetch_sdo_entries(slave, sdo, EC_READ_U8(data + 10)))
|
||||
return -1;
|
||||
}
|
||||
@@ -365,13 +367,13 @@ int ec_slave_fetch_sdo_descriptions(ec_slave_t *slave /**< EtherCAT-Slave */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Lädt alle Entries (Subindizes) zu einem SDO.
|
||||
\return 0, wenn alles ok, sonst < 0
|
||||
Fetches all entries (subindices) to an SDO.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
ec_sdo_t *sdo, /**< SDO */
|
||||
uint8_t subindices /**< Anzahl Subindizes */
|
||||
uint8_t subindices /**< number of subindices */
|
||||
)
|
||||
{
|
||||
uint8_t *data;
|
||||
@@ -394,7 +396,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
if (!(data = ec_slave_mbox_simple_io(slave, &rec_size))) return -1;
|
||||
|
||||
if (EC_READ_U16(data) >> 12 == 0x8 && // SDO information
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // Error response
|
||||
(EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
|
||||
EC_ERR("SDO information error response at slave %i while"
|
||||
" fetching SDO entry 0x%04X:%i!\n", slave->ring_position,
|
||||
sdo->index, i);
|
||||
@@ -403,7 +405,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
}
|
||||
|
||||
if (EC_READ_U16(data) >> 12 != 0x8 || // SDO information
|
||||
(EC_READ_U8(data + 2) & 0x7F) != 0x06 || // entry descr. response
|
||||
(EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
|
||||
EC_READ_U16(data + 6) != sdo->index || // SDO index
|
||||
EC_READ_U8(data + 8) != i) { // SDO subindex
|
||||
EC_ERR("Invalid entry description response at slave %i while"
|
||||
@@ -449,7 +451,7 @@ int ec_slave_fetch_sdo_entries(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt eine SDO-Abort-Meldung aus.
|
||||
Outputs an SDO abort message.
|
||||
*/
|
||||
|
||||
void ec_canopen_abort_msg(uint32_t abort_code)
|
||||
@@ -506,21 +508,20 @@ const ec_code_msg_t sdo_abort_messages[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
// Echtzeitschnittstelle
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest ein 8-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
|
||||
Siehe ec_slave_sdo_read_exp()
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Reads an 8-bit SDO in expedited mode.
|
||||
See ec_slave_sdo_read_exp()
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint8_t *target /**< Speicher für gel. Wert */
|
||||
int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint8_t *target /**< memory for read value */
|
||||
)
|
||||
{
|
||||
uint8_t data[4];
|
||||
@@ -532,15 +533,15 @@ int ecrt_slave_sdo_read_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest ein 16-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
|
||||
Siehe ec_slave_sdo_read_exp()
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Reads a 16-bit SDO in expedited mode.
|
||||
See ec_slave_sdo_read_exp()
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint16_t *target /**< Speicher für gel. Wert */
|
||||
int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint16_t *target /**< memory for read value */
|
||||
)
|
||||
{
|
||||
uint8_t data[4];
|
||||
@@ -552,15 +553,15 @@ int ecrt_slave_sdo_read_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest ein 32-Bit CANopen-SDO im Expedited-Modus aus einem Slave.
|
||||
Siehe ec_slave_sdo_read_exp()
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Reads a 32-bit SDO in expedited mode.
|
||||
See ec_slave_sdo_read_exp()
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint32_t *target /**< Speicher für gel. Wert */
|
||||
int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint32_t *target /**< memory for read value */
|
||||
)
|
||||
{
|
||||
uint8_t data[4];
|
||||
@@ -572,14 +573,14 @@ int ecrt_slave_sdo_read_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beschreibt ein 8-Bit CANopen-SDO eines Slaves im Expedited-Modus.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Writes an 8-bit SDO in expedited mode.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint8_t value /**< Neuer Wert */
|
||||
int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint8_t value /**< new value */
|
||||
)
|
||||
{
|
||||
return ec_slave_sdo_write_exp(slave, sdo_index, sdo_subindex, &value, 1);
|
||||
@@ -588,14 +589,14 @@ int ecrt_slave_sdo_write_exp8(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beschreibt ein 16-Bit CANopen-SDO eines Slaves im Expedited-Modus.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Writes a 16-bit SDO in expedited mode.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint16_t value /**< Neuer Wert */
|
||||
int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint16_t value /**< new value */
|
||||
)
|
||||
{
|
||||
uint8_t data[2];
|
||||
@@ -606,14 +607,14 @@ int ecrt_slave_sdo_write_exp16(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beschreibt ein 32-Bit CANopen-SDO eines Slaves im Expedited-Modus.
|
||||
\return 0 wenn alles ok, < 0 bei Fehler
|
||||
Writes a 32-bit SDO in expedited mode.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT-Slave */
|
||||
uint16_t sdo_index, /**< SDO-Index */
|
||||
uint8_t sdo_subindex, /**< SDO-Subindex */
|
||||
uint32_t value /**< Neuer Wert */
|
||||
int ecrt_slave_sdo_write_exp32(ec_slave_t *slave, /**< EtherCAT slave */
|
||||
uint16_t sdo_index, /**< SDO index */
|
||||
uint8_t sdo_subindex, /**< SDO subindex */
|
||||
uint32_t value /**< new value */
|
||||
)
|
||||
{
|
||||
uint8_t data[4];
|
||||
@@ -632,9 +633,3 @@ EXPORT_SYMBOL(ecrt_slave_sdo_write_exp32);
|
||||
EXPORT_SYMBOL(ecrt_slave_sdo_read);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* c o m m a n d . c
|
||||
*
|
||||
* Methoden für ein EtherCAT-Kommando.
|
||||
* Methods of an EtherCAT command.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -31,7 +31,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Konstruktor.
|
||||
Command constructor.
|
||||
*/
|
||||
|
||||
void ec_command_init(ec_command_t *command)
|
||||
@@ -49,7 +49,7 @@ void ec_command_init(ec_command_t *command)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Destruktor.
|
||||
Command destructor.
|
||||
*/
|
||||
|
||||
void ec_command_clear(ec_command_t *command)
|
||||
@@ -60,7 +60,8 @@ void ec_command_clear(ec_command_t *command)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Alloziert Speicher.
|
||||
Allocates command data memory.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_prealloc(ec_command_t *command, size_t size)
|
||||
@@ -85,19 +86,19 @@ int ec_command_prealloc(ec_command_t *command, size_t size)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-NPRD-Kommando.
|
||||
|
||||
Initializes an EtherCAT NPRD command.
|
||||
Node-adressed physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_nprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
@@ -113,19 +114,19 @@ int ec_command_nprd(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-NPWR-Kommando.
|
||||
|
||||
Initializes an EtherCAT NPWR command.
|
||||
Node-adressed physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_npwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t node_address,
|
||||
/**< Adresse des Knotens (Slaves) */
|
||||
/**< configured station address */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
if (unlikely(node_address == 0x0000))
|
||||
@@ -141,19 +142,19 @@ int ec_command_npwr(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-APRD-Kommando.
|
||||
|
||||
Initializes an EtherCAT APRD command.
|
||||
Autoincrement physical read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_aprd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
@@ -166,19 +167,19 @@ int ec_command_aprd(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-APWR-Kommando.
|
||||
|
||||
Initializes an EtherCAT APWR command.
|
||||
Autoincrement physical write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_apwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t ring_position,
|
||||
/**< Position des Slaves im Bus */
|
||||
/**< auto-increment position */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
@@ -191,17 +192,17 @@ int ec_command_apwr(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-BRD-Kommando.
|
||||
|
||||
Initializes an EtherCAT BRD command.
|
||||
Broadcast read.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_brd(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden Daten */
|
||||
/**< number of bytes to read */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
@@ -214,17 +215,17 @@ int ec_command_brd(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-BWR-Kommando.
|
||||
|
||||
Initializes an EtherCAT BWR command.
|
||||
Broadcast write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_bwr(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint16_t offset,
|
||||
/**< Physikalische Speicheradresse im Slave */
|
||||
/**< physical memory address */
|
||||
size_t data_size
|
||||
/**< Länge der zu schreibenden Daten */
|
||||
/**< number of bytes to write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
@@ -237,17 +238,17 @@ int ec_command_bwr(ec_command_t *command,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Initialisiert ein EtherCAT-LRW-Kommando.
|
||||
|
||||
Initializes an EtherCAT LRW command.
|
||||
Logical read write.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_command_lrw(ec_command_t *command,
|
||||
/**< EtherCAT-Rahmen */
|
||||
/**< EtherCAT command */
|
||||
uint32_t offset,
|
||||
/**< Logische Startadresse */
|
||||
/**< logical address */
|
||||
size_t data_size
|
||||
/**< Länge der zu lesenden/schreibenden Daten */
|
||||
/**< number of bytes to read/write */
|
||||
)
|
||||
{
|
||||
EC_FUNC_HEADER;
|
||||
@@ -257,9 +258,3 @@ int ec_command_lrw(ec_command_t *command,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* c o m m a n d . h
|
||||
*
|
||||
* Struktur für ein EtherCAT-Kommando.
|
||||
* EtherCAT command structure.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -18,7 +18,7 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Typ.
|
||||
EtherCAT command type.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
@@ -35,65 +35,57 @@ typedef enum
|
||||
ec_command_type_t;
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando-Zustand.
|
||||
EtherCAT command state.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_CMD_INIT, /**< Neues Kommando */
|
||||
EC_CMD_QUEUED, /**< Kommando in Warteschlange */
|
||||
EC_CMD_SENT, /**< Kommando gesendet */
|
||||
EC_CMD_RECEIVED, /**< Kommando empfangen */
|
||||
EC_CMD_TIMEOUT, /**< Zeitgrenze überschritten */
|
||||
EC_CMD_ERROR /**< Fehler beim Senden oder Empfangen */
|
||||
EC_CMD_INIT, /**< new command */
|
||||
EC_CMD_QUEUED, /**< command queued by master */
|
||||
EC_CMD_SENT, /**< command has been sent */
|
||||
EC_CMD_RECEIVED, /**< command has been received */
|
||||
EC_CMD_TIMEOUT, /**< command timed out */
|
||||
EC_CMD_ERROR /**< error while sending/receiving */
|
||||
}
|
||||
ec_command_state_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Adresse.
|
||||
|
||||
Im EtherCAT-Kommando sind 4 Bytes für die Adresse reserviert, die je nach
|
||||
Kommandotyp, eine andere Bedeutung haben können: Bei Autoinkrementbefehlen
|
||||
sind die ersten zwei Bytes die (negative) Autoinkrement-Adresse, bei Knoten-
|
||||
adressierten Befehlen entsprechen sie der Knotenadresse. Das dritte und
|
||||
vierte Byte entspricht in diesen Fällen der physikalischen Speicheradresse
|
||||
auf dem Slave. Bei einer logischen Adressierung entsprechen alle vier Bytes
|
||||
der logischen Adresse.
|
||||
EtherCAT address.
|
||||
*/
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint16_t slave; /**< Adresse des Slaves (Ringposition oder Knoten) */
|
||||
uint16_t mem; /**< Physikalische Speicheradresse im Slave */
|
||||
uint16_t slave; /**< configured or autoincrement address */
|
||||
uint16_t mem; /**< physical memory address */
|
||||
}
|
||||
physical; /**< Physikalische Adresse */
|
||||
physical; /**< physical address */
|
||||
|
||||
uint32_t logical; /**< Logische Adresse */
|
||||
uint32_t logical; /**< logical address */
|
||||
}
|
||||
ec_address_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Kommando.
|
||||
EtherCAT command
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
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; /**< 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 */
|
||||
ec_command_state_t state; /**< Zustand */
|
||||
struct list_head list; /**< needed by domain command lists */
|
||||
struct list_head queue; /**< master command queue item */
|
||||
ec_command_type_t type; /**< command type (APRD, BWR, etc) */
|
||||
ec_address_t address; /**< receipient address */
|
||||
uint8_t *data; /**< command data */
|
||||
size_t mem_size; /**< command \a data memory size */
|
||||
size_t data_size; /**< size of the data in \a data */
|
||||
uint8_t index; /**< command index (set by master) */
|
||||
uint16_t working_counter; /**< working counter */
|
||||
ec_command_state_t state; /**< command state */
|
||||
}
|
||||
ec_command_t;
|
||||
|
||||
@@ -113,9 +105,3 @@ int ec_command_lrw(ec_command_t *, uint32_t, size_t);
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
102
master/device.c
102
master/device.c
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* d e v i c e . c
|
||||
*
|
||||
* Methoden für ein EtherCAT-Gerät.
|
||||
* EtherCAT device methods.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -20,16 +20,15 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Geräte-Konstuktor.
|
||||
|
||||
\return 0 wenn alles ok, < 0 bei Fehler (zu wenig Speicher)
|
||||
Device constructor.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_device_init(ec_device_t *device, /**< EtherCAT-Gerät */
|
||||
ec_master_t *master, /**< Zugehöriger Master */
|
||||
struct net_device *net_dev, /**< Net-Device */
|
||||
ec_isr_t isr, /**< Adresse der ISR */
|
||||
struct module *module /**< Modul-Adresse */
|
||||
int ec_device_init(ec_device_t *device, /**< EtherCAT device */
|
||||
ec_master_t *master, /**< master owning the device */
|
||||
struct net_device *net_dev, /**< net_device structure */
|
||||
ec_isr_t isr, /**< pointer to device's ISR */
|
||||
struct module *module /**< pointer to the owning module */
|
||||
)
|
||||
{
|
||||
struct ethhdr *eth;
|
||||
@@ -49,7 +48,7 @@ int ec_device_init(ec_device_t *device, /**< EtherCAT-Ger
|
||||
|
||||
device->tx_skb->dev = net_dev;
|
||||
|
||||
// Ethernet-II-Header hinzufuegen
|
||||
// add Ethernet-II-header
|
||||
skb_reserve(device->tx_skb, ETH_HLEN);
|
||||
eth = (struct ethhdr *) skb_push(device->tx_skb, ETH_HLEN);
|
||||
eth->h_proto = htons(0x88A4);
|
||||
@@ -62,13 +61,10 @@ int ec_device_init(ec_device_t *device, /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Geräte-Destuktor.
|
||||
|
||||
Gibt den dynamisch allozierten Speicher des
|
||||
EtherCAT-Gerätes (den Sende-Socket-Buffer) wieder frei.
|
||||
EtherCAT device destuctor.
|
||||
*/
|
||||
|
||||
void ec_device_clear(ec_device_t *device /**< EtherCAT-Gerät */)
|
||||
void ec_device_clear(ec_device_t *device /**< EtherCAT device */)
|
||||
{
|
||||
if (device->open) ec_device_close(device);
|
||||
if (device->tx_skb) dev_kfree_skb(device->tx_skb);
|
||||
@@ -77,17 +73,11 @@ void ec_device_clear(ec_device_t *device /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Führt die open()-Funktion des Netzwerktreibers aus.
|
||||
|
||||
Dies entspricht einem "ifconfig up". Vorher wird der Zeiger
|
||||
auf das EtherCAT-Gerät auf Gültigkeit geprüft und der
|
||||
Gerätezustand zurückgesetzt.
|
||||
|
||||
\return 0 bei Erfolg, < 0: Ungültiger Zeiger, oder open()
|
||||
fehlgeschlagen
|
||||
Opens the EtherCAT device.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_device_open(ec_device_t *device /**< EtherCAT-Gerät */)
|
||||
int ec_device_open(ec_device_t *device /**< EtherCAT device */)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -101,7 +91,7 @@ int ec_device_open(ec_device_t *device /**< EtherCAT-Ger
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Device could have received frames before
|
||||
// device could have received frames before
|
||||
for (i = 0; i < 4; i++) ec_device_call_isr(device);
|
||||
|
||||
device->link_state = 0;
|
||||
@@ -114,13 +104,11 @@ int ec_device_open(ec_device_t *device /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Führt die stop()-Funktion des net_devices aus.
|
||||
|
||||
\return 0 bei Erfolg, < 0: Kein Gerät zum Schließen oder
|
||||
Schließen fehlgeschlagen.
|
||||
Stops the EtherCAT device.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_device_close(ec_device_t *device /**< EtherCAT-Gerät */)
|
||||
int ec_device_close(ec_device_t *device /**< EtherCAT device */)
|
||||
{
|
||||
if (!device->dev) {
|
||||
EC_ERR("No device to close!\n");
|
||||
@@ -140,12 +128,11 @@ int ec_device_close(ec_device_t *device /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liefert einen Zeiger auf den Sende-Speicher.
|
||||
|
||||
\return Zeiger auf den Speicher, in den die Frame-Daten sollen.
|
||||
Returns a pointer to the device's transmit memory.
|
||||
\return pointer to the TX socket buffer
|
||||
*/
|
||||
|
||||
uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT-Gerät */)
|
||||
uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT device */)
|
||||
{
|
||||
return device->tx_skb->data + ETH_HLEN;
|
||||
}
|
||||
@@ -153,21 +140,19 @@ uint8_t *ec_device_tx_data(ec_device_t *device /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet den Inhalt des Socket-Buffers.
|
||||
|
||||
Schneidet den Inhalt des Socket-Buffers auf die (nun bekannte) Größe zu,
|
||||
fügt den Ethernet-II-Header an und ruft die start_xmit()-Funktion der
|
||||
Netzwerkkarte auf.
|
||||
Sends the content of the transmit socket buffer.
|
||||
Cuts the socket buffer content to the (now known) size, and calls the
|
||||
start_xmit() function of the assigned net_device.
|
||||
*/
|
||||
|
||||
void ec_device_send(ec_device_t *device, /**< EtherCAT-Gerät */
|
||||
size_t size /**< Größe der zu sendenden Daten */
|
||||
void ec_device_send(ec_device_t *device, /**< EtherCAT device */
|
||||
size_t size /**< number of bytes to send */
|
||||
)
|
||||
{
|
||||
if (unlikely(!device->link_state)) // Link down
|
||||
return;
|
||||
|
||||
// Framegröße auf (jetzt bekannte) Länge abschneiden
|
||||
// set the right length for the data
|
||||
device->tx_skb->len = ETH_HLEN + size;
|
||||
|
||||
if (unlikely(device->master->debug_level > 1)) {
|
||||
@@ -175,36 +160,33 @@ void ec_device_send(ec_device_t *device, /**< EtherCAT-Ger
|
||||
ec_print_data(device->tx_skb->data + ETH_HLEN, size);
|
||||
}
|
||||
|
||||
// Senden einleiten
|
||||
// start sending
|
||||
device->dev->hard_start_xmit(device->tx_skb, device->dev);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Ruft die Interrupt-Routine der Netzwerkkarte auf.
|
||||
Calls the interrupt service routine of the assigned net_device.
|
||||
*/
|
||||
|
||||
void ec_device_call_isr(ec_device_t *device /**< EtherCAT-Gerät */)
|
||||
void ec_device_call_isr(ec_device_t *device /**< EtherCAT device */)
|
||||
{
|
||||
if (likely(device->isr)) device->isr(0, device->dev, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Treiberschnittstelle
|
||||
*
|
||||
* Device interface
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Nimmt einen Empfangenen Rahmen entgegen.
|
||||
|
||||
Kopiert die empfangenen Daten in den Receive-Buffer.
|
||||
Accepts a received frame.
|
||||
Forwards the received data to the master.
|
||||
*/
|
||||
|
||||
void ecdev_receive(ec_device_t *device, /**< EtherCAT-Gerät */
|
||||
const void *data, /**< Zeiger auf empfangene Daten */
|
||||
size_t size /**< Größe der empfangenen Daten */
|
||||
void ecdev_receive(ec_device_t *device, /**< EtherCAT device */
|
||||
const void *data, /**< pointer to receibed data */
|
||||
size_t size /**< number of bytes received */
|
||||
)
|
||||
{
|
||||
if (unlikely(device->master->debug_level > 1)) {
|
||||
@@ -218,11 +200,11 @@ void ecdev_receive(ec_device_t *device, /**< EtherCAT-Ger
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Setzt einen neuen Verbindungszustand.
|
||||
Sets a new link state.
|
||||
*/
|
||||
|
||||
void ecdev_link_state(ec_device_t *device, /**< EtherCAT-Gerät */
|
||||
uint8_t state /**< Verbindungszustand */
|
||||
void ecdev_link_state(ec_device_t *device, /**< EtherCAT device */
|
||||
uint8_t state /**< new link state */
|
||||
)
|
||||
{
|
||||
if (unlikely(!device)) {
|
||||
@@ -242,9 +224,3 @@ EXPORT_SYMBOL(ecdev_receive);
|
||||
EXPORT_SYMBOL(ecdev_link_state);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* d e v i c e . h
|
||||
*
|
||||
* Struktur für ein EtherCAT-Gerät.
|
||||
* EtherCAT device structure.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -20,23 +20,21 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Gerät.
|
||||
EtherCAT device.
|
||||
|
||||
Ein EtherCAT-Gerät ist eine Netzwerkkarte, die vom
|
||||
EtherCAT-Master dazu verwendet wird, um Frames zu senden
|
||||
und zu empfangen.
|
||||
An EtherCAT device is a network interface card, that is owned by an
|
||||
EtherCAT master to send and receive EtherCAT frames with.
|
||||
*/
|
||||
|
||||
struct ec_device
|
||||
{
|
||||
ec_master_t *master; /**< EtherCAT-Master */
|
||||
struct net_device *dev; /**< Zeiger auf das reservierte net_device */
|
||||
uint8_t open; /**< Das net_device ist geoeffnet. */
|
||||
struct sk_buff *tx_skb; /**< Zeiger auf Transmit-Socketbuffer */
|
||||
ec_isr_t isr; /**< Adresse der ISR */
|
||||
struct module *module; /**< Zeiger auf das Modul, das das Gerät zur
|
||||
Verfügung stellt. */
|
||||
uint8_t link_state; /**< Verbindungszustand */
|
||||
ec_master_t *master; /**< EtherCAT master */
|
||||
struct net_device *dev; /**< pointer to the assigned net_device */
|
||||
uint8_t open; /**< true, if the net_device has been opened */
|
||||
struct sk_buff *tx_skb; /**< transmit socket buffer */
|
||||
ec_isr_t isr; /**< pointer to the device's interrupt service routine */
|
||||
struct module *module; /**< pointer to the device's owning module */
|
||||
uint8_t link_state; /**< device link state */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -55,9 +53,3 @@ void ec_device_send(ec_device_t *, size_t);
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
163
master/domain.c
163
master/domain.c
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* d o m a i n . c
|
||||
*
|
||||
* Methoden für Gruppen von EtherCAT-Slaves.
|
||||
* EtherCAT domain methods.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -40,12 +40,13 @@ static struct kobj_type ktype_ec_domain = {
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Konstruktor einer EtherCAT-Domäne.
|
||||
Domain constructor.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_domain_init(ec_domain_t *domain, /**< Domäne */
|
||||
ec_master_t *master, /**< Zugehöriger Master */
|
||||
unsigned int index /**< Domänen-Index */
|
||||
int ec_domain_init(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
ec_master_t *master, /**< owning master */
|
||||
unsigned int index /**< domain index */
|
||||
)
|
||||
{
|
||||
domain->master = master;
|
||||
@@ -57,7 +58,7 @@ int ec_domain_init(ec_domain_t *domain, /**< Dom
|
||||
INIT_LIST_HEAD(&domain->field_regs);
|
||||
INIT_LIST_HEAD(&domain->commands);
|
||||
|
||||
// Init kobject and add it to the hierarchy
|
||||
// init kobject and add it to the hierarchy
|
||||
memset(&domain->kobj, 0x00, sizeof(struct kobject));
|
||||
kobject_init(&domain->kobj);
|
||||
domain->kobj.ktype = &ktype_ec_domain;
|
||||
@@ -73,10 +74,10 @@ int ec_domain_init(ec_domain_t *domain, /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Destruktor einer EtherCAT-Domäne.
|
||||
Domain destructor.
|
||||
*/
|
||||
|
||||
void ec_domain_clear(struct kobject *kobj /**< Kobject der Domäne */)
|
||||
void ec_domain_clear(struct kobject *kobj /**< kobject of the domain */)
|
||||
{
|
||||
ec_command_t *command, *next;
|
||||
ec_domain_t *domain;
|
||||
@@ -98,16 +99,16 @@ void ec_domain_clear(struct kobject *kobj /**< Kobject der Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Registriert ein Feld in einer Domäne.
|
||||
|
||||
\return 0 bei Erfolg, < 0 bei Fehler
|
||||
Registeres a data field in a domain.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_domain_reg_field(ec_domain_t *domain, /**< Domäne */
|
||||
ec_slave_t *slave, /**< Slave */
|
||||
const ec_sync_t *sync, /**< Sync-Manager */
|
||||
uint32_t field_offset, /**< Datenfeld-Offset */
|
||||
void **data_ptr /**< Adresse des Prozessdatenzeigers */
|
||||
int ec_domain_reg_field(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
ec_slave_t *slave, /**< slave */
|
||||
const ec_sync_t *sync, /**< sync manager */
|
||||
uint32_t field_offset, /**< data field offset */
|
||||
void **data_ptr /**< pointer to the process data
|
||||
pointer */
|
||||
)
|
||||
{
|
||||
ec_field_reg_t *field_reg;
|
||||
@@ -136,10 +137,10 @@ int ec_domain_reg_field(ec_domain_t *domain, /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt die Liste der registrierten Datenfelder frei.
|
||||
Clears the list of the registered data fields.
|
||||
*/
|
||||
|
||||
void ec_domain_clear_field_regs(ec_domain_t *domain)
|
||||
void ec_domain_clear_field_regs(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_field_reg_t *field_reg, *next;
|
||||
|
||||
@@ -152,12 +153,13 @@ void ec_domain_clear_field_regs(ec_domain_t *domain)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Alloziert ein Prozessdatenkommando und fügt es in die Liste ein.
|
||||
Allocates a process data command and appends it to the list.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
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 */
|
||||
int ec_domain_add_command(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
uint32_t offset, /**< logical offset */
|
||||
size_t data_size /**< size of the command data */
|
||||
)
|
||||
{
|
||||
ec_command_t *command;
|
||||
@@ -181,15 +183,14 @@ int ec_domain_add_command(ec_domain_t *domain, /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Erzeugt eine Domäne.
|
||||
|
||||
Reserviert den Speicher einer Domäne, berechnet die logischen Adressen der
|
||||
FMMUs und setzt die Prozessdatenzeiger der registrierten Felder.
|
||||
|
||||
\return 0 bei Erfolg, < 0 bei Fehler
|
||||
Creates a domain.
|
||||
Reserves domain memory, calculates the logical addresses of the
|
||||
corresponding FMMUs and sets the process data pointer of the registered
|
||||
data fields.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_domain_alloc(ec_domain_t *domain, /**< Domäne */
|
||||
int ec_domain_alloc(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
uint32_t base_address /**< Logische Basisadresse */
|
||||
)
|
||||
{
|
||||
@@ -276,30 +277,33 @@ int ec_domain_alloc(ec_domain_t *domain, /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt die Anzahl der antwortenden Slaves aus.
|
||||
Sets the number of responding slaves and outputs it on demand.
|
||||
This number isn't really the number of responding slaves, but the sum of
|
||||
the working counters of all domain commands. Some slaves increase the
|
||||
working counter by 2, some by 1.
|
||||
*/
|
||||
|
||||
void ec_domain_response_count(ec_domain_t *domain, /**< Domäne */
|
||||
unsigned int count /**< Neue Anzahl */
|
||||
void ec_domain_response_count(ec_domain_t *domain, /**< EtherCAT domain */
|
||||
unsigned int count /**< new WC sum */
|
||||
)
|
||||
{
|
||||
if (count != domain->response_count) {
|
||||
domain->response_count = count;
|
||||
EC_INFO("Domain %i working counter change: %i\n", domain->index, count);
|
||||
EC_INFO("Domain %i working counter change: %i\n", domain->index,
|
||||
count);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Formatiert Attribut-Daten für lesenden Zugriff im SysFS
|
||||
|
||||
\return Anzahl Bytes im Speicher
|
||||
Formats attribute data for SysFS reading.
|
||||
\return number of bytes to read
|
||||
*/
|
||||
|
||||
ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< KObject */
|
||||
struct attribute *attr, /**< Attribut */
|
||||
char *buffer /**< Speicher für die Daten */
|
||||
ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< kobject */
|
||||
struct attribute *attr, /**< attribute */
|
||||
char *buffer /**< memory to store data in */
|
||||
)
|
||||
{
|
||||
ec_domain_t *domain = container_of(kobj, ec_domain_t, kobj);
|
||||
@@ -312,43 +316,39 @@ ssize_t ec_show_domain_attribute(struct kobject *kobj, /**< KObject */
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Echtzeitschnittstelle
|
||||
*
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Registriert ein Datenfeld innerhalb einer Domäne.
|
||||
|
||||
- Ist \a data_ptr NULL, so wird der Slave nur auf den Typ überprüft.
|
||||
- Wenn \a field_count 0 ist, wird angenommen, dass 1 Feld registriert werden
|
||||
soll.
|
||||
- Wenn \a field_count größer als 1 ist, wird angenommen, dass \a data_ptr
|
||||
auf ein entsprechend großes Array zeigt.
|
||||
|
||||
\return Zeiger auf den Slave bei Erfolg, sonst NULL
|
||||
Registers a data field in a domain.
|
||||
- If \a data_ptr is NULL, the slave is only checked against its type.
|
||||
- If \a field_count is 0, it is assumed that one data field is to be
|
||||
registered.
|
||||
- If \a field_count is greater then 1, it is assumed that \a data_ptr
|
||||
is an array of the respective size.
|
||||
\return pointer to the slave on success, else NULL
|
||||
*/
|
||||
|
||||
ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
|
||||
/**< Domäne */
|
||||
/**< EtherCAT domain */
|
||||
const char *address,
|
||||
/**< ASCII-Addresse des Slaves,
|
||||
siehe ecrt_master_get_slave() */
|
||||
/**< ASCII address of the slave,
|
||||
see ecrt_master_get_slave() */
|
||||
const char *vendor_name,
|
||||
/**< Herstellername */
|
||||
/**< vendor name */
|
||||
const char *product_name,
|
||||
/**< Produktname */
|
||||
/**< product name */
|
||||
void **data_ptr,
|
||||
/**< Adresse des Zeigers auf die
|
||||
Prozessdaten */
|
||||
/**< address of the process data
|
||||
pointer */
|
||||
const char *field_name,
|
||||
/**< Name des Datenfeldes */
|
||||
/**< data field name */
|
||||
unsigned int field_index,
|
||||
/**< Gibt an, ab welchem Feld mit
|
||||
Typ \a field_type gezählt
|
||||
werden soll. */
|
||||
/**< offset of data fields with
|
||||
\a field_type */
|
||||
unsigned int field_count
|
||||
/**< Anzahl Felder selben Typs */
|
||||
/**< number of data fields (with
|
||||
the same type) to register */
|
||||
)
|
||||
{
|
||||
ec_slave_t *slave;
|
||||
@@ -361,7 +361,7 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
|
||||
|
||||
master = domain->master;
|
||||
|
||||
// Adresse übersetzen
|
||||
// translate address
|
||||
if (!(slave = ecrt_master_get_slave(master, address))) return NULL;
|
||||
|
||||
if (!(type = slave->type)) {
|
||||
@@ -379,7 +379,7 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
|
||||
}
|
||||
|
||||
if (!data_ptr) {
|
||||
// Wenn data_ptr NULL, Slave als registriert ansehen (nicht warnen).
|
||||
// data_ptr is NULL => mark slave as "registered" (do not warn)
|
||||
slave->registered = 1;
|
||||
}
|
||||
|
||||
@@ -415,17 +415,15 @@ ec_slave_t *ecrt_domain_register_field(ec_domain_t *domain,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Registriert eine ganze Liste von Datenfeldern innerhalb einer Domäne.
|
||||
|
||||
Achtung: Die Liste muss mit einer NULL-Struktur ({}) abgeschlossen sein!
|
||||
|
||||
\return 0 bei Erfolg, sonst < 0
|
||||
Registeres a bunch of data fields.
|
||||
Caution! The list has to be terminated with a NULL structure ({})!
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ecrt_domain_register_field_list(ec_domain_t *domain,
|
||||
/**< Domäne */
|
||||
/**< EtherCAT domain */
|
||||
const ec_field_init_t *fields
|
||||
/**< Array mit Datenfeldern */
|
||||
/**< array of data field registrations */
|
||||
)
|
||||
{
|
||||
const ec_field_init_t *field;
|
||||
@@ -444,10 +442,10 @@ int ecrt_domain_register_field_list(ec_domain_t *domain,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Setzt Prozessdaten-Kommandos in die Warteschlange des Masters.
|
||||
Places all process data commands in the masters command queue.
|
||||
*/
|
||||
|
||||
void ecrt_domain_queue(ec_domain_t *domain /**< Domäne */)
|
||||
void ecrt_domain_queue(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
|
||||
@@ -459,10 +457,10 @@ void ecrt_domain_queue(ec_domain_t *domain /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Verarbeitet empfangene Prozessdaten.
|
||||
Processes received process data.
|
||||
*/
|
||||
|
||||
void ecrt_domain_process(ec_domain_t *domain /**< Domäne */)
|
||||
void ecrt_domain_process(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
unsigned int working_counter_sum;
|
||||
ec_command_t *command;
|
||||
@@ -481,12 +479,11 @@ void ecrt_domain_process(ec_domain_t *domain /**< Dom
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt den Status einer Domäne zurück.
|
||||
|
||||
\return 0 wenn alle Kommandos empfangen wurden, sonst -1.
|
||||
Returns the state of a domain.
|
||||
\return 0 if all commands were received, else -1.
|
||||
*/
|
||||
|
||||
int ecrt_domain_state(ec_domain_t *domain /**< Domäne */)
|
||||
int ecrt_domain_state(ec_domain_t *domain /**< EtherCAT domain */)
|
||||
{
|
||||
ec_command_t *command;
|
||||
|
||||
@@ -506,9 +503,3 @@ EXPORT_SYMBOL(ecrt_domain_process);
|
||||
EXPORT_SYMBOL(ecrt_domain_state);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* d o m a i n . h
|
||||
*
|
||||
* Struktur für eine Gruppe von EtherCAT-Slaves.
|
||||
* EtherCAT domain structure.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -21,39 +21,38 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Datenfeld-Konfiguration.
|
||||
Data field registration type.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
ec_slave_t *slave;
|
||||
const ec_sync_t *sync;
|
||||
uint32_t field_offset;
|
||||
void **data_ptr;
|
||||
struct list_head list; /**< list item */
|
||||
ec_slave_t *slave; /**< slave */
|
||||
const ec_sync_t *sync; /**< sync manager */
|
||||
uint32_t field_offset; /**< data field offset */
|
||||
void **data_ptr; /**< pointer to process data pointer(s) */
|
||||
}
|
||||
ec_field_reg_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Domäne
|
||||
|
||||
Verwaltet die Prozessdaten und das hierfür nötige Kommando einer bestimmten
|
||||
Menge von Slaves.
|
||||
EtherCAT domain.
|
||||
Handles the process data and the therefore needed commands of a certain
|
||||
group of slaves.
|
||||
*/
|
||||
|
||||
struct ec_domain
|
||||
{
|
||||
struct kobject kobj; /**< Kobject der Domäne */
|
||||
struct list_head list; /**< Listenkopf */
|
||||
unsigned int index; /**< Domänen-Index */
|
||||
ec_master_t *master; /**< EtherCAT-Master, zu der die Domäne gehört. */
|
||||
size_t data_size; /**< Größe der Prozessdaten */
|
||||
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 */
|
||||
struct kobject kobj; /**< kobject */
|
||||
struct list_head list; /**< list item */
|
||||
unsigned int index; /**< domain index (just a number) */
|
||||
ec_master_t *master; /**< EtherCAT master owning the domain */
|
||||
size_t data_size; /**< size of the process data */
|
||||
struct list_head commands; /**< process data commands */
|
||||
uint32_t base_address; /**< logical offset address of the process data */
|
||||
unsigned int response_count; /**< number of responding slaves */
|
||||
struct list_head field_regs; /**< data field registrations */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@@ -65,9 +64,3 @@ int ec_domain_alloc(ec_domain_t *, uint32_t);
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -117,9 +117,3 @@ void ec_eoe_print(const ec_eoe_t *eoe)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -43,9 +43,3 @@ void ec_eoe_run(ec_eoe_t *);
|
||||
void ec_eoe_print(const ec_eoe_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* g l o b a l s . h
|
||||
*
|
||||
* Globale Definitionen und Makros für das EtherCAT-Protokoll.
|
||||
* Global definitions and macros.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -16,21 +16,20 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
// EtherCAT-Protokoll
|
||||
#define EC_MAX_FRAME_SIZE 1500 /**< Maximale Größe eines EtherCAT-Frames ohne
|
||||
Ethernet-II-Header und -Prüfsumme */
|
||||
#define EC_MIN_FRAME_SIZE 46 /** Minimale Größe, s. o. */
|
||||
#define EC_FRAME_HEADER_SIZE 2 /**< Größe des EtherCAT-Frame-Headers */
|
||||
#define EC_COMMAND_HEADER_SIZE 10 /**< Größe eines EtherCAT-Kommando-Headers */
|
||||
#define EC_COMMAND_FOOTER_SIZE 2 /**< Größe eines EtherCAT-Kommando-Footers */
|
||||
#define EC_SYNC_SIZE 8 /**< Größe einer Sync-Manager-Konfigurationsseite */
|
||||
#define EC_FMMU_SIZE 16 /**< Größe einer FMMU-Konfigurationsseite */
|
||||
#define EC_MAX_FMMUS 16 /**< Maximale Anzahl FMMUs pro Slave */
|
||||
#define EC_MAX_FRAME_SIZE 1500 /**< maximum size of an EtherCAT frame (without
|
||||
header and CRC) */
|
||||
#define EC_MIN_FRAME_SIZE 46 /** ... minimum size */
|
||||
#define EC_FRAME_HEADER_SIZE 2 /**< size of an EtherCAT frame header */
|
||||
#define EC_COMMAND_HEADER_SIZE 10 /**< size of an EtherCAT command header */
|
||||
#define EC_COMMAND_FOOTER_SIZE 2 /**< size of an EtherCAT command footer */
|
||||
#define EC_SYNC_SIZE 8 /**< size of a sync manager configuration page */
|
||||
#define EC_FMMU_SIZE 16 /**< size of an FMMU configuration page */
|
||||
#define EC_MAX_FMMUS 16 /**< maximum number of FMMUs per slave */
|
||||
#define EC_MAX_DATA_SIZE (EC_MAX_FRAME_SIZE \
|
||||
- EC_FRAME_HEADER_SIZE \
|
||||
- EC_COMMAND_HEADER_SIZE \
|
||||
- EC_COMMAND_FOOTER_SIZE) /**< Maximale Datengröße
|
||||
bei einem Kommando pro
|
||||
Frame */
|
||||
- EC_COMMAND_FOOTER_SIZE) /**< maximum data size of a
|
||||
single command */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@@ -59,16 +58,15 @@ extern void ec_print_data_diff(const uint8_t *, const uint8_t *, size_t);
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Code - Message Pair.
|
||||
|
||||
Code - Message pair.
|
||||
Some EtherCAT commands support reading a status code to display a certain
|
||||
message. This type allows to map a code to a message string.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t code; /**< Code */
|
||||
const char *message; /**< Message belonging to \a code */
|
||||
uint32_t code; /**< code */
|
||||
const char *message; /**< message belonging to \a code */
|
||||
}
|
||||
ec_code_msg_t;
|
||||
|
||||
@@ -76,8 +74,3 @@ ec_code_msg_t;
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* m a i l b o x . c
|
||||
*
|
||||
* Mailbox-Funktionen
|
||||
* Mailbox functionality.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -18,12 +18,13 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Mailbox-Send-Kommando vor.
|
||||
*/
|
||||
Prepares a mailbox-send command.
|
||||
\return pointer to mailbox command data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Mailbox-Protokoll */
|
||||
size_t size /**< Datengröße */
|
||||
uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< slave */
|
||||
uint8_t type, /**< mailbox protocol */
|
||||
size_t size /**< size of the data */
|
||||
)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
@@ -46,10 +47,10 @@ uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
|
||||
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_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); // hhannel & priority
|
||||
EC_WRITE_U8 (command->data + 5, type); // underlying protocol type
|
||||
|
||||
return command->data + 6;
|
||||
}
|
||||
@@ -57,14 +58,15 @@ uint8_t *ec_slave_mbox_prepare_send(ec_slave_t *slave, /**< Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Kommando zum Abfragen des Mailbox-Zustandes vor.
|
||||
*/
|
||||
Prepares a command for checking the mailbox state.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< Slave */)
|
||||
int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< slave */)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
|
||||
// FIXME: Zweiter Sync-Manager nicht immer TX-Mailbox?
|
||||
// FIXME: second sync manager?
|
||||
if (ec_command_nprd(command, slave->station_address, 0x808, 8))
|
||||
return -1;
|
||||
|
||||
@@ -74,10 +76,11 @@ int ec_slave_mbox_prepare_check(ec_slave_t *slave /**< Slave */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Liest den Mailbox-Zustand aus einem empfangenen Kommando.
|
||||
*/
|
||||
Processes a mailbox state checking command.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_check(const ec_slave_t *slave /**< Slave */)
|
||||
int ec_slave_mbox_check(const ec_slave_t *slave /**< slave */)
|
||||
{
|
||||
return EC_READ_U8(slave->mbox_command.data + 5) & 8 ? 1 : 0;
|
||||
}
|
||||
@@ -85,10 +88,11 @@ int ec_slave_mbox_check(const ec_slave_t *slave /**< Slave */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Bereitet ein Kommando zum Laden von Daten von der Mailbox vor.
|
||||
*/
|
||||
Prepares a command to fetch mailbox data.
|
||||
\return 0 in case of success, else < 0
|
||||
*/
|
||||
|
||||
int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< Slave */)
|
||||
int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< slave */)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
|
||||
@@ -101,12 +105,13 @@ int ec_slave_mbox_prepare_fetch(ec_slave_t *slave /**< Slave */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Verarbeitet empfangene Mailbox-Daten.
|
||||
*/
|
||||
Processes received mailbox data.
|
||||
\return pointer to the received data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der empfangenen Daten */
|
||||
uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< slave */
|
||||
uint8_t type, /**< expected mailbox protocol */
|
||||
size_t *size /**< size of the received data */
|
||||
)
|
||||
{
|
||||
ec_command_t *command = &slave->mbox_command;
|
||||
@@ -132,12 +137,12 @@ uint8_t *ec_slave_mbox_fetch(ec_slave_t *slave, /**< Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sendet und wartet auf den Empfang eines Mailbox-Kommandos.
|
||||
*/
|
||||
Sends a mailbox command and waits for its reception.
|
||||
\return pointer to the received data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< Slave */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< slave */
|
||||
size_t *size /**< size of the received data */
|
||||
)
|
||||
{
|
||||
uint8_t type;
|
||||
@@ -158,13 +163,13 @@ uint8_t *ec_slave_mbox_simple_io(ec_slave_t *slave, /**< Slave */
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Wartet auf den Empfang eines Mailbox-Kommandos.
|
||||
*/
|
||||
Waits for the reception of a mailbox command.
|
||||
\return pointer to the received data
|
||||
*/
|
||||
|
||||
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< Slave */
|
||||
uint8_t type, /**< Protokoll */
|
||||
size_t *size /**< Größe der gelesenen
|
||||
Daten */
|
||||
uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< slave */
|
||||
uint8_t type, /**< expected protocol */
|
||||
size_t *size /**< received data size */
|
||||
)
|
||||
{
|
||||
cycles_t start, end, timeout;
|
||||
@@ -186,7 +191,7 @@ uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *slave, /**< Slave */
|
||||
end = get_cycles();
|
||||
|
||||
if (ec_slave_mbox_check(slave))
|
||||
break; // Proceed with receiving data
|
||||
break; // proceed with receiving data
|
||||
|
||||
if ((end - start) >= timeout) {
|
||||
EC_ERR("Mailbox check - Slave %i timed out.\n",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* m a i l b o x . h
|
||||
*
|
||||
* Mailbox-Funktionen.
|
||||
* Mailbox functionality.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -27,9 +27,3 @@ uint8_t *ec_slave_mbox_simple_receive(ec_slave_t *, uint8_t, size_t *);
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
439
master/master.c
439
master/master.c
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* m a s t e r . h
|
||||
*
|
||||
* Struktur für einen EtherCAT-Master.
|
||||
* EtherCAT master structure.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -35,61 +35,59 @@ ec_master_mode_t;
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Rahmen-Statistiken.
|
||||
Cyclic EtherCAT statistics.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int timeouts; /**< Kommando-Timeouts */
|
||||
unsigned int delayed; /**< Verzögerte Kommandos */
|
||||
unsigned int corrupted; /**< Verfälschte Rahmen */
|
||||
unsigned int unmatched; /**< Unpassende Kommandos */
|
||||
unsigned int eoe_errors; /**< Ethernet-over-EtherCAT Fehler */
|
||||
cycles_t t_last; /**< Timestamp-Counter bei der letzten Ausgabe */
|
||||
unsigned int timeouts; /**< command timeouts */
|
||||
unsigned int delayed; /**< delayed commands */
|
||||
unsigned int corrupted; /**< corrupted frames */
|
||||
unsigned int unmatched; /**< unmatched commands */
|
||||
unsigned int eoe_errors; /**< Ethernet-over-EtherCAT errors */
|
||||
cycles_t t_last; /**< time of last output */
|
||||
}
|
||||
ec_stats_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
EtherCAT-Master
|
||||
|
||||
Verwaltet die EtherCAT-Slaves und kommuniziert mit
|
||||
dem zugewiesenen EtherCAT-Gerät.
|
||||
EtherCAT-Master.
|
||||
Manages slaves, domains and IO.
|
||||
*/
|
||||
|
||||
struct ec_master
|
||||
{
|
||||
struct list_head list; /**< Noetig fuer Master-Liste */
|
||||
struct kobject kobj; /**< Kernel-Object */
|
||||
unsigned int index; /**< Master-Index */
|
||||
struct list_head slaves; /**< Liste der Slaves auf dem Bus */
|
||||
unsigned int slave_count; /**< Anzahl Slaves auf dem Bus */
|
||||
ec_device_t *device; /**< EtherCAT-Gerät */
|
||||
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 */
|
||||
int debug_level; /**< Debug-Level im Master-Code */
|
||||
ec_stats_t stats; /**< Rahmen-Statistiken */
|
||||
unsigned int timeout; /**< Timeout für synchronen Datenaustausch */
|
||||
struct list_head eoe_slaves; /**< Ethernet over EtherCAT Slaves */
|
||||
unsigned int reserved; /**< Master durch Echtzeitprozess reserviert */
|
||||
struct timer_list freerun_timer; /**< Timer fuer Free-Run-Modus. */
|
||||
ec_master_mode_t mode; /**< Modus des Masters */
|
||||
struct list_head list; /**< list item */
|
||||
struct kobject kobj; /**< kobject */
|
||||
unsigned int index; /**< master index */
|
||||
struct list_head slaves; /**< list of slaves on the bus */
|
||||
unsigned int slave_count; /**< number of slaves on the bus */
|
||||
ec_device_t *device; /**< EtherCAT device */
|
||||
struct list_head command_queue; /**< command queue */
|
||||
uint8_t command_index; /**< current command index */
|
||||
struct list_head domains; /**< list of domains */
|
||||
ec_command_t simple_command; /**< command structure for initialization */
|
||||
ec_command_t watch_command; /**< command for watching the slaves */
|
||||
unsigned int slaves_responding; /**< number of responding slaves */
|
||||
ec_slave_state_t slave_states; /**< states of the responding slaves */
|
||||
int debug_level; /**< master debug level */
|
||||
ec_stats_t stats; /**< cyclic statistics */
|
||||
unsigned int timeout; /**< timeout in synchronous IO */
|
||||
struct list_head eoe_slaves; /**< Ethernet-over-EtherCAT slaves */
|
||||
unsigned int reserved; /**< true, if the master is reserved for RT */
|
||||
struct timer_list freerun_timer; /**< timer object for free run mode */
|
||||
ec_master_mode_t mode; /**< master mode */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Master creation and deletion
|
||||
// master creation and deletion
|
||||
int ec_master_init(ec_master_t *, unsigned int);
|
||||
void ec_master_clear(struct kobject *);
|
||||
void ec_master_reset(ec_master_t *);
|
||||
|
||||
// Free-Run
|
||||
// free run
|
||||
void ec_master_freerun_start(ec_master_t *);
|
||||
void ec_master_freerun_stop(ec_master_t *);
|
||||
|
||||
@@ -98,10 +96,10 @@ 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 *);
|
||||
|
||||
// Slave management
|
||||
// slave management
|
||||
int ec_master_bus_scan(ec_master_t *);
|
||||
|
||||
// Misc
|
||||
// misc.
|
||||
void ec_master_debug(const ec_master_t *);
|
||||
void ec_master_output_stats(ec_master_t *);
|
||||
void ec_master_run_eoe(ec_master_t *);
|
||||
@@ -109,9 +107,3 @@ void ec_master_run_eoe(ec_master_t *);
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
103
master/module.c
103
master/module.c
@@ -2,9 +2,9 @@
|
||||
*
|
||||
* m o d u l e . c
|
||||
*
|
||||
* EtherCAT-Master-Treiber
|
||||
* EtherCAT master driver module.
|
||||
*
|
||||
* Autoren: Wilhelm Hagemeister, Florian Pose
|
||||
* Author: Florian Pose <fp@igh-essen.com>
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -50,18 +50,14 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(COMPILE_INFO);
|
||||
|
||||
module_param(ec_master_count, int, 1);
|
||||
MODULE_PARM_DESC(ec_master_count, "Number of EtherCAT master to initialize.");
|
||||
MODULE_PARM_DESC(ec_master_count, "number of EtherCAT masters to initialize");
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Init-Funktion des EtherCAT-Master-Treibermodules
|
||||
|
||||
Initialisiert soviele Master, wie im Parameter ec_master_count
|
||||
angegeben wurde (Default ist 1).
|
||||
|
||||
\return 0 wenn alles ok, < 0 bei ungültiger Anzahl Master
|
||||
oder zu wenig Speicher.
|
||||
Module initialization.
|
||||
Initializes \a ec_master_count masters.
|
||||
\return 0 on success, else < 0
|
||||
*/
|
||||
|
||||
int __init ec_init_module(void)
|
||||
@@ -115,9 +111,8 @@ int __init ec_init_module(void)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Cleanup-Funktion des EtherCAT-Master-Treibermoduls
|
||||
|
||||
Entfernt alle Master-Instanzen.
|
||||
Module cleanup.
|
||||
Clears all master instances.
|
||||
*/
|
||||
|
||||
void __exit ec_cleanup_module(void)
|
||||
@@ -142,7 +137,7 @@ void __exit ec_cleanup_module(void)
|
||||
\returns pointer to master
|
||||
*/
|
||||
|
||||
ec_master_t *ec_find_master(unsigned int master_index)
|
||||
ec_master_t *ec_find_master(unsigned int master_index /**< master index */)
|
||||
{
|
||||
ec_master_t *master;
|
||||
|
||||
@@ -155,26 +150,19 @@ ec_master_t *ec_find_master(unsigned int master_index)
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Treiberschnittstelle
|
||||
*
|
||||
* Device interface
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Registeriert das EtherCAT-Geraet fuer einen EtherCAT-Master.
|
||||
|
||||
\return 0 wenn alles ok, oder < 0 wenn bereits ein Gerät registriert
|
||||
oder das Geraet nicht geöffnet werden konnte.
|
||||
Registeres an EtherCAT device for a certain master.
|
||||
\return 0 on success, else < 0
|
||||
*/
|
||||
|
||||
ec_device_t *ecdev_register(unsigned int master_index,
|
||||
/**< Index des EtherCAT-Masters */
|
||||
struct net_device *net_dev,
|
||||
/**< net_device des EtherCAT-Gerätes */
|
||||
ec_isr_t isr,
|
||||
/**< Interrupt-Service-Routine */
|
||||
struct module *module
|
||||
/**< Zeiger auf das Modul */
|
||||
ec_device_t *ecdev_register(unsigned int master_index, /**< master index */
|
||||
struct net_device *net_dev, /**< net_device of
|
||||
the device */
|
||||
ec_isr_t isr, /**< interrupt service routine */
|
||||
struct module *module /**< pointer to the module */
|
||||
)
|
||||
{
|
||||
ec_master_t *master;
|
||||
@@ -218,13 +206,11 @@ ec_device_t *ecdev_register(unsigned int master_index,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Hebt die Registrierung eines EtherCAT-Gerätes auf.
|
||||
Unregisteres an EtherCAT device.
|
||||
*/
|
||||
|
||||
void ecdev_unregister(unsigned int master_index,
|
||||
/**< Index des EtherCAT-Masters */
|
||||
ec_device_t *device
|
||||
/**< EtherCAT-Geraet */
|
||||
void ecdev_unregister(unsigned int master_index, /**< master index */
|
||||
ec_device_t *device /**< EtherCAT device */
|
||||
)
|
||||
{
|
||||
ec_master_t *master;
|
||||
@@ -244,12 +230,10 @@ void ecdev_unregister(unsigned int master_index,
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Starts the master.
|
||||
Starts the master associated with the device.
|
||||
*/
|
||||
|
||||
int ecdev_start(unsigned int master_index
|
||||
/**< Index des EtherCAT-Masters */
|
||||
)
|
||||
int ecdev_start(unsigned int master_index /**< master index */)
|
||||
{
|
||||
ec_master_t *master;
|
||||
if (!(master = ec_find_master(master_index))) return -1;
|
||||
@@ -266,12 +250,10 @@ int ecdev_start(unsigned int master_index
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Stops the master.
|
||||
Stops the master associated with the device.
|
||||
*/
|
||||
|
||||
void ecdev_stop(unsigned int master_index
|
||||
/**< Index des EtherCAT-Masters */
|
||||
)
|
||||
void ecdev_stop(unsigned int master_index /**< master index */)
|
||||
{
|
||||
ec_master_t *master;
|
||||
if (!(master = ec_find_master(master_index))) return;
|
||||
@@ -283,21 +265,16 @@ void ecdev_stop(unsigned int master_index
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* Echtzeitschnittstelle
|
||||
*
|
||||
* Realtime interface
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
Reserviert einen bestimmten EtherCAT-Master und das zugehörige Gerät.
|
||||
|
||||
Gibt einen Zeiger auf den reservierten EtherCAT-Master zurueck.
|
||||
|
||||
\return Zeiger auf EtherCAT-Master oder NULL, wenn Parameter ungueltig.
|
||||
Reserves an EtherCAT master for realtime operation.
|
||||
\return pointer to reserved master, or NULL on error
|
||||
*/
|
||||
|
||||
ec_master_t *ecrt_request_master(unsigned int master_index
|
||||
/**< EtherCAT-Master-Index */
|
||||
/**< master index */
|
||||
)
|
||||
{
|
||||
ec_master_t *master;
|
||||
@@ -351,10 +328,10 @@ ec_master_t *ecrt_request_master(unsigned int master_index
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt einen zuvor angeforderten EtherCAT-Master wieder frei.
|
||||
Releases a reserved EtherCAT master.
|
||||
*/
|
||||
|
||||
void ecrt_release_master(ec_master_t *master /**< EtherCAT-Master */)
|
||||
void ecrt_release_master(ec_master_t *master /**< EtherCAT master */)
|
||||
{
|
||||
EC_INFO("Releasing master %i...\n", master->index);
|
||||
|
||||
@@ -378,10 +355,12 @@ void ecrt_release_master(ec_master_t *master /**< EtherCAT-Master */)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt Frame-Inhalte zwecks Debugging aus.
|
||||
Outputs frame contents for debugging purposes.
|
||||
*/
|
||||
|
||||
void ec_print_data(const uint8_t *data, size_t size)
|
||||
void ec_print_data(const uint8_t *data, /**< pointer to data */
|
||||
size_t size /**< number of bytes to output */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -399,12 +378,12 @@ void ec_print_data(const uint8_t *data, size_t size)
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Gibt Frame-Inhalte zwecks Debugging aus, differentiell.
|
||||
Outputs frame contents and differences for debugging purposes.
|
||||
*/
|
||||
|
||||
void ec_print_data_diff(const uint8_t *d1, /**< Daten 1 */
|
||||
const uint8_t *d2, /**< Daten 2 */
|
||||
size_t size /** Anzahl Bytes */
|
||||
void ec_print_data_diff(const uint8_t *d1, /**< first data */
|
||||
const uint8_t *d2, /**< second data */
|
||||
size_t size /** number of bytes to output */
|
||||
)
|
||||
{
|
||||
unsigned int i;
|
||||
@@ -434,9 +413,3 @@ EXPORT_SYMBOL(ecrt_request_master);
|
||||
EXPORT_SYMBOL(ecrt_release_master);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
272
master/slave.c
272
master/slave.c
File diff suppressed because it is too large
Load Diff
203
master/slave.h
203
master/slave.h
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* s l a v e . h
|
||||
*
|
||||
* Struktur für einen EtherCAT-Slave.
|
||||
* EtherCAT stave structure.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -21,30 +21,30 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Zustand eines EtherCAT-Slaves.
|
||||
State of an EtherCAT slave.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_SLAVE_STATE_UNKNOWN = 0x00,
|
||||
/**< Status unbekannt */
|
||||
/**< unknown state */
|
||||
EC_SLAVE_STATE_INIT = 0x01,
|
||||
/**< Init-Zustand (Keine Mailbox-Kommunikation, Kein I/O) */
|
||||
/**< INIT state (no mailbox communication, no IO) */
|
||||
EC_SLAVE_STATE_PREOP = 0x02,
|
||||
/**< Pre-Operational (Mailbox-Kommunikation, Kein I/O) */
|
||||
/**< PREOP state (mailbox communication, no IO) */
|
||||
EC_SLAVE_STATE_SAVEOP = 0x04,
|
||||
/**< Save-Operational (Mailbox-Kommunikation und Input Update) */
|
||||
/**< SAVEOP (mailbox communication and input update) */
|
||||
EC_SLAVE_STATE_OP = 0x08,
|
||||
/**< Operational, (Mailbox-Kommunikation und Input/Output Update) */
|
||||
/**< OP (mailbox communication and input/output update) */
|
||||
EC_ACK = 0x10
|
||||
/**< Acknoledge-Bit beim Zustandswechsel (kein eigener Zustand) */
|
||||
/**< Acknoledge bit (no state) */
|
||||
}
|
||||
ec_slave_state_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Unterstützte Mailbox-Protokolle.
|
||||
Supported mailbox protocols.
|
||||
*/
|
||||
|
||||
enum
|
||||
@@ -60,124 +60,124 @@ enum
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
FMMU-Konfiguration.
|
||||
FMMU configuration.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const ec_domain_t *domain;
|
||||
const ec_sync_t *sync;
|
||||
uint32_t logical_start_address;
|
||||
const ec_domain_t *domain; /**< domain */
|
||||
const ec_sync_t *sync; /**< sync manager */
|
||||
uint32_t logical_start_address; /**< logical start address */
|
||||
}
|
||||
ec_fmmu_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
String im EEPROM eines EtherCAT-Slaves.
|
||||
String object (EEPROM).
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
size_t size;
|
||||
char *data;
|
||||
struct list_head list; /**< list item */
|
||||
size_t size; /**< size in bytes */
|
||||
char *data; /**< string data */
|
||||
}
|
||||
ec_eeprom_string_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Sync-Manager-Konfiguration laut EEPROM.
|
||||
Sync manager configuration (EEPROM).
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
unsigned int index;
|
||||
uint16_t physical_start_address;
|
||||
uint16_t length;
|
||||
uint8_t control_register;
|
||||
uint8_t enable;
|
||||
struct list_head list; /**< list item */
|
||||
unsigned int index; /**< sync manager index */
|
||||
uint16_t physical_start_address; /**< physical start address */
|
||||
uint16_t length; /**< data length in bytes */
|
||||
uint8_t control_register; /**< control register value */
|
||||
uint8_t enable; /**< enable bit */
|
||||
}
|
||||
ec_eeprom_sync_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
PDO-Typ.
|
||||
PDO type.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_RX_PDO,
|
||||
EC_TX_PDO
|
||||
EC_RX_PDO, /**< Reveive PDO */
|
||||
EC_TX_PDO /**< Transmit PDO */
|
||||
}
|
||||
ec_pdo_type_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
PDO-Beschreibung im EEPROM.
|
||||
PDO description (EEPROM).
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
ec_pdo_type_t type;
|
||||
uint16_t index;
|
||||
uint8_t sync_manager;
|
||||
char *name;
|
||||
struct list_head entries;
|
||||
struct list_head list; /**< list item */
|
||||
ec_pdo_type_t type; /**< PDO type */
|
||||
uint16_t index; /**< PDO index */
|
||||
uint8_t sync_manager; /**< assigned sync manager */
|
||||
char *name; /**< PDO name */
|
||||
struct list_head entries; /**< entry list */
|
||||
}
|
||||
ec_eeprom_pdo_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
PDO-Entry-Beschreibung im EEPROM.
|
||||
PDO entry description (EEPROM).
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
uint16_t index;
|
||||
uint8_t subindex;
|
||||
char *name;
|
||||
uint8_t bit_length;
|
||||
struct list_head list; /**< list item */
|
||||
uint16_t index; /**< PDO index */
|
||||
uint8_t subindex; /**< entry subindex */
|
||||
char *name; /**< entry name */
|
||||
uint8_t bit_length; /**< entry length in bit */
|
||||
}
|
||||
ec_eeprom_pdo_entry_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
CANopen-SDO.
|
||||
CANopen SDO.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
uint16_t index;
|
||||
struct list_head list; /**< list item */
|
||||
uint16_t index; /**< SDO index */
|
||||
//uint16_t type;
|
||||
uint8_t object_code;
|
||||
char *name;
|
||||
struct list_head entries;
|
||||
uint8_t object_code; /**< object code */
|
||||
char *name; /**< SDO name */
|
||||
struct list_head entries; /**< entry list */
|
||||
}
|
||||
ec_sdo_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
CANopen-SDO-Entry.
|
||||
CANopen SDO entry.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct list_head list;
|
||||
uint8_t subindex;
|
||||
uint16_t data_type;
|
||||
uint16_t bit_length;
|
||||
char *name;
|
||||
struct list_head list; /**< list item */
|
||||
uint8_t subindex; /**< entry subindex */
|
||||
uint16_t data_type; /**< entry data type */
|
||||
uint16_t bit_length; /**< entry length in bit */
|
||||
char *name; /**< entry name */
|
||||
}
|
||||
ec_sdo_entry_t;
|
||||
|
||||
@@ -189,69 +189,68 @@ ec_sdo_entry_t;
|
||||
|
||||
struct ec_slave
|
||||
{
|
||||
struct list_head list; /**< Noetig fuer Slave-Liste im Master */
|
||||
struct kobject kobj; /**< Kernel-Object */
|
||||
ec_master_t *master; /**< EtherCAT-Master, zu dem der Slave gehört. */
|
||||
struct list_head list; /**< list item */
|
||||
struct kobject kobj; /**< kobject */
|
||||
ec_master_t *master; /**< master owning the slave */
|
||||
|
||||
// Addresses
|
||||
uint16_t ring_position; /**< Position des Slaves im Bus */
|
||||
uint16_t station_address; /**< Konfigurierte Slave-Adresse */
|
||||
uint16_t coupler_index; /**< Letzter Buskoppler */
|
||||
uint16_t coupler_subindex; /**< Index hinter letztem Buskoppler */
|
||||
// addresses
|
||||
uint16_t ring_position; /**< ring position */
|
||||
uint16_t station_address; /**< configured station address */
|
||||
uint16_t coupler_index; /**< index of the last bus coupler */
|
||||
uint16_t coupler_subindex; /**< index of this slave after last coupler */
|
||||
|
||||
// Base data
|
||||
uint8_t base_type; /**< Slave-Typ */
|
||||
uint8_t base_revision; /**< Revision */
|
||||
uint16_t base_build; /**< Build-Nummer */
|
||||
uint16_t base_fmmu_count; /**< Anzahl unterstützter FMMUs */
|
||||
uint16_t base_sync_count; /**< Anzahl unterstützter Sync-Manager */
|
||||
// base data
|
||||
uint8_t base_type; /**< slave type */
|
||||
uint8_t base_revision; /**< revision */
|
||||
uint16_t base_build; /**< build number */
|
||||
uint16_t base_fmmu_count; /**< number of supported FMMUs */
|
||||
uint16_t base_sync_count; /**< number of supported sync managers */
|
||||
|
||||
// Data link status
|
||||
uint8_t dl_link[4]; /**< Verbindung erkannt */
|
||||
uint8_t dl_loop[4]; /**< Loop geschlossen */
|
||||
uint8_t dl_signal[4]; /**< Signal an RX-Seite erkannt */
|
||||
// data link status
|
||||
uint8_t dl_link[4]; /**< link detected */
|
||||
uint8_t dl_loop[4]; /**< loop closed */
|
||||
uint8_t dl_signal[4]; /**< detected signal on RX port */
|
||||
|
||||
// Slave information interface
|
||||
uint16_t sii_alias; /**< Configured station alias */
|
||||
uint32_t sii_vendor_id; /**< Identifikationsnummer des Herstellers */
|
||||
uint32_t sii_product_code; /**< Herstellerspezifischer Produktcode */
|
||||
uint32_t sii_revision_number; /**< Revisionsnummer */
|
||||
uint32_t sii_serial_number; /**< Seriennummer der Klemme */
|
||||
uint16_t sii_rx_mailbox_offset; /**< Adresse der Mailbox (Master->Slave) */
|
||||
uint16_t sii_rx_mailbox_size; /**< Adresse der Mailbox (Master->Slave) */
|
||||
uint16_t sii_tx_mailbox_offset; /**< Adresse der Mailbox (Slave->Master) */
|
||||
uint16_t sii_tx_mailbox_size; /**< Adresse der Mailbox (Slave->Master) */
|
||||
uint16_t sii_mailbox_protocols; /**< Unterstützte Mailbox-Protokolle */
|
||||
uint8_t sii_physical_layer[4]; /**< Uebertragungsarten der Ports */
|
||||
// slave information interface
|
||||
uint16_t sii_alias; /**< configured station alias */
|
||||
uint32_t sii_vendor_id; /**< vendor id */
|
||||
uint32_t sii_product_code; /**< vendor's product code */
|
||||
uint32_t sii_revision_number; /**< revision number */
|
||||
uint32_t sii_serial_number; /**< serial number */
|
||||
uint16_t sii_rx_mailbox_offset; /**< mailbox address (master to slave) */
|
||||
uint16_t sii_rx_mailbox_size; /**< mailbox size (master to slave) */
|
||||
uint16_t sii_tx_mailbox_offset; /**< mailbox address (slave to master) */
|
||||
uint16_t sii_tx_mailbox_size; /**< mailbox size (slave to master) */
|
||||
uint16_t sii_mailbox_protocols; /**< supported mailbox protocols */
|
||||
uint8_t sii_physical_layer[4]; /**< port media */
|
||||
|
||||
const ec_slave_type_t *type; /**< Zeiger auf die Beschreibung
|
||||
des Slave-Typs */
|
||||
const ec_slave_type_t *type; /**< pointer to slave type object */
|
||||
|
||||
uint8_t registered; /**< Der Slave wurde registriert */
|
||||
uint8_t registered; /**< true, if slave has been registered */
|
||||
|
||||
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU-Konfigurationen */
|
||||
uint8_t fmmu_count; /**< Wieviele FMMUs schon benutzt sind. */
|
||||
ec_fmmu_t fmmus[EC_MAX_FMMUS]; /**< FMMU configurations */
|
||||
uint8_t fmmu_count; /**< number of FMMUs used */
|
||||
|
||||
struct list_head eeprom_strings; /**< Strings im EEPROM */
|
||||
struct list_head eeprom_syncs; /**< Syncmanager-Konfigurationen (EEPROM) */
|
||||
struct list_head eeprom_pdos; /**< PDO-Beschreibungen im EEPROM */
|
||||
struct list_head eeprom_strings; /**< EEPROM STRING categories */
|
||||
struct list_head eeprom_syncs; /**< EEPROM SYNC MANAGER categories */
|
||||
struct list_head eeprom_pdos; /**< EEPROM [RT]XPDO categories */
|
||||
|
||||
char *eeprom_name; /**< Slave-Name laut Hersteller */
|
||||
char *eeprom_group; /**< Slave-Beschreibung laut Hersteller */
|
||||
char *eeprom_desc; /**< Slave-Beschreibung laut Hersteller */
|
||||
char *eeprom_name; /**< slave name acc. to EEPROM */
|
||||
char *eeprom_group; /**< slave group acc. to EEPROM */
|
||||
char *eeprom_desc; /**< slave description acc. to EEPROM */
|
||||
|
||||
struct list_head sdo_dictionary; /**< SDO-Verzeichnis des Slaves */
|
||||
struct list_head sdo_dictionary; /**< SDO directory list */
|
||||
|
||||
ec_command_t mbox_command; /**< Kommando für Mailbox-Kommunikation */
|
||||
ec_command_t mbox_command; /**< mailbox command */
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// Slave construction/destruction
|
||||
// slave construction/destruction
|
||||
int ec_slave_init(ec_slave_t *, ec_master_t *, uint16_t, uint16_t);
|
||||
void ec_slave_clear(struct kobject *);
|
||||
|
||||
// Slave control
|
||||
// slave control
|
||||
int ec_slave_fetch(ec_slave_t *);
|
||||
int ec_slave_sii_read16(ec_slave_t *, uint16_t, uint16_t *);
|
||||
int ec_slave_sii_read32(ec_slave_t *, uint16_t, uint32_t *);
|
||||
@@ -260,19 +259,13 @@ int ec_slave_state_change(ec_slave_t *, uint8_t);
|
||||
int ec_slave_prepare_fmmu(ec_slave_t *, const ec_domain_t *,
|
||||
const ec_sync_t *);
|
||||
|
||||
// CANopen over EtherCAT
|
||||
// CoE
|
||||
int ec_slave_fetch_sdo_list(ec_slave_t *);
|
||||
|
||||
// Misc
|
||||
// misc.
|
||||
void ec_slave_print(const ec_slave_t *, unsigned int);
|
||||
int ec_slave_check_crc(ec_slave_t *);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* t y p e s . c
|
||||
*
|
||||
* EtherCAT-Slave-Typen.
|
||||
* EtherCAT slave descriptions.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -18,36 +18,34 @@
|
||||
const ec_sync_t mailbox_sm0 = {0x1800, 246, 0x26, {NULL}};
|
||||
const ec_sync_t mailbox_sm1 = {0x18F6, 246, 0x22, {NULL}};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Klemmen-Objekte */
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************************************************************
|
||||
* slave objects
|
||||
*****************************************************************************/
|
||||
|
||||
const ec_slave_type_t Beckhoff_EK1100 = {
|
||||
"Beckhoff", "EK1100", "Bus Coupler", EC_TYPE_BUS_COUPLER,
|
||||
{NULL} // Keine Sync-Manager
|
||||
{NULL} // no sync managers
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_slave_type_t Beckhoff_EK1110 = {
|
||||
"Beckhoff", "EK1110", "Extension terminal", EC_TYPE_NORMAL,
|
||||
{NULL} // Keine Sync-Manager
|
||||
{NULL} // no sync managers
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_slave_type_t Beckhoff_BK1120 = {
|
||||
"Beckhoff", "BK1120", "KBUS Coupler", EC_TYPE_NORMAL,
|
||||
{NULL} // Keine Sync-Manager
|
||||
{NULL} // no sync managers
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
const ec_field_t el1014_in = {"InputValue", 1};
|
||||
|
||||
const ec_sync_t el1014_sm0 = { // Inputs
|
||||
const ec_sync_t el1014_sm0 = { // inputs
|
||||
0x1000, 1, 0x00,
|
||||
{&el1014_in, NULL}
|
||||
};
|
||||
@@ -195,15 +193,10 @@ const ec_slave_type_t TR_Electronic_LinEnc2 = {
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beziehung zwischen Identifikationsnummern und Klemmen-Objekt.
|
||||
|
||||
Diese Tabelle stellt die Beziehungen zwischen bestimmten Kombinationen
|
||||
aus Vendor-IDs und Product-Codes und der entsprechenden Klemme her.
|
||||
Neue Klemmen müssen hier eingetragen werden.
|
||||
Mapping between vendor IDs and product codes <=> slave objects.
|
||||
*/
|
||||
|
||||
ec_slave_ident_t slave_idents[] =
|
||||
{
|
||||
ec_slave_ident_t slave_idents[] = {
|
||||
{0x00000002, 0x03F63052, &Beckhoff_EL1014},
|
||||
{0x00000002, 0x044C2C52, &Beckhoff_EK1100},
|
||||
{0x00000002, 0x04562C52, &Beckhoff_EK1110},
|
||||
@@ -222,9 +215,3 @@ ec_slave_ident_t slave_idents[] =
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* t y p e s . h
|
||||
*
|
||||
* EtherCAT-Slave-Typen.
|
||||
* EtherCAT slave types.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -23,27 +23,27 @@
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Besondere Slaves.
|
||||
Special slaves.
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
EC_TYPE_NORMAL,
|
||||
EC_TYPE_BUS_COUPLER,
|
||||
EC_TYPE_EOE
|
||||
EC_TYPE_NORMAL, /**< no special slave */
|
||||
EC_TYPE_BUS_COUPLER, /**< slave is a bus coupler */
|
||||
EC_TYPE_EOE /**< slave is an EoE switch */
|
||||
}
|
||||
ec_special_type_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Prozessdatenfeld.
|
||||
Process data field.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
size_t size;
|
||||
const char *name; /**< field name */
|
||||
size_t size; /**< field size in bytes */
|
||||
}
|
||||
ec_field_t;
|
||||
|
||||
@@ -55,60 +55,45 @@ ec_field_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t physical_start_address;
|
||||
uint16_t size;
|
||||
uint8_t control_byte;
|
||||
const ec_field_t *fields[EC_MAX_FIELDS];
|
||||
uint16_t physical_start_address; /**< physical start address */
|
||||
uint16_t size; /**< size in bytes */
|
||||
uint8_t control_byte; /**< control register value */
|
||||
const ec_field_t *fields[EC_MAX_FIELDS]; /**< field array */
|
||||
}
|
||||
ec_sync_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Beschreibung eines EtherCAT-Slave-Typs.
|
||||
|
||||
Diese Beschreibung dient zur Konfiguration einer bestimmten
|
||||
Slave-Art. Sie enthält die Konfigurationsdaten für die
|
||||
Slave-internen Sync-Manager und FMMUs.
|
||||
Slave description type.
|
||||
*/
|
||||
|
||||
typedef struct ec_slave_type
|
||||
{
|
||||
const char *vendor_name; /**< Name des Herstellers */
|
||||
const char *product_name; /**< Name des Slaves-Typs */
|
||||
const char *description; /**< Genauere Beschreibung des Slave-Typs */
|
||||
ec_special_type_t special; /**< Spezieller Slave-Typ */
|
||||
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< Sync-Manager
|
||||
Konfigurationen */
|
||||
const char *vendor_name; /**< vendor name*/
|
||||
const char *product_name; /**< product name */
|
||||
const char *description; /**< free description */
|
||||
ec_special_type_t special; /**< special slave type? */
|
||||
const ec_sync_t *sync_managers[EC_MAX_SYNC]; /**< sync managers */
|
||||
}
|
||||
ec_slave_type_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/**
|
||||
Identifikation eines Slave-Typs.
|
||||
|
||||
Diese Struktur wird zur 1:n-Zuordnung von Hersteller- und
|
||||
Produktcodes zu den einzelnen Slave-Typen verwendet.
|
||||
Slave type identification.
|
||||
*/
|
||||
|
||||
typedef struct slave_ident
|
||||
typedef struct
|
||||
{
|
||||
uint32_t vendor_id; /**< Hersteller-Code */
|
||||
uint32_t product_code; /**< Herstellerspezifischer Produktcode */
|
||||
const ec_slave_type_t *type; /**< Zeiger auf den entsprechenden Typ */
|
||||
uint32_t vendor_id; /**< vendor id */
|
||||
uint32_t product_code; /**< product code */
|
||||
const ec_slave_type_t *type; /**< associated slave description object */
|
||||
}
|
||||
ec_slave_ident_t;
|
||||
|
||||
extern ec_slave_ident_t slave_idents[]; /**< Statisches Array der
|
||||
Slave-Identifikationen */
|
||||
extern ec_slave_ident_t slave_idents[]; /**< array with slave descriptions */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# Minimales EtherCAT-Modul
|
||||
# Minimal EtherCAT module.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
@@ -11,7 +11,7 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Kbuild-Abschnitt
|
||||
# kbuild section
|
||||
#----------------------------------------------------------------
|
||||
|
||||
obj-m := ec_mini.o
|
||||
@@ -23,7 +23,7 @@ ec_mini-objs := mini.o
|
||||
else
|
||||
|
||||
#----------------------------------------------------------------
|
||||
# Default-Abschnitt
|
||||
# default section
|
||||
#----------------------------------------------------------------
|
||||
|
||||
ifneq ($(wildcard ethercat.conf),)
|
||||
|
||||
38
mini/mini.c
38
mini/mini.c
@@ -2,7 +2,7 @@
|
||||
*
|
||||
* m i n i . c
|
||||
*
|
||||
* Minimalmodul für EtherCAT
|
||||
* Minimal module for EtherCAT.
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
@@ -12,31 +12,28 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
#include "../include/ecrt.h" // Echtzeitschnittstelle
|
||||
#include "../include/ecrt.h" // EtherCAT realtime interface
|
||||
|
||||
#define ASYNC
|
||||
#define FREQUENCY 100
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define ABTASTFREQUENZ 100
|
||||
|
||||
struct timer_list timer;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
// EtherCAT
|
||||
ec_master_t *master = NULL;
|
||||
ec_domain_t *domain1 = NULL;
|
||||
|
||||
// Datenfelder
|
||||
// data fields
|
||||
//void *r_ssi_input, *r_ssi_status, *r_4102[3];
|
||||
|
||||
// Kanäle
|
||||
// channels
|
||||
uint32_t k_pos;
|
||||
uint8_t k_stat;
|
||||
|
||||
ec_field_init_t domain1_fields[] = {
|
||||
{NULL, "1", "Beckhoff", "EL5001", "InputValue", 0},
|
||||
{NULL, "1", "Beckhoff", "EL5001", "InputValue", 0},
|
||||
{NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0},
|
||||
{}
|
||||
};
|
||||
@@ -48,22 +45,22 @@ void run(unsigned long data)
|
||||
static unsigned int counter = 0;
|
||||
|
||||
#ifdef ASYNC
|
||||
// Empfangen
|
||||
// receive
|
||||
ecrt_master_async_receive(master);
|
||||
ecrt_domain_process(domain1);
|
||||
#else
|
||||
// Senden und empfangen
|
||||
// send and receive
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_run(master);
|
||||
ecrt_master_sync_io(master);
|
||||
ecrt_domain_process(domain1);
|
||||
#endif
|
||||
|
||||
// Prozessdaten verarbeiten
|
||||
// process data
|
||||
//k_pos = EC_READ_U32(r_ssi);
|
||||
|
||||
#ifdef ASYNC
|
||||
// Senden
|
||||
// send
|
||||
ecrt_domain_queue(domain1);
|
||||
ecrt_master_run(master);
|
||||
ecrt_master_async_send(master);
|
||||
@@ -73,13 +70,13 @@ void run(unsigned long data)
|
||||
counter--;
|
||||
}
|
||||
else {
|
||||
counter = ABTASTFREQUENZ;
|
||||
counter = FREQUENCY;
|
||||
//printk(KERN_INFO "k_pos = %i\n", k_pos);
|
||||
//printk(KERN_INFO "k_stat = 0x%02X\n", k_stat);
|
||||
}
|
||||
|
||||
// Timer neu starten
|
||||
timer.expires += HZ / ABTASTFREQUENZ;
|
||||
// restart timer
|
||||
timer.expires += HZ / FREQUENCY;
|
||||
add_timer(&timer);
|
||||
}
|
||||
|
||||
@@ -153,14 +150,14 @@ int __init init_mini_module(void)
|
||||
#endif
|
||||
|
||||
#ifdef ASYNC
|
||||
// Einmal senden und warten...
|
||||
// send once and wait...
|
||||
ecrt_master_prepare_async_io(master);
|
||||
#endif
|
||||
|
||||
printk("Starting cyclic sample thread.\n");
|
||||
init_timer(&timer);
|
||||
timer.function = run;
|
||||
timer.expires = jiffies + 10; // Das erste Mal sofort feuern
|
||||
timer.expires = jiffies + 10;
|
||||
add_timer(&timer);
|
||||
|
||||
printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n");
|
||||
@@ -203,8 +200,3 @@ module_exit(cleanup_mini_module);
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Emacs-Konfiguration
|
||||
;;; Local Variables: ***
|
||||
;;; c-basic-offset:4 ***
|
||||
;;; End: ***
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Makefile Echtzeitmodule
|
||||
# Makefile
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
@@ -9,7 +9,7 @@
|
||||
ifneq ($(KERNELRELEASE),)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Kbuild-Abschnitt
|
||||
# kbuild section
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ifneq ($(wildcard $(src)/rt.conf),)
|
||||
@@ -44,7 +44,7 @@ EXTRA_CFLAGS := -I$(src)/rt_lib/msr-include -D_SIMULATION \
|
||||
else
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Default-Abschnitt
|
||||
# default section
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
ifneq ($(wildcard rt.conf),)
|
||||
|
||||
@@ -2,14 +2,6 @@
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# (C) Copyright
|
||||
# Diese Software ist geistiges Eigentum der
|
||||
# Ingenieurgemeinschaft IgH. Sie darf von
|
||||
# Toyota Motorsport GmbH
|
||||
# beliebig kopiert und veraendert werden.
|
||||
# Die Weitergabe an Dritte ist untersagt.
|
||||
# Dieser Urhebrrechtshinweis muss erhalten
|
||||
# bleiben.
|
||||
#
|
||||
# Ingenieurgemeinschaft IgH
|
||||
# Heinz-Baecker-Strasse 34
|
||||
# D-45356 Essen
|
||||
@@ -20,13 +12,13 @@
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Multithreaded Server
|
||||
# Multithreaded Server
|
||||
# according to the example from "Programming Perl"
|
||||
# this code is improved according to the example from
|
||||
# perldoc perlipc, so now safely being usable under Perl 5.8
|
||||
# this code is improved according to the example from
|
||||
# perldoc perlipc, so now safely being usable under Perl 5.8
|
||||
# (see note (*))
|
||||
#
|
||||
# works with read/write on a device-file
|
||||
# works with read/write on a device-file
|
||||
#
|
||||
# $Revision: 1.1 $
|
||||
# $Date: 2004/10/01 16:00:42 $
|
||||
@@ -40,9 +32,9 @@ BEGIN { $ENV{PATH} = '/opt/msr/bin:/usr/bin:/bin' }
|
||||
use Socket;
|
||||
use Carp;
|
||||
use FileHandle;
|
||||
use Getopt::Std;
|
||||
use Getopt::Std;
|
||||
|
||||
use Sys::Syslog qw(:DEFAULT setlogsock);
|
||||
use Sys::Syslog qw(:DEFAULT setlogsock);
|
||||
|
||||
use vars qw (
|
||||
$self $pid $dolog $port $dev %opts $selfbase
|
||||
@@ -53,25 +45,25 @@ use vars qw (
|
||||
|
||||
|
||||
# Do logging to local syslogd by unix-domain socket instead of inetd
|
||||
setlogsock("unix");
|
||||
setlogsock("unix");
|
||||
|
||||
# Prototypes and some little Tools
|
||||
sub spawn;
|
||||
sub logmsg {
|
||||
sub logmsg {
|
||||
my ($level, $debug, @text) = @_;
|
||||
syslog("daemon|$level", @text) if $debug > $dolog;
|
||||
# print STDERR "daemon|$level", @text, "\n" if $dolog;
|
||||
}
|
||||
sub out {
|
||||
my $waitpid = wait;
|
||||
my $waitpid = wait;
|
||||
logmsg("notice", 2, "$waitpid exited");
|
||||
unlink "$selfbase.pid";
|
||||
exit 0;
|
||||
}
|
||||
|
||||
sub help {
|
||||
print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n";
|
||||
exit;
|
||||
print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n";
|
||||
exit;
|
||||
}
|
||||
|
||||
# Process Options
|
||||
@@ -81,7 +73,7 @@ sub help {
|
||||
"p" => 2345,
|
||||
"d" => "/dev/msr"
|
||||
);
|
||||
|
||||
|
||||
getopts("lhp:d:", \%opts);
|
||||
|
||||
help if $opts{"h"};
|
||||
@@ -94,7 +86,7 @@ $port = $opts{"p"};
|
||||
$dev = $opts{"d"};
|
||||
$blksize = 1024; # try to write as much bytes
|
||||
$instdir = "/opt/msr";
|
||||
$authfile = "$instdir/etc/hosts.auth";
|
||||
$authfile = "$instdir/etc/hosts.auth";
|
||||
|
||||
# Start logging
|
||||
openlog($self, 'pid');
|
||||
@@ -127,12 +119,12 @@ setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1))
|
||||
or die "setsocketopt: $!";
|
||||
bind (Server, sockaddr_in($port, INADDR_ANY))
|
||||
or die "bind: $!";
|
||||
listen (Server, SOMAXCONN)
|
||||
listen (Server, SOMAXCONN)
|
||||
or die "listen: $!";
|
||||
|
||||
%authhosts = ();
|
||||
# get authorized hosts
|
||||
open (AUTH, $authfile)
|
||||
open (AUTH, $authfile)
|
||||
or logmsg ("notice", 2, "Could not read allowed hosts file: $authfile");
|
||||
while (<AUTH>) {
|
||||
chomp;
|
||||
@@ -176,26 +168,26 @@ while ( 1 ) {
|
||||
my $name = lc gethostbyaddr($iaddr, AF_INET);
|
||||
my $ipaddr = inet_ntoa($iaddr);
|
||||
my $n = 0;
|
||||
|
||||
|
||||
# tell about the requesting client
|
||||
logmsg ("info", 2, "Connection from >$ipaddr< ($name) at port $port");
|
||||
|
||||
|
||||
spawn sub {
|
||||
my ($head, $hlen, $pos, $pegel, $typ, $siz, $nch, $nrec, $dat, $i, $j, $n, $llen);
|
||||
my ($watchpegel, $shmpegel);
|
||||
my ($rin, $rout, $in, $line, $data_requested, $oversample);
|
||||
my (@channels);
|
||||
|
||||
|
||||
# to use stdio on writing to Client
|
||||
Client->autoflush();
|
||||
|
||||
# Open Device
|
||||
|
||||
# Open Device
|
||||
sysopen (DEV, "$dev", O_RDWR | O_NONBLOCK, 0666) or die("can't open $dev");
|
||||
|
||||
|
||||
# Bitmask to check for input on stdin
|
||||
$rin = "";
|
||||
vec($rin, fileno(Client), 1) = 1;
|
||||
|
||||
vec($rin, fileno(Client), 1) = 1;
|
||||
|
||||
# check for authorized hosts
|
||||
my $access = 'deny';
|
||||
$access = 'allow' if $authhosts{$ipaddr};
|
||||
@@ -208,14 +200,14 @@ while ( 1 ) {
|
||||
$len -= $written;
|
||||
$offset += $written;
|
||||
}
|
||||
|
||||
|
||||
while ( 1 ) {
|
||||
$in = select ($rout=$rin, undef, undef, 0.0); # poll client
|
||||
# look for any Input from Client
|
||||
if ($in) {
|
||||
# exit on EOF
|
||||
$len = sysread (Client, $line, $blksize) or exit;
|
||||
logmsg("info", 0, "got $len bytes: \"$line\"");
|
||||
logmsg("info", 0, "got $len bytes: \"$line\"");
|
||||
$offset = 0;
|
||||
# copy request to device
|
||||
while ($len) {
|
||||
@@ -239,11 +231,11 @@ while ( 1 ) {
|
||||
|
||||
sub spawn {
|
||||
my $coderef = shift;
|
||||
|
||||
|
||||
unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') {
|
||||
confess "usage: spawn CODEREF";
|
||||
}
|
||||
my $pid;
|
||||
my $pid;
|
||||
if (!defined($pid = fork)) {
|
||||
logmsg ("notice", 2, "fork failed: $!");
|
||||
return;
|
||||
@@ -258,15 +250,3 @@ sub spawn {
|
||||
# STDOUT->autoflush();
|
||||
exit &$coderef();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user