1 /**
2  * CANopen Service Data Object - client protocol.
3  *
4  * @file        CO_SDOmaster.h
5  * @ingroup     CO_SDOmaster
6  * @author      Janez Paternoster
7  * @author      Matej Severkar
8  * @copyright   2004 - 2020 Janez Paternoster
9  *
10  * This file is part of CANopenNode, an opensource CANopen Stack.
11  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
12  * For more information on CANopen see <http://www.can-cia.org/>.
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  */
26 
27 
28 #ifndef CO_SDO_CLIENT_H
29 #define CO_SDO_CLIENT_H
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /**
36  * @defgroup CO_SDOmaster SDO client
37  * @ingroup CO_CANopen
38  * @{
39  *
40  * CANopen Service Data Object - client protocol.
41  *
42  * @see @ref CO_SDO
43  */
44 
45 
46 /**
47  * Return values of SDO client functions.
48  */
49 typedef enum{
50     /** Transmit buffer is full. Waiting */
51     CO_SDOcli_transmittBufferFull       = 4,
52     /** Block download is in progress. Sending train of messages */
53     CO_SDOcli_blockDownldInProgress     = 3,
54     /** Block upload in progress. Receiving train of messages */
55     CO_SDOcli_blockUploadInProgress     = 2,
56     /** Waiting server response */
57     CO_SDOcli_waitingServerResponse     = 1,
58     /** Success, end of communication */
59     CO_SDOcli_ok_communicationEnd       = 0,
60     /** Error in arguments */
61     CO_SDOcli_wrongArguments            = -2,
62     /** Communication ended with client abort */
63     CO_SDOcli_endedWithClientAbort      = -9,
64     /** Communication ended with server abort */
65     CO_SDOcli_endedWithServerAbort      = -10,
66     /** Communication ended with timeout */
67     CO_SDOcli_endedWithTimeout          = -11
68 }CO_SDOclient_return_t;
69 
70 
71 /**
72  * SDO Client Parameter. The same as record from Object dictionary (index 0x1280+).
73  */
74 typedef struct{
75     /** Equal to 3 */
76     uint8_t             maxSubIndex;
77     /** Communication object identifier for client transmission. Meaning of the specific bits:
78         - Bit 0...10: 11-bit CAN identifier.
79         - Bit 11..30: reserved, set to 0.
80         - Bit 31: if 1, SDO client object is not used. */
81     uint32_t            COB_IDClientToServer;
82     /** Communication object identifier for message received from server. Meaning of the specific bits:
83         - Bit 0...10: 11-bit CAN identifier.
84         - Bit 11..30: reserved, set to 0.
85         - Bit 31: if 1, SDO client object is not used. */
86     uint32_t            COB_IDServerToClient;
87     /** Node-ID of the SDO server */
88     uint8_t             nodeIDOfTheSDOServer;
89 }CO_SDOclientPar_t;
90 
91 
92 /**
93  * SDO client object
94  */
95 typedef struct{
96     /** From CO_SDOclient_init() */
97     CO_SDOclientPar_t  *SDOClientPar;
98     /** From CO_SDOclient_init() */
99     CO_SDO_t           *SDO;
100     /** Internal state of the SDO client */
101     uint8_t             state;
102     /** Pointer to data buffer supplied by user */
103     uint8_t            *buffer;
104     /** By download application indicates data size in buffer.
105     By upload application indicates buffer size */
106     uint32_t            bufferSize;
107     /** Offset in buffer of next data segment being read/written */
108     uint32_t            bufferOffset;
109     /** Acknowledgement */
110     uint32_t            bufferOffsetACK;
111     /** data length to be uploaded in block transfer */
112     uint32_t            dataSize;
113     /** Data length transferred in block transfer */
114     uint32_t            dataSizeTransfered;
115     /** Timeout timer for SDO communication */
116     uint16_t            timeoutTimer;
117     /** Timeout timer for SDO block transfer */
118     uint16_t            timeoutTimerBLOCK;
119     /** Index of current object in Object Dictionary */
120     uint16_t            index;
121     /** Subindex of current object in Object Dictionary */
122     uint8_t             subIndex;
123     /** From CO_SDOclient_init() */
124     CO_CANmodule_t     *CANdevRx;
125     /** From CO_SDOclient_init() */
126     uint16_t            CANdevRxIdx;
127     /** Indicates, if new SDO message received from CAN bus.
128     It is not cleared, until received message is completely processed. */
129     volatile void      *CANrxNew;
130     /** 8 data bytes of the received message */
131     uint8_t             CANrxData[8];
132     /** From CO_SDOclient_initCallback() or NULL */
133     void              (*pFunctSignal)(void);
134     /** From CO_SDOclient_init() */
135     CO_CANmodule_t     *CANdevTx;
136     /** CAN transmit buffer inside CANdevTx for CAN tx message */
137     CO_CANtx_t         *CANtxBuff;
138     /** From CO_SDOclient_init() */
139     uint16_t            CANdevTxIdx;
140     /** Toggle bit toggled with each subsequent in segmented transfer */
141     uint8_t             toggle;
142     /** Server threshold for switch back to segmented transfer, if data size is small.
143     Set in CO_SDOclient_init(). Can be changed by application. 0 Disables switching. */
144     uint8_t             pst;
145     /** Maximum number of segments in one block. Set in CO_SDOclient_init(). Can
146     be changed by application to 2 .. 127. */
147     uint8_t             block_size_max;
148     /** Last sector number */
149     uint8_t             block_seqno;
150     /** Block size in current transfer */
151     uint8_t             block_blksize;
152     /** Number of bytes in last segment that do not contain data */
153     uint8_t             block_noData;
154     /** Server CRC support in block transfer */
155     uint8_t             crcEnabled;
156     /** Previous value of the COB_IDClientToServer */
157     uint32_t            COB_IDClientToServerPrev;
158     /** Previous value of the COB_IDServerToClient */
159     uint32_t            COB_IDServerToClientPrev;
160 
161 }CO_SDOclient_t;
162 
163 
164 /**
165  * Initialize SDO client object.
166  *
167  * Function must be called in the communication reset section.
168  *
169  * @param SDO_C This object will be initialized.
170  * @param SDO SDO server object. It is used in case, if client is accessing
171  * object dictionary from its own device. If NULL, it will be ignored.
172  * @param SDOClientPar Pointer to _SDO Client Parameter_ record from Object
173  * dictionary (index 0x1280+). Will be written.
174  * @param CANdevRx CAN device for SDO client reception.
175  * @param CANdevRxIdx Index of receive buffer in the above CAN device.
176  * @param CANdevTx CAN device for SDO client transmission.
177  * @param CANdevTxIdx Index of transmit buffer in the above CAN device.
178  *
179  * @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
180  */
181 CO_ReturnError_t CO_SDOclient_init(
182         CO_SDOclient_t         *SDO_C,
183         CO_SDO_t               *SDO,
184         CO_SDOclientPar_t      *SDOClientPar,
185         CO_CANmodule_t         *CANdevRx,
186         uint16_t                CANdevRxIdx,
187         CO_CANmodule_t         *CANdevTx,
188         uint16_t                CANdevTxIdx);
189 
190 
191 /**
192  * Initialize SDOclientRx callback function.
193  *
194  * Function initializes optional callback function, which is called after new
195  * message is received from the CAN bus. Function may wake up external task,
196  * which processes mainline CANopen functions.
197  *
198  * @param SDOclient This object.
199  * @param pFunctSignal Pointer to the callback function. Not called if NULL.
200  */
201 void CO_SDOclient_initCallback(
202         CO_SDOclient_t         *SDOclient,
203         void                  (*pFunctSignal)(void));
204 
205 
206 /**
207  * Setup SDO client object.
208  *
209  * Function must be called before new SDO communication. If previous SDO
210  * communication was with the same node, function does not need to be called.
211  *
212  * @remark If configuring SDO client from network is required, this function
213  * should be set as callback for the corresponding SDO client parameter OD
214  * entry.
215  *
216  * @param SDO_C This object.
217  * @param COB_IDClientToServer See CO_SDOclientPar_t. If zero, then
218  * nodeIDOfTheSDOServer is used with default COB-ID.
219  * @param COB_IDServerToClient See CO_SDOclientPar_t. If zero, then
220  * nodeIDOfTheSDOServer is used with default COB-ID.
221  * @param nodeIDOfTheSDOServer Node-ID of the SDO server. If zero, SDO client
222  * object is not used. If it is the same as node-ID of this node, then data will
223  * be exchanged with this node (without CAN communication).
224  *
225  * @return #CO_SDOclient_return_t
226  */
227 CO_SDOclient_return_t CO_SDOclient_setup(
228         CO_SDOclient_t         *SDO_C,
229         uint32_t                COB_IDClientToServer,
230         uint32_t                COB_IDServerToClient,
231         uint8_t                 nodeIDOfTheSDOServer);
232 
233 
234 /**
235  * Initiate SDO download communication.
236  *
237  * Function initiates SDO download communication with server specified in
238  * CO_SDOclient_init() function. Data will be written to remote node.
239  * Function is non-blocking.
240  *
241  * @param SDO_C This object.
242  * @param index Index of object in object dictionary in remote node.
243  * @param subIndex Subindex of object in object dictionary in remote node.
244  * @param dataTx Pointer to data to be written. Data must be valid until end
245  * of communication. Note that data are aligned in little-endian
246  * format, because CANopen itself uses little-endian. Take care,
247  * when using processors with big-endian.
248  * @param dataSize Size of data in dataTx.
249  * @param blockEnable Try to initiate block transfer.
250  *
251  * @return #CO_SDOclient_return_t
252  */
253 CO_SDOclient_return_t CO_SDOclientDownloadInitiate(
254         CO_SDOclient_t         *SDO_C,
255         uint16_t                index,
256         uint8_t                 subIndex,
257         uint8_t                *dataTx,
258         uint32_t                dataSize,
259         uint8_t                 blockEnable);
260 
261 
262 /**
263  * Process SDO download communication.
264  *
265  * Function must be called cyclically until it returns <=0. It Proceeds SDO
266  * download communication initiated with CO_SDOclientDownloadInitiate().
267  * Function is non-blocking.
268  *
269  * @param SDO_C This object.
270  * @param timeDifference_ms Time difference from previous function call in [milliseconds].
271  * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds.
272  * @param pSDOabortCode Pointer to external variable written by this function
273  * in case of error in communication.
274  *
275  * @return #CO_SDOclient_return_t
276  */
277 CO_SDOclient_return_t CO_SDOclientDownload(
278         CO_SDOclient_t         *SDO_C,
279         uint16_t                timeDifference_ms,
280         uint16_t                SDOtimeoutTime,
281         uint32_t               *pSDOabortCode);
282 
283 
284 /**
285  * Initiate SDO upload communication.
286  *
287  * Function initiates SDO upload communication with server specified in
288  * CO_SDOclient_init() function. Data will be read from remote node.
289  * Function is non-blocking.
290  *
291  * @param SDO_C This object.
292  * @param index Index of object in object dictionary in remote node.
293  * @param subIndex Subindex of object in object dictionary in remote node.
294  * @param dataRx Pointer to data buffer, into which received data will be written.
295  * Buffer must be valid until end of communication. Note that data are aligned
296  * in little-endian format, because CANopen itself uses
297  * little-endian. Take care, when using processors with big-endian.
298  * @param dataRxSize Size of dataRx.
299  * @param blockEnable Try to initiate block transfer.
300  *
301  * @return #CO_SDOclient_return_t
302  */
303 CO_SDOclient_return_t CO_SDOclientUploadInitiate(
304         CO_SDOclient_t         *SDO_C,
305         uint16_t                index,
306         uint8_t                 subIndex,
307         uint8_t                *dataRx,
308         uint32_t                dataRxSize,
309         uint8_t                 blockEnable);
310 
311 
312 /**
313  * Process SDO upload communication.
314  *
315  * Function must be called cyclically until it returns <=0. It Proceeds SDO
316  * upload communication initiated with CO_SDOclientUploadInitiate().
317  * Function is non-blocking.
318  *
319  * @param SDO_C This object.
320  * @param timeDifference_ms Time difference from previous function call in [milliseconds].
321  * @param SDOtimeoutTime Timeout time for SDO communication in milliseconds.
322  * @param pDataSize pointer to external variable, where size of received
323  * data will be written.
324  * @param pSDOabortCode Pointer to external variable written by this function
325  * in case of error in communication.
326  *
327  * @return #CO_SDOclient_return_t
328  */
329 CO_SDOclient_return_t CO_SDOclientUpload(
330         CO_SDOclient_t         *SDO_C,
331         uint16_t                timeDifference_ms,
332         uint16_t                SDOtimeoutTime,
333         uint32_t               *pDataSize,
334         uint32_t               *pSDOabortCode);
335 
336 
337 /**
338  * Close SDO communication temporary.
339  *
340  * Function must be called after finish of each SDO client communication cycle.
341  * It disables reception of SDO client CAN messages. It is necessary, because
342  * CO_SDOclient_receive function may otherwise write into undefined SDO buffer.
343  */
344 void CO_SDOclientClose(CO_SDOclient_t *SDO_C);
345 
346 #ifdef __cplusplus
347 }
348 #endif /*__cplusplus*/
349 
350 /** @} */
351 #endif
352