1
0
Fork 0

SRDO updated to current CANopenNode

This commit is contained in:
Janez 2024-05-31 01:47:28 +02:00
parent 57ce72e6a2
commit f054501d0e
9 changed files with 1142 additions and 1099 deletions

View file

@ -304,8 +304,8 @@ typedef enum {
/** 0x1C, communication, critical, Heartbeat consumer detected remote node
* reset */
CO_EM_HB_CONSUMER_REMOTE_RESET = 0x1CU,
/** 0x1D, communication, critical, (unused) */
CO_EM_1D_unused = 0x1DU,
/** 0x1D, communication, critical, Error in SRDO configuration parameters. */
CO_EM_SRDO_CONFIGURATION = 0x1DU,
/** 0x1E, communication, critical, (unused) */
CO_EM_1E_unused = 0x1EU,
/** 0x1F, communication, critical, (unused) */

View file

@ -570,10 +570,6 @@ extern "C" {
* Possible flags, can be ORed:
* - CO_CONFIG_SRDO_ENABLE - Enable the SRDO object.
* - CO_CONFIG_SRDO_CHECK_TX - Enable checking data before sending.
* - CO_CONFIG_RSRDO_CALLS_EXTENSION - Enable calling configured extension
* callbacks when received RSRDO CAN message modifies OD entries.
* - CO_CONFIG_TRSRDO_CALLS_EXTENSION - Enable calling configured extension
* callbacks before TSRDO CAN message is sent.
* - #CO_CONFIG_FLAG_CALLBACK_PRE - Enable custom callback after preprocessing
* received RSRDO CAN message.
* Callback is configured by CO_SRDO_initCallbackPre().
@ -585,8 +581,6 @@ extern "C" {
#endif
#define CO_CONFIG_SRDO_ENABLE 0x01
#define CO_CONFIG_SRDO_CHECK_TX 0x02
#define CO_CONFIG_RSRDO_CALLS_EXTENSION 0x04
#define CO_CONFIG_TSRDO_CALLS_EXTENSION 0x08
/**
* SRDO Tx time delay

View file

@ -4,7 +4,8 @@
* @file CO_GFC.c
* @ingroup CO_GFC
* @author Robert Grüning
* @copyright 2020 - 2020 Robert Grüning
* @copyright 2020 Robert Grüning
* @copyright 2024 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
@ -27,32 +28,49 @@
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER
/*
* Custom function for reading or writing OD object.
*
* For more information see file CO_ODinterface.h, OD_IO_t.
*/
static ODR_t
OD_write_1300(OD_stream_t* stream, const void* buf, OD_size_t count, OD_size_t* countWritten) {
if ((stream == NULL) || (stream->subIndex != 0U) || (buf == NULL) || (countWritten == NULL)) {
return ODR_DEV_INCOMPAT;
}
static void CO_GFC_receive(void *object, void *msg)
{
CO_GFC_t *GFC;
CO_GFC_t* GFC = stream->object;
uint8_t value = CO_getUint8(buf);
if (value > 1) {
return ODR_INVALID_VALUE;
}
GFC->valid = (value == 1);
/* write value to the original location in the Object Dictionary */
return OD_writeOriginal(stream, buf, count, countWritten);
}
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER
static void
CO_GFC_receive(void* object, void* msg) {
CO_GFC_t* GFC;
uint8_t DLC = CO_CANrxMsg_readDLC(msg);
GFC = (CO_GFC_t *)
object; /* this is the correct pointer type of the first argument */
GFC = (CO_GFC_t*)object; /* this is the correct pointer type of the first argument */
if ((*GFC->valid == 0x01) && (DLC == 0)) {
if (GFC->valid && (DLC == 0)) {
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER
/* Optional signal to RTOS, which can resume task, which handles SRDO.
*/
/* Callback signals Global Failsafe Command */
if (GFC->pFunctSignalSafe != NULL) {
GFC->pFunctSignalSafe(GFC->functSignalObjectSafe);
}
#endif
}
}
void CO_GFC_initCallbackEnterSafeState(CO_GFC_t *GFC,
void *object,
void (*pFunctSignalSafe)(void *object))
{
void
CO_GFC_initCallbackEnterSafeState(CO_GFC_t* GFC, void* object, void (*pFunctSignalSafe)(void* object)) {
if (GFC != NULL) {
GFC->functSignalObjectSafe = object;
GFC->pFunctSignalSafe = pFunctSignalSafe;
@ -60,70 +78,70 @@ void CO_GFC_initCallbackEnterSafeState(CO_GFC_t *GFC,
}
#endif
CO_ReturnError_t CO_GFC_init(CO_GFC_t *GFC,
uint8_t *valid,
CO_CANmodule_t *GFC_CANdevRx,
uint16_t GFC_rxIdx,
uint16_t CANidRxGFC,
CO_CANmodule_t *GFC_CANdevTx,
uint16_t GFC_txIdx,
uint16_t CANidTxGFC)
{
if (GFC == NULL || valid == NULL || GFC_CANdevRx == NULL ||
GFC_CANdevTx == NULL) {
CO_ReturnError_t
CO_GFC_init(CO_GFC_t* GFC, OD_entry_t* OD_1300_gfcParameter, CO_CANmodule_t* GFC_CANdevRx, uint16_t GFC_rxIdx, uint16_t CANidRxGFC,
CO_CANmodule_t* GFC_CANdevTx, uint16_t GFC_txIdx, uint16_t CANidTxGFC) {
if (GFC == NULL || OD_1300_gfcParameter == NULL || GFC_CANdevRx == NULL || GFC_CANdevTx == NULL) {
return CO_ERROR_ILLEGAL_ARGUMENT;
}
GFC->valid = valid;
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_PRODUCER
GFC->CANdevTx = GFC_CANdevTx;
#endif
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER
GFC->functSignalObjectSafe = NULL;
GFC->pFunctSignalSafe = NULL;
#endif
uint8_t valid = 0;
if (OD_get_u8(OD_1300_gfcParameter, 0, &valid, true) != ODR_OK) {
return CO_ERROR_OD_PARAMETERS;
}
GFC->valid = (valid == 1);
/* Configure Object dictionary entry at index 0x1300+ */
GFC->OD_gfcParam_ext.object = GFC;
GFC->OD_gfcParam_ext.read = OD_readOriginal;
GFC->OD_gfcParam_ext.write = OD_write_1300;
OD_extension_init(OD_1300_gfcParameter, &GFC->OD_gfcParam_ext);
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_PRODUCER
GFC->CANtxBuff = CO_CANtxBufferInit(
GFC->CANdevTx, /* CAN device */
GFC_txIdx, /* index of specific buffer inside CAN module */
CANidTxGFC, /* CAN identifier */
0, /* rtr */
0, /* number of data bytes */
0); /* synchronous message flag bit */
GFC->CANdevTx = GFC_CANdevTx;
GFC->CANtxBuff = CO_CANtxBufferInit(GFC->CANdevTx, /* CAN device */
GFC_txIdx, /* index of specific buffer inside CAN module */
CANidTxGFC, /* CAN identifier */
0, /* rtr */
0, /* number of data bytes */
0); /* synchronous message flag bit */
if (GFC->CANtxBuff == NULL) {
return CO_ERROR_TX_UNCONFIGURED;
}
#else
(void)GFC_txIdx; /* unused */
(void)CANidTxGFC; /* unused */
(void)GFC_txIdx; /* unused */
(void)CANidTxGFC; /* unused */
#endif
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER
const CO_ReturnError_t r = CO_CANrxBufferInit(
GFC_CANdevRx, /* CAN device */
GFC_rxIdx, /* rx buffer index */
CANidRxGFC, /* CAN identifier */
0x7FF, /* mask */
0, /* rtr */
(void *)GFC, /* object passed to receive function */
CO_GFC_receive); /* this function will process received message */
GFC->functSignalObjectSafe = NULL;
GFC->pFunctSignalSafe = NULL;
const CO_ReturnError_t r = CO_CANrxBufferInit(GFC_CANdevRx, /* CAN device */
GFC_rxIdx, /* rx buffer index */
CANidRxGFC, /* CAN identifier */
0x7FF, /* mask */
0, /* rtr */
(void*)GFC, /* object passed to receive function */
CO_GFC_receive); /* this function will process received message */
if (r != CO_ERROR_NO) {
return r;
}
#else
(void)GFC_rxIdx; /* unused */
(void)CANidRxGFC; /* unused */
(void)GFC_rxIdx; /* unused */
(void)CANidRxGFC; /* unused */
#endif
return CO_ERROR_NO;
}
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_PRODUCER
CO_ReturnError_t CO_GFCsend(CO_GFC_t *GFC)
{
if (*GFC->valid == 0x01)
CO_ReturnError_t
CO_GFCsend(CO_GFC_t* GFC) {
if (GFC->valid) {
return CO_CANsend(GFC->CANdevTx, GFC->CANtxBuff);
}
return CO_ERROR_NO;
}
#endif

View file

@ -4,7 +4,8 @@
* @file CO_GFC.h
* @ingroup CO_GFC
* @author Robert Grüning
* @copyright 2020 - 2020 Robert Grüning
* @copyright 2020 Robert Grüning
* @copyright 2024 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
@ -27,6 +28,7 @@
#define CO_GFC_H
#include "301/CO_driver.h"
#include "301/CO_ODinterface.h"
/* default configuration, see CO_config.h */
#ifndef CO_CONFIG_GFC
@ -47,26 +49,26 @@ extern "C" {
* @{
* Very simple consumer/producer protocol.
* A net can have multiple GFC producer and multiple GFC consumer.
* On a safety-relevant the producer can send a GFC message (ID 0, DLC 0).
* On a safety-relevant the producer can send a GFC message (ID 1, DLC 0).
* The consumer can use this message to start the transition to a safe state.
* The GFC is optional for the security protocol and is not monitored (timed).
*/
/**
* GFC object.
*/
typedef struct {
uint8_t *valid; /**< From CO_GFC_init() */
#if ((CO_CONFIG_GFC)&CO_CONFIG_GFC_PRODUCER) || defined CO_DOXYGEN
CO_CANmodule_t *CANdevTx; /**< From CO_GFC_init() */
CO_CANtx_t *CANtxBuff; /**< CAN transmit buffer inside CANdevTx */
bool_t valid; /**< From OD parameter 1300 */
OD_extension_t OD_gfcParam_ext; /**< Extension for OD object */
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_PRODUCER) || defined CO_DOXYGEN
CO_CANmodule_t* CANdevTx; /**< From CO_GFC_init() */
CO_CANtx_t* CANtxBuff; /**< CAN transmit buffer inside CANdevTx */
#endif
#if ((CO_CONFIG_GFC)&CO_CONFIG_GFC_CONSUMER) || defined CO_DOXYGEN
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER) || defined CO_DOXYGEN
/** From CO_GFC_initCallbackEnterSafeState() or NULL */
void (*pFunctSignalSafe)(void *object);
void (*pFunctSignalSafe)(void* object);
/** From CO_GFC_initCallbackEnterSafeState() or NULL */
void *functSignalObjectSafe;
void* functSignalObjectSafe;
#endif
} CO_GFC_t;
@ -76,7 +78,8 @@ typedef struct {
* Function must be called in the communication reset section.
*
* @param GFC This object will be initialized.
* @param valid pointer to the valid flag in OD (0x1300)
* @param OD_1300_gfcParameter Pointer to _Global fail-safe command parameter_
* variable from Object dictionary (index 0x1300).
* @param GFC_CANdevRx CAN device used for SRDO reception.
* @param GFC_rxIdx Index of receive buffer in the above CAN device.
* @param CANidRxGFC GFC CAN ID for reception
@ -86,16 +89,11 @@ typedef struct {
*
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
*/
CO_ReturnError_t CO_GFC_init(CO_GFC_t *GFC,
uint8_t *valid,
CO_CANmodule_t *GFC_CANdevRx,
uint16_t GFC_rxIdx,
uint16_t CANidRxGFC,
CO_CANmodule_t *GFC_CANdevTx,
uint16_t GFC_txIdx,
uint16_t CANidTxGFC);
CO_ReturnError_t CO_GFC_init(CO_GFC_t* GFC, OD_entry_t* OD_1300_gfcParameter,
CO_CANmodule_t* GFC_CANdevRx, uint16_t GFC_rxIdx, uint16_t CANidRxGFC,
CO_CANmodule_t* GFC_CANdevTx, uint16_t GFC_txIdx, uint16_t CANidTxGFC);
#if ((CO_CONFIG_GFC)&CO_CONFIG_GFC_CONSUMER) || defined CO_DOXYGEN
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_CONSUMER) || defined CO_DOXYGEN
/**
* Initialize GFC callback function.
*
@ -107,12 +105,10 @@ CO_ReturnError_t CO_GFC_init(CO_GFC_t *GFC,
* Can be NULL
* @param pFunctSignalSafe Pointer to the callback function. Not called if NULL.
*/
void CO_GFC_initCallbackEnterSafeState(CO_GFC_t *GFC,
void *object,
void (*pFunctSignalSafe)(void *object));
void CO_GFC_initCallbackEnterSafeState(CO_GFC_t* GFC, void* object, void (*pFunctSignalSafe)(void* object));
#endif
#if ((CO_CONFIG_GFC)&CO_CONFIG_GFC_PRODUCER) || defined CO_DOXYGEN
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_PRODUCER) || defined CO_DOXYGEN
/**
* Send GFC message.
*
@ -123,7 +119,7 @@ void CO_GFC_initCallbackEnterSafeState(CO_GFC_t *GFC,
*
* @return Same as CO_CANsend().
*/
CO_ReturnError_t CO_GFCsend(CO_GFC_t *GFC);
CO_ReturnError_t CO_GFCsend(CO_GFC_t* GFC);
#endif
/** @} */ /* CO_GFC */

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,9 @@
* @file CO_SRDO.h
* @ingroup CO_SRDO
* @author Robert Grüning
* @copyright 2020 - 2020 Robert Grüning
* @copyright 2020 Robert Grüning
* @copyright 2024 temi54c1l8@github
* @copyright 2024 Janez Paternoster
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
@ -26,8 +28,8 @@
#ifndef CO_SRDO_H
#define CO_SRDO_H
#include "301/CO_ODinterface.h"
#include "301/CO_Emergency.h"
#include "301/CO_ODinterface.h"
/* default configuration, see CO_config.h */
#ifndef CO_CONFIG_SRDO
@ -39,21 +41,42 @@
#if ((CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE) || defined CO_DOXYGEN
#warning SRDO is draft version and is not fully tested!
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup CO_SRDO SRDO
* CANopen Safety Related Data Object protocol.
* CANopen Safety Related Data Object protocol
*
* @ingroup CO_CANopen_304
* @{
* The functionality is very similar to that of the PDOs.
* The main differences is every message is send and received twice.
* Safety Related Data Object protocol is specified by standard EN 50325-5:2010 (formerly CiA304).
* Its functionality is very similar to that of the PDOs. The main differences is every message is send and received twice.
* The second message must be bitwise inverted. The delay between the two messages and between each message pair is monitored.
* The distinction between sending and receiving SRDO is made at runtime (for PDO it is compile time).
* If the security protocol is used, at least one SRDO is mandatory.
*
* If there is erroneous structure of OD entries for SRDO parameters, then @CO_SRDO_init() function
* returns error and CANopen device doesn't work. It is necessary to repair Object Dictionary and reprogram the device.
*
* If there are erroneous values inside SRDO parameters, then Emergency message CO_EM_SRDO_CONFIGURATION is sent.
* Info code (32bit) contains OD index, subindex and additional byte, which helps to determine erroneous OD object.
*
* SRDO configuration consists of one @CO_SRDO_init_start(), @CO_SRDO_init() for each SRDO and one @CO_SRDO_init_end().
* These may be called in CANopen initialization section after all other CANopen objects are initialized.
* If SRDO OD parameters are edited (in NMT pre-operational state), NMT communication reset is necessary.
* Alternatively SRDO configuration may be executed just after transition to NMT operational state.
*
* @CO_SRDO_process() must be executed cyclically, similar as PDO processing. Function is fast, no time consuming tasks.
* Function returns @CO_SRDO_state_t value, which may be used to determine working-state or safe-state of safety related
* device. If return values from all SRDO objects are >= CO_SRDO_state_communicationEstablished, then working state is allowed.
* Otherwise SR device must be in safe state.
*
* Requirement for mapped objects:
* - @OD_attributes_t must have set bit ODA_RSRDO or ODA_RSRDO or ODA_TRSRDO (by CANopenEditor).
*/
/** Maximum size of SRDO message, 8 for standard CAN */
@ -61,10 +84,10 @@ extern "C" {
#define CO_SRDO_MAX_SIZE 8U
#endif
/** Maximum number of entries, which can be mapped to PDO, 8 for standard CAN,
* may be less to preserve RAM usage */
/** Maximum number of entries, which can be mapped to SRDO, 2*8 for standard
* CAN, may be less to preserve RAM usage. Must be multiple of 2. */
#ifndef CO_SRDO_MAX_MAPPED_ENTRIES
#define CO_SRDO_MAX_MAPPED_ENTRIES 8U
#define CO_SRDO_MAX_MAPPED_ENTRIES 16U
#endif
#ifndef CO_SRDO_OWN_TYPES
@ -72,108 +95,133 @@ extern "C" {
typedef uint8_t CO_SRDO_size_t;
#endif
/**
* SRDO internal state
*/
typedef enum {
CO_SRDO_state_error_internal = -10, /**< internal software error */
CO_SRDO_state_error_configuration = -9, /**< error in parameters, emergency message was sent */
CO_SRDO_state_error_txNotInverted = -6, /**< Transmitting SRDO messages was not inverted */
CO_SRDO_state_error_txFail = -5, /**< SRDO CAN message transmission failed */
CO_SRDO_state_error_rxTimeoutSRVT = -4, /**< SRDO message didn't receive inside SRVT time */
CO_SRDO_state_error_rxTimeoutSCT = -3, /**< SRDO inverted message didn't receive inside SCT time */
CO_SRDO_state_error_rxNotInverted = -2, /**< Received SRDO messages was not inverted */
CO_SRDO_state_error_rxShort = -1, /**< Received SRDO message is too short */
CO_SRDO_state_unknown = 0, /**< unknown state, set by @CO_SRDO_init */
CO_SRDO_state_nmtNotOperational = 1, /**< Internal NMT operating state is not NMT operational */
CO_SRDO_state_initializing = 2, /**< Just entered NMT operational state, SRDO message not yet received or transmitted */
CO_SRDO_state_communicationEstablished = 3, /**< SRDO communication established, fully functional */
CO_SRDO_state_deleted = 10 /**< informationDirection for this SRDO is set to 0 */
} CO_SRDO_state_t;
/**
* Gurad Object for SRDO
* monitors:
* Guard Object for SRDO.
*
* Guard object monitors all SRDO objects for:
* - access to CRC objects
* - access configuration valid flag
* - change in operation state
*/
typedef struct{
bool operatingState;
uint8_t configurationValid;
OD_entry_t *SRDO_CRC;
uint8_t checkCRC; /**< specifies whether a CRC check should be performed */
typedef struct {
/** True if NMT operating state is operational */
bool_t NMTisOperational;
/** True if all SRDO objects are properly configured. Set after successful
* finish of all @CO_SRDO_init() functions. Cleared on configuration change. */
bool_t configurationValid;
/** Private helper variable set on the start of SRDO configuration */
bool_t _configurationValid;
/** Object for input / output on the OD variable 13FE:00. Configuration
* of any of the the SRDO parameters will write 0 to that variable. */
OD_IO_t OD_IO_configurationValid;
/** Extension for OD object */
OD_extension_t OD_13FE_extension;
/** Extension for OD object */
OD_extension_t OD_13FF_extension;
}CO_SRDOGuard_t;
} CO_SRDOGuard_t;
/**
* SRDO object.
*/
typedef struct{
CO_EM_t *em; /**< From CO_SRDO_init() */
CO_SRDOGuard_t *SRDOGuard; /**< From CO_SRDO_init() */
OD_t *OD;
uint8_t SRDO_Index; /**< From CO_SRDO_init() */
/** Number of mapped objects in SRDO */
uint8_t mappedObjectsCount;
/** Pointers to 2*8 data objects, where SRDO will be copied */
uint8_t *mapPointer[2][CO_SRDO_MAX_SIZE];
typedef struct {
CO_SRDOGuard_t* SRDOGuard; /**< From CO_SRDO_init() */
CO_EM_t* em; /**< From CO_SRDO_init() */
uint16_t defaultCOB_ID; /**< From CO_SRDO_init() */
uint8_t nodeId; /**< From CO_SRDO_init() */
CO_CANmodule_t* CANdevTx[2];/**< From CO_SRDO_init() */
/** Internal state of this SRDO. */
CO_SRDO_state_t internalState;
/** Copy of variable, internal usage. */
bool_t NMTisOperationalPrevious;
/** 0 - SRDO is disabled; 1 - SRDO is producer (tx); 2 - SRDO is consumer (rx) */
uint8_t informationDirection;
/** Safety Cycle Time from object dictionary translated to microseconds */
uint32_t cycleTime_us;
/** Safety related validation time from object dictionary translated to microseconds */
uint32_t validationTime_us;
/** cycle timer variable in microseconds */
uint32_t cycleTimer;
/** validation timer variable in microseconds */
uint32_t validationTimer;
/** Data length of the received SRDO message. Calculated from mapping */
CO_SRDO_size_t dataLength;
uint8_t nodeId; /**< From CO_SRDO_init() */
uint16_t defaultCOB_ID[2]; /**< From CO_SRDO_init() */
/** 0 - invalid, 1 - tx, 2 - rx */
uint8_t valid;
OD_entry_t *SRDOCommPar; /**< From CO_SRDO_init() */
OD_entry_t *SRDOMapPar; /**< From CO_SRDO_init() */
CO_CANmodule_t *CANdevRx; /**< From CO_SRDO_init() */
CO_CANmodule_t *CANdevTx; /**< From CO_SRDO_init() */
CO_CANtx_t *CANtxBuff[2]; /**< CAN transmit buffer inside CANdevTx */
uint16_t CANdevRxIdx[2]; /**< From CO_SRDO_init() */
uint16_t CANdevTxIdx[2]; /**< From CO_SRDO_init() */
uint8_t toogle; /**< defines the current state */
uint32_t timer; /**< transmit timer and receive timeout */
CO_SRDO_size_t dataLength;
/** Number of mapped objects in SRDO */
uint8_t mappedObjectsCount;
/** Object dictionary interface for all mapped entries. OD_IO.dataOffset has
* special usage with SRDO. It stores information about mappedLength of
* the variable. mappedLength can be less or equal to the OD_IO.dataLength.
* mappedLength greater than OD_IO.dataLength indicates erroneous mapping.
* OD_IO.dataOffset is set to 0 before read/write function call and after
* the call OD_IO.dataOffset is set back to mappedLength. */
OD_IO_t OD_IO[CO_SRDO_MAX_MAPPED_ENTRIES];
/** CAN transmit buffers inside CANdevTx */
CO_CANtx_t* CANtxBuff[2];
/** Variable indicates, if new SRDO message received from CAN bus. */
volatile void *CANrxNew[2];
/** 2*8 data bytes of the received message. */
uint8_t CANrxData[2][8];
/** From CO_SRDO_initCallbackEnterSafeState() or NULL */
void (*pFunctSignalSafe)(void *object);
/** From CO_SRDO_initCallbackEnterSafeState() or NULL */
void *functSignalObjectSafe;
#if ((CO_CONFIG_SRDO) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
/** From CO_SRDO_initCallbackPre() or NULL */
void (*pFunctSignalPre)(void *object);
/** From CO_SRDO_initCallbackPre() or NULL */
void *functSignalObjectPre;
#endif
volatile void* CANrxNew[2];
/** true, if received SRDO is too short */
bool_t rxSrdoShort;
/** two buffers of data bytes for the received message. */
uint8_t CANrxData[2][CO_SRDO_MAX_SIZE];
/** If true, next processed SRDO message is normal (not inverted) */
bool_t nextIsNormal;
/** Extension for OD object */
OD_extension_t OD_communicationParam_ext;
/** Extension for OD object */
OD_extension_t OD_mappingParam_extension;
uint8_t CommPar_informationDirection;
uint16_t CommPar_safetyCycleTime;
uint8_t CommPar_safetyRelatedValidationTime;
uint8_t CommPar_transmissionType;
uint32_t CommPar_COB_ID1_normal;
uint32_t CommPar_COB_ID2_inverted;
}CO_SRDO_t;
#if ((CO_CONFIG_SRDO) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
/** From CO_SRDO_initCallbackPre() or NULL */
void (*pFunctSignalPre)(void* object);
/** From CO_SRDO_initCallbackPre() or NULL */
void* functSignalObjectPre;
#endif
} CO_SRDO_t;
/**
* Initialize SRDOGuard object.
*
* Function must be called in the communication reset section.
* Function must be called in the communication reset section before @CO_SRDO_init functions.
*
* @param SRDOGuard This object will be initialized.
* @param SDO SDO object.
* @param operatingState Pointer to variable indicating CANopen device NMT internal state.
* @param configurationValid Pointer to variable with the SR valid flag
* @param idx_SRDOvalid Index in Object Dictionary
* @param idx_SRDOcrc Index in Object Dictionary
* @param OD_13FE_configurationValid Pointer to _Configuration valid_ variable from Object
* dictionary (index 0x13FE).
* @param OD_13FF_safetyConfigurationSignature Pointer to _Safety configuration signature_ variable
* from Object dictionary (index 0x13FF).
* @param [out] errInfo Additional information in case of error, may be NULL.
*
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
*/
CO_ReturnError_t CO_SRDOGuard_init(
CO_SRDOGuard_t *SRDOGuard,
OD_entry_t *OD_13FE_SRDOValid,
OD_entry_t *OD_13FF_SRDOCRC,
uint32_t *errInfo);
CO_ReturnError_t CO_SRDO_init_start(CO_SRDOGuard_t* SRDOGuard, OD_entry_t* OD_13FE_configurationValid,
OD_entry_t* OD_13FF_safetyConfigurationSignature, uint32_t* errInfo);
/**
* Process operation and valid state changes.
* Finalize SRDOGuard object.
*
* @param SRDOGuard This object.
* @return uint8_t command for CO_SRDO_process().
* - bit 0 entered operational
* - bit 1 validate checksum
* Function must be called in the communication reset section after @CO_SRDO_init functions.
*
* @param SRDOGuard This object will be finalized.
*/
uint8_t CO_SRDOGuard_process(
CO_SRDOGuard_t *SRDOGuard,
bool_t NMTisOperational);
static inline void CO_SRDO_init_end(CO_SRDOGuard_t* SRDOGuard) {
SRDOGuard->configurationValid = SRDOGuard->_configurationValid;
}
/**
* Initialize SRDO object.
@ -181,44 +229,37 @@ uint8_t CO_SRDOGuard_process(
* Function must be called in the communication reset section.
*
* @param SRDO This object will be initialized.
* @param SRDO_Index OD index of this SRDO, 0 for the first.
* @param SRDOGuard SRDOGuard object.
* @param OD CANopen Object Dictionary
* @param em Emergency object.
* @param SDO SDO object.
* @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 SRDO (without NodeId).
* @param SRDOCommPar Pointer to _SRDO communication parameter_ record from Object
* @param defaultCOB_ID Default COB ID for this SRDO for plain data (without NodeId).
* @param OD_130x_SRDOCommPar Pointer to _SRDO communication parameter_ record from Object
* dictionary (index 0x1301+).
* @param SRDOMapPar Pointer to _SRDO mapping parameter_ record from Object
* @param OD_138x_SRDOMapPar Pointer to _SRDO mapping parameter_ record from Object
* dictionary (index 0x1381+).
* @param checksum
* @param idx_SRDOCommPar Index in Object Dictionary
* @param idx_SRDOMapPar Index in Object Dictionary
* @param OD_13FE_configurationValid Pointer to _Configuration valid_ variable from Object
* dictionary (index 0x13FE).
* @param OD_13FF_safetyConfigurationSignature Pointer to _Safety configuration signature_ variable
* from Object dictionary (index 0x13FF).
* @param CANdevRx CAN device used for SRDO reception.
* @param CANdevRxIdxNormal Index of receive buffer in the above CAN device.
* @param CANdevRxIdxInverted Index of receive buffer in the above CAN device.
* @param CANdevTx CAN device used for SRDO transmission.
* @param CANdevTxIdxNormal Index of transmit buffer in the above CAN device.
* @param CANdevTxIdxInverted Index of transmit buffer in the above CAN device.
* @param [out] errInfo Additional information in case of error, may be NULL.
*
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OD_PARAMETERS.
*/
CO_ReturnError_t CO_SRDO_init(
CO_SRDO_t *SRDO,
uint8_t SRDO_Index,
CO_SRDOGuard_t *SRDOGuard,
OD_t *OD,
CO_EM_t *em,
uint8_t nodeId,
uint16_t defaultCOB_ID,
OD_entry_t *SRDOCommPar,
OD_entry_t *SRDOMapPar,
CO_CANmodule_t *CANdevRx,
uint16_t CANdevRxIdxNormal,
uint16_t CANdevRxIdxInverted,
CO_CANmodule_t *CANdevTx,
uint16_t CANdevTxIdxNormal,
uint16_t CANdevTxIdxInverted,
uint32_t *errInfo);
CO_ReturnError_t CO_SRDO_init(CO_SRDO_t* SRDO, uint8_t SRDO_Index, CO_SRDOGuard_t* SRDOGuard, OD_t* OD, CO_EM_t* em,
uint8_t nodeId, uint16_t defaultCOB_ID, OD_entry_t* OD_130x_SRDOCommPar,
OD_entry_t* OD_138x_SRDOMapPar, OD_entry_t* OD_13FE_configurationValid,
OD_entry_t* OD_13FF_safetyConfigurationSignature, CO_CANmodule_t* CANdevRxNormal,
CO_CANmodule_t* CANdevRxInverted, uint16_t CANdevRxIdxNormal, uint16_t CANdevRxIdxInverted,
CO_CANmodule_t* CANdevTxNormal, CO_CANmodule_t* CANdevTxInverted,
uint16_t CANdevTxIdxNormal, uint16_t CANdevTxIdxInverted, uint32_t* errInfo);
#if ((CO_CONFIG_SRDO) & CO_CONFIG_FLAG_CALLBACK_PRE) || defined CO_DOXYGEN
/**
@ -232,58 +273,32 @@ CO_ReturnError_t CO_SRDO_init(
* @param object Pointer to object, which will be passed to pFunctSignalPre(). Can be NULL
* @param pFunctSignalPre Pointer to the callback function. Not called if NULL.
*/
void CO_SRDO_initCallbackPre(
CO_SRDO_t *SRDO,
void *object,
void (*pFunctSignalPre)(void *object));
void CO_SRDO_initCallbackPre(CO_SRDO_t* SRDO, void* object, void (*pFunctSignalPre)(void* object));
#endif
/**
* Initialize SRDO callback function.
*
* Function initializes optional callback function, that is called when SRDO enters a safe state.
* This happens when a timeout is reached or the data is inconsistent. The safe state itself is not further defined.
* One measure, for example, would be to go back to the pre-operational state
* Callback is called from CO_SRDO_process().
*
* @param SRDO This object.
* @param object Pointer to object, which will be passed to pFunctSignalSafe(). Can be NULL
* @param pFunctSignalSafe Pointer to the callback function. Not called if NULL.
*/
void CO_SRDO_initCallbackEnterSafeState(
CO_SRDO_t *SRDO,
void *object,
void (*pFunctSignalSafe)(void *object));
/**
* Send SRDO on event
*
* Sends SRDO before the next refresh timer tiggers. The message itself is send in CO_SRDO_process().
* Sends SRDO before the next refresh timer tiggers. The message itself is send
* in @CO_SRDO_process(). Note that RTOS have to trigger its processing quickly.
* After the transmission the timer is reset to the full refresh time.
*
* @param SRDO This object.
* @return CO_ReturnError_t CO_ERROR_NO if request is granted
*/
CO_ReturnError_t CO_SRDO_requestSend(
CO_SRDO_t *SRDO);
CO_ReturnError_t CO_SRDO_requestSend(CO_SRDO_t* SRDO);
/**
* Process transmitting/receiving SRDO messages.
*
* This function verifies the checksum on demand.
* This function also configures the SRDO on operation state change to operational
* Process transmitting/receiving individual SRDO message.
*
* @param SRDO This object.
* @param commands result from CO_SRDOGuard_process().
* @param timeDifference_us Time difference from previous function call in [microseconds].
* @param [out] timerNext_us info to OS.
* @param [out] timerNext_us info to OS, may be null.
* @param NMTisOperational True if this node is in NMT_OPERATIONAL state.
*
* @return CO_SRDO_state_t internal state
*/
void CO_SRDO_process(
CO_SRDO_t *SRDO,
uint8_t commands,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
CO_SRDO_state_t CO_SRDO_process(CO_SRDO_t* SRDO, uint32_t timeDifference_us, uint32_t* timerNext_us, bool_t NMTisOperational);
/** @} */ /* CO_SRDO */

177
CANopen.c
View file

@ -273,11 +273,11 @@
* number of them. Indexes are sorted in a way, that objects with highest
* priority of the CAN identifier are listed first. */
#define CO_RX_IDX_NMT_SLV 0
#define CO_RX_IDX_SYNC (CO_RX_IDX_NMT_SLV + CO_RX_CNT_NMT_SLV)
#define CO_RX_IDX_GFC (CO_RX_IDX_NMT_SLV + CO_RX_CNT_NMT_SLV)
#define CO_RX_IDX_SYNC (CO_RX_IDX_GFC + CO_RX_CNT_GFC)
#define CO_RX_IDX_EM_CONS (CO_RX_IDX_SYNC + CO_RX_CNT_SYNC)
#define CO_RX_IDX_TIME (CO_RX_IDX_EM_CONS + CO_RX_CNT_EM_CONS)
#define CO_RX_IDX_GFC (CO_RX_IDX_TIME + CO_RX_CNT_TIME)
#define CO_RX_IDX_SRDO (CO_RX_IDX_GFC + CO_RX_CNT_GFC)
#define CO_RX_IDX_SRDO (CO_RX_IDX_TIME + CO_RX_CNT_TIME)
#define CO_RX_IDX_RPDO (CO_RX_IDX_SRDO + CO_RX_CNT_SRDO * 2)
#define CO_RX_IDX_SDO_SRV (CO_RX_IDX_RPDO + CO_RX_CNT_RPDO)
#define CO_RX_IDX_SDO_CLI (CO_RX_IDX_SDO_SRV + CO_RX_CNT_SDO_SRV)
@ -289,11 +289,11 @@
#define CO_CNT_ALL_RX_MSGS (CO_RX_IDX_LSS_MST + CO_RX_CNT_LSS_MST)
#define CO_TX_IDX_NMT_MST 0
#define CO_TX_IDX_SYNC (CO_TX_IDX_NMT_MST + CO_TX_CNT_NMT_MST)
#define CO_TX_IDX_GFC (CO_TX_IDX_NMT_MST + CO_TX_CNT_NMT_MST)
#define CO_TX_IDX_SYNC (CO_TX_IDX_GFC + CO_TX_CNT_GFC)
#define CO_TX_IDX_EM_PROD (CO_TX_IDX_SYNC + CO_TX_CNT_SYNC)
#define CO_TX_IDX_TIME (CO_TX_IDX_EM_PROD + CO_TX_CNT_EM_PROD)
#define CO_TX_IDX_GFC (CO_TX_IDX_TIME + CO_TX_CNT_TIME)
#define CO_TX_IDX_SRDO (CO_TX_IDX_GFC + CO_TX_CNT_GFC)
#define CO_TX_IDX_SRDO (CO_TX_IDX_TIME + CO_TX_CNT_TIME)
#define CO_TX_IDX_TPDO (CO_TX_IDX_SRDO + CO_TX_CNT_SRDO * 2)
#define CO_TX_IDX_SDO_SRV (CO_TX_IDX_TPDO + CO_TX_CNT_TPDO)
#define CO_TX_IDX_SDO_CLI (CO_TX_IDX_SDO_SRV + CO_TX_CNT_SDO_SRV)
@ -555,6 +555,9 @@ CO_t *CO_new(CO_config_t *config, uint32_t *heapMemoryUsed) {
* highest priority of the CAN identifier are listed first. */
int16_t idxRx = 0;
co->RX_IDX_NMT_SLV = idxRx; idxRx += RX_CNT_NMT_SLV;
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
co->RX_IDX_GFC = idxRx; idxRx += RX_CNT_GFC;
#endif
#if (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE
co->RX_IDX_SYNC = idxRx; idxRx += RX_CNT_SYNC;
#endif
@ -562,9 +565,6 @@ CO_t *CO_new(CO_config_t *config, uint32_t *heapMemoryUsed) {
#if (CO_CONFIG_TIME) & CO_CONFIG_TIME_ENABLE
co->RX_IDX_TIME = idxRx; idxRx += RX_CNT_TIME;
#endif
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
co->RX_IDX_GFC = idxRx; idxRx += RX_CNT_GFC;
#endif
#if (CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE
co->RX_IDX_SRDO = idxRx; idxRx += RX_CNT_SRDO * 2;
#endif
@ -594,6 +594,9 @@ CO_t *CO_new(CO_config_t *config, uint32_t *heapMemoryUsed) {
int16_t idxTx = 0;
co->TX_IDX_NMT_MST = idxTx; idxTx += TX_CNT_NMT_MST;
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
co->TX_IDX_GFC = idxTx; idxTx += TX_CNT_GFC;
#endif
#if (CO_CONFIG_SYNC) & CO_CONFIG_SYNC_ENABLE
co->TX_IDX_SYNC = idxTx; idxTx += TX_CNT_SYNC;
#endif
@ -601,9 +604,6 @@ CO_t *CO_new(CO_config_t *config, uint32_t *heapMemoryUsed) {
#if (CO_CONFIG_TIME) & CO_CONFIG_TIME_ENABLE
co->TX_IDX_TIME = idxTx; idxTx += TX_CNT_TIME;
#endif
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
co->TX_IDX_GFC = idxTx; idxTx += TX_CNT_GFC;
#endif
#if (CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE
co->TX_IDX_SRDO = idxTx; idxTx += TX_CNT_SRDO * 2;
#endif
@ -1170,54 +1170,6 @@ CO_ReturnError_t CO_CANopenInit(CO_t *co,
}
#endif
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
if (CO_GET_CNT(GFC) == 1) {
err = CO_GFC_init(co->GFC,
&OD_globalFailSafeCommandParameter,
co->CANmodule,
CO_GET_CO(RX_IDX_GFC),
CO_CAN_ID_GFC,
co->CANmodule,
CO_GET_CO(TX_IDX_GFC),
CO_CAN_ID_GFC);
if (err) { return err; }
}
#endif
#if (CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE
if (CO_GET_CNT(SRDO) > 0) {
err = CO_SRDOGuard_init(co->SRDOGuard,
OD_GET(H13FE, OD_H13FE_SRDO_VALID),
OD_GET(H13FF, OD_H13FF_SRDO_CHECKSUM),
errInfo);
if (err) { return err; }
OD_entry_t *SRDOcomm = OD_GET(H1301, OD_H1301_SRDO_1_PARAM);
OD_entry_t *SRDOmap = OD_GET(H1381, OD_H1381_SRDO_1_MAPPING);
for (int16_t i = 0; i < CO_GET_CNT(SRDO); i++) {
uint16_t CANdevRxIdx = CO_GET_CO(RX_IDX_SRDO) + 2 * i;
uint16_t CANdevTxIdx = CO_GET_CO(TX_IDX_SRDO) + 2 * i;
err = CO_SRDO_init(&co->SRDO[i], i,
co->SRDOGuard,
od,
em,
nodeId,
((i == 0) ? CO_CAN_ID_SRDO_1 : 0),
SRDOcomm++,
SRDOmap++,
co->CANmodule,
CANdevRxIdx,
CANdevRxIdx + 1,
co->CANmodule,
CANdevTxIdx,
CANdevTxIdx + 1,
errInfo);
if (err) { return err; }
}
}
#endif
#if (CO_CONFIG_LSS) & CO_CONFIG_LSS_MASTER
if (CO_GET_CNT(LSS_MST) == 1) {
err = CO_LSSmaster_init(co->LSSmaster,
@ -1369,6 +1321,84 @@ CO_ReturnError_t CO_CANopenInitPDO(CO_t *co,
}
/******************************************************************************/
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE) || ((CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE)
CO_ReturnError_t CO_CANopenInitSRDO(CO_t *co,
CO_EM_t *em,
OD_t *od,
uint8_t nodeId,
uint32_t *errInfo)
{
if (co == NULL) {
return CO_ERROR_ILLEGAL_ARGUMENT;
}
if (nodeId < 1 || nodeId > 127 || co->nodeIdUnconfigured) {
return (co->nodeIdUnconfigured)
? CO_ERROR_NODE_ID_UNCONFIGURED_LSS : CO_ERROR_ILLEGAL_ARGUMENT;
}
#if (CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE
if (CO_GET_CNT(GFC) == 1) {
CO_ReturnError_t err;
err = CO_GFC_init(co->GFC,
OD_GET(H1300, OD_H1300_GFC_PARAM),
co->CANmodule,
CO_GET_CO(RX_IDX_GFC),
CO_CAN_ID_GFC,
co->CANmodule,
CO_GET_CO(TX_IDX_GFC),
CO_CAN_ID_GFC);
if (err) { return err; }
}
#endif
#if (CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE
if (CO_GET_CNT(SRDO) > 0) {
CO_ReturnError_t err;
err = CO_SRDO_init_start(co->SRDOGuard,
OD_GET(H13FE, OD_H13FE_SRDO_VALID),
OD_GET(H13FF, OD_H13FF_SRDO_CHECKSUM),
errInfo);
if (err) { return err; }
OD_entry_t *SRDOcomm = OD_GET(H1301, OD_H1301_SRDO_1_PARAM);
OD_entry_t *SRDOmap = OD_GET(H1381, OD_H1381_SRDO_1_MAPPING);
for (int16_t i = 0; i < CO_GET_CNT(SRDO); i++) {
uint16_t CANdevRxIdx = CO_GET_CO(RX_IDX_SRDO) + 2 * i;
uint16_t CANdevTxIdx = CO_GET_CO(TX_IDX_SRDO) + 2 * i;
err = CO_SRDO_init(&co->SRDO[i],
i,
co->SRDOGuard,
od,
em,
nodeId,
((i == 0) ? CO_CAN_ID_SRDO_1 : 0),
SRDOcomm++,
SRDOmap++,
OD_GET(H13FE, OD_H13FE_SRDO_VALID),
OD_GET(H13FF, OD_H13FF_SRDO_CHECKSUM),
co->CANmodule,
co->CANmodule,
CANdevRxIdx,
CANdevRxIdx + 1,
co->CANmodule,
co->CANmodule,
CANdevTxIdx,
CANdevTxIdx + 1,
errInfo);
if (err) { return err; }
}
CO_SRDO_init_end(co->SRDOGuard);
}
#endif
return CO_ERROR_NO;
}
#endif
/******************************************************************************/
CO_NMT_reset_cmd_t CO_process(CO_t *co,
bool_t enableGateway,
@ -1593,25 +1623,30 @@ void CO_process_TPDO(CO_t *co,
/******************************************************************************/
#if (CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE
void CO_process_SRDO(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us)
CO_SRDO_state_t CO_process_SRDO(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us)
{
if (co->nodeIdUnconfigured) {
return;
return CO_SRDO_state_unknown;
}
bool_t NMTisOperational =
CO_NMT_getInternalState(co->NMT) == CO_NMT_OPERATIONAL;
uint8_t firstOperational = CO_SRDOGuard_process(co->SRDOGuard,
NMTisOperational);
CO_SRDO_state_t lowestState = CO_SRDO_state_deleted;
for (int16_t i = 0; i < CO_GET_CNT(SRDO); i++) {
CO_SRDO_process(&co->SRDO[i],
firstOperational,
timeDifference_us,
timerNext_us);
CO_SRDO_state_t state = CO_SRDO_process(&co->SRDO[i],
timeDifference_us,
timerNext_us,
NMTisOperational);
if (state < lowestState) {
state = lowestState;
}
}
return lowestState;
}
#endif

View file

@ -261,8 +261,8 @@ typedef struct {
uint8_t CNT_SRDO;
OD_entry_t *ENTRY_H1301; /**< OD entry for @ref CO_SRDO_init() */
OD_entry_t *ENTRY_H1381; /**< OD entry for @ref CO_SRDO_init() */
OD_entry_t *ENTRY_H13FE; /**< OD entry for @ref CO_SRDOGuard_init() */
OD_entry_t *ENTRY_H13FF; /**< OD entry for @ref CO_SRDOGuard_init() */
OD_entry_t *ENTRY_H13FE; /**< OD entry for @ref CO_SRDO_init() */
OD_entry_t *ENTRY_H13FF; /**< OD entry for @ref CO_SRDO_init() */
/** Number of LSSslave objects, 0 or 1 (CANrx + CANtx). */
uint8_t CNT_LSS_SLV;
/** Number of LSSmaster objects, 0 or 1 (CANrx + CANtx). */
@ -393,8 +393,8 @@ typedef struct {
#endif
#endif
#if ((CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE) || defined CO_DOXYGEN
/** SRDO object, initialised by @ref CO_SRDOGuard_init(), single SRDOGuard
* object is included inside all SRDO objects */
/** SRDO guard object, initialised by @ref CO_SRDO_init_start(), single
* SRDOGuard object is included inside all SRDO objects */
CO_SRDOGuard_t *SRDOGuard;
/** SRDO objects, initialised by @ref CO_SRDO_init() */
CO_SRDO_t *SRDO;
@ -577,6 +577,34 @@ CO_ReturnError_t CO_CANopenInitPDO(CO_t *co,
uint32_t *errInfo);
/**
* Initialize Safety related Data Objects.
*
* Function must be called in the end of communication reset section after all
* CANopen and application initialization, otherwise some OD variables wont be
* mapped into SRDO correctly.
*
* @param co CANopen object.
* @param em Emergency object, which is used inside PDO objects for error
* reporting.
* @param od CANopen Object dictionary
* @param nodeId CANopen Node ID (1 ... 127) or 0xFF(unconfigured). If
* unconfigured, then PDO will not be initialized nor processed.
* @param [out] errInfo Additional information in case of error, may be NULL.
*
* @return CO_ERROR_NO in case of success.
*/
#if ((CO_CONFIG_GFC) & CO_CONFIG_GFC_ENABLE) || ((CO_CONFIG_SRDO) & CO_CONFIG_SRDO_ENABLE)
CO_ReturnError_t CO_CANopenInitSRDO(CO_t *co,
CO_EM_t *em,
OD_t *od,
uint8_t nodeId,
uint32_t *errInfo);
#endif
/**
* Process CANopen objects.
*
@ -682,10 +710,12 @@ void CO_process_TPDO(CO_t *co,
* @param timeDifference_us Time difference from previous function call in
* microseconds.
* @param [out] timerNext_us info to OS - see CO_process().
*
* @return @CO_SRDO_state_t lowest state of the SRDO objects.
*/
void CO_process_SRDO(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
CO_SRDO_state_t CO_process_SRDO(CO_t *co,
uint32_t timeDifference_us,
uint32_t *timerNext_us);
#endif
/** @} */ /* CO_CANopen */

View file

@ -137,7 +137,7 @@ File structure
- **crc16-ccitt.h/.c** - Calculation of CRC 16 CCITT polynomial.
- **303/** - CANopen Recommendation
- **CO_LEDs.h/.c** - CANopen LED Indicators
- **304/** - CANopen Safety (Implemented only in v1.3, not updated for the latest version).
- **304/** - CANopen Safety Related Data Object, as specified by EN 50325-5:2010
- **CO_SRDO.h/.c** - CANopen Safety-relevant Data Object protocol.
- **CO_GFC.h/.c** - CANopen Global Failsafe Command (producer and consumer).
- **305/** - CANopen layer setting services (LSS) and protocols.