etisserant@0: /* etisserant@0: This file is part of CanFestival, a library implementing CanOpen Stack. etisserant@0: etisserant@0: Copyright (C): Edouard TISSERANT and Francis DUPIN etisserant@0: etisserant@0: See COPYING file for copyrights details. etisserant@0: etisserant@0: This library is free software; you can redistribute it and/or etisserant@0: modify it under the terms of the GNU Lesser General Public etisserant@0: License as published by the Free Software Foundation; either etisserant@0: version 2.1 of the License, or (at your option) any later version. etisserant@0: etisserant@0: This library is distributed in the hope that it will be useful, etisserant@0: but WITHOUT ANY WARRANTY; without even the implied warranty of etisserant@0: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU etisserant@0: Lesser General Public License for more details. etisserant@0: etisserant@0: You should have received a copy of the GNU Lesser General Public etisserant@0: License along with this library; if not, write to the Free Software etisserant@0: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA etisserant@0: */ etisserant@0: etisserant@0: #ifndef __sdo_h__ etisserant@0: #define __sdo_h__ etisserant@0: etisserant@0: typedef void (*SDOtimeoutError_t)(UNS8 line); etisserant@0: struct struct_s_transfer; etisserant@0: etisserant@0: #include "timer.h" etisserant@0: etisserant@32: typedef void (*SDOCallback_t)(CO_Data* d, UNS8 nodeId); etisserant@32: etisserant@0: /* The Transfer structure etisserant@0: Used to store the different segments of etisserant@0: - a SDO received before writing in the dictionary etisserant@0: - the reading of the dictionary to put on a SDO to transmit etisserant@0: */ etisserant@0: etisserant@0: struct struct_s_transfer { etisserant@0: UNS8 nodeId; //own ID if server, or node ID of the server if client etisserant@0: etisserant@0: UNS8 whoami; // Takes the values SDO_CLIENT or SDO_SERVER etisserant@0: UNS8 state; // state of the transmission : Takes the values SDO_... etisserant@0: UNS8 toggle; etisserant@0: UNS32 abortCode; // Sent or received etisserant@0: // index and subindex of the dictionary where to store etisserant@0: // (for a received SDO) or to read (for a transmit SDO) etisserant@0: UNS16 index; etisserant@0: UNS8 subIndex; etisserant@0: UNS32 count; // Number of data received or to be sent. etisserant@0: UNS32 offset; // stack pointer of data[] etisserant@0: // Used only to tranfer part of a line to or from a SDO. etisserant@0: // offset is always pointing on the next free cell of data[]. etisserant@0: // WARNING s_transfer.data is subject to ENDIANISATION etisserant@0: // (with respect to CANOPEN_BIG_ENDIAN) etisserant@0: UNS8 data [SDO_MAX_LENGTH_TRANSFERT]; etisserant@0: UNS8 dataType; // Defined in objdictdef.h Value is visible_string etisserant@0: // if it is a string, any other value if it is not a string, etisserant@0: // like 0. In fact, it is used only if client. etisserant@0: TIMER_HANDLE timer; // Time counter to implement a timeout in milliseconds. etisserant@0: // It is automatically incremented whenever etisserant@0: // the line state is in SDO_DOWNLOAD_IN_PROGRESS or etisserant@0: // SDO_UPLOAD_IN_PROGRESS, and reseted to 0 etisserant@0: // when the response SDO have been received. etisserant@32: SDOCallback_t Callback; // The user callback func to be called at SDO transaction end etisserant@0: }; etisserant@0: typedef struct struct_s_transfer s_transfer; etisserant@0: etisserant@0: etisserant@0: #include "data.h" etisserant@0: etisserant@0: /// The 8 bytes data of the SDO etisserant@0: struct BODY{ etisserant@0: UNS8 data[8]; etisserant@0: }; etisserant@0: etisserant@0: /// The SDO structure ... etisserant@0: struct struct_s_SDO { etisserant@0: UNS8 nodeId; //in any case, Node ID of the server (case sender or receiver). etisserant@0: struct BODY body; etisserant@0: }; etisserant@0: etisserant@0: etisserant@0: typedef struct struct_s_SDO s_SDO; etisserant@0: etisserant@0: /** Reset all sdo buffers etisserant@0: */ etisserant@0: void resetSDO (CO_Data* d); etisserant@0: etisserant@0: etisserant@0: /** Copy the data received from the SDO line transfert to the object dictionary etisserant@0: * Returns SDO error code if error. Else, returns 0; etisserant@0: */ etisserant@0: UNS32 SDOlineToObjdict (CO_Data* d, UNS8 line); etisserant@0: etisserant@0: /** Copy the data from the object dictionary to the SDO line for a network transfert. etisserant@0: * Returns SDO error code if error. Else, returns 0; etisserant@0: */ etisserant@0: UNS32 objdictToSDOline (CO_Data* d, UNS8 line); etisserant@0: etisserant@0: /** copy data from an existant line in the argument "* data" etisserant@0: * Returns 0xFF if error. Else, returns 0; etisserant@0: */ etisserant@0: UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8 * data); etisserant@0: etisserant@0: /** Add data to an existant line etisserant@0: * Returns 0xFF if error. Else, returns 0; etisserant@0: */ etisserant@0: UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS8 nbBytes, UNS8 * data); etisserant@0: etisserant@0: /** Called when an internal SDO abort occurs. etisserant@0: * Release the line * Only if server * etisserant@0: * If client, the line must be released manually in the core application. etisserant@0: * The reason of that is to permit the program to read the transfers[][] structure before its reset, etisserant@0: * because many informations are stored on it : index, subindex, data received or trasmited, ... etisserant@0: * In all cases, sends a SDO abort. etisserant@0: * Returns 0 etisserant@0: */ etisserant@0: UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index, etisserant@0: UNS8 subIndex, UNS32 abortCode); etisserant@0: etisserant@0: /** Reset an unused line. etisserant@0: * etisserant@0: */ etisserant@0: void resetSDOline (CO_Data* d, UNS8 line); etisserant@0: etisserant@0: /** Initialize some fields of the structure. etisserant@0: * Returns 0 etisserant@0: */ etisserant@0: UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state); etisserant@0: etisserant@0: /** Search for an unused line in the transfers array etisserant@0: * to store a new SDO. etisserant@0: * ie a line which value of the field "state" is "SDO_RESET" etisserant@0: * An unused line have the field "state" at the value SDO_RESET etisserant@0: * bus_id is hardware dependant etisserant@0: * whoami : create the line for a SDO_SERVER or SDO_CLIENT. etisserant@0: * return 0xFF if all the lines are on use. Else, return 0 etisserant@0: */ etisserant@0: UNS8 getSDOfreeLine (CO_Data* d, UNS8 whoami, UNS8 *line); etisserant@0: etisserant@0: /** Search for the line, in the transfers array, which contains the etisserant@0: * beginning of the reception of a fragmented SDO etisserant@0: * whoami takes 2 values : look for a line opened as SDO_CLIENT or SDO_SERVER etisserant@0: * bus_id is hardware dependant etisserant@0: * nodeId correspond to the message node-id etisserant@0: * return 0xFF if error. Else, return 0 etisserant@0: */ etisserant@0: UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line); etisserant@0: etisserant@0: /** Close a transmission. etisserant@0: * nodeId : Node id of the server if both server or client etisserant@0: * whoami : Line opened as SDO_CLIENT or SDO_SERVER etisserant@0: */ etisserant@0: UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami); etisserant@0: etisserant@0: /** Bytes in the line structure which must be transmited (or received) etisserant@0: * bus_id is hardware dependant. etisserant@0: * return 0. etisserant@0: */ etisserant@0: UNS8 getSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 * nbBytes); etisserant@0: etisserant@0: /** Store in the line structure the nb of bytes which must be transmited (or received) etisserant@0: * bus_id is hardware dependant. etisserant@0: * return 0 if success, 0xFF if error. etisserant@0: */ etisserant@0: UNS8 setSDOlineRestBytes (CO_Data* d, UNS8 line, UNS8 nbBytes); etisserant@0: etisserant@0: /** Transmit a SDO frame on the bus bus_id etisserant@0: * sdo is a structure which contains the sdo to transmit etisserant@0: * bus_id is hardware dependant etisserant@0: * whoami takes 2 values : SDO_CLIENT or SDO_SERVER etisserant@0: * return canSend(bus_id,&m) or 0xFF if error etisserant@0: */ etisserant@0: UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo); etisserant@0: etisserant@0: /** Transmit a SDO error to the client. The reasons may be : etisserant@0: * Read/Write to a undefined object etisserant@0: * Read/Write to a undefined subindex etisserant@0: * Read/write a not valid length object etisserant@0: * Write a read only object etisserant@0: * whoami takes 2 values : SDO_CLIENT or SDO_SERVER etisserant@0: */ etisserant@0: UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode); etisserant@0: etisserant@0: /** Treat a SDO frame reception etisserant@0: * bus_id is hardware dependant etisserant@0: * call the function sendSDO etisserant@0: * return 0xFF if error etisserant@0: * 0x80 if transfert aborted by the server etisserant@0: * 0x0 ok etisserant@0: */ etisserant@0: UNS8 proceedSDO (CO_Data* d, Message *m); etisserant@0: etisserant@0: /** Used by the application to send a SDO request frame to write the data *data etisserant@0: * at the index and subIndex indicated etisserant@0: * in the dictionary of the slave whose node_id is nodeId etisserant@0: * Count : nb of bytes to write in the dictionnary. etisserant@0: * datatype (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. etisserant@0: * bus_id is hardware dependant etisserant@0: * return 0xFF if error, else return 0 etisserant@0: */ etisserant@0: UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, etisserant@0: UNS8 subIndex, UNS8 count, UNS8 dataType, void *data); etisserant@0: etisserant@0: /** Used by the application to send a SDO request frame to read etisserant@0: * in the dictionary of a server node whose node_id is ID etisserant@0: * at the index and subIndex indicated etisserant@0: * bus_id is hardware dependant etisserant@0: * datatype (defined in objdictdef.h) : put "visible_string" for strings, 0 for integers or reals or other value. etisserant@0: * return 0xFF if error, else return 0 etisserant@0: */ etisserant@0: UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, etisserant@0: UNS8 subIndex, UNS8 dataType); etisserant@0: etisserant@0: /** Use this function after a readNetworkDict to get the result. etisserant@0: Returns : SDO_FINISHED // data is available etisserant@0: SDO_ABORTED_RCV // Transfert failed. (abort SDO received) etisserant@0: SDO_ABORTED_INTERNAL // Transfert failed. Internal abort. etisserant@0: SDO_UPLOAD_IN_PROGRESS // Data not yet available etisserant@0: SDO_DOWNLOAD_IN_PROGRESS // Should not arrive ! etisserant@0: etisserant@0: dataType (defined in objdictdef.h) : type expected. put "visible_string" for strings, 0 for integers or reals. etisserant@0: abortCode : 0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV) etisserant@0: example : etisserant@0: UNS32 data; etisserant@0: UNS8 size; etisserant@0: readNetworkDict(0, 0x05, 0x1016, 1, 0) // get the data index 1016 subindex 1 of node 5 etisserant@0: while (getReadResultNetworkDict (0, 0x05, &data, &size) != SDO_UPLOAD_IN_PROGRESS); etisserant@0: */ etisserant@0: UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, etisserant@0: UNS8 *size, UNS32 * abortCode); etisserant@0: etisserant@0: /** etisserant@0: Use this function after a writeNetworkDict to get the result of the write etisserant@0: It is mandatory to call this function because it is releasing the line used for the transfer. etisserant@0: Returns : SDO_FINISHED // data is available etisserant@0: SDO_ABORTED_RCV // Transfert failed. (abort SDO received) etisserant@0: SDO_ABORTED_INTERNAL // Transfert failed. Internal abort. etisserant@0: SDO_DOWNLOAD_IN_PROGRESS // Data not yet available etisserant@0: SDO_UPLOAD_IN_PROGRESS // Should not arrive ! etisserant@0: abortCode : 0 = not available. Else : SDO abort code. (received if return SDO_ABORTED_RCV) etisserant@0: example : etisserant@0: UNS32 data = 0x50; etisserant@0: UNS8 size; etisserant@0: UNS32 abortCode; etisserant@0: writeNetworkDict(0, 0x05, 0x1016, 1, size, &data) // write the data index 1016 subindex 1 of node 5 etisserant@0: while ( getWriteResultNetworkDict (0, 0x05, &abortCode) != SDO_DOWNLOAD_IN_PROGRESS); etisserant@0: */ etisserant@0: UNS8 getWriteResultNetworkDict (CO_Data* d, UNS8 nodeId, UNS32 * abortCode); etisserant@0: etisserant@0: #endif