Sam Grove
/
canopen_slavenode
CANfestival - an open source CANopen framework
Diff: framework/include/sdo.h
- Revision:
- 0:6219434a0cb5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/framework/include/sdo.h Mon May 30 07:14:41 2011 +0000 @@ -0,0 +1,479 @@ +/* +This file is part of CanFestival, a library implementing CanOpen Stack. + +Copyright (C): Edouard TISSERANT and Francis DUPIN + +See COPYING file for copyrights details. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/** @defgroup comobj Communication Objects + * @ingroup userapi + */ + +/** @defgroup sdo Service Data Object (SDO) + * SDOs provide the access to entries in the CANopen Object Dictionary. + * An SDO is made up of at least two CAN messages with different identifiers. + * SDO s are always confirmed point-to-point communications services. + * @ingroup comobj + */ + +#ifndef __sdo_h__ +#define __sdo_h__ + +struct struct_s_transfer; + +#include "canopen_timer.h" + +typedef void (*SDOCallback_t)(CO_Data* d, UNS8 nodeId); + +/* The Transfer structure +Used to store the different segments of + - a SDO received before writing in the dictionary + - the reading of the dictionary to put on a SDO to transmit +*/ + +struct struct_s_transfer { + UNS8 nodeId; /**<own ID if server, or node ID of the server if client */ + + UNS8 whoami; /**< Takes the values SDO_CLIENT or SDO_SERVER */ + UNS8 state; /**< state of the transmission : Takes the values SDO_... */ + UNS8 toggle; + UNS32 abortCode; /**< Sent or received */ + /**< index and subindex of the dictionary where to store */ + /**< (for a received SDO) or to read (for a transmit SDO) */ + UNS16 index; + UNS8 subIndex; + UNS32 count; /**< Number of data received or to be sent. */ + UNS32 offset; /**< stack pointer of data[] + * Used only to tranfer part of a line to or from a SDO. + * offset is always pointing on the next free cell of data[]. + * WARNING s_transfer.data is subject to ENDIANISATION + * (with respect to CANOPEN_BIG_ENDIAN) + */ + UNS8 data [SDO_MAX_LENGTH_TRANSFERT]; +#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION + UNS8 *dynamicData; + UNS32 dynamicDataSize; +#endif //SDO_DYNAMIC_BUFFER_ALLOCATION + UNS8 dataType; /**< Defined in objdictdef.h Value is visible_string + * if it is a string, any other value if it is not a string, + * like 0. In fact, it is used only if client. + */ + TIMER_HANDLE timer; /**< Time counter to implement a timeout in milliseconds. + * It is automatically incremented whenever + * the line state is in SDO_DOWNLOAD_IN_PROGRESS or + * SDO_UPLOAD_IN_PROGRESS, and reseted to 0 + * when the response SDO have been received. + */ + SDOCallback_t Callback; /**< The user callback func to be called at SDO transaction end */ +}; +typedef struct struct_s_transfer s_transfer; + + +#include "data.h" + + +struct BODY{ + UNS8 data[8]; /**< The 8 bytes data of the SDO */ +}; + +/* The SDO structure ...*/ +struct struct_s_SDO { + UNS8 nodeId; /**< In any case, Node ID of the server (case sender or receiver).*/ + struct BODY body; +}; + + +typedef struct struct_s_SDO s_SDO; + +/*! +** Called by writeNetworkDict +** +** @param d +** @param nodeId +** @param index +** @param subIndex +** @param count +** @param dataType +** @param data +** @param Callback +** @param endianize +** +** @return +**/ +UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, + UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize); + +/** + * @brief Reset of a SDO exchange on timeout. + * Send a SDO abort. + * @param *d Pointer on a CAN object data structure + * @param id + */ +void SDOTimeoutAlarm(CO_Data* d, UNS32 id); + +/** + * @brief Reset all SDO buffers. + * @param *d Pointer on a CAN object data structure + */ +void resetSDO (CO_Data* d); + + +/** + * @brief Copy the data received from the SDO line transfert to the object dictionary. + * @param *d Pointer on a CAN object data structure + * @param line SDO line + * @return SDO error code if error. Else, returns 0. + */ +UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line); + +/** + * @brief Copy the data from the object dictionary to the SDO line for a network transfert. + * @param *d Pointer on a CAN object data structure + * @param line SDO line + * @return SDO error code if error. Else, returns 0. + */ +UNS32 objdictToSDOline (CO_Data* d, UNS8 line); + +/** + * @brief Copy data from an existant line in the argument "* data" + * @param d Pointer on a CAN object data structure + * @param line SDO line + * @param nbBytes + * @param *data Pointer on the data + * @return 0xFF if error. Else, returns 0. + */ +UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8 * data); + +/** + * @brief Add data to an existant line + * @param d Pointer on a CAN object data structure + * @param line SDO line + * @param nbBytes + * @param *data Pointer on the data + * @return 0xFF if error. Else, returns 0. + */ +UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8 * data); + +/** + * @brief Called when an internal SDO abort occurs. + * Release the line * Only if server * + * If client, the line must be released manually in the core application. + * The reason of that is to permit the program to read the transfers structure before its reset, + * because many informations are stored on it : index, subindex, data received or trasmited, ... + * In all cases, sends a SDO abort. + * @param *d Pointer on a CAN object data structure + * @param nodeId + * @param whoami + * @param index + * @param subIndex + * @param abortCode + * @return 0 + */ +UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode); + +/** + * @brief Reset an unused line. + * @param *d Pointer on a CAN object data structure + * @param line SDO line + */ +void resetSDOline (CO_Data* d, UNS8 line); + +/** + * @brief Initialize some fields of the structure. + * @param *d Pointer on a CAN object data structure + * @param line + * @param nodeId + * @param index + * @param subIndex + * @param state + * @return 0 + */ +UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state); + +/** + * @brief Search for an unused line in the transfers array + * to store a new SDO. + * ie a line which value of the field "state" is "SDO_RESET" + * An unused line have the field "state" at the value SDO_RESET + * @param *d Pointer on a CAN object data structure + * @param whoami Create the line for a SDO_SERVER or SDO_CLIENT. + * @param *line Pointer on a SDO line + * @return 0xFF if all the lines are on use. Else, return 0. + */ +UNS8 getSDOfreeLine (CO_Data* d, UNS8 whoami, UNS8 *line); + +/** + * @brief Search for the line, in the transfers array, which contains the + * beginning of the reception of a fragmented SDO + * @param *d Pointer on a CAN object data structure + * @param nodeId correspond to the message node-id + * @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER + * @param *line Pointer on a SDO line + * @return 0xFF if error. Else, return 0 + */ +UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line); + +/** + * @brief Search for the line, in the transfers array, which contains the + * beginning of the reception of a fragmented SDO + * + * Because getSDOlineOnUse() does not return any line in state \c SDO_ABORTED_INTERNAL, + * this funtion is used to return them, too. + * + * @param *d Pointer on a CAN object data structure + * @param nodeId correspond to the message node-id + * @param whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER + * @param *line Pointer on a SDO line + * @return 0xFF if error. Else, return 0 + */ +UNS8 getSDOlineToClose (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line); + +/** + * @brief Close a transmission. + * @param *d Pointer on a CAN object data structure + * @param nodeId Node id of the server if both server or client + * @param whoami Line opened as SDO_CLIENT or SDO_SERVER + */ +UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami); + +/** + * @brief Bytes in the line structure which must be transmited (or received) + * @param *d Pointer on a CAN object data structure + * @param line SDO line + * @param *nbBytes Pointer on nbBytes + * @return 0. + */ +UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 * nbBytes); + +/** + * @brief Store in the line structure the nb of bytes which must be transmited (or received) + * @param *d Pointer on a CAN object data structure + * @param line SDO line + * @param nbBytes + * @return 0 if success, 0xFF if error. + */ +UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS32 nbBytes); + +/** + * @brief Transmit a SDO frame on the bus bus_id + * @param *d Pointer on a CAN object data structure + * @param whoami Takes 2 values : SDO_CLIENT or SDO_SERVER + * @param sdo SDO Structure which contains the sdo to transmit + * @return canSend(bus_id,&m) or 0xFF if error. + */ +UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo); + +/** + * @brief Transmit a SDO error to the client. The reasons may be : + * Read/Write to a undefined object + * Read/Write to a undefined subindex + * Read/write a not valid length object + * Write a read only object + * @param *d Pointer on a CAN object data structure + * @param whoami takes 2 values : SDO_CLIENT or SDO_SERVER + * @param nodeId + * @param index + * @param subIndex + * @param abortCode + * @return 0 + */ +UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 abortCode); + +/** + * @brief Treat a SDO frame reception + * call the function sendSDO + * @param *d Pointer on a CAN object data structure + * @param *m Pointer on a CAN message structure + * @return code : + * - 0xFF if error + * - 0x80 if transfert aborted by the server + * - 0x0 ok + */ +UNS8 proceedSDO (CO_Data* d, Message *m); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to write the data at the index and subIndex indicated + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param count number of bytes to write in the dictionnary. + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @param *data Pointer to data + * @return + * - 0 is returned upon success. + * - 0xFE is returned when no sdo client to communicate with node. + * - 0xFF is returned when error occurs. + */ +UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, + UNS8 subIndex, UNS32 count, UNS8 dataType, void *data); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to write in a distant node dictionnary. + * @details The function Callback which must be defined in the user code is called at the + * end of the exchange. (on succes or abort). + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param count number of bytes to write in the dictionnary. + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @param *data Pointer to data + * @param Callback Callback function + * @return + * - 0 is returned upon success. + * - 0xFE is returned when no sdo client to communicate with node. + * - 0xFF is returned when error occurs. + */ +UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index, + UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to write in a distant node dictionnary. + * @details The function Callback which must be defined in the user code is called at the + * end of the exchange. (on succes or abort). First free SDO client parameter is + * automatically initialized for specific node if not already defined. + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param count number of bytes to write in the dictionnary. + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @param *data Pointer to data + * @param Callback Callback function + * @param endianize When not 0, data is endianized into network byte order + * when 0, data is not endianized and copied in machine native + * endianness + * @return + * - 0 is returned upon success. + * - 0xFF is returned when error occurs. + */ +UNS8 writeNetworkDictCallBackAI (CO_Data* d, UNS8 nodeId, UNS16 index, + UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to read. + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @return + * - 0 is returned upon success. + * - 0xFE is returned when no sdo client to communicate with node. + * - 0xFF is returned when error occurs. + */ +UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to read in a distant node dictionnary. + * @details The function Callback which must be defined in the user code is called at the + * end of the exchange. (on succes or abort). + * @param *d Pointer on a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @param Callback Callback function + * @return + * - 0 is returned upon success. + * - 0xFE is returned when no sdo client to communicate with node. + * - 0xFF is returned when error occurs. + */ +UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback); + +/** + * @ingroup sdo + * @brief Used to send a SDO request frame to read in a distant node dictionnary. + * @details The function Callback which must be defined in the user code is called at the + * end of the exchange. (on succes or abort). First free SDO client parameter is + * automatically initialized for specific node if not already defined. + * @param *d Pointer on a CAN object data structure + * @param nodeId Node Id of the slave + * @param index At index indicated + * @param subIndex At subIndex indicated + * @param dataType (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. + * @param Callback Callback function + * @return + * - 0 is returned upon success. + * - 0xFF is returned when error occurs. + */ +UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback); + +/** + * @ingroup sdo + * @brief Use this function after calling readNetworkDict to get the result. + * + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param *data Pointer to the datas + * @param *size Pointer to the size + * @param *abortCode Pointer to the abortcode. (0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV) + * + * + * @return + * - SDO_FINISHED // datas are available + * - SDO_ABORTED_RCV // Transfert failed (abort SDO received) + * - SDO_ABORTED_INTERNAL // Transfert failed (internal abort) + * - SDO_UPLOAD_IN_PROGRESS // Datas are not yet available + * - SDO_DOWNLOAD_IN_PROGRESS // Download is in progress + * \n\n + * example : + * @code + * UNS32 data; + * UNS8 size; + * readNetworkDict(0, 0x05, 0x1016, 1, 0) // get the data index 1016 subindex 1 of node 5 + * while (getReadResultNetworkDict (0, 0x05, &data, &size) == SDO_UPLOAD_IN_PROGRESS); + * @endcode +*/ +UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size, UNS32 * abortCode); + +/** + * @ingroup sdo + * @brief Use this function after calling writeNetworkDict function to get the result of the write. + * @details It is mandatory to call this function because it is releasing the line used for the transfer. + * @param *d Pointer to a CAN object data structure + * @param nodeId Node Id of the slave + * @param *abortCode Pointer to the abortcode + * - 0 = not available. + * - SDO abort code (received if return SDO_ABORTED_RCV) + * + * @return : + * - SDO_FINISHED // datas are available + * - SDO_ABORTED_RCV // Transfert failed (abort SDO received) + * - SDO_ABORTED_INTERNAL // Transfert failed (Internal abort) + * - SDO_DOWNLOAD_IN_PROGRESS // Datas are not yet available + * - SDO_UPLOAD_IN_PROGRESS // Upload in progress + * \n\n + * example : + * @code + * UNS32 data = 0x50; + * UNS8 size; + * UNS32 abortCode; + * writeNetworkDict(0, 0x05, 0x1016, 1, size, &data) // write the data index 1016 subindex 1 of node 5 + * while (getWriteResultNetworkDict (0, 0x05, &abortCode) == SDO_DOWNLOAD_IN_PROGRESS); + * @endcode +*/ +UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode); + +#endif