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@149: void _SDOtimeoutError (UNS8); etisserant@149: 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 { frdupin@71: UNS8 nodeId; /*own ID if server, or node ID of the server if client */ etisserant@0: frdupin@71: UNS8 whoami; /* Takes the values SDO_CLIENT or SDO_SERVER */ frdupin@71: UNS8 state; /* state of the transmission : Takes the values SDO_... */ etisserant@0: UNS8 toggle; frdupin@71: UNS32 abortCode; /* Sent or received */ frdupin@71: /* index and subindex of the dictionary where to store */ frdupin@71: /* (for a received SDO) or to read (for a transmit SDO) */ etisserant@0: UNS16 index; etisserant@0: UNS8 subIndex; frdupin@71: UNS32 count; /* Number of data received or to be sent. */ frdupin@71: UNS32 offset; /* stack pointer of data[] frdupin@71: * Used only to tranfer part of a line to or from a SDO. frdupin@71: * offset is always pointing on the next free cell of data[]. frdupin@71: * WARNING s_transfer.data is subject to ENDIANISATION frdupin@71: * (with respect to CANOPEN_BIG_ENDIAN) frdupin@71: */ etisserant@0: UNS8 data [SDO_MAX_LENGTH_TRANSFERT]; frdupin@71: UNS8 dataType; /* Defined in objdictdef.h Value is visible_string frdupin@71: * if it is a string, any other value if it is not a string, frdupin@71: * like 0. In fact, it is used only if client. frdupin@71: */ frdupin@71: TIMER_HANDLE timer; /* Time counter to implement a timeout in milliseconds. frdupin@74: * It is automatically incremented whenever frdupin@74: * the line state is in SDO_DOWNLOAD_IN_PROGRESS or frdupin@74: * SDO_UPLOAD_IN_PROGRESS, and reseted to 0 frdupin@74: * when the response SDO have been received. frdupin@71: */ frdupin@71: 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: frdupin@71: /* The 8 bytes data of the SDO */ etisserant@0: struct BODY{ etisserant@0: UNS8 data[8]; etisserant@0: }; etisserant@0: frdupin@71: /* The SDO structure ...*/ etisserant@0: struct struct_s_SDO { frdupin@71: 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: frdupin@53: /** Reset of a SDO exchange on timeout. frdupin@53: * Send a SDO abort frdupin@53: */ frdupin@53: void SDOTimeoutAlarm(CO_Data* d, UNS32 id); frdupin@53: 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); frdupin@53: /** Used to send a SDO request frame to write in a distant node dictionnary. frdupin@53: * The function Callback which must be defined in the user code is called at the frdupin@53: * end of the exchange. (on succes or abort). frdupin@53: */ frdupin@53: UNS8 writeNetworkDictCallBack (CO_Data* d, UNS8 nodeId, UNS16 index, frdupin@53: UNS8 subIndex, UNS8 count, UNS8 dataType, void *data, SDOCallback_t Callback); 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); frdupin@53: frdupin@53: /** Used to send a SDO request frame to read in a distant node dictionnary. frdupin@53: * The function Callback which must be defined in the user code is called at the frdupin@53: * end of the exchange. (on succes or abort). frdupin@53: */ frdupin@53: UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback); 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: frdupin@53: frdupin@53: frdupin@53: etisserant@0: #endif