CO_driver interface: remove Emergency object dependency for reporting CAN
errors, use CANerrorStatus own variable instead. Emergency object updated.
This commit is contained in:
parent
e1c7e2dbfa
commit
ca452c47cc
13 changed files with 212 additions and 120 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
27
CANopen.c
27
CANopen.c
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue