1
0
Fork 0

socketCAN driver:

- Always enable CANptr and timestamp info in CO_CANrx_t.
- Update documentation
This commit is contained in:
Janez 2020-02-29 18:09:29 +01:00
parent f21cde9ab0
commit 9d17b0d671
11 changed files with 148 additions and 112 deletions

View file

@ -129,7 +129,7 @@ extern "C" {
#ifdef CO_DOXYGEN #ifdef CO_DOXYGEN
/** /**
* @defgroup CO_NO_OBJ Number of CANopenNode communication objects. * @defgroup CO_NO_OBJ Configuration
* *
* Definitions specify, which and how many CANopenNode communication objects * Definitions specify, which and how many CANopenNode communication objects
* will be used in current configuration. Usage of some objects is mandatory and * will be used in current configuration. Usage of some objects is mandatory and

View file

@ -2057,7 +2057,7 @@ PREDEFINED = CO_DOXYGEN \
CO_NO_SDO_CLIENT=1 \ CO_NO_SDO_CLIENT=1 \
CO_NO_NMT_MASTER=1 \ CO_NO_NMT_MASTER=1 \
CO_NO_LSS_SERVER \ CO_NO_LSS_SERVER \
CO_NO_LSS_CLIENT \ CO_NO_LSS_CLIENT=1 \
CO_NO_TRACE=1 CO_NO_TRACE=1
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this

View file

@ -37,6 +37,7 @@ Change Log
- NMT self start functionality (OD object 1F80) implemented to strictly folow standard. Default value for object 1F80 have to be updated in OD editor. See README.md. - NMT self start functionality (OD object 1F80) implemented to strictly folow standard. Default value for object 1F80 have to be updated in OD editor. See README.md.
### Fixed ### Fixed
- Various fixes. - Various fixes.
- neuberger-socketCAN fixed.
### Added ### Added
- CANopen TIME protocol added. - CANopen TIME protocol added.

View file

@ -111,9 +111,9 @@ void CANrx_threadTmr_close(void)
void CANrx_threadTmr_process(void) void CANrx_threadTmr_process(void)
{ {
int32_t result; int32_t result;
int32_t i; uint64_t i;
bool_t syncWas; bool_t syncWas;
unsigned long long missed; uint64_t missed;
result = CO_CANrxWait(CO->CANmodule[0], threadRT.interval_fd, NULL); result = CO_CANrxWait(CO->CANmodule[0], threadRT.interval_fd, NULL);
if (result < 0) { if (result < 0) {

View file

@ -33,75 +33,90 @@
extern "C" { extern "C" {
#endif #endif
/** /**
* @defgroup CO_socketCAN socketCAN * @defgroup CO_socketCAN socketCAN
* @{ * @{
* *
* Linux specific interface to CANopenNode * Linux specific interface to CANopenNode
* *
* CANopenNode runs in two threads: timer based realtime thread for CAN receive, * CANopenNode runs in two threads:
* SYNC and PDO and mainline thread for other processing. * - timer based real-time thread for CAN receive, SYNC and PDO, see
* CANrx_threadTmr_process()
* - mainline thread for other processing, see threadMain_process()
* *
* The "threads" specified here do not fork threads themselves, but require * The "threads" specified here do not fork threads themselves, but require
* that two threads are provided by the calling application. * that two threads are provided by the calling application.
* It uses the global CO object and has one thread-local struct for variables.
*/ */
/** /**
* Initialize mainline thread. * Initialize mainline thread.
* *
* threadMain is non-realtime thread for CANopenNode processing. It is nonblocking
* and should be called cyclically in 50 ms intervals or less if necessary. This
* is indicated by the callback function.
* This thread processes CO_process() function from CANopen.c file.
*
* @param callback this function is called to indicate #threadMain_process() has * @param callback this function is called to indicate #threadMain_process() has
* work to do * work to do
* @param object this pointer is given to _callback()_ * @param object this pointer is given to _callback()_
*/ */
extern void threadMain_init(void (*callback)(void*), void *object); extern void threadMain_init(void (*callback)(void*), void *object);
/** /**
* Cleanup mainline thread. * Cleanup mainline thread.
*/ */
extern void threadMain_close(void); extern void threadMain_close(void);
/** /**
* Process mainline thread. * Process mainline thread.
* *
* Function must be called cyclically and after callback * threadMain is non-realtime thread for CANopenNode processing. It is
* initialized by threadMain_init(). There is no configuration for CANopen
* objects. There is also no configuration for epool or interval timer or notify
* pipe. These must be specified externally.
*
* threadMain_process() calls CO_process() function for processing mainline
* CANopen objects. It is non-blocking and should be called cyclically in 50 ms
* intervals (typically). Function must also be called immediately after
* callback provided in threadMain_init() is called.
* *
* @param reset return value from CO_process() function. * @param reset return value from CO_process() function.
*/ */
extern void threadMain_process(CO_NMT_reset_cmd_t *reset); extern void threadMain_process(CO_NMT_reset_cmd_t *reset);
/** /**
* Initialize realtime thread. * Initialize realtime thread.
* *
* CANrx_threadTmr is realtime thread for CANopenNode processing. It is nonblocking
* and must be executed at CAN message receive or periodically in 1ms (or something)
* intervals. Inside interval is processed CANopen SYNC message, RPDOs(inputs)
* and TPDOs(outputs).
* CANrx_threadTmr uses CAN socket from CO_driver.c
*
* @remark If realtime is required, this thread must be registred as such in the Linux
* kernel.
*
* @param interval_us Interval of periodic timer in microseconds, recommended * @param interval_us Interval of periodic timer in microseconds, recommended
* value for realtime response: 1000 us * value for realtime response: 1000 us
*/ */
extern void CANrx_threadTmr_init(uint32_t interval_us); extern void CANrx_threadTmr_init(uint32_t interval_us);
/** /**
* Terminate realtime thread. * Terminate realtime thread.
*/ */
extern void CANrx_threadTmr_close(void); extern void CANrx_threadTmr_close(void);
/** /**
* Process realtime thread. * Process real-time thread.
* *
* This function must be called inside an infinite loop. It blocks until either * CANrx_threadTmr is realtime thread for CANopenNode processing. It is
* some event happens or a timer runs out. * initialized by CANrx_threadTmr_init(). There is no configuration for CANopen
* objects. But configuration for epool event notification facility is included
* in CO_CANmodule_init() from CO_driver.c. Epool is configured to monitor the
* following file descriptors: notify pipe, CANrx sockets from all interfaces
* and interval timer.
*
* CANrx_threadTmr_process() blocks on epoll_wait(). This is implemented inside
* CO_CANrxWait() from CO_driver.c. New CAN message is processed in
* CANrx_threadTmr_process() function, which calls CO_process_SYNC(),
* CO_process_RPDO() and CO_process_TPDO() functions for each expired timer
* interval. This function must be called inside an infinite loop.
*
* @remark If realtime is required, this thread must be registered as such in
* the Linux kernel.
*/ */
extern void CANrx_threadTmr_process(); extern void CANrx_threadTmr_process();

View file

@ -2,7 +2,7 @@
* CANopen Object Dictionary storage object for Linux SocketCAN. * CANopen Object Dictionary storage object for Linux SocketCAN.
* *
* @file CO_OD_storage.h * @file CO_OD_storage.h
* @ingroup CO_socketCAN * @ingroup CO_socketCAN_OD_storage
* @author Janez Paternoster * @author Janez Paternoster
* @copyright 2015 - 2020 Janez Paternoster * @copyright 2015 - 2020 Janez Paternoster
* *
@ -38,7 +38,7 @@ extern "C" {
#endif #endif
/** /**
* @defgroup CO_OD_storage OD_storage * @defgroup CO_socketCAN_OD_storage OD storage
* @ingroup CO_socketCAN * @ingroup CO_socketCAN
* @{ * @{
* *

View file

@ -32,7 +32,9 @@
#include <linux/can/error.h> #include <linux/can/error.h>
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <asm/socket.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <time.h>
#include "301/CO_driver.h" #include "301/CO_driver.h"
#include "CO_error.h" #include "CO_error.h"
@ -268,11 +270,9 @@ CO_ReturnError_t CO_CANmodule_init(
rxArray[i].mask = 0xFFFFFFFFU; rxArray[i].mask = 0xFFFFFFFFU;
rxArray[i].object = NULL; rxArray[i].object = NULL;
rxArray[i].CANrx_callback = NULL; rxArray[i].CANrx_callback = NULL;
#ifdef CO_DRIVER_MULTI_INTERFACE
rxArray[i].CANptr = NULL; rxArray[i].CANptr = NULL;
rxArray[i].timestamp.tv_sec = 0; rxArray[i].timestamp.tv_sec = 0;
rxArray[i].timestamp.tv_nsec = 0; rxArray[i].timestamp.tv_nsec = 0;
#endif
} }
#ifndef CO_DRIVER_MULTI_INTERFACE #ifndef CO_DRIVER_MULTI_INTERFACE
@ -344,7 +344,7 @@ CO_ReturnError_t CO_CANmodule_addInterface(
log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(ovfl)"); log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(ovfl)");
return CO_ERROR_SYSCALL; return CO_ERROR_SYSCALL;
} }
#ifdef CO_DRIVER_MULTI_INTERFACE
/* enable software time stamp mode (hardware timestamps do not work properly /* enable software time stamp mode (hardware timestamps do not work properly
* on all devices)*/ * on all devices)*/
tmp = (SOF_TIMESTAMPING_SOFTWARE | tmp = (SOF_TIMESTAMPING_SOFTWARE |
@ -354,7 +354,6 @@ CO_ReturnError_t CO_CANmodule_addInterface(
log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(timestamping)"); log_printf(LOG_DEBUG, DBG_ERRNO, "setsockopt(timestamping)");
return CO_ERROR_SYSCALL; return CO_ERROR_SYSCALL;
} }
#endif
//todo - modify rx buffer size? first one needs root //todo - modify rx buffer size? first one needs root
//ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&bytes, sLen); //ret = setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, (void *)&bytes, sLen);
@ -501,11 +500,9 @@ CO_ReturnError_t CO_CANrxBufferInit(
/* Configure object variables */ /* Configure object variables */
buffer->object = object; buffer->object = object;
buffer->CANrx_callback = CANrx_callback; buffer->CANrx_callback = CANrx_callback;
#ifdef CO_DRIVER_MULTI_INTERFACE
buffer->CANptr = NULL; buffer->CANptr = NULL;
buffer->timestamp.tv_nsec = 0; buffer->timestamp.tv_nsec = 0;
buffer->timestamp.tv_sec = 0; buffer->timestamp.tv_sec = 0;
#endif
/* CAN identifier and CAN mask, bit aligned with CAN module */ /* CAN identifier and CAN mask, bit aligned with CAN module */
buffer->ident = ident & CAN_SFF_MASK; buffer->ident = ident & CAN_SFF_MASK;
@ -626,7 +623,7 @@ CO_ReturnError_t CO_CANtxBuffer_setInterface(
#endif /* CO_DRIVER_MULTI_INTERFACE */ #endif /* CO_DRIVER_MULTI_INTERFACE */
/******************************************************************************/ /* send CAN message ***********************************************************/
static CO_ReturnError_t CO_CANCheckSendInterface( static CO_ReturnError_t CO_CANCheckSendInterface(
CO_CANmodule_t *CANmodule, CO_CANmodule_t *CANmodule,
CO_CANtx_t *buffer, CO_CANtx_t *buffer,
@ -773,12 +770,12 @@ void CO_CANverifyErrors(CO_CANmodule_t *CANmodule)
} }
/******************************************************************************/ /* Read CAN message from socket and verify some errors ************************/
static CO_ReturnError_t CO_CANread( static CO_ReturnError_t CO_CANread(
CO_CANmodule_t *CANmodule, CO_CANmodule_t *CANmodule,
CO_CANinterface_t *interface, CO_CANinterface_t *interface,
struct can_frame *msg, struct can_frame *msg, /* CAN message, return value */
struct timespec *timestamp) struct timespec *timestamp) /* timestamp of CAN message, return value */
{ {
int32_t n; int32_t n;
uint32_t dropped; uint32_t dropped;
@ -838,10 +835,11 @@ static CO_ReturnError_t CO_CANread(
} }
static int32_t CO_CANrxMsg( /* find msg inside rxArray and call corresponding CANrx_callback **************/
static int32_t CO_CANrxMsg( /* return index of received message in rxArray or -1 */
CO_CANmodule_t *CANmodule, CO_CANmodule_t *CANmodule,
struct can_frame *msg, struct can_frame *msg, /* CAN message input */
CO_CANrxMsg_t *buffer) CO_CANrxMsg_t *buffer) /* If not NULL, msg will be copied to buffer */
{ {
int32_t retval; int32_t retval;
const CO_CANrxMsg_t *rcvMsg; /* pointer to received message in CAN module */ const CO_CANrxMsg_t *rcvMsg; /* pointer to received message in CAN module */
@ -888,9 +886,7 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
{ {
int32_t retval; int32_t retval;
int32_t ret; int32_t ret;
#ifdef CO_DRIVER_MULTI_INTERFACE
const void *CANptr; const void *CANptr;
#endif
CO_ReturnError_t err; CO_ReturnError_t err;
CO_CANinterface_t *interface = NULL; CO_CANinterface_t *interface = NULL;
struct epoll_event ev[1]; struct epoll_event ev[1];
@ -938,7 +934,7 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
/* one of the sockets is ready */ /* one of the sockets is ready */
if ((ev[0].data.fd == CO_NotifyPipeGetFd(CANmodule->pipe)) || if ((ev[0].data.fd == CO_NotifyPipeGetFd(CANmodule->pipe)) ||
(ev[0].data.fd == fdTimer)) { (ev[0].data.fd == fdTimer)) {
/* timer/pipe socket */ /* timer or notify pipe */
return -1; return -1;
} }
else { else {
@ -949,10 +945,8 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
interface = &CANmodule->CANinterfaces[i]; interface = &CANmodule->CANinterfaces[i];
if (ev[0].data.fd == interface->fd) { if (ev[0].data.fd == interface->fd) {
#ifdef CO_DRIVER_MULTI_INTERFACE
/* get interface handle */ /* get interface handle */
CANdriverState = interface->CANptr; CANptr = interface->CANptr;
#endif
/* get message */ /* get message */
err = CO_CANread(CANmodule, interface, &msg, &timestamp); err = CO_CANread(CANmodule, interface, &msg, &timestamp);
if (err != CO_ERROR_NO) { if (err != CO_ERROR_NO) {
@ -983,16 +977,15 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
int32_t msgIndex; int32_t msgIndex;
#ifdef CO_DRIVER_ERROR_REPORTING #ifdef CO_DRIVER_ERROR_REPORTING
/* clear listenOnly and noackCounter if necessary */
CO_CANerror_rxMsg(&interface->errorhandler); CO_CANerror_rxMsg(&interface->errorhandler);
#endif #endif
msgIndex = CO_CANrxMsg(CANmodule, &msg, buffer); msgIndex = CO_CANrxMsg(CANmodule, &msg, buffer);
if (msgIndex > -1) { if (msgIndex > -1) {
#ifdef CO_DRIVER_MULTI_INTERFACE
/* Store message info */ /* Store message info */
CANmodule->rxArray[msgIndex].timestamp = timestamp; CANmodule->rxArray[msgIndex].timestamp = timestamp;
CANmodule->rxArray[msgIndex].CANptr = CANptr; CANmodule->rxArray[msgIndex].CANptr = CANptr;
#endif
} }
retval = msgIndex; retval = msgIndex;
} }

View file

@ -1,7 +1,8 @@
/* /**
* Linux socketCAN specific definitions for CANopenNode. * Linux socketCAN specific definitions for CANopenNode.
* *
* @file CO_driver_target.h * @file CO_driver_target.h
* @ingroup CO_socketCAN_driver_target
* @author Janez Paternoster * @author Janez Paternoster
* @author Martin Wagner * @author Martin Wagner
* @copyright 2004 - 2020 Janez Paternoster * @copyright 2004 - 2020 Janez Paternoster
@ -25,15 +26,41 @@
*/ */
/* This file contains device and application specific definitions.
* It is included from CO_driver.h, which contains documentation
* for common definitions below. */
#ifndef CO_DRIVER_TARGET #ifndef CO_DRIVER_TARGET
#define CO_DRIVER_TARGET #define CO_DRIVER_TARGET
/* This file contains device and application specific definitions. #include <stddef.h>
* It is included from CO_driver.h, which contains documentation #include <stdbool.h>
* for definitions below. */ #include <stdint.h>
#include <endian.h>
#include <pthread.h>
#include <linux/can.h>
#include <net/if.h>
/* #if __has_include("CO_driver_custom.h")
* @name multi interface support #include "CO_driver_custom.h"
#endif
#include "CO_notify_pipe.h"
#include "CO_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup CO_socketCAN_driver_target CO_driver_target.h
* @ingroup CO_socketCAN
* @{
*
* Linux socketCAN specific @ref CO_driver definitions for CANopenNode.
*/
/**
* Multi interface support
* *
* Enable this to use interface combining at driver level. This * Enable this to use interface combining at driver level. This
* adds functions to broadcast/selective transmit messages on the * adds functions to broadcast/selective transmit messages on the
@ -51,40 +78,32 @@
* This is not intended to realize interface redundancy!!! * This is not intended to realize interface redundancy!!!
*/ */
/* #define CO_DRIVER_MULTI_INTERFACE */ /* #define CO_DRIVER_MULTI_INTERFACE */
#ifdef CO_DOXYGEN
#define CO_DRIVER_MULTI_INTERFACE
#endif
/* /**
* @name CAN bus error reporting * CAN bus error reporting
* *
* CO_DRIVER_ERROR_REPORTING enabled adds support for socketCAN error detection * CO_DRIVER_ERROR_REPORTING enabled adds support for socketCAN error detection
* and handling functions inside the driver. This is needed when you have * 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 * CANopen with "0" connected nodes as a use case, as this is normally
* forbidden in CAN. * forbidden in CAN.
* *
* you need to enable error reporting in your kernel driver using * you need to enable error reporting in your kernel driver using:
* "ip link set canX type can berr-reporting on". Of course, the kernel * @code{.sh}
* driver for your hardware needs this functionality to be implemented... * ip link set canX type can berr-reporting on
* @endcode
* Of course, the kernel driver for your hardware needs this functionality to be
* implemented...
*/ */
#ifndef CO_DRIVER_ERROR_REPORTING_DISABLE /* #define CO_DRIVER_ERROR_REPORTING */
#ifdef CO_DOXYGEN
#define CO_DRIVER_ERROR_REPORTING #define CO_DRIVER_ERROR_REPORTING
#endif #endif
#include <stddef.h> /* skip this section for Doxygen, because it is documented in CO_driver.h */
#include <stdbool.h> #ifndef CO_DOXYGEN
#include <stdint.h>
#include <sys/time.h>
#include <endian.h>
#include <pthread.h>
#include <linux/can.h>
#include <net/if.h>
#include "CO_notify_pipe.h"
#ifdef CO_DRIVER_ERROR_REPORTING
#include "CO_error.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Basic definitions */ /* Basic definitions */
#ifdef __BYTE_ORDER #ifdef __BYTE_ORDER
@ -135,11 +154,9 @@ typedef struct {
uint32_t mask; uint32_t mask;
void *object; void *object;
void (*CANrx_callback)(void *object, void *message); void (*CANrx_callback)(void *object, void *message);
#ifdef CO_DRIVER_MULTI_INTERFACE const void *CANptr; /* CAN Interface identifier from last
/* info about last received message */ message */
const void *CANptr; /* CAN Interface identifier */ struct timespec timestamp; /* time of reception of last message */
struct timespec timestamp; /* time of reception */
#endif
} CO_CANrx_t; } CO_CANrx_t;
/* Transmit message object as aligned in socketCAN. */ /* Transmit message object as aligned in socketCAN. */
@ -182,7 +199,8 @@ typedef struct {
volatile bool_t CANnormal; volatile bool_t CANnormal;
void *em; void *em;
CO_NotifyPipe_t *pipe; /* Notification Pipe */ CO_NotifyPipe_t *pipe; /* Notification Pipe */
int fdEpoll; /* epoll FD */ int fdEpoll; /* epoll FD for pipe, CANrx sockets in all
interfaces and fdTimerRead */
int fdTimerRead; /* timer handle from CANrxWait() */ int fdTimerRead; /* timer handle from CANrxWait() */
#ifdef CO_DRIVER_MULTI_INTERFACE #ifdef CO_DRIVER_MULTI_INTERFACE
/* Lookup tables Cob ID to rx/tx array index. /* Lookup tables Cob ID to rx/tx array index.
@ -221,9 +239,11 @@ static inline void CO_UNLOCK_OD() {
#define CO_FLAG_SET(rxNew) {CO_MemoryBarrier(); rxNew = (void*)1L;} #define CO_FLAG_SET(rxNew) {CO_MemoryBarrier(); rxNew = (void*)1L;}
#define CO_FLAG_CLEAR(rxNew) {CO_MemoryBarrier(); rxNew = NULL;} #define CO_FLAG_CLEAR(rxNew) {CO_MemoryBarrier(); rxNew = NULL;}
#endif /* CO_DOXYGEN */
#ifdef CO_DRIVER_MULTI_INTERFACE #ifdef CO_DRIVER_MULTI_INTERFACE
/* /**
* Add socketCAN interface to can driver * Add socketCAN interface to can driver
* *
* Function must be called after CO_CANmodule_init. * Function must be called after CO_CANmodule_init.
@ -236,7 +256,7 @@ static inline void CO_UNLOCK_OD() {
CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule, CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule,
const void *CANptr); const void *CANptr);
/* /**
* Check on which interface the last message for one message buffer was received * 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 * It is in the responsibility of the user to check that this information is
@ -256,7 +276,7 @@ bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule,
const void **const CANptrRx, const void **const CANptrRx,
struct timespec *timestamp); struct timespec *timestamp);
/* /**
* Set which interface should be used for message buffer transmission * Set which interface should be used for message buffer transmission
* *
* It is in the responsibility of the user to ensure that the correct interface * It is in the responsibility of the user to ensure that the correct interface
@ -277,26 +297,33 @@ CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t *CANmodule,
#endif /* CO_DRIVER_MULTI_INTERFACE */ #endif /* CO_DRIVER_MULTI_INTERFACE */
/* /**
* Functions receives CAN messages. It is blocking. * Functions receives CAN messages (blocking)
* *
* This function can be used in two ways * This function waits for received CAN message, CAN error frame, notification
* - automatic mode (call callback that is set by #CO_CANrxBufferInit() function) * pipe or fdTimer expiration. In case of CAN message it searches _rxArray_ from
* - manual mode (evaluate message filters, return received message) * 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_.
* *
* Both modes can be combined. * 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.
* - manual mode: evaluate message filters, return received message
* *
* @param CANmodule This object. * @param CANmodule This object.
* @param fdTimer file descriptor with activated timeout. fd is not read after * @param fdTimer File descriptor with activated timeout. If set to -1, then
* expiring! -1 if not used. * timer will not be used. File descriptor must be read
* @param buffer [out] storage for received message or _NULL_ * externally if retval == -1! Read must be nonblocking and
* @retval >= 0 index of received message in array set by #CO_CANmodule_init() * provides number of timer expirations since last read.
* _rxArray_, copy available in _buffer_ * @param [out] buffer Storage for received message or _NULL_ if not used.
* @retval -1 no message received * @retval >= 0 index of received message in array from CO_CANmodule_t
* _rxArray_, copy of CAN message is available in _buffer_.
* @retval -1 no message received (timer expired or notification pipe or error)
*/ */
int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int32_t CO_CANrxWait(CO_CANmodule_t* CANmodule, int fdTimer, CO_CANrxMsg_t* buffer);
int fdTimer,
CO_CANrxMsg_t *buffer); /** @} */
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -26,6 +26,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <time.h>
#include <linux/can/error.h> #include <linux/can/error.h>
#include "301/CO_driver.h" #include "301/CO_driver.h"

View file

@ -2,7 +2,7 @@
* CANopenNode Linux socketCAN Error handling. * CANopenNode Linux socketCAN Error handling.
* *
* @file CO_error.h * @file CO_error.h
* @ingroup CO_socketCAN * @ingroup CO_socketCAN_ERROR
* @author Martin Wagner * @author Martin Wagner
* @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH * @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH
* *
@ -41,11 +41,11 @@ extern "C" {
#endif #endif
/** /**
* @defgroup CO_socketCAN_ERROR socketCAN_ERROR * @defgroup CO_socketCAN_ERROR CAN errors & Log
* @ingroup CO_socketCAN * @ingroup CO_socketCAN
* @{ * @{
* *
* CANopen Errors and logging of messages * CANopen Errors and System message log
*/ */
/** /**
@ -108,9 +108,7 @@ typedef enum {
typedef struct { typedef struct {
int fd; /**< interface FD */ int fd; /**< interface FD */
char ifName[IFNAMSIZ]; /**< interface name as string */ char ifName[IFNAMSIZ]; /**< interface name as string */
uint32_t noackCounter; /**< counts no ACK on CAN transmission */
uint32_t noackCounter;
volatile unsigned char listenOnly; /**< set to listen only mode */ volatile unsigned char listenOnly; /**< set to listen only mode */
struct timespec timestamp; /**< listen only mode started at this time */ struct timespec timestamp; /**< listen only mode started at this time */
} CO_CANinterfaceErrorhandler_t; } CO_CANinterfaceErrorhandler_t;
@ -143,7 +141,8 @@ void CO_CANerror_disable(
/** /**
* Message received event * Message received event
* *
* when a message is received at least one other CAN module is connected * 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. * @param CANerrorhandler CAN error object.
*/ */
@ -154,7 +153,7 @@ void CO_CANerror_rxMsg(
/** /**
* Check if interface is ready for message transmission * Check if interface is ready for message transmission
* *
* message musn't be transmitted if not ready * Message mustn't be transmitted if not ready.
* *
* @param CANerrorhandler CAN error object. * @param CANerrorhandler CAN error object.
* @return CO_INTERFACE_ACTIVE message transmission ready * @return CO_INTERFACE_ACTIVE message transmission ready
@ -166,7 +165,7 @@ CO_CANinterfaceState_t CO_CANerror_txMsg(
/** /**
* Error message received event * Error message received event
* *
* this handles all received error messages * This handles all received error messages.
* *
* @param CANerrorhandler CAN error object. * @param CANerrorhandler CAN error object.
* @param msg received error message * @param msg received error message

View file

@ -2,7 +2,7 @@
* Notify pipe for Linux threads. * Notify pipe for Linux threads.
* *
* @file CO_notify_pipe.h * @file CO_notify_pipe.h
* @ingroup CO_socketCAN * @ingroup CO_socketCAN_notify_pipe
* @author Martin Wagner * @author Martin Wagner
* @copyright 2017 - 2020 Neuberger Gebaeudeautomation GmbH * @copyright 2017 - 2020 Neuberger Gebaeudeautomation GmbH
* *
@ -32,7 +32,7 @@ extern "C" {
#endif #endif
/** /**
* @defgroup CO_pipe Pipe * @defgroup CO_socketCAN_notify_pipe Notify pipe
* @ingroup CO_socketCAN * @ingroup CO_socketCAN
* @{ * @{
* *