1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for kernel PDO 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: EplPdok.c,v $
56 $Revision: 1.8 $ $Date: 2008/10/17 15:32:32 $
63 -------------------------------------------------------------------------
67 2006/05/22 d.k.: start of the implementation, version 1.00
69 ****************************************************************************/
71 #include "kernel/EplPdok.h"
72 #include "kernel/EplPdokCal.h"
73 #include "kernel/EplEventk.h"
74 #include "kernel/EplObdk.h"
76 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
78 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) == 0)
80 #error 'ERROR: Missing DLLk-Modul!'
84 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0)
86 #error 'ERROR: Missing OBDk-Modul!'
89 /***************************************************************************/
92 /* G L O B A L D E F I N I T I O N S */
95 /***************************************************************************/
97 //---------------------------------------------------------------------------
99 //---------------------------------------------------------------------------
101 #define EPL_PDOK_OBD_IDX_RX_COMM_PARAM 0x1400
102 #define EPL_PDOK_OBD_IDX_RX_MAPP_PARAM 0x1600
103 #define EPL_PDOK_OBD_IDX_TX_COMM_PARAM 0x1800
104 #define EPL_PDOK_OBD_IDX_TX_MAPP_PARAM 0x1A00
106 //---------------------------------------------------------------------------
108 //---------------------------------------------------------------------------
110 //---------------------------------------------------------------------------
111 // modul globale vars
112 //---------------------------------------------------------------------------
114 //---------------------------------------------------------------------------
115 // local function prototypes
116 //---------------------------------------------------------------------------
118 /***************************************************************************/
121 /* C L A S S EplPdok */
124 /***************************************************************************/
129 /***************************************************************************/
131 //=========================================================================//
133 // P R I V A T E D E F I N I T I O N S //
135 //=========================================================================//
137 //---------------------------------------------------------------------------
139 //---------------------------------------------------------------------------
141 //---------------------------------------------------------------------------
143 //---------------------------------------------------------------------------
145 //---------------------------------------------------------------------------
147 //---------------------------------------------------------------------------
149 //---------------------------------------------------------------------------
150 // local function prototypes
151 //---------------------------------------------------------------------------
153 //=========================================================================//
155 // P U B L I C F U N C T I O N S //
157 //=========================================================================//
159 //---------------------------------------------------------------------------
161 // Function: EplPdokAddInstance()
163 // Description: add and initialize new instance of EPL stack
167 // Returns: tEplKernel = error code
172 //---------------------------------------------------------------------------
174 tEplKernel
EplPdokAddInstance(void)
177 return kEplSuccessful
;
180 //---------------------------------------------------------------------------
182 // Function: EplPdokDelInstance()
184 // Description: deletes an instance of EPL stack
188 // Returns: tEplKernel = error code
193 //---------------------------------------------------------------------------
195 tEplKernel
EplPdokDelInstance(void)
198 return kEplSuccessful
;
201 //---------------------------------------------------------------------------
203 // Function: EplPdokCbPdoReceived
205 // Description: This function is called by DLL if PRes or PReq frame was
206 // received. It posts the frame to the event queue.
207 // It is called in states NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
208 // The passed PDO needs not to be valid.
210 // Parameters: pFrameInfo_p = pointer to frame info structure
212 // Returns: tEplKernel = error code
217 //---------------------------------------------------------------------------
219 tEplKernel
EplPdokCbPdoReceived(tEplFrameInfo
* pFrameInfo_p
)
221 tEplKernel Ret
= kEplSuccessful
;
224 Event
.m_EventSink
= kEplEventSinkPdok
;
225 Event
.m_EventType
= kEplEventTypePdoRx
;
226 // limit copied data to size of PDO (because from some CNs the frame is larger than necessary)
227 Event
.m_uiSize
= AmiGetWordFromLe(&pFrameInfo_p
->m_pFrame
->m_Data
.m_Pres
.m_le_wSize
) + 24; // pFrameInfo_p->m_uiFrameSize;
228 Event
.m_pArg
= pFrameInfo_p
->m_pFrame
;
229 Ret
= EplEventkPost(&Event
);
234 //---------------------------------------------------------------------------
236 // Function: EplPdokCbPdoTransmitted
238 // Description: This function is called by DLL if PRes or PReq frame was
239 // sent. It posts the pointer to the frame to the event queue.
240 // It is called in NMT_CS_PRE_OPERATIONAL_2,
241 // NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
243 // Parameters: pFrameInfo_p = pointer to frame info structure
245 // Returns: tEplKernel = error code
250 //---------------------------------------------------------------------------
252 tEplKernel
EplPdokCbPdoTransmitted(tEplFrameInfo
* pFrameInfo_p
)
254 tEplKernel Ret
= kEplSuccessful
;
257 Event
.m_EventSink
= kEplEventSinkPdok
;
258 Event
.m_EventType
= kEplEventTypePdoTx
;
259 Event
.m_uiSize
= sizeof(tEplFrameInfo
);
260 Event
.m_pArg
= pFrameInfo_p
;
261 Ret
= EplEventkPost(&Event
);
266 //---------------------------------------------------------------------------
268 // Function: EplPdokCbSoa
270 // Description: This function is called by DLL if SoA frame was
271 // received resp. sent. It posts this event to the event queue.
273 // Parameters: pFrameInfo_p = pointer to frame info structure
275 // Returns: tEplKernel = error code
280 //---------------------------------------------------------------------------
282 tEplKernel
EplPdokCbSoa(tEplFrameInfo
* pFrameInfo_p
)
284 tEplKernel Ret
= kEplSuccessful
;
287 Event
.m_EventSink
= kEplEventSinkPdok
;
288 Event
.m_EventType
= kEplEventTypePdoSoa
;
291 Ret
= EplEventkPost(&Event
);
296 //---------------------------------------------------------------------------
298 // Function: EplPdokProcess
300 // Description: This function processes all received and transmitted PDOs.
301 // This function must not be interrupted by any other task
302 // except ISRs (like the ethernet driver ISR, which may call
303 // EplPdokCbFrameReceived() or EplPdokCbFrameTransmitted()).
305 // Parameters: pEvent_p = pointer to event structure
307 // Returns: tEplKernel = error code
312 //---------------------------------------------------------------------------
314 tEplKernel
EplPdokProcess(tEplEvent
* pEvent_p
)
316 tEplKernel Ret
= kEplSuccessful
;
333 tEplFrameInfo
*pFrameInfo
;
334 unsigned int uiNodeId
;
337 // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes
338 // TPDO: 0x00=PRes, MN: CnNodeId=PReq
340 switch (pEvent_p
->m_EventType
) {
341 case kEplEventTypePdoRx
: // RPDO received
342 pFrame
= (tEplFrame
*) pEvent_p
->m_pArg
;
344 // check if received RPDO is valid
346 AmiGetByteFromLe(&pFrame
->m_Data
.m_Pres
.m_le_bFlag1
);
347 if ((bFrameData
& EPL_FRAME_FLAG1_RD
) == 0) { // RPDO invalid
350 // retrieve EPL message type
351 MsgType
= AmiGetByteFromLe(&pFrame
->m_le_bMessageType
);
352 if (MsgType
== kEplMsgTypePreq
) { // RPDO is PReq frame
353 uiNodeId
= EPL_PDO_PREQ_NODE_ID
; // 0x00
354 } else { // RPDO is PRes frame
356 uiNodeId
= AmiGetByteFromLe(&pFrame
->m_le_bSrcNodeId
);
359 // search for appropriate valid RPDO in OD
360 wObdMappIndex
= EPL_PDOK_OBD_IDX_RX_MAPP_PARAM
;
361 for (wObdCommIndex
= EPL_PDOK_OBD_IDX_RX_COMM_PARAM
;
362 wObdCommIndex
< (EPL_PDOK_OBD_IDX_RX_COMM_PARAM
+ 0x00FF);
363 wObdCommIndex
++, wObdMappIndex
++) {
365 // read node ID from OD
367 EplObdReadEntry(wObdCommIndex
, 0x01, &bObdData
,
369 if ((Ret
== kEplObdIndexNotExist
)
370 || (Ret
== kEplObdSubindexNotExist
)
371 || (Ret
== kEplObdIllegalPart
)) { // PDO does not exist; last PDO reached
372 Ret
= kEplSuccessful
;
374 } else if (Ret
!= kEplSuccessful
) { // other fatal error occured
377 // entry read successfully
378 if (bObdData
!= uiNodeId
) { // node ID does not equal - wrong PDO, try next PDO in OD
382 // read number of mapped objects from OD; this indicates if the PDO is valid
384 EplObdReadEntry(wObdMappIndex
, 0x00, &bObjectCount
,
386 if ((Ret
== kEplObdIndexNotExist
)
387 || (Ret
== kEplObdSubindexNotExist
)
388 || (Ret
== kEplObdIllegalPart
)) { // PDO does not exist; last PDO reached
389 Ret
= kEplSuccessful
;
391 } else if (Ret
!= kEplSuccessful
) { // other fatal error occured
394 // entry read successfully
395 if (bObjectCount
== 0) { // PDO in OD not valid, try next PDO in OD
400 // check PDO mapping version
402 EplObdReadEntry(wObdCommIndex
, 0x02, &bObdData
,
404 if (Ret
!= kEplSuccessful
) { // other fatal error occured
407 // entry read successfully
408 // retrieve PDO version from frame
410 AmiGetByteFromLe(&pFrame
->m_Data
.m_Pres
.
412 if ((bObdData
& EPL_VERSION_MAIN
) != (bFrameData
& EPL_VERSION_MAIN
)) { // PDO versions do not match
413 // $$$ raise PDO error
414 // termiate processing of this RPDO
421 AmiGetWordFromLe(&pFrame
->m_Data
.m_Pres
.m_le_wSize
);
424 for (bMappSubindex
= 1; bMappSubindex
<= bObjectCount
;
427 // read object mapping from OD
429 EplObdReadEntry(wObdMappIndex
,
431 &qwObjectMapping
, &ObdSize
);
432 if (Ret
!= kEplSuccessful
) { // other fatal error occured
435 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
436 if (qwObjectMapping
== 0) { // invalid entry, continue with next entry
439 // decode object mapping
441 (u16
) (qwObjectMapping
&
442 0x000000000000FFFFLL
);
444 (u8
) ((qwObjectMapping
&
445 0x0000000000FF0000LL
) >> 16);
447 (u16
) ((qwObjectMapping
&
448 0x0000FFFF00000000LL
) >> 32);
450 (u16
) ((qwObjectMapping
&
451 0xFFFF000000000000LL
) >> 48);
453 // check if object exceeds PDO size
454 if (((wBitOffset
+ wBitSize
) >> 3) > wPdoSize
) { // wrong object mapping; PDO size is too low
455 // $$$ raise PDO error
456 // terminate processing of this RPDO
459 // copy object from RPDO to process/OD variable
460 ObdSize
= wBitSize
>> 3;
462 EplObdWriteEntryFromLe(wObdCommIndex
,
466 m_le_abPayload
[(wBitOffset
>> 3)], ObdSize
);
467 if (Ret
!= kEplSuccessful
) { // other fatal error occured
473 // processing finished successfully
478 case kEplEventTypePdoTx
: // TPDO transmitted
479 pFrameInfo
= (tEplFrameInfo
*) pEvent_p
->m_pArg
;
480 pFrame
= pFrameInfo
->m_pFrame
;
482 // set TPDO invalid, so that only fully processed TPDOs are sent as valid
484 AmiGetByteFromLe(&pFrame
->m_Data
.m_Pres
.m_le_bFlag1
);
485 AmiSetByteToLe(&pFrame
->m_Data
.m_Pres
.m_le_bFlag1
,
486 (bFrameData
& ~EPL_FRAME_FLAG1_RD
));
488 // retrieve EPL message type
489 MsgType
= AmiGetByteFromLe(&pFrame
->m_le_bMessageType
);
490 if (MsgType
== kEplMsgTypePres
) { // TPDO is PRes frame
491 uiNodeId
= EPL_PDO_PRES_NODE_ID
; // 0x00
492 } else { // TPDO is PReq frame
494 uiNodeId
= AmiGetByteFromLe(&pFrame
->m_le_bDstNodeId
);
497 // search for appropriate valid TPDO in OD
498 wObdMappIndex
= EPL_PDOK_OBD_IDX_TX_MAPP_PARAM
;
499 wObdCommIndex
= EPL_PDOK_OBD_IDX_TX_COMM_PARAM
;
500 for (wPdoId
= 0;; wPdoId
++, wObdCommIndex
++, wObdMappIndex
++) {
502 // read node ID from OD
504 EplObdReadEntry(wObdCommIndex
, 0x01, &bObdData
,
506 if ((Ret
== kEplObdIndexNotExist
)
507 || (Ret
== kEplObdSubindexNotExist
)
508 || (Ret
== kEplObdIllegalPart
)) { // PDO does not exist; last PDO reached
509 Ret
= kEplSuccessful
;
511 } else if (Ret
!= kEplSuccessful
) { // other fatal error occured
514 // entry read successfully
515 if (bObdData
!= uiNodeId
) { // node ID does not equal - wrong PDO, try next PDO in OD
519 // read number of mapped objects from OD; this indicates if the PDO is valid
521 EplObdReadEntry(wObdMappIndex
, 0x00, &bObjectCount
,
523 if ((Ret
== kEplObdIndexNotExist
)
524 || (Ret
== kEplObdSubindexNotExist
)
525 || (Ret
== kEplObdIllegalPart
)) { // PDO does not exist; last PDO reached
526 Ret
= kEplSuccessful
;
528 } else if (Ret
!= kEplSuccessful
) { // other fatal error occured
531 // entry read successfully
532 if (bObjectCount
== 0) { // PDO in OD not valid, try next PDO in OD
538 // get PDO mapping version from OD
540 EplObdReadEntry(wObdCommIndex
, 0x02, &bObdData
,
542 if (Ret
!= kEplSuccessful
) { // other fatal error occured
545 // entry read successfully
546 // set PDO version in frame
547 AmiSetByteToLe(&pFrame
->m_Data
.m_Pres
.m_le_bPdoVersion
,
550 // calculate PDO size
554 for (bMappSubindex
= 1; bMappSubindex
<= bObjectCount
;
557 // read object mapping from OD
559 EplObdReadEntry(wObdMappIndex
,
561 &qwObjectMapping
, &ObdSize
);
562 if (Ret
!= kEplSuccessful
) { // other fatal error occured
565 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
566 if (qwObjectMapping
== 0) { // invalid entry, continue with next entry
569 // decode object mapping
571 (u16
) (qwObjectMapping
&
572 0x000000000000FFFFLL
);
574 (u8
) ((qwObjectMapping
&
575 0x0000000000FF0000LL
) >> 16);
577 (u16
) ((qwObjectMapping
&
578 0x0000FFFF00000000LL
) >> 32);
580 (u16
) ((qwObjectMapping
&
581 0xFFFF000000000000LL
) >> 48);
583 // calculate max PDO size
584 ObdSize
= wBitSize
>> 3;
585 wVarSize
= (wBitOffset
>> 3) + (u16
) ObdSize
;
586 if ((unsigned int)(wVarSize
+ 24) > pFrameInfo
->m_uiFrameSize
) { // TPDO is too short
587 // $$$ raise PDO error, set Ret
590 if (wVarSize
> wPdoSize
) { // memorize new PDO size
593 // copy object from process/OD variable to TPDO
595 EplObdReadEntryToLe(wObdCommIndex
,
597 &pFrame
->m_Data
.m_Pres
.
598 m_le_abPayload
[(wBitOffset
>> 3)], &ObdSize
);
599 if (Ret
!= kEplSuccessful
) { // other fatal error occured
605 // set PDO size in frame
606 AmiSetWordToLe(&pFrame
->m_Data
.m_Pres
.m_le_wSize
,
609 Ret
= EplPdokCalAreTpdosValid(&fValid
);
610 if (fValid
!= FALSE
) {
613 AmiGetByteFromLe(&pFrame
->m_Data
.m_Pres
.
615 AmiSetByteToLe(&pFrame
->m_Data
.m_Pres
.
618 EPL_FRAME_FLAG1_RD
));
620 // processing finished successfully
626 case kEplEventTypePdoSoa
: // SoA received
629 Ret
= EplPdokCalSetTpdosValid(FALSE
);
635 "EplPdokProcess(): unhandled event type!\n");
643 //=========================================================================//
645 // P R I V A T E F U N C T I O N S //
647 //=========================================================================//
649 //---------------------------------------------------------------------------
665 //---------------------------------------------------------------------------
667 #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)