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 //---------------------------------------------------------------------------
123 /***************************************************************************/
126 /* C L A S S EplPdok */
129 /***************************************************************************/
134 /***************************************************************************/
136 //=========================================================================//
138 // P R I V A T E D E F I N I T I O N S //
140 //=========================================================================//
142 //---------------------------------------------------------------------------
144 //---------------------------------------------------------------------------
146 //---------------------------------------------------------------------------
148 //---------------------------------------------------------------------------
150 //---------------------------------------------------------------------------
152 //---------------------------------------------------------------------------
154 //---------------------------------------------------------------------------
155 // local function prototypes
156 //---------------------------------------------------------------------------
158 //=========================================================================//
160 // P U B L I C F U N C T I O N S //
162 //=========================================================================//
164 //---------------------------------------------------------------------------
166 // Function: EplPdokAddInstance()
168 // Description: add and initialize new instance of EPL stack
172 // Returns: tEplKernel = error code
177 //---------------------------------------------------------------------------
179 tEplKernel EplPdokAddInstance(void)
182 return kEplSuccessful;
185 //---------------------------------------------------------------------------
187 // Function: EplPdokDelInstance()
189 // Description: deletes an instance of EPL stack
193 // Returns: tEplKernel = error code
198 //---------------------------------------------------------------------------
200 tEplKernel EplPdokDelInstance(void)
203 return kEplSuccessful;
206 //---------------------------------------------------------------------------
208 // Function: EplPdokCbPdoReceived
210 // Description: This function is called by DLL if PRes or PReq frame was
211 // received. It posts the frame to the event queue.
212 // It is called in states NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
213 // The passed PDO needs not to be valid.
215 // Parameters: pFrameInfo_p = pointer to frame info structure
217 // Returns: tEplKernel = error code
222 //---------------------------------------------------------------------------
224 tEplKernel EplPdokCbPdoReceived(tEplFrameInfo * pFrameInfo_p)
226 tEplKernel Ret = kEplSuccessful;
229 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
231 // MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
234 Event.m_EventSink = kEplEventSinkPdok;
235 Event.m_EventType = kEplEventTypePdoRx;
236 // limit copied data to size of PDO (because from some CNs the frame is larger than necessary)
237 Event.m_uiSize = AmiGetWordFromLe(&pFrameInfo_p->m_pFrame->m_Data.m_Pres.m_le_wSize) + 24; // pFrameInfo_p->m_uiFrameSize;
238 Event.m_pArg = pFrameInfo_p->m_pFrame;
239 Ret = EplEventkPost(&Event);
241 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
243 // MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
249 //---------------------------------------------------------------------------
251 // Function: EplPdokCbPdoTransmitted
253 // Description: This function is called by DLL if PRes or PReq frame was
254 // sent. It posts the pointer to the frame to the event queue.
255 // It is called in NMT_CS_PRE_OPERATIONAL_2,
256 // NMT_CS_READY_TO_OPERATE and NMT_CS_OPERATIONAL.
258 // Parameters: pFrameInfo_p = pointer to frame info structure
260 // Returns: tEplKernel = error code
265 //---------------------------------------------------------------------------
267 tEplKernel EplPdokCbPdoTransmitted(tEplFrameInfo * pFrameInfo_p)
269 tEplKernel Ret = kEplSuccessful;
272 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
274 MCF_GPIO_PODR_PCIBG &= ~PDO_LED; // Level
277 Event.m_EventSink = kEplEventSinkPdok;
278 Event.m_EventType = kEplEventTypePdoTx;
279 Event.m_uiSize = sizeof(tEplFrameInfo);
280 Event.m_pArg = pFrameInfo_p;
281 Ret = EplEventkPost(&Event);
283 #if (DEV_SYSTEM == _DEV_GNU_CF548X_)
285 MCF_GPIO_PODR_PCIBG |= PDO_LED; // Level
291 //---------------------------------------------------------------------------
293 // Function: EplPdokCbSoa
295 // Description: This function is called by DLL if SoA frame was
296 // received resp. sent. It posts this event to the event queue.
298 // Parameters: pFrameInfo_p = pointer to frame info structure
300 // Returns: tEplKernel = error code
305 //---------------------------------------------------------------------------
307 tEplKernel EplPdokCbSoa(tEplFrameInfo * pFrameInfo_p)
309 tEplKernel Ret = kEplSuccessful;
312 Event.m_EventSink = kEplEventSinkPdok;
313 Event.m_EventType = kEplEventTypePdoSoa;
316 Ret = EplEventkPost(&Event);
321 //---------------------------------------------------------------------------
323 // Function: EplPdokProcess
325 // Description: This function processes all received and transmitted PDOs.
326 // This function must not be interrupted by any other task
327 // except ISRs (like the ethernet driver ISR, which may call
328 // EplPdokCbFrameReceived() or EplPdokCbFrameTransmitted()).
330 // Parameters: pEvent_p = pointer to event structure
332 // Returns: tEplKernel = error code
337 //---------------------------------------------------------------------------
339 tEplKernel EplPdokProcess(tEplEvent * pEvent_p)
341 tEplKernel Ret = kEplSuccessful;
346 QWORD qwObjectMapping;
358 tEplFrameInfo *pFrameInfo;
359 unsigned int uiNodeId;
362 // 0xFF=invalid, RPDO: 0x00=PReq, localNodeId=PRes, remoteNodeId=PRes
363 // TPDO: 0x00=PRes, MN: CnNodeId=PReq
365 switch (pEvent_p->m_EventType) {
366 case kEplEventTypePdoRx: // RPDO received
367 pFrame = (tEplFrame *) pEvent_p->m_pArg;
369 // check if received RPDO is valid
371 AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
372 if ((bFrameData & EPL_FRAME_FLAG1_RD) == 0) { // RPDO invalid
375 // retrieve EPL message type
376 MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
377 if (MsgType == kEplMsgTypePreq) { // RPDO is PReq frame
378 uiNodeId = EPL_PDO_PREQ_NODE_ID; // 0x00
379 } else { // RPDO is PRes frame
381 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bSrcNodeId);
384 // search for appropriate valid RPDO in OD
385 wObdMappIndex = EPL_PDOK_OBD_IDX_RX_MAPP_PARAM;
386 for (wObdCommIndex = EPL_PDOK_OBD_IDX_RX_COMM_PARAM;
387 wObdCommIndex < (EPL_PDOK_OBD_IDX_RX_COMM_PARAM + 0x00FF);
388 wObdCommIndex++, wObdMappIndex++) {
390 // read node ID from OD
392 EplObdReadEntry(wObdCommIndex, 0x01, &bObdData,
394 if ((Ret == kEplObdIndexNotExist)
395 || (Ret == kEplObdSubindexNotExist)
396 || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
397 Ret = kEplSuccessful;
399 } else if (Ret != kEplSuccessful) { // other fatal error occured
402 // entry read successfully
403 if (bObdData != uiNodeId) { // node ID does not equal - wrong PDO, try next PDO in OD
407 // read number of mapped objects from OD; this indicates if the PDO is valid
409 EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount,
411 if ((Ret == kEplObdIndexNotExist)
412 || (Ret == kEplObdSubindexNotExist)
413 || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
414 Ret = kEplSuccessful;
416 } else if (Ret != kEplSuccessful) { // other fatal error occured
419 // entry read successfully
420 if (bObjectCount == 0) { // PDO in OD not valid, try next PDO in OD
425 // check PDO mapping version
427 EplObdReadEntry(wObdCommIndex, 0x02, &bObdData,
429 if (Ret != kEplSuccessful) { // other fatal error occured
432 // entry read successfully
433 // retrieve PDO version from frame
435 AmiGetByteFromLe(&pFrame->m_Data.m_Pres.
437 if ((bObdData & EPL_VERSION_MAIN) != (bFrameData & EPL_VERSION_MAIN)) { // PDO versions do not match
438 // $$$ raise PDO error
439 // termiate processing of this RPDO
446 AmiGetWordFromLe(&pFrame->m_Data.m_Pres.m_le_wSize);
449 for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
451 ObdSize = 8; // QWORD
452 // read object mapping from OD
454 EplObdReadEntry(wObdMappIndex,
456 &qwObjectMapping, &ObdSize);
457 if (Ret != kEplSuccessful) { // other fatal error occured
460 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
461 if (qwObjectMapping == 0) { // invalid entry, continue with next entry
464 // decode object mapping
466 (WORD) (qwObjectMapping &
467 0x000000000000FFFFLL);
469 (BYTE) ((qwObjectMapping &
470 0x0000000000FF0000LL) >> 16);
472 (WORD) ((qwObjectMapping &
473 0x0000FFFF00000000LL) >> 32);
475 (WORD) ((qwObjectMapping &
476 0xFFFF000000000000LL) >> 48);
478 // check if object exceeds PDO size
479 if (((wBitOffset + wBitSize) >> 3) > wPdoSize) { // wrong object mapping; PDO size is too low
480 // $$$ raise PDO error
481 // terminate processing of this RPDO
484 // copy object from RPDO to process/OD variable
485 ObdSize = wBitSize >> 3;
487 EplObdWriteEntryFromLe(wObdCommIndex,
491 m_le_abPayload[(wBitOffset >> 3)], ObdSize);
492 if (Ret != kEplSuccessful) { // other fatal error occured
498 // processing finished successfully
503 case kEplEventTypePdoTx: // TPDO transmitted
504 pFrameInfo = (tEplFrameInfo *) pEvent_p->m_pArg;
505 pFrame = pFrameInfo->m_pFrame;
507 // set TPDO invalid, so that only fully processed TPDOs are sent as valid
509 AmiGetByteFromLe(&pFrame->m_Data.m_Pres.m_le_bFlag1);
510 AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bFlag1,
511 (bFrameData & ~EPL_FRAME_FLAG1_RD));
513 // retrieve EPL message type
514 MsgType = AmiGetByteFromLe(&pFrame->m_le_bMessageType);
515 if (MsgType == kEplMsgTypePres) { // TPDO is PRes frame
516 uiNodeId = EPL_PDO_PRES_NODE_ID; // 0x00
517 } else { // TPDO is PReq frame
519 uiNodeId = AmiGetByteFromLe(&pFrame->m_le_bDstNodeId);
522 // search for appropriate valid TPDO in OD
523 wObdMappIndex = EPL_PDOK_OBD_IDX_TX_MAPP_PARAM;
524 wObdCommIndex = EPL_PDOK_OBD_IDX_TX_COMM_PARAM;
525 for (wPdoId = 0;; wPdoId++, wObdCommIndex++, wObdMappIndex++) {
527 // read node ID from OD
529 EplObdReadEntry(wObdCommIndex, 0x01, &bObdData,
531 if ((Ret == kEplObdIndexNotExist)
532 || (Ret == kEplObdSubindexNotExist)
533 || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
534 Ret = kEplSuccessful;
536 } else if (Ret != kEplSuccessful) { // other fatal error occured
539 // entry read successfully
540 if (bObdData != uiNodeId) { // node ID does not equal - wrong PDO, try next PDO in OD
544 // read number of mapped objects from OD; this indicates if the PDO is valid
546 EplObdReadEntry(wObdMappIndex, 0x00, &bObjectCount,
548 if ((Ret == kEplObdIndexNotExist)
549 || (Ret == kEplObdSubindexNotExist)
550 || (Ret == kEplObdIllegalPart)) { // PDO does not exist; last PDO reached
551 Ret = kEplSuccessful;
553 } else if (Ret != kEplSuccessful) { // other fatal error occured
556 // entry read successfully
557 if (bObjectCount == 0) { // PDO in OD not valid, try next PDO in OD
563 // get PDO mapping version from OD
565 EplObdReadEntry(wObdCommIndex, 0x02, &bObdData,
567 if (Ret != kEplSuccessful) { // other fatal error occured
570 // entry read successfully
571 // set PDO version in frame
572 AmiSetByteToLe(&pFrame->m_Data.m_Pres.m_le_bPdoVersion,
575 // calculate PDO size
579 for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
581 ObdSize = 8; // QWORD
582 // read object mapping from OD
584 EplObdReadEntry(wObdMappIndex,
586 &qwObjectMapping, &ObdSize);
587 if (Ret != kEplSuccessful) { // other fatal error occured
590 // check if object mapping entry is valid, i.e. unequal zero, because "empty" entries are allowed
591 if (qwObjectMapping == 0) { // invalid entry, continue with next entry
594 // decode object mapping
596 (WORD) (qwObjectMapping &
597 0x000000000000FFFFLL);
599 (BYTE) ((qwObjectMapping &
600 0x0000000000FF0000LL) >> 16);
602 (WORD) ((qwObjectMapping &
603 0x0000FFFF00000000LL) >> 32);
605 (WORD) ((qwObjectMapping &
606 0xFFFF000000000000LL) >> 48);
608 // calculate max PDO size
609 ObdSize = wBitSize >> 3;
610 wVarSize = (wBitOffset >> 3) + (WORD) ObdSize;
611 if ((unsigned int)(wVarSize + 24) > pFrameInfo->m_uiFrameSize) { // TPDO is too short
612 // $$$ raise PDO error, set Ret
615 if (wVarSize > wPdoSize) { // memorize new PDO size
618 // copy object from process/OD variable to TPDO
620 EplObdReadEntryToLe(wObdCommIndex,
622 &pFrame->m_Data.m_Pres.
623 m_le_abPayload[(wBitOffset >> 3)], &ObdSize);
624 if (Ret != kEplSuccessful) { // other fatal error occured
630 // set PDO size in frame
631 AmiSetWordToLe(&pFrame->m_Data.m_Pres.m_le_wSize,
634 Ret = EplPdokCalAreTpdosValid(&fValid);
635 if (fValid != FALSE) {
638 AmiGetByteFromLe(&pFrame->m_Data.m_Pres.
640 AmiSetByteToLe(&pFrame->m_Data.m_Pres.
643 EPL_FRAME_FLAG1_RD));
645 // processing finished successfully
651 case kEplEventTypePdoSoa: // SoA received
654 Ret = EplPdokCalSetTpdosValid(FALSE);
660 "EplPdokProcess(): unhandled event type!\n");
668 //=========================================================================//
670 // P R I V A T E F U N C T I O N S //
672 //=========================================================================//
674 //---------------------------------------------------------------------------
690 //---------------------------------------------------------------------------
692 #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOK)) != 0)