1
0
Fork 0

Format the .h files using clang-format v15.

This commit is contained in:
Janez 2024-07-09 01:29:26 +02:00
parent e3b61c3630
commit 4c9505083c
7 changed files with 328 additions and 454 deletions

1
.clang-format Symbolic link
View file

@ -0,0 +1 @@
CANopenNode/.clang-format

View file

@ -28,17 +28,16 @@ extern "C" {
#endif
/**
* @defgroup CO_applicationLinux Application interface to CANopenNode
* Application interface, similar to Arduino, extended to CANopen and
* additional, realtime thread.
* @defgroup CO_applicationLinux Application interface to CANopenNode Application interface, similar to Arduino,
* extended to CANopen and additional, realtime thread.
*
* @ingroup CO_socketCAN
* @{
*/
/**
* Function is called once on the program startup, after Object dictionary
* initialization and before CANopen initialization.
* Function is called once on the program startup, after Object dictionary initialization and before CANopen
* initialization.
*
* @param [in,out] bitRate Stored CAN bit rate, can be overridden.
* @param [in,out] nodeId Stored CANopen NodeId, can be overridden.
@ -46,52 +45,44 @@ extern "C" {
*
* @return @ref CO_ReturnError_t CO_ERROR_NO in case of success.
*/
CO_ReturnError_t app_programStart(uint16_t *bitRate,
uint8_t *nodeId,
uint32_t *errInfo);
CO_ReturnError_t app_programStart(uint16_t* bitRate, uint8_t* nodeId, uint32_t* errInfo);
/**
* Function is called after CANopen communication reset.
*
* @param co CANopen object.
*/
void app_communicationReset(CO_t *co);
void app_communicationReset(CO_t* co);
/**
* Function is called just before program ends.
*/
void app_programEnd();
/**
* Function is called cyclically from main().
*
* Place for the slower code (all must be non-blocking).
*
* @warning
* Mind race conditions between this functions and app_programRt(), which
* run from the realtime thread. If accessing Object dictionary variable which
* is also mappable to PDO, it is necessary to use CO_LOCK_OD() and
* CO_UNLOCK_OD() macros from @ref CO_critical_sections.
* Mind race conditions between this functions and app_programRt(), which run from the realtime thread. If accessing
* Object dictionary variable which is also mappable to PDO, it is necessary to use CO_LOCK_OD() and CO_UNLOCK_OD()
* macros from @ref CO_critical_sections.
*
* @param co CANopen object.
* @param timer1usDiff Time difference since last call in microseconds
*/
void app_programAsync(CO_t *co, uint32_t timer1usDiff);
void app_programAsync(CO_t* co, uint32_t timer1usDiff);
/**
* Function is called cyclically from realtime thread at constant intervals.
*
* Code inside this function must be executed fast. Take care on race conditions
* with app_programAsync.
* Code inside this function must be executed fast. Take care on race conditions with app_programAsync.
*
* @param co CANopen object.
* @param timer1usDiff Time difference since last call in microseconds
*/
void app_programRt(CO_t *co, uint32_t timer1usDiff);
void app_programRt(CO_t* co, uint32_t timer1usDiff);
/** @} */ /* CO_applicationLinux */

View file

@ -20,13 +20,11 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
#ifndef CO_DRIVER_TARGET_H
#define CO_DRIVER_TARGET_H
/* This file contains device and application specific definitions.
* It is included from CO_driver.h, which contains documentation
* for common definitions below. */
/* This file contains device and application specific definitions. It is included from CO_driver.h, which contains
* documentation for common definitions below. */
#include <stddef.h>
#include <stdbool.h>
@ -49,9 +47,7 @@
extern "C" {
#endif
/* Stack configuration override default values.
* For more information see file CO_config.h. */
/* Stack configuration override default values. For more information see file CO_config.h. */
#ifdef CO_SINGLE_THREAD
#define CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE 0
#else
@ -60,37 +56,28 @@ extern "C" {
#define CO_CONFIG_GLOBAL_FLAG_TIMERNEXT CO_CONFIG_FLAG_TIMERNEXT
#ifndef CO_CONFIG_NMT
#define CO_CONFIG_NMT (CO_CONFIG_NMT_CALLBACK_CHANGE | \
CO_CONFIG_NMT_MASTER | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#define CO_CONFIG_NMT \
(CO_CONFIG_NMT_CALLBACK_CHANGE | CO_CONFIG_NMT_MASTER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#endif
#ifndef CO_CONFIG_HB_CONS
#define CO_CONFIG_HB_CONS (CO_CONFIG_HB_CONS_ENABLE | \
CO_CONFIG_HB_CONS_CALLBACK_CHANGE | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#define CO_CONFIG_HB_CONS \
(CO_CONFIG_HB_CONS_ENABLE | CO_CONFIG_HB_CONS_CALLBACK_CHANGE | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#endif
#ifndef CO_CONFIG_EM
#define CO_CONFIG_EM (CO_CONFIG_EM_PRODUCER | \
CO_CONFIG_EM_PROD_CONFIGURABLE | \
CO_CONFIG_EM_PROD_INHIBIT | \
CO_CONFIG_EM_HISTORY | \
CO_CONFIG_EM_STATUS_BITS | \
CO_CONFIG_EM_CONSUMER | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#define CO_CONFIG_EM \
(CO_CONFIG_EM_PRODUCER | CO_CONFIG_EM_PROD_CONFIGURABLE | CO_CONFIG_EM_PROD_INHIBIT | CO_CONFIG_EM_HISTORY \
| CO_CONFIG_EM_STATUS_BITS | CO_CONFIG_EM_CONSUMER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#endif
#ifndef CO_CONFIG_SDO_SRV
#define CO_CONFIG_SDO_SRV (CO_CONFIG_SDO_SRV_SEGMENTED | \
CO_CONFIG_SDO_SRV_BLOCK | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#define CO_CONFIG_SDO_SRV \
(CO_CONFIG_SDO_SRV_SEGMENTED | CO_CONFIG_SDO_SRV_BLOCK | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#endif
#ifndef CO_CONFIG_SDO_SRV_BUFFER_SIZE
@ -98,50 +85,37 @@ extern "C" {
#endif
#ifndef CO_CONFIG_SDO_CLI
#define CO_CONFIG_SDO_CLI (CO_CONFIG_SDO_CLI_ENABLE | \
CO_CONFIG_SDO_CLI_SEGMENTED | \
CO_CONFIG_SDO_CLI_BLOCK | \
CO_CONFIG_SDO_CLI_LOCAL | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | \
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#define CO_CONFIG_SDO_CLI \
(CO_CONFIG_SDO_CLI_ENABLE | CO_CONFIG_SDO_CLI_SEGMENTED | CO_CONFIG_SDO_CLI_BLOCK | CO_CONFIG_SDO_CLI_LOCAL \
| CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | CO_CONFIG_GLOBAL_FLAG_TIMERNEXT | CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#endif
#ifndef CO_CONFIG_TIME
#define CO_CONFIG_TIME (CO_CONFIG_TIME_ENABLE | \
CO_CONFIG_TIME_PRODUCER | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#define CO_CONFIG_TIME \
(CO_CONFIG_TIME_ENABLE | CO_CONFIG_TIME_PRODUCER | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_OD_DYNAMIC)
#endif
#ifndef CO_CONFIG_LSS
#define CO_CONFIG_LSS (CO_CONFIG_LSS_SLAVE | \
CO_CONFIG_LSS_SLAVE_FASTSCAN_DIRECT_RESPOND | \
CO_CONFIG_LSS_MASTER | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE)
#define CO_CONFIG_LSS \
(CO_CONFIG_LSS_SLAVE | CO_CONFIG_LSS_SLAVE_FASTSCAN_DIRECT_RESPOND | CO_CONFIG_LSS_MASTER \
| CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE)
#endif
#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | \
CO_CONFIG_GFC_CONSUMER | \
CO_CONFIG_GFC_PRODUCER)
#define CO_CONFIG_GFC (CO_CONFIG_GFC_ENABLE | CO_CONFIG_GFC_CONSUMER | CO_CONFIG_GFC_PRODUCER)
#define CO_CONFIG_SRDO (CO_CONFIG_SRDO_ENABLE | \
CO_CONFIG_SRDO_CHECK_TX | \
CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE | \
CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#define CO_CONFIG_SRDO \
(CO_CONFIG_SRDO_ENABLE | CO_CONFIG_SRDO_CHECK_TX | CO_CONFIG_GLOBAL_FLAG_CALLBACK_PRE \
| CO_CONFIG_GLOBAL_FLAG_TIMERNEXT)
#ifndef CO_CONFIG_GTW
#define CO_CONFIG_GTW (CO_CONFIG_GTW_ASCII | \
CO_CONFIG_GTW_ASCII_SDO | \
CO_CONFIG_GTW_ASCII_NMT | \
CO_CONFIG_GTW_ASCII_LSS | \
CO_CONFIG_GTW_ASCII_LOG | \
CO_CONFIG_GTW_ASCII_ERROR_DESC | \
CO_CONFIG_GTW_ASCII_PRINT_HELP | \
CO_CONFIG_GTW_ASCII_PRINT_LEDS)
#define CO_CONFIG_GTW_BLOCK_DL_LOOP 3
#define CO_CONFIG_GTW \
(CO_CONFIG_GTW_ASCII | CO_CONFIG_GTW_ASCII_SDO | CO_CONFIG_GTW_ASCII_NMT | CO_CONFIG_GTW_ASCII_LSS \
| CO_CONFIG_GTW_ASCII_LOG | CO_CONFIG_GTW_ASCII_ERROR_DESC | CO_CONFIG_GTW_ASCII_PRINT_HELP \
| CO_CONFIG_GTW_ASCII_PRINT_LEDS)
#define CO_CONFIG_GTW_BLOCK_DL_LOOP 3
#define CO_CONFIG_GTWA_COMM_BUF_SIZE 2000
#define CO_CONFIG_GTWA_LOG_BUF_SIZE 10000
#define CO_CONFIG_GTWA_LOG_BUF_SIZE 10000
#endif
#ifndef CO_CONFIG_CRC16
@ -149,14 +123,11 @@ extern "C" {
#endif
#ifndef CO_CONFIG_FIFO
#define CO_CONFIG_FIFO (CO_CONFIG_FIFO_ENABLE | \
CO_CONFIG_FIFO_ALT_READ | \
CO_CONFIG_FIFO_CRC16_CCITT | \
CO_CONFIG_FIFO_ASCII_COMMANDS | \
CO_CONFIG_FIFO_ASCII_DATATYPES)
#define CO_CONFIG_FIFO \
(CO_CONFIG_FIFO_ENABLE | CO_CONFIG_FIFO_ALT_READ | CO_CONFIG_FIFO_CRC16_CCITT | CO_CONFIG_FIFO_ASCII_COMMANDS \
| CO_CONFIG_FIFO_ASCII_DATATYPES)
#endif
/* Print debug info from some internal parts of the stack */
#if (CO_CONFIG_DEBUG) & CO_CONFIG_DEBUG_COMMON
#include <stdio.h>
@ -164,7 +135,6 @@ extern "C" {
#define CO_DEBUG_COMMON(msg) log_printf(LOG_DEBUG, DBG_CO_DEBUG, msg);
#endif
/**
* @defgroup CO_socketCAN_driver_target CO_driver_target.h
* Linux socketCAN specific @ref CO_driver definitions for CANopenNode.
@ -176,18 +146,14 @@ extern "C" {
/**
* Multi interface support
*
* Enable this to use interface combining at driver level. This
* adds functions to broadcast/selective transmit messages on the
* given interfaces as well as combining all received message into
* one queue.
* Enable this to use interface combining at driver level. This adds functions to broadcast/selective transmit messages
* on the given interfaces as well as combining all received message into one queue.
*
* If CO_DRIVER_MULTI_INTERFACE is set to 0, then CO_CANmodule_init()
* adds single socketCAN interface specified by CANptr argument. In case of
* failure, CO_CANmodule_init() returns CO_ERROR_SYSCALL.
* If CO_DRIVER_MULTI_INTERFACE is set to 0, then CO_CANmodule_init() adds single socketCAN interface specified by
* CANptr argument. In case of failure, CO_CANmodule_init() returns CO_ERROR_SYSCALL.
*
* If CO_DRIVER_MULTI_INTERFACE is set to 1, then CO_CANmodule_init()
* ignores CANptr argument. Interfaces must be added by
* CO_CANmodule_addInterface() function after CO_CANmodule_init().
* If CO_DRIVER_MULTI_INTERFACE is set to 1, then CO_CANmodule_init() ignores CANptr argument. Interfaces must be added
* by CO_CANmodule_addInterface() function after CO_CANmodule_init().
*
* Macro is set to 0 (disabled) by default. It can be overridden.
*
@ -200,16 +166,15 @@ extern "C" {
/**
* CAN bus error reporting
*
* CO_DRIVER_ERROR_REPORTING enabled adds support for socketCAN error detection
* and handling functions inside the driver. This is needed when you have
* CANopen with "0" connected nodes as a use case, as this is normally
* forbidden in CAN.
* CO_DRIVER_ERROR_REPORTING enabled adds support for socketCAN error detection and handling functions inside the
* driver. This is needed when you have CANopen with "0" connected nodes as a use case, as this is normally forbidden
* in CAN.
*
* Macro is set to 1 (enabled) by default. It can be overridden.
*
* you need to enable error reporting in your kernel driver using:
* @code{.sh}
* ip link set canX type can berr-reporting on
ip link set canX type can berr-reporting on
* @endcode
* Of course, the kernel driver for your hardware needs this functionality to be
* implemented...
@ -224,25 +189,24 @@ extern "C" {
/* Basic definitions */
#ifdef __BYTE_ORDER
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define CO_LITTLE_ENDIAN
#define CO_SWAP_16(x) x
#define CO_SWAP_32(x) x
#define CO_SWAP_64(x) x
#define CO_LITTLE_ENDIAN
#define CO_SWAP_16(x) x
#define CO_SWAP_32(x) x
#define CO_SWAP_64(x) x
#else
#define CO_BIG_ENDIAN
#include <byteswap.h>
#define CO_SWAP_16(x) bswap_16(x)
#define CO_SWAP_32(x) bswap_32(x)
#define CO_SWAP_64(x) bswap_64(x)
#define CO_BIG_ENDIAN
#include <byteswap.h>
#define CO_SWAP_16(x) bswap_16(x)
#define CO_SWAP_32(x) bswap_32(x)
#define CO_SWAP_64(x) bswap_64(x)
#endif
#endif
/* NULL is defined in stddef.h */
/* true and false are defined in stdbool.h */
/* int8_t to uint64_t are defined in stdint.h */
typedef uint_fast8_t bool_t;
typedef float float32_t;
typedef double float64_t;
typedef uint_fast8_t bool_t;
typedef float float32_t;
typedef double float64_t;
/* CAN receive message structure as aligned in socketCAN. */
typedef struct {
@ -253,57 +217,59 @@ typedef struct {
} CO_CANrxMsg_t;
/* Access to received CAN message */
static inline uint16_t CO_CANrxMsg_readIdent(void *rxMsg) {
CO_CANrxMsg_t *rxMsgCasted = (CO_CANrxMsg_t *)rxMsg;
return (uint16_t) (rxMsgCasted->ident & CAN_SFF_MASK);
}
static inline uint8_t CO_CANrxMsg_readDLC(void *rxMsg) {
CO_CANrxMsg_t *rxMsgCasted = (CO_CANrxMsg_t *)rxMsg;
return (uint8_t) (rxMsgCasted->DLC);
}
static inline uint8_t *CO_CANrxMsg_readData(void *rxMsg) {
CO_CANrxMsg_t *rxMsgCasted = (CO_CANrxMsg_t *)rxMsg;
return (uint8_t *) (rxMsgCasted->data);
static inline uint16_t
CO_CANrxMsg_readIdent(void* rxMsg) {
CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
return (uint16_t)(rxMsgCasted->ident & CAN_SFF_MASK);
}
static inline uint8_t
CO_CANrxMsg_readDLC(void* rxMsg) {
CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
return (uint8_t)(rxMsgCasted->DLC);
}
static inline uint8_t*
CO_CANrxMsg_readData(void* rxMsg) {
CO_CANrxMsg_t* rxMsgCasted = (CO_CANrxMsg_t*)rxMsg;
return (uint8_t*)(rxMsgCasted->data);
}
/* Received message object */
typedef struct {
uint32_t ident;
uint32_t mask;
void *object;
void (*CANrx_callback)(void *object, void *message);
void* object;
void (*CANrx_callback)(void* object, void* message);
int can_ifindex; /* CAN Interface index from last message */
struct timespec timestamp; /* time of reception of last message */
struct timespec timestamp; /* time of reception of last message */
} CO_CANrx_t;
/* Transmit message object as aligned in socketCAN. */
typedef struct {
uint32_t ident;
uint8_t DLC;
uint8_t padding[3]; /* ensure alignment */
uint8_t padding[3]; /* ensure alignment */
uint8_t data[8];
volatile bool_t bufferFull;
volatile bool_t syncFlag; /* info about transmit message */
int can_ifindex; /* CAN Interface index to use */
volatile bool_t syncFlag; /* info about transmit message */
int can_ifindex; /* CAN Interface index to use */
} CO_CANtx_t;
/* Max COB ID for standard frame format */
#define CO_CAN_MSG_SFF_MAX_COB_ID (1 << CAN_SFF_ID_BITS)
/* CAN interface object (CANptr), passed to CO_CANinit() */
typedef struct {
int can_ifindex; /* CAN Interface index */
int epoll_fd; /* File descriptor for epoll, which waits for
CAN receive event */
int can_ifindex; /* CAN Interface index */
int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
} CO_CANptrSocketCan_t;
/* socketCAN interface object */
typedef struct {
int can_ifindex; /* CAN Interface index */
char ifName[IFNAMSIZ]; /* CAN Interface name */
int fd; /* socketCAN file descriptor */
int can_ifindex; /* CAN Interface index */
char ifName[IFNAMSIZ]; /* CAN Interface name */
int fd; /* socketCAN file descriptor */
#if CO_DRIVER_ERROR_REPORTING > 0 || defined CO_DOXYGEN
CO_CANinterfaceErrorhandler_t errorhandler;
#endif
@ -311,30 +277,26 @@ typedef struct {
/* CAN module object */
typedef struct {
/* List of can interfaces. From CO_CANmodule_init() or one per
* CO_CANmodule_addInterface() call */
CO_CANinterface_t *CANinterfaces;
/* List of can interfaces. From CO_CANmodule_init() or one per CO_CANmodule_addInterface() call */
CO_CANinterface_t* CANinterfaces;
uint32_t CANinterfaceCount; /* interface count */
CO_CANrx_t *rxArray;
CO_CANrx_t* rxArray;
uint16_t rxSize;
struct can_filter *rxFilter;/* socketCAN filter list, one per rx buffer */
uint32_t rxDropCount; /* messages dropped on rx socket queue */
CO_CANtx_t *txArray;
struct can_filter* rxFilter; /* socketCAN filter list, one per rx buffer */
uint32_t rxDropCount; /* messages dropped on rx socket queue */
CO_CANtx_t* txArray;
uint16_t txSize;
uint16_t CANerrorStatus;
volatile bool_t CANnormal;
volatile uint16_t CANtxCount;
int epoll_fd; /* File descriptor for epoll, which waits for
CAN receive event */
int epoll_fd; /* File descriptor for epoll, which waits for CAN receive event */
#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
/* Lookup tables Cob ID to rx/tx array index.
* Only feasible for SFF Messages. */
/* Lookup tables Cob ID to rx/tx array index. Only feasible for SFF Messages. */
uint32_t rxIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
uint32_t txIdentToIndex[CO_CAN_MSG_SFF_MAX_COB_ID];
#endif
} CO_CANmodule_t;
/* Data storage: Maximum file name length including path */
#ifndef CO_STORAGE_PATH_MAX
#define CO_STORAGE_PATH_MAX 255
@ -342,26 +304,28 @@ typedef struct {
/* Data storage object for one entry */
typedef struct {
void *addr;
void* addr;
size_t len;
uint8_t subIndexOD;
uint8_t attr;
/* Name of the file, where data block is stored */
char filename[CO_STORAGE_PATH_MAX];
/* CRC checksum of the data stored previously, for auto storage */
uint16_t crc;
/* Pointer to opened file, for auto storage */
FILE *fp;
char filename[CO_STORAGE_PATH_MAX]; /* Name of the file, where data block is stored */
uint16_t crc; /* CRC checksum of the data stored previously, for auto storage */
FILE* fp; /* Pointer to opened file, for auto storage */
} CO_storage_entry_t;
#ifdef CO_SINGLE_THREAD
#define CO_LOCK_CAN_SEND(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_UNLOCK_CAN_SEND(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_LOCK_EMCY(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_UNLOCK_EMCY(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_LOCK_OD(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_UNLOCK_OD(CAN_MODULE) {(void) CAN_MODULE;}
#define CO_LOCK_CAN_SEND(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_UNLOCK_CAN_SEND(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_LOCK_EMCY(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_UNLOCK_EMCY(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_LOCK_OD(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_UNLOCK_OD(CAN_MODULE) \
{ (void)CAN_MODULE; }
#define CO_MemoryBarrier()
#else
@ -371,37 +335,53 @@ typedef struct {
/* (un)lock critical section in CO_errorReport() or CO_errorReset() */
extern pthread_mutex_t CO_EMCY_mutex;
static inline int CO_LOCK_EMCY(CO_CANmodule_t *CANmodule) {
static inline int
CO_LOCK_EMCY(CO_CANmodule_t* CANmodule) {
(void)CANmodule;
return pthread_mutex_lock(&CO_EMCY_mutex);
}
static inline void CO_UNLOCK_EMCY(CO_CANmodule_t *CANmodule) {
static inline void
CO_UNLOCK_EMCY(CO_CANmodule_t* CANmodule) {
(void)CANmodule;
(void)pthread_mutex_unlock(&CO_EMCY_mutex);
}
/* (un)lock critical section when accessing Object Dictionary */
extern pthread_mutex_t CO_OD_mutex;
static inline int CO_LOCK_OD(CO_CANmodule_t *CANmodule) {
static inline int
CO_LOCK_OD(CO_CANmodule_t* CANmodule) {
(void)CANmodule;
return pthread_mutex_lock(&CO_OD_mutex);
}
static inline void CO_UNLOCK_OD(CO_CANmodule_t *CANmodule) {
static inline void
CO_UNLOCK_OD(CO_CANmodule_t* CANmodule) {
(void)CANmodule;
(void)pthread_mutex_unlock(&CO_OD_mutex);
}
/* Synchronization between CAN receive and message processing threads. */
#define CO_MemoryBarrier() {__sync_synchronize();}
#define CO_MemoryBarrier() \
{ __sync_synchronize(); }
#endif /* CO_SINGLE_THREAD */
#define CO_FLAG_READ(rxNew) ((rxNew) != NULL)
#define CO_FLAG_SET(rxNew) {CO_MemoryBarrier(); rxNew = (void*)1L;}
#define CO_FLAG_CLEAR(rxNew) {CO_MemoryBarrier(); rxNew = NULL;}
#define CO_FLAG_SET(rxNew) \
{ \
CO_MemoryBarrier(); \
rxNew = (void*)1L; \
}
#define CO_FLAG_CLEAR(rxNew) \
{ \
CO_MemoryBarrier(); \
rxNew = NULL; \
}
#endif /* #ifndef CO_DOXYGEN */
#if CO_DRIVER_MULTI_INTERFACE > 0 || defined CO_DOXYGEN
/**
* Add socketCAN interface to can driver
@ -410,40 +390,34 @@ static inline void CO_UNLOCK_OD(CO_CANmodule_t *CANmodule) {
*
* @param CANmodule This object will be initialized.
* @param can_ifindex CAN Interface index
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
* CO_ERROR_SYSCALL or CO_ERROR_INVALID_STATE.
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT, CO_ERROR_SYSCALL or CO_ERROR_INVALID_STATE.
*/
CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule,
int can_ifindex);
CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t* CANmodule, int can_ifindex);
/**
* Check on which interface the last message for one message buffer was received
*
* It is in the responsibility of the user to check that this information is
* useful as some messages can be received at any time on any bus.
* It is in the responsibility of the user to check that this information is useful as some messages can be received at
* any time on any bus.
*
* @param CANmodule This object.
* @param ident 11-bit standard CAN Identifier.
* @param [out] CANptrRx message was received on this interface
* @param [out] timestamp message was received at this time (system clock)
*
* @retval false message has never been received, therefore no base address
* and timestamp are available
* @retval false message has never been received, therefore no base address and timestamp are available
* @retval true base address and timestamp are valid
*/
bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule,
uint16_t ident,
const void **const CANptrRx,
struct timespec *timestamp);
bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t* CANmodule, uint16_t ident, const void** const CANptrRx,
struct timespec* timestamp);
/**
* Set which interface should be used for message buffer transmission
*
* It is in the responsibility of the user to ensure that the correct interface
* is used. Some messages need to be transmitted on all interfaces.
* It is in the responsibility of the user to ensure that the correct interface is used. Some messages need to be
* transmitted on all interfaces.
*
* If given interface is unknown or NULL is used, a message is transmitted on
* all available interfaces.
* If given interface is unknown or NULL is used, a message is transmitted on all available interfaces.
*
* @param CANmodule This object.
* @param ident 11-bit standard CAN Identifier.
@ -451,40 +425,31 @@ bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule,
*
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
*/
CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t *CANmodule,
uint16_t ident,
const void *CANptrTx);
CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t* CANmodule, uint16_t ident, const void* CANptrTx);
#endif /* CO_DRIVER_MULTI_INTERFACE */
/**
* Receives CAN messages from matching epoll event
*
* This function verifies, if epoll event matches event from any CANinterface.
* In case of match, message is read from CAN and pre-processed for CANopenNode
* objects. CAN error frames are also processed.
* This function verifies, if epoll event matches event from any CANinterface. In case of match, message is read from
* CAN and pre-processed for CANopenNode objects. CAN error frames are also processed.
*
* In case of CAN message function searches _rxArray_ from CO_CANmodule_t and
* if matched it calls the corresponding CANrx_callback, optionally copies
* received CAN message to _buffer_ and returns index of matched _rxArray_.
* In case of CAN message function searches _rxArray_ from CO_CANmodule_t and if matched it calls the corresponding
* CANrx_callback, optionally copies received CAN message to _buffer_ and returns index of matched _rxArray_.
*
* This function can be used in two ways, which can be combined:
* - automatic mode: If CANrx_callback is specified for matched _rxArray_, then
* calls its callback.
* - automatic mode: If CANrx_callback is specified for matched _rxArray_, then calls its callback.
* - manual mode: evaluate message filters, return received message
*
* @param CANmodule This object.
* @param ev Epoll event, which vill be verified for matches.
* @param [out] buffer Storage for received message or _NULL_ if not used.
* @param [out] msgIndex Index of received message in array from CO_CANmodule_t
* _rxArray_, copy of CAN message is available in _buffer_.
* @param [out] msgIndex Index of received message in array from CO_CANmodule_t _rxArray_, copy of CAN message is
* available in _buffer_.
*
* @return True, if epoll event matches any CAN interface.
*/
bool_t CO_CANrxFromEpoll(CO_CANmodule_t *CANmodule,
struct epoll_event *ev,
CO_CANrxMsg_t *buffer,
int32_t *msgIndex);
bool_t CO_CANrxFromEpoll(CO_CANmodule_t* CANmodule, struct epoll_event* ev, CO_CANrxMsg_t* buffer, int32_t* msgIndex);
/** @} */

View file

@ -39,21 +39,18 @@ extern "C" {
* Linux specific interface to CANopenNode.
*
* @{
* Linux includes CAN interface inside its kernel, so called SocketCAN. It
* operates as a network device. For more information on Linux SocketCAN see
* https://www.kernel.org/doc/html/latest/networking/can.html
* Linux includes CAN interface inside its kernel, so called SocketCAN. It operates as a network device. For more
* information on Linux SocketCAN see https://www.kernel.org/doc/html/latest/networking/can.html
*
* Linux specific files for interfacing with Linux SocketCAN are located inside
* "CANopenNode/socketCAN" directory.
* Linux specific files for interfacing with Linux SocketCAN are located inside "CANopenNode/socketCAN" directory.
*
* CANopenNode runs as a set of non-blocking functions. It can run in single or
* multiple threads. Best approach for RT IO device can be with two threads:
* - timer based real-time thread for CAN receive, SYNC and PDO, see
* @ref CO_epoll_processRT()
* CANopenNode runs as a set of non-blocking functions. It can run in single or multiple threads. Best approach for RT
* IO device can be with two threads:
* - timer based real-time thread for CAN receive, SYNC and PDO, see @ref CO_epoll_processRT()
* - mainline thread for other processing, see @ref CO_epoll_processMain()
*
* Main references for Linux functions used here are Linux man pages and the
* book: The Linux Programming Interface by Michael Kerrisk.
* Main references for Linux functions used here are Linux man pages and the book: The Linux Programming Interface by
* Michael Kerrisk.
* @}
*/
@ -63,55 +60,39 @@ extern "C" {
*
* @ingroup CO_socketCAN
* @{
* The Linux epoll API performs a monitoring multiple file descriptors to see
* if I/O is possible on any of them.
* The Linux epoll API performs a monitoring multiple file descriptors to see if I/O is possible on any of them.
*
* CANopenNode uses epoll interface to provide an event based mechanism. Epoll
* waits for multiple different events, such as: interval timer event,
* notification event, CAN receive event or socket based event for gateway.
* CANopenNode non-blocking functions are processed after each event.
* CANopenNode uses epoll interface to provide an event based mechanism. Epoll waits for multiple different events, such
* as: interval timer event, notification event, CAN receive event or socket based event for gateway. CANopenNode
* non-blocking functions are processed after each event.
*
* CANopenNode itself offers functionality for calculation of time, when next
* interval timer event should trigger the processing. It can also trigger
* notification events in case of multi-thread operation.
* CANopenNode itself offers functionality for calculation of time, when next interval timer event should trigger the
* processing. It can also trigger notification events in case of multi-thread operation.
*/
/**
* Object for epoll, timer and event API.
*/
typedef struct {
/** Epoll file descriptor */
int epoll_fd;
/** Notification event file descriptor */
int event_fd;
/** Interval timer file descriptor */
int timer_fd;
/** Interval of the timer in microseconds, from @ref CO_epoll_create() */
uint32_t timerInterval_us;
/** Time difference since last @ref CO_epoll_wait() execution in
* microseconds */
uint32_t timeDifference_us;
/** Timer value in microseconds, which can be changed by application and can
* shorten time of next @ref CO_epoll_wait() execution */
uint32_t timerNext_us;
/** True,if timer event is inside @ref CO_epoll_wait() */
bool_t timerEvent;
/** time value from the last process call in microseconds */
uint64_t previousTime_us;
/** Structure for timerfd */
struct itimerspec tm;
/** Structure for epoll_wait */
struct epoll_event ev;
/** true, if new epoll event is necessary to process */
bool_t epoll_new;
int epoll_fd; /**< Epoll file descriptor */
int event_fd; /**< Notification event file descriptor */
int timer_fd; /**< Interval timer file descriptor */
uint32_t timerInterval_us; /**< Interval of the timer in microseconds, from @ref CO_epoll_create() */
uint32_t timeDifference_us; /**< Time difference since last @ref CO_epoll_wait() execution in microseconds */
uint32_t timerNext_us; /**< Timer value in microseconds, which can be changed by application and can shorten
time of next @ref CO_epoll_wait() execution */
bool_t timerEvent; /**< True,if timer event is inside @ref CO_epoll_wait() */
uint64_t previousTime_us; /**< time value from the last process call in microseconds */
struct itimerspec tm; /**< Structure for timerfd */
struct epoll_event ev; /**< Structure for epoll_wait */
bool_t epoll_new; /**< true, if new epoll event is necessary to process */
} CO_epoll_t;
/**
* Create Linux epoll, timerfd and eventfd
*
* Create and configure multiple Linux notification facilities, which trigger
* execution of the task. Epoll blocks and monitors multiple file descriptors,
* timerfd triggers in constant timer intervals and eventfd triggers on external
* Create and configure multiple Linux notification facilities, which trigger execution of the task. Epoll blocks and
* monitors multiple file descriptors, timerfd triggers in constant timer intervals and eventfd triggers on external
* signal.
*
* @param ep This object
@ -119,38 +100,35 @@ typedef struct {
*
* @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_SYSCALL.
*/
CO_ReturnError_t CO_epoll_create(CO_epoll_t *ep, uint32_t timerInterval_us);
CO_ReturnError_t CO_epoll_create(CO_epoll_t* ep, uint32_t timerInterval_us);
/**
* Close epoll, timerfd and eventfd
*
* @param ep This object
*/
void CO_epoll_close(CO_epoll_t *ep);
void CO_epoll_close(CO_epoll_t* ep);
/**
* Wait for an epoll event
*
* This function blocks until event registered on epoll: timerfd, eventfd, or
* application specified event. Function also calculates timeDifference_us since
* last call and prepares timerNext_us.
* This function blocks until event registered on epoll: timerfd, eventfd, or application specified event. Function also
* calculates timeDifference_us since last call and prepares timerNext_us.
*
* @param ep This object
*/
void CO_epoll_wait(CO_epoll_t *ep);
void CO_epoll_wait(CO_epoll_t* ep);
/**
* Closing function for an epoll event
*
* This function must be called after @ref CO_epoll_wait(). Between them
* should be application specified processing functions, which can check for
* own events and do own processing. Application may also lower timerNext_us
* variable. If lowered, then interval timer will be reconfigured and
* @ref CO_epoll_wait() will be triggered earlier.
* This function must be called after @ref CO_epoll_wait(). Between them should be application specified processing
* functions, which can check for own events and do own processing. Application may also lower timerNext_us variable. If
* lowered, then interval timer will be reconfigured and @ref CO_epoll_wait() will be triggered earlier.
*
* @param ep This object
*/
void CO_epoll_processLast(CO_epoll_t *ep);
void CO_epoll_processLast(CO_epoll_t* ep);
/**
* Initialization of functions in CANopen reset-communication section
@ -160,52 +138,41 @@ void CO_epoll_processLast(CO_epoll_t *ep);
* @param ep This object
* @param co CANopen object
*/
void CO_epoll_initCANopenMain(CO_epoll_t *ep, CO_t *co);
void CO_epoll_initCANopenMain(CO_epoll_t* ep, CO_t* co);
/**
* Process CANopen mainline functions
*
* This function calls @ref CO_process(). It is non-blocking and should execute
* cyclically. It should be between @ref CO_epoll_wait() and
* @ref CO_epoll_processLast() functions.
* This function calls @ref CO_process(). It is non-blocking and should execute cyclically. It should be between @ref
* CO_epoll_wait() and @ref CO_epoll_processLast() functions.
*
* @param ep This object
* @param co CANopen object
* @param enableGateway If true, gateway to external world will be enabled.
* @param [out] reset Return from @ref CO_process().
*/
void CO_epoll_processMain(CO_epoll_t *ep,
CO_t *co,
bool_t enableGateway,
CO_NMT_reset_cmd_t *reset);
void CO_epoll_processMain(CO_epoll_t* ep, CO_t* co, bool_t enableGateway, CO_NMT_reset_cmd_t* reset);
/**
* Process CAN receive and realtime functions
*
* This function checks epoll for CAN receive event and processes CANopen
* realtime functions: @ref CO_process_SYNC(), @ref CO_process_RPDO() and
* @ref CO_process_TPDO(). It is non-blocking and should execute cyclically.
* It should be between @ref CO_epoll_wait() and @ref CO_epoll_processLast()
* functions.
* This function checks epoll for CAN receive event and processes CANopen realtime functions: @ref CO_process_SYNC(),
* @ref CO_process_RPDO() and @ref CO_process_TPDO(). It is non-blocking and should execute cyclically. It should be
* between @ref CO_epoll_wait() and @ref CO_epoll_processLast() functions.
*
* Function can be used in the mainline thread or in own realtime thread.
*
* Processing of CANopen realtime functions is protected with @ref CO_LOCK_OD.
* Also Node-Id must be configured and CANmodule must be in CANnormal for
* processing.
* Processing of CANopen realtime functions is protected with @ref CO_LOCK_OD. Also Node-Id must be configured and
* CANmodule must be in CANnormal for processing.
*
* @param ep Pointer to @ref CO_epoll_t object.
* @param co CANopen object
* @param realtime Set to true, if function is called from the own realtime
* thread, and is executed at short constant interval.
* @param realtime Set to true, if function is called from the own realtime thread, and is executed at short constant
* interval.
*/
void CO_epoll_processRT(CO_epoll_t *ep,
CO_t *co,
bool_t realtime);
void CO_epoll_processRT(CO_epoll_t* ep, CO_t* co, bool_t realtime);
#if ((CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII) || defined CO_DOXYGEN
#if ((CO_CONFIG_GTW)&CO_CONFIG_GTW_ASCII) || defined CO_DOXYGEN
/**
* Command interface type for gateway-ascii
*/
@ -221,30 +188,20 @@ typedef enum {
* Object for gateway
*/
typedef struct {
/** Epoll file descriptor, from @ref CO_epoll_createGtw() */
int epoll_fd;
/** Command interface type or tcp port number, see
* @ref CO_commandInterface_t */
int32_t commandInterface;
/** Socket timeout in microseconds */
uint32_t socketTimeout_us;
/** Socket timeout timer in microseconds */
uint32_t socketTimeoutTmr_us;
/** Path in case of local socket */
char *localSocketPath;
/** Gateway socket file descriptor */
int gtwa_fdSocket;
/** Gateway io stream file descriptor */
int gtwa_fd;
/** Indication of fresh command */
bool_t freshCommand;
int epoll_fd; /**< Epoll file descriptor, from @ref CO_epoll_createGtw() */
int32_t commandInterface; /**< Command interface type or tcp port number, see @ref CO_commandInterface_t */
uint32_t socketTimeout_us; /**< Socket timeout in microseconds */
uint32_t socketTimeoutTmr_us; /**< Socket timeout timer in microseconds */
char* localSocketPath; /**< Path in case of local socket */
int gtwa_fdSocket; /**< Gateway socket file descriptor */
int gtwa_fd; /**< Gateway io stream file descriptor */
bool_t freshCommand; /**< Indication of fresh command */
} CO_epoll_gtw_t;
/**
* Create socket for gateway-ascii command interface and add it to epoll
*
* Depending on arguments function configures stdio interface or local socket
* or IP socket.
* Depending on arguments function configures stdio interface or local socket or IP socket.
*
* @param epGtw This object
* @param epoll_fd Already configured epoll file descriptor
@ -254,18 +211,15 @@ typedef struct {
*
* @return @ref CO_ReturnError_t CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_SYSCALL.
*/
CO_ReturnError_t CO_epoll_createGtw(CO_epoll_gtw_t *epGtw,
int epoll_fd,
int32_t commandInterface,
uint32_t socketTimeout_ms,
char *localSocketPath);
CO_ReturnError_t CO_epoll_createGtw(CO_epoll_gtw_t* epGtw, int epoll_fd, int32_t commandInterface,
uint32_t socketTimeout_ms, char* localSocketPath);
/**
* Close gateway-ascii sockets
*
* @param epGtw This object
*/
void CO_epoll_closeGtw(CO_epoll_gtw_t *epGtw);
void CO_epoll_closeGtw(CO_epoll_gtw_t* epGtw);
/**
* Initialization of gateway functions in CANopen reset-communication section
@ -273,22 +227,19 @@ void CO_epoll_closeGtw(CO_epoll_gtw_t *epGtw);
* @param epGtw This object
* @param co CANopen object
*/
void CO_epoll_initCANopenGtw(CO_epoll_gtw_t *epGtw, CO_t *co);
void CO_epoll_initCANopenGtw(CO_epoll_gtw_t* epGtw, CO_t* co);
/**
* Process CANopen gateway functions
*
* This function checks for epoll events and verifies socket connection timeout.
* It is non-blocking and should execute cyclically. It should be between
* @ref CO_epoll_wait() and @ref CO_epoll_processLast() functions.
* This function checks for epoll events and verifies socket connection timeout. It is non-blocking and should execute
* cyclically. It should be between @ref CO_epoll_wait() and @ref CO_epoll_processLast() functions.
*
* @param epGtw This object
* @param co CANopen object
* @param ep Pointer to @ref CO_epoll_t object.
*/
void CO_epoll_processGtw(CO_epoll_gtw_t *epGtw,
CO_t *co,
CO_epoll_t *ep);
void CO_epoll_processGtw(CO_epoll_gtw_t* epGtw, CO_t* co, CO_epoll_t* ep);
#endif /* (CO_CONFIG_GTW) & CO_CONFIG_GTW_ASCII */
/** @} */

View file

@ -19,7 +19,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
#ifndef CO_ERROR_H
#define CO_ERROR_H
@ -30,9 +29,9 @@
#include <net/if.h>
#if __has_include("CO_error_custom.h")
#include "CO_error_custom.h"
#include "CO_error_custom.h"
#else
#include "CO_error_msgs.h"
#include "CO_error_msgs.h"
#endif
#ifdef __cplusplus
@ -50,24 +49,21 @@ extern "C" {
/**
* Message logging function.
*
* Function must be defined by application. It should record log message to some
* place, for example syslog() call in Linux or logging functionality in
* CANopen gateway @ref CO_CANopen_309_3.
* Function must be defined by application. It should record log message to some place, for example syslog() call in
* Linux or logging functionality in CANopen gateway @ref CO_CANopen_309_3.
*
* By default system stores messages in /var/log/syslog file.
* Log can optionally be configured before, for example to filter out less
* critical errors than LOG_NOTICE, specify program name, print also process PID
* and print also to standard error, set 'user' type of program, use:
* By default system stores messages in /var/log/syslog file. Log can optionally be configured before, for example to
* filter out less critical errors than LOG_NOTICE, specify program name, print also process PID and print also to
* standard error, set 'user' type of program, use:
* @code
* setlogmask (LOG_UPTO (LOG_NOTICE));
* openlog ("exampleprog", LOG_PID | LOG_PERROR, LOG_USER);
setlogmask (LOG_UPTO (LOG_NOTICE));
openlog ("exampleprog", LOG_PID | LOG_PERROR, LOG_USER);
* @endcode
*
* @param priority one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG
* @param format format string as in printf
*/
void log_printf(int priority, const char *format, ...);
void log_printf(int priority, const char* format, ...);
/**
* driver interface state
@ -78,42 +74,36 @@ void log_printf(int priority, const char *format, ...);
* - bus off (no influence on bus)
*/
typedef enum {
CO_INTERFACE_ACTIVE, /**< CAN error passive/active */
CO_INTERFACE_LISTEN_ONLY, /**< CAN error passive/active, but currently no other device on bus */
CO_INTERFACE_BUS_OFF /**< CAN bus off */
CO_INTERFACE_ACTIVE, /**< CAN error passive/active */
CO_INTERFACE_LISTEN_ONLY, /**< CAN error passive/active, but currently no other device on bus */
CO_INTERFACE_BUS_OFF /**< CAN bus off */
} CO_CANinterfaceState_t;
/**
* This is how many NO-ACKs need to be received in a row to assume
* that no other nodes are connected to a bus and therefore are
* assuming listen-only
* This is how many NO-ACKs need to be received in a row to assume that no other nodes are connected to a bus and
* therefore are assuming listen-only
*/
#define CO_CANerror_NOACK_MAX 16
#define CO_CANerror_NOACK_MAX 16
/**
* This is how long we are going to block transmission if listen-only
* mode is active
* This is how long we are going to block transmission if listen-only mode is active
*
* Time is in seconds.
*/
#define CO_CANerror_LISTEN_ONLY 10
/**
* socketCAN interface error handling
*/
typedef struct {
int fd; /**< interface FD */
char ifName[IFNAMSIZ]; /**< interface name as string */
uint32_t noackCounter; /**< counts no ACK on CAN transmission */
volatile unsigned char listenOnly; /**< set to listen only mode */
struct timespec timestamp; /**< listen only mode started at this time */
uint16_t CANerrorStatus; /**< CAN error status bitfield, see @ref CO_CAN_ERR_status_t */
int fd; /**< interface FD */
char ifName[IFNAMSIZ]; /**< interface name as string */
uint32_t noackCounter; /**< counts no ACK on CAN transmission */
volatile unsigned char listenOnly; /**< set to listen only mode */
struct timespec timestamp; /**< listen only mode started at this time */
uint16_t CANerrorStatus; /**< CAN error status bitfield, see @ref CO_CAN_ERR_status_t */
} CO_CANinterfaceErrorhandler_t;
/**
* Initialize CAN error handler
*
@ -123,32 +113,24 @@ typedef struct {
* @param fd interface file descriptor
* @param ifname interface name as string
*/
void CO_CANerror_init(
CO_CANinterfaceErrorhandler_t *CANerrorhandler,
int fd,
const char *ifname);
void CO_CANerror_init(CO_CANinterfaceErrorhandler_t* CANerrorhandler, int fd, const char* ifname);
/**
* Reset CAN error handler
*
* @param CANerrorhandler CAN error object.
*/
void CO_CANerror_disable(
CO_CANinterfaceErrorhandler_t *CANerrorhandler);
void CO_CANerror_disable(CO_CANinterfaceErrorhandler_t* CANerrorhandler);
/**
* Message received event
*
* When a message is received at least one other CAN module is connected.
* Function clears listenOnly and noackCounter error flags.
* When a message is received at least one other CAN module is connected. Function clears listenOnly and noackCounter
* error flags.
*
* @param CANerrorhandler CAN error object.
*/
void CO_CANerror_rxMsg(
CO_CANinterfaceErrorhandler_t *CANerrorhandler);
void CO_CANerror_rxMsg(CO_CANinterfaceErrorhandler_t* CANerrorhandler);
/**
* Check if interface is ready for message transmission
@ -158,9 +140,7 @@ void CO_CANerror_rxMsg(
* @param CANerrorhandler CAN error object.
* @return CO_INTERFACE_ACTIVE message transmission ready
*/
CO_CANinterfaceState_t CO_CANerror_txMsg(
CO_CANinterfaceErrorhandler_t *CANerrorhandler);
CO_CANinterfaceState_t CO_CANerror_txMsg(CO_CANinterfaceErrorhandler_t* CANerrorhandler);
/**
* Error message received event
@ -171,10 +151,8 @@ CO_CANinterfaceState_t CO_CANerror_txMsg(
* @param msg received error message
* @return #CO_CANinterfaceState_t
*/
CO_CANinterfaceState_t CO_CANerror_rxMsgError(
CO_CANinterfaceErrorhandler_t *CANerrorhandler,
const struct can_frame *msg);
CO_CANinterfaceState_t CO_CANerror_rxMsgError(CO_CANinterfaceErrorhandler_t* CANerrorhandler,
const struct can_frame* msg);
/** @} */

View file

@ -18,7 +18,6 @@
* See the License for the specific language governing permissions and limitations under the License.
*/
#ifndef CO_ERROR_MSGS_H
#define CO_ERROR_MSGS_H
@ -26,65 +25,67 @@
extern "C" {
#endif
/*
* Message definitions for Linux CANopen socket driver (notice and errors)
*/
#define CAN_NOT_FOUND "(%s) CAN Interface \"%s\" not found", __func__
#define CAN_INIT_FAILED "(%s) CAN Interface \"%s\" Init failed", __func__
#define CAN_BINDING_FAILED "(%s) Binding CAN Interface \"%s\" failed", __func__
#define CAN_ERROR_FILTER_FAILED "(%s) Setting CAN Interface \"%s\" error filter failed", __func__
#define CAN_FILTER_FAILED "(%s) Setting CAN Interface \"%s\" message filter failed", __func__
#define CAN_NAMETOINDEX "CAN Interface \"%s\" -> Index %d"
#define CAN_SOCKET_BUF_SIZE "CAN Interface \"%s\" RX buffer set to %d messages (%d Bytes)"
#define CAN_NOT_FOUND "(%s) CAN Interface \"%s\" not found", __func__
#define CAN_INIT_FAILED "(%s) CAN Interface \"%s\" Init failed", __func__
#define CAN_BINDING_FAILED "(%s) Binding CAN Interface \"%s\" failed", __func__
#define CAN_ERROR_FILTER_FAILED "(%s) Setting CAN Interface \"%s\" error filter failed", __func__
#define CAN_FILTER_FAILED "(%s) Setting CAN Interface \"%s\" message filter failed", __func__
#define CAN_NAMETOINDEX "CAN Interface \"%s\" -> Index %d"
#define CAN_SOCKET_BUF_SIZE "CAN Interface \"%s\" RX buffer set to %d messages (%d Bytes)"
#define CAN_RX_SOCKET_QUEUE_OVERFLOW "CAN Interface \"%s\" has lost %d messages"
#define CAN_BUSOFF "CAN Interface \"%s\" changed to \"Bus Off\". Switching to Listen Only mode..."
#define CAN_NOACK "CAN Interface \"%s\" no \"ACK\" received. Switching to Listen Only mode..."
#define CAN_RX_PASSIVE "CAN Interface \"%s\" changed state to \"Rx Passive\""
#define CAN_TX_PASSIVE "CAN Interface \"%s\" changed state to \"Tx Passive\""
#define CAN_TX_LEVEL_ACTIVE "CAN Interface \"%s\" changed state to \"Active\""
#define CAN_RX_BUF_OVERFLOW "CAN Interface \"%s\" Rx buffer overflow. Message dropped"
#define CAN_TX_BUF_OVERFLOW "CAN Interface \"%s\" Tx buffer overflow. Message dropped"
#define CAN_RX_LEVEL_WARNING "CAN Interface \"%s\" reached Rx Warning Level"
#define CAN_TX_LEVEL_WARNING "CAN Interface \"%s\" reached Tx Warning Level"
#define CAN_BUSOFF "CAN Interface \"%s\" changed to \"Bus Off\". Switching to Listen Only mode..."
#define CAN_NOACK "CAN Interface \"%s\" no \"ACK\" received. Switching to Listen Only mode..."
#define CAN_RX_PASSIVE "CAN Interface \"%s\" changed state to \"Rx Passive\""
#define CAN_TX_PASSIVE "CAN Interface \"%s\" changed state to \"Tx Passive\""
#define CAN_TX_LEVEL_ACTIVE "CAN Interface \"%s\" changed state to \"Active\""
#define CAN_RX_BUF_OVERFLOW "CAN Interface \"%s\" Rx buffer overflow. Message dropped"
#define CAN_TX_BUF_OVERFLOW "CAN Interface \"%s\" Tx buffer overflow. Message dropped"
#define CAN_RX_LEVEL_WARNING "CAN Interface \"%s\" reached Rx Warning Level"
#define CAN_TX_LEVEL_WARNING "CAN Interface \"%s\" reached Tx Warning Level"
/*
* Message definitions for debugging
*/
#define DBG_GENERAL "(%s) Error: %s%d", __func__
#define DBG_ERRNO "(%s) OS error \"%s\" in %s", __func__, strerror(errno)
#define DBG_CO_DEBUG "(%s) CO_DEBUG: %s", __func__
#define DBG_CAN_TX_FAILED "(%s) Transmitting CAN msg OID 0x%03x failed(%s)", __func__
#define DBG_CAN_RX_PARAM_FAILED "(%s) Setting CAN rx buffer failed (%s)", __func__
#define DBG_CAN_RX_FAILED "(%s) Receiving CAN msg failed (%s)", __func__
#define DBG_CAN_ERROR_GENERAL "(%s) Socket error msg ID: 0x%08x, Data[0..7]: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x (%s)", __func__
#define DBG_CAN_RX_EPOLL "(%s) CAN Epoll error (0x%02x - %s)", __func__
#define DBG_CAN_SET_LISTEN_ONLY "(%s) %s Set Listen Only", __func__
#define DBG_CAN_CLR_LISTEN_ONLY "(%s) %s Leave Listen Only", __func__
#define DBG_GENERAL "(%s) Error: %s%d", __func__
#define DBG_ERRNO "(%s) OS error \"%s\" in %s", __func__, strerror(errno)
#define DBG_CO_DEBUG "(%s) CO_DEBUG: %s", __func__
#define DBG_CAN_TX_FAILED "(%s) Transmitting CAN msg OID 0x%03x failed(%s)", __func__
#define DBG_CAN_RX_PARAM_FAILED "(%s) Setting CAN rx buffer failed (%s)", __func__
#define DBG_CAN_RX_FAILED "(%s) Receiving CAN msg failed (%s)", __func__
#define DBG_CAN_ERROR_GENERAL \
"(%s) Socket error msg ID: 0x%08x, Data[0..7]: 0x%02x, 0x%02x, 0x%02x, 0x%02x," \
" 0x%02x, 0x%02x, 0x%02x, 0x%02x (%s)", \
__func__
#define DBG_CAN_RX_EPOLL "(%s) CAN Epoll error (0x%02x - %s)", __func__
#define DBG_CAN_SET_LISTEN_ONLY "(%s) %s Set Listen Only", __func__
#define DBG_CAN_CLR_LISTEN_ONLY "(%s) %s Leave Listen Only", __func__
/* mainline */
#define DBG_EMERGENCY_RX "CANopen Emergency message from node 0x%02X: errorCode=0x%04X, errorRegister=0x%02X, errorBit=0x%02X, infoCode=0x%08X"
#define DBG_NMT_CHANGE "CANopen NMT state changed to: \"%s\" (%d)"
#define DBG_HB_CONS_NMT_CHANGE "CANopen Remote node ID = 0x%02X (index = %d): NMT state changed to: \"%s\" (%d)"
#define DBG_ARGUMENT_UNKNOWN "(%s) Unknown %s argument: \"%s\"", __func__
#define DBG_NOT_TCP_PORT "(%s) -c argument \"%s\" is not a valid tcp port", __func__
#define DBG_WRONG_NODE_ID "(%s) Wrong node ID \"%d\"", __func__
#define DBG_WRONG_PRIORITY "(%s) Wrong RT priority \"%d\"", __func__
#define DBG_NO_CAN_DEVICE "(%s) Can't find CAN device \"%s\"", __func__
#define DBG_STORAGE "(%s) Error with storage \"%s\"", __func__
#define DBG_OD_ENTRY "(%s) Error in Object Dictionary entry: 0x%X", __func__
#define DBG_CAN_OPEN "(%s) CANopen error in %s, err=%d", __func__
#define DBG_CAN_OPEN_INFO "CANopen device, Node ID = 0x%02X, %s"
#define DBG_EMERGENCY_RX \
"CANopen Emergency message from node 0x%02X: errorCode=0x%04X, errorRegister=0x%02X, errorBit=0x%02X, " \
"infoCode=0x%08X"
#define DBG_NMT_CHANGE "CANopen NMT state changed to: \"%s\" (%d)"
#define DBG_HB_CONS_NMT_CHANGE "CANopen Remote node ID = 0x%02X (index = %d): NMT state changed to: \"%s\" (%d)"
#define DBG_ARGUMENT_UNKNOWN "(%s) Unknown %s argument: \"%s\"", __func__
#define DBG_NOT_TCP_PORT "(%s) -c argument \"%s\" is not a valid tcp port", __func__
#define DBG_WRONG_NODE_ID "(%s) Wrong node ID \"%d\"", __func__
#define DBG_WRONG_PRIORITY "(%s) Wrong RT priority \"%d\"", __func__
#define DBG_NO_CAN_DEVICE "(%s) Can't find CAN device \"%s\"", __func__
#define DBG_STORAGE "(%s) Error with storage \"%s\"", __func__
#define DBG_OD_ENTRY "(%s) Error in Object Dictionary entry: 0x%X", __func__
#define DBG_CAN_OPEN "(%s) CANopen error in %s, err=%d", __func__
#define DBG_CAN_OPEN_INFO "CANopen device, Node ID = 0x%02X, %s"
/* CO_epoll_interface */
#define DBG_EPOLL_UNKNOWN "(%s) CAN Epoll error, events=0x%02x, fd=%d", __func__
#define DBG_COMMAND_LOCAL_BIND "(%s) Can't bind local socket to path \"%s\"", __func__
#define DBG_COMMAND_TCP_BIND "(%s) Can't bind tcp socket to port \"%d\"", __func__
#define DBG_COMMAND_STDIO_INFO "CANopen command interface on \"standard IO\" started"
#define DBG_COMMAND_LOCAL_INFO "CANopen command interface on local socket \"%s\" started"
#define DBG_COMMAND_TCP_INFO "CANopen command interface on tcp port \"%d\" started"
#define DBG_EPOLL_UNKNOWN "(%s) CAN Epoll error, events=0x%02x, fd=%d", __func__
#define DBG_COMMAND_LOCAL_BIND "(%s) Can't bind local socket to path \"%s\"", __func__
#define DBG_COMMAND_TCP_BIND "(%s) Can't bind tcp socket to port \"%d\"", __func__
#define DBG_COMMAND_STDIO_INFO "CANopen command interface on \"standard IO\" started"
#define DBG_COMMAND_LOCAL_INFO "CANopen command interface on local socket \"%s\" started"
#define DBG_COMMAND_TCP_INFO "CANopen command interface on tcp port \"%d\" started"
#ifdef __cplusplus
}

View file

@ -23,7 +23,7 @@
#include "storage/CO_storage.h"
#if ((CO_CONFIG_STORAGE) & CO_CONFIG_STORAGE_ENABLE) || defined CO_DOXYGEN
#if ((CO_CONFIG_STORAGE)&CO_CONFIG_STORAGE_ENABLE) || defined CO_DOXYGEN
#ifdef __cplusplus
extern "C" {
@ -35,58 +35,45 @@ extern "C" {
*
* @ingroup CO_socketCAN
* @{
*
* See also @ref CO_storage.
*/
/**
* Initialize data storage object (Linux specific)
*
* This function should be called by application after the program startup,
* before @ref CO_CANopenInit(). This function initializes storage object,
* OD extensions on objects 1010 and 1011, reads data from file, verifies them
* and writes data to addresses specified inside entries. This function
* internally calls @ref CO_storage_init().
* This function should be called by application after the program startup, before @ref CO_CANopenInit(). This function
* initializes storage object, OD extensions on objects 1010 and 1011, reads data from file, verifies them and writes
* data to addresses specified inside entries. This function internally calls @ref CO_storage_init().
*
* @param storage This object will be initialized. It must be defined by application and must exist permanently.
* @param CANmodule CAN device, used for @ref CO_LOCK_OD() macro.
* @param OD_1010_StoreParameters OD entry for 0x1010 -"Store parameters". Entry is optional, may be NULL.
* @param OD_1011_RestoreDefaultParam OD entry for 0x1011 -"Restore default
* parameters". Entry is optional, may be NULL.
* @param OD_1011_RestoreDefaultParam OD entry for 0x1011 -"Restore default parameters". Entry is optional, may be NULL.
* @param entries Pointer to array of storage entries, see @ref CO_storage_init.
* @param entriesCount Count of storage entries
* @param [out] storageInitError If function returns CO_ERROR_DATA_CORRUPT,
* then this variable contains a bit mask from subIndexOD values, where data
* was not properly initialized. If other error, then this variable contains
* index or erroneous entry.
* @param [out] storageInitError If function returns CO_ERROR_DATA_CORRUPT, then this variable contains a bit mask from
* subIndexOD values, where data was not properly initialized. If other error, then this variable contains index or
* erroneous entry.
*
* @return CO_ERROR_NO, CO_ERROR_DATA_CORRUPT if data can not be initialized,
* CO_ERROR_ILLEGAL_ARGUMENT or CO_ERROR_OUT_OF_MEMORY.
* @return CO_ERROR_NO, CO_ERROR_DATA_CORRUPT if data can not be initialized, CO_ERROR_ILLEGAL_ARGUMENT or
* CO_ERROR_OUT_OF_MEMORY.
*/
CO_ReturnError_t CO_storageLinux_init(CO_storage_t *storage,
CO_CANmodule_t *CANmodule,
OD_entry_t *OD_1010_StoreParameters,
OD_entry_t *OD_1011_RestoreDefaultParam,
CO_storage_entry_t *entries,
uint8_t entriesCount,
uint32_t *storageInitError);
CO_ReturnError_t CO_storageLinux_init(CO_storage_t* storage, CO_CANmodule_t* CANmodule,
OD_entry_t* OD_1010_StoreParameters, OD_entry_t* OD_1011_RestoreDefaultParam,
CO_storage_entry_t* entries, uint8_t entriesCount, uint32_t* storageInitError);
/**
* Automatically save data if differs from previous call.
*
* Should be called cyclically by program. Each interval it verifies, if crc
* checksum of data differs from previous checksum. If it does, data are saved
* into pre-opened file.
* Should be called cyclically by program. Each interval it verifies, if crc checksum of data differs from previous
* checksum. If it does, data are saved into pre-opened file.
*
* @param storage This object
* @param closeFiles If true, then all files will be closed. Use on end of the program.
*
* @return 0 on success or bit mask from subIndexOD values, where data was not able to be saved.
*/
uint32_t CO_storageLinux_auto_process(CO_storage_t *storage,
bool_t closeFiles);
uint32_t CO_storageLinux_auto_process(CO_storage_t* storage, bool_t closeFiles);
/** @} */ /* CO_storageLinux */