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 (DEV_SYSTEM == _DEV_GNU_CF548X_)
81 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)
83 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_DLLK)) == 0)
85 #error 'ERROR: Missing DLLk-Modul!'
89 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDK)) == 0)
91 #error 'ERROR: Missing OBDk-Modul!'
94 /***************************************************************************/
97 /* G L O B A L D E F I N I T I O N S */
100 /***************************************************************************/
102 //---------------------------------------------------------------------------
104 //---------------------------------------------------------------------------
106 #define EPL_PDOK_OBD_IDX_RX_COMM_PARAM 0x1400
107 #define EPL_PDOK_OBD_IDX_RX_MAPP_PARAM 0x1600
108 #define EPL_PDOK_OBD_IDX_TX_COMM_PARAM 0x1800
109 #define EPL_PDOK_OBD_IDX_TX_MAPP_PARAM 0x1A00
111 //---------------------------------------------------------------------------
113 //---------------------------------------------------------------------------
115 //---------------------------------------------------------------------------
116 // modul globale vars
117 //---------------------------------------------------------------------------
119 //---------------------------------------------------------------------------
120 // local function prototypes
121 //---------------------------------------------------------------------------
124 /***************************************************************************/
127 /* C L A S S EplPdok */
130 /***************************************************************************/
135 /***************************************************************************/
138 //=========================================================================//
140 // P R I V A T E D E F I N I T I O N S //
142 //=========================================================================//
144 //---------------------------------------------------------------------------
146 //---------------------------------------------------------------------------
148 //---------------------------------------------------------------------------
150 //---------------------------------------------------------------------------
152 //---------------------------------------------------------------------------
154 //---------------------------------------------------------------------------
157 //---------------------------------------------------------------------------
158 // local function prototypes
159 //---------------------------------------------------------------------------
162 //=========================================================================//
164 // P U B L I C F U N C T I O N S //
166 //=========================================================================//
168 //---------------------------------------------------------------------------
170 // Function: EplPdokAddInstance()
172 // Description: add and initialize new instance of EPL stack
176 // Returns: tEplKernel = error code
181 //---------------------------------------------------------------------------
183 tEplKernel EplPdokAddInstance(void)
186 return kEplSuccessful;
189 //---------------------------------------------------------------------------
191 // Function: EplPdokDelInstance()
193 // Description: deletes an instance of EPL stack
197 // Returns: tEplKernel = error code
202 //---------------------------------------------------------------------------
204 tEplKernel EplPdokDelInstance(void)
207 return kEplSuccessful;
211 //---------------------------------------------------------------------------
213 // Function: EplPdokCbPdoReceived
215 // Description: This function is called by DLL if PRes or PReq frame was
216 // received. It posts the frame to the event queue.
217 // It is called in states NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
218 // The passed PDO needs not to be valid.
220 // Parameters: pFrameInfo_p = pointer to frame info structure
222 // Returns: tEplKernel = error code
227 //---------------------------------------------------------------------------
229 tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p)
231 tEplKernel Ret = kEplSuccessful;
234 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
236 // MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
239 Event.m_EventSink = kEplEventSinkPdok;
240 Event.m_EventType = kEplEventTypePdoRx;
241 // limit copied data to size of PDO (because from some CNs the frame is larger than necessary)
242 Event.m_uiSize = AmiGetWordFromLe(&pFrameInfo_p->m_pFrame->m_Data.m_Pres.m_le_wSize) + 24; // pFrameInfo_p->m_uiFrameSize;
243 Event.m_pArg = pFrameInfo_p->m_pFrame;
244 Ret = EplEventkPost(&Event);
246 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
248 // MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
254 //---------------------------------------------------------------------------
256 // Function: EplPdokCbPdoTransmitted
258 // Description: This function is called by DLL if PRes or PReq frame was
259 // sent. It posts the pointer to the frame to the event queue.
260 // It is called in NMT_CS_PRE_OPERATIONAL_2,
261 // NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
263 // Parameters: pFrameInfo_p = pointer to frame info structure
265 // Returns: tEplKernel = error code
270 //---------------------------------------------------------------------------
272 tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p)
274 tEplKernel Ret = kEplSuccessful;
277 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
279 MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
282 Event.m_EventSink = kEplEventSinkPdok;
283 Event.m_EventType = kEplEventTypePdoTx;
284 Event.m_uiSize = sizeof (tEplFrameInfo);
285 Event.m_pArg = pFrameInfo_p;
286 Ret = EplEventkPost(&Event);
288 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
290 MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
296 //---------------------------------------------------------------------------
298 // Function: EplPdokCbSoa
300 // Description: This function is called by DLL if SoA frame was
301 // received resp. sent. It posts this event to the event queue.
303 // Parameters: pFrameInfo_p = pointer to frame info structure
305 // Returns: tEplKernel = error code
310 //---------------------------------------------------------------------------
312 tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p)
314 tEplKernel Ret = kEplSuccessful;
317 Event.m_EventSink = kEplEventSinkPdok;
318 Event.m_EventType = kEplEventTypePdoSoa;
321 Ret = EplEventkPost(&Event);
326 //---------------------------------------------------------------------------
328 // Function: EplPdokProcess
330 // Description: This function processes all received and transmitted PDOs.
331 // This function must not be interrupted by any other task
332 // except ISRs (like the ethernet driver ISR, which may call
333 // EplPdokCbFrameReceived() or EplPdokCbFrameTransmitted()).
335 // Parameters: pEvent_p = pointer to event structure
337 // Returns: tEplKernel = error code
342 //---------------------------------------------------------------------------
344 tEplKernel EplPdokProcess(tEplEvent * pEvent_p)
346 tEplKernel Ret = kEplSuccessful;
351 QWORD qwObjectMapping;
363 tEplFrameInfo *pFrameInfo;
364 unsigned int uiNodeId;
367 // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes
368 // TPDO: 0x00=PRes, MN: CnNodeId=PReq
370 switch (pEvent_p->m_EventType)
372 case kEplEventTypePdoRx: // RPDO received
373 pFrame = (tEplFrame *) pEvent_p->m_pArg;
375 // check if received RPDO is valid
376 bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
377 if ((bFrameData & EPL_FRAME_FLAG1_RD) == 0)
382 // retrieve EPL message type
383 MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
384 if (MsgType == kEplMsgTypePreq)
385 { // RPDO is PReq frame
386 uiNodeId = EPL_PDO_PREQ_NODE_ID; // 0x00
389 { // RPDO is PRes frame
391 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
394 // search for appropriate valid RPDO in OD
395 wObdMappIndex = EPL_PDOK_OBD_IDX_RX_MAPP_PARAM;
396 for (wObdCommIndex = EPL_PDOK_OBD_IDX_RX_COMM_PARAM;
397 wObdCommIndex < (EPL_PDOK_OBD_IDX_RX_COMM_PARAM + 0x00FF);
398 wObdCommIndex++, wObdMappIndex++)
401 // read node ID from OD
402 Ret = EplObdReadEntry(wObdCommIndex, 0x01, &bObdData, &ObdSize);
403 if ((Ret == kEplObdIndexNotExist)
404 || (Ret == kEplObdSubindexNotExist)
405 || (Ret == kEplObdIllegalPart))
406 { // PDO does not exist; last PDO reached
407 Ret = kEplSuccessful;
410 else if (Ret != kEplSuccessful)
411 { // other fatal error occured
414 // entry read successfully
415 if (bObdData != uiNodeId)
416 { // node ID does not equal - wrong PDO, try next PDO in OD
420 // read number of mapped objects from OD; this indicates if the PDO is valid
421 Ret = EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount, &ObdSize);
422 if ((Ret == kEplObdIndexNotExist)
423 || (Ret == kEplObdSubindexNotExist)
424 || (Ret == kEplObdIllegalPart))
425 { // PDO does not exist; last PDO reached
426 Ret = kEplSuccessful;
429 else if (Ret != kEplSuccessful)
430 { // other fatal error occured
433 // entry read successfully
434 if (bObjectCount == 0)
435 { // PDO in OD not valid, try next PDO in OD
440 // check PDO mapping version
441 Ret = EplObdReadEntry(wObdCommIndex, 0x02, &bObdData, &ObdSize);
442 if (Ret != kEplSuccessful)
443 { // other fatal error occured
446 // entry read successfully
447 // retrieve PDO version from frame
448 bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion);
449 if ((bObdData & EPL_VERSION_MAIN) != (bFrameData & EPL_VERSION_MAIN))
450 { // PDO versions do not match
451 // $$$ raise PDO error
452 // termiate processing of this RPDO
459 wPdoSize = AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize);
462 for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++)
464 ObdSize = 8; // QWORD
465 // read object mapping from OD
466 Ret = EplObdReadEntry(wObdMappIndex, bMappSubindex, &qwObjectMapping, &ObdSize);
467 if (Ret != kEplSuccessful)
468 { // other fatal error occured
472 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
473 if (qwObjectMapping == 0)
474 { // invalid entry, continue with next entry
478 // decode object mapping
479 wObdCommIndex = (WORD) (qwObjectMapping & 0x000000000000FFFFLL);
480 bObdSubindex = (BYTE) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16);
481 wBitOffset = (WORD) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32);
482 wBitSize = (WORD) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48);
484 // check if object exceeds PDO size
485 if (((wBitOffset + wBitSize) >> 3) > wPdoSize)
486 { // wrong object mapping; PDO size is too low
487 // $$$ raise PDO error
488 // terminate processing of this RPDO
492 // copy object from RPDO to process/OD variable
493 ObdSize = wBitSize >> 3;
494 Ret = EplObdWriteEntryFromLe(wObdCommIndex, bObdSubindex, &pFrame->m_Data.m_Pres.m_le_abPayload[(wBitOffset >> 3)], ObdSize);
495 if (Ret != kEplSuccessful)
496 { // other fatal error occured
502 // processing finished successfully
507 case kEplEventTypePdoTx: // TPDO transmitted
508 pFrameInfo = (tEplFrameInfo *) pEvent_p->m_pArg;
509 pFrame = pFrameInfo->m_pFrame;
511 // set TPDO invalid, so that only fully processed TPDOs are sent as valid
512 bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
513 AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1, (bFrameData & ~EPL_FRAME_FLAG1_RD));
515 // retrieve EPL message type
516 MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
517 if (MsgType == kEplMsgTypePres)
518 { // TPDO is PRes frame
519 uiNodeId = EPL_PDO_PRES_NODE_ID; // 0x00
522 { // TPDO is PReq frame
524 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
527 // search for appropriate valid TPDO in OD
528 wObdMappIndex = EPL_PDOK_OBD_IDX_TX_MAPP_PARAM;
529 wObdCommIndex = EPL_PDOK_OBD_IDX_TX_COMM_PARAM;
530 for (wPdoId = 0; ; wPdoId++, wObdCommIndex++, wObdMappIndex++)
533 // read node ID from OD
534 Ret = EplObdReadEntry(wObdCommIndex, 0x01, &bObdData, &ObdSize);
535 if ((Ret == kEplObdIndexNotExist)
536 || (Ret == kEplObdSubindexNotExist)
537 || (Ret == kEplObdIllegalPart))
538 { // PDO does not exist; last PDO reached
539 Ret = kEplSuccessful;
542 else if (Ret != kEplSuccessful)
543 { // other fatal error occured
546 // entry read successfully
547 if (bObdData != uiNodeId)
548 { // node ID does not equal - wrong PDO, try next PDO in OD
552 // read number of mapped objects from OD; this indicates if the PDO is valid
553 Ret = EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount, &ObdSize);
554 if ((Ret == kEplObdIndexNotExist)
555 || (Ret == kEplObdSubindexNotExist)
556 || (Ret == kEplObdIllegalPart))
557 { // PDO does not exist; last PDO reached
558 Ret = kEplSuccessful;
561 else if (Ret != kEplSuccessful)
562 { // other fatal error occured
565 // entry read successfully
566 if (bObjectCount == 0)
567 { // PDO in OD not valid, try next PDO in OD
574 // get PDO mapping version from OD
575 Ret = EplObdReadEntry(wObdCommIndex, 0x02, &bObdData, &ObdSize);
576 if (Ret != kEplSuccessful)
577 { // other fatal error occured
580 // entry read successfully
581 // set PDO version in frame
582 AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion, bObdData);
584 // calculate PDO size
588 for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++)
590 ObdSize = 8; // QWORD
591 // read object mapping from OD
592 Ret = EplObdReadEntry(wObdMappIndex, bMappSubindex, &qwObjectMapping, &ObdSize);
593 if (Ret != kEplSuccessful)
594 { // other fatal error occured
598 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
599 if (qwObjectMapping == 0)
600 { // invalid entry, continue with next entry
604 // decode object mapping
605 wObdCommIndex = (WORD) (qwObjectMapping & 0x000000000000FFFFLL);
606 bObdSubindex = (BYTE) ((qwObjectMapping & 0x0000000000FF0000LL) >> 16);
607 wBitOffset = (WORD) ((qwObjectMapping & 0x0000FFFF00000000LL) >> 32);
608 wBitSize = (WORD) ((qwObjectMapping & 0xFFFF000000000000LL) >> 48);
610 // calculate max PDO size
611 ObdSize = wBitSize >> 3;
612 wVarSize = (wBitOffset >> 3) + (WORD) ObdSize;
613 if ((unsigned int)(wVarSize + 24) > pFrameInfo->m_uiFrameSize)
614 { // TPDO is too short
615 // $$$ raise PDO error, set Ret
618 if (wVarSize > wPdoSize)
619 { // memorize new PDO size
623 // copy object from process/OD variable to TPDO
624 Ret = EplObdReadEntryToLe(wObdCommIndex, bObdSubindex, &pFrame->m_Data.m_Pres.m_le_abPayload[(wBitOffset >> 3)], &ObdSize);
625 if (Ret != kEplSuccessful)
626 { // other fatal error occured
632 // set PDO size in frame
633 AmiSetWordToLe(&pFrame->m_Data.m_Pres.m_le_wSize, wPdoSize);
635 Ret = EplPdokCalAreTpdosValid(&fValid);
639 bFrameData = AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
640 AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1, (bFrameData | EPL_FRAME_FLAG1_RD));
643 // processing finished successfully
649 case kEplEventTypePdoSoa: // SoA received
652 Ret = EplPdokCalSetTpdosValid(FALSE);
657 ASSERTMSG(FALSE, "EplPdokProcess(): unhandled event type!\n");
665 //=========================================================================//
667 // P R I V A T E F U N C T I O N S //
669 //=========================================================================//
671 //---------------------------------------------------------------------------
687 //---------------------------------------------------------------------------
689 #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)