Basic reading realtime Sdo access working.

This commit is contained in:
Florian Pose
2008-03-04 09:57:36 +00:00
parent 421d1cf381
commit e90dab2a4e
14 changed files with 292 additions and 51 deletions

View File

@@ -41,10 +41,13 @@
/*****************************************************************************/
// module parameters
// Module parameters
#define FREQUENCY 100
// Optional features
#define CONFIGURE_MAPPING
#define EXTERNAL_MEMORY
#define SDO_ACCESS
#define PFX "ec_mini: "
@@ -112,6 +115,13 @@ static ec_pdo_info_t el2004_mapping[] = {
/*****************************************************************************/
#ifdef SDO_ACCESS
static ec_sdo_request_t *sdo;
static int not_first_time = 0;
#endif
/*****************************************************************************/
void check_domain1_state(void)
{
ec_domain_state_t ds;
@@ -155,6 +165,32 @@ void check_master_state(void)
/*****************************************************************************/
#ifdef SDO_ACCESS
void read_sdo(void)
{
switch (ecrt_sdo_request_state(sdo)) {
case EC_REQUEST_COMPLETE:
if (not_first_time) {
printk(KERN_INFO PFX "Sdo value: 0x%04X\n",
EC_READ_U16(ecrt_sdo_request_data(sdo)));
} else {
not_first_time = 1;
}
ecrt_sdo_request_read(sdo);
break;
case EC_REQUEST_FAILURE:
printk(KERN_INFO PFX "Failed to read Sdo!\n");
ecrt_sdo_request_read(sdo);
break;
default:
printk(KERN_INFO PFX "Still busy...\n");
break;
}
}
#endif
/*****************************************************************************/
void cyclic_task(unsigned long data)
{
// receive process data
@@ -168,7 +204,7 @@ void cyclic_task(unsigned long data)
if (counter) {
counter--;
} else { // do this at FREQUENCY
} else { // do this at 1 Hz
counter = FREQUENCY;
// calculate new process data
@@ -176,6 +212,11 @@ void cyclic_task(unsigned long data)
// check for master state (optional)
check_master_state();
#ifdef SDO_ACCESS
// read process data Sdo
read_sdo();
#endif
}
// write process data
@@ -256,6 +297,19 @@ int __init init_mini_module(void)
}
#endif
#ifdef SDO_ACCESS
printk(KERN_INFO PFX "Creating Sdo requests...\n");
if (!(sc = ecrt_master_slave_config(master, 0, 1, Beckhoff_EL3162))) {
printk(KERN_ERR PFX "Failed to get slave configuration.\n");
goto out_release_master;
}
if (!(sdo = ecrt_slave_config_create_sdo_request(sc, 0x3102, 2, 2))) {
printk(KERN_ERR PFX "Failed to create Sdo request.\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

@@ -131,6 +131,9 @@ typedef struct ec_slave_config ec_slave_config_t; /**< \see ec_slave_config */
struct ec_domain;
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. */
/*****************************************************************************/
/** Bus state.
@@ -248,6 +251,28 @@ typedef struct {
offset in the process data. */
} ec_pdo_entry_reg_t;
/*****************************************************************************/
/** Generic request state.
*/
typedef enum {
EC_REQUEST_QUEUED,
EC_REQUEST_IN_PROGRESS,
EC_REQUEST_COMPLETE,
EC_REQUEST_FAILURE
} ec_request_state_t;
/*****************************************************************************/
/** Sdo request error.
*
* This is used as return type of ecrt_sdo_request_error().
*/
typedef enum {
EC_SDO_REQUEST_SUCCESS, /**< There is no error. */
EC_SDO_REQUEST_TIMEOUT, /**< The request timed out. */
} ec_sdo_request_error_t;
/******************************************************************************
* Global functions
*****************************************************************************/
@@ -513,6 +538,18 @@ int ecrt_slave_config_sdo32(
uint32_t value /**< Value to set. */
);
/** Create an Sdo request to exchange Sdos during realtime operation.
*
* The created Sdo request object is freed automatically when the master is
* released.
*/
ec_sdo_request_t *ecrt_slave_config_create_sdo_request(
ec_slave_config_t *sc, /**< Slave configuration. */
uint16_t index, /**< Sdo index. */
uint8_t subindex, /**< Sdo subindex. */
size_t size /**< Data size to reserve. */
);
/** Outputs the state of the slave configuration.
*
* Stores the state information in the given \a state structure.
@@ -599,6 +636,62 @@ void ecrt_domain_state(
information. */
);
/*****************************************************************************
* Sdo request methods.
****************************************************************************/
/** Set the timeout for an Sdo request.
*
* If the request cannot be processed in the specified time, if will be marked
* as failed.
*/
void ecrt_sdo_request_timeout(
ec_sdo_request_t *req, /**< Sdo request. */
uint32_t timeout /**< Timeout in milliseconds. */
);
/** Access to the Sdo request's data.
*
* \attention The return value is invalid during (ecrt_sdo_request_state() !=
* EC_REQUEST_COMPLETE) a read operation, because the internal Sdo data
* memory could be re-allocated.
*
* \return Pointer to the internal Sdo data memory.
*/
uint8_t *ecrt_sdo_request_data(
ec_sdo_request_t *req /**< Sdo request. */
);
/** Get the current state of the Sdo request.
*
* \return Request state.
*/
ec_request_state_t ecrt_sdo_request_state(
const ec_sdo_request_t *req /**< Sdo request. */
);
/** Get the error code of the Sdo request.
*/
ec_sdo_request_error_t ecrt_sdo_request_error(
const ec_sdo_request_t *req /**< Sdo request. */
);
/** Schedule an Sdo write operation.
*/
void ecrt_sdo_request_write(
ec_sdo_request_t *req /**< Sdo request. */
);
/** Schedule an Sdo read operation .
*
* \attention After calling this function, the return value of
* ecrt_sdo_request_data() will be invalid until ecrt_sdo_request_state()
* is EC_REQUEST_COMPLETE.
*/
void ecrt_sdo_request_read(
ec_sdo_request_t *req /**< Sdo request. */
);
/******************************************************************************
* Bitwise read/write macros
*****************************************************************************/

View File

@@ -182,7 +182,7 @@ void ec_fsm_coe_map_action_next_dir(
ec_pdo_mapping_clear_pdos(&fsm->mapping);
ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index, 0);
ec_sdo_request_read(&fsm->request);
ecrt_sdo_request_read(&fsm->request);
fsm->state = ec_fsm_coe_map_state_pdo_count;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
@@ -238,7 +238,7 @@ void ec_fsm_coe_map_action_next_pdo(
if (fsm->sync_subindex <= fsm->sync_subindices) {
ec_sdo_request_address(&fsm->request, fsm->sync_sdo_index,
fsm->sync_subindex);
ec_sdo_request_read(&fsm->request);
ecrt_sdo_request_read(&fsm->request);
fsm->state = ec_fsm_coe_map_state_pdo;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
@@ -295,7 +295,7 @@ void ec_fsm_coe_map_state_pdo(
list_add_tail(&fsm->pdo->list, &fsm->mapping.pdos);
ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
ec_sdo_request_read(&fsm->request);
ecrt_sdo_request_read(&fsm->request);
fsm->state = ec_fsm_coe_map_state_pdo_entry_count;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately
@@ -342,7 +342,7 @@ void ec_fsm_coe_map_action_next_pdo_entry(
{
if (fsm->pdo_subindex <= fsm->pdo_subindices) {
ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->pdo_subindex);
ec_sdo_request_read(&fsm->request);
ecrt_sdo_request_read(&fsm->request);
fsm->state = ec_fsm_coe_map_state_pdo_entry;
ec_fsm_coe_upload(fsm->fsm_coe, fsm->slave, &fsm->request);
ec_fsm_coe_exec(fsm->fsm_coe); // execute immediately

View File

@@ -41,6 +41,7 @@
#include "globals.h"
#include "master.h"
#include "mailbox.h"
#include "slave_config.h"
#ifdef EC_EOE
#include "ethernet.h"
#endif
@@ -376,9 +377,39 @@ int ec_fsm_master_action_process_sdo(
{
ec_master_t *master = fsm->master;
ec_master_sdo_request_t *request;
ec_sdo_request_t *req;
ec_slave_t *slave;
// search the first request to be processed
// search for internal requests to be processed
list_for_each_entry(slave, &master->slaves, list) {
if (!slave->config)
continue;
list_for_each_entry(req, &slave->config->sdo_requests, list) {
if (req->state == EC_REQUEST_QUEUED) {
req->state = EC_REQUEST_IN_PROGRESS;
if (slave->current_state == EC_SLAVE_STATE_INIT ||
slave->error_flag) {
req->state = EC_REQUEST_FAILURE;
continue;
}
if (master->debug_level)
EC_DBG("Processing Sdo request for slave %u...\n",
slave->ring_position);
fsm->idle = 0;
fsm->sdo_request = req;
fsm->slave = slave;
fsm->state = ec_fsm_master_state_sdo_request;
ec_fsm_coe_upload(&fsm->fsm_coe, slave, req);
ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
return 1;
}
}
}
// search the first external request to be processed
while (1) {
down(&master->sdo_sem);
if (list_empty(&master->slave_sdo_requests)) {
@@ -410,7 +441,8 @@ int ec_fsm_master_action_process_sdo(
// Start uploading Sdo
fsm->idle = 0;
fsm->sdo_request = request;
fsm->sdo_request = &request->req;
fsm->slave = slave;
fsm->state = ec_fsm_master_state_sdo_request;
ec_fsm_coe_upload(&fsm->fsm_coe, slave, &request->req);
ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
@@ -499,7 +531,7 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm
return;
}
// Check for a pending Sdo request
// Check for pending Sdo requests
if (ec_fsm_master_action_process_sdo(fsm))
return;
@@ -1026,25 +1058,25 @@ void ec_fsm_master_state_sdodict(ec_fsm_master_t *fsm /**< master state machine
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *fsm /**< master state machine */)
{
ec_master_t *master = fsm->master;
ec_master_sdo_request_t *request = fsm->sdo_request;
ec_sdo_request_t *request = fsm->sdo_request;
if (ec_fsm_coe_exec(&fsm->fsm_coe)) return;
if (!ec_fsm_coe_success(&fsm->fsm_coe)) {
EC_DBG("Failed to process Sdo request for slave %i.\n",
EC_DBG("Failed to process Sdo request for slave %u.\n",
fsm->slave->ring_position);
request->req.state = EC_REQUEST_FAILURE;
request->state = EC_REQUEST_FAILURE;
wake_up(&master->sdo_queue);
fsm->state = ec_fsm_master_state_error;
return;
}
// Sdo request finished
request->req.state = EC_REQUEST_COMPLETE;
request->state = EC_REQUEST_COMPLETE;
wake_up(&master->sdo_queue);
if (master->debug_level)
EC_DBG("Finished Sdo request for slave %i.\n",
EC_DBG("Finished Sdo request for slave %u.\n",
fsm->slave->ring_position);
// check for another Sdo request

View File

@@ -97,7 +97,7 @@ struct ec_fsm_master {
ec_slave_t *slave; /**< current slave */
ec_eeprom_write_request_t *eeprom_request; /**< EEPROM write request */
off_t eeprom_index; /**< index to EEPROM write request data */
ec_master_sdo_request_t *sdo_request; /**< Sdo request to process. */
ec_sdo_request_t *sdo_request; /**< Sdo request to process. */
ec_fsm_slave_config_t fsm_slave_config; /**< slave state machine */
ec_fsm_slave_scan_t fsm_slave_scan; /**< slave state machine */

View File

@@ -214,7 +214,7 @@ void ec_fsm_pdo_config_next_pdo(
EC_WRITE_U8(&fsm->request.data, 0);
fsm->request.data_size = 1;
ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Setting entry count to zero for Pdo 0x%04X.\n",
fsm->pdo->index);
@@ -254,7 +254,7 @@ void ec_fsm_pdo_config_add_entry(
EC_WRITE_U32(&fsm->request.data, value);
fsm->request.data_size = 4;
ec_sdo_request_address(&fsm->request, fsm->pdo->index, fsm->entry_count);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Configuring Pdo entry %08X at position %u.\n",
value, fsm->entry_count);
@@ -320,7 +320,7 @@ void ec_fsm_pdo_config_state_add_entry(
EC_WRITE_U8(&fsm->request.data, fsm->entry_count);
fsm->request.data_size = 1;
ec_sdo_request_address(&fsm->request, fsm->pdo->index, 0);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Setting number of Pdo entries to %u.\n",
fsm->entry_count);

View File

@@ -205,7 +205,7 @@ void ec_fsm_pdo_mapping_next_dir(
EC_WRITE_U8(&fsm->request.data, 0); // zero Pdos mapped
fsm->request.data_size = 1;
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Setting Pdo count to zero for SM%u.\n", fsm->sync->index);
@@ -248,7 +248,7 @@ void ec_fsm_pdo_mapping_add_pdo(
fsm->request.data_size = 2;
ec_sdo_request_address(&fsm->request,
0x1C10 + fsm->sync->index, fsm->pdo_count);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Mapping Pdo 0x%04X at position %u.\n",
fsm->pdo->index, fsm->pdo_count);
@@ -314,7 +314,7 @@ void ec_fsm_pdo_mapping_state_add_pdo(
EC_WRITE_U8(&fsm->request.data, fsm->pdo_count);
fsm->request.data_size = 1;
ec_sdo_request_address(&fsm->request, 0x1C10 + fsm->sync->index, 0);
ec_sdo_request_write(&fsm->request);
ecrt_sdo_request_write(&fsm->request);
if (fsm->slave->master->debug_level)
EC_DBG("Setting number of mapped Pdos to %u.\n",
fsm->pdo_count);

View File

@@ -450,7 +450,7 @@ void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *fsm /**< slave st
fsm->state = ec_fsm_slave_config_state_sdo_conf;
fsm->request = list_entry(fsm->slave->config->sdo_configs.next,
ec_sdo_request_t, list);
ec_sdo_request_write(fsm->request);
ecrt_sdo_request_write(fsm->request);
ec_fsm_coe_download(&fsm->fsm_coe, fsm->slave, fsm->request);
ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
}
@@ -479,7 +479,7 @@ void ec_fsm_slave_config_state_sdo_conf(
if (fsm->request->list.next != &fsm->slave->config->sdo_configs) {
fsm->request = list_entry(fsm->request->list.next, ec_sdo_request_t,
list);
ec_sdo_request_write(fsm->request);
ecrt_sdo_request_write(fsm->request);
ec_fsm_coe_download(&fsm->fsm_coe, fsm->slave, fsm->request);
ec_fsm_coe_exec(&fsm->fsm_coe); // execute immediately
return;

View File

@@ -191,17 +191,6 @@ typedef struct {
/*****************************************************************************/
/** Master request state.
*/
typedef enum {
EC_REQUEST_QUEUED,
EC_REQUEST_IN_PROGRESS,
EC_REQUEST_COMPLETE,
EC_REQUEST_FAILURE
} ec_request_state_t;
/*****************************************************************************/
/** Origin type.
*/
typedef enum {

View File

@@ -269,7 +269,7 @@ ssize_t ec_sdo_entry_read_value(
request.slave = entry->sdo->slave;
ec_sdo_request_init(&request.req);
ec_sdo_request_address(&request.req, entry->sdo->index, entry->subindex);
ec_sdo_request_read(&request.req);
ecrt_sdo_request_read(&request.req);
// schedule request.
down(&master->sdo_sem);

View File

@@ -148,26 +148,54 @@ int ec_sdo_request_copy_data(
return 0;
}
/*****************************************************************************
* Realtime interface.
****************************************************************************/
void ecrt_sdo_request_timeout(ec_sdo_request_t *req, uint32_t timeout)
{
}
/*****************************************************************************/
/** Start an Sdo read operation (Sdo upload).
*/
void ec_sdo_request_read(
ec_sdo_request_t *req /**< Sdo request. */
)
uint8_t *ecrt_sdo_request_data(ec_sdo_request_t *req)
{
return req->data;
}
/*****************************************************************************/
ec_request_state_t ecrt_sdo_request_state(const ec_sdo_request_t *req)
{
return req->state;
}
/*****************************************************************************/
ec_sdo_request_error_t ecrt_sdo_request_error(const ec_sdo_request_t *req)
{
return EC_SDO_REQUEST_SUCCESS; // FIXME
}
/*****************************************************************************/
void ecrt_sdo_request_read(ec_sdo_request_t *req)
{
req->state = EC_REQUEST_QUEUED;
}
/*****************************************************************************/
/** Start an Sdo write operation (Sdo download).
*/
void ec_sdo_request_write(
ec_sdo_request_t *req /**< Sdo request. */
)
void ecrt_sdo_request_write(ec_sdo_request_t *req)
{
req->state = EC_REQUEST_QUEUED;
}
/*****************************************************************************/
EXPORT_SYMBOL(ecrt_sdo_request_timeout);
EXPORT_SYMBOL(ecrt_sdo_request_data);
EXPORT_SYMBOL(ecrt_sdo_request_state);
EXPORT_SYMBOL(ecrt_sdo_request_error);
EXPORT_SYMBOL(ecrt_sdo_request_read);
EXPORT_SYMBOL(ecrt_sdo_request_write);

View File

@@ -43,13 +43,15 @@
#include <linux/list.h>
#include "../include/ecrt.h"
#include "globals.h"
/*****************************************************************************/
/** CANopen Sdo request.
*/
typedef struct {
struct ec_sdo_request {
struct list_head list; /**< List item. */
uint16_t index; /**< Sdo index. */
uint8_t subindex; /**< Sdo subindex. */
@@ -57,7 +59,7 @@ typedef struct {
size_t mem_size; /**< Size of Sdo data memory. */
size_t data_size; /**< Size of Sdo data. */
ec_request_state_t state; /**< Sdo request state. */
} ec_sdo_request_t;
};
/*****************************************************************************/
@@ -68,9 +70,6 @@ void ec_sdo_request_address(ec_sdo_request_t *, uint16_t, uint8_t);
int ec_sdo_request_alloc(ec_sdo_request_t *, size_t);
int ec_sdo_request_copy_data(ec_sdo_request_t *, const uint8_t *, size_t);
void ec_sdo_request_read(ec_sdo_request_t *);
void ec_sdo_request_write(ec_sdo_request_t *);
/*****************************************************************************/
#endif

View File

@@ -105,6 +105,7 @@ int ec_slave_config_init(ec_slave_config_t *sc, /**< Slave configuration. */
ec_pdo_mapping_init(&sc->mapping[dir]);
INIT_LIST_HEAD(&sc->sdo_configs);
INIT_LIST_HEAD(&sc->sdo_requests);
sc->used_fmmus = 0;
@@ -174,6 +175,13 @@ void ec_slave_config_clear(struct kobject *kobj /**< kobject of the config. */)
kfree(req);
}
// free all Sdo requests
list_for_each_entry_safe(req, next_req, &sc->sdo_requests, list) {
list_del(&req->list);
ec_sdo_request_clear(req);
kfree(req);
}
kfree(sc);
}
@@ -276,6 +284,16 @@ ssize_t ec_slave_config_info(
buf += sprintf(buf, "\n");
}
// type-cast to avoid warnings on some compilers
if (!list_empty((struct list_head *) &sc->sdo_requests)) {
buf += sprintf(buf, "\nSdo requests:\n");
list_for_each_entry(req, &sc->sdo_requests, list) {
buf += sprintf(buf, " 0x%04X:%u\n", req->index, req->subindex);
}
buf += sprintf(buf, "\n");
}
return buf - buffer;
}
@@ -672,6 +690,32 @@ int ecrt_slave_config_sdo32(ec_slave_config_t *slave, uint16_t index,
/*****************************************************************************/
ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
uint16_t index, uint8_t subindex, size_t size)
{
ec_sdo_request_t *req;
if (!(req = (ec_sdo_request_t *)
kmalloc(sizeof(ec_sdo_request_t), GFP_KERNEL))) {
EC_ERR("Failed to allocate Sdo request memory!\n");
return NULL;
}
ec_sdo_request_init(req);
ec_sdo_request_address(req, index, subindex);
if (ec_sdo_request_alloc(req, size)) {
ec_sdo_request_clear(req);
kfree(req);
return NULL;
}
list_add_tail(&req->list, &sc->sdo_requests);
return req;
}
/*****************************************************************************/
/** \cond */
EXPORT_SYMBOL(ecrt_slave_config_pdo);
@@ -681,6 +725,7 @@ EXPORT_SYMBOL(ecrt_slave_config_reg_pdo_entry);
EXPORT_SYMBOL(ecrt_slave_config_sdo8);
EXPORT_SYMBOL(ecrt_slave_config_sdo16);
EXPORT_SYMBOL(ecrt_slave_config_sdo32);
EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request);
/** \endcond */

View File

@@ -71,7 +71,8 @@ struct ec_slave_config {
ec_pdo_mapping_t mapping[2]; /**< Output and input Pdo mapping. */
struct list_head sdo_configs; /**< Sdo configurations. */
struct list_head sdo_configs; /**< List of Sdo configurations. */
struct list_head sdo_requests; /**< List of Sdo requests. */
ec_fmmu_config_t fmmu_configs[EC_MAX_FMMUS]; /**< FMMU configurations. */
uint8_t used_fmmus; /**< Number of FMMUs used. */