1
0
Fork 0

CO_driver interface: remove Emergency object dependency for reporting CAN

errors, use CANerrorStatus own variable instead. Emergency object updated.
This commit is contained in:
Janez 2020-06-13 14:06:35 +02:00
parent e1c7e2dbfa
commit ca452c47cc
13 changed files with 212 additions and 120 deletions

View file

@ -184,6 +184,7 @@ CO_ReturnError_t CO_EM_init(
emPr->preDefErrSize = preDefErrSize;
emPr->preDefErrNoOfErrors = 0U;
emPr->inhibitEmTimer = 0U;
emPr->CANerrorStatusOld = 0U;
/* clear error status bits */
for(i=0U; i<errorStatusBitsSize; i++){
@ -208,7 +209,6 @@ CO_ReturnError_t CO_EM_init(
/* configure emergency message CAN transmission */
emPr->CANdev = CANdevTx;
emPr->CANdev->em = (void*)em; /* update pointer inside CAN device. */
emPr->CANtxBuff = CO_CANtxBufferInit(
CANdevTx, /* CAN device */
CANdevTxIdx, /* index of specific buffer inside CAN module */
@ -271,9 +271,70 @@ void CO_EM_process(
uint8_t errorMask;
uint8_t i;
uint32_t emInhTime_us = (uint32_t)emInhTime_100us * 100;
uint16_t CANerrSt = emPr->CANdev->CANerrorStatus;
/* verify errors from driver and other */
CO_CANverifyErrors(emPr->CANdev);
/* verify errors from driver */
if (CANerrSt != emPr->CANerrorStatusOld) {
uint16_t CANerrStChanged = CANerrSt ^ emPr->CANerrorStatusOld;
emPr->CANerrorStatusOld = CANerrSt;
if (CANerrStChanged & (CO_CAN_ERRTX_WARNING | CO_CAN_ERRRX_WARNING)) {
if (CANerrSt & (CO_CAN_ERRTX_WARNING | CO_CAN_ERRRX_WARNING))
CO_errorReport(em, CO_EM_CAN_BUS_WARNING, CO_EMC_NO_ERROR, 0);
else
CO_errorReset(em, CO_EM_CAN_BUS_WARNING, 0);
}
if (CANerrStChanged & CO_CAN_ERRTX_PASSIVE) {
if (CANerrSt & CO_CAN_ERRTX_PASSIVE)
CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE,
CO_EMC_CAN_PASSIVE, 0);
else
CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE, 0);
}
if (CANerrStChanged & CO_CAN_ERRTX_BUS_OFF) {
if (CANerrSt & CO_CAN_ERRTX_BUS_OFF)
CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF,
CO_EMC_BUS_OFF_RECOVERED, 0);
else
CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, 0);
}
if (CANerrStChanged & CO_CAN_ERRTX_OVERFLOW) {
if (CANerrSt & CO_CAN_ERRTX_OVERFLOW)
CO_errorReport(em, CO_EM_CAN_TX_OVERFLOW,
CO_EMC_CAN_OVERRUN, 0);
else
CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW, 0);
}
if (CANerrStChanged & CO_CAN_ERRTX_PDO_LATE) {
if (CANerrSt & CO_CAN_ERRTX_PDO_LATE)
CO_errorReport(em, CO_EM_TPDO_OUTSIDE_WINDOW,
CO_EMC_COMMUNICATION, 0);
else
CO_errorReset(em, CO_EM_TPDO_OUTSIDE_WINDOW, 0);
}
if (CANerrStChanged & CO_CAN_ERRRX_PASSIVE) {
if (CANerrSt & CO_CAN_ERRRX_PASSIVE)
CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE,
CO_EMC_CAN_PASSIVE, 0);
else
CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE, 0);
}
if (CANerrStChanged & CO_CAN_ERRRX_OVERFLOW) {
if (CANerrSt & CO_CAN_ERRRX_OVERFLOW)
CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW,
CO_EMC_CAN_OVERRUN, 0);
else
CO_errorReset(em, CO_EM_CAN_RXB_OVERFLOW, 0);
}
}
/* verify other errors */
if(em->wrongErrorReport != 0U){
CO_errorReport(em, CO_EM_WRONG_ERROR_REPORT, CO_EMC_SOFTWARE_INTERNAL, (uint32_t)em->wrongErrorReport);
em->wrongErrorReport = 0U;

View file

@ -346,6 +346,7 @@ typedef struct{
uint8_t preDefErrNoOfErrors;/**< Number of active errors in preDefErr */
uint32_t inhibitEmTimer; /**< Internal timer for emergency message */
CO_EM_t *em; /**< CO_EM_t sub object is included here */
uint16_t CANerrorStatusOld;/**< Old CAN error status bitfield */
CO_CANmodule_t *CANdev; /**< From CO_EM_init() */
CO_CANtx_t *CANtxBuff; /**< CAN transmit buffer */
}CO_EMpr_t;

View file

@ -359,6 +359,8 @@ typedef struct {
uint16_t rxSize; /**< From CO_CANmodule_init() */
CO_CANtx_t *txArray; /**< From CO_CANmodule_init() */
uint16_t txSize; /**< From CO_CANmodule_init() */
uint16_t CANerrorStatus; /**< CAN error status bitfield,
see @ref CO_CAN_ERR_status_t */
volatile bool_t CANnormal; /**< CAN module is in normal mode */
volatile bool_t useCANrxFilters; /**< Value different than zero indicates,
that CAN module hardware filters are used for CAN reception. If
@ -373,7 +375,6 @@ typedef struct {
volatile uint16_t CANtxCount; /**< Number of messages in transmit
buffer, which are waiting to be copied to the CAN module */
uint32_t errOld; /**< Previous state of CAN errors */
void *em; /**< Emergency object */
} CO_CANmodule_t;
@ -472,6 +473,30 @@ typedef enum {
} CO_Default_CAN_ID_t;
/**
* CAN error status bitmasks.
*
* CAN warning level is reached, if CAN transmit or receive error counter is
* more or equal to 96. CAN passive level is reached, if counters are more or
* equal to 128. Transmitter goes in error state 'bus off' if transmit error
* counter is more or equal to 256.
*/
typedef enum {
CO_CAN_ERRTX_WARNING = 0x0001, /**< 0x0001, CAN transmitter warning */
CO_CAN_ERRTX_PASSIVE = 0x0002, /**< 0x0002, CAN transmitter passive */
CO_CAN_ERRTX_BUS_OFF = 0x0004, /**< 0x0004, CAN transmitter bus off */
CO_CAN_ERRTX_OVERFLOW = 0x0008, /**< 0x0008, CAN transmitter overflow */
CO_CAN_ERRTX_PDO_LATE = 0x0080, /**< 0x0080, TPDO is outside sync window */
CO_CAN_ERRRX_WARNING = 0x0100, /**< 0x0100, CAN receiver warning */
CO_CAN_ERRRX_PASSIVE = 0x0200, /**< 0x0200, CAN receiver passive */
CO_CAN_ERRRX_OVERFLOW = 0x0800, /**< 0x0800, CAN receiver overflow */
CO_CAN_ERR_WARN_PASSIVE = 0x0303/**< 0x0303, combination */
} CO_CAN_ERR_status_t;
/**
* Return values of some CANopen functions. If function was executed
* successfully it returns 0 otherwise it returns <0.
@ -640,7 +665,7 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer);
* CANopen allows synchronous PDO communication only inside time between SYNC
* message and SYNC Window. If time is outside this window, new synchronous PDOs
* must not be sent and all pending sync TPDOs, which may be on CAN TX buffers,
* must be cleared.
* may optionally be cleared.
*
* This function checks (and aborts transmission if necessary) CAN TX buffers
* when it is called. Function should be called by the stack in the moment,
@ -652,13 +677,14 @@ void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule);
/**
* Verify all errors of CAN module.
* Process can module - verify CAN errors
*
* Function is called directly from CO_EM_process() function.
* Function must be called cyclically. It should calculate CANerrorStatus
* bitfield for CAN errors defined in @ref CO_CAN_ERR_status_t.
*
* @param CANmodule This object.
*/
void CO_CANverifyErrors(CO_CANmodule_t *CANmodule);
void CO_CANmodule_process(CO_CANmodule_t *CANmodule);
/** @} */ /* @defgroup CO_driver Driver */

View file

@ -45,15 +45,14 @@ CO_ReturnError_t CO_LEDs_init(CO_LEDs_t *LEDs) {
/******************************************************************************/
void CO_LEDs_process(CO_LEDs_t *LEDs,
uint32_t timeDifference_us,
CO_NMT_internalState_t NMTstate,
bool_t LSSconfig,
bool_t ErrCANbusOff,
bool_t ErrNodeId,
bool_t ErrCANbusWarn,
bool_t ErrRpdo,
bool_t ErrSync,
bool_t ErrHbCons,
bool_t ErrCANbusWarn,
bool_t ErrOther,
CO_NMT_internalState_t NMTstate,
bool_t LSSconfig,
bool_t firmwareDownload,
uint32_t *timerNext_us)
{
@ -117,14 +116,14 @@ void CO_LEDs_process(CO_LEDs_t *LEDs,
uint8_t rd_co, gr_co;
/* CANopen red ERROR LED */
if (ErrCANbusOff) rd_co = 1;
else if (ErrNodeId) rd_co = rd & CO_LED_flicker;
else if (ErrRpdo) rd_co = rd & CO_LED_flash_4;
else if (ErrSync) rd_co = rd & CO_LED_flash_3;
else if (ErrHbCons) rd_co = rd & CO_LED_flash_2;
else if (ErrCANbusWarn) rd_co = rd & CO_LED_flash_1;
else if (ErrOther) rd_co = rd & CO_LED_blink;
else rd_co = 0;
if (ErrCANbusOff) rd_co = 1;
else if (NMTstate == CO_NMT_INITIALIZING) rd_co = rd & CO_LED_flicker;
else if (ErrRpdo) rd_co = rd & CO_LED_flash_4;
else if (ErrSync) rd_co = rd & CO_LED_flash_3;
else if (ErrHbCons) rd_co = rd & CO_LED_flash_2;
else if (ErrCANbusWarn) rd_co = rd & CO_LED_flash_1;
else if (ErrOther) rd_co = rd & CO_LED_blink;
else rd_co = 0;
/* CANopen green RUN LED */
if (LSSconfig) gr_co = gr & CO_LED_flicker;

View file

@ -116,29 +116,27 @@ CO_ReturnError_t CO_LEDs_init(CO_LEDs_t *LEDs);
* @param LEDs This object.
* @param timeDifference_us Time difference from previous function call in
* [microseconds].
* @param ErrCANbusOff CAN bus off indication (highest priority).
* @param ErrNodeId LSS unconfigured Node Id indication.
* @param ErrRpdo RPDO evnet timer timeout indication.
* @param ErrSync Sync receive timeout indication.
* @param ErrHbCons Heartbeat consumer error (remote node) indication.
* @param ErrCANbusWarn CAN error warning limit reached indication.
* @param ErrOther Other error indication (lowest priority).
* @param NMTstate NMT operating state.
* @param LSSconfig Node is in LSS configuration state indication.
* @param ErrCANbusOff CAN bus off indication (highest priority).
* @param ErrCANbusWarn CAN error warning limit reached indication.
* @param ErrRpdo RPDO event timer timeout indication.
* @param ErrSync Sync receive timeout indication.
* @param ErrHbCons Heartbeat consumer error (remote node) indication.
* @param ErrOther Other error indication (lowest priority).
* @param firmwareDownload Firmware download is in progress indication.
* @param [out] timerNext_us info to OS - see CO_process().
*/
void CO_LEDs_process(CO_LEDs_t *LEDs,
uint32_t timeDifference_us,
CO_NMT_internalState_t NMTstate,
bool_t LSSconfig,
bool_t ErrCANbusOff,
bool_t ErrNodeId,
bool_t ErrCANbusWarn,
bool_t ErrRpdo,
bool_t ErrSync,
bool_t ErrHbCons,
bool_t ErrCANbusWarn,
bool_t ErrOther,
CO_NMT_internalState_t NMTstate,
bool_t LSSconfig,
bool_t firmwareDownload,
uint32_t *timerNext_us);

View file

@ -856,30 +856,31 @@ CO_NMT_reset_cmd_t CO_process(CO_t *co,
bool_t NMTisPreOrOperational = false;
CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
CO_CANmodule_process(CO->CANmodule[0]);
#if CO_NO_LSS_SLAVE == 1
bool_t resetLSS = CO_LSSslave_process(co->LSSslave);
#endif
#if (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE
bool_t unc = co->nodeIdUnconfigured;
uint16_t CANerrorStatus = CO->CANmodule[0]->CANerrorStatus;
CO_LEDs_process(co->LEDs,
timeDifference_us,
CO_isError(co->em, CO_EM_CAN_TX_BUS_OFF),
co->nodeIdUnconfigured,
0, /* RPDO event timer timeout */
CO_isError(co->em, CO_EM_SYNC_TIME_OUT),
CO_isError(co->em, CO_EM_HEARTBEAT_CONSUMER)
|| CO_isError(co->em, CO_EM_HB_CONSUMER_REMOTE_RESET),
CO_isError(co->em, CO_EM_CAN_BUS_WARNING)
|| CO_isError(co->em, CO_EM_CAN_TX_BUS_PASSIVE)
|| CO_isError(co->em, CO_EM_CAN_RX_BUS_PASSIVE),
OD_errorRegister != 0,
co->NMT->operatingState,
unc ? CO_NMT_INITIALIZING : co->NMT->operatingState,
#if CO_NO_LSS_SLAVE == 1
CO_LSSslave_getState(co->LSSslave)
== CO_LSS_STATE_CONFIGURATION,
== CO_LSS_STATE_CONFIGURATION,
#else
0,
false,
#endif
(CANerrorStatus & CO_CAN_ERRTX_BUS_OFF) != 0,
(CANerrorStatus & CO_CAN_ERR_WARN_PASSIVE) != 0,
0, /* RPDO event timer timeout */
unc ? false : CO_isError(co->em, CO_EM_SYNC_TIME_OUT),
unc ? false : (CO_isError(co->em, CO_EM_HEARTBEAT_CONSUMER)
|| CO_isError(co->em, CO_EM_HB_CONSUMER_REMOTE_RESET)),
OD_errorRegister != 0,
CO_STATUS_FIRMWARE_DOWNLOAD_IN_PROGRESS,
timerNext_us);
#endif /* (CO_CONFIG_LEDS) & CO_CONFIG_LEDS_ENABLE */

View file

@ -23,6 +23,7 @@ Change Log
- SDO client is rewritten. Now includes read/write fifo interface to transfer data.
- LED indicator indication (CiA303-3) moved from NMT into own files. Now fully comply to standard.
- LSS slave is integrated into CANopenNode more directly.
- CO_driver interface: remove Emergency object dependency for reporting CAN errors, use CANerrorStatus own variable instead. Emergency object updated.
### Changed SocketCAN
- ./stack/socketCAN removed from the project, ./stack/Neuberger-socketCAN moved to ./socketCAN
- driver API updated

View file

@ -27,7 +27,6 @@
#include "301/CO_driver.h"
#include "301/CO_Emergency.h"
/******************************************************************************/
@ -67,13 +66,13 @@ CO_ReturnError_t CO_CANmodule_init(
CANmodule->rxSize = rxSize;
CANmodule->txArray = txArray;
CANmodule->txSize = txSize;
CANmodule->CANerrorStatus = 0;
CANmodule->CANnormal = false;
CANmodule->useCANrxFilters = (rxSize <= 32U) ? true : false;/* microcontroller dependent */
CANmodule->bufferInhibitFlag = false;
CANmodule->firstCANtxMessage = true;
CANmodule->CANtxCount = 0U;
CANmodule->errOld = 0U;
CANmodule->em = NULL;
for(i=0U; i<rxSize; i++){
rxArray[i].ident = 0U;
@ -196,7 +195,7 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer){
if(buffer->bufferFull){
if(!CANmodule->firstCANtxMessage){
/* don't set error, if bootup message is still on buffers */
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, buffer->ident);
CANmodule->CANerrorStatus |= CO_CAN_ERRTX_OVERFLOW;
}
err = CO_ERROR_TX_OVERFLOW;
}
@ -249,66 +248,62 @@ void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule){
if(tpdoDeleted != 0U){
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_TPDO_OUTSIDE_WINDOW, CO_EMC_COMMUNICATION, tpdoDeleted);
CANmodule->CANerrorStatus |= CO_CAN_ERRTX_PDO_LATE;
}
}
/******************************************************************************/
void CO_CANverifyErrors(CO_CANmodule_t *CANmodule){
uint16_t rxErrors, txErrors, overflow;
CO_EM_t* em = (CO_EM_t*)CANmodule->em;
uint32_t err;
/* Get error counters from the module. If necessary, function may use
* different way to determine errors. */
static uint16_t rxErrors=0, txErrors=0, overflow=0;
/* get error counters from module. Id possible, function may use different way to
* determine errors. */
rxErrors = CANmodule->txSize;
txErrors = CANmodule->txSize;
overflow = CANmodule->txSize;
void CO_CANmodule_process(CO_CANmodule_t *CANmodule) {
uint32_t err;
err = ((uint32_t)txErrors << 16) | ((uint32_t)rxErrors << 8) | overflow;
if(CANmodule->errOld != err){
if (CANmodule->errOld != err) {
uint16_t status = CANmodule->CANerrorStatus;
CANmodule->errOld = err;
if(txErrors >= 256U){ /* bus off */
CO_errorReport(em, CO_EM_CAN_TX_BUS_OFF, CO_EMC_BUS_OFF_RECOVERED, err);
if (txErrors >= 256U) {
/* bus off */
status |= CO_CAN_ERRTX_BUS_OFF;
}
else{ /* not bus off */
CO_errorReset(em, CO_EM_CAN_TX_BUS_OFF, err);
else {
/* recalculate CANerrorStatus, first clear some flags */
status &= 0xFFFF ^ (CO_CAN_ERRTX_BUS_OFF |
CO_CAN_ERRRX_WARNING | CO_CAN_ERRRX_PASSIVE |
CO_CAN_ERRTX_WARNING | CO_CAN_ERRTX_PASSIVE);
if((rxErrors >= 96U) || (txErrors >= 96U)){ /* bus warning */
CO_errorReport(em, CO_EM_CAN_BUS_WARNING, CO_EMC_NO_ERROR, err);
/* rx bus warning or passive */
if (rxErrors >= 128) {
status |= CO_CAN_ERRRX_WARNING | CO_CAN_ERRRX_PASSIVE;
} else if (rxErrors >= 96) {
status |= CO_CAN_ERRRX_WARNING;
}
if(rxErrors >= 128U){ /* RX bus passive */
CO_errorReport(em, CO_EM_CAN_RX_BUS_PASSIVE, CO_EMC_CAN_PASSIVE, err);
}
else{
CO_errorReset(em, CO_EM_CAN_RX_BUS_PASSIVE, err);
/* tx bus warning or passive */
if (txErrors >= 128) {
status |= CO_CAN_ERRTX_WARNING | CO_CAN_ERRTX_PASSIVE;
} else if (rxErrors >= 96) {
status |= CO_CAN_ERRTX_WARNING;
}
if(txErrors >= 128U){ /* TX bus passive */
if(!CANmodule->firstCANtxMessage){
CO_errorReport(em, CO_EM_CAN_TX_BUS_PASSIVE, CO_EMC_CAN_PASSIVE, err);
}
}
else{
bool_t isError = CO_isError(em, CO_EM_CAN_TX_BUS_PASSIVE);
if(isError){
CO_errorReset(em, CO_EM_CAN_TX_BUS_PASSIVE, err);
CO_errorReset(em, CO_EM_CAN_TX_OVERFLOW, err);
}
}
if((rxErrors < 96U) && (txErrors < 96U)){ /* no error */
CO_errorReset(em, CO_EM_CAN_BUS_WARNING, err);
/* if not tx passive clear also overflow */
if ((status & CO_CAN_ERRTX_PASSIVE) == 0) {
status &= 0xFFFF ^ CO_CAN_ERRTX_OVERFLOW;
}
}
if(overflow != 0U){ /* CAN RX bus overflow */
CO_errorReport(em, CO_EM_CAN_RXB_OVERFLOW, CO_EMC_CAN_OVERRUN, err);
if (overflow != 0) {
/* CAN RX bus overflow */
status |= CO_CAN_ERRRX_OVERFLOW;
}
CANmodule->CANerrorStatus = status;
}
}

View file

@ -177,13 +177,13 @@ typedef struct {
uint16_t rxSize;
CO_CANtx_t *txArray;
uint16_t txSize;
uint16_t CANerrorStatus;
volatile bool_t CANnormal;
volatile bool_t useCANrxFilters;
volatile bool_t bufferInhibitFlag;
volatile bool_t firstCANtxMessage;
volatile uint16_t CANtxCount;
uint32_t errOld;
void *em;
} CO_CANmodule_t;

View file

@ -41,10 +41,6 @@
#include "301/CO_driver.h"
#include "CO_error.h"
#if CO_DRIVER_USE_EMERGENCY > 0
#include "301/CO_Emergency.h"
#endif
pthread_mutex_t CO_EMCY_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t CO_OD_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -249,8 +245,8 @@ CO_ReturnError_t CO_CANmodule_init(
CANmodule->rxSize = rxSize;
CANmodule->txArray = txArray;
CANmodule->txSize = txSize;
CANmodule->CANerrorStatus = 0;
CANmodule->CANnormal = false;
CANmodule->em = NULL; //this is set inside CO_Emergency.c init function!
CANmodule->fdTimerRead = -1;
#if CO_DRIVER_MULTI_INTERFACE > 0
for (i = 0; i < CO_CAN_MSG_SFF_MAX_COB_ID; i++) {
@ -663,6 +659,9 @@ static CO_ReturnError_t CO_CANCheckSendInterface(
else if (errno == ENOBUFS) {
/* socketCAN doesn't support blocking write. You can wait here for
* a few hundred us and then try again */
#if CO_DRIVER_ERROR_REPORTING > 0
interface->errorhandler.CANerrorStatus |= CO_CAN_ERRTX_OVERFLOW;
#endif
return CO_ERROR_TX_BUSY;
}
else if (n != CAN_MTU) {
@ -671,8 +670,8 @@ static CO_ReturnError_t CO_CANCheckSendInterface(
} while (errno != 0);
if(n != CAN_MTU){
#if CO_DRIVER_USE_EMERGENCY > 0
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, 0);
#if CO_DRIVER_ERROR_REPORTING > 0
interface->errorhandler.CANerrorStatus |= CO_CAN_ERRTX_OVERFLOW;
#endif
log_printf(LOG_ERR, DBG_CAN_TX_FAILED, buffer->ident, interface->ifName);
log_printf(LOG_DEBUG, DBG_ERRNO, "send()");
@ -710,9 +709,6 @@ CO_ReturnError_t CO_CANsend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
err = CO_CANCheckSend(CANmodule, buffer);
if (err == CO_ERROR_TX_BUSY) {
/* send doesn't have "busy" */
#if CO_DRIVER_USE_EMERGENCY > 0
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_TX_OVERFLOW, CO_EMC_CAN_OVERRUN, 0);
#endif
log_printf(LOG_ERR, DBG_CAN_TX_FAILED, buffer->ident, "CANx");
log_printf(LOG_DEBUG, DBG_ERRNO, "send()");
err = CO_ERROR_TX_OVERFLOW;
@ -758,13 +754,20 @@ void CO_CANclearPendingSyncPDOs(CO_CANmodule_t *CANmodule)
/******************************************************************************/
void CO_CANverifyErrors(CO_CANmodule_t *CANmodule)
void CO_CANmodule_process(CO_CANmodule_t *CANmodule)
{
(void)CANmodule;
/* socketCAN doesn't support microcontroller-like error counters. If an
* error has occured, a special can message is created by the driver and
* received by the application like a regular message.
* Therefore, error counter evaluation is included in rx function.*/
* Therefore, error counter evaluation is included in rx function.
* Here we just copy evaluated CANerrorStatus from the first CAN interface. */
#if CO_DRIVER_ERROR_REPORTING > 0
if (CANmodule->CANinterfaceCount > 0) {
CANmodule->CANerrorStatus =
CANmodule->CANinterfaces[0].errorhandler.CANerrorStatus;
}
#endif
}
@ -797,9 +800,8 @@ static CO_ReturnError_t CO_CANread(
n = recvmsg(interface->fd, &msghdr, 0);
if (n != CAN_MTU) {
#if CO_DRIVER_USE_EMERGENCY > 0
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_RXB_OVERFLOW,
CO_EMC_CAN_OVERRUN, n);
#if CO_DRIVER_ERROR_REPORTING > 0
interface->errorhandler.CANerrorStatus |= CO_CAN_ERRRX_OVERFLOW;
#endif
log_printf(LOG_DEBUG, DBG_CAN_RX_FAILED, interface->ifName);
log_printf(LOG_DEBUG, DBG_ERRNO, "recvmsg()");
@ -817,9 +819,8 @@ static CO_ReturnError_t CO_CANread(
else if (cmsg->cmsg_type == SO_RXQ_OVFL) {
dropped = *(uint32_t*)CMSG_DATA(cmsg);
if (dropped > CANmodule->rxDropCount) {
#if CO_DRIVER_USE_EMERGENCY > 0
CO_errorReport((CO_EM_t*)CANmodule->em, CO_EM_CAN_RXB_OVERFLOW,
CO_EMC_COMMUNICATION, 0);
#if CO_DRIVER_ERROR_REPORTING > 0
interface->errorhandler.CANerrorStatus |= CO_CAN_ERRRX_OVERFLOW;
#endif
log_printf(LOG_ERR, CAN_RX_SOCKET_QUEUE_OVERFLOW,
interface->ifName, dropped);

View file

@ -191,18 +191,6 @@ extern "C" {
#define CO_DRIVER_ERROR_REPORTING 1
#endif
/**
* Use CANopen Emergency object on CAN RX or TX overflow.
*
* If CO_DRIVER_USE_EMERGENCY is set to 1, then CANopen Emergency message will
* be sent, if CAN rx or tx bufers are overflowed.
*
* Macro is set to 1 (enabled) by default. It can be overridden.
*/
#ifndef CO_DRIVER_USE_EMERGENCY
#define CO_DRIVER_USE_EMERGENCY 1
#endif
/* skip this section for Doxygen, because it is documented in CO_driver.h */
#ifndef CO_DOXYGEN
@ -304,8 +292,8 @@ typedef struct {
uint32_t rxDropCount; /* messages dropped on rx socket queue */
CO_CANtx_t *txArray;
uint16_t txSize;
uint16_t CANerrorStatus;
volatile bool_t CANnormal;
void *em;
int fdEvent; /* notification event file descriptor */
int fdEpoll; /* epoll FD for event, CANrx sockets in all
interfaces and fdTimerRead */

View file

@ -32,6 +32,7 @@
#include <linux/can/error.h>
#include "CO_error.h"
#include "301/CO_driver.h"
/**
@ -98,6 +99,7 @@ static CO_CANinterfaceState_t CO_CANerrorBusoff(
* Restarting the interface is the only way to clear kernel and hardware
* tx queues */
result = CO_CANerrorSetListenOnly(CANerrorhandler, true);
CANerrorhandler->CANerrorStatus |= CO_CAN_ERRTX_BUS_OFF;
}
return result;
}
@ -117,25 +119,42 @@ static CO_CANinterfaceState_t CO_CANerrorCrtl(
* to do in here
* - we can't really do anything about buffer overflows here. Confirmed
* CANopen protocols will detect the error, non-confirmed protocols
* need to be error tolerant */
* need to be error tolerant.
* - There is no information, when CAN controller leaves warning level,
* so we can't clear it. So we also don't set it. */
if ((msg->can_id & CAN_ERR_CRTL) != 0) {
/* clear bus off here */
CANerrorhandler->CANerrorStatus &= 0xFFFF ^ CO_CAN_ERRTX_BUS_OFF;
if ((msg->data[1] & CAN_ERR_CRTL_RX_PASSIVE) != 0) {
log_printf(LOG_NOTICE, CAN_RX_PASSIVE, CANerrorhandler->ifName);
CANerrorhandler->CANerrorStatus |= CO_CAN_ERRRX_PASSIVE;
/* CANerrorhandler->CANerrorStatus |= CO_CAN_ERRRX_WARNING; */
}
else if ((msg->data[1] & CAN_ERR_CRTL_TX_PASSIVE) != 0) {
log_printf(LOG_NOTICE, CAN_TX_PASSIVE, CANerrorhandler->ifName);
CANerrorhandler->CANerrorStatus |= CO_CAN_ERRTX_PASSIVE;
/* CANerrorhandler->CANerrorStatus |= CO_CAN_ERRTX_WARNING; */
}
else if ((msg->data[1] & CAN_ERR_CRTL_RX_OVERFLOW) != 0) {
log_printf(LOG_NOTICE, CAN_RX_BUF_OVERFLOW, CANerrorhandler->ifName);
CANerrorhandler->CANerrorStatus |= CO_CAN_ERRRX_OVERFLOW;
}
else if ((msg->data[1] & CAN_ERR_CRTL_TX_OVERFLOW) != 0) {
log_printf(LOG_NOTICE, CAN_TX_BUF_OVERFLOW, CANerrorhandler->ifName);
CANerrorhandler->CANerrorStatus |= CO_CAN_ERRTX_OVERFLOW;
}
else if ((msg->data[1] & CAN_ERR_CRTL_RX_WARNING) != 0) {
log_printf(LOG_INFO, CAN_RX_LEVEL_WARNING, CANerrorhandler->ifName);
/* clear passive flag, set warning */
CANerrorhandler->CANerrorStatus &= 0x7FFF ^ CO_CAN_ERRRX_PASSIVE;
/* CANerrorhandler->CANerrorStatus |= CO_CAN_ERRRX_WARNING; */
}
else if ((msg->data[1] & CAN_ERR_CRTL_TX_WARNING) != 0) {
log_printf(LOG_INFO, CAN_TX_LEVEL_WARNING, CANerrorhandler->ifName);
/* clear passive flag, set warning */
CANerrorhandler->CANerrorStatus &= 0x7FFF ^ CO_CAN_ERRTX_PASSIVE;
/* CANerrorhandler->CANerrorStatus |= CO_CAN_ERRTX_WARNING; */
}
else if ((msg->data[1] & CAN_ERR_CRTL_ACTIVE) != 0) {
log_printf(LOG_NOTICE, CAN_TX_LEVEL_ACTIVE, CANerrorhandler->ifName);
@ -195,6 +214,7 @@ void CO_CANerror_init(
CANerrorhandler->listenOnly = false;
CANerrorhandler->timestamp.tv_sec = 0;
CANerrorhandler->timestamp.tv_nsec = 0;
CANerrorhandler->CANerrorStatus = 0;
}

View file

@ -116,6 +116,7 @@ typedef struct {
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;