From e507bc923213f518cc8c9eb882060aa27337b582 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Wed, 23 Feb 2022 13:09:58 -0500 Subject: [PATCH 1/2] Added ability for isotp to have multiple active objects --- isotp.h | 22 ++++++++++++++++++---- isotp.tpp | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 8 deletions(-) diff --git a/isotp.h b/isotp.h index 6afda54..96539ba 100644 --- a/isotp.h +++ b/isotp.h @@ -41,6 +41,13 @@ #include "ESP32_CAN.h" #endif +enum ISOTP_FLOW +{ + FLOW_CTS = 0, + FLOW_WAIT= 1, + FLOW_ABORT = 2 +}; + typedef struct ISOTP_data { uint32_t id = 0; /* can identifier */ struct { @@ -50,7 +57,8 @@ typedef struct ISOTP_data { } flags; uint16_t len = 8; /* length of CAN message or callback payload */ uint16_t blockSize = 0; /* used for flow control, specify how many frame blocks per frame control request */ - uint8_t flow_control_type = 0; /* flow control type: 0: Clear to Send, 1: Wait, 2: Abort */ + uint16_t blockNum = 0; /* used with blockSize. This tracks how many blocks we're at. Redo flow control afterward */ + ISOTP_FLOW flow_control_type = FLOW_CTS; /* flow control type */ uint16_t separation_time = 0; /* time between frames */ } ISOTP_data; @@ -83,14 +91,20 @@ class isotp_Base { public: virtual void _process_frame_data(const CAN_message_t &msg) = 0; virtual void write(const ISOTP_data &config, const uint8_t *buf, uint16_t size) = 0; + void setBoundID(int32_t newID) { boundID = newID; } + void setBoundBus(int32_t bus) { boundBus = bus; } _isotp_cb_ptr _isotp_handler = nullptr; + static int buffer_hosts; + int thisBufferHost = 0; + int boundBus = -1; + int boundID = -1; }; -static isotp_Base* _ISOTP_OBJ = nullptr; +static isotp_Base* _ISOTP_OBJ[16] = { nullptr }; ISOTP_CLASS class isotp : public isotp_Base { public: - isotp() { _ISOTP_OBJ = this; } + isotp(); #if defined(TEENSYDUINO) // Teensy void setWriteBus(FlexCAN_T4_Base* _busWritePtr) { _isotp_busToWrite = _busWritePtr; } @@ -100,7 +114,7 @@ ISOTP_CLASS class isotp : public isotp_Base { void begin() { enable(); } void enable(bool yes = 1) { isotp_enabled = yes; } void setPadding(uint8_t _byte) { padding_value = _byte; } - void onReceive(_isotp_cb_ptr handler) { _ISOTP_OBJ->_isotp_handler = handler; } + void onReceive(_isotp_cb_ptr handler) { _ISOTP_OBJ[thisBufferHost]->_isotp_handler = handler; } void write(const ISOTP_data &config, const uint8_t *buf, uint16_t size); void write(const ISOTP_data &config, const char *buf, uint16_t size) { write(config, (const uint8_t*)buf, size); } void sendFlowControl(const ISOTP_data &config); diff --git a/isotp.tpp b/isotp.tpp index 9447ad8..b399080 100644 --- a/isotp.tpp +++ b/isotp.tpp @@ -31,7 +31,20 @@ #include #include "Arduino.h" +int isotp_Base::buffer_hosts = 0; +ISOTP_FUNC ISOTP_OPT::isotp() { + _ISOTP_OBJ[isotp_Base::buffer_hosts] = this; + thisBufferHost = isotp_Base::buffer_hosts; + isotp_Base::buffer_hosts++; +} + +//blocksize can be 0 in which case there is no counting. +//separation time can either be delay in ms if <= 127 or +//delay in microseconds if 0xF1 through 0xF9 but then +//it's the lower nibble * 100us +//currently this is not automatically being send by our reception +//but it could/should be. ISOTP_FUNC void ISOTP_OPT::sendFlowControl(const ISOTP_data &config) { CAN_message_t msg; msg.id = config.id; @@ -56,7 +69,6 @@ ISOTP_FUNC void ISOTP_OPT::sendFlowControl(const ISOTP_data &config) { } - ISOTP_FUNC void ISOTP_OPT::write(const ISOTP_data &config, const uint8_t *buf, uint16_t size) { CAN_message_t msg; msg.id = config.id; @@ -64,6 +76,11 @@ ISOTP_FUNC void ISOTP_OPT::write(const ISOTP_data &config, const uint8_t *buf, u if (size < 8) { /* single frame */ msg.len = size + 1; msg.buf[0] = size & 0x0f; + if (config.flags.usePadding) + { + for (int i = msg.len; i < 8; i++) msg.buf[i] = padding_value; + msg.len = 8; + } memmove(&msg.buf[1], &buf[0], size); _isotp_busToWrite->write(msg); return; @@ -76,6 +93,11 @@ ISOTP_FUNC void ISOTP_OPT::write(const ISOTP_data &config, const uint8_t *buf, u _isotp_busToWrite->write(msg); } + //this code should actually wait for the receiving side to send back a flow control + //message and then use those parameters instead of our own separation time. This would + //unfortunately then require that the code be able to be threaded or called somehow. + //It would require either a RTOS or calling the routine in a loop. The Arduino way + //would more correctly be having a loop function #if defined(TEENSYDUINO) // Teensy delay(constrain(config.separation_time, 0, 127)); #elif defined(ARDUINO_ARCH_ESP32) //ESP32 @@ -111,7 +133,7 @@ ISOTP_FUNC void ISOTP_OPT::_process_frame_data(const CAN_message_t &msg) { config.id = msg.id; config.len = msg.buf[0]; config.flags.extended = msg.flags.extended; - if ( _ISOTP_OBJ->_isotp_handler ) _ISOTP_OBJ->_isotp_handler(config, msg.buf + 1); + if ( _ISOTP_OBJ[thisBufferHost]->_isotp_handler ) _ISOTP_OBJ[thisBufferHost]->_isotp_handler(config, msg.buf + 1); } if ( (msg.buf[0] >> 4) == 1 ) { /* first frame */ @@ -120,6 +142,7 @@ ISOTP_FUNC void ISOTP_OPT::_process_frame_data(const CAN_message_t &msg) { memmove(data + 7, &msg.buf[0], 8); /* ID, ID, ID, ID, QPOS, QPOS, SEQUENCE: TOTAL 7 */ _rx_slots.findRemove(data, sizeof(data), 0, 1, 2, 3, 3); _rx_slots.push_back(data, sizeof(data)); + //really ought to send flow control msg here. Some remote nodes will require this before sending the rest of the frames } /* first frame */ if ( (msg.buf[0] >> 4) == 2 ) { /* consecutive frames */ @@ -142,7 +165,7 @@ ISOTP_FUNC void ISOTP_OPT::_process_frame_data(const CAN_message_t &msg) { config.id = ((uint32_t)(data[0] << 24) | data[1] << 16 | data[2] << 8 | data[3]); config.len = ((((uint16_t)data[7] & 0xF) << 8) | data[8]); config.flags.extended = msg.flags.extended; - if ( _ISOTP_OBJ->_isotp_handler ) _ISOTP_OBJ->_isotp_handler(config, data + 9); + if ( _ISOTP_OBJ[thisBufferHost]->_isotp_handler ) _ISOTP_OBJ[thisBufferHost]->_isotp_handler(config, data + 9); if ( ext_isotp_output1 ) ext_isotp_output1(config, data + 9); } } @@ -150,6 +173,17 @@ ISOTP_FUNC void ISOTP_OPT::_process_frame_data(const CAN_message_t &msg) { } +//catch the callback interrupt from the main library and process each registered ISOTP handler. +//Each one registers for an ID and a BUS and we only pass traffic if it matches. But -1 means wildcard +//and the wildcard is the default so this still works the same as it used to by default. void ext_output2(const CAN_message_t &msg) { - _ISOTP_OBJ->_process_frame_data(msg); + for ( int i = 0; i < isotp_Base::buffer_hosts; i++ ) + { + if ( _ISOTP_OBJ[i] ) + { + if ( (_ISOTP_OBJ[i]->boundBus < 0) || (_ISOTP_OBJ[i]->boundBus == msg.bus) ) + if ( (_ISOTP_OBJ[i]->boundID < 0) || (_ISOTP_OBJ[i]->boundID == msg.id) ) + _ISOTP_OBJ[i]->_process_frame_data(msg); + } + } } From b87483c67e8cc5335bd345644ab0f8bdce022241 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Thu, 8 Feb 2024 21:15:10 -0500 Subject: [PATCH 2/2] Add error checking to CAN3/FD interface, rework the rest of the error code to be more memory efficient --- FlexCAN_T4.h | 62 ++++++++++++++++++++++++++++++++++------- FlexCAN_T4.tpp | 19 +++++++------ FlexCAN_T4FD.tpp | 72 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 20 deletions(-) diff --git a/FlexCAN_T4.h b/FlexCAN_T4.h index fd34059..fdab38a 100644 --- a/FlexCAN_T4.h +++ b/FlexCAN_T4.h @@ -34,8 +34,41 @@ #include "circular_buffer.h" #include "imxrt_flexcan.h" +static const char* CAN_STATE_STRINGS[] = +{ + "Unknown", + "Idle", + "Not synchronized to CAN bus", + "Transmitting", + "Receiving" +}; + +static const char* CAN_FLTCONF_STRINGS[] = +{ + "Unknown", + "Error Active", + "Error Passive", + "Bus Off" +}; + +enum CAN_STATE +{ + CAN_STATE_UNK = 0, + CAN_STATE_IDLE, + CAN_STATE_NO_SYNC, + CAN_STATE_TX, + CAN_STATE_RX +}; + +enum FLT_CONF +{ + FLTCONF_UNK = 0, + FLTCONF_ERR_ACTIVE, + FLTCONF_ERR_PASSIVE, + FLTCONF_BUS_OFF +}; + typedef struct CAN_error_t { - char state[30] = "Idle"; bool BIT1_ERR = 0; bool BIT0_ERR = 0; bool ACK_ERR = 0; @@ -44,14 +77,19 @@ typedef struct CAN_error_t { bool STF_ERR = 0; bool TX_WRN = 0; bool RX_WRN = 0; - char FLT_CONF[14] = { 0 }; + bool BIT1_ERR_FD = 0; + bool BIT0_ERR_FD = 0; + bool CRC_ERR_FD = 0; + bool FRM_ERR_FD = 0; + bool STF_ERR_FD = 0; uint8_t RX_ERR_COUNTER = 0; uint8_t TX_ERR_COUNTER = 0; uint32_t ESR1 = 0; uint16_t ECR = 0; + CAN_STATE canState = CAN_STATE_UNK; + FLT_CONF fltConf = FLTCONF_UNK; } CAN_error_t; - typedef struct CAN_message_t { uint32_t id = 0; // can identifier uint16_t timestamp = 0; // FlexCAN time when message arrived @@ -329,6 +367,12 @@ class FlexCAN_T4_Base { virtual int write(const CAN_message_t &msg) = 0; virtual bool isFD() = 0; virtual uint8_t getFirstTxBoxSize(); + virtual bool error(CAN_error_t &error, bool printDetails); + virtual void printErrors(const CAN_error_t &error); + protected: + uint32_t nvicIrq = 0; + Circular_Buffer busESR1; + Circular_Buffer busECR; }; #if defined(__IMXRT1062__) @@ -374,6 +418,7 @@ FCTPFD_CLASS class FlexCAN_T4FD : public FlexCAN_T4_Base { void enableMBInterrupts(bool status = 1); void disableMBInterrupts() { enableMBInterrupts(0); } uint64_t events(); + bool error(CAN_error_t &error, bool printDetails); void onReceive(const FLEXCAN_MAILBOX &mb_num, _MBFD_ptr handler); /* individual mailbox callback function */ void onReceive(_MBFD_ptr handler); /* global callback function */ void setMBFilter(FLEXCAN_FLTEN input); /* enable/disable traffic for all MBs (for individual masking) */ @@ -406,6 +451,7 @@ FCTPFD_CLASS class FlexCAN_T4FD : public FlexCAN_T4_Base { void FLEXCAN_EnterFreezeMode(); void reset() { softReset(); } /* reset flexcan controller (needs register restore capabilities...) */ void flexcan_interrupt(); + void printErrors(const CAN_error_t &error); void writeIFLAG(uint64_t value); void writeIFLAGBit(uint8_t mb_num); uint8_t max_mailboxes(); @@ -419,7 +465,6 @@ FCTPFD_CLASS class FlexCAN_T4FD : public FlexCAN_T4_Base { void writeIMASKBit(uint8_t mb_num, bool set = 1); uint8_t busNumber; uint8_t mailbox_reader_increment = 0; - uint32_t nvicIrq = 0; uint8_t dlc_to_len(uint8_t val); uint8_t len_to_dlc(uint8_t val); uint32_t setBaudRateFD(CANFD_timings_t config, uint32_t flexdata_choice, bool advanced); /* internally used */ @@ -484,6 +529,7 @@ FCTP_CLASS class FlexCAN_T4 : public FlexCAN_T4_Base { int write(const CANFD_message_t &msg) { return 0; } /* to satisfy base class for external pointers */ int write(FLEXCAN_MAILBOX mb_num, const CAN_message_t &msg); /* use a single mailbox for transmitting */ uint64_t events(); + bool error(CAN_error_t &error, bool printDetails); uint8_t setRFFN(FLEXCAN_RFFN_TABLE rffn = RFFN_8); /* Number Of Rx FIFO Filters (0 == 8 filters, 1 == 16 filters, etc.. */ uint8_t setRFFN(uint8_t rffn) { return setRFFN((FLEXCAN_RFFN_TABLE)constrain(rffn, 0, 15)); } void setFIFOFilterTable(FLEXCAN_FIFOTABLE letter); @@ -511,7 +557,6 @@ FCTP_CLASS class FlexCAN_T4 : public FlexCAN_T4_Base { uint8_t getFirstTxBoxSize(){ return 8; } void FLEXCAN_ExitFreezeMode(); void FLEXCAN_EnterFreezeMode(); - bool error(CAN_error_t &error, bool printDetails); uint32_t getRXQueueCount() { return rxBuffer.size(); } uint32_t getTXQueueCount() { return txBuffer.size(); } @@ -520,12 +565,10 @@ FCTP_CLASS class FlexCAN_T4 : public FlexCAN_T4_Base { void writeTxMailbox(uint8_t mb_num, const CAN_message_t &msg); uint64_t readIMASK();// { return (((uint64_t)FLEXCANb_IMASK2(_bus) << 32) | FLEXCANb_IMASK1(_bus)); } void flexcan_interrupt(); + void printErrors(const CAN_error_t &error); void flexcanFD_interrupt() { ; } // dummy placeholder to satisfy base class Circular_Buffer rxBuffer; Circular_Buffer txBuffer; - Circular_Buffer busESR1; - Circular_Buffer busECR; - void printErrors(const CAN_error_t &error); #if defined(__IMXRT1062__) uint32_t getClock(); #endif @@ -550,8 +593,7 @@ FCTP_CLASS class FlexCAN_T4 : public FlexCAN_T4_Base { void writeIFLAG(uint64_t value); void writeIFLAGBit(uint8_t mb_num); void writeIMASK(uint64_t value); - void writeIMASKBit(uint8_t mb_num, bool set = 1); - uint32_t nvicIrq = 0; + void writeIMASKBit(uint8_t mb_num, bool set = 1); uint32_t currentBitrate = 0UL; uint8_t mailbox_reader_increment = 0; uint8_t busNumber; diff --git a/FlexCAN_T4.tpp b/FlexCAN_T4.tpp index cf8691f..ab210b2 100644 --- a/FlexCAN_T4.tpp +++ b/FlexCAN_T4.tpp @@ -1328,10 +1328,11 @@ FCTP_FUNC bool FCTP_OPT::error(CAN_error_t &error, bool printDetails) { error.ESR1 = busESR1.read(); error.ECR = busECR.read(); - if ( (error.ESR1 & 0x400C8) == 0x40080 ) strncpy((char*)error.state, "Idle", (sizeof(error.state) - 1)); - else if ( (error.ESR1 & 0x400C8) == 0x0 ) strncpy((char*)error.state, "Not synchronized to CAN bus", (sizeof(error.state) - 1)); - else if ( (error.ESR1 & 0x400C8) == 0x40040 ) strncpy((char*)error.state, "Transmitting", (sizeof(error.state) - 1)); - else if ( (error.ESR1 & 0x400C8) == 0x40008 ) strncpy((char*)error.state, "Receiving", (sizeof(error.state) - 1)); + error.canState = CAN_STATE_UNK; + if ( (error.ESR1 & 0x400C8) == 0x40080 ) error.canState = CAN_STATE_IDLE; + else if ( (error.ESR1 & 0x400C8) == 0x0 ) error.canState = CAN_STATE_NO_SYNC; + else if ( (error.ESR1 & 0x400C8) == 0x40040 ) error.canState = CAN_STATE_TX; + else if ( (error.ESR1 & 0x400C8) == 0x40008 ) error.canState = CAN_STATE_RX; error.BIT1_ERR = (error.ESR1 & (1UL << 15)) ? 1 : 0; error.BIT0_ERR = (error.ESR1 & (1UL << 14)) ? 1 : 0; @@ -1342,9 +1343,9 @@ FCTP_FUNC bool FCTP_OPT::error(CAN_error_t &error, bool printDetails) { error.TX_WRN = (error.ESR1 & (1UL << 9)) ? 1 : 0; error.RX_WRN = (error.ESR1 & (1UL << 8)) ? 1 : 0; - if ( (error.ESR1 & 0x30) == 0x0 ) strncpy((char*)error.FLT_CONF, "Error Active", (sizeof(error.FLT_CONF) - 1)); - else if ( (error.ESR1 & 0x30) == 0x1 ) strncpy((char*)error.FLT_CONF, "Error Passive", (sizeof(error.FLT_CONF) - 1)); - else strncpy((char*)error.FLT_CONF, "Bus off", (sizeof(error.FLT_CONF) - 1)); + if ( (error.ESR1 & 0x30) == 0x0 ) error.fltConf = FLTCONF_ERR_ACTIVE; + else if ( (error.ESR1 & 0x30) == 0x1 ) error.fltConf = FLTCONF_ERR_PASSIVE; + else error.fltConf = FLTCONF_BUS_OFF; error.RX_ERR_COUNTER = (uint8_t)(error.ECR >> 8); error.TX_ERR_COUNTER = (uint8_t)error.ECR; @@ -1355,7 +1356,7 @@ FCTP_FUNC bool FCTP_OPT::error(CAN_error_t &error, bool printDetails) { } FCTP_FUNC void FCTP_OPT::printErrors(const CAN_error_t &error) { - Serial.print("FlexCAN State: "); Serial.print((char*)error.state); + Serial.print("FlexCAN State: "); Serial.print(CAN_STATE_STRINGS[(int)error.canState]); if ( error.BIT1_ERR ) Serial.print(", BIT1_ERR"); if ( error.BIT0_ERR ) Serial.print(", BIT0_ERR"); if ( error.ACK_ERR ) Serial.print(", ACK_ERR"); @@ -1364,7 +1365,7 @@ FCTP_FUNC void FCTP_OPT::printErrors(const CAN_error_t &error) { if ( error.STF_ERR ) Serial.print(", STF_ERR"); if ( error.RX_WRN ) Serial.printf(", RX_WRN: %d", error.RX_ERR_COUNTER); if ( error.TX_WRN ) Serial.printf(", TX_WRN: %d", error.TX_ERR_COUNTER); - Serial.printf(", FLT_CONF: %s\n", (char*)error.FLT_CONF); + Serial.printf(", FLT_CONF: %s\n", CAN_FLTCONF_STRINGS[(int)error.fltConf]); } FCTP_FUNC void FCTP_OPT::enableDMA(bool state) { /* only CAN3 supports this on 1062, untested */ diff --git a/FlexCAN_T4FD.tpp b/FlexCAN_T4FD.tpp index 7480ad0..f8fddd3 100644 --- a/FlexCAN_T4FD.tpp +++ b/FlexCAN_T4FD.tpp @@ -89,6 +89,64 @@ FCTPFD_FUNC void FCTPFD_OPT::begin() { NVIC_ENABLE_IRQ(nvicIrq); } +FCTPFD_FUNC bool FCTPFD_OPT::error(CAN_error_t &error, bool printDetails) { + if ( !busESR1.size() ) return 0; + NVIC_DISABLE_IRQ(nvicIrq); + error.ESR1 = busESR1.read(); + error.ECR = busECR.read(); + + error.canState = CAN_STATE_UNK; + if ( (error.ESR1 & 0x400C8) == 0x40080 ) error.canState = CAN_STATE_IDLE; + else if ( (error.ESR1 & 0x400C8) == 0x0 ) error.canState = CAN_STATE_NO_SYNC; + else if ( (error.ESR1 & 0x400C8) == 0x40040 ) error.canState = CAN_STATE_TX; + else if ( (error.ESR1 & 0x400C8) == 0x40008 ) error.canState = CAN_STATE_RX; + + error.BIT1_ERR = (error.ESR1 & (1UL << 15)) ? 1 : 0; + error.BIT0_ERR = (error.ESR1 & (1UL << 14)) ? 1 : 0; + error.ACK_ERR = (error.ESR1 & (1UL << 13)) ? 1 : 0; + error.CRC_ERR = (error.ESR1 & (1UL << 12)) ? 1 : 0; + error.FRM_ERR = (error.ESR1 & (1UL << 11)) ? 1 : 0; + error.STF_ERR = (error.ESR1 & (1UL << 10)) ? 1 : 0; + error.TX_WRN = (error.ESR1 & (1UL << 9)) ? 1 : 0; + error.RX_WRN = (error.ESR1 & (1UL << 8)) ? 1 : 0; + error.BIT1_ERR_FD = (error.ESR1 & (1UL << 31)) ? 1 : 0; + error.BIT0_ERR_FD = (error.ESR1 & (1UL << 30)) ? 1 : 0; + error.CRC_ERR_FD = (error.ESR1 & (1UL << 28)) ? 1 : 0; + error.FRM_ERR_FD = (error.ESR1 & (1UL << 27)) ? 1 : 0; + error.STF_ERR_FD = (error.ESR1 & (1UL << 26)) ? 1 : 0; + + if ( (error.ESR1 & 0x30) == 0x0 ) error.fltConf = FLTCONF_ERR_ACTIVE; + else if ( (error.ESR1 & 0x30) == 0x1 ) error.fltConf = FLTCONF_ERR_PASSIVE; + else error.fltConf = FLTCONF_BUS_OFF; + + error.RX_ERR_COUNTER = (uint8_t)(error.ECR >> 8); + error.TX_ERR_COUNTER = (uint8_t)error.ECR; + + if ( printDetails ) printErrors(error); + NVIC_ENABLE_IRQ(nvicIrq); + return 1; +} + +FCTPFD_FUNC void FCTPFD_OPT::printErrors(const CAN_error_t &error) { + Serial.print("FlexCAN State: "); Serial.print(CAN_STATE_STRINGS[(int)error.canState]); + if ( error.BIT1_ERR ) Serial.print(", BIT1_ERR"); + if ( error.BIT0_ERR ) Serial.print(", BIT0_ERR"); + if ( error.ACK_ERR ) Serial.print(", ACK_ERR"); + if ( error.CRC_ERR ) Serial.print(", CRC_ERR"); + if ( error.FRM_ERR ) Serial.print(", FRM_ERR"); + if ( error.STF_ERR ) Serial.print(", STF_ERR"); + + if ( error.BIT1_ERR_FD ) Serial.print(", BIT1_ERR_FD"); + if ( error.BIT0_ERR_FD ) Serial.print(", BIT0_ERR_FD"); + if ( error.CRC_ERR_FD ) Serial.print(", CRC_ERR_FD"); + if ( error.FRM_ERR_FD ) Serial.print(", FRM_ERR_FD"); + if ( error.STF_ERR_FD ) Serial.print(", STF_ERR_FD"); + + if ( error.RX_WRN ) Serial.printf(", RX_WRN: %d", error.RX_ERR_COUNTER); + if ( error.TX_WRN ) Serial.printf(", TX_WRN: %d", error.TX_ERR_COUNTER); + Serial.printf(", FLT_CONF: %s\n", CAN_FLTCONF_STRINGS[(int)error.fltConf]); +} + FCTPFD_FUNC uint8_t FCTPFD_OPT::setRegions(uint8_t size) { FLEXCAN_EnterFreezeMode(); FLEXCANb_FDCTRL(_bus) &= ~0x1B0000; /* clear both memory region bits */ @@ -473,7 +531,19 @@ FCTPFD_FUNC void FCTPFD_OPT::flexcan_interrupt() { ext_outputFD3(msg); } } - FLEXCANb_ESR1(_bus) = FLEXCANb_ESR1(_bus); + + uint32_t esr1 = FLEXCANb_ESR1(_bus); + static uint32_t last_esr1 = 0; + if ( (last_esr1 & 0x7FFBF) != (esr1 & 0x7FFBF) ) { + if ( busESR1.size() < busESR1.capacity() ) { + busESR1.write(esr1); + busECR.write(FLEXCANb_ECR(_bus)); + last_esr1 = esr1; + } + } + FLEXCANb_ESR1(_bus) |= esr1; + + asm volatile ("dsb"); } FCTPFD_FUNC void FCTPFD_OPT::struct2queueRx(const CANFD_message_t &msg) {