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!"
85 /***************************************************************************/
88 /* G L O B A L D E F I N I T I O N S */
91 /***************************************************************************/
93 //---------------------------------------------------------------------------
95 //---------------------------------------------------------------------------
97 #define EPL_PDOU_OBD_IDX_RX_COMM_PARAM 0x1400
98 #define EPL_PDOU_OBD_IDX_RX_MAPP_PARAM 0x1600
99 #define EPL_PDOU_OBD_IDX_TX_COMM_PARAM 0x1800
100 #define EPL_PDOU_OBD_IDX_TX_MAPP_PARAM 0x1A00
101 #define EPL_PDOU_OBD_IDX_MAPP_PARAM 0x0200
102 #define EPL_PDOU_OBD_IDX_MASK 0xFF00
103 #define EPL_PDOU_PDO_ID_MASK 0x00FF
105 //---------------------------------------------------------------------------
107 //---------------------------------------------------------------------------
109 //---------------------------------------------------------------------------
110 // modul globale vars
111 //---------------------------------------------------------------------------
113 //---------------------------------------------------------------------------
114 // local function prototypes
115 //---------------------------------------------------------------------------
117 /***************************************************************************/
120 /* C L A S S EplPdou */
123 /***************************************************************************/
128 /***************************************************************************/
130 //=========================================================================//
132 // P R I V A T E D E F I N I T I O N S //
134 //=========================================================================//
136 //---------------------------------------------------------------------------
138 //---------------------------------------------------------------------------
140 //---------------------------------------------------------------------------
142 //---------------------------------------------------------------------------
144 //---------------------------------------------------------------------------
146 //---------------------------------------------------------------------------
148 //---------------------------------------------------------------------------
149 // local function prototypes
150 //---------------------------------------------------------------------------
152 static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p,
153 unsigned int uiIndex_p);
155 static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
156 unsigned int *puiIndex_p,
157 unsigned int *puiSubIndex_p,
158 unsigned int *puiBitOffset_p,
159 unsigned int *puiBitSize_p);
161 static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
162 tEplObdAccess AccessType_p,
163 DWORD * pdwAbortCode_p,
164 unsigned int *puiPdoSize_p);
166 //=========================================================================//
168 // P U B L I C F U N C T I O N S //
170 //=========================================================================//
172 //---------------------------------------------------------------------------
174 // Function: EplPdouAddInstance()
176 // Description: add and initialize new instance of EPL stack
180 // Returns: tEplKernel = error code
185 //---------------------------------------------------------------------------
187 tEplKernel EplPdouAddInstance(void)
190 return kEplSuccessful;
193 //---------------------------------------------------------------------------
195 // Function: EplPdouDelInstance()
197 // Description: deletes an instance of EPL stack
201 // Returns: tEplKernel = error code
206 //---------------------------------------------------------------------------
208 tEplKernel EplPdouDelInstance(void)
211 return kEplSuccessful;
214 //---------------------------------------------------------------------------
216 // Function: EplPdouCbObdAccess
218 // Description: callback function for OD accesses
220 // Parameters: pParam_p = OBD parameter
222 // Returns: tEplKernel = error code
227 //---------------------------------------------------------------------------
229 tEplKernel PUBLIC EplPdouCbObdAccess(tEplObdCbParam MEM * pParam_p)
231 tEplKernel Ret = kEplSuccessful;
232 unsigned int uiPdoId;
233 unsigned int uiIndexType;
236 QWORD qwObjectMapping;
237 tEplObdAccess AccessType;
239 unsigned int uiCurPdoSize;
241 unsigned int uiSubIndex;
244 uiPdoId = pParam_p->m_uiIndex & EPL_PDOU_PDO_ID_MASK;
246 // fetch object index type
247 uiIndexType = pParam_p->m_uiIndex & EPL_PDOU_OBD_IDX_MASK;
249 if (pParam_p->m_ObdEvent != kEplObdEvPreWrite) { // read accesses, post write events etc. are OK
250 pParam_p->m_dwAbortCode = 0;
254 switch (uiIndexType) {
255 case EPL_PDOU_OBD_IDX_RX_COMM_PARAM:
256 // RPDO communication parameter accessed
257 case EPL_PDOU_OBD_IDX_TX_COMM_PARAM:
258 { // TPDO communication parameter accessed
259 Ret = EplPdouCheckPdoValidity(pParam_p,
260 (EPL_PDOU_OBD_IDX_MAPP_PARAM
261 | pParam_p->m_uiIndex));
262 if (Ret != kEplSuccessful) { // PDO is valid or does not exist
269 case EPL_PDOU_OBD_IDX_RX_MAPP_PARAM:
270 { // RPDO mapping parameter accessed
272 AccessType = kEplObdAccWrite;
276 case EPL_PDOU_OBD_IDX_TX_MAPP_PARAM:
277 { // TPDO mapping parameter accessed
279 AccessType = kEplObdAccRead;
284 { // this callback function is only for
285 // PDO mapping and communication parameters
286 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
291 // RPDO and TPDO mapping parameter accessed
293 if (pParam_p->m_uiSubIndex == 0) { // object mapping count accessed
295 // PDO is enabled or disabled
296 bObjectCount = *((BYTE *) pParam_p->m_pArg);
298 if (bObjectCount == 0) { // PDO shall be disabled
300 // that is always possible
303 // PDO shall be enabled
304 // it should have been disabled for this operation
305 Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
306 if (Ret != kEplSuccessful) { // PDO is valid or does not exist
310 if (AccessType == kEplObdAccWrite) {
311 uiSubIndex = 0x04; // PReqActPayloadLimit_U16
313 uiSubIndex = 0x05; // PResActPayloadLimit_U16
316 // fetch maximum PDO size from Object 1F98h: NMT_CycleTiming_REC
317 ObdSize = sizeof(wMaxPdoSize);
319 EplObduReadEntry(0x1F98, uiSubIndex, &wMaxPdoSize,
321 if (Ret != kEplSuccessful) { // other fatal error occured
322 pParam_p->m_dwAbortCode = EPL_SDOAC_GENERAL_ERROR;
325 // check all objectmappings
326 for (bMappSubindex = 1; bMappSubindex <= bObjectCount;
328 // read object mapping from OD
329 ObdSize = sizeof(qwObjectMapping); // QWORD
330 Ret = EplObduReadEntry(pParam_p->m_uiIndex,
331 bMappSubindex, &qwObjectMapping,
333 if (Ret != kEplSuccessful) { // other fatal error occured
334 pParam_p->m_dwAbortCode =
335 EPL_SDOAC_GENERAL_ERROR;
338 // check object mapping
339 Ret = EplPdouCheckObjectMapping(qwObjectMapping,
344 if (Ret != kEplSuccessful) { // illegal object mapping
348 if (uiCurPdoSize > wMaxPdoSize) { // mapping exceeds object size
349 pParam_p->m_dwAbortCode =
350 EPL_SDOAC_GENERAL_ERROR;
351 Ret = kEplPdoVarNotFound;
356 } else { // ObjectMapping
357 Ret = EplPdouCheckPdoValidity(pParam_p, pParam_p->m_uiIndex);
358 if (Ret != kEplSuccessful) { // PDO is valid or does not exist
361 // check existence of object and validity of object length
363 qwObjectMapping = *((QWORD *) pParam_p->m_pArg);
365 Ret = EplPdouCheckObjectMapping(qwObjectMapping,
367 &pParam_p->m_dwAbortCode,
376 //=========================================================================//
378 // P R I V A T E F U N C T I O N S //
380 //=========================================================================//
382 //---------------------------------------------------------------------------
384 // Function: EplPdouCheckPdoValidity
386 // Description: check if PDO is valid
388 // Parameters: pParam_p = OBD parameter
390 // Returns: tEplKernel = error code
395 //---------------------------------------------------------------------------
397 static tEplKernel EplPdouCheckPdoValidity(tEplObdCbParam MEM * pParam_p,
398 unsigned int uiIndex_p)
400 tEplKernel Ret = kEplSuccessful;
405 // read number of mapped objects from OD; this indicates if the PDO is valid
406 Ret = EplObduReadEntry(uiIndex_p, 0x00, &bObjectCount, &ObdSize);
407 if (Ret != kEplSuccessful) { // other fatal error occured
408 pParam_p->m_dwAbortCode =
409 EPL_SDOAC_GEN_INTERNAL_INCOMPATIBILITY;
412 // entry read successfully
413 if (bObjectCount != 0) { // PDO in OD is still valid
414 pParam_p->m_dwAbortCode = EPL_SDOAC_GEN_PARAM_INCOMPATIBILITY;
415 Ret = kEplPdoNotExist;
423 //---------------------------------------------------------------------------
425 // Function: EplPdouDecodeObjectMapping
427 // Description: decodes the given object mapping entry into index, subindex,
428 // bit offset and bit size.
430 // Parameters: qwObjectMapping_p = object mapping entry
431 // puiIndex_p = [OUT] pointer to object index
432 // puiSubIndex_p = [OUT] pointer to subindex
433 // puiBitOffset_p = [OUT] pointer to bit offset
434 // puiBitSize_p = [OUT] pointer to bit size
440 //---------------------------------------------------------------------------
442 static void EplPdouDecodeObjectMapping(QWORD qwObjectMapping_p,
443 unsigned int *puiIndex_p,
444 unsigned int *puiSubIndex_p,
445 unsigned int *puiBitOffset_p,
446 unsigned int *puiBitSize_p)
448 *puiIndex_p = (unsigned int)
449 (qwObjectMapping_p & 0x000000000000FFFFLL);
451 *puiSubIndex_p = (unsigned int)
452 ((qwObjectMapping_p & 0x0000000000FF0000LL) >> 16);
454 *puiBitOffset_p = (unsigned int)
455 ((qwObjectMapping_p & 0x0000FFFF00000000LL) >> 32);
457 *puiBitSize_p = (unsigned int)
458 ((qwObjectMapping_p & 0xFFFF000000000000LL) >> 48);
462 //---------------------------------------------------------------------------
464 // Function: EplPdouCheckObjectMapping
466 // Description: checks the given object mapping entry.
468 // Parameters: qwObjectMapping_p = object mapping entry
469 // AccessType_p = access type to mapped object:
470 // write = RPDO and read = TPDO
471 // puiPdoSize_p = [OUT] pointer to covered PDO size
472 // (offset + size) in byte;
473 // 0 if mapping failed
474 // pdwAbortCode_p = [OUT] pointer to SDO abort code;
475 // 0 if mapping is possible
477 // Returns: tEplKernel = error code
481 //---------------------------------------------------------------------------
483 static tEplKernel EplPdouCheckObjectMapping(QWORD qwObjectMapping_p,
484 tEplObdAccess AccessType_p,
485 DWORD * pdwAbortCode_p,
486 unsigned int *puiPdoSize_p)
488 tEplKernel Ret = kEplSuccessful;
490 unsigned int uiIndex;
491 unsigned int uiSubIndex;
492 unsigned int uiBitOffset;
493 unsigned int uiBitSize;
494 tEplObdAccess AccessType;
497 if (qwObjectMapping_p == 0) { // discard zero value
501 // decode object mapping
502 EplPdouDecodeObjectMapping(qwObjectMapping_p,
504 &uiSubIndex, &uiBitOffset, &uiBitSize);
506 if ((uiBitOffset & 0x7) != 0x0) { // bit mapping is not supported
507 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
508 Ret = kEplPdoGranularityMismatch;
512 if ((uiBitSize & 0x7) != 0x0) { // bit mapping is not supported
513 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
514 Ret = kEplPdoGranularityMismatch;
518 Ret = EplObduGetAccessType(uiIndex, uiSubIndex, &AccessType);
519 if (Ret != kEplSuccessful) { // entry doesn't exist
520 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
524 if ((AccessType & kEplObdAccPdo) == 0) { // object is not mappable
525 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
526 Ret = kEplPdoVarNotFound;
530 if ((AccessType & AccessType_p) == 0) { // object is not writeable (RPDO) or readable (TPDO) respectively
531 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_MAPPABLE;
532 Ret = kEplPdoVarNotFound;
536 ObdSize = EplObduGetDataSize(uiIndex, uiSubIndex);
537 if (ObdSize < (uiBitSize >> 3)) { // object does not exist or has smaller size
538 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
539 Ret = kEplPdoVarNotFound;
542 Ret = EplObduIsNumerical(uiIndex, uiSubIndex, &fNumerical);
543 if (Ret != kEplSuccessful) { // entry doesn't exist
544 *pdwAbortCode_p = EPL_SDOAC_OBJECT_NOT_EXIST;
548 if ((fNumerical != FALSE)
549 && ((uiBitSize >> 3) != ObdSize)) {
550 // object is numerical,
551 // therefor size has to fit, but it does not.
552 *pdwAbortCode_p = EPL_SDOAC_GENERAL_ERROR;
553 Ret = kEplPdoVarNotFound;
556 // calucaled needed PDO size
557 *puiPdoSize_p = (uiBitOffset >> 3) + (uiBitSize >> 3);
563 #endif // #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_PDOU)) != 0)