Renamed EEPROM to SII.

This commit is contained in:
Florian Pose 2008-03-17 09:38:48 +00:00
parent 77c29c0418
commit f69b21af02
13 changed files with 197 additions and 194 deletions

2
NEWS
View File

@ -64,6 +64,8 @@ Changes in version 1.4.0:
* Added MODPROBE_FLAGS variable in start script and sysconfig file.
* Implemented missing datagram types.
* Allow multiple sync manager categories in SII.
* Changed all occurrences of 'EEPROM' to 'SII', renamed the eeprom sysfs file
to sii, in particular.
-------------------------------------------------------------------------------

View File

@ -6,7 +6,7 @@ digraph master {
center=1
ratio=fill
action_process_eeprom [shape=point,label=""]
action_process_sii [shape=point,label=""]
action_process_sdo [shape=point,label=""]
action_configure [shape=point,label=""]
action_next_slave_state [shape=point,label=""]
@ -20,7 +20,7 @@ digraph master {
broadcast -> clear_addresses
broadcast -> read_states [weight=10]
action_process_eeprom -> write_eeprom
action_process_sii -> write_sii
action_process_sdo -> sdo_request
@ -29,7 +29,7 @@ digraph master {
action_process_states -> action_configure
action_process_states -> action_process_sdo
action_process_states -> sdodict
action_process_states -> action_process_eeprom
action_process_states -> action_process_sii
action_process_states -> end
action_next_slave_state -> read_states
@ -66,9 +66,9 @@ digraph master {
configure_slave -> action_configure
configure_slave -> end
//write_eeprom -> error
write_eeprom -> action_process_eeprom
write_eeprom -> end
//write_sii -> error
write_sii -> action_process_sii
write_sii -> end
//sdodict -> error
sdodict -> end

View File

@ -18,11 +18,11 @@ digraph slavescan {
base -> datalink [weight=10]
datalink -> error
datalink -> eeprom_size [weight=10]
datalink -> sii_size [weight=10]
eeprom_size -> error
eeprom_size -> eeprom_data [weight=10]
sii_size -> error
sii_size -> sii_data [weight=10]
eeprom_data -> error
eeprom_data -> end [weight=10]
sii_data -> error
sii_data -> end [weight=10]
}

View File

@ -60,7 +60,7 @@ void ec_fsm_master_state_rewrite_addresses(ec_fsm_master_t *);
void ec_fsm_master_state_configure_slave(ec_fsm_master_t *);
void ec_fsm_master_state_clear_addresses(ec_fsm_master_t *);
void ec_fsm_master_state_scan_slaves(ec_fsm_master_t *);
void ec_fsm_master_state_write_eeprom(ec_fsm_master_t *);
void ec_fsm_master_state_write_sii(ec_fsm_master_t *);
void ec_fsm_master_state_sdodict(ec_fsm_master_t *);
void ec_fsm_master_state_sdo_request(ec_fsm_master_t *);
void ec_fsm_master_state_end(ec_fsm_master_t *);
@ -313,50 +313,50 @@ void ec_fsm_master_state_broadcast(ec_fsm_master_t *fsm /**< master state machin
/*****************************************************************************/
/**
* Check for pending EEPROM write requests and process one.
* \return non-zero, if an EEPROM write request is processed.
* Check for pending SII write requests and process one.
* \return non-zero, if an SII write request is processed.
*/
int ec_fsm_master_action_process_eeprom(
int ec_fsm_master_action_process_sii(
ec_fsm_master_t *fsm /**< master state machine */
)
{
ec_master_t *master = fsm->master;
ec_eeprom_write_request_t *request;
ec_sii_write_request_t *request;
ec_slave_t *slave;
// search the first request to be processed
while (1) {
down(&master->eeprom_sem);
if (list_empty(&master->eeprom_requests)) {
up(&master->eeprom_sem);
down(&master->sii_sem);
if (list_empty(&master->sii_requests)) {
up(&master->sii_sem);
break;
}
// get first request
request = list_entry(master->eeprom_requests.next,
ec_eeprom_write_request_t, list);
request = list_entry(master->sii_requests.next,
ec_sii_write_request_t, list);
list_del_init(&request->list); // dequeue
request->state = EC_REQUEST_BUSY;
up(&master->eeprom_sem);
up(&master->sii_sem);
slave = request->slave;
if (slave->online_state == EC_SLAVE_OFFLINE) {
EC_ERR("Discarding EEPROM data, slave %i offline.\n",
EC_ERR("Discarding SII data, slave %i offline.\n",
slave->ring_position);
request->state = EC_REQUEST_FAILURE;
wake_up(&master->eeprom_queue);
wake_up(&master->sii_queue);
continue;
}
// found pending EEPROM write operation. execute it!
// found pending SII write operation. execute it!
if (master->debug_level)
EC_DBG("Writing EEPROM data to slave %i...\n",
EC_DBG("Writing SII data to slave %i...\n",
slave->ring_position);
fsm->eeprom_request = request;
fsm->eeprom_index = 0;
fsm->sii_request = request;
fsm->sii_index = 0;
ec_fsm_sii_write(&fsm->fsm_sii, request->slave, request->word_offset,
request->data, EC_FSM_SII_USE_CONFIGURED_ADDRESS);
fsm->state = ec_fsm_master_state_write_eeprom;
fsm->state = ec_fsm_master_state_write_sii;
fsm->state(fsm); // execute immediately
return 1;
}
@ -562,9 +562,9 @@ void ec_fsm_master_action_process_states(ec_fsm_master_t *fsm
return;
}
// check for pending EEPROM write operations.
if (ec_fsm_master_action_process_eeprom(fsm))
return; // EEPROM write request found
// check for pending SII write operations.
if (ec_fsm_master_action_process_sii(fsm))
return; // SII write request found
}
fsm->state = ec_fsm_master_state_end;
@ -971,49 +971,49 @@ void ec_fsm_master_state_configure_slave(ec_fsm_master_t *fsm
/*****************************************************************************/
/**
Master state: WRITE EEPROM.
Master state: WRITE SII.
*/
void ec_fsm_master_state_write_eeprom(
void ec_fsm_master_state_write_sii(
ec_fsm_master_t *fsm /**< master state machine */)
{
ec_master_t *master = fsm->master;
ec_eeprom_write_request_t *request = fsm->eeprom_request;
ec_sii_write_request_t *request = fsm->sii_request;
ec_slave_t *slave = request->slave;
if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
slave->error_flag = 1;
EC_ERR("Failed to write EEPROM data to slave %i.\n",
EC_ERR("Failed to write SII data to slave %i.\n",
slave->ring_position);
request->state = EC_REQUEST_FAILURE;
wake_up(&master->eeprom_queue);
wake_up(&master->sii_queue);
fsm->state = ec_fsm_master_state_error;
return;
}
fsm->eeprom_index++;
if (fsm->eeprom_index < request->word_size) {
fsm->sii_index++;
if (fsm->sii_index < request->word_size) {
ec_fsm_sii_write(&fsm->fsm_sii, slave,
request->word_offset + fsm->eeprom_index,
request->data + fsm->eeprom_index * 2,
request->word_offset + fsm->sii_index,
request->data + fsm->sii_index * 2,
EC_FSM_SII_USE_CONFIGURED_ADDRESS);
ec_fsm_sii_exec(&fsm->fsm_sii); // execute immediately
return;
}
// finished writing EEPROM
// finished writing SII
if (master->debug_level)
EC_DBG("Finished writing %u words of EEPROM data to slave %u.\n",
EC_DBG("Finished writing %u words of SII data to slave %u.\n",
request->word_size, slave->ring_position);
request->state = EC_REQUEST_SUCCESS;
wake_up(&master->eeprom_queue);
wake_up(&master->sii_queue);
// TODO: Evaluate new EEPROM contents!
// TODO: Evaluate new SII contents!
// check for another EEPROM write request
if (ec_fsm_master_action_process_eeprom(fsm))
// check for another SII write request
if (ec_fsm_master_action_process_sii(fsm))
return; // processing another request
fsm->state = ec_fsm_master_state_end;

View File

@ -52,7 +52,7 @@
/*****************************************************************************/
/** EEPROM write request.
/** SII write request.
*/
typedef struct {
struct list_head list; /**< list head */
@ -61,7 +61,7 @@ typedef struct {
size_t word_size; /**< data size in words */
const uint8_t *data; /**< pointer to the data */
ec_request_state_t state; /**< state of the request */
} ec_eeprom_write_request_t;
} ec_sii_write_request_t;
/*****************************************************************************/
@ -95,8 +95,8 @@ struct ec_fsm_master {
not meet the initial conditions */
unsigned int config_error; /**< error during slave configuration */
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_sii_write_request_t *sii_request; /**< SII write request */
off_t sii_index; /**< index to SII write request data */
ec_sdo_request_t *sdo_request; /**< Sdo request to process. */
ec_fsm_slave_config_t fsm_slave_config; /**< slave state machine */

View File

@ -46,12 +46,12 @@
/**
* Read/Write timeout. [ms]
*/
#define EEPROM_TIMEOUT 10
#define SII_TIMEOUT 10
/**
* Time before evaluating answer at writing. [ms]
*/
#define EEPROM_INHIBIT 5
#define SII_INHIBIT 5
//#define SII_DEBUG
@ -290,7 +290,7 @@ void ec_fsm_sii_state_read_fetch(
// read operation busy
// still busy... timeout?
if (datagram->cycles_received
- fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
- fsm->cycles_start >= (cycles_t) SII_TIMEOUT * cpu_khz) {
if (fsm->check_once_more) {
fsm->check_once_more = 0;
} else {
@ -426,7 +426,7 @@ void ec_fsm_sii_state_write_check2(
/* FIXME: some slaves never answer with the busy flag set...
* wait a few ms for the write operation to complete. */
if (datagram->cycles_received - fsm->cycles_start
< (cycles_t) EEPROM_INHIBIT * cpu_khz) {
< (cycles_t) SII_INHIBIT * cpu_khz) {
#ifdef SII_DEBUG
EC_DBG("too early.\n");
#endif
@ -439,7 +439,7 @@ void ec_fsm_sii_state_write_check2(
// write operation busy bit
// still busy... timeout?
if (datagram->cycles_received
- fsm->cycles_start >= (cycles_t) EEPROM_TIMEOUT * cpu_khz) {
- fsm->cycles_start >= (cycles_t) SII_TIMEOUT * cpu_khz) {
if (fsm->check_once_more) {
fsm->check_once_more = 0;
} else {

View File

@ -52,8 +52,8 @@ void ec_fsm_slave_scan_state_address(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_state(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_base(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_preop(ec_fsm_slave_scan_t *);
void ec_fsm_slave_scan_state_pdos(ec_fsm_slave_scan_t *);
@ -344,22 +344,22 @@ void ec_fsm_slave_scan_state_datalink(ec_fsm_slave_scan_t *fsm /**< slave state
slave->dl_signal[i] = dl_status & (1 << (9 + i * 2)) ? 1 : 0;
}
// Start fetching EEPROM size
// Start fetching SII size
fsm->sii_offset = EC_FIRST_EEPROM_CATEGORY_OFFSET; // first category header
fsm->sii_offset = EC_FIRST_SII_CATEGORY_OFFSET; // first category header
ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
EC_FSM_SII_USE_CONFIGURED_ADDRESS);
fsm->state = ec_fsm_slave_scan_state_eeprom_size;
fsm->state = ec_fsm_slave_scan_state_sii_size;
fsm->state(fsm); // execute state immediately
}
/*****************************************************************************/
/**
Slave scan state: EEPROM SIZE.
Slave scan state: SII SIZE.
*/
void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
void ec_fsm_slave_scan_state_sii_size(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
{
ec_slave_t *slave = fsm->slave;
uint16_t cat_type, cat_size;
@ -369,7 +369,7 @@ void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *fsm /**< slave sta
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_scan_state_error;
EC_ERR("Failed to read EEPROM size of slave %i.\n",
EC_ERR("Failed to read SII size of slave %i.\n",
slave->ring_position);
return;
}
@ -379,13 +379,13 @@ void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *fsm /**< slave sta
if (cat_type != 0xFFFF) { // not the last category
off_t next_offset = 2UL + fsm->sii_offset + cat_size;
if (next_offset >= EC_MAX_EEPROM_SIZE) {
EC_WARN("EEPROM size of slave %i exceeds"
if (next_offset >= EC_MAX_SII_SIZE) {
EC_WARN("SII size of slave %i exceeds"
" %u words (0xffff limiter missing?).\n",
slave->ring_position, EC_MAX_EEPROM_SIZE);
slave->ring_position, EC_MAX_SII_SIZE);
// cut off category data...
slave->eeprom_size = EC_FIRST_EEPROM_CATEGORY_OFFSET * 2;
goto alloc_eeprom;
slave->sii_size = EC_FIRST_SII_CATEGORY_OFFSET * 2;
goto alloc_sii;
}
fsm->sii_offset = next_offset;
ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
@ -394,28 +394,28 @@ void ec_fsm_slave_scan_state_eeprom_size(ec_fsm_slave_scan_t *fsm /**< slave sta
return;
}
slave->eeprom_size = (fsm->sii_offset + 1) * 2;
slave->sii_size = (fsm->sii_offset + 1) * 2;
alloc_eeprom:
if (slave->eeprom_data) {
EC_WARN("Freeing old EEPROM data on slave %i...\n",
alloc_sii:
if (slave->sii_data) {
EC_WARN("Freeing old SII data on slave %i...\n",
slave->ring_position);
kfree(slave->eeprom_data);
kfree(slave->sii_data);
}
if (!(slave->eeprom_data =
(uint8_t *) kmalloc(slave->eeprom_size, GFP_ATOMIC))) {
EC_ERR("Failed to allocate %u bytes of EEPROM data for slave %u.\n",
slave->eeprom_size, slave->ring_position);
slave->eeprom_size = 0;
if (!(slave->sii_data =
(uint8_t *) kmalloc(slave->sii_size, GFP_ATOMIC))) {
EC_ERR("Failed to allocate %u bytes of SII data for slave %u.\n",
slave->sii_size, slave->ring_position);
slave->sii_size = 0;
slave->error_flag = 1;
fsm->state = ec_fsm_slave_scan_state_error;
return;
}
// Start fetching EEPROM contents
// Start fetching SII contents
fsm->state = ec_fsm_slave_scan_state_eeprom_data;
fsm->state = ec_fsm_slave_scan_state_sii_data;
fsm->sii_offset = 0x0000;
ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
EC_FSM_SII_USE_CONFIGURED_ADDRESS);
@ -425,36 +425,36 @@ alloc_eeprom:
/*****************************************************************************/
/**
Slave scan state: EEPROM DATA.
Slave scan state: SII DATA.
*/
void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
void ec_fsm_slave_scan_state_sii_data(ec_fsm_slave_scan_t *fsm /**< slave state machine */)
{
ec_slave_t *slave = fsm->slave;
uint16_t *cat_word, cat_type, cat_size, eeprom_word_size = slave->eeprom_size / 2;
uint16_t *cat_word, cat_type, cat_size, sii_word_size = slave->sii_size / 2;
if (ec_fsm_sii_exec(&fsm->fsm_sii)) return;
if (!ec_fsm_sii_success(&fsm->fsm_sii)) {
fsm->slave->error_flag = 1;
fsm->state = ec_fsm_slave_scan_state_error;
EC_ERR("Failed to fetch EEPROM contents of slave %i.\n",
EC_ERR("Failed to fetch SII contents of slave %i.\n",
slave->ring_position);
return;
}
// 2 words fetched
if (fsm->sii_offset + 2 <= eeprom_word_size) { // 2 words fit
memcpy(slave->eeprom_data + fsm->sii_offset * 2,
if (fsm->sii_offset + 2 <= sii_word_size) { // 2 words fit
memcpy(slave->sii_data + fsm->sii_offset * 2,
fsm->fsm_sii.value, 4);
}
else { // copy the last word
memcpy(slave->eeprom_data + fsm->sii_offset * 2,
memcpy(slave->sii_data + fsm->sii_offset * 2,
fsm->fsm_sii.value, 2);
}
if (fsm->sii_offset + 2 < eeprom_word_size) {
if (fsm->sii_offset + 2 < sii_word_size) {
// fetch the next 2 words
fsm->sii_offset += 2;
ec_fsm_sii_read(&fsm->fsm_sii, slave, fsm->sii_offset,
@ -463,39 +463,39 @@ void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave sta
return;
}
// Evaluate EEPROM contents
// Evaluate SII contents
ec_slave_clear_sync_managers(slave);
slave->sii.alias =
EC_READ_U16(slave->eeprom_data + 2 * 0x0004);
EC_READ_U16(slave->sii_data + 2 * 0x0004);
slave->sii.vendor_id =
EC_READ_U32(slave->eeprom_data + 2 * 0x0008);
EC_READ_U32(slave->sii_data + 2 * 0x0008);
slave->sii.product_code =
EC_READ_U32(slave->eeprom_data + 2 * 0x000A);
EC_READ_U32(slave->sii_data + 2 * 0x000A);
slave->sii.revision_number =
EC_READ_U32(slave->eeprom_data + 2 * 0x000C);
EC_READ_U32(slave->sii_data + 2 * 0x000C);
slave->sii.serial_number =
EC_READ_U32(slave->eeprom_data + 2 * 0x000E);
EC_READ_U32(slave->sii_data + 2 * 0x000E);
slave->sii.rx_mailbox_offset =
EC_READ_U16(slave->eeprom_data + 2 * 0x0018);
EC_READ_U16(slave->sii_data + 2 * 0x0018);
slave->sii.rx_mailbox_size =
EC_READ_U16(slave->eeprom_data + 2 * 0x0019);
EC_READ_U16(slave->sii_data + 2 * 0x0019);
slave->sii.tx_mailbox_offset =
EC_READ_U16(slave->eeprom_data + 2 * 0x001A);
EC_READ_U16(slave->sii_data + 2 * 0x001A);
slave->sii.tx_mailbox_size =
EC_READ_U16(slave->eeprom_data + 2 * 0x001B);
EC_READ_U16(slave->sii_data + 2 * 0x001B);
slave->sii.mailbox_protocols =
EC_READ_U16(slave->eeprom_data + 2 * 0x001C);
EC_READ_U16(slave->sii_data + 2 * 0x001C);
if (eeprom_word_size == EC_FIRST_EEPROM_CATEGORY_OFFSET) {
// eeprom does not contain category data
if (sii_word_size == EC_FIRST_SII_CATEGORY_OFFSET) {
// sii does not contain category data
fsm->state = ec_fsm_slave_scan_state_end;
return;
}
if (eeprom_word_size < EC_FIRST_EEPROM_CATEGORY_OFFSET + 1) {
EC_ERR("Unexpected end of EEPROM data in slave %u:"
if (sii_word_size < EC_FIRST_SII_CATEGORY_OFFSET + 1) {
EC_ERR("Unexpected end of SII data in slave %u:"
" First category header missing.\n",
slave->ring_position);
goto end;
@ -503,13 +503,13 @@ void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave sta
// evaluate category data
cat_word =
(uint16_t *) slave->eeprom_data + EC_FIRST_EEPROM_CATEGORY_OFFSET;
(uint16_t *) slave->sii_data + EC_FIRST_SII_CATEGORY_OFFSET;
while (EC_READ_U16(cat_word) != 0xFFFF) {
// type and size words must fit
if (cat_word + 2 - (uint16_t *) slave->eeprom_data
> eeprom_word_size) {
EC_ERR("Unexpected end of EEPROM data in slave %u:"
if (cat_word + 2 - (uint16_t *) slave->sii_data
> sii_word_size) {
EC_ERR("Unexpected end of SII data in slave %u:"
" Category header incomplete.\n",
slave->ring_position);
goto end;
@ -519,9 +519,9 @@ void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave sta
cat_size = EC_READ_U16(cat_word + 1);
cat_word += 2;
if (cat_word + cat_size - (uint16_t *) slave->eeprom_data
> eeprom_word_size) {
EC_WARN("Unexpected end of EEPROM data in slave %u:"
if (cat_word + cat_size - (uint16_t *) slave->sii_data
> sii_word_size) {
EC_WARN("Unexpected end of SII data in slave %u:"
" Category data incomplete.\n",
slave->ring_position);
goto end;
@ -562,8 +562,8 @@ void ec_fsm_slave_scan_state_eeprom_data(ec_fsm_slave_scan_t *fsm /**< slave sta
}
cat_word += cat_size;
if (cat_word - (uint16_t *) slave->eeprom_data >= eeprom_word_size) {
EC_WARN("Unexpected end of EEPROM data in slave %u:"
if (cat_word - (uint16_t *) slave->sii_data >= sii_word_size) {
EC_WARN("Unexpected end of SII data in slave %u:"
" Next category header missing.\n",
slave->ring_position);
goto end;

View File

@ -64,8 +64,8 @@
/** Minimum size of a buffer used with ec_state_string(). */
#define EC_STATE_STRING_SIZE 32
/** Maximum EEPROM size in words, to avoid infinite reading. */
#define EC_MAX_EEPROM_SIZE 1024
/** Maximum SII size in words, to avoid infinite reading. */
#define EC_MAX_SII_SIZE 1024
/******************************************************************************
* EtherCAT protocol
@ -87,8 +87,8 @@
#define EC_MAX_DATA_SIZE (ETH_DATA_LEN - EC_FRAME_HEADER_SIZE \
- EC_DATAGRAM_HEADER_SIZE - EC_DATAGRAM_FOOTER_SIZE)
/** Word offset of first EEPROM category. */
#define EC_FIRST_EEPROM_CATEGORY_OFFSET 0x40
/** Word offset of first SII category. */
#define EC_FIRST_SII_CATEGORY_OFFSET 0x40
/** Size of a sync manager configuration page. */
#define EC_SYNC_PAGE_SIZE 8

View File

@ -171,9 +171,9 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->release_cb = NULL;
master->cb_data = NULL;
INIT_LIST_HEAD(&master->eeprom_requests);
init_MUTEX(&master->eeprom_sem);
init_waitqueue_head(&master->eeprom_queue);
INIT_LIST_HEAD(&master->sii_requests);
init_MUTEX(&master->sii_sem);
init_waitqueue_head(&master->sii_queue);
INIT_LIST_HEAD(&master->slave_sdo_requests);
init_MUTEX(&master->sdo_sem);

View File

@ -152,10 +152,10 @@ struct ec_master {
void (*ext_release_cb)(void *); /**< externam lock release callback */
void *ext_cb_data; /**< data parameter of external locking callbacks */
struct list_head eeprom_requests; /**< EEPROM write requests */
struct semaphore eeprom_sem; /**< semaphore protecting the list of
EEPROM write requests */
wait_queue_head_t eeprom_queue; /**< wait queue for EEPROM
struct list_head sii_requests; /**< SII write requests */
struct semaphore sii_sem; /**< semaphore protecting the list of
SII write requests */
wait_queue_head_t sii_queue; /**< wait queue for SII
write requests from user space */
struct list_head slave_sdo_requests; /**< Sdo access requests. */

View File

@ -67,13 +67,13 @@ char *ec_slave_sii_string(ec_slave_t *, unsigned int);
EC_SYSFS_READ_ATTR(info);
EC_SYSFS_READ_WRITE_ATTR(state);
EC_SYSFS_READ_WRITE_ATTR(eeprom);
EC_SYSFS_READ_WRITE_ATTR(sii);
EC_SYSFS_READ_WRITE_ATTR(alias);
static struct attribute *def_attrs[] = {
&attr_info,
&attr_state,
&attr_eeprom,
&attr_sii,
&attr_alias,
NULL,
};
@ -127,8 +127,8 @@ int ec_slave_init(ec_slave_t *slave, /**< EtherCAT slave */
slave->base_build = 0;
slave->base_fmmu_count = 0;
slave->eeprom_data = NULL;
slave->eeprom_size = 0;
slave->sii_data = NULL;
slave->sii_size = 0;
slave->sii.alias = 0;
slave->sii.vendor_id = 0;
@ -270,7 +270,8 @@ void ec_slave_clear(struct kobject *kobj /**< kobject of the slave */)
kfree(pdo);
}
if (slave->eeprom_data) kfree(slave->eeprom_data);
if (slave->sii_data)
kfree(slave->sii_data);
kfree(slave);
}
@ -861,39 +862,39 @@ ssize_t ec_slave_info(const ec_slave_t *slave, /**< EtherCAT slave */
/*****************************************************************************/
/**
* Schedules an EEPROM write request.
* Schedules an SII write request.
* \return 0 case of success, otherwise error code.
*/
int ec_slave_schedule_eeprom_writing(
ec_eeprom_write_request_t *request /**< EEPROM write request */
int ec_slave_schedule_sii_writing(
ec_sii_write_request_t *request /**< SII write request */
)
{
ec_master_t *master = request->slave->master;
request->state = EC_REQUEST_QUEUED;
// schedule EEPROM write request.
down(&master->eeprom_sem);
list_add_tail(&request->list, &master->eeprom_requests);
up(&master->eeprom_sem);
// schedule SII write request.
down(&master->sii_sem);
list_add_tail(&request->list, &master->sii_requests);
up(&master->sii_sem);
// wait for processing through FSM
if (wait_event_interruptible(master->eeprom_queue,
if (wait_event_interruptible(master->sii_queue,
request->state != EC_REQUEST_QUEUED)) {
// interrupted by signal
down(&master->eeprom_sem);
down(&master->sii_sem);
if (request->state == EC_REQUEST_QUEUED) {
list_del(&request->list);
up(&master->eeprom_sem);
up(&master->sii_sem);
return -EINTR;
}
// request already processing: interrupt not possible.
up(&master->eeprom_sem);
up(&master->sii_sem);
}
// wait until master FSM has finished processing
wait_event(master->eeprom_queue,
wait_event(master->sii_queue,
request->state != EC_REQUEST_BUSY);
return request->state == EC_REQUEST_SUCCESS ? 0 : -EIO;
@ -902,7 +903,7 @@ int ec_slave_schedule_eeprom_writing(
/*****************************************************************************/
/**
* Calculates the EEPROM checksum field.
* Calculates the SII checksum field.
*
* The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
* initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
@ -916,7 +917,7 @@ int ec_slave_schedule_eeprom_writing(
* \return CRC8
*/
uint8_t ec_slave_eeprom_crc(
uint8_t ec_slave_sii_crc(
const uint8_t *data, /**< pointer to data */
size_t length /**< number of bytes in \a data */
)
@ -945,33 +946,33 @@ uint8_t ec_slave_eeprom_crc(
/*****************************************************************************/
/**
* Writes complete EEPROM contents to a slave.
* Writes complete SII contents to a slave.
* \return data size written in case of success, otherwise error code.
*/
ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< new EEPROM data */
ssize_t ec_slave_write_sii(ec_slave_t *slave, /**< EtherCAT slave */
const uint8_t *data, /**< new SII data */
size_t size /**< size of data in bytes */
)
{
ec_eeprom_write_request_t request;
ec_sii_write_request_t request;
const uint16_t *cat_header;
uint16_t cat_type, cat_size;
int ret;
uint8_t crc;
if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
EC_ERR("Writing EEPROMs only allowed in idle mode!\n");
EC_ERR("Writing SIIs only allowed in idle mode!\n");
return -EBUSY;
}
if (size % 2) {
EC_ERR("EEPROM data size is odd (%u bytes)! SII data must be"
EC_ERR("SII data size is odd (%u bytes)! SII data must be"
" word-aligned. Dropping.\n", size);
return -EINVAL;
}
// init EEPROM write request
// init SII write request
INIT_LIST_HEAD(&request.list);
request.slave = slave;
request.data = data;
@ -979,39 +980,39 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
request.word_size = size / 2;
if (request.word_size < 0x0041) {
EC_ERR("EEPROM data too short (%u words)! Mimimum is"
EC_ERR("SII data too short (%u words)! Mimimum is"
" 40 fixed words + 1 delimiter. Dropping.\n",
request.word_size);
return -EINVAL;
}
// calculate checksum
crc = ec_slave_eeprom_crc(data, 14); // CRC over words 0 to 6
crc = ec_slave_sii_crc(data, 14); // CRC over words 0 to 6
if (crc != data[14]) {
EC_WARN("EEPROM CRC incorrect. Must be 0x%02x.\n", crc);
EC_WARN("SII CRC incorrect. Must be 0x%02x.\n", crc);
}
cat_header = (const uint16_t *) request.data
+ EC_FIRST_EEPROM_CATEGORY_OFFSET;
+ EC_FIRST_SII_CATEGORY_OFFSET;
cat_type = EC_READ_U16(cat_header);
while (cat_type != 0xFFFF) { // cycle through categories
if (cat_header + 1 >
(const uint16_t *) request.data + request.word_size) {
EC_ERR("EEPROM data corrupted! Dropping.\n");
EC_ERR("SII data corrupted! Dropping.\n");
return -EINVAL;
}
cat_size = EC_READ_U16(cat_header + 1);
if (cat_header + cat_size + 2 >
(const uint16_t *) request.data + request.word_size) {
EC_ERR("EEPROM data corrupted! Dropping.\n");
EC_ERR("SII data corrupted! Dropping.\n");
return -EINVAL;
}
cat_header += cat_size + 2;
cat_type = EC_READ_U16(cat_header);
}
// EEPROM data ok. schedule writing.
if ((ret = ec_slave_schedule_eeprom_writing(&request)))
// SII data ok. schedule writing.
if ((ret = ec_slave_schedule_sii_writing(&request)))
return ret; // error code
return size; // success
@ -1020,7 +1021,7 @@ ssize_t ec_slave_write_eeprom(ec_slave_t *slave, /**< EtherCAT slave */
/*****************************************************************************/
/**
* Writes the Secondary slave address (alias) to the slave's EEPROM.
* Writes the Secondary slave address (alias) to the slave's SII.
* \return data size written in case of success, otherwise error code.
*/
@ -1029,14 +1030,14 @@ ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */
size_t size /**< size of data in bytes */
)
{
ec_eeprom_write_request_t request;
ec_sii_write_request_t request;
char *remainder;
uint16_t alias;
int ret;
uint8_t eeprom_data[16], crc;
uint8_t sii_data[16], crc;
if (slave->master->mode != EC_MASTER_MODE_IDLE) { // FIXME
EC_ERR("Writing to EEPROM is only allowed in idle mode!\n");
EC_ERR("Writing to SII is only allowed in idle mode!\n");
return -EBUSY;
}
@ -1046,30 +1047,30 @@ ssize_t ec_slave_write_alias(ec_slave_t *slave, /**< EtherCAT slave */
return -EINVAL;
}
if (!slave->eeprom_data || slave->eeprom_size < 16) {
EC_ERR("Failed to read EEPROM contents from slave %u.\n",
if (!slave->sii_data || slave->sii_size < 16) {
EC_ERR("Failed to read SII contents from slave %u.\n",
slave->ring_position);
return -EINVAL;
}
// copy first 7 words of recent EEPROM contents
memcpy(eeprom_data, slave->eeprom_data, 14);
// copy first 7 words of recent SII contents
memcpy(sii_data, slave->sii_data, 14);
// write new alias address in word 4
EC_WRITE_U16(eeprom_data + 8, alias);
EC_WRITE_U16(sii_data + 8, alias);
// calculate new checksum over words 0 to 6
crc = ec_slave_eeprom_crc(eeprom_data, 14);
EC_WRITE_U16(eeprom_data + 14, crc);
crc = ec_slave_sii_crc(sii_data, 14);
EC_WRITE_U16(sii_data + 14, crc);
// init EEPROM write request
// init SII write request
INIT_LIST_HEAD(&request.list);
request.slave = slave;
request.data = eeprom_data;
request.data = sii_data;
request.word_offset = 0x0000;
request.word_size = 8;
if ((ret = ec_slave_schedule_eeprom_writing(&request)))
if ((ret = ec_slave_schedule_sii_writing(&request)))
return ret; // error code
slave->sii.alias = alias; // FIXME: do this in state machine
@ -1108,16 +1109,16 @@ ssize_t ec_show_slave_attribute(struct kobject *kobj, /**< slave's kobject */
return sprintf(buffer, "UNKNOWN\n");
}
}
else if (attr == &attr_eeprom) {
if (slave->eeprom_data) {
if (slave->eeprom_size > PAGE_SIZE) {
EC_ERR("EEPROM contents of slave %u exceed 1 page (%u/%u).\n",
slave->ring_position, slave->eeprom_size,
else if (attr == &attr_sii) {
if (slave->sii_data) {
if (slave->sii_size > PAGE_SIZE) {
EC_ERR("SII contents of slave %u exceed 1 page (%u/%u).\n",
slave->ring_position, slave->sii_size,
(int) PAGE_SIZE);
}
else {
memcpy(buffer, slave->eeprom_data, slave->eeprom_size);
return slave->eeprom_size;
memcpy(buffer, slave->sii_data, slave->sii_size);
return slave->sii_size;
}
}
}
@ -1163,8 +1164,8 @@ ssize_t ec_store_slave_attribute(struct kobject *kobj, /**< slave's kobject */
state, slave->ring_position);
return size;
}
else if (attr == &attr_eeprom) {
return ec_slave_write_eeprom(slave, buffer, size);
else if (attr == &attr_sii) {
return ec_slave_write_sii(slave, buffer, size);
}
else if (attr == &attr_alias) {
return ec_slave_write_alias(slave, buffer, size);

View File

@ -142,26 +142,26 @@ typedef struct {
uint16_t mailbox_protocols; /**< Supported mailbox protocols. */
// Strings
char **strings; /**< Strings in EEPROM categories. */
unsigned int string_count; /**< number of EEPROM strings */
char **strings; /**< Strings in SII categories. */
unsigned int string_count; /**< number of SII strings */
// General
unsigned int has_general; /**< General category present. */
char *group; /**< slave group acc. to EEPROM */
char *image; /**< slave image name acc. to EEPROM */
char *order; /**< slave order number acc. to EEPROM */
char *name; /**< slave name acc. to EEPROM */
char *group; /**< slave group acc. to SII */
char *image; /**< slave image name acc. to SII */
char *order; /**< slave order number acc. to SII */
char *name; /**< slave name acc. to SII */
uint8_t physical_layer[4]; /**< port media */
ec_sii_coe_details_t coe_details; /**< CoE detail flags. */
ec_sii_general_flags_t general_flags; /**< General flags. */
int16_t current_on_ebus; /**< power consumption */
// SyncM
ec_sync_t *syncs; /**< EEPROM SYNC MANAGER categories */
unsigned int sync_count; /**< number of sync managers in EEPROM */
ec_sync_t *syncs; /**< SII SYNC MANAGER categories */
unsigned int sync_count; /**< number of sync managers in SII */
// [RT]XPDO
struct list_head pdos; /**< EEPROM [RT]XPDO categories */
struct list_head pdos; /**< SII [RT]XPDO categories */
} ec_sii_t;
/*****************************************************************************/
@ -197,9 +197,9 @@ struct ec_slave
uint8_t dl_loop[4]; /**< loop closed */
uint8_t dl_signal[4]; /**< detected signal on RX port */
// EEPROM
uint8_t *eeprom_data; /**< Complete EEPROM image */
size_t eeprom_size; /**< size of the EEPROM contents in bytes */
// SII
uint8_t *sii_data; /**< Complete SII image */
size_t sii_size; /**< size of the SII contents in bytes */
// slave information interface
ec_sii_t sii; /**< SII data. */

View File

@ -73,7 +73,7 @@ void ec_sync_clear(
/*****************************************************************************/
/** Initializes a sync manager configuration page with EEPROM data.
/** Initializes a sync manager configuration page with SII data.
*
* The referenced memory (\a data) must be at least \a EC_SYNC_SIZE bytes.
*/