Added VoE handler.

This commit is contained in:
Florian Pose
2008-09-01 14:17:18 +00:00
parent 54d13f2a92
commit 12d30c487a
34 changed files with 714 additions and 117 deletions

View File

@@ -48,6 +48,7 @@
#define EL3152_ALT_PDOS 0
#define EXTERNAL_MEMORY 1
#define SDO_ACCESS 0
#define VOE_ACCESS 0
#define PFX "ec_mini: "
@@ -184,6 +185,10 @@ static ec_sync_info_t el2004_syncs[] = {
static ec_sdo_request_t *sdo;
#endif
#if VOE_ACCESS
static ec_voe_handler_t *voe;
#endif
/*****************************************************************************/
void check_domain1_state(void)
@@ -249,18 +254,18 @@ void check_slave_config_states(void)
void read_sdo(void)
{
switch (ecrt_sdo_request_state(sdo)) {
case EC_SDO_REQUEST_UNUSED: // request was not used yet
case EC_REQUEST_UNUSED: // request was not used yet
ecrt_sdo_request_read(sdo); // trigger first read
break;
case EC_SDO_REQUEST_BUSY:
case EC_REQUEST_BUSY:
printk(KERN_INFO PFX "Still busy...\n");
break;
case EC_SDO_REQUEST_SUCCESS:
case EC_REQUEST_SUCCESS:
printk(KERN_INFO PFX "Sdo value: 0x%04X\n",
EC_READ_U16(ecrt_sdo_request_data(sdo)));
ecrt_sdo_request_read(sdo); // trigger next read
break;
case EC_SDO_REQUEST_ERROR:
case EC_REQUEST_ERROR:
printk(KERN_INFO PFX "Failed to read Sdo!\n");
ecrt_sdo_request_read(sdo); // retry reading
break;
@@ -270,6 +275,31 @@ void read_sdo(void)
/*****************************************************************************/
#if VOE_ACCESS
void read_voe(void)
{
switch (ecrt_voe_handler_execute(voe)) {
case EC_REQUEST_UNUSED:
ecrt_voe_handler_read(voe); // trigger first read
break;
case EC_REQUEST_BUSY:
printk(KERN_INFO PFX "VoE read still busy...\n");
break;
case EC_REQUEST_SUCCESS:
printk(KERN_INFO PFX "VoE received.\n");
// get data via ecrt_voe_handler_data(voe)
ecrt_voe_handler_read(voe); // trigger next read
break;
case EC_REQUEST_ERROR:
printk(KERN_INFO PFX "Failed to read VoE data!\n");
ecrt_voe_handler_read(voe); // retry reading
break;
}
}
#endif
/*****************************************************************************/
void cyclic_task(unsigned long data)
{
// receive process data
@@ -299,6 +329,10 @@ void cyclic_task(unsigned long data)
// read process data Sdo
read_sdo();
#endif
#if VOE_ACCESS
read_voe();
#endif
}
// write process data
@@ -401,6 +435,14 @@ int __init init_mini_module(void)
ecrt_sdo_request_timeout(sdo, 500); // ms
#endif
#if VOE_ACCESS
printk(KERN_INFO PFX "Creating VoE handlers...\n");
if (!(voe = ecrt_slave_config_create_voe_handler(sc_ana_in, 1000))) {
printk(KERN_ERR PFX "Failed to create VoE handler.\n");
goto out_release_master;
}
#endif
printk(KERN_INFO PFX "Registering Pdo entries...\n");
if (ecrt_domain_reg_pdo_entry_list(domain1, domain1_regs)) {
printk(KERN_ERR PFX "Pdo entry registration failed!\n");

View File

@@ -113,7 +113,7 @@
/** EtherCAT realtime interface minor version number.
*/
#define ECRT_VER_MINOR 4
#define ECRT_VER_MINOR 5
/** EtherCAT realtime interface version word generator.
*/
@@ -151,6 +151,9 @@ typedef struct ec_domain ec_domain_t; /**< \see ec_domain */
struct ec_sdo_request;
typedef struct ec_sdo_request ec_sdo_request_t; /**< \see ec_sdo_request. */
struct ec_voe_handler;
typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */
/*****************************************************************************/
/** Master state.
@@ -305,16 +308,17 @@ typedef struct {
/*****************************************************************************/
/** Sdo request state.
/** Request state.
*
* This is used as return type of ecrt_sdo_request_state().
* This is used as return type for ecrt_sdo_request_state() and
* ecrt_voe_handler_state().
*/
typedef enum {
EC_SDO_REQUEST_UNUSED, /**< Not requested. */
EC_SDO_REQUEST_BUSY, /**< Request is being processed. */
EC_SDO_REQUEST_SUCCESS, /**< Request was processed successfully. */
EC_SDO_REQUEST_ERROR, /**< Request processing failed. */
} ec_sdo_request_state_t;
EC_REQUEST_UNUSED, /**< Not requested. */
EC_REQUEST_BUSY, /**< Request is being processed. */
EC_REQUEST_SUCCESS, /**< Request was processed successfully. */
EC_REQUEST_ERROR, /**< Request processing failed. */
} ec_request_state_t;
/******************************************************************************
* Global functions
@@ -727,6 +731,17 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(
size_t size /**< Data size to reserve. */
);
/** Create an VoE handler to exchange vendor-specific data during realtime
* operation.
*
* The created VoE handler object is freed automatically when the master is
* released.
*/
ec_voe_handler_t *ecrt_slave_config_create_voe_handler(
ec_slave_config_t *sc, /**< Slave configuration. */
size_t size /**< Data size to reserve. */
);
/** Outputs the state of the slave configuration.
*
* Stores the state information in the given \a state structure.
@@ -878,7 +893,7 @@ size_t ecrt_sdo_request_data_size(
*
* \return Request state.
*/
ec_sdo_request_state_t ecrt_sdo_request_state(
ec_request_state_t ecrt_sdo_request_state(
const ec_sdo_request_t *req /**< Sdo request. */
);
@@ -904,6 +919,73 @@ void ecrt_sdo_request_read(
ec_sdo_request_t *req /**< Sdo request. */
);
/*****************************************************************************
* VoE handler methods.
****************************************************************************/
/** Access to the VoE handler's data.
*
* This function returns a pointer to the handler's internal memory.
*
* - After a read operation was successful, the memory contains the received
* data. The size of the received data can be determined via
* ecrt_voe_handler_data_size().
* - Before a write operation is triggered, the data have to be written to
* the internal memory. Be sure, that the data fit into the memory. The
* memory size is a parameter of ecrt_slave_config_create_voe_handler().
*
* \return Pointer to the internal memory.
*/
uint8_t *ecrt_voe_handler_data(
ec_voe_handler_t *voe /**< VoE handler. */
);
/** Returns the current data size.
*
* When the VoE handler is created, the data size is set to the size of the
* reserved memory. At a write operation, the data size is set to the number
* of bytes to write. After a read operation the size is set to the size of
* the read data. The size is not modified in any other situation.
*
* \return Data size in bytes.
*/
size_t ecrt_voe_handler_data_size(
const ec_voe_handler_t *voe /**< VoE handler. */
);
/** Start a VoE write operation.
*
* After this function has been called, the ecrt_voe_handler_execute() method
* must be called in every bus cycle as long as it returns EC_REQUEST_BUSY.
*/
void ecrt_voe_handler_write(
ec_voe_handler_t *voe, /**< VoE handler. */
size_t size /**< Number of bytes to write. */
);
/** Start a VoE read operation.
*
* After this function has been called, the ecrt_voe_handler_execute() method
* must be called in every bus cycle as long as it returns EC_REQUEST_BUSY.
*
* On success, the size of the read data can be determined via
* ecrt_voe_handler_data_size().
*/
void ecrt_voe_handler_read(
ec_voe_handler_t *voe /**< VoE handler. */
);
/** Execute the handler.
*
* This method executes the VoE handler. It has to be called in every bus cycle
* as long as it returns EC_REQUEST_BUSY.
*
* \return Handler state.
*/
ec_request_state_t ecrt_voe_handler_execute(
ec_voe_handler_t *voe /**< VoE handler. */
);
/******************************************************************************
* Bitwise read/write macros
*****************************************************************************/

View File

@@ -61,7 +61,8 @@ ec_master-objs := \
slave.o \
slave_config.o \
sync.o \
sync_config.o
sync_config.o \
voe_handler.o
ifeq (@ENABLE_EOE@,1)
ec_master-objs += ethernet.o

View File

@@ -64,7 +64,8 @@ noinst_HEADERS = \
slave.c slave.h \
slave_config.c slave_config.h \
sync.c sync.h \
sync_config.c sync_config.h
sync_config.c sync_config.h \
voe_handler.c voe_handler.h
BUILT_SOURCES = \
Kbuild

View File

@@ -726,10 +726,10 @@ int ec_cdev_ioctl_slave_sdo_upload(
// wait for processing through FSM
if (wait_event_interruptible(master->sdo_queue,
request.req.state != EC_REQUEST_QUEUED)) {
request.req.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
if (request.req.state == EC_REQUEST_QUEUED) {
if (request.req.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->master_sem);
ec_sdo_request_clear(&request.req);
@@ -740,11 +740,11 @@ int ec_cdev_ioctl_slave_sdo_upload(
}
// wait until master FSM has finished processing
wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY);
data.abort_code = request.req.abort_code;
if (request.req.state != EC_REQUEST_SUCCESS) {
if (request.req.state != EC_INT_REQUEST_SUCCESS) {
data.data_size = 0;
retval = -EIO;
} else {
@@ -828,10 +828,10 @@ int ec_cdev_ioctl_slave_sdo_download(
// wait for processing through FSM
if (wait_event_interruptible(master->sdo_queue,
request.req.state != EC_REQUEST_QUEUED)) {
request.req.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
if (request.req.state == EC_REQUEST_QUEUED) {
if (request.req.state == EC_INT_REQUEST_QUEUED) {
list_del(&request.req.list);
up(&master->master_sem);
ec_sdo_request_clear(&request.req);
@@ -842,11 +842,11 @@ int ec_cdev_ioctl_slave_sdo_download(
}
// wait until master FSM has finished processing
wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
wait_event(master->sdo_queue, request.req.state != EC_INT_REQUEST_BUSY);
data.abort_code = request.req.abort_code;
retval = request.req.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
retval = request.req.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
retval = -EFAULT;
@@ -954,7 +954,7 @@ int ec_cdev_ioctl_slave_sii_write(
request.words = words;
request.offset = data.offset;
request.nwords = data.nwords;
request.state = EC_REQUEST_QUEUED;
request.state = EC_INT_REQUEST_QUEUED;
// schedule SII write request.
list_add_tail(&request.list, &master->sii_requests);
@@ -963,10 +963,10 @@ int ec_cdev_ioctl_slave_sii_write(
// wait for processing through FSM
if (wait_event_interruptible(master->sii_queue,
request.state != EC_REQUEST_QUEUED)) {
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
if (request.state == EC_REQUEST_QUEUED) {
if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -977,11 +977,11 @@ int ec_cdev_ioctl_slave_sii_write(
}
// wait until master FSM has finished processing
wait_event(master->sii_queue, request.state != EC_REQUEST_BUSY);
wait_event(master->sii_queue, request.state != EC_INT_REQUEST_BUSY);
kfree(words);
return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/
@@ -1027,7 +1027,7 @@ int ec_cdev_ioctl_slave_phy_read(
request.data = contents;
request.offset = data.offset;
request.length = data.length;
request.state = EC_REQUEST_QUEUED;
request.state = EC_INT_REQUEST_QUEUED;
// schedule request.
list_add_tail(&request.list, &master->phy_requests);
@@ -1036,10 +1036,10 @@ int ec_cdev_ioctl_slave_phy_read(
// wait for processing through FSM
if (wait_event_interruptible(master->phy_queue,
request.state != EC_REQUEST_QUEUED)) {
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
if (request.state == EC_REQUEST_QUEUED) {
if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -1050,15 +1050,15 @@ int ec_cdev_ioctl_slave_phy_read(
}
// wait until master FSM has finished processing
wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
wait_event(master->phy_queue, request.state != EC_INT_REQUEST_BUSY);
if (request.state == EC_REQUEST_SUCCESS) {
if (request.state == EC_INT_REQUEST_SUCCESS) {
if (copy_to_user((void __user *) data.data, contents, data.length))
return -EFAULT;
}
kfree(contents);
return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/
@@ -1110,7 +1110,7 @@ int ec_cdev_ioctl_slave_phy_write(
request.data = contents;
request.offset = data.offset;
request.length = data.length;
request.state = EC_REQUEST_QUEUED;
request.state = EC_INT_REQUEST_QUEUED;
// schedule request.
list_add_tail(&request.list, &master->phy_requests);
@@ -1119,10 +1119,10 @@ int ec_cdev_ioctl_slave_phy_write(
// wait for processing through FSM
if (wait_event_interruptible(master->phy_queue,
request.state != EC_REQUEST_QUEUED)) {
request.state != EC_INT_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->master_sem);
if (request.state == EC_REQUEST_QUEUED) {
if (request.state == EC_INT_REQUEST_QUEUED) {
// abort request
list_del(&request.list);
up(&master->master_sem);
@@ -1133,11 +1133,11 @@ int ec_cdev_ioctl_slave_phy_write(
}
// wait until master FSM has finished processing
wait_event(master->phy_queue, request.state != EC_REQUEST_BUSY);
wait_event(master->phy_queue, request.state != EC_INT_REQUEST_BUSY);
kfree(contents);
return request.state == EC_REQUEST_SUCCESS ? 0 : -EIO;
return request.state == EC_INT_REQUEST_SUCCESS ? 0 : -EIO;
}
/*****************************************************************************/

View File

@@ -45,7 +45,6 @@
#include <linux/cdev.h>
#include "globals.h"
#include "../include/ecrt.h"
/*****************************************************************************/

View File

@@ -43,7 +43,6 @@
#include <linux/interrupt.h>
#include "../include/ecrt.h"
#include "../devices/ecdev.h"
#include "globals.h"

View File

@@ -41,7 +41,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "master.h"
#include "slave.h"

View File

@@ -41,7 +41,6 @@
#include <linux/list.h>
#include <linux/netdevice.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "datagram.h"

View File

@@ -40,8 +40,6 @@
#ifndef __EC_FMMU_CONFIG_H__
#define __EC_FMMU_CONFIG_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "sync.h"

View File

@@ -42,7 +42,6 @@
#define __EC_FSM_CHANGE_H__
#include "globals.h"
#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"

View File

@@ -42,7 +42,6 @@
#define __EC_FSM_COE_H__
#include "globals.h"
#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"
#include "sdo.h"

View File

@@ -305,7 +305,7 @@ int ec_fsm_master_action_process_sii(
request = list_entry(master->sii_requests.next,
ec_sii_write_request_t, list);
list_del_init(&request->list); // dequeue
request->state = EC_REQUEST_BUSY;
request->state = EC_INT_REQUEST_BUSY;
// found pending SII write operation. execute it!
if (master->debug_level)
@@ -345,7 +345,7 @@ int ec_fsm_master_action_process_phy(
request = list_entry(master->phy_requests.next,
ec_phy_request_t, list);
list_del_init(&request->list); // dequeue
request->state = EC_REQUEST_BUSY;
request->state = EC_INT_REQUEST_BUSY;
// found pending request; process it!
if (master->debug_level)
@@ -360,7 +360,7 @@ int ec_fsm_master_action_process_phy(
if (request->length > fsm->datagram->mem_size) {
EC_ERR("Request length (%u) exceeds maximum datagram size (%u)!\n",
request->length, fsm->datagram->mem_size);
request->state = EC_REQUEST_FAILURE;
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
continue;
}
@@ -398,10 +398,10 @@ int ec_fsm_master_action_process_sdo(
if (!slave->config)
continue;
list_for_each_entry(req, &slave->config->sdo_requests, list) {
if (req->state == EC_REQUEST_QUEUED) {
if (req->state == EC_INT_REQUEST_QUEUED) {
if (ec_sdo_request_timed_out(req)) {
req->state = EC_REQUEST_FAILURE;
req->state = EC_INT_REQUEST_FAILURE;
if (master->debug_level)
EC_DBG("Sdo request for slave %u timed out...\n",
slave->ring_position);
@@ -409,11 +409,11 @@ int ec_fsm_master_action_process_sdo(
}
if (slave->current_state == EC_SLAVE_STATE_INIT) {
req->state = EC_REQUEST_FAILURE;
req->state = EC_INT_REQUEST_FAILURE;
continue;
}
req->state = EC_REQUEST_BUSY;
req->state = EC_INT_REQUEST_BUSY;
if (master->debug_level)
EC_DBG("Processing Sdo request for slave %u...\n",
slave->ring_position);
@@ -438,13 +438,13 @@ int ec_fsm_master_action_process_sdo(
request = list_entry(master->slave_sdo_requests.next,
ec_master_sdo_request_t, list);
list_del_init(&request->list); // dequeue
request->req.state = EC_REQUEST_BUSY;
request->req.state = EC_INT_REQUEST_BUSY;
slave = request->slave;
if (slave->current_state == EC_SLAVE_STATE_INIT) {
EC_ERR("Discarding Sdo request, slave %u is in INIT.\n",
slave->ring_position);
request->req.state = EC_REQUEST_FAILURE;
request->req.state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
continue;
}
@@ -812,7 +812,7 @@ void ec_fsm_master_state_write_sii(
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
EC_ERR("Failed to write SII data to slave %u.\n",
slave->ring_position);
request->state = EC_REQUEST_FAILURE;
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sii_queue);
ec_fsm_master_restart(fsm);
return;
@@ -839,7 +839,7 @@ void ec_fsm_master_state_write_sii(
}
// TODO: Evaluate other SII contents!
request->state = EC_REQUEST_SUCCESS;
request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->sii_queue);
// check for another SII write request
@@ -898,14 +898,14 @@ void ec_fsm_master_state_sdo_request(
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
EC_DBG("Failed to process Sdo request for slave %u.\n",
fsm->slave->ring_position);
request->state = EC_REQUEST_FAILURE;
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
ec_fsm_master_restart(fsm);
return;
}
// Sdo request finished
request->state = EC_REQUEST_SUCCESS;
request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->sdo_queue);
if (master->debug_level)
@@ -934,7 +934,7 @@ void ec_fsm_master_state_phy_request(
if (datagram->state != EC_DATAGRAM_RECEIVED) {
EC_ERR("Failed to receive phy request datagram (state %u).\n",
datagram->state);
request->state = EC_REQUEST_FAILURE;
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
ec_fsm_master_restart(fsm);
return;
@@ -947,7 +947,7 @@ void ec_fsm_master_state_phy_request(
if (!request->data) {
EC_ERR("Failed to allocate %u bytes of memory for phy request.\n",
request->length);
request->state = EC_REQUEST_FAILURE;
request->state = EC_INT_REQUEST_FAILURE;
wake_up(&master->phy_queue);
ec_fsm_master_restart(fsm);
return;
@@ -955,7 +955,7 @@ void ec_fsm_master_state_phy_request(
memcpy(request->data, datagram->data, request->length);
}
request->state = EC_REQUEST_SUCCESS;
request->state = EC_INT_REQUEST_SUCCESS;
wake_up(&master->phy_queue);
// check for another PHY request

View File

@@ -41,8 +41,6 @@
#ifndef __EC_FSM_MASTER_H__
#define __EC_FSM_MASTER_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "datagram.h"
#include "sdo_request.h"
@@ -60,7 +58,7 @@ typedef struct {
uint16_t offset; /**< SII word offset. */
size_t nwords; /**< Number of words. */
const uint16_t *words; /**< Pointer to the data words. */
ec_request_state_t state; /**< State of the request. */
ec_internal_request_state_t state; /**< State of the request. */
} ec_sii_write_request_t;
/*****************************************************************************/
@@ -74,7 +72,7 @@ typedef struct {
uint16_t offset; /**< Physical memory offset. */
size_t length; /**< Number of bytes. */
uint8_t *data;
ec_request_state_t state; /**< State of the request. */
ec_internal_request_state_t state; /**< State of the request. */
} ec_phy_request_t;
/*****************************************************************************/

View File

@@ -41,8 +41,6 @@
#ifndef __EC_FSM_PDO_H__
#define __EC_FSM_PDO_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "datagram.h"
#include "fsm_coe.h"

View File

@@ -41,7 +41,6 @@
#define __EC_FSM_PDO_ENTRY_H__
#include "globals.h"
#include "../include/ecrt.h"
#include "datagram.h"
#include "fsm_coe.h"

View File

@@ -42,7 +42,6 @@
#define __EC_FSM_SII_H__
#include "globals.h"
#include "../include/ecrt.h"
#include "datagram.h"
#include "slave.h"

View File

@@ -41,8 +41,6 @@
#ifndef __EC_FSM_SLAVE_CONFIG_H__
#define __EC_FSM_SLAVE_CONFIG_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "datagram.h"

View File

@@ -41,8 +41,6 @@
#ifndef __EC_FSM_SLAVE_SCAN_H__
#define __EC_FSM_SLAVE_SCAN_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "datagram.h"
#include "slave.h"

View File

@@ -43,6 +43,7 @@
#include <linux/types.h>
#include "../globals.h"
#include "../include/ecrt.h"
/******************************************************************************
* EtherCAT master
@@ -253,12 +254,16 @@ typedef struct {
* state_table in master/sdo_request.c.
*/
typedef enum {
EC_REQUEST_INIT,
EC_REQUEST_QUEUED,
EC_REQUEST_BUSY,
EC_REQUEST_SUCCESS,
EC_REQUEST_FAILURE
} ec_request_state_t;
EC_INT_REQUEST_INIT,
EC_INT_REQUEST_QUEUED,
EC_INT_REQUEST_BUSY,
EC_INT_REQUEST_SUCCESS,
EC_INT_REQUEST_FAILURE
} ec_internal_request_state_t;
/*****************************************************************************/
extern const ec_request_state_t ec_request_state_translation_table[];
/*****************************************************************************/

View File

@@ -46,7 +46,6 @@
#include <linux/device.h>
#include <linux/version.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "slave_config.h"

View File

@@ -545,6 +545,20 @@ unsigned int ecrt_version_magic(void)
/*****************************************************************************/
/** Global request state type translation table.
*
* Translates an internal request state to an external one.
*/
const ec_request_state_t ec_request_state_translation_table[] = {
EC_REQUEST_UNUSED, // EC_INT_REQUEST_INIT,
EC_REQUEST_BUSY, // EC_INT_REQUEST_QUEUED,
EC_REQUEST_BUSY, // EC_INT_REQUEST_BUSY,
EC_REQUEST_SUCCESS, // EC_INT_REQUEST_SUCCESS,
EC_REQUEST_ERROR // EC_INT_REQUEST_FAILURE
};
/*****************************************************************************/
/** \cond */
module_init(ec_init_module);

View File

@@ -43,8 +43,6 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "pdo_entry.h"

View File

@@ -43,8 +43,6 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
/*****************************************************************************/

View File

@@ -43,8 +43,6 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "pdo.h"

View File

@@ -54,18 +54,6 @@ void ec_sdo_request_clear_data(ec_sdo_request_t *);
/*****************************************************************************/
/** State type translation table.
*/
static const ec_sdo_request_state_t state_translation_table[] = {
EC_SDO_REQUEST_UNUSED, // EC_REQUEST_INIT,
EC_SDO_REQUEST_BUSY, // EC_REQUEST_QUEUED,
EC_SDO_REQUEST_BUSY, // EC_REQUEST_BUSY,
EC_SDO_REQUEST_SUCCESS, // EC_REQUEST_SUCCESS,
EC_SDO_REQUEST_ERROR // EC_REQUEST_FAILURE
};
/*****************************************************************************/
/** Sdo request constructor.
*/
void ec_sdo_request_init(
@@ -78,7 +66,7 @@ void ec_sdo_request_init(
req->dir = EC_DIR_INVALID;
req->issue_timeout = 0; // no timeout
req->response_timeout = EC_SDO_REQUEST_RESPONSE_TIMEOUT;
req->state = EC_REQUEST_INIT;
req->state = EC_INT_REQUEST_INIT;
req->abort_code = 0x00000000;
}
@@ -207,9 +195,9 @@ size_t ecrt_sdo_request_data_size(const ec_sdo_request_t *req)
/*****************************************************************************/
ec_sdo_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
ec_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
{
return state_translation_table[req->state];
return ec_request_state_translation_table[req->state];
}
/*****************************************************************************/
@@ -217,7 +205,7 @@ ec_sdo_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
void ecrt_sdo_request_read(ec_sdo_request_t *req)
{
req->dir = EC_DIR_INPUT;
req->state = EC_REQUEST_QUEUED;
req->state = EC_INT_REQUEST_QUEUED;
req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}
@@ -227,7 +215,7 @@ void ecrt_sdo_request_read(ec_sdo_request_t *req)
void ecrt_sdo_request_write(ec_sdo_request_t *req)
{
req->dir = EC_DIR_OUTPUT;
req->state = EC_REQUEST_QUEUED;
req->state = EC_INT_REQUEST_QUEUED;
req->abort_code = 0x00000000;
req->jiffies_start = jiffies;
}

View File

@@ -43,8 +43,6 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
/*****************************************************************************/
@@ -65,7 +63,7 @@ struct ec_sdo_request {
ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means downloading to
the slave, EC_DIR_INPUT means uploading from the
slave. */
ec_request_state_t state; /**< Sdo request state. */
ec_internal_request_state_t state; /**< Sdo request state. */
unsigned long jiffies_start; /**< Jiffies, when the request was issued. */
unsigned long jiffies_sent; /**< Jiffies, when the upload/download
request was sent. */

View File

@@ -44,8 +44,6 @@
#include <linux/list.h>
#include <linux/kobject.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "datagram.h"
#include "pdo.h"

View File

@@ -42,6 +42,7 @@
#include "globals.h"
#include "master.h"
#include "voe_handler.h"
#include "slave_config.h"
@@ -75,6 +76,7 @@ void ec_slave_config_init(
INIT_LIST_HEAD(&sc->sdo_configs);
INIT_LIST_HEAD(&sc->sdo_requests);
INIT_LIST_HEAD(&sc->voe_handlers);
sc->used_fmmus = 0;
}
@@ -91,6 +93,7 @@ void ec_slave_config_clear(
{
unsigned int i;
ec_sdo_request_t *req, *next_req;
ec_voe_handler_t *voe, *next_voe;
ec_slave_config_detach(sc);
@@ -111,6 +114,13 @@ void ec_slave_config_clear(
ec_sdo_request_clear(req);
kfree(req);
}
// free all VoE handlers
list_for_each_entry_safe(voe, next_voe, &sc->voe_handlers, list) {
list_del(&voe->list);
ec_voe_handler_clear(voe);
kfree(voe);
}
}
/*****************************************************************************/
@@ -742,6 +752,35 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
/*****************************************************************************/
ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc,
size_t size)
{
ec_voe_handler_t *voe;
if (sc->master->debug_level)
EC_DBG("ecrt_slave_config_create_voe_handler(sc = 0x%x, size = %u)\n",
(u32) sc, size);
if (!(voe = (ec_voe_handler_t *)
kmalloc(sizeof(ec_voe_handler_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate Sdo request memory!\n");
return NULL;
}
if (ec_voe_handler_init(voe, sc, size)) {
kfree(voe);
return NULL;
}
down(&sc->master->master_sem);
list_add_tail(&voe->list, &sc->voe_handlers);
up(&sc->master->master_sem);
return voe;
}
/*****************************************************************************/
void ecrt_slave_config_state(const ec_slave_config_t *sc,
ec_slave_config_state_t *state)
{

View File

@@ -43,8 +43,6 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
#include "slave.h"
#include "sync_config.h"
@@ -74,7 +72,7 @@ struct ec_slave_config {
struct list_head sdo_configs; /**< List of Sdo configurations. */
struct list_head sdo_requests; /**< List of Sdo requests. */
struct list_head voe_handlers; /**< List of VoE handlers. */
};
/*****************************************************************************/

View File

@@ -40,8 +40,6 @@
#ifndef __EC_SYNC_H__
#define __EC_SYNC_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "pdo_list.h"

View File

@@ -40,8 +40,6 @@
#ifndef __EC_SYNC_CONFIG_H__
#define __EC_SYNC_CONFIG_H__
#include "../include/ecrt.h"
#include "globals.h"
#include "pdo_list.h"

386
master/voe_handler.c Normal file
View File

@@ -0,0 +1,386 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/** \file
* Vendor-specific-over-EtherCAT protocol handler functions.
*/
/*****************************************************************************/
#include <linux/module.h>
#include "master.h"
#include "slave_config.h"
#include "mailbox.h"
#include "voe_handler.h"
/** VoE response timeout in [ms].
*/
#define EC_VOE_RESPONSE_TIMEOUT 500
/*****************************************************************************/
void ec_voe_handler_clear_data(ec_voe_handler_t *);
void ec_voe_handler_state_write_start(ec_voe_handler_t *);
void ec_voe_handler_state_write_response(ec_voe_handler_t *);
void ec_voe_handler_state_read_start(ec_voe_handler_t *);
void ec_voe_handler_state_read_check(ec_voe_handler_t *);
void ec_voe_handler_state_read_response(ec_voe_handler_t *);
void ec_voe_handler_state_end(ec_voe_handler_t *);
void ec_voe_handler_state_error(ec_voe_handler_t *);
/*****************************************************************************/
/** VoE handler constructor.
*/
int ec_voe_handler_init(
ec_voe_handler_t *voe, /**< VoE handler. */
ec_slave_config_t *sc, /**< Parent slave configuration. */
size_t size /**< Size of memory to reserve. */
)
{
voe->config = sc;
voe->data_size = 0;
voe->dir = EC_DIR_INVALID;
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_INIT;
ec_datagram_init(&voe->datagram);
if (ec_datagram_prealloc(&voe->datagram, size + 6))
return -1;
return 0;
}
/*****************************************************************************/
/** VoE handler destructor.
*/
void ec_voe_handler_clear(
ec_voe_handler_t *voe /**< VoE handler. */
)
{
ec_datagram_clear(&voe->datagram);
}
/*****************************************************************************
* Application interface.
****************************************************************************/
uint8_t *ecrt_voe_handler_data(ec_voe_handler_t *voe)
{
return voe->datagram.data + 6;
}
/*****************************************************************************/
size_t ecrt_voe_handler_data_size(const ec_voe_handler_t *voe)
{
return voe->data_size;
}
/*****************************************************************************/
void ecrt_voe_handler_read(ec_voe_handler_t *voe)
{
voe->dir = EC_DIR_INPUT;
voe->state = ec_voe_handler_state_read_start;
voe->request_state = EC_INT_REQUEST_QUEUED;
}
/*****************************************************************************/
void ecrt_voe_handler_write(ec_voe_handler_t *voe, size_t size)
{
voe->dir = EC_DIR_OUTPUT;
voe->datagram.data_size = size + 6;
voe->state = ec_voe_handler_state_write_start;
voe->request_state = EC_INT_REQUEST_QUEUED;
}
/*****************************************************************************/
ec_request_state_t ecrt_voe_handler_execute(ec_voe_handler_t *voe)
{
if (voe->config->slave) {
voe->state(voe);
if (voe->request_state == EC_REQUEST_BUSY)
ec_master_queue_datagram(voe->config->master, &voe->datagram);
} else {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
}
return ec_request_state_translation_table[voe->request_state];
}
/******************************************************************************
* State functions.
*****************************************************************************/
void ec_voe_handler_state_write_start(ec_voe_handler_t *voe)
{
ec_slave_t *slave = voe->config->slave;
uint8_t *data;
if (slave->master->debug_level) {
EC_DBG("Writing %u bytes of VoE data to slave %u.\n",
voe->data_size, slave->ring_position);
ec_print_data(ecrt_voe_handler_data(voe), voe->data_size);
}
if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
if (!(data = ec_slave_mbox_prepare_send(
slave, &voe->datagram, 0x01, voe->data_size))) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
voe->retries = EC_FSM_RETRIES;
voe->jiffies_start = jiffies;
voe->state = ec_voe_handler_state_write_response;
}
/*****************************************************************************/
void ec_voe_handler_state_write_response(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Failed to receive VoE write request datagram for"
" slave %u (datagram state %u).\n",
slave->ring_position, datagram->state);
return;
}
if (datagram->working_counter != 1) {
if (!datagram->working_counter) {
unsigned long diff_ms =
(jiffies - voe->jiffies_start) * 1000 / HZ;
if (diff_ms < EC_VOE_RESPONSE_TIMEOUT) {
if (slave->master->debug_level) {
EC_DBG("Slave %u did not respond to VoE write request. "
"Retrying after %u ms...\n",
slave->ring_position, (u32) diff_ms);
}
// no response; send request datagram again
return;
}
}
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Reception of VoE write request failed on slave %u: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
if (voe->config->master->debug_level)
EC_DBG("VoE write request successful.\n");
voe->request_state = EC_INT_REQUEST_SUCCESS;
voe->state = ec_voe_handler_state_end;
}
/*****************************************************************************/
void ec_voe_handler_state_read_start(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
if (slave->master->debug_level)
EC_DBG("Reading VoE data to slave %u.\n", slave->ring_position);
if (!(slave->sii.mailbox_protocols & EC_MBOX_VOE)) {
EC_ERR("Slave %u does not support VoE!\n", slave->ring_position);
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
voe->jiffies_start = jiffies;
voe->retries = EC_FSM_RETRIES;
voe->state = ec_voe_handler_state_read_check;
}
/*****************************************************************************/
void ec_voe_handler_state_read_check(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Failed to receive VoE mailbox check datagram from slave %u"
" (datagram state %u).\n",
slave->ring_position, datagram->state);
return;
}
if (datagram->working_counter != 1) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Reception of VoE mailbox check"
" datagram failed on slave %u: ", slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
if (!ec_slave_mbox_check(datagram)) {
unsigned long diff_ms =
(datagram->jiffies_received - voe->jiffies_start) * 1000 / HZ;
if (diff_ms >= EC_VOE_RESPONSE_TIMEOUT) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Timeout while waiting for VoE data on "
"slave %u.\n", slave->ring_position);
return;
}
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
voe->retries = EC_FSM_RETRIES;
return;
}
// Fetch response
ec_slave_mbox_prepare_fetch(slave, datagram); // can not fail.
voe->retries = EC_FSM_RETRIES;
voe->state = ec_voe_handler_state_read_response;
}
/*****************************************************************************/
void ec_voe_handler_state_read_response(ec_voe_handler_t *voe)
{
ec_datagram_t *datagram = &voe->datagram;
ec_slave_t *slave = voe->config->slave;
ec_master_t *master = voe->config->master;
uint8_t *data, mbox_prot;
size_t rec_size;
if (datagram->state == EC_DATAGRAM_TIMED_OUT && voe->retries--)
return;
if (datagram->state != EC_DATAGRAM_RECEIVED) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Failed to receive VoE read datagram for"
" slave %u (datagram state %u).\n",
slave->ring_position, datagram->state);
return;
}
if (datagram->working_counter != 1) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_ERR("Reception of VoE read response failed on slave %u: ",
slave->ring_position);
ec_datagram_print_wc_error(datagram);
return;
}
if (!(data = ec_slave_mbox_fetch(slave, datagram,
&mbox_prot, &rec_size))) {
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
return;
}
if (mbox_prot != 0x01) { // VoE
voe->state = ec_voe_handler_state_error;
voe->request_state = EC_INT_REQUEST_FAILURE;
EC_WARN("Received mailbox protocol 0x%02X as response.\n", mbox_prot);
ec_print_data(data, rec_size);
return;
}
if (master->debug_level) {
EC_DBG("VoE data:\n");
ec_print_data(data, rec_size);
}
voe->data_size = rec_size;
voe->request_state = EC_INT_REQUEST_SUCCESS;
voe->state = ec_voe_handler_state_end; // success
}
/*****************************************************************************/
void ec_voe_handler_state_end(ec_voe_handler_t *voe)
{
}
/*****************************************************************************/
void ec_voe_handler_state_error(ec_voe_handler_t *voe)
{
}
/*****************************************************************************/
/** \cond */
EXPORT_SYMBOL(ecrt_voe_handler_data);
EXPORT_SYMBOL(ecrt_voe_handler_data_size);
EXPORT_SYMBOL(ecrt_voe_handler_read);
EXPORT_SYMBOL(ecrt_voe_handler_write);
EXPORT_SYMBOL(ecrt_voe_handler_execute);
/** \endcond */
/*****************************************************************************/

74
master/voe_handler.h Normal file
View File

@@ -0,0 +1,74 @@
/******************************************************************************
*
* $Id$
*
* Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
* The IgH EtherCAT Master is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The IgH EtherCAT Master is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with the IgH EtherCAT Master; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The right to use EtherCAT Technology is granted and comes free of
* charge under condition of compatibility of product made by
* Licensee. People intending to distribute/sell products based on the
* code, have to sign an agreement to guarantee that products using
* software based on IgH EtherCAT master stay compatible with the actual
* EtherCAT specification (which are released themselves as an open
* standard) as the (only) precondition to have the right to use EtherCAT
* Technology, IP and trade marks.
*
*****************************************************************************/
/**
\file
Vendor-specific-over-EtherCAT protocol handler.
*/
/*****************************************************************************/
#ifndef __EC_VOE_HANDLER_H__
#define __EC_VOE_HANDLER_H__
#include <linux/list.h>
#include "globals.h"
#include "datagram.h"
/*****************************************************************************/
/** Vendor-specific-over-EtherCAT handler.
*/
struct ec_voe_handler {
struct list_head list; /**< List item. */
ec_slave_config_t *config; /**< Parent slave configuration. */
ec_datagram_t datagram; /**< State machine datagram. */
size_t data_size; /**< Size of Sdo data. */
ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means writing to
the slave, EC_DIR_INPUT means reading from the
slave. */
void (*state)(ec_voe_handler_t *); /**< State function */
ec_internal_request_state_t request_state; /**< Handler state. */
unsigned int retries; /**< retries upon datagram timeout */
unsigned long jiffies_start; /**< Timestamp for timeout calculation. */
};
/*****************************************************************************/
int ec_voe_handler_init(ec_voe_handler_t *, ec_slave_config_t *, size_t);
void ec_voe_handler_clear(ec_voe_handler_t *);
/*****************************************************************************/
#endif