1 /*
2 * CANopen Service Data Object - client.
3 *
4 * @file CO_SDOmaster.c
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 #include "CO_driver.h"
29 #include "CO_SDO.h"
30 #include "CO_SDOmaster.h"
31 #include "crc16-ccitt.h"
32
33
34 /* Client command specifier */
35 #define CCS_DOWNLOAD_INITIATE 1
36 #define CCS_DOWNLOAD_SEGMENT 0
37
38 #define CCS_UPLOAD_INITIATE 2
39 #define CCS_UPLOAD_SEGMENT 3
40
41 #define CCS_ABORT 4
42
43 #define CCS_UPLOAD_BLOCK 5
44 #define CCS_DOWNLOAD_BLOCK 6
45
46 /* Server Command Specifier */
47 #define SCS_UPLOAD_INITIATE 2
48 #define SCS_UPLOAD_SEGMENT 0
49
50 #define SCS_DOWNLOAD_INITIATED 3
51 #define SCS_DOWNLOAD_SEGMENT 1
52
53 #define SCS_ABORT 4
54
55 #define SCS_DOWNLOAD_BLOCK 5
56 #define SCS_UPLOAD_BLOCK 6
57
58
59 /* client states */
60 #define SDO_STATE_NOTDEFINED 0
61 #define SDO_STATE_ABORT 1
62
63 /* DOWNLOAD EXPEDITED/SEGMENTED */
64 #define SDO_STATE_DOWNLOAD_INITIATE 10
65 #define SDO_STATE_DOWNLOAD_REQUEST 11
66 #define SDO_STATE_DOWNLOAD_RESPONSE 12
67
68 /* UPLOAD EXPEDITED/SEGMENTED */
69 #define SDO_STATE_UPLOAD_INITIATED 20
70 #define SDO_STATE_UPLOAD_REQUEST 21
71 #define SDO_STATE_UPLOAD_RESPONSE 22
72
73 /* DOWNLOAD BLOCK */
74 #define SDO_STATE_BLOCKDOWNLOAD_INITIATE 100
75 #define SDO_STATE_BLOCKDOWNLOAD_INPROGRES 101
76 #define SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK 102
77 #define SDO_STATE_BLOCKDOWNLOAD_CRC 103
78 #define SDO_STATE_BLOCKDOWNLOAD_CRC_ACK 104
79
80 /* UPLOAD BLOCK */
81 #define SDO_STATE_BLOCKUPLOAD_INITIATE 200
82 #define SDO_STATE_BLOCKUPLOAD_INITIATE_ACK 201
83 #define SDO_STATE_BLOCKUPLOAD_INPROGRES 202
84 #define SDO_STATE_BLOCKUPLOAD_SUB_END 203
85 #define SDO_STATE_BLOCKUPLOAD_BLOCK_ACK 204
86 #define SDO_STATE_BLOCKUPLOAD_BLOCK_ACK_LAST 205
87 #define SDO_STATE_BLOCKUPLOAD_BLOCK_CRC 206
88 #define SDO_STATE_BLOCKUPLOAD_BLOCK_END 207
89
90
91 /*
92 * Read received message from CAN module.
93 *
94 * Function will be called (by CAN receive interrupt) every time, when CAN
95 * message with correct identifier will be received. For more information and
96 * description of parameters see file CO_driver.h.
97 */
CO_SDOclient_receive(void * object,const CO_CANrxMsg_t * msg)98 static void CO_SDOclient_receive(void *object, const CO_CANrxMsg_t *msg){
99 CO_SDOclient_t *SDO_C;
100
101 SDO_C = (CO_SDOclient_t*)object; /* this is the correct pointer type of the first argument */
102
103 /* verify message length and message overflow (previous message was not processed yet) */
104 if((msg->DLC == 8U) && (!IS_CANrxNew(SDO_C->CANrxNew)) && (SDO_C->state != SDO_STATE_NOTDEFINED)){
105 if(SDO_C->state != SDO_STATE_BLOCKUPLOAD_INPROGRES) {
106 /* copy data and set 'new message' flag */
107 SDO_C->CANrxData[0] = msg->data[0];
108 SDO_C->CANrxData[1] = msg->data[1];
109 SDO_C->CANrxData[2] = msg->data[2];
110 SDO_C->CANrxData[3] = msg->data[3];
111 SDO_C->CANrxData[4] = msg->data[4];
112 SDO_C->CANrxData[5] = msg->data[5];
113 SDO_C->CANrxData[6] = msg->data[6];
114 SDO_C->CANrxData[7] = msg->data[7];
115
116 SET_CANrxNew(SDO_C->CANrxNew);
117 }
118 else {
119 /* block upload, copy data directly */
120 uint8_t seqno;
121
122 SDO_C->CANrxData[0] = msg->data[0];
123 seqno = SDO_C->CANrxData[0] & 0x7f;
124 SDO_C->timeoutTimer = 0;
125 SDO_C->timeoutTimerBLOCK = 0;
126
127 /* check correct sequence number. */
128 if(seqno == (SDO_C->block_seqno + 1)) {
129 /* block_seqno is correct */
130 uint8_t i;
131
132 SDO_C->block_seqno++;
133
134 /* copy data */
135 for(i=1; i<8; i++) {
136 SDO_C->buffer[SDO_C->dataSizeTransfered++] = msg->data[i];
137 if(SDO_C->dataSizeTransfered >= SDO_C->bufferSize) {
138 /* buffer full, break reception */
139 SDO_C->state = SDO_STATE_BLOCKUPLOAD_SUB_END;
140 SET_CANrxNew(SDO_C->CANrxNew);
141 break;
142 }
143 }
144
145 /* break reception if last segment or block sequence is too large */
146 if(((SDO_C->CANrxData[0] & 0x80U) == 0x80U) || (SDO_C->block_seqno >= SDO_C->block_blksize)) {
147 SDO_C->state = SDO_STATE_BLOCKUPLOAD_SUB_END;
148 SET_CANrxNew(SDO_C->CANrxNew);
149 }
150 }
151 else if((seqno == SDO_C->block_seqno) || (SDO_C->block_seqno == 0U)){
152 /* Ignore message, if it is duplicate or if sequence didn't started yet. */
153 }
154 else {
155 /* seqno is totally wrong, break reception. */
156 SDO_C->state = SDO_STATE_BLOCKUPLOAD_SUB_END;
157 SET_CANrxNew(SDO_C->CANrxNew);
158 }
159 }
160
161 /* Optional signal to RTOS, which can resume task, which handles SDO client. */
162 if(IS_CANrxNew(SDO_C->CANrxNew) && SDO_C->pFunctSignal != NULL) {
163 SDO_C->pFunctSignal();
164 }
165 }
166 }
167
168
169 /******************************************************************************/
CO_SDOclient_init(CO_SDOclient_t * SDO_C,CO_SDO_t * SDO,CO_SDOclientPar_t * SDOClientPar,CO_CANmodule_t * CANdevRx,uint16_t CANdevRxIdx,CO_CANmodule_t * CANdevTx,uint16_t CANdevTxIdx)170 CO_ReturnError_t CO_SDOclient_init(
171 CO_SDOclient_t *SDO_C,
172 CO_SDO_t *SDO,
173 CO_SDOclientPar_t *SDOClientPar,
174 CO_CANmodule_t *CANdevRx,
175 uint16_t CANdevRxIdx,
176 CO_CANmodule_t *CANdevTx,
177 uint16_t CANdevTxIdx)
178 {
179 /* verify arguments */
180 if(SDO_C==NULL || SDO==NULL || SDOClientPar==NULL || SDOClientPar->maxSubIndex!=3 ||
181 CANdevRx==NULL || CANdevTx==NULL){
182 return CO_ERROR_ILLEGAL_ARGUMENT;
183 }
184
185 /* Configure object variables */
186 SDO_C->state = SDO_STATE_NOTDEFINED;
187 CLEAR_CANrxNew(SDO_C->CANrxNew);
188
189 SDO_C->pst = 21; /* block transfer */
190 SDO_C->block_size_max = 127; /* block transfer */
191
192 SDO_C->SDO = SDO;
193 SDO_C->SDOClientPar = SDOClientPar;
194
195 SDO_C->pFunctSignal = NULL;
196
197 SDO_C->CANdevRx = CANdevRx;
198 SDO_C->CANdevRxIdx = CANdevRxIdx;
199 SDO_C->CANdevTx = CANdevTx;
200 SDO_C->CANdevTxIdx = CANdevTxIdx;
201
202 SDO_C->COB_IDClientToServerPrev = 0;
203 SDO_C->COB_IDServerToClientPrev = 0;
204 CO_SDOclient_setup(SDO_C, SDO_C->SDOClientPar->COB_IDClientToServer,
205 SDO_C->SDOClientPar->COB_IDServerToClient,
206 SDO_C->SDOClientPar->nodeIDOfTheSDOServer);
207
208 return CO_ERROR_NO;
209 }
210
211
212 /******************************************************************************/
CO_SDOclient_initCallback(CO_SDOclient_t * SDOclient,void (* pFunctSignal)(void))213 void CO_SDOclient_initCallback(
214 CO_SDOclient_t *SDOclient,
215 void (*pFunctSignal)(void))
216 {
217 if(SDOclient != NULL){
218 SDOclient->pFunctSignal = pFunctSignal;
219 }
220 }
221
222
223 /******************************************************************************/
CO_SDOclient_setup(CO_SDOclient_t * SDO_C,uint32_t COB_IDClientToServer,uint32_t COB_IDServerToClient,uint8_t nodeIDOfTheSDOServer)224 CO_SDOclient_return_t CO_SDOclient_setup(
225 CO_SDOclient_t *SDO_C,
226 uint32_t COB_IDClientToServer,
227 uint32_t COB_IDServerToClient,
228 uint8_t nodeIDOfTheSDOServer)
229 {
230 uint32_t idCtoS, idStoC;
231 uint8_t idNode;
232
233 /* verify parameters */
234 if(SDO_C == NULL || (COB_IDClientToServer&0x7FFFF800L) != 0 ||
235 (COB_IDServerToClient&0x7FFFF800L) != 0 || nodeIDOfTheSDOServer > 127)
236 {
237 return CO_SDOcli_wrongArguments;
238 }
239
240 /* Configure object variables */
241 SDO_C->state = SDO_STATE_NOTDEFINED;
242 CLEAR_CANrxNew(SDO_C->CANrxNew);
243
244 /* setup Object Dictionary variables */
245 if((COB_IDClientToServer & 0x80000000L) != 0 || (COB_IDServerToClient & 0x80000000L) != 0 || nodeIDOfTheSDOServer == 0){
246 /* SDO is NOT used */
247 idCtoS = 0x80000000L;
248 idStoC = 0x80000000L;
249 idNode = 0;
250 }
251 else{
252 if(COB_IDClientToServer == 0 || COB_IDServerToClient == 0){
253 idCtoS = 0x600 + nodeIDOfTheSDOServer;
254 idStoC = 0x580 + nodeIDOfTheSDOServer;
255 }
256 else{
257 idCtoS = COB_IDClientToServer;
258 idStoC = COB_IDServerToClient;
259 }
260 idNode = nodeIDOfTheSDOServer;
261 }
262
263 SDO_C->SDOClientPar->COB_IDClientToServer = idCtoS;
264 SDO_C->SDOClientPar->COB_IDServerToClient = idStoC;
265 SDO_C->SDOClientPar->nodeIDOfTheSDOServer = idNode;
266
267 /* configure SDO client CAN reception, if differs. */
268 if(SDO_C->COB_IDClientToServerPrev != idCtoS || SDO_C->COB_IDServerToClientPrev != idStoC) {
269 CO_CANrxBufferInit(
270 SDO_C->CANdevRx, /* CAN device */
271 SDO_C->CANdevRxIdx, /* rx buffer index */
272 (uint16_t)idStoC, /* CAN identifier */
273 0x7FF, /* mask */
274 0, /* rtr */
275 (void*)SDO_C, /* object passed to receive function */
276 CO_SDOclient_receive); /* this function will process received message */
277
278 /* configure SDO client CAN transmission */
279 SDO_C->CANtxBuff = CO_CANtxBufferInit(
280 SDO_C->CANdevTx, /* CAN device */
281 SDO_C->CANdevTxIdx, /* index of specific buffer inside CAN module */
282 (uint16_t)idCtoS, /* CAN identifier */
283 0, /* rtr */
284 8, /* number of data bytes */
285 0); /* synchronous message flag bit */
286
287 SDO_C->COB_IDClientToServerPrev = idCtoS;
288 SDO_C->COB_IDServerToClientPrev = idStoC;
289 }
290
291 return CO_SDOcli_ok_communicationEnd;
292 }
293
294
295 /******************************************************************************/
CO_SDOclient_abort(CO_SDOclient_t * SDO_C,uint32_t code)296 static void CO_SDOclient_abort(CO_SDOclient_t *SDO_C, uint32_t code){
297 SDO_C->CANtxBuff->data[0] = 0x80;
298 SDO_C->CANtxBuff->data[1] = SDO_C->index & 0xFF;
299 SDO_C->CANtxBuff->data[2] = (SDO_C->index>>8) & 0xFF;
300 SDO_C->CANtxBuff->data[3] = SDO_C->subIndex;
301 CO_memcpySwap4(&SDO_C->CANtxBuff->data[4], &code);
302 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
303 SDO_C->state = SDO_STATE_NOTDEFINED;
304 CLEAR_CANrxNew(SDO_C->CANrxNew);
305 }
306
307
308 /******************************************************************************/
CO_SDOTxBufferClear(CO_SDOclient_t * SDO_C)309 static void CO_SDOTxBufferClear(CO_SDOclient_t *SDO_C) {
310 uint16_t i;
311
312 for(i=0; i<8; i++) {
313 SDO_C->CANtxBuff->data[i] = 0;
314 }
315 SDO_C->CANtxBuff->bufferFull = 0;
316 }
317
318
319 /*******************************************************************************
320 *
321 * DOWNLOAD
322 *
323 *
324 ******************************************************************************/
CO_SDOclientDownloadInitiate(CO_SDOclient_t * SDO_C,uint16_t index,uint8_t subIndex,uint8_t * dataTx,uint32_t dataSize,uint8_t blockEnable)325 CO_SDOclient_return_t CO_SDOclientDownloadInitiate(
326 CO_SDOclient_t *SDO_C,
327 uint16_t index,
328 uint8_t subIndex,
329 uint8_t *dataTx,
330 uint32_t dataSize,
331 uint8_t blockEnable)
332 {
333 /* verify parameters */
334 if(SDO_C == NULL || dataTx == 0 || dataSize == 0) {
335 return CO_SDOcli_wrongArguments;
336 }
337
338 /* save parameters */
339 SDO_C->buffer = dataTx;
340 SDO_C->bufferSize = dataSize;
341
342 SDO_C->state = SDO_STATE_DOWNLOAD_INITIATE;
343
344 /* prepare CAN tx message */
345 CO_SDOTxBufferClear(SDO_C);
346
347 SDO_C->index = index;
348 SDO_C->subIndex = subIndex;
349 SDO_C->CANtxBuff->data[1] = index & 0xFF;
350 SDO_C->CANtxBuff->data[2] = index >> 8;
351 SDO_C->CANtxBuff->data[3] = subIndex;
352
353 /* if nodeIDOfTheSDOServer == node-ID of this node, then exchange data with this node */
354 if(SDO_C->SDOClientPar->nodeIDOfTheSDOServer == SDO_C->SDO->nodeId){
355
356 /* Optional signal to RTOS. We can immediately continue SDO Client */
357 if(SDO_C->pFunctSignal != NULL) {
358 SDO_C->pFunctSignal();
359 }
360
361 return CO_SDOcli_ok_communicationEnd;
362 }
363
364 if(dataSize <= 4){
365 uint16_t i;
366 /* expedited transfer */
367 SDO_C->CANtxBuff->data[0] = 0x23 | ((4-dataSize) << 2);
368
369 /* copy data */
370 for(i=dataSize+3; i>=4; i--) SDO_C->CANtxBuff->data[i] = dataTx[i-4];
371 }
372 else if((SDO_C->bufferSize > SDO_C->pst) && blockEnable != 0){ /* BLOCK transfer */
373 /* set state of block transfer */
374 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_INITIATE;
375
376 /* init HEAD of packet */
377 SDO_C->CANtxBuff->data[0] = CCS_DOWNLOAD_BLOCK<<5;
378 /* set flag for CRC */
379 SDO_C->CANtxBuff->data[0] |= 0x01<<2;
380
381 /* size indicator: */
382 SDO_C->CANtxBuff->data[0] |= 0x01<<1;
383 /* set length of data */
384 SDO_C->CANtxBuff->data[4] = (uint8_t) dataSize;
385 SDO_C->CANtxBuff->data[5] = (uint8_t) (dataSize >> 8);
386 SDO_C->CANtxBuff->data[6] = (uint8_t) (dataSize >> 16);
387 SDO_C->CANtxBuff->data[7] = (uint8_t) (dataSize >> 24);
388
389 }
390 else{
391 uint32_t len;
392 /* segmented transfer */
393 SDO_C->CANtxBuff->data[0] = 0x21;
394 len = dataSize;
395 CO_memcpySwap4(&SDO_C->CANtxBuff->data[4], &len);
396 }
397
398 /* empty receive buffer, reset timeout timer and send message */
399 CLEAR_CANrxNew(SDO_C->CANrxNew);
400 SDO_C->timeoutTimer = 0;
401 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
402
403 return CO_SDOcli_ok_communicationEnd;
404 }
405
406
407 /******************************************************************************/
CO_SDOclientDownload(CO_SDOclient_t * SDO_C,uint16_t timeDifference_ms,uint16_t SDOtimeoutTime,uint32_t * pSDOabortCode)408 CO_SDOclient_return_t CO_SDOclientDownload(
409 CO_SDOclient_t *SDO_C,
410 uint16_t timeDifference_ms,
411 uint16_t SDOtimeoutTime,
412 uint32_t *pSDOabortCode)
413 {
414 CO_SDOclient_return_t ret = CO_SDOcli_waitingServerResponse;
415
416 /* verify parameters */
417 if(SDO_C == NULL) {
418 return CO_SDOcli_wrongArguments;
419 }
420
421 /* clear abort code */
422 *pSDOabortCode = CO_SDO_AB_NONE;
423
424 /* if nodeIDOfTheSDOServer == node-ID of this node, then exchange data with this node */
425 if(SDO_C->SDO && SDO_C->SDOClientPar->nodeIDOfTheSDOServer == SDO_C->SDO->nodeId){
426 SDO_C->state = SDO_STATE_NOTDEFINED;
427 CLEAR_CANrxNew(SDO_C->CANrxNew);
428
429 /* If SDO server is busy return error */
430 if(SDO_C->SDO->state != 0){
431 return CO_SDOcli_endedWithClientAbort;
432 }
433
434 /* init ODF_arg */
435 *pSDOabortCode = CO_SDO_initTransfer(SDO_C->SDO, SDO_C->index, SDO_C->subIndex);
436 if((*pSDOabortCode) != CO_SDO_AB_NONE){
437 return CO_SDOcli_endedWithServerAbort;
438 }
439
440 /* set buffer */
441 SDO_C->SDO->ODF_arg.data = SDO_C->buffer;
442
443 /* write data to the Object dictionary */
444 *pSDOabortCode = CO_SDO_writeOD(SDO_C->SDO, SDO_C->bufferSize);
445 if((*pSDOabortCode) != CO_SDO_AB_NONE){
446 return CO_SDOcli_endedWithServerAbort;
447 }
448
449 return CO_SDOcli_ok_communicationEnd;
450 }
451
452
453 /* RX data ****************************************************************************************** */
454 if(IS_CANrxNew(SDO_C->CANrxNew)){
455 uint8_t SCS = SDO_C->CANrxData[0]>>5; /* Client command specifier */
456
457 /* ABORT */
458 if (SDO_C->CANrxData[0] == (SCS_ABORT<<5)){
459 SDO_C->state = SDO_STATE_NOTDEFINED;
460 CO_memcpySwap4(pSDOabortCode , &SDO_C->CANrxData[4]);
461 CLEAR_CANrxNew(SDO_C->CANrxNew);
462 return CO_SDOcli_endedWithServerAbort;
463 }
464
465 switch (SDO_C->state){
466
467 case SDO_STATE_DOWNLOAD_INITIATE:{
468
469 if (SCS == SCS_DOWNLOAD_INITIATED){
470 if(SDO_C->bufferSize <= 4){
471 /* expedited transfer */
472 SDO_C->state = SDO_STATE_NOTDEFINED;
473 CLEAR_CANrxNew(SDO_C->CANrxNew);
474 return CO_SDOcli_ok_communicationEnd;
475 }
476 else{
477 /* segmented transfer - prepare the first segment */
478 SDO_C->bufferOffset = 0;
479 SDO_C->toggle =0;
480 SDO_C->state = SDO_STATE_DOWNLOAD_REQUEST;
481 }
482 }
483 else{
484 *pSDOabortCode = CO_SDO_AB_CMD;
485 SDO_C->state = SDO_STATE_ABORT;
486 }
487 break;
488 }
489
490 case SDO_STATE_DOWNLOAD_RESPONSE:{
491
492 if (SCS == SCS_DOWNLOAD_SEGMENT){
493 /* verify toggle bit */
494 if((SDO_C->CANrxData[0]&0x10) != (SDO_C->toggle<<4)){
495 *pSDOabortCode = CO_SDO_AB_TOGGLE_BIT;
496 SDO_C->state = SDO_STATE_ABORT;
497 break;
498 }
499 /* alternate toggle bit */
500 if (SDO_C->toggle ==0x00)
501 SDO_C->toggle =0x01;
502 else
503 SDO_C->toggle =0x00;
504
505 /* is end of transfer? */
506 if(SDO_C->bufferOffset == SDO_C->bufferSize){
507 SDO_C->state = SDO_STATE_NOTDEFINED;
508 CLEAR_CANrxNew(SDO_C->CANrxNew);
509 return CO_SDOcli_ok_communicationEnd;
510 }
511 SDO_C->state = SDO_STATE_DOWNLOAD_REQUEST;
512 }
513 else{
514 *pSDOabortCode = CO_SDO_AB_CMD;
515 SDO_C->state = SDO_STATE_ABORT;
516 }
517 break;
518 }
519
520 case SDO_STATE_BLOCKDOWNLOAD_INITIATE:{ /* waiting on reply on block download initiated */
521 if (SCS == SCS_DOWNLOAD_BLOCK){
522 uint16_t IndexTmp;
523 IndexTmp = SDO_C->CANrxData[2];
524 IndexTmp = IndexTmp << 8;
525 IndexTmp |= SDO_C->CANrxData[1];
526
527 if(IndexTmp != SDO_C->index || SDO_C->CANrxData[3] != SDO_C->subIndex) {
528 /* wrong index */
529 *pSDOabortCode = CO_SDO_AB_PRAM_INCOMPAT;
530 SDO_C->state = SDO_STATE_ABORT;
531 break;
532 }
533 /* set blksize */
534 SDO_C->block_blksize = SDO_C->CANrxData[4];
535
536 SDO_C->block_seqno = 0;
537 SDO_C->bufferOffset = 0;
538 SDO_C->bufferOffsetACK = 0;
539 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_INPROGRES;
540 }
541 else{
542 *pSDOabortCode = CO_SDO_AB_CMD;
543 SDO_C->state = SDO_STATE_ABORT;
544 }
545 break;
546 }
547
548 case SDO_STATE_BLOCKDOWNLOAD_INPROGRES:
549 case SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK:{ /* waiting block ACK */
550 if (SCS == SCS_DOWNLOAD_BLOCK){
551 /* check server subcommand */
552 if((SDO_C->CANrxData[0] & 0x02) == 0){
553 /* wrong server sub command */
554 *pSDOabortCode = CO_SDO_AB_CMD;
555 SDO_C->state = SDO_STATE_ABORT;
556 break;
557 }
558 /* check number of segments */
559 if(SDO_C->CANrxData[1] != SDO_C->block_blksize){
560 /* NOT all segments transferred successfully */
561 SDO_C->bufferOffsetACK += SDO_C->CANrxData[1] * 7;
562 SDO_C->bufferOffset = SDO_C->bufferOffsetACK;
563 }
564 else{
565 SDO_C->bufferOffsetACK = SDO_C->bufferOffset;
566 }
567 /* set size of next block */
568 SDO_C->block_blksize = SDO_C->CANrxData[2];
569 SDO_C->block_seqno = 0;
570
571 if(SDO_C->bufferOffset >= SDO_C->bufferSize)
572 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_CRC;
573 else
574 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_INPROGRES;
575 }
576 else{
577 *pSDOabortCode = CO_SDO_AB_CMD;
578 SDO_C->state = SDO_STATE_ABORT;
579 }
580 break;
581 }
582
583 case SDO_STATE_BLOCKDOWNLOAD_CRC_ACK:{
584 if (SCS == SCS_DOWNLOAD_BLOCK){
585 if((SDO_C->CANrxData[0] & 0x01) == 0){
586 /* wrong server sub command */
587 *pSDOabortCode = CO_SDO_AB_CMD;
588 SDO_C->state = SDO_STATE_ABORT;
589 break;
590 }
591 /* SDO block download successfully transferred */
592 SDO_C->state = SDO_STATE_NOTDEFINED;
593 SDO_C->timeoutTimer = 0;
594 CLEAR_CANrxNew(SDO_C->CANrxNew);
595 return CO_SDOcli_ok_communicationEnd;
596 }
597 else{
598 *pSDOabortCode = CO_SDO_AB_CMD;
599 SDO_C->state = SDO_STATE_ABORT;
600 break;
601 }
602 }
603
604 default:{
605 *pSDOabortCode = CO_SDO_AB_CMD;
606 SDO_C->state = SDO_STATE_ABORT;
607 break;
608 }
609 }
610 SDO_C->timeoutTimer = 0;
611 CLEAR_CANrxNew(SDO_C->CANrxNew);
612 }
613
614 /* TMO *********************************************************************************************** */
615 if(SDO_C->timeoutTimer < SDOtimeoutTime){
616 SDO_C->timeoutTimer += timeDifference_ms;
617 }
618 if(SDO_C->timeoutTimer >= SDOtimeoutTime){ /* communication TMO */
619 *pSDOabortCode = CO_SDO_AB_TIMEOUT;
620 CO_SDOclient_abort(SDO_C, *pSDOabortCode);
621 return CO_SDOcli_endedWithTimeout;
622 }
623
624 /* TX data ******************************************************************************************* */
625 if(SDO_C->CANtxBuff->bufferFull) {
626 return CO_SDOcli_transmittBufferFull;
627 }
628
629 CO_SDOTxBufferClear(SDO_C);
630 switch (SDO_C->state){
631 /* ABORT */
632 case SDO_STATE_ABORT:{
633 SDO_C->state = SDO_STATE_NOTDEFINED;
634 CO_SDOclient_abort (SDO_C, *pSDOabortCode);
635 ret = CO_SDOcli_endedWithClientAbort;
636 break;
637 }
638 /* SEGMENTED */
639 case SDO_STATE_DOWNLOAD_REQUEST:{
640 uint16_t i, j;
641 /* calculate length to be sent */
642 j = SDO_C->bufferSize - SDO_C->bufferOffset;
643 if(j > 7) j = 7;
644 /* fill data bytes */
645 for(i=0; i<j; i++)
646 SDO_C->CANtxBuff->data[i+1] = SDO_C->buffer[SDO_C->bufferOffset + i];
647
648 for(; i<7; i++)
649 SDO_C->CANtxBuff->data[i+1] = 0;
650
651 SDO_C->bufferOffset += j;
652 /* SDO command specifier */
653 SDO_C->CANtxBuff->data[0] = CCS_DOWNLOAD_SEGMENT | ((SDO_C->toggle)<<4) | ((7-j)<<1);
654 /* is end of transfer? */
655 if(SDO_C->bufferOffset == SDO_C->bufferSize){
656 SDO_C->CANtxBuff->data[0] |= 1;
657 }
658 /* Send next SDO message */
659 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
660 SDO_C->state = SDO_STATE_DOWNLOAD_RESPONSE;
661 break;
662 }
663
664 /* BLOCK */
665 case SDO_STATE_BLOCKDOWNLOAD_INPROGRES:{
666 SDO_C->block_seqno += 1;
667 SDO_C->CANtxBuff->data[0] = SDO_C->block_seqno;
668
669 if(SDO_C->block_seqno >= SDO_C->block_blksize){
670 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK;
671 }
672 /* set data */
673 SDO_C->block_noData = 0;
674
675 uint8_t i;
676 for(i = 1; i < 8; i++){
677 if(SDO_C->bufferOffset < SDO_C->bufferSize){
678 SDO_C->CANtxBuff->data[i] = *(SDO_C->buffer + SDO_C->bufferOffset);
679 }
680 else{
681 SDO_C->CANtxBuff->data[i] = 0;
682 SDO_C->block_noData += 1;
683 }
684
685 SDO_C->bufferOffset += 1;
686 }
687
688 if(SDO_C->bufferOffset >= SDO_C->bufferSize){
689 SDO_C->CANtxBuff->data[0] |= 0x80;
690 SDO_C->block_blksize = SDO_C->block_seqno;
691 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_BLOCK_ACK;
692 }
693
694 /* tx data */
695 SDO_C->timeoutTimer = 0;
696 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
697
698 break;
699 }
700
701 case SDO_STATE_BLOCKDOWNLOAD_CRC:{
702 SDO_C->CANtxBuff->data[0] = (CCS_DOWNLOAD_BLOCK<<5) | (SDO_C->block_noData << 2) | 0x01;
703
704 uint16_t tmp16;
705
706 tmp16 = crc16_ccitt((unsigned char *)SDO_C->buffer, (unsigned int)SDO_C->bufferSize, 0);
707
708 SDO_C->CANtxBuff->data[1] = (uint8_t) tmp16;
709 SDO_C->CANtxBuff->data[2] = (uint8_t) (tmp16>>8);
710
711 /* set state */
712 SDO_C->state = SDO_STATE_BLOCKDOWNLOAD_CRC_ACK;
713 /* tx data */
714 SDO_C->timeoutTimer = 0;
715 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
716
717 break;
718 }
719
720 default:{
721 break;
722 }
723 }
724
725 if(SDO_C->state == SDO_STATE_BLOCKDOWNLOAD_INPROGRES) {
726 ret = CO_SDOcli_blockDownldInProgress;
727 }
728
729 return ret;
730 }
731
732
733 /*******************************************************************************
734 *
735 * UPLOAD
736 *
737 ******************************************************************************/
CO_SDOclientUploadInitiate(CO_SDOclient_t * SDO_C,uint16_t index,uint8_t subIndex,uint8_t * dataRx,uint32_t dataRxSize,uint8_t blockEnable)738 CO_SDOclient_return_t CO_SDOclientUploadInitiate(
739 CO_SDOclient_t *SDO_C,
740 uint16_t index,
741 uint8_t subIndex,
742 uint8_t *dataRx,
743 uint32_t dataRxSize,
744 uint8_t blockEnable)
745 {
746 /* verify parameters */
747 if(SDO_C == NULL || dataRx == 0 || dataRxSize < 4) {
748 return CO_SDOcli_wrongArguments;
749 }
750
751 /* save parameters */
752 SDO_C->buffer = dataRx;
753 SDO_C->bufferSize = dataRxSize;
754
755 /* prepare CAN tx message */
756 CO_SDOTxBufferClear(SDO_C);
757
758 SDO_C->index = index;
759 SDO_C->subIndex = subIndex;
760
761 SDO_C->CANtxBuff->data[1] = index & 0xFF;
762 SDO_C->CANtxBuff->data[2] = index >> 8;
763 SDO_C->CANtxBuff->data[3] = subIndex;
764
765
766 if(blockEnable == 0){
767 SDO_C->state = SDO_STATE_UPLOAD_INITIATED;
768 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_INITIATE<<5);
769 }
770 else{
771 SDO_C->state = SDO_STATE_BLOCKUPLOAD_INITIATE;
772
773 /* header */
774 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_BLOCK<<5);
775
776 /* set CRC */
777 SDO_C->CANtxBuff->data[0] |= 0x04;
778
779 /* set number of segments in block */
780 SDO_C->block_blksize = SDO_C->block_size_max;
781 if ((SDO_C->block_blksize *7) > SDO_C->bufferSize){
782 return CO_SDOcli_wrongArguments;
783 }
784
785 SDO_C->CANtxBuff->data[4] = SDO_C->block_blksize;
786 SDO_C->CANtxBuff->data[5] = SDO_C->pst;
787
788
789 SDO_C->block_seqno = 0;
790 }
791
792 /* if nodeIDOfTheSDOServer == node-ID of this node, then exchange data with this node */
793 if(SDO_C->SDOClientPar->nodeIDOfTheSDOServer == SDO_C->SDO->nodeId){
794
795 /* Optional signal to RTOS. We can immediately continue SDO Client */
796 if(SDO_C->pFunctSignal != NULL) {
797 SDO_C->pFunctSignal();
798 }
799
800 return CO_SDOcli_ok_communicationEnd;
801 }
802
803 /* empty receive buffer, reset timeout timer and send message */
804 CLEAR_CANrxNew(SDO_C->CANrxNew);
805 SDO_C->timeoutTimer = 0;
806 SDO_C->timeoutTimerBLOCK =0;
807 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
808
809 return CO_SDOcli_ok_communicationEnd;
810 }
811
812
813 /******************************************************************************/
CO_SDOclientUpload(CO_SDOclient_t * SDO_C,uint16_t timeDifference_ms,uint16_t SDOtimeoutTime,uint32_t * pDataSize,uint32_t * pSDOabortCode)814 CO_SDOclient_return_t CO_SDOclientUpload(
815 CO_SDOclient_t *SDO_C,
816 uint16_t timeDifference_ms,
817 uint16_t SDOtimeoutTime,
818 uint32_t *pDataSize,
819 uint32_t *pSDOabortCode)
820 {
821 uint16_t indexTmp;
822 uint32_t tmp32;
823 CO_SDOclient_return_t ret = CO_SDOcli_waitingServerResponse;
824
825 /* verify parameters */
826 if(SDO_C == NULL) {
827 return CO_SDOcli_wrongArguments;
828 }
829
830 /* clear abort code */
831 *pSDOabortCode = CO_SDO_AB_NONE;
832
833 /* if nodeIDOfTheSDOServer == node-ID of this node, then exchange data with this node */
834 if(SDO_C->SDO && SDO_C->SDOClientPar->nodeIDOfTheSDOServer == SDO_C->SDO->nodeId){
835 SDO_C->state = SDO_STATE_NOTDEFINED;
836 CLEAR_CANrxNew(SDO_C->CANrxNew);
837
838 /* If SDO server is busy return error */
839 if(SDO_C->SDO->state != 0){
840 *pSDOabortCode = CO_SDO_AB_DEVICE_INCOMPAT;
841 return CO_SDOcli_endedWithClientAbort;
842 }
843
844 /* init ODF_arg */
845 *pSDOabortCode = CO_SDO_initTransfer(SDO_C->SDO, SDO_C->index, SDO_C->subIndex);
846 if((*pSDOabortCode) != CO_SDO_AB_NONE){
847 return CO_SDOcli_endedWithServerAbort;
848 }
849
850 /* set buffer and length if domain */
851 SDO_C->SDO->ODF_arg.data = SDO_C->buffer;
852 if(SDO_C->SDO->ODF_arg.ODdataStorage == 0)
853 SDO_C->SDO->ODF_arg.dataLength = SDO_C->bufferSize;
854
855 /* read data from the Object dictionary */
856 *pSDOabortCode = CO_SDO_readOD(SDO_C->SDO, SDO_C->bufferSize);
857 if((*pSDOabortCode) != CO_SDO_AB_NONE){
858 return CO_SDOcli_endedWithServerAbort;
859 }
860
861 /* set data size */
862 *pDataSize = SDO_C->SDO->ODF_arg.dataLength;
863
864 /* is SDO buffer too small */
865 if(SDO_C->SDO->ODF_arg.lastSegment == 0){
866 *pSDOabortCode = CO_SDO_AB_OUT_OF_MEM; /* Out of memory */
867 return CO_SDOcli_endedWithServerAbort;
868 }
869
870 return CO_SDOcli_ok_communicationEnd;
871 }
872
873
874 /* RX data ******************************************************************************** */
875 if(IS_CANrxNew(SDO_C->CANrxNew)){
876 uint8_t SCS = SDO_C->CANrxData[0]>>5; /* Client command specifier */
877
878 /* ABORT */
879 if (SDO_C->CANrxData[0] == (SCS_ABORT<<5)){
880 SDO_C->state = SDO_STATE_NOTDEFINED;
881 CLEAR_CANrxNew(SDO_C->CANrxNew);
882 CO_memcpySwap4(pSDOabortCode , &SDO_C->CANrxData[4]);
883 return CO_SDOcli_endedWithServerAbort;
884 }
885 switch (SDO_C->state){
886 case SDO_STATE_UPLOAD_INITIATED:{
887
888
889
890 if (SCS == SCS_UPLOAD_INITIATE){
891 if(SDO_C->CANrxData[0] & 0x02){
892 uint8_t size;
893 /* Expedited transfer */
894 if(SDO_C->CANrxData[0] & 0x01)/* is size indicated */
895 size = 4 - ((SDO_C->CANrxData[0]>>2)&0x03); /* size */
896 else
897 size = 4;
898
899 *pDataSize = size;
900
901 /* copy data */
902 while(size--) SDO_C->buffer[size] = SDO_C->CANrxData[4+size];
903 SDO_C->state = SDO_STATE_NOTDEFINED;
904 CLEAR_CANrxNew(SDO_C->CANrxNew);
905
906 return CO_SDOcli_ok_communicationEnd;
907 }
908 else{
909 /* segmented transfer - prepare first segment */
910 SDO_C->bufferOffset = 0;
911 SDO_C->state = SDO_STATE_UPLOAD_REQUEST;
912
913 SDO_C->toggle =0;
914 /* continue with segmented upload */
915 }
916 }
917 else{
918 *pSDOabortCode = CO_SDO_AB_CMD;
919 SDO_C->state = SDO_STATE_ABORT;
920 }
921 break;
922 }
923
924 case SDO_STATE_UPLOAD_RESPONSE:{
925 if (SCS == SCS_UPLOAD_SEGMENT){
926 uint16_t size, i;
927 /* verify toggle bit */
928 if((SDO_C->CANrxData[0] &0x10) != (~SDO_C->toggle &0x10)){
929 *pSDOabortCode = CO_SDO_AB_TOGGLE_BIT;
930 SDO_C->state = SDO_STATE_ABORT;
931 break;
932 }
933 /* get size */
934 size = 7 - ((SDO_C->CANrxData[0]>>1)&0x07);
935 /* verify length */
936 if((SDO_C->bufferOffset + size) > SDO_C->bufferSize){
937 *pSDOabortCode = CO_SDO_AB_OUT_OF_MEM; /* Out of memory */
938 SDO_C->state = SDO_STATE_ABORT;
939 break;
940 }
941 /* copy data to buffer */
942 for(i=0; i<size; i++)
943 SDO_C->buffer[SDO_C->bufferOffset + i] = SDO_C->CANrxData[1 + i];
944 SDO_C->bufferOffset += size;
945 /* If no more segments to be uploaded, finish communication */
946 if(SDO_C->CANrxData[0] & 0x01){
947 *pDataSize = SDO_C->bufferOffset;
948 SDO_C->state = SDO_STATE_NOTDEFINED;
949 CLEAR_CANrxNew(SDO_C->CANrxNew);
950 return CO_SDOcli_ok_communicationEnd;
951 }
952 /* set state */
953 SDO_C->state = SDO_STATE_UPLOAD_REQUEST;
954 break;
955 }
956 else{
957 *pSDOabortCode = CO_SDO_AB_CMD;
958 SDO_C->state = SDO_STATE_ABORT;
959 }
960 break;
961 }
962
963 case SDO_STATE_BLOCKUPLOAD_INITIATE:{
964 if (SCS == SCS_UPLOAD_BLOCK){ /* block upload initiate response */
965
966 SDO_C->state = SDO_STATE_BLOCKUPLOAD_INITIATE_ACK;
967
968 /* SCR support */
969 if((SDO_C->CANrxData[0] & 0x04) != 0)
970 SDO_C->crcEnabled = 1; /* CRC suported */
971 else
972 SDO_C->crcEnabled = 0; /* CRC not suported */
973
974 /* chech Index ans subnindex */
975 indexTmp = SDO_C->CANrxData[2];
976 indexTmp = indexTmp << 8;
977 indexTmp |= SDO_C->CANrxData[1];
978
979 if(indexTmp != SDO_C->index || SDO_C->CANrxData[3] != SDO_C->subIndex){
980 *pSDOabortCode = CO_SDO_AB_PRAM_INCOMPAT;
981 SDO_C->state = SDO_STATE_ABORT;
982 }
983
984 /* set length */
985 if(SDO_C->CANrxData[0]&0x02){
986 uint32_t len;
987 CO_memcpySwap4(&len, &SDO_C->CANrxData[4]);
988 SDO_C->dataSize = len;
989 }
990 else{
991 SDO_C->dataSize = 0;
992 }
993
994 /* check available buffer size */
995 if (SDO_C->dataSize > SDO_C->bufferSize){
996 *pSDOabortCode = CO_SDO_AB_OUT_OF_MEM;
997 SDO_C->state = SDO_STATE_ABORT;
998 }
999
1000 SDO_C->dataSizeTransfered =0;
1001 }
1002 else if (SCS == SCS_UPLOAD_INITIATE){ /* switch to regular segmented transfer */
1003 if(SDO_C->CANrxData[0] & 0x02){
1004 uint8_t size;
1005 /* Expedited transfer */
1006 if(SDO_C->CANrxData[0] & 0x01)/* is size indicated */
1007 size = 4 - ((SDO_C->CANrxData[0]>>2)&0x03); /* size */
1008 else
1009 size = 4;
1010
1011 *pDataSize = size;
1012
1013 /* copy data */
1014 while(size--) SDO_C->buffer[size] = SDO_C->CANrxData[4+size];
1015 SDO_C->state = SDO_STATE_NOTDEFINED;
1016 CLEAR_CANrxNew(SDO_C->CANrxNew);
1017
1018 return CO_SDOcli_ok_communicationEnd;
1019 }
1020 else{
1021 /* segmented transfer - prepare first segment */
1022 SDO_C->bufferOffset = 0;
1023 SDO_C->state = SDO_STATE_UPLOAD_REQUEST;
1024
1025 SDO_C->toggle =0;
1026 /* continue with segmented upload */
1027 }
1028 }
1029 else{ /* unknown SCS */
1030 *pSDOabortCode = CO_SDO_AB_CMD;
1031 SDO_C->state = SDO_STATE_ABORT;
1032 }
1033 break;
1034 }
1035
1036 case SDO_STATE_BLOCKUPLOAD_INPROGRES:{
1037 /* data are copied directly in receive function */
1038 break;
1039 }
1040
1041 case SDO_STATE_BLOCKUPLOAD_SUB_END:{
1042 /* data was copied by receive function, sub-block is finished */
1043 /* Is last segment? */
1044 if(SDO_C->CANrxData[0] & 0x80) {
1045 /* Is data size indicated and wrong? */
1046 if((SDO_C->dataSize != 0) && (SDO_C->dataSize > SDO_C->dataSizeTransfered)) {
1047 *pSDOabortCode = CO_SDO_AB_TYPE_MISMATCH;
1048 SDO_C->state = SDO_STATE_ABORT;
1049 }
1050 else {
1051 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_ACK_LAST;
1052 }
1053 }
1054 else {
1055 /* Is SDO buffer overflow? */
1056 if(SDO_C->dataSizeTransfered >= SDO_C->bufferSize) {
1057 *pSDOabortCode = CO_SDO_AB_OUT_OF_MEM;
1058 SDO_C->state = SDO_STATE_ABORT;
1059 }
1060 else {
1061 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_ACK;
1062 }
1063 }
1064 break;
1065 }
1066
1067 case SDO_STATE_BLOCKUPLOAD_BLOCK_CRC:{
1068 if (SCS == SCS_UPLOAD_BLOCK){
1069 tmp32 = ((SDO_C->CANrxData[0]>>2) & 0x07);
1070 SDO_C->dataSizeTransfered -= tmp32;
1071
1072 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_END;
1073 if (SDO_C->crcEnabled){
1074 uint16_t tmp16;
1075 CO_memcpySwap2(&tmp16, &SDO_C->CANrxData[1]);
1076
1077 if (tmp16 != crc16_ccitt((unsigned char *)SDO_C->buffer, (unsigned int)SDO_C->dataSizeTransfered, 0)){
1078 *pSDOabortCode = CO_SDO_AB_CRC;
1079 SDO_C->state = SDO_STATE_ABORT;
1080 }
1081 else{
1082 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_END;
1083 }
1084 }
1085 else{
1086 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_END;
1087 }
1088
1089 }
1090 else{
1091 *pSDOabortCode = CO_SDO_AB_GENERAL;
1092 SDO_C->state = SDO_STATE_ABORT;
1093 }
1094 break;
1095 }
1096
1097 default:{
1098 *pSDOabortCode = CO_SDO_AB_CMD;
1099 SDO_C->state = SDO_STATE_ABORT;
1100 break;
1101 }
1102 }
1103 SDO_C->timeoutTimer = 0;
1104 CLEAR_CANrxNew(SDO_C->CANrxNew);
1105 }
1106
1107 /* TMO *************************************************************************************************** */
1108 if(SDO_C->timeoutTimer < SDOtimeoutTime){
1109 SDO_C->timeoutTimer += timeDifference_ms;
1110 if (SDO_C->state == SDO_STATE_BLOCKUPLOAD_INPROGRES)
1111 SDO_C->timeoutTimerBLOCK += timeDifference_ms;
1112 }
1113 if(SDO_C->timeoutTimer >= SDOtimeoutTime){ /* communication TMO */
1114 *pSDOabortCode = CO_SDO_AB_TIMEOUT;
1115 CO_SDOclient_abort(SDO_C, *pSDOabortCode);
1116 return CO_SDOcli_endedWithTimeout;
1117 }
1118 if(SDO_C->timeoutTimerBLOCK >= (SDOtimeoutTime/2)){ /* block TMO */
1119 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_ACK;
1120 }
1121
1122
1123 /* TX data ******************************************************************************** */
1124 if(SDO_C->CANtxBuff->bufferFull) {
1125 return CO_SDOcli_transmittBufferFull;
1126 }
1127
1128 CO_SDOTxBufferClear(SDO_C);
1129 switch (SDO_C->state){
1130 case SDO_STATE_ABORT:{
1131 SDO_C->state = SDO_STATE_NOTDEFINED;
1132 CO_SDOclient_abort (SDO_C, *pSDOabortCode);
1133 ret = CO_SDOcli_endedWithClientAbort;
1134 break;
1135 }
1136
1137 /* SEGMENTED UPLOAD */
1138 case SDO_STATE_UPLOAD_REQUEST:{
1139 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_SEGMENT<<5) | (SDO_C->toggle & 0x10);
1140 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
1141
1142 SDO_C->state = SDO_STATE_UPLOAD_RESPONSE;
1143 SDO_C->toggle = ~SDO_C->toggle;
1144
1145 break;
1146 }
1147 /* BLOCK */
1148 case SDO_STATE_BLOCKUPLOAD_INITIATE_ACK:{
1149 SDO_C->timeoutTimerBLOCK = 0;
1150 SDO_C->block_seqno = 0;
1151 SDO_C->state = SDO_STATE_BLOCKUPLOAD_INPROGRES;
1152
1153 /* header */
1154 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_BLOCK<<5) | 0x03;
1155 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
1156
1157 break;
1158 }
1159
1160 case SDO_STATE_BLOCKUPLOAD_BLOCK_ACK_LAST:{
1161 /* header */
1162 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_BLOCK<<5) | 0x02;
1163 SDO_C->CANtxBuff->data[1] = SDO_C->block_seqno;
1164
1165 SDO_C->block_seqno = 0;
1166 SDO_C->timeoutTimerBLOCK = 0;
1167
1168 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_CRC;
1169
1170 SDO_C->CANtxBuff->data[2] = SDO_C->block_blksize;
1171 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
1172
1173 break;
1174 }
1175
1176 case SDO_STATE_BLOCKUPLOAD_BLOCK_ACK:{
1177 /* header */
1178 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_BLOCK<<5) | 0x02;
1179 SDO_C->CANtxBuff->data[1] = SDO_C->block_seqno;
1180
1181 /* set next block size */
1182 if (SDO_C->dataSize != 0){
1183 if(SDO_C->dataSizeTransfered >= SDO_C->dataSize){
1184 SDO_C->block_blksize = 0;
1185 SDO_C->state = SDO_STATE_BLOCKUPLOAD_BLOCK_CRC;
1186 }
1187 else{
1188 tmp32 = ((SDO_C->dataSize - SDO_C->dataSizeTransfered) / 7);
1189 if(tmp32 >= SDO_C->block_size_max){
1190 SDO_C->block_blksize = SDO_C->block_size_max;
1191 }
1192 else{
1193 if((SDO_C->dataSize - SDO_C->dataSizeTransfered) % 7 == 0)
1194 SDO_C->block_blksize = tmp32;
1195 else
1196 SDO_C->block_blksize = tmp32 + 1;
1197 }
1198 SDO_C->block_seqno = 0;
1199 SDO_C->timeoutTimerBLOCK = 0;
1200 SDO_C->state = SDO_STATE_BLOCKUPLOAD_INPROGRES;
1201 }
1202 }
1203 else{
1204 SDO_C->block_seqno = 0;
1205 SDO_C->timeoutTimerBLOCK = 0;
1206
1207 SDO_C->state = SDO_STATE_BLOCKUPLOAD_INPROGRES;
1208 }
1209 SDO_C->CANtxBuff->data[2] = SDO_C->block_blksize;
1210 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
1211
1212 break;
1213 }
1214
1215 case SDO_STATE_BLOCKUPLOAD_BLOCK_END:{
1216 SDO_C->CANtxBuff->data[0] = (CCS_UPLOAD_BLOCK<<5) | 0x01;
1217
1218 CO_CANsend(SDO_C->CANdevTx, SDO_C->CANtxBuff);
1219
1220 *pDataSize = SDO_C->dataSizeTransfered;
1221
1222 SDO_C->state = SDO_STATE_NOTDEFINED;
1223
1224 ret = CO_SDOcli_ok_communicationEnd;
1225 break;
1226 }
1227
1228 default:
1229 break;
1230 }
1231
1232 if(SDO_C->state == SDO_STATE_BLOCKUPLOAD_INPROGRES) {
1233 ret = CO_SDOcli_blockUploadInProgress;
1234 }
1235
1236 return ret;
1237 }
1238
1239
1240 /******************************************************************************/
CO_SDOclientClose(CO_SDOclient_t * SDO_C)1241 void CO_SDOclientClose(CO_SDOclient_t *SDO_C){
1242 if(SDO_C != NULL) {
1243 SDO_C->state = SDO_STATE_NOTDEFINED;
1244 }
1245 }
1246