NNP STM Generic Remote Module git-main
Loading...
Searching...
No Matches
lss.c
Go to the documentation of this file.
1
22#include "data.h"
23#include "lss.h"
24#include "canfestival.h"
25#include "sysdep.h"
26
27#ifdef CO_ENABLE_LSS
28
29//#define LSS_TIMEOUT_MS (TIMEVAL)1000 /* ms */
30//#define LSS_FS_TIMEOUT_MS (TIMEVAL)100 /* ms */
31
32/* Returns the LSS ident field from a Message struct */
33#define getLSSIdent(msg) (((UNS32)msg->data[4] << 24) | ((UNS32)msg->data[3] << 16) | (msg->data[2] << 8) | (msg->data[1]))
34
35
36/* Returns the LSS switch delay field from a Message struct */
37#define getLSSDelay(msg) ((msg->data[2] << 8) | (msg->data[1]))
38
39/* Returns the LSS FastScan BitCheck field from a Message struct */
40#define getLSSBitCheck(msg) msg->data[5]
41
42/* Returns the LSS FastScan LSSSub field from a Message struct */
43#define getLSSSub(msg) msg->data[6]
44
45/* Returns the LSS FastScan LSSNext field from a Message struct */
46#define getLSSNext(msg) msg->data[7]
47
48/* Prototypes for internals functions */
49UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2);
50void LssAlarmMSG(CO_Data* d, UNS32 id);
51void LssAlarmSDELAY(CO_Data* d, UNS32 id);
52
53
54#define StopLSS_MSG_TIMER(){\
55 MSG_WAR(0x3D01, "StopLSS_MSG_TIMER", 0);\
56 d->lss_transfer.timerMSG = DelAlarm(d->lss_transfer.timerMSG);}
57
58#define StartLSS_MSG_TIMER(){\
59 MSG_WAR(0x3D02, "StartLSS_MSG_TIMER",0);\
60 d->lss_transfer.timerMSG = SetAlarm(d,0,&LssAlarmMSG,MS_TO_TIMEVAL(LSS_TIMEOUT_MS),0);}
61
62#define StopLSS_SDELAY_TIMER(){\
63 MSG_WAR(0x3D03, "StopLSS_SDELAY_TIMER", 0);\
64 d->lss_transfer.timerSDELAY = DelAlarm(d->lss_transfer.timerSDELAY);}
65
66#define StartLSS_SDELAY_TIMER(){\
67 MSG_WAR(0x3D04, "StartLSS_SDELAY_TIMER",0);\
68 d->lss_transfer.timerSDELAY= SetAlarm(d,0,&LssAlarmSDELAY,MS_TO_TIMEVAL(d->lss_transfer.switchDelay),MS_TO_TIMEVAL(d->lss_transfer.switchDelay));}
69
70
71#ifdef CO_ENABLE_LSS_FS
72/* Prototypes for internals functions */
73void LssAlarmFS(CO_Data* d, UNS32 id);
74
75#define StopLSS_FS_TIMER(){\
76 MSG_WAR(0x3D05, "StopLSS_FS_TIMER", id);\
77 d->lss_transfer.timerFS = DelAlarm(d->lss_transfer.timerFS);}
78
79#define StartLSS_FS_TIMER(){\
80 MSG_WAR(0x3D06, "StartLSS_FS_TIMER",0);\
81 d->lss_transfer.timerFS = SetAlarm(d,0,&LssAlarmFS,MS_TO_TIMEVAL(LSS_FS_TIMEOUT_MS),0);}
82#endif
83
84
85void LssAlarmMSG(CO_Data* d, UNS32 id)
86{
87 StopLSS_MSG_TIMER();
88#ifdef CO_ENABLE_LSS_FS
89 if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
90 if(d->lss_transfer.FastScan_SM==LSS_FS_RESET){
91 /* if at least one node had answered before the timer expired, start the FastScan protocol*/
92 if(d->lss_transfer.LSSanswer!=0){
93 UNS32 Mask=0xFFFFFFFF;
94 d->lss_transfer.LSSanswer=0;
95 d->lss_transfer.BitChecked=d->lss_transfer.lss_fs_transfer.FS_BitChecked[0];
96 Mask=(UNS32)((UNS64)Mask<<(d->lss_transfer.BitChecked+1));
97 d->lss_transfer.IDNumber=d->lss_transfer.lss_fs_transfer.FS_LSS_ID[0] & Mask;
98 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
99 //printf("BitChecked=%d, IDNumber=%x MASK=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber,Mask);
100 StartLSS_FS_TIMER();
101 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
102 return;
103 }
104 else{
105
106 d->lss_transfer.state = LSS_FINISHED;
107 /* Inform the application that there aren't not configured nodes in the net */
108 d->lss_transfer.dat1=1;
109 }
110 }
111 else{
112 /* This should not happen, an error ocurred*/
113 MSG_ERR(0x1D07, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
114 d->lss_transfer.state = LSS_ABORTED_INTERNAL;
115 d->lss_transfer.FastScan_SM=LSS_FS_RESET;
116 }
117 }
118 else
119#endif
120 if(d->lss_transfer.command==LSS_IDENT_REMOTE_NON_CONF){
121 MSG_WAR(0x2D08, "LSS timeout. There are not no-configured slaves in the net", 0);
122 d->lss_transfer.state = LSS_FINISHED;
123 d->lss_transfer.dat1=1;
124 }
125 else{
126 MSG_ERR(0x1D09, "LSS timeout. LSS response not received.", 0);
127 MSG_WAR(0x2D0A, "LSS timeout command specifier : ", d->lss_transfer.command);
128 /* Set aborted state */
129 d->lss_transfer.state = LSS_ABORTED_INTERNAL;
130#ifdef CO_ENABLE_LSS_FS
131 d->lss_transfer.FastScan_SM = LSS_FS_RESET;
132#endif
133 }
134
135 /* Call the user function to inform of the problem.*/
136 if(d->lss_transfer.Callback){
137 /*If there is a callback, it is responsible of the error*/
138 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
139 }
140}
141
142
149void LssAlarmSDELAY(CO_Data* d, UNS32 id)
150{
151
152 /* The first switch_delay period expired. Store the node state, change it
153 * so no CAN messages will be sent or received, call the ChangeBaudRate function*/
154 if(d->lss_transfer.switchDelayState==SDELAY_FIRST){
155 MSG_WAR(0x3D0B, "LSS switch delay first period expired",0);
156 d->lss_transfer.switchDelayState=SDELAY_SECOND;
157 //(*d->lss_ChangeBaudRate)(d,d->lss_transfer.baudRate);
158 canChangeBaudRate(d->lss_transfer.canHandle_t, d->lss_transfer.baudRate);
159 }
160 else{ /* d->lss_transfer.switchDelayState==SDELAY_SECOND */
161 MSG_WAR(0x3D0C, "LSS switch delay second period expired",0);
162 d->lss_transfer.switchDelayState=SDELAY_OFF;
163 StopLSS_SDELAY_TIMER();
164
165 if (*(d->iam_a_slave))
166 d->canHandle=d->lss_transfer.canHandle_t;
167 else{
168 d->lss_transfer.dat1=0;
169 d->lss_transfer.state=LSS_FINISHED;
170 /* Call the user function */
171 if(d->lss_transfer.Callback){
172 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
173 }
174 }
175 }
176}
177
178#ifdef CO_ENABLE_LSS_FS
185void LssAlarmFS(CO_Data* d, UNS32 id)
186{
187 StopLSS_FS_TIMER();
188
189 switch(d->lss_transfer.FastScan_SM){
190 case LSS_FS_RESET:
191 {
192 /* This should not happen, an error ocurred*/
193 MSG_ERR(0x1D0D, "LSS FastScan timeout. FastScan_SM inconsisten state.", d->lss_transfer.FastScan_SM);
194 }
195 break;
196 case LSS_FS_PROCESSING:
197 {
198 /* If there isn't any answer, set the bit */
199 if(d->lss_transfer.LSSanswer==0){
200 UNS32 Mask=0x1;
201 Mask<<=d->lss_transfer.BitChecked;
202 d->lss_transfer.IDNumber|=Mask;
203 }
204
205 if(d->lss_transfer.BitChecked==0){
206 /* We finished with the current LSS-ID[sub], confirm it */
207 d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
208 if(d->lss_transfer.LSSNext<3)d->lss_transfer.LSSNext++;
209 }
210 else{
211 d->lss_transfer.BitChecked--;
212 }
213 //printf("BitChecked=%d, IDNumber=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber);
214 d->lss_transfer.LSSanswer=0;
215 StartLSS_FS_TIMER();
216 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
217 return;
218 }
219 break;
220 case LSS_FS_CONFIRMATION:
221 {
222 if(d->lss_transfer.LSSanswer!=0){
223 d->lss_transfer.LSSanswer=0;
224
225 if(d->lss_transfer.LSSSub==3){
226 /* The LSS FastScan protocol finished correctly. Restore the parameters */
227 d->lss_transfer.BitChecked=128;
228 d->lss_transfer.FastScan_SM=LSS_FS_RESET;
229 d->lss_transfer.LSSSub=0;
230 d->lss_transfer.LSSNext=0;
231 d->lss_transfer.IDNumber=0;
232
233 /* Inform the application that the FastScan finished correctly */
234 d->lss_transfer.state = LSS_FINISHED;
235 d->lss_transfer.dat1=0;
236 }
237 else{
238 UNS32 Mask=0xFFFFFFFF;
239 /* Start with the next LSS-ID[sub] */
240 d->lss_transfer.LSSSub++;
241 d->lss_transfer.BitChecked=d->lss_transfer.lss_fs_transfer.FS_BitChecked[d->lss_transfer.LSSSub];
242 Mask=(UNS32)((UNS64)Mask<<(d->lss_transfer.BitChecked+1));
243 d->lss_transfer.IDNumber=d->lss_transfer.lss_fs_transfer.FS_LSS_ID[d->lss_transfer.LSSSub] & Mask;
244 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
245 //printf("BitChecked=%d, IDNumber=%x MASK=%x\n",d->lss_transfer.BitChecked,d->lss_transfer.IDNumber,Mask);
246 StartLSS_FS_TIMER();
247 sendMasterLSSMessage(d,LSS_IDENT_FASTSCAN,0,0);
248 return;
249 }
250 }
251 else{
252 /* This should not happen, an error ocurred*/
253 MSG_ERR(0x1D0E, "LSS FastScan timeout. FastScan response not received.", 0);
254 MSG_ERR(0x1D0E, "There is not any node with LSS_ID# =>", d->lss_transfer.LSSSub);
255 MSG_ERR(0x1D0E, "with the value =>", d->lss_transfer.IDNumber);
256 /* Set aborted state */
257 d->lss_transfer.state = LSS_ABORTED_INTERNAL;
258 d->lss_transfer.FastScan_SM = LSS_FS_RESET;
259 }
260 }
261 break;
262 }
263
264 /* Call the user function to inform of the problem.*/
265 if(d->lss_transfer.Callback){
266 /*If there is a callback, it is responsible of the error*/
267 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
268 }
269}
270#endif
271
272
278void startLSS(CO_Data* d)
279{
280 /*MSG_WAR(0x3D09, "LSS services started",0);*/
281}
282
288void stopLSS(CO_Data* d)
289{
290 /*MSG_WAR(0x3D09, "LSS services stopped",0);*/
291}
292
301UNS8 sendSlaveLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
302{
303 Message m;
304 UNS8 i;
305
306 if (!d->CurrentCommunicationState.csLSS){
307 MSG_WAR(0x2D17, "unable to send the LSS message, not in the proper state =>", d->nodeState);
308 return 0xFF;
309 }
310
311 for(i=1;i<8;i++)m.data[i]=0;
312 m.len = 8;
313 m.rtr = NOT_A_REQUEST;
314 m.data[0]=command;
315 m.cob_id=UNS16_LE(SLSS_ADRESS);
316
317 /* Tha data sent with the msg depends on the command */
318 switch(command){
319 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
320 m.data[1]=*(UNS8 *)dat1;
321 break;
322 case LSS_CONF_NODE_ID: /* Configure Node-ID */
323 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
324 case LSS_CONF_STORE: /* Store Configured Parameters */
325 m.data[1]=*(UNS8 *)dat1;
326 m.data[2]=*(UNS8 *)dat2;
327 break;
328 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
329 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
330 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
331 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
332 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
333 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
334 m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
335 m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
336 break;
337 case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response*/
338 case LSS_IDENT_SLAVE: /* LSS Identify Slave */
339 case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
340 break;
341 default:
342 MSG_ERR(0x1D18, "send Slave LSS command not implemented", command);
343 return 0xFF;
344 }
345
346 return canSend(d->canHandle, &m);
347}
348
349/* If a baud rate is not supported just comment the line. */
350static UNS8 CO_TranslateBaudRate(char* optarg){
351// if(!strcmp( optarg, "1M")) return 0x00;
352// if(!strcmp( optarg, "800K")) return 0x01;
353// if(!strcmp( optarg, "500K")) return 0x02;
354// if(!strcmp( optarg, "250K")) return 0x03;
355// if(!strcmp( optarg, "125K")) return 0x04;
356 if(!strcmp( optarg, "100K")) return 0x05;
357// if(!strcmp( optarg, "50K")) return 0x06;
358// if(!strcmp( optarg, "20K")) return 0x07;
359// if(!strcmp( optarg, "10K")) return 0x08;
360 return 0xFF;
361}
362
371UNS8 sendMasterLSSMessage(CO_Data* d, UNS8 command,void *dat1,void *dat2)
372{
373 Message m;
374 UNS8 i;
375 UNS8 res;
376 UNS8 hasResponse=0;
377
378 for(i=1;i<8;i++)m.data[i]=0;
379 m.len = 8;
380 m.rtr = NOT_A_REQUEST;
381 m.data[0]=command;
382 m.cob_id=UNS16_LE(MLSS_ADRESS);
383
384 /* Tha data sent with the msg depends on the command */
385 switch(command){
386 case LSS_CONF_NODE_ID: /* Configure Node-ID */
387 hasResponse=1;
388 case LSS_SM_GLOBAL: /* Switch Mode Global */
389 m.data[1]=*(UNS8 *)dat1;
390 break;
391 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
392
393 m.data[1]=*(UNS8 *)dat1;
394 d->lss_transfer.baudRate=*(char **)dat2;
395
396 if((m.data[2]=CO_TranslateBaudRate(d->lss_transfer.baudRate))!=0xFF){
397 hasResponse=1;
398 break;
399 }
400
401 MSG_ERR(0x1D19, "Master-> Baud rate not supported",0);
402 d->lss_transfer.dat1=0xFF;
403
404 /* if bit timing is not supported comment the previous code and uncomment the following one*/
405 /*{
406 MSG_ERR(0x1D1A, "Master-> Bit timing not supported",0);
407 d->lss_transfer.dat1=0x01;
408 }*/
409
410 d->lss_transfer.dat2=0;
411 /* If there is a callback, it is responsible of the error */
412 if(d->lss_transfer.Callback)
413 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
414 return 0xFF;
415 //break;
416 case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
417 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
418 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
419 if(d->lss_transfer.baudRate!="none"){
420 d->lss_transfer.switchDelay=(UNS16)(*(UNS32*)dat1 & 0xFFFF);
421 d->lss_transfer.switchDelayState=SDELAY_FIRST;
422 d->lss_transfer.canHandle_t=d->canHandle;
423 res=canSend(d->canHandle,&m);
424 if(res==0){
425 StartLSS_SDELAY_TIMER();
426 d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
427 }
428 return res;
429 }
430 else{
431 MSG_ERR(0x1D1B, "Master-> Baud rate not specified",0);
432 d->lss_transfer.dat1=1;
433 /* If there is a callback, it is responsible of the error */
434 if(d->lss_transfer.Callback){
435 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
436 }
437 return 0xFF;
438 }
439 //break;
440 case LSS_SM_SELECTIVE_SERIAL:
441 case LSS_IDENT_REMOTE_SERIAL_HIGH:
442 hasResponse=1;
443 case LSS_SM_SELECTIVE_VENDOR: /* Switch Mode Selective */
444 case LSS_SM_SELECTIVE_PRODUCT:
445 case LSS_SM_SELECTIVE_REVISION:
446 case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
447 case LSS_IDENT_REMOTE_PRODUCT:
448 case LSS_IDENT_REMOTE_REV_LOW:
449 case LSS_IDENT_REMOTE_REV_HIGH:
450 case LSS_IDENT_REMOTE_SERIAL_LOW:
451 m.data[1]=(UNS8)(*(UNS32*)dat1 & 0xFF);
452 m.data[2]=(UNS8)(*(UNS32*)dat1>>8 & 0xFF);
453 m.data[3]=(UNS8)(*(UNS32*)dat1>>16 & 0xFF);
454 m.data[4]=(UNS8)(*(UNS32*)dat1>>24 & 0xFF);
455 break;
456
457 case LSS_CONF_STORE: /* Store Configured Parameters */
458 case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
459 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
460 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
461 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
462 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
463 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
464 hasResponse=1;
465 break;
466#ifdef CO_ENABLE_LSS_FS
467 case LSS_IDENT_FASTSCAN:
468 if(d->lss_transfer.FastScan_SM==LSS_FS_RESET){
469 UNS8 i;
470 /* Initialize the lss_fs_transfer FastScan parameters */
471 for(i=0;i<4;i++){
472 d->lss_transfer.lss_fs_transfer.FS_LSS_ID[i]=(*(lss_fs_transfer_t*)dat1).FS_LSS_ID[i];
473 d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]=(*(lss_fs_transfer_t*)dat1).FS_BitChecked[i];
474 /* Adjust BitChecked from 32-1 to 31-0 */
475 if(d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]>0)d->lss_transfer.lss_fs_transfer.FS_BitChecked[i]--;
476 }
477
478 d->lss_transfer.IDNumber=0;
479 d->lss_transfer.BitChecked=128;
480 d->lss_transfer.LSSSub=0;
481 d->lss_transfer.LSSNext=0;
482
483 /* it will generate a response only if it is the start of the FastScan protocol*/
484 hasResponse=1;
485 }
486 m.data[1]=(UNS8)(d->lss_transfer.IDNumber & 0xFF);
487 m.data[2]=(UNS8)(d->lss_transfer.IDNumber>>8 & 0xFF);
488 m.data[3]=(UNS8)(d->lss_transfer.IDNumber>>16 & 0xFF);
489 m.data[4]=(UNS8)(d->lss_transfer.IDNumber>>24 & 0xFF);
490 m.data[5]=d->lss_transfer.BitChecked;
491 m.data[6]=d->lss_transfer.LSSSub;
492 m.data[7]=d->lss_transfer.LSSNext;
493 break;
494#endif
495 default:
496 MSG_ERR(0x1D1C, "send Master LSS command not implemented", command);
497 return 0xFF;
498 }
499
500 res=canSend(d->canHandle,&m);
501 if(res==0 && hasResponse==1){
502 StartLSS_MSG_TIMER();
503 d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
504 }
505 return res;
506}
507
517UNS8 sendLSS(CO_Data* d, UNS8 command,void *dat1,void *dat2)
518{
519 UNS8 res=1;
520
521 /* Tha data sent with the msg depends on the command and if the sender is a master or a slave */
522 if (*(d->iam_a_slave)){
523 res = sendSlaveLSSMessage(d, command,dat1,dat2);
524 }
525 else {/* It is a Master */
526 res = sendMasterLSSMessage(d, command,dat1,dat2);
527 }
528 return res ;
529}
530
531
541UNS8 proceedLSS_Master(CO_Data* d, Message* m )
542{
543 UNS8 msg_cs;
544 UNS32 Dat1=0;
545 UNS8 Dat2=0;
546
547 if(d->lss_transfer.state!=LSS_TRANS_IN_PROGRESS)
548 {
549 //MSG_WAR(0x3D0D, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
550 //return 0;
551 goto ErrorProcessMaster;
552 }
553
554 MSG_WAR(0x3D1E, "MasterLSS proceedLSS; command ", m->data[0]);
555
556 switch(msg_cs=m->data[0]){
557 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
558 if(d->lss_transfer.command!=LSS_INQ_NODE_ID)goto ErrorProcessMaster;
559 Dat1=m->data[1];
560 break;
561 case LSS_CONF_NODE_ID: /* Configure Node-ID */
562 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
563 case LSS_CONF_STORE: /* Store Configured Parameters */
564 if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
565 Dat1=m->data[1];
566 Dat2=m->data[2];
567 break;
568 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
569 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
570 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
571 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
572 if(d->lss_transfer.command!=msg_cs)goto ErrorProcessMaster;
573 Dat1=getLSSIdent(m);
574 break;
575 case LSS_IDENT_SLAVE: /* LSS Identify Slave */
576#ifdef CO_ENABLE_LSS_FS
577 if(d->lss_transfer.command==LSS_IDENT_FASTSCAN){
578 /* A message arrived during the timer period */
579 d->lss_transfer.LSSanswer=1;
580 return 0;
581 }
582 else
583#endif
584 if(d->lss_transfer.command!=LSS_IDENT_REMOTE_VENDOR && \
585 d->lss_transfer.command!=LSS_IDENT_REMOTE_PRODUCT && \
586 d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_LOW && \
587 d->lss_transfer.command!=LSS_IDENT_REMOTE_REV_HIGH && \
588 d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_LOW && \
589 d->lss_transfer.command!=LSS_IDENT_REMOTE_SERIAL_HIGH )
590 goto ErrorProcessMaster;
591 break;
592 case LSS_SM_SELECTIVE_RESP: /* Switch Mode Selective response */
593 if(d->lss_transfer.command!=LSS_SM_SELECTIVE_VENDOR && \
594 d->lss_transfer.command!=LSS_SM_SELECTIVE_PRODUCT && \
595 d->lss_transfer.command!=LSS_SM_SELECTIVE_REVISION && \
596 d->lss_transfer.command!=LSS_SM_SELECTIVE_SERIAL )
597 goto ErrorProcessMaster;
598 break;
599 case LSS_IDENT_NON_CONF_SLAVE: /* LSS identify non-configured remote slave */
600 if(d->lss_transfer.command!=LSS_IDENT_REMOTE_NON_CONF)goto ErrorProcessMaster;
601 break;
602 default:
603 MSG_ERR(0x1D1F, "Master LSS command not implemented", msg_cs);
604 return 0xFF;
605 }
606
607 StopLSS_MSG_TIMER();
608 d->lss_transfer.state = LSS_FINISHED;
609
610 d->lss_transfer.dat1=Dat1;
611 d->lss_transfer.dat2=Dat2;
612 /* If there is a callback, it is responsible of the received response */
613 if(d->lss_transfer.Callback)
614 (*d->lss_transfer.Callback)(d,d->lss_transfer.command);
615
616 return 0;
617
618ErrorProcessMaster:
619 MSG_WAR(0x3D20, "MasterLSS proceedLSS; unexpected message arrived;command ", m->data[0]);
620 return 0xFF;
621
622}
623
624/*
625 * @ingroup lss
626 * @brief This function is called when the node is receiving a Slave LSS message (cob-id = 0x7E4).
627 * - Call the callback function or send the response message depending on the LSS comand within m.
628 * @param *d Pointer on a CAN object data structure
629 * @param *m message
630 * @return 0 if OK
631 */
632UNS8 proceedLSS_Slave(CO_Data* d, Message* m )
633{
634 UNS8 msg_cs;
635
636 MSG_WAR(0x3D21, "SlaveLSS proceedLSS; command ", m->data[0]);
637
638 switch(msg_cs=m->data[0]){
639 case LSS_SM_GLOBAL: /* Switch Mode Global */
640 /* if there is not a mode change break*/
641 if(m->data[1] == d->lss_transfer.mode){
642 MSG_WAR(0x3D22, "SlaveLSS already in the mode ", m->data[1]);
643 break;
644 }
645
646 if(m->data[1]==LSS_CONFIGURATION_MODE) {
647 MSG_WAR(0x3D23, "SlaveLSS switching to configuration mode ", 0);
648 /* Store the NodeId in case it will be changed */
649 //d->lss_transfer.nodeID=getNodeId(d);
650 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
651 }
652 else if(m->data[1]==LSS_WAITING_MODE){
653 MSG_WAR(0x3D24, "SlaveLSS switching to operational mode ", 0);
654
655 /* If the nodeID has changed update it and put the node state to Initialisation. */
656 if(d->lss_transfer.nodeID!=getNodeId(d)){
657 if(getNodeId(d)==0xFF){/* The nodeID was 0xFF; initialize the application*/
658 MSG_WAR(0x3D25, "The node Id has changed. Reseting to Initialisation state",0);
659 setNodeId(d, d->lss_transfer.nodeID);
660 setState(d, Initialisation);
661 }
662 else{/* The nodeID will be changed on NMT_Reset_Comunication Request*/
663 }
664 }
665 d->lss_transfer.mode=LSS_WAITING_MODE;
666 }
667 break;
668 case LSS_CONF_NODE_ID: /* Configure Node-ID */
669 {
670 UNS8 error_code=0;
671 UNS8 spec_error=0;
672
673 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
674 if(m->data[1]>127 && m->data[1]!=0xFF){
675 MSG_ERR(0x1D26, "NodeID out of range",0);
676 error_code=1; /* NodeID out of range */
677 }
678 else{
679 d->lss_transfer.nodeID=m->data[1];
680 }
681 }
682 else{
683 MSG_WAR(0x3D27, "SlaveLSS not in configuration mode",0);
684 //error_code=0xFF;
685 break;
686 }
687 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
688 }
689 break;
690 case LSS_CONF_BIT_TIMING: /* Configure Bit Timing Parameters */
691 {
692 UNS8 error_code=0;
693 UNS8 spec_error=0;
694
695 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
696 /* If a baud rate is not supported just comment the line. */
697 switch(m->data[2]){
698 case 0x00:d->lss_transfer.baudRate="1M";break;
699 case 0x01:d->lss_transfer.baudRate="800K";break;
700 case 0x02:d->lss_transfer.baudRate="500K";break;
701 case 0x03:d->lss_transfer.baudRate="250K";break;
702 case 0x04:d->lss_transfer.baudRate="125K";break;
703 case 0x05:d->lss_transfer.baudRate="100K";break;
704 case 0x06:d->lss_transfer.baudRate="50K";break;
705 case 0x07:d->lss_transfer.baudRate="20K";break;
706 case 0x08:d->lss_transfer.baudRate="10K";break;
707 default:
708 MSG_ERR(0x1D28, "Baud rate not supported",0);
709 error_code=0xFF; /* Baud rate not supported*/
710 break;
711 }
712 }
713 else{
714 MSG_WAR(0x3D2A, "SlaveLSS not in configuration mode",0);
715 //error_code=0xFF;
716 break;
717 }
718
719 /* if bit timing is not supported comment the previous code and uncomment the following */
720 /*{
721 MSG_ERR(0x1D29, "Bit timing not supported",0);
722 error_code=0x01; // bit timing not supported
723 }*/
724
725 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
726 }
727 break;
728 case LSS_CONF_ACT_BIT_TIMING: /* Activate Bit Timing Parameters */
729
730 if(d->lss_transfer.mode!=LSS_CONFIGURATION_MODE){
731 MSG_ERR(0x3D2B, "SlaveLSS not in configuration mode",0);
732 break;
733 }
734
735 if(d->lss_transfer.baudRate!="none"){
736 d->lss_transfer.switchDelay=getLSSDelay(m);
737 MSG_WAR(0x3D2C, "Slave Switch Delay set to: ",d->lss_transfer.switchDelay);
738 d->lss_transfer.switchDelayState=SDELAY_FIRST;
739 //d->lss_transfer.currentState=getState(d);
740 //setState(d, LssTimingDelay);
741 d->lss_transfer.canHandle_t=d->canHandle;
742 d->canHandle=NULL;
743 StartLSS_SDELAY_TIMER();
744 }
745 break;
746 case LSS_CONF_STORE: /* Store Configured Parameters */
747 {
748 UNS8 error_code=0;
749 UNS8 spec_error=0;
750
751 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE){
752 if(d->lss_StoreConfiguration){
753 /* call lss_StoreConfiguration with NodeId */
754 (*d->lss_StoreConfiguration)(d,&error_code,&spec_error);
755 }
756 else{
757 MSG_ERR(0x1D2E, "Store configuration not supported",0);
758 error_code=1; /* store configuration is not supported */
759 }
760 }
761 else{
762 MSG_WAR(0x3D2F, "SlaveLSS not in configuration mode",0);
763 //error_code=0xFF;
764 break;
765 }
766 sendSlaveLSSMessage(d,msg_cs,&error_code,&spec_error);
767 }
768 break;
769 case LSS_SM_SELECTIVE_VENDOR: /* Switch Mode Selective */
770 case LSS_SM_SELECTIVE_PRODUCT:
771 case LSS_SM_SELECTIVE_REVISION:
772 case LSS_SM_SELECTIVE_SERIAL:
773 {
774 UNS32 errorCode;
775 const indextable *ptrTable;
776 ODCallback_t *Callback;
777 UNS32 _SpecificNodeInfo;
778
779 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
780 {
781 MSG_ERR(0x1D30, "Switch Mode Selective only supported in operational mode",0);
782 break;
783 }
784
785 _SpecificNodeInfo=getLSSIdent(m);
786
787 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
788 if(_SpecificNodeInfo==*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_SM_SELECTIVE_VENDOR-1)].pObject){
789
790 d->lss_transfer.addr_sel_match|=(0x01<<(msg_cs-LSS_SM_SELECTIVE_VENDOR));
791 /* If all the fields has been set */
792 if(d->lss_transfer.addr_sel_match==0x0F){
793
794 MSG_WAR(0x3D31, "SlaveLSS switching to configuration mode ", 0);
795 d->lss_transfer.addr_sel_match=0;
796 d->lss_transfer.nodeID=getNodeId(d);
797 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
798
799 sendSlaveLSSMessage(d,LSS_SM_SELECTIVE_RESP,0,0);
800 }
801 }
802 else {
803 MSG_WAR(0x3D32, "LSS identity field doesn't match ", _SpecificNodeInfo);
804 d->lss_transfer.addr_sel_match=0;
805 }
806 }
807 break;
808 case LSS_IDENT_REMOTE_VENDOR: /* LSS Identify Remote Slaves */
809 case LSS_IDENT_REMOTE_PRODUCT:
810 case LSS_IDENT_REMOTE_REV_LOW:
811 case LSS_IDENT_REMOTE_REV_HIGH:
812 case LSS_IDENT_REMOTE_SERIAL_LOW:
813 case LSS_IDENT_REMOTE_SERIAL_HIGH:
814 {
815 UNS32 errorCode;
816 const indextable *ptrTable;
817 ODCallback_t *Callback;
818 UNS32 _SpecificNodeInfo;
819
820 _SpecificNodeInfo=getLSSIdent(m);
821
822 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
823
824 /* Check if the data match the identity object. */
825 switch(msg_cs){
826 case LSS_IDENT_REMOTE_VENDOR:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo == *(UNS32*)ptrTable->pSubindex[1].pObject)? d->lss_transfer.addr_ident_match|0x01:0; break;
827 case LSS_IDENT_REMOTE_PRODUCT:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo == *(UNS32*)ptrTable->pSubindex[2].pObject)? d->lss_transfer.addr_ident_match|0x02:0; break;
828 case LSS_IDENT_REMOTE_REV_LOW:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo <= *(UNS32*)ptrTable->pSubindex[3].pObject)? d->lss_transfer.addr_ident_match|0x04:0; break;
829 case LSS_IDENT_REMOTE_REV_HIGH:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo >= *(UNS32*)ptrTable->pSubindex[3].pObject)? d->lss_transfer.addr_ident_match|0x08:0; break;
830 case LSS_IDENT_REMOTE_SERIAL_LOW:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo <= *(UNS32*)ptrTable->pSubindex[4].pObject)? d->lss_transfer.addr_ident_match|0x10:0; break;
831 case LSS_IDENT_REMOTE_SERIAL_HIGH:d->lss_transfer.addr_ident_match=(_SpecificNodeInfo >= *(UNS32*)ptrTable->pSubindex[4].pObject)? d->lss_transfer.addr_ident_match|0x20:0; break;
832 }
833 /* If all the fields has been set.. */
834 if(d->lss_transfer.addr_ident_match==0x3F){
835 MSG_WAR(0x3D33, "SlaveLSS identified ", 0);
836 d->lss_transfer.addr_ident_match=0;
837 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
838 }
839 else if(d->lss_transfer.addr_ident_match==0){
840 MSG_WAR(0x3D34, "LSS identify field doesn't match ", _SpecificNodeInfo);
841 }
842 }
843 break;
844 case LSS_IDENT_REMOTE_NON_CONF: /* LSS identify non-configured remote slave */
845 {
846 if(getNodeId(d)==0xFF){
847 MSG_WAR(0x3D35, "SlaveLSS non-configured ", 0);
848 sendSlaveLSSMessage(d,LSS_IDENT_NON_CONF_SLAVE,0,0);
849 }
850 else{
851 MSG_WAR(0x3D36, "SlaveLSS already configured ", 0);
852 }
853 }
854 break;
855 case LSS_INQ_VENDOR_ID: /* Inquire Identity Vendor-ID */
856 case LSS_INQ_PRODUCT_CODE: /* Inquire Identity Product-Code */
857 case LSS_INQ_REV_NUMBER: /* Inquire Identity Revision-Number */
858 case LSS_INQ_SERIAL_NUMBER: /* Inquire Identity Serial-Number */
859 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
860 {
861
862 UNS32 errorCode;
863 const indextable *ptrTable;
864 ODCallback_t *Callback;
865 UNS32 _SpecificNodeInfo;
866
867 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
868 _SpecificNodeInfo=*(UNS32*)ptrTable->pSubindex[msg_cs-(LSS_INQ_VENDOR_ID-1)].pObject;
869 MSG_WAR(0x3D37, "SlaveLSS identity field inquired ", _SpecificNodeInfo);
870
871 sendSlaveLSSMessage(d,msg_cs,&_SpecificNodeInfo,0);
872 }
873 break;
874 case LSS_INQ_NODE_ID: /* Inquire Node-ID */
875 if(d->lss_transfer.mode==LSS_CONFIGURATION_MODE)
876 {
877 UNS8 NodeID;
878
879 NodeID=getNodeId(d);
880 MSG_WAR(0x3D38, "SlaveLSS Node ID inquired ", NodeID);
881 sendSlaveLSSMessage(d,msg_cs,&NodeID,0);
882 }
883 else{
884 MSG_WAR(0x3D39, "SlaveLSS not in configuration mode",0);
885 }
886 break;
887#ifdef CO_ENABLE_LSS_FS
888 case LSS_IDENT_FASTSCAN:
889 {
890 /* If the nodeID isn't 0xFF the slave shall not participate */
891 if(getNodeId(d)!=0xFF)break;
892 if(getLSSBitCheck(m)==128)d->lss_transfer.FastScan_SM=LSS_FS_RESET;
893
894 switch(d->lss_transfer.FastScan_SM){
895 case LSS_FS_RESET:
896 {
897 UNS32 errorCode;
898 const indextable *ptrTable;
899 ODCallback_t *Callback;
900
901 MSG_WAR(0x3D3A, "SlaveLSS Reseting LSSPos", 0);
902 d->lss_transfer.LSSPos=0;
903 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
904
905 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
906 d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
907
908 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
909 }
910 break;
911 case LSS_FS_PROCESSING:/*if(getLSSBitCheck(m)<32)*/
912 if(d->lss_transfer.LSSPos==getLSSSub(m))
913 {
914 UNS32 Mask=0xFFFFFFFF<<getLSSBitCheck(m);
915
916 MSG_WAR(0x3D3B, "SlaveLSS FastScan IDNumber", getLSSIdent(m));
917 MSG_WAR(0x3D3C, "SlaveLSS FastScan BitMask ", Mask);
918 MSG_WAR(0x3D3D, "SlaveLSS FastScan LSS-ID ", d->lss_transfer.IDNumber);
919
920 if((getLSSIdent(m) & Mask)==(d->lss_transfer.IDNumber & Mask))
921 {
922 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
923 }
924
925 if(getLSSBitCheck(m)==0)
926 {
927 d->lss_transfer.FastScan_SM=LSS_FS_CONFIRMATION;
928 }
929 }
930 break;
931 case LSS_FS_CONFIRMATION:
932 if(d->lss_transfer.LSSPos==getLSSSub(m))
933 {
934 if(getLSSIdent(m)==d->lss_transfer.IDNumber)
935 {
936 /* Current LSS-ID[sub] confirmed correctly */
937 MSG_WAR(0x3D3E, "SlaveLSS FastScan IDNumber and LSS-ID match=>", d->lss_transfer.IDNumber);
938 if(d->lss_transfer.LSSPos==3)
939 {
940 /* All LSS-ID[sub] identified correctly, switching to configuration mode */
941 MSG_WAR(0x3D3F, "SlaveLSS switching to configuration mode ", 0);
942 d->lss_transfer.nodeID=getNodeId(d);
943 d->lss_transfer.mode=LSS_CONFIGURATION_MODE;
944 d->lss_transfer.FastScan_SM=LSS_FS_RESET;
945 d->lss_transfer.LSSPos=0xFF;
946 }
947 else
948 {
949 /* Switch to the next LSS-ID[sub] */
950 UNS32 errorCode;
951 const indextable *ptrTable;
952 ODCallback_t *Callback;
953
954 d->lss_transfer.LSSPos=getLSSNext(m);
955 ptrTable = (*d->scanIndexOD)(0x1018, &errorCode, &Callback);
956 d->lss_transfer.IDNumber=*(UNS32*)ptrTable->pSubindex[d->lss_transfer.LSSPos+1].pObject;
957 d->lss_transfer.FastScan_SM=LSS_FS_PROCESSING;
958 }
959 sendSlaveLSSMessage(d,LSS_IDENT_SLAVE,0,0);
960 }
961 }
962 break;
963 }
964 }
965 break;
966#endif
967 default:
968 MSG_ERR(0x1D40, "SlaveLSS command not implemented", msg_cs);
969 return 0xFF;
970 }
971
972 return 0;
973}
974
975/* Used by the Master application to send a LSS command, WITHOUT response, to the slave.
976 * command: the LSS command. LSS_...
977 * dat1 and dat2: pointers to optional data (depend on command).
978 * return sendLSS(d,command,dat1,dat2)
979 */
980/*UNS8 configNetworkNode(CO_Data* d, UNS8 command, void *dat1, void* dat2)
981{
982 return sendMasterLSSMessage(d,command,dat1,dat2);
983}*/
984
985
998UNS8 configNetworkNode (CO_Data* d, UNS8 command, void *dat1, void* dat2, LSSCallback_t Callback)
999{
1000 //d->lss_transfer.state=LSS_TRANS_IN_PROGRESS;
1001 d->lss_transfer.Callback=Callback;
1002 d->lss_transfer.command=command;
1003
1004 StopLSS_MSG_TIMER();
1005 //StartLSS_MSG_TIMER();
1006
1007 return sendMasterLSSMessage(d,command,dat1,dat2);
1008}
1009
1030UNS8 getConfigResultNetworkNode (CO_Data* d, UNS8 command, UNS32* dat1, UNS8* dat2)
1031{
1032 *dat1=d->lss_transfer.dat1;
1033 *dat2=d->lss_transfer.dat2;
1034 return d->lss_transfer.state;
1035}
1036
1037//void _lss_StoreConfiguration(UNS8 *error, UNS8 *spec_error){printf("_lss_StoreConfiguration\n");}
1038
1039#endif
#define UNS8
Unsigned int8 representation in CANFest.
Definition applicfg.h:25
#define UNS16
Unsigned int16 representation in CANFest.
Definition applicfg.h:26
#define UNS64
Unsigned int64 representation in CANFest.
Definition applicfg.h:32
#define MSG_WAR(num, str, val)
Definition of MSG_WAR.
Definition applicfg.h:64
#define UNS32
Unsigned int32 representation in CANFest.
Definition applicfg.h:27
#define MSG_ERR(num, str, val)
Definition of MSG_ERR.
Definition applicfg.h:52
UNS8 setState(CO_Data *d, e_nodeState newState)
Change the state of the node.
Definition states.c:161
UNS8 getNodeId(CO_Data *d)
Returns the nodId.
Definition states.c:250
void setNodeId(CO_Data *d, UNS8 nodeId)
Define the node ID. Initialize the object dictionary.
Definition states.c:261
Definition can.h:13
UNS16 cob_id
Definition can.h:14
UNS8 data[8]
Definition can.h:17
UNS8 rtr
Definition can.h:15
UNS8 len
Definition can.h:16
This structure contains all necessary informations to define a CANOpen node.
Definition data.h:44