1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: source file for user PDO module
9 Currently, this module just implements a OD callback function
10 to check if the PDO configuration is valid.
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
25 3. Neither the name of SYSTEC electronic GmbH nor the names of its
26 contributors may be used to endorse or promote products derived
27 from this software without prior written permission. For written
28 permission, please contact info@systec-electronic.com.
30 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
33 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
34 COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
35 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
36 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 POSSIBILITY OF SUCH DAMAGE.
45 If a provision of this License is or becomes illegal, invalid or
46 unenforceable in any jurisdiction, that shall not affect:
47 1. the validity or enforceability in that jurisdiction of any other
48 provision of this License; or
49 2. the validity or enforceability in other jurisdictions of that or
50 any other provision of this License.
52 -------------------------------------------------------------------------
54 $RCSfile: EplPdou.c,v $
58 $Revision: 1.5 $ $Date: 2008/10/17 15:32:32 $
65 -------------------------------------------------------------------------
69 2006/05/22 d.k.: start of the implementation, version 1.00
71 ****************************************************************************/
74 //#include "user/EplPdouCal.h"
75 #include "user/EplObdu.h"
76 #include "user/EplPdou.h"
79 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)
81 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_OBDU)) == 0) && (EPL_OBD_USE_KERNEL == FALSE)
82 #error "EPL PDOu module needs EPL module OBDU or OBDK!"
86 /***************************************************************************/
89 /* G L O B A L D E F I N I T I O N S */
92 /***************************************************************************/
94 //---------------------------------------------------------------------------
96 //---------------------------------------------------------------------------
98 #define EPL_PDOU_OBD_IDX_RX_COMM_PARAM 0x1400
99 #define EPL_PDOU_OBD_IDX_RX_MAPP_PARAM 0x1600
100 #define EPL_PDOU_OBD_IDX_TX_COMM_PARAM 0x1800
101 #define EPL_PDOU_OBD_IDX_TX_MAPP_PARAM 0x1A00
102 #define EPL_PDOU_OBD_IDX_MAPP_PARAM 0x0200
103 #define EPL_PDOU_OBD_IDX_MASK 0xFF00
104 #define EPL_PDOU_PDO_ID_MASK 0x00FF
107 //---------------------------------------------------------------------------
109 //---------------------------------------------------------------------------
111 //---------------------------------------------------------------------------
112 // modul globale vars
113 //---------------------------------------------------------------------------
115 //---------------------------------------------------------------------------
116 // local function prototypes
117 //---------------------------------------------------------------------------
120 /***************************************************************************/
123 /* C L A S S EplPdou */
126 /***************************************************************************/
131 /***************************************************************************/
134 //=========================================================================//
136 // P R I V A T E D E F I N I T I O N S //
138 //=========================================================================//
140 //---------------------------------------------------------------------------
142 //---------------------------------------------------------------------------
144 //---------------------------------------------------------------------------
146 //---------------------------------------------------------------------------
148 //---------------------------------------------------------------------------
150 //---------------------------------------------------------------------------
153 //---------------------------------------------------------------------------
154 // local function prototypes
155 //---------------------------------------------------------------------------
157 static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM* pParam_p, unsigned int uiIndex_p);
159 static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
160 unsigned int* puiIndex_p,
161 unsigned int* puiSubIndex_p,
162 unsigned int* puiBitOffset_p,
163 unsigned int* puiBitSize_p);
165 static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
166 tEplObdAccess AccessType_p,
167 DWORD* pdwAbortCode_p,
168 unsigned int* puiPdoSize_p);
172 //=========================================================================//
174 // P U B L I C F U N C T I O N S //
176 //=========================================================================//
178 //---------------------------------------------------------------------------
180 // Function: EplPdouAddInstance()
182 // Description: add and initialize new instance of EPL stack
186 // Returns: tEplKernel = error code
191 //---------------------------------------------------------------------------
193 tEplKernel EplPdouAddInstance(void)
196 return kEplSuccessful;
200 //---------------------------------------------------------------------------
202 // Function: EplPdouDelInstance()
204 // Description: deletes an instance of EPL stack
208 // Returns: tEplKernel = error code
213 //---------------------------------------------------------------------------
215 tEplKernel EplPdouDelInstance(void)
218 return kEplSuccessful;
222 //---------------------------------------------------------------------------
224 // Function: EplPdouCbObdAccess
226 // Description: callback function for OD accesses
228 // Parameters: pParam_p = OBD parameter
230 // Returns: tEplKernel = error code
235 //---------------------------------------------------------------------------
237 tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM* pParam_p)
239 tEplKernel Ret = kEplSuccessful;
240 unsigned int uiPdoId;
241 unsigned int uiIndexType;
244 QWORD qwObjectMapping;
245 tEplObdAccess AccessType;
247 unsigned int uiCurPdoSize;
249 unsigned int uiSubIndex;
252 uiPdoId = pParam_p->m_uiIndex & EPL_PDOU_PDO_ID_MASK;
254 // fetch object index type
255 uiIndexType = pParam_p->m_uiIndex & EPL_PDOU_OBD_IDX_MASK;
257 if (pParam_p->m_ObdEvent != kEplObdEvPreWrite)
258 { // read accesses, post write events etc. are OK
259 pParam_p->m_dwAbortCode = 0;
266 case EPL_PDOU_OBD_IDX_RX_COMM_PARAM:
267 // RPDO communication parameter accessed
268 case EPL_PDOU_OBD_IDX_TX_COMM_PARAM:
269 { // TPDO communication parameter accessed
270 Ret = EplPdouCheckPdoValidity(pParam_p,
271 (EPL_PDOU_OBD_IDX_MAPP_PARAM | pParam_p->m_uiIndex));
272 if (Ret != kEplSuccessful)
273 { // PDO is valid or does not exist
280 case EPL_PDOU_OBD_IDX_RX_MAPP_PARAM:
281 { // RPDO mapping parameter accessed
283 AccessType = kEplObdAccWrite;
287 case EPL_PDOU_OBD_IDX_TX_MAPP_PARAM:
288 { // TPDO mapping parameter accessed
290 AccessType = kEplObdAccRead;
295 { // this callback function is only for
296 // PDO mapping and communication parameters
297 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
302 // RPDO and TPDO mapping parameter accessed
304 if (pParam_p->m_uiSubIndex == 0)
305 { // object mapping count accessed
307 // PDO is enabled or disabled
308 bObjectCount = *((BYTE*) pParam_p->m_pArg);
310 if (bObjectCount == 0)
311 { // PDO shall be disabled
313 // that is always possible
317 // PDO shall be enabled
318 // it should have been disabled for this operation
319 Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
320 if (Ret != kEplSuccessful)
321 { // PDO is valid or does not exist
325 if (AccessType == kEplObdAccWrite)
327 uiSubIndex = 0x04; // PReqActPayloadLimit_U16
331 uiSubIndex = 0x05; // PResActPayloadLimit_U16
334 // fetch maximum PDO size from Object 1F98h: NMT_CycleTiming_REC
335 ObdSize = sizeof (wMaxPdoSize);
336 Ret = EplObduReadEntry(0x1F98, uiSubIndex, &wMaxPdoSize, &ObdSize);
337 if (Ret != kEplSuccessful)
338 { // other fatal error occured
339 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
343 // check all objectmappings
344 for (bMappSubindex = 1; bMappSubindex <= bObjectCount; bMappSubindex++)
346 // read object mapping from OD
347 ObdSize = sizeof (qwObjectMapping); // QWORD
348 Ret = EplObduReadEntry(pParam_p->m_uiIndex,
349 bMappSubindex, &qwObjectMapping, &ObdSize);
350 if (Ret != kEplSuccessful)
351 { // other fatal error occured
352 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
356 // check object mapping
357 Ret = EplPdouCheckObjectMapping(qwObjectMapping,
359 &pParam_p->m_dwAbortCode,
361 if (Ret != kEplSuccessful)
362 { // illegal object mapping
366 if (uiCurPdoSize > wMaxPdoSize)
367 { // mapping exceeds object size
368 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
369 Ret = kEplPdoVarNotFound;
378 Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
379 if (Ret != kEplSuccessful)
380 { // PDO is valid or does not exist
384 // check existence of object and validity of object length
386 qwObjectMapping = *((QWORD*) pParam_p->m_pArg);
388 Ret = EplPdouCheckObjectMapping(qwObjectMapping,
390 &pParam_p->m_dwAbortCode,
401 //=========================================================================//
403 // P R I V A T E F U N C T I O N S //
405 //=========================================================================//
407 //---------------------------------------------------------------------------
409 // Function: EplPdouCheckPdoValidity
411 // Description: check if PDO is valid
413 // Parameters: pParam_p = OBD parameter
415 // Returns: tEplKernel = error code
420 //---------------------------------------------------------------------------
422 static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM* pParam_p, unsigned int uiIndex_p)
424 tEplKernel Ret = kEplSuccessful;
429 // read number of mapped objects from OD; this indicates if the PDO is valid
430 Ret = EplObduReadEntry(uiIndex_p, 0x00, &bObjectCount, &ObdSize);
431 if (Ret != kEplSuccessful)
432 { // other fatal error occured
433 pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY;
436 // entry read successfully
437 if (bObjectCount != 0)
438 { // PDO in OD is still valid
439 pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY;
440 Ret = kEplPdoNotExist;
449 //---------------------------------------------------------------------------
451 // Function: EplPdouDecodeObjectMapping
453 // Description: decodes the given object mapping entry into index, subindex,
454 // bit offset and bit size.
456 // Parameters: qwObjectMapping_p = object mapping entry
457 // puiIndex_p = [OUT] pointer to object index
458 // puiSubIndex_p = [OUT] pointer to subindex
459 // puiBitOffset_p = [OUT] pointer to bit offset
460 // puiBitSize_p = [OUT] pointer to bit size
466 //---------------------------------------------------------------------------
468 static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
469 unsigned int* puiIndex_p,
470 unsigned int* puiSubIndex_p,
471 unsigned int* puiBitOffset_p,
472 unsigned int* puiBitSize_p)
474 *puiIndex_p = (unsigned int)
475 (qwObjectMapping_p & 0x000000000000FFFFLL);
477 *puiSubIndex_p = (unsigned int)
478 ((qwObjectMapping_p & 0x0000000000FF0000LL) >> 16);
480 *puiBitOffset_p = (unsigned int)
481 ((qwObjectMapping_p & 0x0000FFFF00000000LL) >> 32);
483 *puiBitSize_p = (unsigned int)
484 ((qwObjectMapping_p & 0xFFFF000000000000LL) >> 48);
489 //---------------------------------------------------------------------------
491 // Function: EplPdouCheckObjectMapping
493 // Description: checks the given object mapping entry.
495 // Parameters: qwObjectMapping_p = object mapping entry
496 // AccessType_p = access type to mapped object:
497 // write = RPDO and read = TPDO
498 // puiPdoSize_p = [OUT] pointer to covered PDO size
499 // (offset + size) in byte;
500 // 0 if mapping failed
501 // pdwAbortCode_p = [OUT] pointer to SDO abort code;
502 // 0 if mapping is possible
504 // Returns: tEplKernel = error code
508 //---------------------------------------------------------------------------
510 static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
511 tEplObdAccess AccessType_p,
512 DWORD* pdwAbortCode_p,
513 unsigned int* puiPdoSize_p)
515 tEplKernel Ret = kEplSuccessful;
517 unsigned int uiIndex;
518 unsigned int uiSubIndex;
519 unsigned int uiBitOffset;
520 unsigned int uiBitSize;
521 tEplObdAccess AccessType;
524 if (qwObjectMapping_p == 0)
525 { // discard zero value
530 // decode object mapping
531 EplPdouDecodeObjectMapping(qwObjectMapping_p,
537 if ((uiBitOffset & 0x7) != 0x0)
538 { // bit mapping is not supported
539 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
540 Ret = kEplPdoGranularityMismatch;
544 if ((uiBitSize & 0x7) != 0x0)
545 { // bit mapping is not supported
546 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
547 Ret = kEplPdoGranularityMismatch;
552 Ret = EplObduGetAccessType(uiIndex, uiSubIndex, &AccessType);
553 if (Ret != kEplSuccessful)
554 { // entry doesn't exist
555 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
559 if ((AccessType & kEplObdAccPdo) == 0)
560 { // object is not mappable
561 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
562 Ret = kEplPdoVarNotFound;
566 if ((AccessType & AccessType_p) == 0)
567 { // object is not writeable (RPDO) or readable (TPDO) respectively
568 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
569 Ret = kEplPdoVarNotFound;
573 ObdSize = EplObduGetDataSize(uiIndex, uiSubIndex);
574 if (ObdSize < (uiBitSize >> 3))
575 { // object does not exist or has smaller size
576 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
577 Ret = kEplPdoVarNotFound;
580 Ret = EplObduIsNumerical(uiIndex, uiSubIndex, &fNumerical);
581 if (Ret != kEplSuccessful)
582 { // entry doesn't exist
583 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
587 if ((fNumerical != FALSE)
588 && ((uiBitSize >> 3) != ObdSize))
590 // object is numerical,
591 // therefor size has to fit, but it does not.
592 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
593 Ret = kEplPdoVarNotFound;
597 // calucaled needed PDO size
598 *puiPdoSize_p = (uiBitOffset >> 3) + (uiBitSize >> 3);
605 #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)