388 lines
16 KiB
C
388 lines
16 KiB
C
/**
|
|
* CANopen Process Data Object protocol.
|
|
*
|
|
* @file CO_PDO.h
|
|
* @ingroup CO_PDO
|
|
* @author Janez Paternoster
|
|
* @copyright 2004 - 2020 Janez Paternoster
|
|
*
|
|
* This file is part of CANopenNode, an opensource CANopen Stack.
|
|
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
|
|
* For more information on CANopen see <http://www.can-cia.org/>.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
|
|
#ifndef CO_PDO_H
|
|
#define CO_PDO_H
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**
|
|
* @defgroup CO_PDO PDO
|
|
* @ingroup CO_CANopen
|
|
* @{
|
|
*
|
|
* CANopen Process Data Object protocol.
|
|
*
|
|
* Process data objects are used for real-time data transfer with no protocol
|
|
* overhead.
|
|
*
|
|
* TPDO with specific identifier is transmitted by one device and recieved by
|
|
* zero or more devices as RPDO. PDO communication parameters(COB-ID,
|
|
* transmission type, etc.) are in Object Dictionary at index 0x1400+ and
|
|
* 0x1800+. PDO mapping parameters (size and contents of the PDO) are in Object
|
|
* Dictionary at index 0x1600+ and 0x1A00+.
|
|
*
|
|
* Features of the PDO as implemented here, in CANopenNode:
|
|
* - Dynamic PDO mapping.
|
|
* - Map granularity of one byte.
|
|
* - After RPDO is received from CAN bus, its data are copied to buffer.
|
|
* Function CO_RPDO_process() (called by application) copies data to
|
|
* mapped objects in Object Dictionary. Synchronous RPDOs are processed AFTER
|
|
* reception of the next SYNC message.
|
|
* - Function CO_TPDO_process() (called by application) sends TPDO if
|
|
* necessary. There are possible different transmission types, including
|
|
* automatic detection of Change of State of specific variable.
|
|
*/
|
|
|
|
|
|
/**
|
|
* RPDO communication parameter. The same as record from Object dictionary (index 0x1400+).
|
|
*/
|
|
typedef struct{
|
|
uint8_t maxSubIndex; /**< Equal to 2 */
|
|
/** Communication object identifier for message received. Meaning of the specific bits:
|
|
- Bit 0-10: COB-ID for PDO, to change it bit 31 must be set.
|
|
- Bit 11-29: set to 0 for 11 bit COB-ID.
|
|
- Bit 30: If true, rtr are NOT allowed for PDO.
|
|
- Bit 31: If true, node does NOT use the PDO. */
|
|
uint32_t COB_IDUsedByRPDO;
|
|
/** Transmission type. Values:
|
|
- 0-240: Reciving is synchronous, process after next reception of the SYNC object.
|
|
- 241-253: Not used.
|
|
- 254: Manufacturer specific.
|
|
- 255: Asynchronous. */
|
|
uint8_t transmissionType;
|
|
}CO_RPDOCommPar_t;
|
|
|
|
|
|
/**
|
|
* RPDO mapping parameter. The same as record from Object dictionary (index 0x1600+).
|
|
*/
|
|
typedef struct{
|
|
/** Actual number of mapped objects from 0 to 8. To change mapped object,
|
|
this value must be 0. */
|
|
uint8_t numberOfMappedObjects;
|
|
/** Location and size of the mapped object. Bit meanings `0xIIIISSLL`:
|
|
- Bit 0-7: Data Length in bits.
|
|
- Bit 8-15: Subindex from object distionary.
|
|
- Bit 16-31: Index from object distionary. */
|
|
uint32_t mappedObject1;
|
|
uint32_t mappedObject2; /**< Same */
|
|
uint32_t mappedObject3; /**< Same */
|
|
uint32_t mappedObject4; /**< Same */
|
|
uint32_t mappedObject5; /**< Same */
|
|
uint32_t mappedObject6; /**< Same */
|
|
uint32_t mappedObject7; /**< Same */
|
|
uint32_t mappedObject8; /**< Same */
|
|
}CO_RPDOMapPar_t;
|
|
|
|
|
|
/**
|
|
* TPDO communication parameter. The same as record from Object dictionary (index 0x1800+).
|
|
*/
|
|
typedef struct{
|
|
uint8_t maxSubIndex; /**< Equal to 6 */
|
|
/** Communication object identifier for transmitting message. Meaning of the specific bits:
|
|
- Bit 0-10: COB-ID for PDO, to change it bit 31 must be set.
|
|
- Bit 11-29: set to 0 for 11 bit COB-ID.
|
|
- Bit 30: If true, rtr are NOT allowed for PDO.
|
|
- Bit 31: If true, node does NOT use the PDO. */
|
|
uint32_t COB_IDUsedByTPDO;
|
|
/** Transmission type. Values:
|
|
- 0: Transmiting is synchronous, specification in device profile.
|
|
- 1-240: Transmiting is synchronous after every N-th SYNC object.
|
|
- 241-251: Not used.
|
|
- 252-253: Transmited only on reception of Remote Transmission Request.
|
|
- 254: Manufacturer specific.
|
|
- 255: Asinchronous, specification in device profile. */
|
|
uint8_t transmissionType;
|
|
/** Minimum time between transmissions of the PDO in 100micro seconds.
|
|
Zero disables functionality. */
|
|
uint16_t inhibitTime;
|
|
/** Not used */
|
|
uint8_t compatibilityEntry;
|
|
/** Time between periodic transmissions of the PDO in milliseconds.
|
|
Zero disables functionality. */
|
|
uint16_t eventTimer;
|
|
/** Used with numbered SYNC messages. Values:
|
|
- 0: Counter of the SYNC message shall not be processed.
|
|
- 1-240: The SYNC message with the counter value equal to this value
|
|
shall be regarded as the first received SYNC message. */
|
|
uint8_t SYNCStartValue;
|
|
}CO_TPDOCommPar_t;
|
|
|
|
|
|
/**
|
|
* TPDO mapping parameter. The same as record from Object dictionary (index 0x1A00+).
|
|
*/
|
|
typedef struct{
|
|
/** Actual number of mapped objects from 0 to 8. To change mapped object,
|
|
this value must be 0. */
|
|
uint8_t numberOfMappedObjects;
|
|
/** Location and size of the mapped object. Bit meanings `0xIIIISSLL`:
|
|
- Bit 0-7: Data Length in bits.
|
|
- Bit 8-15: Subindex from object distionary.
|
|
- Bit 16-31: Index from object distionary. */
|
|
uint32_t mappedObject1;
|
|
uint32_t mappedObject2; /**< Same */
|
|
uint32_t mappedObject3; /**< Same */
|
|
uint32_t mappedObject4; /**< Same */
|
|
uint32_t mappedObject5; /**< Same */
|
|
uint32_t mappedObject6; /**< Same */
|
|
uint32_t mappedObject7; /**< Same */
|
|
uint32_t mappedObject8; /**< Same */
|
|
}CO_TPDOMapPar_t;
|
|
|
|
|
|
/**
|
|
* RPDO object.
|
|
*/
|
|
typedef struct{
|
|
CO_EM_t *em; /**< From CO_RPDO_init() */
|
|
CO_SDO_t *SDO; /**< From CO_RPDO_init() */
|
|
CO_SYNC_t *SYNC; /**< From CO_RPDO_init() */
|
|
const CO_RPDOCommPar_t *RPDOCommPar;/**< From CO_RPDO_init() */
|
|
const CO_RPDOMapPar_t *RPDOMapPar; /**< From CO_RPDO_init() */
|
|
uint8_t *operatingState; /**< From CO_RPDO_init() */
|
|
uint8_t nodeId; /**< From CO_RPDO_init() */
|
|
uint16_t defaultCOB_ID; /**< From CO_RPDO_init() */
|
|
uint8_t restrictionFlags;/**< From CO_RPDO_init() */
|
|
/** True, if PDO is enabled and valid */
|
|
bool_t valid;
|
|
/** True, if PDO synchronous (transmissionType <= 240) */
|
|
bool_t synchronous;
|
|
/** Data length of the received PDO message. Calculated from mapping */
|
|
uint8_t dataLength;
|
|
/** Pointers to 8 data objects, where PDO will be copied */
|
|
uint8_t *mapPointer[8];
|
|
/** Variable indicates, if new PDO message received from CAN bus. */
|
|
volatile void *CANrxNew[2];
|
|
/** 8 data bytes of the received message. */
|
|
uint8_t CANrxData[2][8];
|
|
CO_CANmodule_t *CANdevRx; /**< From CO_RPDO_init() */
|
|
uint16_t CANdevRxIdx; /**< From CO_RPDO_init() */
|
|
}CO_RPDO_t;
|
|
|
|
|
|
/**
|
|
* TPDO object.
|
|
*/
|
|
typedef struct{
|
|
CO_EM_t *em; /**< From CO_TPDO_init() */
|
|
CO_SDO_t *SDO; /**< From CO_TPDO_init() */
|
|
CO_SYNC_t *SYNC; /**< From CO_TPDO_init() */
|
|
const CO_TPDOCommPar_t *TPDOCommPar;/**< From CO_TPDO_init() */
|
|
const CO_TPDOMapPar_t *TPDOMapPar; /**< From CO_TPDO_init() */
|
|
uint8_t *operatingState; /**< From CO_TPDO_init() */
|
|
uint8_t nodeId; /**< From CO_TPDO_init() */
|
|
uint16_t defaultCOB_ID; /**< From CO_TPDO_init() */
|
|
uint8_t restrictionFlags;/**< From CO_TPDO_init() */
|
|
bool_t valid; /**< True, if PDO is enabled and valid */
|
|
/** Data length of the transmitting PDO message. Calculated from mapping */
|
|
uint8_t dataLength;
|
|
/** If application set this flag, PDO will be later sent by
|
|
function CO_TPDO_process(). Depends on transmission type. */
|
|
uint8_t sendRequest;
|
|
/** Pointers to 8 data objects, where PDO will be copied */
|
|
uint8_t *mapPointer[8];
|
|
/** Each flag bit is connected with one mapPointer. If flag bit
|
|
is true, CO_TPDO_process() functiuon will send PDO if
|
|
Change of State is detected on value pointed by that mapPointer */
|
|
uint8_t sendIfCOSFlags;
|
|
/** SYNC counter used for PDO sending */
|
|
uint8_t syncCounter;
|
|
/** Inhibit timer used for inhibit PDO sending translated to microseconds */
|
|
uint32_t inhibitTimer;
|
|
/** Event timer used for PDO sending translated to microseconds */
|
|
uint32_t eventTimer;
|
|
CO_CANmodule_t *CANdevTx; /**< From CO_TPDO_init() */
|
|
CO_CANtx_t *CANtxBuff; /**< CAN transmit buffer inside CANdev */
|
|
uint16_t CANdevTxIdx; /**< From CO_TPDO_init() */
|
|
}CO_TPDO_t;
|
|
|
|
|
|
/**
|
|
* Initialize RPDO object.
|
|
*
|
|
* Function must be called in the communication reset section.
|
|
*
|
|
* @param RPDO This object will be initialized.
|
|
* @param em Emergency object.
|
|
* @param SDO SDO server object.
|
|
* @param operatingState Pointer to variable indicating CANopen device NMT internal state.
|
|
* @param nodeId CANopen Node ID of this device. If default COB_ID is used, value will be added.
|
|
* @param defaultCOB_ID Default COB ID for this PDO (without NodeId).
|
|
* See #CO_Default_CAN_ID_t
|
|
* @param restrictionFlags Flag bits indicates, how PDO communication
|
|
* and mapping parameters are handled:
|
|
* - Bit1: If true, communication parameters are writeable only in pre-operational NMT state.
|
|
* - Bit2: If true, mapping parameters are writeable only in pre-operational NMT state.
|
|
* - Bit3: If true, communication parameters are read-only.
|
|
* - Bit4: If true, mapping parameters are read-only.
|
|
* @param RPDOCommPar Pointer to _RPDO communication parameter_ record from Object
|
|
* dictionary (index 0x1400+).
|
|
* @param RPDOMapPar Pointer to _RPDO mapping parameter_ record from Object
|
|
* dictionary (index 0x1600+).
|
|
* @param idx_RPDOCommPar Index in Object Dictionary.
|
|
* @param idx_RPDOMapPar Index in Object Dictionary.
|
|
* @param CANdevRx CAN device for PDO reception.
|
|
* @param CANdevRxIdx Index of receive buffer in the above CAN device.
|
|
*
|
|
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
|
|
*/
|
|
CO_ReturnError_t CO_RPDO_init(
|
|
CO_RPDO_t *RPDO,
|
|
CO_EM_t *em,
|
|
CO_SDO_t *SDO,
|
|
CO_SYNC_t *SYNC,
|
|
uint8_t *operatingState,
|
|
uint8_t nodeId,
|
|
uint16_t defaultCOB_ID,
|
|
uint8_t restrictionFlags,
|
|
const CO_RPDOCommPar_t *RPDOCommPar,
|
|
const CO_RPDOMapPar_t *RPDOMapPar,
|
|
uint16_t idx_RPDOCommPar,
|
|
uint16_t idx_RPDOMapPar,
|
|
CO_CANmodule_t *CANdevRx,
|
|
uint16_t CANdevRxIdx);
|
|
|
|
|
|
/**
|
|
* Initialize TPDO object.
|
|
*
|
|
* Function must be called in the communication reset section.
|
|
*
|
|
* @param TPDO This object will be initialized.
|
|
* @param em Emergency object.
|
|
* @param SDO SDO object.
|
|
* @param operatingState Pointer to variable indicating CANopen device NMT internal state.
|
|
* @param nodeId CANopen Node ID of this device. If default COB_ID is used, value will be added.
|
|
* @param defaultCOB_ID Default COB ID for this PDO (without NodeId).
|
|
* See #CO_Default_CAN_ID_t
|
|
* @param restrictionFlags Flag bits indicates, how PDO communication
|
|
* and mapping parameters are handled:
|
|
* - Bit1: If true, communication parameters are writeable only in pre-operational NMT state.
|
|
* - Bit2: If true, mapping parameters are writeable only in pre-operational NMT state.
|
|
* - Bit3: If true, communication parameters are read-only.
|
|
* - Bit4: If true, mapping parameters are read-only.
|
|
* @param TPDOCommPar Pointer to _TPDO communication parameter_ record from Object
|
|
* dictionary (index 0x1400+).
|
|
* @param TPDOMapPar Pointer to _TPDO mapping parameter_ record from Object
|
|
* dictionary (index 0x1600+).
|
|
* @param idx_TPDOCommPar Index in Object Dictionary.
|
|
* @param idx_TPDOMapPar Index in Object Dictionary.
|
|
* @param CANdevTx CAN device used for PDO transmission.
|
|
* @param CANdevTxIdx Index of transmit buffer in the above CAN device.
|
|
*
|
|
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
|
|
*/
|
|
CO_ReturnError_t CO_TPDO_init(
|
|
CO_TPDO_t *TPDO,
|
|
CO_EM_t *em,
|
|
CO_SDO_t *SDO,
|
|
CO_SYNC_t *SYNC,
|
|
uint8_t *operatingState,
|
|
uint8_t nodeId,
|
|
uint16_t defaultCOB_ID,
|
|
uint8_t restrictionFlags,
|
|
const CO_TPDOCommPar_t *TPDOCommPar,
|
|
const CO_TPDOMapPar_t *TPDOMapPar,
|
|
uint16_t idx_TPDOCommPar,
|
|
uint16_t idx_TPDOMapPar,
|
|
CO_CANmodule_t *CANdevTx,
|
|
uint16_t CANdevTxIdx);
|
|
|
|
|
|
/**
|
|
* Verify Change of State of the PDO.
|
|
*
|
|
* Function verifies if variable mapped to TPDO has changed its value. Verified
|
|
* are only variables, which has set attribute _CO_ODA_TPDO_DETECT_COS_ in
|
|
* #CO_SDO_OD_attributes_t.
|
|
*
|
|
* Function may be called by application just before CO_TPDO_process() function,
|
|
* for example: `TPDOx->sendRequest = CO_TPDOisCOS(TPDOx); CO_TPDO_process(TPDOx, ....`
|
|
*
|
|
* @param TPDO TPDO object.
|
|
*
|
|
* @return True if COS was detected.
|
|
*/
|
|
uint8_t CO_TPDOisCOS(CO_TPDO_t *TPDO);
|
|
|
|
|
|
/**
|
|
* Send TPDO message.
|
|
*
|
|
* Function prepares TPDO data from Object Dictionary variables. It should not
|
|
* be called by application, it is called from CO_TPDO_process().
|
|
*
|
|
*
|
|
* @param TPDO TPDO object.
|
|
*
|
|
* @return Same as CO_CANsend().
|
|
*/
|
|
int16_t CO_TPDOsend(CO_TPDO_t *TPDO);
|
|
|
|
|
|
/**
|
|
* Process received PDO messages.
|
|
*
|
|
* Function must be called cyclically in any NMT state. It copies data from RPDO
|
|
* to Object Dictionary variables if: new PDO receives and PDO is valid and NMT
|
|
* operating state is operational. It does not verify _transmission type_.
|
|
*
|
|
* @param RPDO This object.
|
|
* @param syncWas True, if CANopen SYNC message was just received or transmitted.
|
|
*/
|
|
void CO_RPDO_process(CO_RPDO_t *RPDO, bool_t syncWas);
|
|
|
|
|
|
/**
|
|
* Process transmitting PDO messages.
|
|
*
|
|
* Function must be called cyclically in any NMT state. It prepares and sends
|
|
* TPDO if necessary. If Change of State needs to be detected, function
|
|
* CO_TPDOisCOS() must be called before.
|
|
*
|
|
* @param TPDO This object.
|
|
* @param SYNC SYNC object. Ignored if NULL.
|
|
* @param syncWas True, if CANopen SYNC message was just received or transmitted.
|
|
* @param timeDifference_us Time difference from previous function call in [microseconds].
|
|
*/
|
|
void CO_TPDO_process(
|
|
CO_TPDO_t *TPDO,
|
|
bool_t syncWas,
|
|
uint32_t timeDifference_us);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif /*__cplusplus*/
|
|
|
|
/** @} */
|
|
#endif
|