1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for asychronous SDO Sequence Layer module
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in the
21 documentation and/or other materials provided with the distribution.
23 3. Neither the name of SYSTEC electronic GmbH nor the names of its
24 contributors may be used to endorse or promote products derived
25 from this software without prior written permission. For written
26 permission, please contact info@systec-electronic.com.
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 POSSIBILITY OF SUCH DAMAGE.
43 If a provision of this License is or becomes illegal, invalid or
44 unenforceable in any jurisdiction, that shall not affect:
45 1. the validity or enforceability in that jurisdiction of any other
46 provision of this License; or
47 2. the validity or enforceability in other jurisdictions of that or
48 any other provision of this License.
50 -------------------------------------------------------------------------
52 $RCSfile: EplSdoAsySequ.c,v $
56 $Revision: 1.10 $ $Date: 2008/11/13 17:13:09 $
63 -------------------------------------------------------------------------
67 2006/06/26 k.t.: start of the implementation
69 ****************************************************************************/
71 #include "user/EplSdoAsySequ.h"
73 #if ((((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) == 0) &&\
74 (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) == 0) )
76 #error 'ERROR: At least UDP or Asnd module needed!'
79 /***************************************************************************/
82 /* G L O B A L D E F I N I T I O N S */
85 /***************************************************************************/
87 //---------------------------------------------------------------------------
89 //---------------------------------------------------------------------------
91 #define EPL_SDO_HISTORY_SIZE 5
93 #ifndef EPL_MAX_SDO_SEQ_CON
94 #define EPL_MAX_SDO_SEQ_CON 10
97 #define EPL_SEQ_DEFAULT_TIMEOUT 5000 // in [ms] => 5 sec
99 #define EPL_SEQ_RETRY_COUNT 5 // => max. Timeout 30 sec
101 #define EPL_SEQ_NUM_THRESHOLD 100 // threshold which distinguishes between old and new sequence numbers
103 // define frame with size of Asnd-Header-, SDO Sequenze Header size, SDO Command header
104 // and Ethernet-Header size
105 #define EPL_SEQ_FRAME_SIZE 24
106 // size of the header of the asynchronus SDO Sequence layer
107 #define EPL_SEQ_HEADER_SIZE 4
109 // buffersize for one frame in history
110 #define EPL_SEQ_HISTROY_FRAME_SIZE EPL_MAX_SDO_FRAME_SIZE
112 // mask to get scon and rcon
113 #define EPL_ASY_SDO_CON_MASK 0x03
115 //---------------------------------------------------------------------------
117 //---------------------------------------------------------------------------
119 // events for processfunction
121 kAsySdoSeqEventNoEvent
= 0x00, // no Event
122 kAsySdoSeqEventInitCon
= 0x01, // init connection
123 kAsySdoSeqEventFrameRec
= 0x02, // frame received
124 kAsySdoSeqEventFrameSend
= 0x03, // frame to send
125 kAsySdoSeqEventTimeout
= 0x04, // Timeout for connection
126 kAsySdoSeqEventCloseCon
= 0x05 // higher layer close connection
127 } tEplAsySdoSeqEvent
;
129 // structure for History-Buffer
132 u8 m_bWrite
; // index of the next free buffer entry
133 u8 m_bAck
; // index of the next message which should become acknowledged
134 u8 m_bRead
; // index between m_bAck and m_bWrite to the next message for retransmission
135 u8 m_aabHistoryFrame
[EPL_SDO_HISTORY_SIZE
]
136 [EPL_SEQ_HISTROY_FRAME_SIZE
];
137 unsigned int m_auiFrameSize
[EPL_SDO_HISTORY_SIZE
];
139 } tEplAsySdoConHistory
;
141 // state of the statemaschine
143 kEplAsySdoStateIdle
= 0x00,
144 kEplAsySdoStateInit1
= 0x01,
145 kEplAsySdoStateInit2
= 0x02,
146 kEplAsySdoStateInit3
= 0x03,
147 kEplAsySdoStateConnected
= 0x04,
148 kEplAsySdoStateWaitAck
= 0x05
151 // connection control structure
153 tEplSdoConHdl m_ConHandle
;
154 tEplAsySdoState m_SdoState
;
155 u8 m_bRecSeqNum
; // name from view of the communication partner
156 u8 m_bSendSeqNum
; // name from view of the communication partner
157 tEplAsySdoConHistory m_SdoConHistory
;
158 tEplTimerHdl m_EplTimerHdl
;
159 unsigned int m_uiRetryCount
; // retry counter
160 unsigned int m_uiUseCount
; // one sequence layer connection may be used by
161 // multiple command layer connections
165 // instance structure
167 tEplAsySdoSeqCon m_AsySdoConnection
[EPL_MAX_SDO_SEQ_CON
];
168 tEplSdoComReceiveCb m_fpSdoComReceiveCb
;
169 tEplSdoComConCb m_fpSdoComConCb
;
171 #if defined(WIN32) || defined(_WIN32)
172 LPCRITICAL_SECTION m_pCriticalSection
;
173 CRITICAL_SECTION m_CriticalSection
;
175 LPCRITICAL_SECTION m_pCriticalSectionReceive
;
176 CRITICAL_SECTION m_CriticalSectionReceive
;
179 } tEplAsySdoSequInstance
;
181 //---------------------------------------------------------------------------
182 // modul globale vars
183 //---------------------------------------------------------------------------
185 static tEplAsySdoSequInstance AsySdoSequInstance_g
;
187 //---------------------------------------------------------------------------
188 // local function prototypes
189 //---------------------------------------------------------------------------
191 static tEplKernel
EplSdoAsySeqProcess(unsigned int uiHandle_p
,
192 unsigned int uiDataSize_p
,
194 tEplAsySdoSeq
* pRecFrame_p
,
195 tEplAsySdoSeqEvent Event_p
);
197 static tEplKernel
EplSdoAsySeqSendIntern(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
198 unsigned int uiDataSize_p
,
200 BOOL fFrameInHistory
);
202 static tEplKernel
EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
203 unsigned int uiDataSize_p
,
204 tEplFrame
* pEplFrame_p
);
206 tEplKernel
EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p
,
207 tEplAsySdoSeq
*pSdoSeqData_p
,
208 unsigned int uiDataSize_p
);
210 static tEplKernel
EplSdoAsyInitHistory(void);
212 static tEplKernel
EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
213 tEplFrame
* pFrame_p
,
214 unsigned int uiSize_p
);
216 static tEplKernel
EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
219 static tEplKernel
EplSdoAsyReadFromHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
220 tEplFrame
** ppFrame_p
,
221 unsigned int *puiSize_p
,
224 static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon
*
227 static tEplKernel
EplSdoAsySeqSetTimer(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
228 unsigned long ulTimeout
);
230 /***************************************************************************/
233 /* C L A S S <EPL asychronus SDO Sequence layer> */
236 /***************************************************************************/
238 // Description: this module contains the asynchronus SDO Sequence Layer for
239 // the EPL SDO service
242 /***************************************************************************/
244 //=========================================================================//
246 // P U B L I C F U N C T I O N S //
248 //=========================================================================//
250 //---------------------------------------------------------------------------
252 // Function: EplSdoAsySeqInit
254 // Description: init first instance
258 // Parameters: fpSdoComCb_p = callback function to inform Command layer
260 // fpSdoComConCb_p = callback function to inform command layer
261 // about connection state
264 // Returns: tEplKernel = errorcode
269 //---------------------------------------------------------------------------
270 tEplKernel
EplSdoAsySeqInit(tEplSdoComReceiveCb fpSdoComCb_p
,
271 tEplSdoComConCb fpSdoComConCb_p
)
275 Ret
= EplSdoAsySeqAddInstance(fpSdoComCb_p
, fpSdoComConCb_p
);
281 //---------------------------------------------------------------------------
283 // Function: EplSdoAsySeqAddInstance
285 // Description: init following instances
289 // Parameters: fpSdoComCb_p = callback function to inform Command layer
291 // fpSdoComConCb_p = callback function to inform command layer
292 // about connection state
294 // Returns: tEplKernel = errorcode
299 //---------------------------------------------------------------------------
300 tEplKernel
EplSdoAsySeqAddInstance(tEplSdoComReceiveCb fpSdoComCb_p
,
301 tEplSdoComConCb fpSdoComConCb_p
)
305 Ret
= kEplSuccessful
;
307 // check functionpointer
308 if (fpSdoComCb_p
== NULL
) {
309 Ret
= kEplSdoSeqMissCb
;
312 AsySdoSequInstance_g
.m_fpSdoComReceiveCb
= fpSdoComCb_p
;
315 // check functionpointer
316 if (fpSdoComConCb_p
== NULL
) {
317 Ret
= kEplSdoSeqMissCb
;
320 AsySdoSequInstance_g
.m_fpSdoComConCb
= fpSdoComConCb_p
;
323 // set controllstructure to 0
324 EPL_MEMSET(&AsySdoSequInstance_g
.m_AsySdoConnection
[0], 0x00,
325 sizeof(AsySdoSequInstance_g
.m_AsySdoConnection
));
328 Ret
= EplSdoAsyInitHistory();
329 if (Ret
!= kEplSuccessful
) {
332 #if defined(WIN32) || defined(_WIN32)
333 // create critical section for process function
334 AsySdoSequInstance_g
.m_pCriticalSection
=
335 &AsySdoSequInstance_g
.m_CriticalSection
;
336 InitializeCriticalSection(AsySdoSequInstance_g
.m_pCriticalSection
);
338 // init critical section for receive cb function
339 AsySdoSequInstance_g
.m_pCriticalSectionReceive
=
340 &AsySdoSequInstance_g
.m_CriticalSectionReceive
;
341 InitializeCriticalSection(AsySdoSequInstance_g
.
342 m_pCriticalSectionReceive
);
345 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
347 Ret
= EplSdoUdpuAddInstance(EplSdoAsyReceiveCb
);
348 if (Ret
!= kEplSuccessful
) {
353 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
355 Ret
= EplSdoAsnduAddInstance(EplSdoAsyReceiveCb
);
356 if (Ret
!= kEplSuccessful
) {
366 //---------------------------------------------------------------------------
368 // Function: EplSdoAsySeqDelInstance
370 // Description: delete instances
377 // Returns: tEplKernel = errorcode
382 //---------------------------------------------------------------------------
383 tEplKernel
EplSdoAsySeqDelInstance(void)
386 unsigned int uiCount
;
387 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
389 Ret
= kEplSuccessful
;
391 // delete timer of open connections
393 pAsySdoSeqCon
= &AsySdoSequInstance_g
.m_AsySdoConnection
[0];
394 while (uiCount
< EPL_MAX_SDO_SEQ_CON
) {
395 if (pAsySdoSeqCon
->m_ConHandle
!= 0) {
396 EplTimeruDeleteTimer(&pAsySdoSeqCon
->m_EplTimerHdl
);
402 #if defined(WIN32) || defined(_WIN32)
403 // delete critical section for process function
404 DeleteCriticalSection(AsySdoSequInstance_g
.m_pCriticalSection
);
407 // set instance-table to 0
408 EPL_MEMSET(&AsySdoSequInstance_g
, 0x00, sizeof(AsySdoSequInstance_g
));
410 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
411 // delete lower layer
412 Ret
= EplSdoUdpuDelInstance();
415 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
416 // delete lower layer
417 Ret
= EplSdoAsnduDelInstance();
423 //---------------------------------------------------------------------------
425 // Function: EplSdoAsySeqInitCon
427 // Description: start initialization of a sequence layer connection.
428 // It tries to reuse an existing connection to the same node.
431 // Parameters: pSdoSeqConHdl_p = pointer to the variable for the connection handle
432 // uiNodeId_p = Node Id of the target
433 // SdoType = Type of the SDO connection
436 // Returns: tEplKernel = errorcode
441 //---------------------------------------------------------------------------
442 tEplKernel
EplSdoAsySeqInitCon(tEplSdoSeqConHdl
*pSdoSeqConHdl_p
,
443 unsigned int uiNodeId_p
,
447 unsigned int uiCount
;
448 unsigned int uiFreeCon
;
449 tEplSdoConHdl ConHandle
;
450 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
451 Ret
= kEplSuccessful
;
454 // call init function of the protcol abstraction layer
455 // which tries to find an existing connection to the same node
460 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
461 Ret
= EplSdoUdpuInitCon(&ConHandle
, uiNodeId_p
);
462 if (Ret
!= kEplSuccessful
) {
466 Ret
= kEplSdoSeqUnsupportedProt
;
472 case kEplSdoTypeAsnd
:
474 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
475 Ret
= EplSdoAsnduInitCon(&ConHandle
, uiNodeId_p
);
476 if (Ret
!= kEplSuccessful
) {
480 Ret
= kEplSdoSeqUnsupportedProt
;
485 // unsupported protocols
486 // -> auto should be replaced by command layer
487 case kEplSdoTypeAuto
:
491 Ret
= kEplSdoSeqUnsupportedProt
;
495 } // end of switch(SdoType)
497 // find existing connection to the same node or find empty entry for connection
499 uiFreeCon
= EPL_MAX_SDO_SEQ_CON
;
500 pAsySdoSeqCon
= &AsySdoSequInstance_g
.m_AsySdoConnection
[0];
502 while (uiCount
< EPL_MAX_SDO_SEQ_CON
) {
503 if (pAsySdoSeqCon
->m_ConHandle
== ConHandle
) { // existing connection found
506 if (pAsySdoSeqCon
->m_ConHandle
== 0) {
513 if (uiCount
== EPL_MAX_SDO_SEQ_CON
) {
514 if (uiFreeCon
== EPL_MAX_SDO_SEQ_CON
) { // no free entry found
519 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
520 Ret
= EplSdoUdpuDelCon(ConHandle
);
521 if (Ret
!= kEplSuccessful
) {
529 case kEplSdoTypeAsnd
:
531 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
532 Ret
= EplSdoAsnduDelCon(ConHandle
);
533 if (Ret
!= kEplSuccessful
) {
540 // unsupported protocols
541 // -> auto should be replaced by command layer
542 case kEplSdoTypeAuto
:
546 Ret
= kEplSdoSeqUnsupportedProt
;
550 } // end of switch(SdoType)
552 Ret
= kEplSdoSeqNoFreeHandle
;
554 } else { // free entry found
556 &AsySdoSequInstance_g
.m_AsySdoConnection
[uiFreeCon
];
557 pAsySdoSeqCon
->m_ConHandle
= ConHandle
;
562 *pSdoSeqConHdl_p
= (uiCount
| EPL_SDO_ASY_HANDLE
);
564 // increment use counter
565 pAsySdoSeqCon
->m_uiUseCount
++;
567 // call intern process function
568 Ret
= EplSdoAsySeqProcess(uiCount
,
569 0, NULL
, NULL
, kAsySdoSeqEventInitCon
);
575 //---------------------------------------------------------------------------
577 // Function: EplSdoAsySeqSendData
579 // Description: send sata unsing a established connection
583 // Parameters: pSdoSeqConHdl_p = connection handle
584 // uiDataSize_p = Size of Frame to send
585 // -> wihtout SDO sequence layer header, Asnd header
587 // ==> SDO Sequence layer payload
588 // SdoType = Type of the SDO connection
591 // Returns: tEplKernel = errorcode
596 //---------------------------------------------------------------------------
597 tEplKernel
EplSdoAsySeqSendData(tEplSdoSeqConHdl SdoSeqConHdl_p
,
598 unsigned int uiDataSize_p
,
599 tEplFrame
*pabData_p
)
602 unsigned int uiHandle
;
604 uiHandle
= (SdoSeqConHdl_p
& ~EPL_SDO_SEQ_HANDLE_MASK
);
606 // check if connection ready
607 if (AsySdoSequInstance_g
.m_AsySdoConnection
[uiHandle
].m_SdoState
==
608 kEplAsySdoStateIdle
) {
609 // no connection with this handle
610 Ret
= kEplSdoSeqInvalidHdl
;
612 } else if (AsySdoSequInstance_g
.m_AsySdoConnection
[uiHandle
].
613 m_SdoState
!= kEplAsySdoStateConnected
) {
614 Ret
= kEplSdoSeqConnectionBusy
;
618 Ret
= EplSdoAsySeqProcess(uiHandle
,
620 pabData_p
, NULL
, kAsySdoSeqEventFrameSend
);
625 //---------------------------------------------------------------------------
627 // Function: EplSdoAsySeqProcessEvent
629 // Description: function processes extern events
630 // -> later needed for timeout controll with timer-module
634 // Parameters: pEvent_p = pointer to event
637 // Returns: tEplKernel = errorcode
642 //---------------------------------------------------------------------------
643 tEplKernel
EplSdoAsySeqProcessEvent(tEplEvent
*pEvent_p
)
646 tEplTimerEventArg
*pTimerEventArg
;
647 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
648 tEplTimerHdl EplTimerHdl
;
649 unsigned int uiCount
;
651 Ret
= kEplSuccessful
;
653 if (pEvent_p
== NULL
) {
654 Ret
= kEplSdoSeqInvalidEvent
;
658 if (pEvent_p
->m_EventType
!= kEplEventTypeTimer
) {
659 Ret
= kEplSdoSeqInvalidEvent
;
663 pTimerEventArg
= (tEplTimerEventArg
*) pEvent_p
->m_pArg
;
664 EplTimerHdl
= pTimerEventArg
->m_TimerHdl
;
666 // get pointer to intern control structure of connection
667 if (pTimerEventArg
->m_ulArg
== 0) {
670 pAsySdoSeqCon
= (tEplAsySdoSeqCon
*) pTimerEventArg
->m_ulArg
;
672 // check if time is current
673 if (EplTimerHdl
!= pAsySdoSeqCon
->m_EplTimerHdl
) {
675 EplTimeruDeleteTimer(&EplTimerHdl
);
679 EplTimeruDeleteTimer(&pAsySdoSeqCon
->m_EplTimerHdl
);
681 // get indexnumber of control structure
683 while ((&AsySdoSequInstance_g
.m_AsySdoConnection
[uiCount
]) !=
686 if (uiCount
> EPL_MAX_SDO_SEQ_CON
) {
691 // process event and call processfunction if needed
692 Ret
= EplSdoAsySeqProcess(uiCount
,
693 0, NULL
, NULL
, kAsySdoSeqEventTimeout
);
700 //---------------------------------------------------------------------------
702 // Function: EplSdoAsySeqDelCon
704 // Description: del and close one connection
708 // Parameters: SdoSeqConHdl_p = handle of connection
711 // Returns: tEplKernel = errorcode
716 //---------------------------------------------------------------------------
717 tEplKernel
EplSdoAsySeqDelCon(tEplSdoSeqConHdl SdoSeqConHdl_p
)
719 tEplKernel Ret
= kEplSuccessful
;
720 unsigned int uiHandle
;
721 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
723 uiHandle
= (SdoSeqConHdl_p
& ~EPL_SDO_SEQ_HANDLE_MASK
);
725 // check if handle invalid
726 if (uiHandle
>= EPL_MAX_SDO_SEQ_CON
) {
727 Ret
= kEplSdoSeqInvalidHdl
;
730 // get pointer to connection
731 pAsySdoSeqCon
= &AsySdoSequInstance_g
.m_AsySdoConnection
[uiHandle
];
733 // decrement use counter
734 pAsySdoSeqCon
->m_uiUseCount
--;
736 if (pAsySdoSeqCon
->m_uiUseCount
== 0) {
737 // process close in processfunction
738 Ret
= EplSdoAsySeqProcess(uiHandle
,
740 NULL
, NULL
, kAsySdoSeqEventCloseCon
);
743 if ((pAsySdoSeqCon
->m_ConHandle
& EPL_SDO_ASY_HANDLE_MASK
) ==
744 EPL_SDO_UDP_HANDLE
) {
745 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
746 // call close function of lower layer
747 EplSdoUdpuDelCon(pAsySdoSeqCon
->m_ConHandle
);
748 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
750 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
751 // call close function of lower layer
752 EplSdoAsnduDelCon(pAsySdoSeqCon
->m_ConHandle
);
753 #endif // end of #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
757 EplTimeruDeleteTimer(&pAsySdoSeqCon
->m_EplTimerHdl
);
759 // clean controllstructure
760 EPL_MEMSET(pAsySdoSeqCon
, 0x00, sizeof(tEplAsySdoSeqCon
));
761 pAsySdoSeqCon
->m_SdoConHistory
.m_bFreeEntries
=
762 EPL_SDO_HISTORY_SIZE
;
770 //=========================================================================//
772 // P R I V A T E F U N C T I O N S //
774 //=========================================================================//
776 //---------------------------------------------------------------------------
778 // Function: EplEplSdoAsySeqProcess
780 // Description: intern function to process the asynchronus SDO Sequence Layer
785 // Parameters: uiHandle_p = index of the control structure of the connection
786 // uiDataSize_p = size of data frame to process (can be 0)
787 // -> without size of sequence header and Asnd header!!!
789 // pData_p = pointer to frame to send (can be NULL)
790 // pRecFrame_p = pointer to received frame (can be NULL)
791 // Event_p = Event to process
795 // Returns: tEplKernel = errorcode
800 //---------------------------------------------------------------------------
801 static tEplKernel
EplSdoAsySeqProcess(unsigned int uiHandle_p
,
802 unsigned int uiDataSize_p
,
804 tEplAsySdoSeq
* pRecFrame_p
,
805 tEplAsySdoSeqEvent Event_p
)
808 unsigned int uiFrameSize
;
809 tEplFrame
*pEplFrame
;
810 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
811 tEplSdoSeqConHdl SdoSeqConHdl
;
812 unsigned int uiFreeEntries
;
814 #if defined(WIN32) || defined(_WIN32)
815 // enter critical section for process function
816 EnterCriticalSection(AsySdoSequInstance_g
.m_pCriticalSection
);
819 Ret
= kEplSuccessful
;
821 // get handle for hinger layer
822 SdoSeqConHdl
= uiHandle_p
| EPL_SDO_ASY_HANDLE
;
824 // check if handle invalid
825 if ((SdoSeqConHdl
& ~EPL_SDO_SEQ_HANDLE_MASK
) ==
826 EPL_SDO_SEQ_INVALID_HDL
) {
827 Ret
= kEplSdoSeqInvalidHdl
;
830 // get pointer to connection
831 pAsySdoSeqCon
= &AsySdoSequInstance_g
.m_AsySdoConnection
[uiHandle_p
];
834 if ((pData_p
== NULL
) && (pRecFrame_p
== NULL
) && (uiDataSize_p
!= 0)) {
835 Ret
= kEplSdoSeqInvalidFrame
;
839 switch (pAsySdoSeqCon
->m_SdoState
) {
841 case kEplAsySdoStateIdle
:
846 // -> send init frame and change to
847 // kEplAsySdoStateInit1
848 case kAsySdoSeqEventInitCon
:
850 // set sending scon to 1
851 pAsySdoSeqCon
->m_bRecSeqNum
= 0x01;
852 // set set send rcon to 0
853 pAsySdoSeqCon
->m_bSendSeqNum
= 0x00;
855 EplSdoAsySeqSendIntern
856 (pAsySdoSeqCon
, 0, NULL
, FALSE
);
857 if (Ret
!= kEplSuccessful
) {
861 pAsySdoSeqCon
->m_SdoState
=
862 kEplAsySdoStateInit1
;
866 EplSdoAsySeqSetTimer(pAsySdoSeqCon
,
867 EPL_SEQ_DEFAULT_TIMEOUT
);
872 // init con from extern
873 // check rcon and scon
875 case kAsySdoSeqEventFrameRec
:
878 PRINTF3("%s scon=%u rcon=%u\n",
880 pRecFrame_p->m_le_bSendSeqNumCon,
881 pRecFrame_p->m_le_bRecSeqNumCon);
883 // check if scon == 1 and rcon == 0
886 EPL_ASY_SDO_CON_MASK
) == 0x00)
889 m_le_bSendSeqNumCon
&
890 EPL_ASY_SDO_CON_MASK
) == 0x01)) {
891 // save sequence numbers
892 pAsySdoSeqCon
->m_bRecSeqNum
=
896 pAsySdoSeqCon
->m_bSendSeqNum
=
899 m_le_bSendSeqNumCon
);
900 // create answer and send answer
901 // set rcon to 1 (in send direction own scon)
902 pAsySdoSeqCon
->m_bRecSeqNum
++;
904 EplSdoAsySeqSendIntern
905 (pAsySdoSeqCon
, 0, NULL
,
907 if (Ret
!= kEplSuccessful
) {
910 // change state to kEplAsySdoStateInit2
911 pAsySdoSeqCon
->m_SdoState
=
912 kEplAsySdoStateInit2
;
918 EPL_SEQ_DEFAULT_TIMEOUT
);
919 } else { // error -> close
926 EPL_ASY_SDO_CON_MASK
) !=
928 || ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
929 // save sequence numbers
939 m_le_bSendSeqNumCon
);
940 // set rcon and scon to 0
948 EplSdoAsySeqSendIntern
952 // call Command Layer Cb
953 AsySdoSequInstance_g
.
956 kAsySdoConStateInitError
);
965 } // end of switch(Event_p)
969 // init connection step 1
970 // wait for frame with scon = 1
972 case kEplAsySdoStateInit1
:
974 // PRINTF0("EplSdoAsySequ: StateInit1\n");
979 case kAsySdoSeqEventFrameRec
:
981 // check scon == 1 and rcon == 1
984 EPL_ASY_SDO_CON_MASK
) == 0x01)
985 && ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) == 0x01)) { // create answer own scon = 2
986 // save sequence numbers
987 pAsySdoSeqCon
->m_bRecSeqNum
=
991 pAsySdoSeqCon
->m_bSendSeqNum
=
994 m_le_bSendSeqNumCon
);
996 pAsySdoSeqCon
->m_bRecSeqNum
++;
998 EplSdoAsySeqSendIntern
999 (pAsySdoSeqCon
, 0, NULL
,
1001 if (Ret
!= kEplSuccessful
) {
1004 // change state to kEplAsySdoStateInit3
1005 pAsySdoSeqCon
->m_SdoState
=
1006 kEplAsySdoStateInit3
;
1010 EplSdoAsySeqSetTimer
1012 EPL_SEQ_DEFAULT_TIMEOUT
);
1015 // check if scon == 1 and rcon == 0, i.e. other side wants me to be server
1016 else if (((pRecFrame_p
->
1017 m_le_bRecSeqNumCon
&
1018 EPL_ASY_SDO_CON_MASK
) ==
1022 m_le_bSendSeqNumCon
&
1023 EPL_ASY_SDO_CON_MASK
) ==
1025 // save sequence numbers
1026 pAsySdoSeqCon
->m_bRecSeqNum
=
1029 m_le_bRecSeqNumCon
);
1030 pAsySdoSeqCon
->m_bSendSeqNum
=
1033 m_le_bSendSeqNumCon
);
1034 // create answer and send answer
1035 // set rcon to 1 (in send direction own scon)
1036 pAsySdoSeqCon
->m_bRecSeqNum
++;
1038 EplSdoAsySeqSendIntern
1039 (pAsySdoSeqCon
, 0, NULL
,
1041 if (Ret
!= kEplSuccessful
) {
1044 // change state to kEplAsySdoStateInit2
1045 pAsySdoSeqCon
->m_SdoState
=
1046 kEplAsySdoStateInit2
;
1050 EplSdoAsySeqSetTimer
1052 EPL_SEQ_DEFAULT_TIMEOUT
);
1053 } else { // error -> Close
1054 pAsySdoSeqCon
->m_SdoState
=
1055 kEplAsySdoStateIdle
;
1057 EplTimeruDeleteTimer
1061 m_le_bRecSeqNumCon
&
1062 EPL_ASY_SDO_CON_MASK
) !=
1064 || ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
1065 // save sequence numbers
1070 m_le_bRecSeqNumCon
);
1075 m_le_bSendSeqNumCon
);
1077 // set rcon and scon to 0
1085 EplSdoAsySeqSendIntern
1089 // call Command Layer Cb
1090 AsySdoSequInstance_g
.
1093 kAsySdoConStateInitError
);
1099 case kAsySdoSeqEventTimeout
:
1101 pAsySdoSeqCon
->m_SdoState
=
1102 kEplAsySdoStateIdle
;
1104 // set rcon and scon to 0
1105 pAsySdoSeqCon
->m_bSendSeqNum
&=
1107 pAsySdoSeqCon
->m_bRecSeqNum
&=
1110 EplSdoAsySeqSendIntern(pAsySdoSeqCon
,
1112 // call Command Layer Cb
1113 AsySdoSequInstance_g
.
1114 m_fpSdoComConCb(SdoSeqConHdl
,
1115 kAsySdoConStateInitError
);
1123 } // end of switch(Event_p)
1127 // init connection step 2
1128 case kEplAsySdoStateInit2
:
1130 // PRINTF0("EplSdoAsySequ: StateInit2\n");
1135 case kAsySdoSeqEventFrameRec
:
1137 // check scon == 2 and rcon == 1
1139 m_le_bRecSeqNumCon
&
1140 EPL_ASY_SDO_CON_MASK
) == 0x01)
1141 && ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) == 0x02)) { // create answer own rcon = 2
1142 // save sequence numbers
1143 pAsySdoSeqCon
->m_bRecSeqNum
=
1146 m_le_bRecSeqNumCon
);
1147 pAsySdoSeqCon
->m_bSendSeqNum
=
1150 m_le_bSendSeqNumCon
);
1152 pAsySdoSeqCon
->m_bRecSeqNum
++;
1154 EplSdoAsySeqSendIntern
1155 (pAsySdoSeqCon
, 0, NULL
,
1157 if (Ret
!= kEplSuccessful
) {
1160 // change state to kEplAsySdoStateConnected
1161 pAsySdoSeqCon
->m_SdoState
=
1162 kEplAsySdoStateConnected
;
1166 EplSdoAsySeqSetTimer
1168 EPL_SEQ_DEFAULT_TIMEOUT
);
1170 // call Command Layer Cb
1171 AsySdoSequInstance_g
.
1174 kAsySdoConStateConnected
);
1177 // check scon == 1 and rcon == 1, i.e. other side wants me to initiate the connection
1178 else if (((pRecFrame_p
->
1179 m_le_bRecSeqNumCon
&
1180 EPL_ASY_SDO_CON_MASK
) ==
1184 m_le_bSendSeqNumCon
&
1185 EPL_ASY_SDO_CON_MASK
) ==
1187 // save sequence numbers
1188 pAsySdoSeqCon
->m_bRecSeqNum
=
1191 m_le_bRecSeqNumCon
);
1192 pAsySdoSeqCon
->m_bSendSeqNum
=
1195 m_le_bSendSeqNumCon
);
1196 // create answer and send answer
1197 // set rcon to 1 (in send direction own scon)
1198 pAsySdoSeqCon
->m_bRecSeqNum
++;
1200 EplSdoAsySeqSendIntern
1201 (pAsySdoSeqCon
, 0, NULL
,
1203 if (Ret
!= kEplSuccessful
) {
1208 EplSdoAsySeqSetTimer
1210 EPL_SEQ_DEFAULT_TIMEOUT
);
1211 // change state to kEplAsySdoStateInit3
1212 pAsySdoSeqCon
->m_SdoState
=
1213 kEplAsySdoStateInit3
;
1215 } else { // error -> Close
1216 pAsySdoSeqCon
->m_SdoState
=
1217 kEplAsySdoStateIdle
;
1219 EplTimeruDeleteTimer
1223 m_le_bRecSeqNumCon
&
1224 EPL_ASY_SDO_CON_MASK
) !=
1226 || ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
1227 // save sequence numbers
1232 m_le_bRecSeqNumCon
);
1237 m_le_bSendSeqNumCon
);
1238 // set rcon and scon to 0
1246 EplSdoAsySeqSendIntern
1250 // call Command Layer Cb
1251 AsySdoSequInstance_g
.
1254 kAsySdoConStateInitError
);
1260 case kAsySdoSeqEventTimeout
:
1262 pAsySdoSeqCon
->m_SdoState
=
1263 kEplAsySdoStateIdle
;
1264 // set rcon and scon to 0
1265 pAsySdoSeqCon
->m_bSendSeqNum
&=
1267 pAsySdoSeqCon
->m_bRecSeqNum
&=
1270 EplSdoAsySeqSendIntern(pAsySdoSeqCon
,
1273 // call Command Layer Cb
1274 AsySdoSequInstance_g
.
1275 m_fpSdoComConCb(SdoSeqConHdl
,
1276 kAsySdoConStateInitError
);
1284 } // end of switch(Event_p)
1288 // init connection step 3
1289 case kEplAsySdoStateInit3
:
1294 case kAsySdoSeqEventFrameRec
:
1296 // check scon == 2 and rcon == 2
1298 m_le_bRecSeqNumCon
&
1299 EPL_ASY_SDO_CON_MASK
) == 0x02)
1302 m_le_bSendSeqNumCon
&
1303 EPL_ASY_SDO_CON_MASK
) == 0x02)) {
1304 // save sequence numbers
1305 pAsySdoSeqCon
->m_bRecSeqNum
=
1308 m_le_bRecSeqNumCon
);
1309 pAsySdoSeqCon
->m_bSendSeqNum
=
1312 m_le_bSendSeqNumCon
);
1313 // change state to kEplAsySdoStateConnected
1314 pAsySdoSeqCon
->m_SdoState
=
1315 kEplAsySdoStateConnected
;
1319 EplSdoAsySeqSetTimer
1321 EPL_SEQ_DEFAULT_TIMEOUT
);
1322 // call Command Layer Cb
1323 AsySdoSequInstance_g
.
1326 kAsySdoConStateConnected
);
1329 // check scon == 2 and rcon == 1
1330 else if (((pRecFrame_p
->
1331 m_le_bRecSeqNumCon
&
1332 EPL_ASY_SDO_CON_MASK
) ==
1334 && ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) == 0x02)) { // create answer own rcon = 2
1335 // save sequence numbers
1336 pAsySdoSeqCon
->m_bRecSeqNum
=
1339 m_le_bRecSeqNumCon
);
1340 pAsySdoSeqCon
->m_bSendSeqNum
=
1343 m_le_bSendSeqNumCon
);
1345 pAsySdoSeqCon
->m_bRecSeqNum
++;
1347 EplSdoAsySeqSendIntern
1348 (pAsySdoSeqCon
, 0, NULL
,
1350 if (Ret
!= kEplSuccessful
) {
1353 // change state to kEplAsySdoStateConnected
1354 pAsySdoSeqCon
->m_SdoState
=
1355 kEplAsySdoStateConnected
;
1359 EplSdoAsySeqSetTimer
1361 EPL_SEQ_DEFAULT_TIMEOUT
);
1363 // call Command Layer Cb
1364 AsySdoSequInstance_g
.
1367 kAsySdoConStateConnected
);
1369 } else { // error -> Close
1370 pAsySdoSeqCon
->m_SdoState
=
1371 kEplAsySdoStateIdle
;
1373 EplTimeruDeleteTimer
1377 m_le_bRecSeqNumCon
&
1378 EPL_ASY_SDO_CON_MASK
) !=
1380 || ((pRecFrame_p
->m_le_bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) != 0x00)) { // d.k. only answer with close message if the message sent was not a close message
1381 // save sequence numbers
1386 m_le_bRecSeqNumCon
);
1391 m_le_bSendSeqNumCon
);
1392 // set rcon and scon to 0
1400 EplSdoAsySeqSendIntern
1404 // call Command Layer Cb
1405 AsySdoSequInstance_g
.
1408 kAsySdoConStateInitError
);
1414 case kAsySdoSeqEventTimeout
:
1416 pAsySdoSeqCon
->m_SdoState
=
1417 kEplAsySdoStateIdle
;
1418 // set rcon and scon to 0
1419 pAsySdoSeqCon
->m_bSendSeqNum
&=
1421 pAsySdoSeqCon
->m_bRecSeqNum
&=
1424 EplSdoAsySeqSendIntern(pAsySdoSeqCon
,
1427 // call Command Layer Cb
1428 AsySdoSequInstance_g
.
1429 m_fpSdoComConCb(SdoSeqConHdl
,
1430 kAsySdoConStateInitError
);
1438 } // end of switch(Event_p)
1442 // connection established
1443 case kEplAsySdoStateConnected
:
1449 case kAsySdoSeqEventFrameSend
:
1453 EplSdoAsySeqSetTimer(pAsySdoSeqCon
,
1454 EPL_SEQ_DEFAULT_TIMEOUT
);
1455 // check if data frame or ack
1456 if (pData_p
== NULL
) { // send ack
1458 //pAsySdoSeqCon->m_bRecSeqNum += 4;
1460 EplSdoAsySeqSendIntern
1461 (pAsySdoSeqCon
, 0, NULL
,
1463 if (Ret
!= kEplSuccessful
) {
1466 } else { // send dataframe
1467 // increment send sequence number
1468 pAsySdoSeqCon
->m_bRecSeqNum
+=
1471 EplSdoAsySeqSendIntern
1473 uiDataSize_p
, pData_p
,
1475 if (Ret
== kEplSdoSeqRequestAckNeeded
) { // request ack
1476 // change state to wait ack
1479 kEplAsySdoStateWaitAck
;
1480 // set Ret to kEplSuccessful, because no error
1482 Ret
= kEplSuccessful
;
1488 // call Command Layer Cb
1489 AsySdoSequInstance_g
.
1492 kAsySdoConStateFrameSended
);
1496 } // end of case kAsySdoSeqEventFrameSend
1499 case kAsySdoSeqEventFrameRec
:
1502 AmiGetByteFromLe(&pRecFrame_p
->
1503 m_le_bSendSeqNumCon
);
1507 EplSdoAsySeqSetTimer(pAsySdoSeqCon
,
1508 EPL_SEQ_DEFAULT_TIMEOUT
);
1510 switch (bSendSeqNumCon
&
1511 EPL_ASY_SDO_CON_MASK
) {
1512 // close from other node
1519 kEplAsySdoStateIdle
;
1521 EplTimeruDeleteTimer
1524 // call Command Layer Cb
1525 AsySdoSequInstance_g
.
1528 kAsySdoConStateConClosed
);
1533 // Request Ack or Error Ack
1534 // possible contain data
1539 if ((AmiGetByteFromLe
1543 EPL_ASY_SDO_CON_MASK
)
1545 // PRINTF0("EplSdoAsySequ: error response received\n");
1547 // error response (retransmission request)
1548 // resend frames from history
1550 // read frame from history
1552 EplSdoAsyReadFromHistory
1563 while ((pEplFrame
!= NULL
)
1569 EplSdoAsySeqSendLowerLayer
1579 // read next frame from history
1581 EplSdoAsyReadFromHistory
1592 } // end of while((pabFrame != NULL)
1593 } // end of if (error response)
1595 if (((pAsySdoSeqCon
->m_bSendSeqNum
+ 4) & EPL_SEQ_NUM_MASK
) == (bSendSeqNumCon
& EPL_SEQ_NUM_MASK
)) { // next frame of sequence received
1596 // save send sequence number (without ack request)
1603 // check if ack or data-frame
1604 //ignore ack -> already processed
1607 EPL_SEQ_HEADER_SIZE
)
1609 AsySdoSequInstance_g
.
1612 ((tEplAsySdoCom
*) & pRecFrame_p
->m_le_abSdoSeqPayload
), (uiDataSize_p
- EPL_SEQ_HEADER_SIZE
));
1613 // call Command Layer Cb
1614 AsySdoSequInstance_g
.
1617 kAsySdoConStateFrameSended
);
1620 // call Command Layer Cb
1621 AsySdoSequInstance_g
.
1624 kAsySdoConStateAckReceived
);
1626 } else if (((bSendSeqNumCon
- pAsySdoSeqCon
->m_bSendSeqNum
- 4) & EPL_SEQ_NUM_MASK
) < EPL_SEQ_NUM_THRESHOLD
) { // frame of sequence was lost,
1627 // because difference of received and old value
1628 // is less then halve of the values range.
1630 // send error frame with own rcon = 3
1635 EplSdoAsySeqSendIntern
1639 // restore send sequence number
1653 // break here, because a requested acknowledge
1654 // was sent implicitly above
1657 // else, ignore repeated frame
1659 if ((bSendSeqNumCon
& EPL_ASY_SDO_CON_MASK
) == 3) { // ack request received
1661 // create ack with own scon = 2
1663 EplSdoAsySeqSendIntern
1677 } // switch(pAsySdoSeqCon->m_bSendSeqNum & EPL_ASY_SDO_CON_MASK)
1679 } // end of case kAsySdoSeqEventFrameRec:
1681 //close event from higher layer
1682 case kAsySdoSeqEventCloseCon
:
1684 pAsySdoSeqCon
->m_SdoState
=
1685 kEplAsySdoStateIdle
;
1686 // set rcon and scon to 0
1687 pAsySdoSeqCon
->m_bSendSeqNum
&=
1689 pAsySdoSeqCon
->m_bRecSeqNum
&=
1692 EplSdoAsySeqSendIntern(pAsySdoSeqCon
,
1696 EplTimeruDeleteTimer(&pAsySdoSeqCon
->
1698 // call Command Layer Cb is not necessary, because the event came from there
1699 // AsySdoSequInstance_g.m_fpSdoComConCb(SdoSeqConHdl,
1700 // kAsySdoConStateInitError);
1705 case kAsySdoSeqEventTimeout
:
1709 EplSdoAsyGetFreeEntriesFromHistory
1711 if ((uiFreeEntries
<
1712 EPL_SDO_HISTORY_SIZE
)
1713 && (pAsySdoSeqCon
->m_uiRetryCount
< EPL_SEQ_RETRY_COUNT
)) { // unacknowlegded frames in history
1714 // and retry counter not exceeded
1716 // resend data with acknowledge request
1718 // increment retry counter
1719 pAsySdoSeqCon
->m_uiRetryCount
++;
1723 EplSdoAsySeqSetTimer
1725 EPL_SEQ_DEFAULT_TIMEOUT
);
1727 // read first frame from history
1729 EplSdoAsyReadFromHistory
1730 (pAsySdoSeqCon
, &pEplFrame
,
1731 &uiFrameSize
, TRUE
);
1732 if (Ret
!= kEplSuccessful
) {
1736 if ((pEplFrame
!= NULL
)
1737 && (uiFrameSize
!= 0)) {
1739 // set ack request in scon
1741 (&pEplFrame
->m_Data
.
1744 m_le_bSendSeqNumCon
,
1750 m_le_bSendSeqNumCon
)
1755 EplSdoAsySeqSendLowerLayer
1766 // timeout, because of no traffic -> Close
1767 pAsySdoSeqCon
->m_SdoState
=
1768 kEplAsySdoStateIdle
;
1769 // set rcon and scon to 0
1770 pAsySdoSeqCon
->m_bSendSeqNum
&=
1772 pAsySdoSeqCon
->m_bRecSeqNum
&=
1775 EplSdoAsySeqSendIntern
1776 (pAsySdoSeqCon
, 0, NULL
,
1779 // call Command Layer Cb
1780 AsySdoSequInstance_g
.
1783 kAsySdoConStateTimeout
);
1793 } // end of switch(Event_p)
1797 // wait for Acknowledge (history buffer full)
1798 case kEplAsySdoStateWaitAck
:
1800 PRINTF0("EplSdoAsySequ: StateWaitAck\n");
1803 Ret
= EplSdoAsySeqSetTimer(pAsySdoSeqCon
,
1804 EPL_SEQ_DEFAULT_TIMEOUT
);
1806 //TODO: retry of acknowledge
1807 if (Event_p
== kAsySdoSeqEventFrameRec
) {
1809 switch (pRecFrame_p
->
1810 m_le_bRecSeqNumCon
&
1811 EPL_ASY_SDO_CON_MASK
) {
1812 // close-frome other node
1816 pAsySdoSeqCon
->m_SdoState
=
1817 kEplAsySdoStateIdle
;
1819 EplTimeruDeleteTimer
1822 // call Command Layer Cb
1823 AsySdoSequInstance_g
.
1826 kAsySdoConStateConClosed
);
1835 // -> change to state kEplAsySdoStateConnected
1836 pAsySdoSeqCon
->m_SdoState
=
1837 kEplAsySdoStateConnected
;
1838 // call Command Layer Cb
1839 AsySdoSequInstance_g
.
1842 kAsySdoConStateAckReceived
);
1843 // send data to higher layer if needed
1845 EPL_SEQ_HEADER_SIZE
) {
1846 AsySdoSequInstance_g
.
1851 m_le_abSdoSeqPayload
),
1853 EPL_SEQ_HEADER_SIZE
));
1858 // Request Ack or Error Ack
1861 // -> change to state kEplAsySdoStateConnected
1862 pAsySdoSeqCon
->m_SdoState
=
1863 kEplAsySdoStateConnected
;
1865 if (pRecFrame_p
->m_le_bRecSeqNumCon
== pAsySdoSeqCon
->m_bRecSeqNum
) { // ack request
1867 // save sequence numbers
1872 m_le_bRecSeqNumCon
);
1877 m_le_bSendSeqNumCon
);
1879 // create answer own rcon = 2
1883 // check if ack or data-frame
1885 EPL_SEQ_HEADER_SIZE
)
1887 AsySdoSequInstance_g
.
1890 ((tEplAsySdoCom
*) & pRecFrame_p
->m_le_abSdoSeqPayload
), (uiDataSize_p
- EPL_SEQ_HEADER_SIZE
));
1891 // call Command Layer Cb
1892 AsySdoSequInstance_g
.
1895 kAsySdoConStateFrameSended
);
1899 EplSdoAsySeqSendIntern
1912 // resend frames from history
1914 // read frame from history
1916 EplSdoAsyReadFromHistory
1921 while ((pEplFrame
!=
1927 EplSdoAsySeqSendLowerLayer
1938 // read frame from history
1940 EplSdoAsyReadFromHistory
1945 } // end of while((pabFrame != NULL)
1949 } // end of switch(pRecFrame_p->m_le_bRecSeqNumCon & EPL_ASY_SDO_CON_MASK)
1951 } else if (Event_p
== kAsySdoSeqEventTimeout
) { // error -> Close
1952 pAsySdoSeqCon
->m_SdoState
= kEplAsySdoStateIdle
;
1953 // set rcon and scon to 0
1954 pAsySdoSeqCon
->m_bSendSeqNum
&=
1956 pAsySdoSeqCon
->m_bRecSeqNum
&= EPL_SEQ_NUM_MASK
;
1958 EplSdoAsySeqSendIntern(pAsySdoSeqCon
,
1961 // call Command Layer Cb
1962 AsySdoSequInstance_g
.
1963 m_fpSdoComConCb(SdoSeqConHdl
,
1964 kAsySdoConStateTimeout
);
1973 EPL_DBGLVL_SDO_TRACE0
1974 ("Error: Unknown State in EplSdoAsySeqProcess\n");
1977 } // end of switch(pAsySdoSeqCon->m_SdoState)
1981 #if defined(WIN32) || defined(_WIN32)
1982 // leave critical section for process function
1983 LeaveCriticalSection(AsySdoSequInstance_g
.m_pCriticalSection
);
1989 //---------------------------------------------------------------------------
1991 // Function: EplSdoAsySeqSendIntern
1993 // Description: intern function to create and send a frame
1994 // -> if uiDataSize_p == 0 create a frame with infos from
1999 // Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection
2000 // uiDataSize_p = size of data frame to process (can be 0)
2001 // -> without size of sequence header and Asnd header!!!
2002 // pData_p = pointer to frame to process (can be NULL)
2003 // fFrameInHistory = if TRUE frame is saved to history else not
2007 // Returns: tEplKernel = errorcode
2012 //---------------------------------------------------------------------------
2013 static tEplKernel
EplSdoAsySeqSendIntern(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2014 unsigned int uiDataSize_p
,
2015 tEplFrame
* pData_p
,
2016 BOOL fFrameInHistory_p
)
2019 u8 abFrame
[EPL_SEQ_FRAME_SIZE
];
2020 tEplFrame
*pEplFrame
;
2021 unsigned int uiFreeEntries
;
2023 if (pData_p
== NULL
) { // set pointer to own frame
2024 EPL_MEMSET(&abFrame
[0], 0x00, sizeof(abFrame
));
2025 pEplFrame
= (tEplFrame
*) & abFrame
[0];
2026 } else { // set pointer to frame from calling function
2027 pEplFrame
= pData_p
;
2030 if (fFrameInHistory_p
!= FALSE
) {
2031 // check if only one free entry in history buffer
2033 EplSdoAsyGetFreeEntriesFromHistory(pAsySdoSeqCon_p
);
2034 if (uiFreeEntries
== 1) { // request an acknowledge in dataframe
2036 pAsySdoSeqCon_p
->m_bRecSeqNum
|= 0x03;
2039 // fillin header informations
2040 // set service id sdo
2041 AmiSetByteToLe(&pEplFrame
->m_Data
.m_Asnd
.m_le_bServiceId
, 0x05);
2042 AmiSetByteToLe(&pEplFrame
->m_Data
.m_Asnd
.m_Payload
.m_SdoSequenceFrame
.
2043 m_le_abReserved
, 0x00);
2044 // set receive sequence number and rcon
2045 AmiSetByteToLe(&pEplFrame
->m_Data
.m_Asnd
.m_Payload
.m_SdoSequenceFrame
.
2046 m_le_bRecSeqNumCon
, pAsySdoSeqCon_p
->m_bSendSeqNum
);
2047 // set send sequence number and scon
2048 AmiSetByteToLe(&pEplFrame
->m_Data
.m_Asnd
.m_Payload
.m_SdoSequenceFrame
.
2049 m_le_bSendSeqNumCon
, pAsySdoSeqCon_p
->m_bRecSeqNum
);
2052 uiDataSize_p
+= EPL_SEQ_HEADER_SIZE
;
2054 // forward frame to appropriate lower layer
2055 Ret
= EplSdoAsySeqSendLowerLayer(pAsySdoSeqCon_p
, uiDataSize_p
, pEplFrame
); // pointer to frame
2057 // check if all allright
2058 if ((Ret
== kEplSuccessful
)
2059 && (fFrameInHistory_p
!= FALSE
)) {
2060 // set own scon to 2 if needed
2061 if ((pAsySdoSeqCon_p
->m_bRecSeqNum
& 0x03) == 0x03) {
2062 pAsySdoSeqCon_p
->m_bRecSeqNum
--;
2064 // save frame to history
2065 Ret
= EplSdoAsyAddFrameToHistory(pAsySdoSeqCon_p
,
2066 pEplFrame
, uiDataSize_p
);
2067 if (Ret
== kEplSdoSeqNoFreeHistory
) { // request Ack needed
2068 Ret
= kEplSdoSeqRequestAckNeeded
;
2076 //---------------------------------------------------------------------------
2078 // Function: EplSdoAsySeqSendLowerLayer
2080 // Description: intern function to send a previously created frame to lower layer
2082 // Parameters: pAsySdoSeqCon_p = pointer to control structure of the connection
2083 // uiDataSize_p = size of data frame to process (can be 0)
2084 // -> without size of Asnd header!!!
2085 // pData_p = pointer to frame to process (can be NULL)
2087 // Returns: tEplKernel = errorcode
2092 //---------------------------------------------------------------------------
2093 static tEplKernel
EplSdoAsySeqSendLowerLayer(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2094 unsigned int uiDataSize_p
,
2095 tEplFrame
* pEplFrame_p
)
2099 // call send-function
2100 // check handle for UDP or Asnd
2101 if ((pAsySdoSeqCon_p
->m_ConHandle
& EPL_SDO_ASY_HANDLE_MASK
) == EPL_SDO_UDP_HANDLE
) { // send over UDP
2102 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_UDP)) != 0)
2103 Ret
= EplSdoUdpuSendData(pAsySdoSeqCon_p
->m_ConHandle
, pEplFrame_p
, // pointer to frame
2106 Ret
= kEplSdoSeqUnsupportedProt
;
2109 } else if ((pAsySdoSeqCon_p
->m_ConHandle
& EPL_SDO_ASY_HANDLE_MASK
) == EPL_SDO_ASND_HANDLE
) { // ASND
2110 #if(((EPL_MODULE_INTEGRATION) & (EPL_MODULE_SDO_ASND)) != 0)
2111 Ret
= EplSdoAsnduSendData(pAsySdoSeqCon_p
->m_ConHandle
, pEplFrame_p
, // pointer to frame
2114 Ret
= kEplSdoSeqUnsupportedProt
;
2117 Ret
= kEplSdoSeqInvalidHdl
;
2123 //---------------------------------------------------------------------------
2125 // Function: EplSdoAsyReceiveCb
2127 // Description: callback-function for received frames from lower layer
2131 // Parameters: ConHdl_p = handle of the connection
2132 // pSdoSeqData_p = pointer to frame
2133 // uiDataSize_p = size of frame
2136 // Returns: tEplKernel = errorcode
2141 //---------------------------------------------------------------------------
2142 tEplKernel
EplSdoAsyReceiveCb(tEplSdoConHdl ConHdl_p
,
2143 tEplAsySdoSeq
*pSdoSeqData_p
,
2144 unsigned int uiDataSize_p
)
2147 unsigned int uiCount
= 0;
2148 unsigned int uiFreeEntry
= EPL_MAX_SDO_SEQ_CON
;
2149 tEplAsySdoSeqCon
*pAsySdoSeqCon
;
2151 #if defined(WIN32) || defined(_WIN32)
2152 // enter critical section
2153 EnterCriticalSection(AsySdoSequInstance_g
.m_pCriticalSectionReceive
);
2156 EPL_DBGLVL_SDO_TRACE2("Handle: 0x%x , First Databyte 0x%x\n", ConHdl_p
,
2157 ((u8
*) pSdoSeqData_p
)[0]);
2159 // search controll structure for this connection
2160 pAsySdoSeqCon
= &AsySdoSequInstance_g
.m_AsySdoConnection
[uiCount
];
2161 while (uiCount
< EPL_MAX_SDO_SEQ_CON
) {
2162 if (pAsySdoSeqCon
->m_ConHandle
== ConHdl_p
) {
2164 } else if ((pAsySdoSeqCon
->m_ConHandle
== 0)
2165 && (uiFreeEntry
== EPL_MAX_SDO_SEQ_CON
)) {
2167 uiFreeEntry
= uiCount
;
2173 if (uiCount
== EPL_MAX_SDO_SEQ_CON
) { // new connection
2174 if (uiFreeEntry
== EPL_MAX_SDO_SEQ_CON
) {
2175 Ret
= kEplSdoSeqNoFreeHandle
;
2179 &AsySdoSequInstance_g
.
2180 m_AsySdoConnection
[uiFreeEntry
];
2181 // save handle from lower layer
2182 pAsySdoSeqCon
->m_ConHandle
= ConHdl_p
;
2183 // increment use counter
2184 pAsySdoSeqCon
->m_uiUseCount
++;
2185 uiCount
= uiFreeEntry
;
2188 // call history ack function
2189 Ret
= EplSdoAsyAckFrameToHistory(pAsySdoSeqCon
,
2192 m_le_bRecSeqNumCon
) &
2194 if (Ret
!= kEplSuccessful
) {
2197 #if defined(WIN32) || defined(_WIN32)
2198 // leave critical section
2199 LeaveCriticalSection(AsySdoSequInstance_g
.m_pCriticalSectionReceive
);
2202 // call process function with pointer of frame and event kAsySdoSeqEventFrameRec
2203 Ret
= EplSdoAsySeqProcess(uiCount
,
2205 NULL
, pSdoSeqData_p
, kAsySdoSeqEventFrameRec
);
2211 //---------------------------------------------------------------------------
2213 // Function: EplSdoAsyInitHistory
2215 // Description: inti function for history buffer
2222 // Returns: tEplKernel = errorcode
2227 //---------------------------------------------------------------------------
2228 static tEplKernel
EplSdoAsyInitHistory(void)
2231 unsigned int uiCount
;
2233 Ret
= kEplSuccessful
;
2234 // init m_bFreeEntries in history-buffer
2235 for (uiCount
= 0; uiCount
< EPL_MAX_SDO_SEQ_CON
; uiCount
++) {
2236 AsySdoSequInstance_g
.m_AsySdoConnection
[uiCount
].
2237 m_SdoConHistory
.m_bFreeEntries
= EPL_SDO_HISTORY_SIZE
;
2243 //---------------------------------------------------------------------------
2245 // Function: EplSdoAsyAddFrameToHistory
2247 // Description: function to add a frame to the history buffer
2251 // Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
2252 // pFrame_p = pointer to frame
2253 // uiSize_p = size of the frame
2254 // -> without size of the ethernet header
2255 // and the asnd header
2257 // Returns: tEplKernel = errorcode
2262 //---------------------------------------------------------------------------
2263 static tEplKernel
EplSdoAsyAddFrameToHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2264 tEplFrame
* pFrame_p
,
2265 unsigned int uiSize_p
)
2268 tEplAsySdoConHistory
*pHistory
;
2270 Ret
= kEplSuccessful
;
2272 // add frame to history buffer
2275 // $$$ d.k. EPL_SEQ_HISTORY_FRAME_SIZE includes the header size, but uiSize_p does not!!!
2276 if (uiSize_p
> EPL_SEQ_HISTROY_FRAME_SIZE
) {
2277 Ret
= kEplSdoSeqFrameSizeError
;
2280 // save pointer to history
2281 pHistory
= &pAsySdoSeqCon_p
->m_SdoConHistory
;
2283 // check if a free entry is available
2284 if (pHistory
->m_bFreeEntries
> 0) { // write message in free entry
2286 ((tEplFrame
*) pHistory
->
2287 m_aabHistoryFrame
[pHistory
->m_bWrite
])->
2288 m_le_bMessageType
, &pFrame_p
->m_le_bMessageType
,
2289 uiSize_p
+ EPL_ASND_HEADER_SIZE
);
2291 pHistory
->m_auiFrameSize
[pHistory
->m_bWrite
] = uiSize_p
;
2293 // decremend number of free bufferentries
2294 pHistory
->m_bFreeEntries
--;
2296 // increment writeindex
2297 pHistory
->m_bWrite
++;
2299 // check if write-index run over array-boarder
2300 if (pHistory
->m_bWrite
== EPL_SDO_HISTORY_SIZE
) {
2301 pHistory
->m_bWrite
= 0;
2304 } else { // no free entry
2305 Ret
= kEplSdoSeqNoFreeHistory
;
2312 //---------------------------------------------------------------------------
2314 // Function: EplSdoAsyAckFrameToHistory
2316 // Description: function to delete acknowledged frames fron history buffer
2320 // Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
2321 // bRecSeqNumber_p = receive sequence number of the received frame
2324 // Returns: tEplKernel = errorcode
2329 //---------------------------------------------------------------------------
2330 static tEplKernel
EplSdoAsyAckFrameToHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2334 tEplAsySdoConHistory
*pHistory
;
2338 Ret
= kEplSuccessful
;
2340 // get pointer to history buffer
2341 pHistory
= &pAsySdoSeqCon_p
->m_SdoConHistory
;
2343 // release all acknowledged frames from history buffer
2345 // check if there are entries in history
2346 if (pHistory
->m_bFreeEntries
< EPL_SDO_HISTORY_SIZE
) {
2347 bAckIndex
= pHistory
->m_bAck
;
2350 (((tEplFrame
*) pHistory
->
2351 m_aabHistoryFrame
[bAckIndex
])->m_Data
.m_Asnd
.
2352 m_Payload
.m_SdoSequenceFrame
.
2353 m_le_bSendSeqNumCon
& EPL_SEQ_NUM_MASK
);
2354 if (((bRecSeqNumber_p
-
2355 bCurrentSeqNum
) & EPL_SEQ_NUM_MASK
)
2356 < EPL_SEQ_NUM_THRESHOLD
) {
2357 pHistory
->m_auiFrameSize
[bAckIndex
] = 0;
2359 pHistory
->m_bFreeEntries
++;
2360 if (bAckIndex
== EPL_SDO_HISTORY_SIZE
) { // read index run over array-boarder
2363 } else { // nothing to do anymore,
2364 // because any further frame in history has larger sequence
2365 // number than the acknowledge
2369 while ((((bRecSeqNumber_p
- 1 -
2370 bCurrentSeqNum
) & EPL_SEQ_NUM_MASK
)
2371 < EPL_SEQ_NUM_THRESHOLD
)
2372 && (pHistory
->m_bWrite
!= bAckIndex
));
2374 // store local read-index to global var
2375 pHistory
->m_bAck
= bAckIndex
;
2382 //---------------------------------------------------------------------------
2384 // Function: EplSdoAsyReadFromHistory
2386 // Description: function to one frame from history
2390 // Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
2391 // ppFrame_p = pointer to pointer to the buffer of the stored frame
2392 // puiSize_p = OUT: size of the frame
2393 // fInitRead = bool which indicate a start of retransmission
2394 // -> return last not acknowledged message if TRUE
2397 // Returns: tEplKernel = errorcode
2402 //---------------------------------------------------------------------------
2403 static tEplKernel
EplSdoAsyReadFromHistory(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2404 tEplFrame
** ppFrame_p
,
2405 unsigned int *puiSize_p
,
2409 tEplAsySdoConHistory
*pHistory
;
2411 Ret
= kEplSuccessful
;
2413 // read one message from History
2415 // get pointer to history buffer
2416 pHistory
= &pAsySdoSeqCon_p
->m_SdoConHistory
;
2419 if (fInitRead_p
!= FALSE
) { // initialize read index to the index which shall be acknowledged next
2420 pHistory
->m_bRead
= pHistory
->m_bAck
;
2422 // check if entries are available for reading
2423 if ((pHistory
->m_bFreeEntries
< EPL_SDO_HISTORY_SIZE
)
2424 && (pHistory
->m_bWrite
!= pHistory
->m_bRead
)) {
2425 // PRINTF4("EplSdoAsyReadFromHistory(): init = %d, read = %u, write = %u, ack = %u", (int) fInitRead_p, (u16)pHistory->m_bRead, (u16)pHistory->m_bWrite, (u16)pHistory->m_bAck);
2426 // PRINTF2(", free entries = %u, next frame size = %u\n", (u16)pHistory->m_bFreeEntries, pHistory->m_auiFrameSize[pHistory->m_bRead]);
2428 // return pointer to stored frame
2430 (tEplFrame
*) pHistory
->m_aabHistoryFrame
[pHistory
->
2434 *puiSize_p
= pHistory
->m_auiFrameSize
[pHistory
->m_bRead
];
2436 pHistory
->m_bRead
++;
2437 if (pHistory
->m_bRead
== EPL_SDO_HISTORY_SIZE
) {
2438 pHistory
->m_bRead
= 0;
2442 // PRINTF3("EplSdoAsyReadFromHistory(): read = %u, ack = %u, free entries = %u, no frame\n", (u16)pHistory->m_bRead, (u16)pHistory->m_bAck, (u16)pHistory->m_bFreeEntries);
2444 // no more frames to send
2445 // return null pointer
2455 //---------------------------------------------------------------------------
2457 // Function: EplSdoAsyGetFreeEntriesFromHistory
2459 // Description: function returns the number of free histroy entries
2463 // Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
2466 // Returns: unsigned int = number of free entries
2471 //---------------------------------------------------------------------------
2472 static unsigned int EplSdoAsyGetFreeEntriesFromHistory(tEplAsySdoSeqCon
*
2475 unsigned int uiFreeEntries
;
2478 (unsigned int)pAsySdoSeqCon_p
->m_SdoConHistory
.m_bFreeEntries
;
2480 return uiFreeEntries
;
2483 //---------------------------------------------------------------------------
2485 // Function: EplSdoAsySeqSetTimer
2487 // Description: function sets or modify timer in timermosule
2491 // Parameters: pAsySdoSeqCon_p = pointer to control structure of this connection
2492 // ulTimeout = timeout in ms
2495 // Returns: unsigned int = number of free entries
2500 //---------------------------------------------------------------------------
2501 static tEplKernel
EplSdoAsySeqSetTimer(tEplAsySdoSeqCon
* pAsySdoSeqCon_p
,
2502 unsigned long ulTimeout
)
2505 tEplTimerArg TimerArg
;
2507 TimerArg
.m_EventSink
= kEplEventSinkSdoAsySeq
;
2508 TimerArg
.m_ulArg
= (unsigned long)pAsySdoSeqCon_p
;
2510 if (pAsySdoSeqCon_p
->m_EplTimerHdl
== 0) { // create new timer
2511 Ret
= EplTimeruSetTimerMs(&pAsySdoSeqCon_p
->m_EplTimerHdl
,
2512 ulTimeout
, TimerArg
);
2513 } else { // modify exisiting timer
2514 Ret
= EplTimeruModifyTimerMs(&pAsySdoSeqCon_p
->m_EplTimerHdl
,
2515 ulTimeout
, TimerArg
);