From 56c455617392ca7c8b24e65addafdce9d2421cab Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 14 Mar 2023 16:12:45 +0100 Subject: [PATCH] New SoE request API; implemented API in kernel. --- include/ecrt.h | 142 ++++++++++++++++++++++++++++++++++++++++-- master/fsm_master.c | 117 ++++++++++++++++++++++++++++------ master/fsm_master.h | 5 +- master/slave_config.c | 67 ++++++++++++++++++-- master/slave_config.h | 7 ++- master/soe_request.c | 87 +++++++++++++++++++++++++- master/soe_request.h | 8 ++- 7 files changed, 395 insertions(+), 38 deletions(-) diff --git a/include/ecrt.h b/include/ecrt.h index 3f6b4b19..40bcec25 100644 --- a/include/ecrt.h +++ b/include/ecrt.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT master userspace library. * @@ -43,6 +41,13 @@ * * - Added the ecrt_slave_config_flag() method and the EC_HAVE_FLAGS * definition to check for its existence. + * - Added SoE IDN requests, including the datatype ec_soe_request_t and the + * methods ecrt_slave_config_create_soe_request(), + * ecrt_soe_request_object(), ecrt_soe_request_timeout(), + * ecrt_soe_request_data(), ecrt_soe_request_data_size(), + * ecrt_soe_request_state(), ecrt_soe_request_write() and + * ecrt_soe_request_read(). Use the EC_HAVE_SOE_REQUESTS to check, if the + * functionality is available. * * Changes in version 1.5.2: * @@ -52,7 +57,7 @@ * - Added the EC_HAVE_REDUNDANCY define, to check, if the interface contains * redundancy features. * - Added ecrt_sdo_request_index() to change SDO index and subindex after - * handler creation. + * request creation. * - Added interface for retrieving CoE emergency messages, i. e. * ecrt_slave_config_emerg_size(), ecrt_slave_config_emerg_pop(), * ecrt_slave_config_emerg_clear(), ecrt_slave_config_emerg_overruns() and @@ -200,6 +205,14 @@ */ #define EC_HAVE_FLAGS +/** Defined if the methods ecrt_slave_config_create_soe_request(), + * ecrt_soe_request_object(), ecrt_soe_request_timeout(), + * ecrt_soe_request_data(), ecrt_soe_request_data_size(), + * ecrt_soe_request_state(), ecrt_soe_request_write() and + * ecrt_soe_request_read() and the datatype ec_soe_request_t are available. + */ +#define EC_HAVE_SOE_REQUESTS + /*****************************************************************************/ /** End of list marker. @@ -254,11 +267,14 @@ 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_soe_request; +typedef struct ec_soe_request ec_soe_request_t; /**< \see ec_soe_request. */ + struct ec_voe_handler; typedef struct ec_voe_handler ec_voe_handler_t; /**< \see ec_voe_handler. */ struct ec_reg_request; -typedef struct ec_reg_request ec_reg_request_t; /**< \see ec_sdo_request. */ +typedef struct ec_reg_request ec_reg_request_t; /**< \see ec_reg_request. */ /*****************************************************************************/ @@ -1559,6 +1575,23 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request( size_t size /**< Data size to reserve. */ ); +/** Create an SoE request to exchange SoE IDNs during realtime operation. + * + * The created SoE request object is freed automatically when the master is + * released. + * + * This method has to be called in non-realtime context before + * ecrt_master_activate(). + * + * \return New SoE request, or NULL on error. + */ +ec_soe_request_t *ecrt_slave_config_create_soe_request( + ec_slave_config_t *sc, /**< Slave configuration. */ + uint8_t drive_no, /**< Drive number. */ + uint16_t idn, /**< Sercos ID-Number. */ + size_t size /**< Data size to reserve. */ + ); + /** Create an VoE handler to exchange vendor-specific data during realtime * operation. * @@ -1874,6 +1907,105 @@ void ecrt_sdo_request_read( ec_sdo_request_t *req /**< SDO request. */ ); +/***************************************************************************** + * SoE request methods. + ****************************************************************************/ + +/** Set the request's drive and Sercos ID numbers. + * + * \attention If the drive number and/or IDN is changed while + * ecrt_soe_request_state() returns EC_REQUEST_BUSY, this may lead to + * unexpected results. + */ +void ecrt_soe_request_idn( + ec_soe_request_t *req, /**< IDN request. */ + uint8_t drive_no, /**< SDO index. */ + uint16_t idn /**< SoE IDN. */ + ); + +/** Set the timeout for an SoE request. + * + * If the request cannot be processed in the specified time, if will be marked + * as failed. + * + * The timeout is permanently stored in the request object and is valid until + * the next call of this method. + */ +void ecrt_soe_request_timeout( + ec_soe_request_t *req, /**< SoE request. */ + uint32_t timeout /**< Timeout in milliseconds. Zero means no + timeout. */ + ); + +/** Access to the SoE request's data. + * + * This function returns a pointer to the request's internal IDN data memory. + * + * - After a read operation was successful, integer data can be evaluated + * using the EC_READ_*() macros as usual. Example: + * \code + * uint16_t value = EC_READ_U16(ecrt_soe_request_data(idn_req))); + * \endcode + * - If a write operation shall be triggered, the data have to be written to + * the internal memory. Use the EC_WRITE_*() macros, if you are writing + * integer data. Be sure, that the data fit into the memory. The memory size + * is a parameter of ecrt_slave_config_create_soe_request(). + * \code + * EC_WRITE_U16(ecrt_soe_request_data(idn_req), 0xFFFF); + * \endcode + * + * \attention The return value can be invalidated during a read operation, + * because the internal IDN data memory could be re-allocated if the read IDN + * data do not fit inside. + * + * \return Pointer to the internal IDN data memory. + */ +uint8_t *ecrt_soe_request_data( + ec_soe_request_t *req /**< SoE request. */ + ); + +/** Returns the current IDN data size. + * + * When the SoE request is created, the data size is set to the size of the + * reserved memory. 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 IDN data size in bytes. + */ +size_t ecrt_soe_request_data_size( + const ec_soe_request_t *req /**< SoE request. */ + ); + +/** Get the current state of the SoE request. + * + * \return Request state. + */ +ec_request_state_t ecrt_soe_request_state( + ec_soe_request_t *req /**< SoE request. */ + ); + +/** Schedule an SoE IDN write operation. + * + * \attention This method may not be called while ecrt_soe_request_state() + * returns EC_REQUEST_BUSY. + */ +void ecrt_soe_request_write( + ec_soe_request_t *req /**< SoE request. */ + ); + +/** Schedule an SoE IDN read operation. + * + * \attention This method may not be called while ecrt_soe_request_state() + * returns EC_REQUEST_BUSY. + * + * \attention After calling this function, the return value of + * ecrt_soe_request_data() must be considered as invalid while + * ecrt_soe_request_state() returns EC_REQUEST_BUSY. + */ +void ecrt_soe_request_read( + ec_soe_request_t *req /**< SoE request. */ + ); + /***************************************************************************** * VoE handler methods. ****************************************************************************/ diff --git a/master/fsm_master.c b/master/fsm_master.c index d2532510..92595dda 100644 --- a/master/fsm_master.c +++ b/master/fsm_master.c @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -66,6 +64,7 @@ void ec_fsm_master_state_assign_sii(ec_fsm_master_t *); void ec_fsm_master_state_write_sii(ec_fsm_master_t *); void ec_fsm_master_state_sdo_dictionary(ec_fsm_master_t *); void ec_fsm_master_state_sdo_request(ec_fsm_master_t *); +void ec_fsm_master_state_soe_request(ec_fsm_master_t *); void ec_fsm_master_enter_clear_addresses(ec_fsm_master_t *); void ec_fsm_master_enter_write_system_times(ec_fsm_master_t *); @@ -83,8 +82,18 @@ void ec_fsm_master_init( fsm->master = master; fsm->datagram = datagram; + // inits the member variables state, idle, dev_idx, link_state, + // slaves_responding, slave_states and rescan_required ec_fsm_master_reset(fsm); + fsm->retries = 0; + fsm->scan_jiffies = 0; + fsm->slave = NULL; + fsm->sii_request = NULL; + fsm->sii_index = 0; + fsm->sdo_request = NULL; + fsm->soe_request = NULL; + // init sub-state-machines ec_fsm_coe_init(&fsm->fsm_coe); ec_fsm_soe_init(&fsm->fsm_soe); @@ -492,17 +501,18 @@ int ec_fsm_master_action_process_sii( /*****************************************************************************/ -/** Check for pending SDO requests and process one. +/** Check for pending internal SDO/SoE requests and process one. * * \return non-zero, if an SDO request is processed. */ -int ec_fsm_master_action_process_sdo( +int ec_fsm_master_action_process_int_request( ec_fsm_master_t *fsm /**< Master state machine. */ ) { ec_master_t *master = fsm->master; ec_slave_t *slave; - ec_sdo_request_t *req; + ec_sdo_request_t *sdo_req; + ec_soe_request_t *soe_req; // search for internal requests to be processed for (slave = master->slaves; @@ -513,33 +523,61 @@ int ec_fsm_master_action_process_sdo( continue; } - list_for_each_entry(req, &slave->config->sdo_requests, list) { - if (req->state == EC_INT_REQUEST_QUEUED) { + list_for_each_entry(sdo_req, &slave->config->sdo_requests, list) { + if (sdo_req->state == EC_INT_REQUEST_QUEUED) { - if (ec_sdo_request_timed_out(req)) { - req->state = EC_INT_REQUEST_FAILURE; + if (ec_sdo_request_timed_out(sdo_req)) { + sdo_req->state = EC_INT_REQUEST_FAILURE; EC_SLAVE_DBG(slave, 1, "Internal SDO request" " timed out.\n"); continue; } if (slave->current_state == EC_SLAVE_STATE_INIT) { - req->state = EC_INT_REQUEST_FAILURE; + sdo_req->state = EC_INT_REQUEST_FAILURE; continue; } - req->state = EC_INT_REQUEST_BUSY; + sdo_req->state = EC_INT_REQUEST_BUSY; EC_SLAVE_DBG(slave, 1, "Processing internal" " SDO request...\n"); fsm->idle = 0; - fsm->sdo_request = req; + fsm->sdo_request = sdo_req; fsm->slave = slave; fsm->state = ec_fsm_master_state_sdo_request; - ec_fsm_coe_transfer(&fsm->fsm_coe, slave, req); + ec_fsm_coe_transfer(&fsm->fsm_coe, slave, sdo_req); ec_fsm_coe_exec(&fsm->fsm_coe, fsm->datagram); return 1; } } + + list_for_each_entry(soe_req, &slave->config->soe_requests, list) { + if (soe_req->state == EC_INT_REQUEST_QUEUED) { + + if (ec_soe_request_timed_out(soe_req)) { + soe_req->state = EC_INT_REQUEST_FAILURE; + EC_SLAVE_DBG(slave, 1, "Internal SoE request" + " timed out.\n"); + continue; + } + + if (slave->current_state == EC_SLAVE_STATE_INIT) { + soe_req->state = EC_INT_REQUEST_FAILURE; + continue; + } + + soe_req->state = EC_INT_REQUEST_BUSY; + EC_SLAVE_DBG(slave, 1, "Processing internal" + " SoE request...\n"); + fsm->idle = 0; + fsm->soe_request = soe_req; + fsm->slave = slave; + fsm->state = ec_fsm_master_state_soe_request; + ec_fsm_soe_transfer(&fsm->fsm_soe, slave, soe_req); + ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram); + return 1; + } + } } return 0; } @@ -557,8 +595,8 @@ void ec_fsm_master_action_idle( ec_master_t *master = fsm->master; ec_slave_t *slave; - // Check for pending internal SDO requests - if (ec_fsm_master_action_process_sdo(fsm)) { + // Check for pending internal SDO or SoE requests + if (ec_fsm_master_action_process_int_request(fsm)) { return; } @@ -1357,8 +1395,51 @@ void ec_fsm_master_state_sdo_request( EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SDO request.\n"); - // check for another SDO request - if (ec_fsm_master_action_process_sdo(fsm)) { + // check for another SDO/SoE request + if (ec_fsm_master_action_process_int_request(fsm)) { + return; // processing another request + } + + ec_fsm_master_restart(fsm); +} + +/*****************************************************************************/ + +/** Master state: SoE REQUEST. + */ +void ec_fsm_master_state_soe_request( + ec_fsm_master_t *fsm /**< Master state machine. */ + ) +{ + ec_soe_request_t *request = fsm->soe_request; + + if (!request) { + // configuration was cleared in the meantime + ec_fsm_master_restart(fsm); + return; + } + + if (ec_fsm_soe_exec(&fsm->fsm_soe, fsm->datagram)) { + return; + } + + if (!ec_fsm_soe_success(&fsm->fsm_soe)) { + EC_SLAVE_DBG(fsm->slave, 1, + "Failed to process internal SoE request.\n"); + request->state = EC_INT_REQUEST_FAILURE; + wake_up_all(&fsm->master->request_queue); + ec_fsm_master_restart(fsm); + return; + } + + // SoE request finished + request->state = EC_INT_REQUEST_SUCCESS; + wake_up_all(&fsm->master->request_queue); + + EC_SLAVE_DBG(fsm->slave, 1, "Finished internal SoE request.\n"); + + // check for another CoE/SoE request + if (ec_fsm_master_action_process_int_request(fsm)) { return; // processing another request } diff --git a/master/fsm_master.h b/master/fsm_master.h index a41b949c..3e461b43 100644 --- a/master/fsm_master.h +++ b/master/fsm_master.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -88,6 +86,7 @@ struct ec_fsm_master { 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_soe_request_t *soe_request; /**< SoE request to process. */ ec_fsm_coe_t fsm_coe; /**< CoE state machine */ ec_fsm_soe_t fsm_soe; /**< SoE state machine */ diff --git a/master/slave_config.c b/master/slave_config.c index f2c45a30..28dc7d35 100644 --- a/master/slave_config.c +++ b/master/slave_config.c @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -87,6 +85,7 @@ void ec_slave_config_init( INIT_LIST_HEAD(&sc->sdo_configs); INIT_LIST_HEAD(&sc->sdo_requests); + INIT_LIST_HEAD(&sc->soe_requests); INIT_LIST_HEAD(&sc->reg_requests); INIT_LIST_HEAD(&sc->voe_handlers); INIT_LIST_HEAD(&sc->soe_configs); @@ -132,6 +131,13 @@ void ec_slave_config_clear( kfree(req); } + // free all SoE requests + list_for_each_entry_safe(soe, next_soe, &sc->soe_requests, list) { + list_del(&soe->list); + ec_soe_request_clear(soe); + kfree(soe); + } + // free all register requests list_for_each_entry_safe(reg, next_reg, &sc->reg_requests, list) { list_del(®->list); @@ -507,7 +513,7 @@ const ec_flag_t *ec_slave_config_get_flag_by_pos_const( /*****************************************************************************/ -/** Finds a CoE handler via its position in the list. +/** Finds a CoE SDO request via its position in the list. * * \return Search result, or NULL. */ @@ -1158,6 +1164,58 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request( /*****************************************************************************/ +/** Same as ecrt_slave_config_create_soe_request(), but with ERR_PTR() return + * value. + */ +ec_soe_request_t *ecrt_slave_config_create_soe_request_err( + ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size) +{ + ec_soe_request_t *req; + int ret; + + EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, " + "drive_no = 0x%02X, idn = 0x%04X, size = %zu)\n", + __func__, sc, drive_no, idn, size); + + if (!(req = (ec_soe_request_t *) + kmalloc(sizeof(ec_soe_request_t), GFP_KERNEL))) { + EC_CONFIG_ERR(sc, "Failed to allocate IDN request memory!\n"); + return ERR_PTR(-ENOMEM); + } + + ec_soe_request_init(req); + ecrt_soe_request_idn(req, drive_no, idn); + + ret = ec_soe_request_alloc(req, size); + if (ret < 0) { + ec_soe_request_clear(req); + kfree(req); + return ERR_PTR(ret); + } + + // prepare data for optional writing + memset(req->data, 0x00, size); + req->data_size = size; + + down(&sc->master->master_sem); + list_add_tail(&req->list, &sc->soe_requests); + up(&sc->master->master_sem); + + return req; +} + +/*****************************************************************************/ + +ec_soe_request_t *ecrt_slave_config_create_soe_request( + ec_slave_config_t *sc, uint8_t drive_no, uint16_t idn, size_t size) +{ + ec_soe_request_t *req = ecrt_slave_config_create_soe_request_err(sc, + drive_no, idn, size); + return IS_ERR(req) ? NULL : req; +} + +/*****************************************************************************/ + /** Same as ecrt_slave_config_create_reg_request(), but with ERR_PTR() return * value. */ @@ -1373,6 +1431,7 @@ EXPORT_SYMBOL(ecrt_slave_config_emerg_pop); EXPORT_SYMBOL(ecrt_slave_config_emerg_clear); EXPORT_SYMBOL(ecrt_slave_config_emerg_overruns); EXPORT_SYMBOL(ecrt_slave_config_create_sdo_request); +EXPORT_SYMBOL(ecrt_slave_config_create_soe_request); EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler); EXPORT_SYMBOL(ecrt_slave_config_create_reg_request); EXPORT_SYMBOL(ecrt_slave_config_state); diff --git a/master/slave_config.h b/master/slave_config.h index ad22e4ed..2d518c58 100644 --- a/master/slave_config.h +++ b/master/slave_config.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -143,6 +141,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 soe_requests; /**< List of SoE requests. */ struct list_head voe_handlers; /**< List of VoE handlers. */ struct list_head reg_requests; /**< List of register requests. */ struct list_head soe_configs; /**< List of SoE configurations. */ @@ -181,6 +180,8 @@ ec_flag_t *ec_slave_config_find_flag(ec_slave_config_t *, const char *); ec_sdo_request_t *ecrt_slave_config_create_sdo_request_err( ec_slave_config_t *, uint16_t, uint8_t, size_t); +ec_soe_request_t *ecrt_slave_config_create_soe_request_err( + ec_slave_config_t *, uint8_t, uint16_t, size_t); ec_voe_handler_t *ecrt_slave_config_create_voe_handler_err( ec_slave_config_t *, size_t); ec_reg_request_t *ecrt_slave_config_create_reg_request_err( diff --git a/master/soe_request.c b/master/soe_request.c index 4ad90353..1dd28b2c 100644 --- a/master/soe_request.c +++ b/master/soe_request.c @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -64,8 +62,10 @@ void ec_soe_request_init( req->data = NULL; req->mem_size = 0; req->data_size = 0; + req->issue_timeout = 0; // no timeout req->dir = EC_DIR_INVALID; req->state = EC_INT_REQUEST_INIT; + req->jiffies_start = 0U; req->jiffies_sent = 0U; req->error_code = 0x0000; } @@ -236,6 +236,7 @@ void ec_soe_request_read( req->dir = EC_DIR_INPUT; req->state = EC_INT_REQUEST_QUEUED; req->error_code = 0x0000; + req->jiffies_start = jiffies; } /*****************************************************************************/ @@ -249,6 +250,86 @@ void ec_soe_request_write( req->dir = EC_DIR_OUTPUT; req->state = EC_INT_REQUEST_QUEUED; req->error_code = 0x0000; + req->jiffies_start = jiffies; } /*****************************************************************************/ + +/** Checks, if the timeout was exceeded. + * + * \return non-zero if the timeout was exceeded, else zero. + */ +int ec_soe_request_timed_out(const ec_soe_request_t *req /**< SDO request. */) +{ + return req->issue_timeout + && jiffies - req->jiffies_start > HZ * req->issue_timeout / 1000; +} + +/***************************************************************************** + * Application interface. + ****************************************************************************/ + +void ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no, + uint16_t idn) +{ + req->drive_no = drive_no; + req->idn = idn; +} + +/*****************************************************************************/ + +void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout) +{ + req->issue_timeout = timeout; +} + +/*****************************************************************************/ + +uint8_t *ecrt_soe_request_data(ec_soe_request_t *req) +{ + return req->data; +} + +/*****************************************************************************/ + +size_t ecrt_soe_request_data_size(const ec_soe_request_t *req) +{ + return req->data_size; +} + +/*****************************************************************************/ + +ec_request_state_t ecrt_soe_request_state(ec_soe_request_t *req) +{ + return ec_request_state_translation_table[req->state]; +} + +/*****************************************************************************/ + +void ecrt_soe_request_read(ec_soe_request_t *req) +{ + ec_soe_request_read(req); +} + +/*****************************************************************************/ + +void ecrt_soe_request_write(ec_soe_request_t *req) +{ + ec_soe_request_write(req); +} + +/*****************************************************************************/ + +/** \cond */ + +EXPORT_SYMBOL(ecrt_soe_request_idn); +EXPORT_SYMBOL(ecrt_soe_request_timeout); +EXPORT_SYMBOL(ecrt_soe_request_data); +EXPORT_SYMBOL(ecrt_soe_request_data_size); +EXPORT_SYMBOL(ecrt_soe_request_state); +EXPORT_SYMBOL(ecrt_soe_request_read); +EXPORT_SYMBOL(ecrt_soe_request_write); + +/** \endcond */ + +/*****************************************************************************/ diff --git a/master/soe_request.h b/master/soe_request.h index 40f61aa6..c5ff9404 100644 --- a/master/soe_request.h +++ b/master/soe_request.h @@ -45,7 +45,7 @@ /** Sercos-over-EtherCAT request. */ -typedef struct { +struct ec_soe_request { struct list_head list; /**< List item. */ uint8_t drive_no; /**< Drive number. */ uint16_t idn; /**< Sercos ID-Number. */ @@ -53,13 +53,16 @@ typedef struct { uint8_t *data; /**< Pointer to SDO data. */ size_t mem_size; /**< Size of SDO data memory. */ size_t data_size; /**< Size of SDO data. */ + uint32_t issue_timeout; /**< Maximum time in ms, the processing of the + request may take. */ ec_direction_t dir; /**< Direction. EC_DIR_OUTPUT means writing to the slave, EC_DIR_INPUT means reading from the slave. */ ec_internal_request_state_t state; /**< Request state. */ + unsigned long jiffies_start; /**< Jiffies, when the request was issued. */ unsigned long jiffies_sent; /**< Jiffies, when the upload/download request was sent. */ uint16_t error_code; /**< SoE error code. */ -} ec_soe_request_t; +}; /*****************************************************************************/ @@ -74,6 +77,7 @@ int ec_soe_request_copy_data(ec_soe_request_t *, const uint8_t *, size_t); int ec_soe_request_append_data(ec_soe_request_t *, const uint8_t *, size_t); void ec_soe_request_read(ec_soe_request_t *); void ec_soe_request_write(ec_soe_request_t *); +int ec_soe_request_timed_out(const ec_soe_request_t *); /*****************************************************************************/