Merge pull request #1480 from dalathegreat/bugfix/foxess-can-crash

Restore CAN-FD library to v2.1.4
This commit is contained in:
Daniel Öster 2025-09-02 18:28:33 +03:00 committed by GitHub
commit 77b1844151
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 624 additions and 591 deletions

View file

@ -1,20 +1,20 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD, CANFD mode // A CAN driver for MCP2517FD, CANFD mode
// by Pierre Molinaro // by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FD.h" #include "ACAN2517FD.h"
#include "../../system_settings.h" //Contains task priority //Modded by Battery-Emulator #include "../../system_settings.h" //Contains task priority
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static const uint8_t TXBWS = 0 ; static const uint8_t TXBWS = 0 ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// Note about ESP32 // Note about ESP32
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// //
// It appears that Arduino ESP32 interrupts are managed in a completely different way from "usual" Arduino: // It appears that Arduino ESP32 interrupts are managed in a completely different way from "usual" Arduino:
// - SPI.usingInterrupt is not implemented; // - SPI.usingInterrupt is not implemented;
@ -43,7 +43,7 @@ static const uint8_t TXBWS = 0 ;
// #endif // #endif
// mSPI.endTransaction () ; // mSPI.endTransaction () ;
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
static void myESP32Task (void * pData) { static void myESP32Task (void * pData) {
@ -55,9 +55,9 @@ static const uint8_t TXBWS = 0 ;
} }
#endif #endif
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// ACAN2517FD register addresses // ACAN2517FD register addresses
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static const uint16_t CON_REGISTER = 0x000 ; static const uint16_t CON_REGISTER = 0x000 ;
static const uint16_t NBTCFG_REGISTER = 0x004 ; static const uint16_t NBTCFG_REGISTER = 0x004 ;
@ -68,85 +68,85 @@ static const uint16_t TREC_REGISTER = 0x034 ;
static const uint16_t BDIAG0_REGISTER = 0x038 ; static const uint16_t BDIAG0_REGISTER = 0x038 ;
static const uint16_t BDIAG1_REGISTER = 0x03C ; static const uint16_t BDIAG1_REGISTER = 0x03C ;
//------------------------------------------------------------------------------ //······················································································································
// TXQ REGISTERS // TXQ REGISTERS
//------------------------------------------------------------------------------ //······················································································································
static const uint16_t TXQCON_REGISTER = 0x050 ; static const uint16_t TXQCON_REGISTER = 0x050 ;
static const uint16_t TXQSTA_REGISTER = 0x054 ; static const uint16_t TXQSTA_REGISTER = 0x054 ;
static const uint16_t TXQUA_REGISTER = 0x058 ; static const uint16_t TXQUA_REGISTER = 0x058 ;
//------------------------------------------------------------------------------ //······················································································································
// INTERRUPT REGISTERS // INTERRUPT REGISTERS
//------------------------------------------------------------------------------ //······················································································································
static const uint16_t INT_REGISTER = 0x01C ; static const uint16_t INT_REGISTER = 0x01C ;
//------------------------------------------------------------------------------ //······················································································································
// FIFO REGISTERS // FIFO REGISTERS
//------------------------------------------------------------------------------ //······················································································································
static uint16_t FIFOCON_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 static uint16_t FIFOCON_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x05C + 12 * (inFIFOIndex - 1) ; return 0x05C + 12 * (inFIFOIndex - 1) ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint16_t FIFOSTA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 static uint16_t FIFOSTA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x060 + 12 * (inFIFOIndex - 1) ; return 0x060 + 12 * (inFIFOIndex - 1) ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint16_t FIFOUA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31 static uint16_t FIFOUA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x064 + 12 * (inFIFOIndex - 1) ; return 0x064 + 12 * (inFIFOIndex - 1) ;
} }
//------------------------------------------------------------------------------ //······················································································································
// FILTER REGISTERS // FILTER REGISTERS
//------------------------------------------------------------------------------ //······················································································································
static uint16_t FLTCON_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 58) static uint16_t FLTCON_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 58)
return 0x1D0 + inFilterIndex ; return 0x1D0 + inFilterIndex ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint16_t FLTOBJ_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 60) static uint16_t FLTOBJ_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 60)
return 0x1F0 + 8 * inFilterIndex ; return 0x1F0 + 8 * inFilterIndex ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint16_t MASK_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 61) static uint16_t MASK_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 61)
return 0x1F4 + 8 * inFilterIndex ; return 0x1F4 + 8 * inFilterIndex ;
} }
//------------------------------------------------------------------------------ //······················································································································
// OSCILLATOR REGISTER // OSCILLATOR REGISTER
//------------------------------------------------------------------------------ //······················································································································
static const uint16_t OSC_REGISTER = 0xE00 ; static const uint16_t OSC_REGISTER = 0xE00 ;
//------------------------------------------------------------------------------ //······················································································································
// INPUT / OUPUT CONTROL REGISTER // INPUT / OUPUT CONTROL REGISTER
//------------------------------------------------------------------------------ //······················································································································
static const uint16_t IOCON_REGISTER_00_07 = 0xE04 ; static const uint16_t IOCON_REGISTER_00_07 = 0xE04 ;
static const uint16_t IOCON_REGISTER_08_15 = 0xE05 ; static const uint16_t IOCON_REGISTER_08_15 = 0xE05 ;
static const uint16_t IOCON_REGISTER_16_23 = 0xE06 ; static const uint16_t IOCON_REGISTER_16_23 = 0xE06 ;
static const uint16_t IOCON_REGISTER_24_31 = 0xE07 ; static const uint16_t IOCON_REGISTER_24_31 = 0xE07 ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// RECEIVE FIFO INDEX // RECEIVE FIFO INDEX
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static const uint8_t RECEIVE_FIFO_INDEX = 1 ; static const uint8_t RECEIVE_FIFO_INDEX = 1 ;
static const uint8_t TRANSMIT_FIFO_INDEX = 2 ; static const uint8_t TRANSMIT_FIFO_INDEX = 2 ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// BYTE BUFFER UTILITY FUNCTIONS // BYTE BUFFER UTILITY FUNCTIONS
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static void enterU32InBufferAtIndex (const uint32_t inValue, uint8_t ioBuffer [], const uint8_t inIndex) { static void enterU32InBufferAtIndex (const uint32_t inValue, uint8_t ioBuffer [], const uint8_t inIndex) {
ioBuffer [inIndex + 0] = (uint8_t) inValue ; ioBuffer [inIndex + 0] = (uint8_t) inValue ;
@ -155,7 +155,7 @@ static void enterU32InBufferAtIndex (const uint32_t inValue, uint8_t ioBuffer []
ioBuffer [inIndex + 3] = (uint8_t) (inValue >> 24) ; ioBuffer [inIndex + 3] = (uint8_t) (inValue >> 24) ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint32_t u32FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) { static uint32_t u32FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) {
uint32_t result = (uint32_t) ioBuffer [inIndex + 0] ; uint32_t result = (uint32_t) ioBuffer [inIndex + 0] ;
@ -165,7 +165,7 @@ static uint32_t u32FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex
return result ; return result ;
} }
//------------------------------------------------------------------------------ //······················································································································
static uint16_t u16FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) { static uint16_t u16FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) {
uint16_t result = (uint16_t) ioBuffer [inIndex + 0] ; uint16_t result = (uint16_t) ioBuffer [inIndex + 0] ;
@ -173,7 +173,8 @@ static uint16_t u16FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static inline void turnOffInterrupts () { static inline void turnOffInterrupts () {
#ifndef DISABLEMCP2517FDCOMPAT #ifndef DISABLEMCP2517FDCOMPAT
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
@ -208,6 +209,7 @@ mINT (inINT),
mUsesTXQ (false), mUsesTXQ (false),
mHardwareTxFIFOFull (false), mHardwareTxFIFOFull (false),
mRxInterruptEnabled (true), mRxInterruptEnabled (true),
mHasDataBitRate (false),
mTransmitFIFOPayload (0), mTransmitFIFOPayload (0),
mTXQBufferPayload (0), mTXQBufferPayload (0),
mReceiveFIFOPayload (0), mReceiveFIFOPayload (0),
@ -221,7 +223,7 @@ mDriverTransmitBuffer ()
{ {
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings, uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
void (* inInterruptServiceRoutine) (void)) { void (* inInterruptServiceRoutine) (void)) {
@ -232,7 +234,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
return begin (inSettings, inInterruptServiceRoutine, filters) ; return begin (inSettings, inInterruptServiceRoutine, filters) ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings, uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
void (* inInterruptServiceRoutine) (void), void (* inInterruptServiceRoutine) (void),
@ -501,6 +503,8 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
// bits 11-8: TSEG2 - 1 // bits 11-8: TSEG2 - 1
// bits 7-4: unused // bits 7-4: unused
// bits 3-0: SJW - 1 // bits 3-0: SJW - 1
mHasDataBitRate = inSettings.mDataBitRateFactor != ::DataBitRateFactor::x1 ;
if (mHasDataBitRate) {
data = inSettings.mBitRatePrescaler - 1 ; data = inSettings.mBitRatePrescaler - 1 ;
data <<= 8 ; data <<= 8 ;
data |= inSettings.mDataPhaseSegment1 - 1 ; data |= inSettings.mDataPhaseSegment1 - 1 ;
@ -509,6 +513,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
data <<= 8 ; data <<= 8 ;
data |= inSettings.mDataSJW - 1 ; data |= inSettings.mDataSJW - 1 ;
writeRegister32 (DBTCFG_REGISTER, data) ; writeRegister32 (DBTCFG_REGISTER, data) ;
}
//----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24) //----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24)
// bits 7-4: Transmit Bandwith Sharing Bits ---> 0 // bits 7-4: Transmit Bandwith Sharing Bits ---> 0
// bit 3: Abort All Pending Transmissions bit --> 0 // bit 3: Abort All Pending Transmissions bit --> 0
@ -526,14 +531,14 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
} }
} }
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
xTaskCreate (myESP32Task, "ACAN2517Handler", 1024, this, TASK_ACAN2517FD_PRIORITY, &mESP32TaskHandle) ; //Modded by Battery-Emulator xTaskCreate (myESP32Task, "ACAN2517Handler", 1024, this, TASK_ACAN2517FD_PRIORITY, &mESP32TaskHandle) ;
#endif #endif
if (mINT != 255) { // 255 means interrupt is not used if (mINT != 255) { // 255 means interrupt is not used
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ; attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ;
#else #else
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ; // Thank to Flole998 attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ; // Thank to Flole998
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
#endif #endif
} }
// If you begin() multiple times without constructor, // If you begin() multiple times without constructor,
@ -545,9 +550,9 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
return errorCode ; return errorCode ;
} }
//------------------------------------------------------------------------------ //······················································································································
// end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin) // end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin)
//------------------------------------------------------------------------------ //······················································································································
bool ACAN2517FD::end (void) { bool ACAN2517FD::end (void) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -592,19 +597,15 @@ bool ACAN2517FD::end (void) {
return ok ; return ok ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// SEND FRAME // SEND FRAME
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) { bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) {
bool ok = inMessage.isValid () ; bool ok = inMessage.isValid () ;
if (ok) { if (ok) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
#ifdef ARDUINO_ARCH_ESP32 turnOffInterrupts () ;
taskDISABLE_INTERRUPTS () ;
#else
noInterrupts () ;
#endif
if (inMessage.idx == 0) { if (inMessage.idx == 0) {
ok = inMessage.len <= mTransmitFIFOPayload ; ok = inMessage.len <= mTransmitFIFOPayload ;
if (ok) { if (ok) {
@ -622,7 +623,7 @@ bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) {
return ok ; return ok ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) { bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
bool result ; bool result ;
@ -644,7 +645,7 @@ bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
static uint32_t lengthCodeForLength (const uint8_t inLength) { static uint32_t lengthCodeForLength (const uint8_t inLength) {
uint32_t result = inLength & 0x0F ; uint32_t result = inLength & 0x0F ;
@ -660,7 +661,7 @@ static uint32_t lengthCodeForLength (const uint8_t inLength) {
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) { void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
const uint16_t ramAddr = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (TRANSMIT_FIFO_INDEX))) ; const uint16_t ramAddr = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (TRANSMIT_FIFO_INDEX))) ;
@ -685,7 +686,9 @@ void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
break ; break ;
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH : case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit flags |= 1 << 7 ; // Set FDF bit
if (mHasDataBitRate) {
flags |= 1 << 6 ; // Set BRS bit flags |= 1 << 6 ; // Set BRS bit
}
break ; break ;
} }
//--- Word count //--- Word count
@ -711,7 +714,7 @@ void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 1, data8); writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 1, data8);
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) { bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
bool ok = mUsesTXQ ; bool ok = mUsesTXQ ;
@ -748,7 +751,9 @@ bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
break ; break ;
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH : case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit flags |= 1 << 7 ; // Set FDF bit
if (mHasDataBitRate) {
flags |= 1 << 6 ; // Set BRS bit flags |= 1 << 6 ; // Set BRS bit
}
break ; break ;
} }
//--- Word count //--- Word count
@ -777,9 +782,9 @@ bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
return ok ; return ok ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// RECEIVE FRAME // RECEIVE FRAME
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::available (void) { bool ACAN2517FD::available (void) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -790,35 +795,28 @@ bool ACAN2517FD::available (void) {
return hasReceivedMessage ; return hasReceivedMessage ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::receive (CANFDMessage & outMessage) { bool ACAN2517FD::receive (CANFDMessage & outMessage) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const bool hasReceivedMessage = mDriverReceiveBuffer.remove (outMessage) ; const bool hasReceivedMessage = mDriverReceiveBuffer.remove (outMessage) ;
//--- If receive interrupt is disabled, enable it (added in release 2.17) //--- If receive interrupt is disabled, enable it (added in release 2.17)
if (mINT == 255) { // No interrupt pin if (mINT == 255) { // No interrupt pin
mRxInterruptEnabled = true ; mRxInterruptEnabled = true ;
isr_poll_core () ; // Perform polling isr_poll_core () ; // Perform polling
}else if (!mRxInterruptEnabled) { }else if (!mRxInterruptEnabled) {
mSPI.beginTransaction (mSPISettings) ;
#ifdef ARDUINO_ARCH_ESP32
taskDISABLE_INTERRUPTS () ;
#else
noInterrupts () ;
#endif
mRxInterruptEnabled = true ; mRxInterruptEnabled = true ;
uint8_t data8 = readRegister8Assume_SPI_transaction (INT_REGISTER + 2) ; uint8_t data8 = readRegister8Assume_SPI_transaction (INT_REGISTER + 2) ;
data8 |= (1 << 1) ; // Receive FIFO Interrupt Enable data8 |= (1 << 1) ; // Receive FIFO Interrupt Enable
writeRegister8Assume_SPI_transaction (INT_REGISTER + 2, data8) ; writeRegister8Assume_SPI_transaction (INT_REGISTER + 2, data8) ;
}
turnOnInterrupts(); turnOnInterrupts();
mSPI.endTransaction () ; mSPI.endTransaction () ;
}
return hasReceivedMessage ; return hasReceivedMessage ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMatchCallBack) { bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMatchCallBack) {
CANFDMessage receivedMessage ; CANFDMessage receivedMessage ;
@ -836,9 +834,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
return hasReceived ; return hasReceived ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// POLLING (ESP32) // POLLING (ESP32)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) { void ACAN2517FD::poll (void) {
@ -848,22 +846,22 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
} }
#endif #endif
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// POLLING (other than ESP32) // POLLING (other than ESP32)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifndef ARDUINO_ARCH_ESP32 #ifndef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) { void ACAN2517FD::poll (void) {
noInterrupts () ; turnOffInterrupts () ;
isr_poll_core () ; isr_poll_core () ;
interrupts () ; turnOnInterrupts () ;
} }
#endif #endif
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINE (ESP32) // INTERRUPT SERVICE ROUTINE (ESP32)
// https://stackoverflow.com/questions/51750377/how-to-disable-interrupt-watchdog-in-esp32-or-increase-isr-time-limit // https://stackoverflow.com/questions/51750377/how-to-disable-interrupt-watchdog-in-esp32-or-increase-isr-time-limit
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
void ACAN2517FD::isr (void) { void ACAN2517FD::isr (void) {
@ -873,9 +871,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
} }
#endif #endif
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINE (other than ESP32) // INTERRUPT SERVICE ROUTINE (other than ESP32)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifndef ARDUINO_ARCH_ESP32 #ifndef ARDUINO_ARCH_ESP32
void ACAN2517FD::isr (void) { void ACAN2517FD::isr (void) {
@ -883,9 +881,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
} }
#endif #endif
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINES (common) // INTERRUPT SERVICE ROUTINES (common)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::isr_poll_core (void) { void ACAN2517FD::isr_poll_core (void) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -935,7 +933,7 @@ void ACAN2517FD::isr_poll_core (void) {
mSPI.endTransaction () ; mSPI.endTransaction () ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FIFO is not full void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FIFO is not full
CANFDMessage message ; CANFDMessage message ;
@ -950,7 +948,7 @@ void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FI
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::receiveInterrupt (void) { void ACAN2517FD::receiveInterrupt (void) {
const uint16_t ramAddress = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (RECEIVE_FIFO_INDEX))) ; const uint16_t ramAddress = uint16_t (0x400 + readRegister32Assume_SPI_transaction (FIFOUA_REGISTER (RECEIVE_FIFO_INDEX))) ;
@ -1009,9 +1007,9 @@ void ACAN2517FD::receiveInterrupt (void) {
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// MCP2517FD REGISTER ACCESS, SECOND LEVEL FUNCTIONS (HANDLE CS, ASSUME WITHIN SPI TRANSACTION) // MCP2517FD REGISTER ACCESS, SECOND LEVEL FUNCTIONS (HANDLE CS, ASSUME WITHIN SPI TRANSACTION)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress, void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress,
const uint32_t inValue) { const uint32_t inValue) {
@ -1029,7 +1027,7 @@ void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegiste
deassertCS () ; deassertCS () ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress, void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress,
const uint8_t inValue) { const uint8_t inValue) {
@ -1044,7 +1042,7 @@ void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegister
deassertCS () ; deassertCS () ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::readRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress) { uint32_t ACAN2517FD::readRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- Read word register via 6-byte buffer (speed enhancement, thanks to thomasfla) //--- Read word register via 6-byte buffer (speed enhancement, thanks to thomasfla)
@ -1063,7 +1061,7 @@ uint32_t ACAN2517FD::readRegister32Assume_SPI_transaction (const uint16_t inRegi
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint16_t ACAN2517FD::readRegister16Assume_SPI_transaction (const uint16_t inRegisterAddress) { uint16_t ACAN2517FD::readRegister16Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- Read half-word register via 4-byte buffer (speed enhancement, thanks to thomasfla) //--- Read half-word register via 4-byte buffer (speed enhancement, thanks to thomasfla)
@ -1082,7 +1080,7 @@ uint16_t ACAN2517FD::readRegister16Assume_SPI_transaction (const uint16_t inRegi
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint8_t ACAN2517FD::readRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress) { uint8_t ACAN2517FD::readRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- Read byte register via 3-byte buffer (speed enhancement, thanks to thomasfla) //--- Read byte register via 3-byte buffer (speed enhancement, thanks to thomasfla)
@ -1096,9 +1094,9 @@ uint8_t ACAN2517FD::readRegister8Assume_SPI_transaction (const uint16_t inRegist
return buffer [2] ; return buffer [2] ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// MCP2517FD REGISTER ACCESS, THIRD LEVEL FUNCTIONS (HANDLE CS AND SPI TRANSACTION) // MCP2517FD REGISTER ACCESS, THIRD LEVEL FUNCTIONS (HANDLE CS AND SPI TRANSACTION)
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t inValue) { void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t inValue) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -1108,7 +1106,7 @@ void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t
mSPI.endTransaction () ; mSPI.endTransaction () ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint8_t ACAN2517FD::readRegister8 (const uint16_t inRegisterAddress) { uint8_t ACAN2517FD::readRegister8 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -1119,7 +1117,7 @@ turnOnInterrupts () ;
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint16_t ACAN2517FD::readRegister16 (const uint16_t inRegisterAddress) { uint16_t ACAN2517FD::readRegister16 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -1130,7 +1128,7 @@ turnOnInterrupts () ;
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister32 (const uint16_t inRegisterAddress, const uint32_t inValue) { void ACAN2517FD::writeRegister32 (const uint16_t inRegisterAddress, const uint32_t inValue) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -1140,7 +1138,7 @@ turnOnInterrupts () ;
mSPI.endTransaction () ; mSPI.endTransaction () ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::readRegister32 (const uint16_t inRegisterAddress) { uint32_t ACAN2517FD::readRegister32 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ; mSPI.beginTransaction (mSPISettings) ;
@ -1151,16 +1149,16 @@ turnOnInterrupts () ;
return result ; return result ;
} }
//------------------------------------------------------------------------------ //······················································································································
// Current MCP2517FD Operation Mode // Current MCP2517FD Operation Mode
//------------------------------------------------------------------------------ //······················································································································
ACAN2517FDSettings::OperationMode ACAN2517FD::currentOperationMode (void) { ACAN2517FDSettings::OperationMode ACAN2517FD::currentOperationMode (void) {
const uint8_t mode = readRegister8 (CON_REGISTER + 2) >> 5 ; const uint8_t mode = readRegister8 (CON_REGISTER + 2) >> 5 ;
return ACAN2517FDSettings::OperationMode (mode) ; return ACAN2517FDSettings::OperationMode (mode) ;
} }
//------------------------------------------------------------------------------ //······················································································································
bool ACAN2517FD::recoverFromRestrictedOperationMode (void) { bool ACAN2517FD::recoverFromRestrictedOperationMode (void) {
bool recoveryDone = false ; bool recoveryDone = false ;
@ -1184,9 +1182,9 @@ bool ACAN2517FD::recoverFromRestrictedOperationMode (void) {
return recoveryDone ; return recoveryDone ;
} }
//------------------------------------------------------------------------------ //······················································································································
// Set MCP2517FD Operation Mode // Set MCP2517FD Operation Mode
//------------------------------------------------------------------------------ //······················································································································
void ACAN2517FD::setOperationMode (const ACAN2517FDSettings::OperationMode inOperationMode) { void ACAN2517FD::setOperationMode (const ACAN2517FDSettings::OperationMode inOperationMode) {
// bits 7-4: Transmit Bandwith Sharing Bits ---> 0 // bits 7-4: Transmit Bandwith Sharing Bits ---> 0
@ -1194,7 +1192,7 @@ void ACAN2517FD::setOperationMode (const ACAN2517FDSettings::OperationMode inOpe
writeRegister8 (CON_REGISTER + 3, uint8_t (inOperationMode)); writeRegister8 (CON_REGISTER + 3, uint8_t (inOperationMode));
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::reset2517FD (void) { void ACAN2517FD::reset2517FD (void) {
mSPI.beginTransaction (mSPISettings) ; // Check RESET is performed with 800 kHz clock mSPI.beginTransaction (mSPISettings) ; // Check RESET is performed with 800 kHz clock
@ -1206,10 +1204,10 @@ turnOnInterrupts () ;
mSPI.endTransaction () ; mSPI.endTransaction () ;
} }
//------------------------------------------------------------------------------ //······················································································································
// Sleep Mode to Configuration Mode // Sleep Mode to Configuration Mode
// (returns true if MCP2517FD was in sleep mode) // (returns true if MCP2517FD was in sleep mode)
//------------------------------------------------------------------------------ //······················································································································
// The device exits Sleep mode due to a dominant edge on RXCAN or by enabling the oscillator (clearing OSC.OSCDIS). // The device exits Sleep mode due to a dominant edge on RXCAN or by enabling the oscillator (clearing OSC.OSCDIS).
// The module will transition automatically to Configuration mode. // The module will transition automatically to Configuration mode.
@ -1228,21 +1226,21 @@ bool ACAN2517FD::performSleepModeToConfigurationMode (void) {
return inSleepMode ; return inSleepMode ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::errorCounters (void) { uint32_t ACAN2517FD::errorCounters (void) {
return readRegister32 (TREC_REGISTER) ; return readRegister32 (TREC_REGISTER) ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::diagInfos (const int inIndex) { // thanks to Flole998 and turmary uint32_t ACAN2517FD::diagInfos (const int inIndex) { // thanks to Flole998 and turmary
return readRegister32 (inIndex ? BDIAG1_REGISTER: BDIAG0_REGISTER) ; return readRegister32 (inIndex ? BDIAG1_REGISTER: BDIAG0_REGISTER) ;
} }
//------------------------------------------------------------------------------ //······················································································································
// GPIO // GPIO
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::gpioSetMode (const uint8_t inPin, const uint8_t inMode) { void ACAN2517FD::gpioSetMode (const uint8_t inPin, const uint8_t inMode) {
if (inPin <= 1) { if (inPin <= 1) {
@ -1262,7 +1260,7 @@ void ACAN2517FD::gpioSetMode (const uint8_t inPin, const uint8_t inMode) {
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::gpioWrite (const uint8_t inPin, const uint8_t inLevel) { void ACAN2517FD::gpioWrite (const uint8_t inPin, const uint8_t inLevel) {
if (inPin <= 1) { if (inPin <= 1) {
@ -1276,14 +1274,14 @@ void ACAN2517FD::gpioWrite (const uint8_t inPin, const uint8_t inLevel) {
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::gpioRead (const uint8_t inPin) { bool ACAN2517FD::gpioRead (const uint8_t inPin) {
const uint8_t value = readRegister8 (IOCON_REGISTER_16_23) ; const uint8_t value = readRegister8 (IOCON_REGISTER_16_23) ;
return (value >> inPin) & 1 ; return (value >> inPin) & 1 ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::configureGPIO0AsXSTBY (void) { void ACAN2517FD::configureGPIO0AsXSTBY (void) {
uint8_t value = readRegister8 (IOCON_REGISTER_00_07) ; uint8_t value = readRegister8 (IOCON_REGISTER_00_07) ;
@ -1291,4 +1289,4 @@ void ACAN2517FD::configureGPIO0AsXSTBY (void) {
writeRegister8 (IOCON_REGISTER_00_07, value) ; writeRegister8 (IOCON_REGISTER_00_07, value) ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------

View file

@ -1,16 +1,17 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD, CANFD mode // A CAN driver for MCP2517FD, CANFD mode
// by Pierre Molinaro // by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
//------------------------------------------------------------------------------ //
//----------------------------------------------------------------------------------------------------------------------
#pragma once #pragma once
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FDSettings.h" #include "ACAN2517FDSettings.h"
#include "ACAN2517FD_ACANFDBuffer.h" #include "ACANFDBuffer.h"
#include "ACAN2517FD_CANMessage.h" #include "CANMessage.h"
#include "ACAN2517FDFilters.h" #include "ACAN2517FDFilters.h"
#include <SPI.h> #include <SPI.h>
@ -24,23 +25,23 @@
// //
#define DISABLEMCP2517FDCOMPAT #define DISABLEMCP2517FDCOMPAT
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// ACAN2517FD class // ACAN2517FD class
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
class ACAN2517FD { class ACAN2517FD {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// CONSTRUCTOR // CONSTRUCTOR
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: ACAN2517FD (const uint8_t inCS, // CS input of MCP2517FD public: ACAN2517FD (const uint8_t inCS, // CS input of MCP2517FD
SPIClass & inSPI, // Hardware SPI object SPIClass & inSPI, // Hardware SPI object
const uint8_t inINT) ; // INT output of MCP2517FD const uint8_t inINT) ; // INT output of MCP2517FD
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// begin method (returns 0 if no error) // begin method (returns 0 if no error)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t begin (const ACAN2517FDSettings & inSettings, public: uint32_t begin (const ACAN2517FDSettings & inSettings,
void (* inInterruptServiceRoutine) (void)) ; void (* inInterruptServiceRoutine) (void)) ;
@ -72,22 +73,22 @@ class ACAN2517FD {
public: static const uint32_t kISRNotNullAndNoIntPin = uint32_t (1) << 19 ; public: static const uint32_t kISRNotNullAndNoIntPin = uint32_t (1) << 19 ;
public: static const uint32_t kInvalidTDCO = uint32_t (1) << 20 ; public: static const uint32_t kInvalidTDCO = uint32_t (1) << 20 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin) // end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin)
// Return true if end method succeeds, and false otherwise // Return true if end method succeeds, and false otherwise
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool end (void) ; public: bool end (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Send a message // Send a message
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool tryToSend (const CANFDMessage & inMessage) ; public: bool tryToSend (const CANFDMessage & inMessage) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Receive a message // Receive a message
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool receive (CANFDMessage & outMessage) ; public: bool receive (CANFDMessage & outMessage) ;
public: bool available (void) ; public: bool available (void) ;
@ -97,44 +98,44 @@ class ACAN2517FD {
//--- Call back function array //--- Call back function array
private: ACANFDCallBackRoutine * mCallBackFunctionArray = NULL ; private: ACANFDCallBackRoutine * mCallBackFunctionArray = NULL ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Get error counters // Get error counters
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t errorCounters (void) ; public: uint32_t errorCounters (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Get diagnostic information (thanks to Flole998 and turmary) // Get diagnostic information (thanks to Flole998 and turmary)
// inIndex == 0 returns BDIAG0_REGISTER // inIndex == 0 returns BDIAG0_REGISTER
// inIndex != 0 returns BDIAG1_REGISTER // inIndex != 0 returns BDIAG1_REGISTER
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t diagInfos (const int inIndex = 1) ; public: uint32_t diagInfos (const int inIndex = 1) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Operation Mode // Operation Mode
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: ACAN2517FDSettings::OperationMode currentOperationMode (void) ; public: ACAN2517FDSettings::OperationMode currentOperationMode (void) ;
public: void setOperationMode (const ACAN2517FDSettings::OperationMode inMode) ; public: void setOperationMode (const ACAN2517FDSettings::OperationMode inMode) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Recovery from Restricted Operation Mode // Recovery from Restricted Operation Mode
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool recoverFromRestrictedOperationMode (void) ; public: bool recoverFromRestrictedOperationMode (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Sleep Mode to Configuration Mode // Sleep Mode to Configuration Mode
// (returns true if MCP2517FD was in sleep mode) // (returns true if MCP2517FD was in sleep mode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool performSleepModeToConfigurationMode (void) ; public: bool performSleepModeToConfigurationMode (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Private properties // Private properties
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
private: TaskHandle_t mESP32TaskHandle = nullptr ; private: TaskHandle_t mESP32TaskHandle = nullptr ;
@ -146,51 +147,40 @@ class ACAN2517FD {
private: bool mUsesTXQ ; private: bool mUsesTXQ ;
private: bool mHardwareTxFIFOFull ; private: bool mHardwareTxFIFOFull ;
private: bool mRxInterruptEnabled ; // Added in 2.1.7 private: bool mRxInterruptEnabled ; // Added in 2.1.7
private: bool mHasDataBitRate ;
private: uint8_t mTransmitFIFOPayload ; // in byte count private: uint8_t mTransmitFIFOPayload ; // in byte count
private: uint8_t mTXQBufferPayload ; // in byte count private: uint8_t mTXQBufferPayload ; // in byte count
private: uint8_t mReceiveFIFOPayload ; // in byte count private: uint8_t mReceiveFIFOPayload ; // in byte count
private: uint8_t mTXBWS_RequestedMode ; private: uint8_t mTXBWS_RequestedMode ;
private: uint8_t mHardwareReceiveBufferOverflowCount ; private: uint8_t mHardwareReceiveBufferOverflowCount ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Receive buffer // Receive buffer
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
private: ACANFDBuffer mDriverReceiveBuffer ; private: ACANFDBuffer mDriverReceiveBuffer ;
public: uint32_t driverReceiveBufferPeakCount (void) const { public: uint32_t driverReceiveBufferPeakCount (void) const { return mDriverReceiveBuffer.peakCount () ; }
return mDriverReceiveBuffer.peakCount () ;
}
public: uint8_t hardwareReceiveBufferOverflowCount (void) const { public: uint8_t hardwareReceiveBufferOverflowCount (void) const { return mHardwareReceiveBufferOverflowCount ; }
return mHardwareReceiveBufferOverflowCount ;
}
public: void resetHardwareReceiveBufferOverflowCount (void) { public: void resetHardwareReceiveBufferOverflowCount (void) { mHardwareReceiveBufferOverflowCount = 0 ; }
mHardwareReceiveBufferOverflowCount = 0 ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Transmit buffer // Transmit buffer
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
private: ACANFDBuffer mDriverTransmitBuffer ; private: ACANFDBuffer mDriverTransmitBuffer ;
public: uint32_t driverTransmitBufferSize (void) const { public: uint32_t driverTransmitBufferSize (void) const { return mDriverTransmitBuffer.size () ; }
return mDriverTransmitBuffer.size () ;
}
public: uint32_t driverTransmitBufferCount (void) const { public: uint32_t driverTransmitBufferCount (void) const { return mDriverTransmitBuffer.count () ; }
return mDriverTransmitBuffer.count () ;
}
public: uint32_t driverTransmitBufferPeakCount (void) const { public: uint32_t driverTransmitBufferPeakCount (void) const { return mDriverTransmitBuffer.peakCount () ; }
return mDriverTransmitBuffer.peakCount () ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Private methods // Private methods
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
private: void writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint32_t inValue) ; private: void writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint32_t inValue) ;
private: void writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint8_t inValue) ; private: void writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress, const uint8_t inValue) ;
@ -212,15 +202,15 @@ class ACAN2517FD {
private: bool enterInTransmitBuffer (const CANFDMessage & inMessage) ; private: bool enterInTransmitBuffer (const CANFDMessage & inMessage) ;
private: void appendInControllerTxFIFO (const CANFDMessage & inMessage) ; private: void appendInControllerTxFIFO (const CANFDMessage & inMessage) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Polling // Polling
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: void poll (void) ; public: void poll (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Interrupt service routine // Interrupt service routine
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: void isr (void) ; public: void isr (void) ;
public: void isr_poll_core (void) ; public: void isr_poll_core (void) ;
@ -230,9 +220,9 @@ class ACAN2517FD {
public: SemaphoreHandle_t mISRSemaphore ; public: SemaphoreHandle_t mISRSemaphore ;
#endif #endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //----------------------------------------------------------------------------------------------------------------------
// Optimized CS handling (thanks to Flole998) // Optimized CS handling (thanks to Flole998)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
#if defined(__AVR__) #if defined(__AVR__)
private: volatile uint8_t *cs_pin_reg; private: volatile uint8_t *cs_pin_reg;
@ -303,8 +293,10 @@ class ACAN2517FD {
*(cs_pin_reg+8+2) = cs_pin_mask; *(cs_pin_reg+8+2) = cs_pin_mask;
} }
#elif defined(ARDUINO_ARCH_ESP8266) #elif defined(ARDUINO_ARCH_ESP8266)
// private: volatile uint32_t *cs_pin_reg;
private: uint32_t cs_pin_mask; private: uint32_t cs_pin_mask;
private: inline void initCS () { private: inline void initCS () {
// cs_pin_reg = (volatile uint32_t*)GPO;
cs_pin_mask = 1 << mCS; cs_pin_mask = 1 << mCS;
pinMode(mCS, OUTPUT); pinMode(mCS, OUTPUT);
} }
@ -341,9 +333,9 @@ class ACAN2517FD {
} }
#endif #endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// GPIO // GPIO
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: void gpioSetMode (const uint8_t inPin, const uint8_t inMode) ; public: void gpioSetMode (const uint8_t inPin, const uint8_t inMode) ;
@ -353,16 +345,16 @@ class ACAN2517FD {
public: void configureGPIO0AsXSTBY (void) ; public: void configureGPIO0AsXSTBY (void) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// No copy // No copy
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
private: ACAN2517FD (const ACAN2517FD &) = delete ; private: ACAN2517FD (const ACAN2517FD &) = delete ;
private: ACAN2517FD & operator = (const ACAN2517FD &) = delete ; private: ACAN2517FD & operator = (const ACAN2517FD &) = delete ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------

View file

@ -1,27 +1,27 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// An utility class for: // An utility class for:
// - ACAN2517FD CAN driver for MCP2517FD (CANFD mode) // - ACAN2517FD CAN driver for MCP2517FD (CANFD mode)
// by Pierre Molinaro // by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifndef ACAN2517FD_FILTERS_CLASS_DEFINED #ifndef ACAN2517FD_FILTERS_CLASS_DEFINED
#define ACAN2517FD_FILTERS_CLASS_DEFINED #define ACAN2517FD_FILTERS_CLASS_DEFINED
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FD_CANFDMessage.h" #include "CANFDMessage.h"
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// ACAN2517FDFilters class // ACAN2517FDFilters class
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
class ACAN2517FDFilters { class ACAN2517FDFilters {
//------------------------------------------------------------------------------ //······················································································································
// EMBEDDED CLASS // EMBEDDED CLASS
//------------------------------------------------------------------------------ //······················································································································
private: class Filter { private: class Filter {
public: Filter * mNextFilter ; public: Filter * mNextFilter ;
@ -43,9 +43,9 @@ class ACAN2517FDFilters {
private: Filter & operator = (const Filter &) ; private: Filter & operator = (const Filter &) ;
} ; } ;
//------------------------------------------------------------------------------ //······················································································································
// ENUMERATED TYPE // ENUMERATED TYPE
//------------------------------------------------------------------------------ //······················································································································
public: typedef enum { public: typedef enum {
kFiltersOk, kFiltersOk,
@ -58,15 +58,15 @@ class ACAN2517FDFilters {
kInconsistencyBetweenMaskAndAcceptance kInconsistencyBetweenMaskAndAcceptance
} FilterStatus ; } FilterStatus ;
//------------------------------------------------------------------------------ //······················································································································
// CONSTRUCTOR // CONSTRUCTOR
//------------------------------------------------------------------------------ //······················································································································
public: ACAN2517FDFilters (void) {} public: ACAN2517FDFilters (void) {}
//------------------------------------------------------------------------------ //······················································································································
// DESTRUCTOR // DESTRUCTOR
//------------------------------------------------------------------------------ //······················································································································
public: ~ ACAN2517FDFilters (void) { public: ~ ACAN2517FDFilters (void) {
while (mFirstFilter != NULL) { while (mFirstFilter != NULL) {
@ -76,9 +76,9 @@ class ACAN2517FDFilters {
} }
} }
//------------------------------------------------------------------------------ //······················································································································
// RECEIVE FILTERS // RECEIVE FILTERS
//------------------------------------------------------------------------------ //······················································································································
public: void appendPassAllFilter (const ACANFDCallBackRoutine inCallBackRoutine) { // Accept any frame public: void appendPassAllFilter (const ACANFDCallBackRoutine inCallBackRoutine) { // Accept any frame
Filter * f = new Filter (0, 0, inCallBackRoutine) ; Filter * f = new Filter (0, 0, inCallBackRoutine) ;
@ -91,7 +91,7 @@ class ACAN2517FDFilters {
mFilterCount += 1 ; mFilterCount += 1 ;
} }
//------------------------------------------------------------------------------ //······················································································································
public: void appendFormatFilter (const tFrameFormat inFormat, // Accept any identifier public: void appendFormatFilter (const tFrameFormat inFormat, // Accept any identifier
const ACANFDCallBackRoutine inCallBackRoutine) { const ACANFDCallBackRoutine inCallBackRoutine) {
@ -107,7 +107,7 @@ class ACAN2517FDFilters {
mFilterCount += 1 ; mFilterCount += 1 ;
} }
//------------------------------------------------------------------------------ //······················································································································
public: void appendFrameFilter (const tFrameFormat inFormat, public: void appendFrameFilter (const tFrameFormat inFormat,
const uint32_t inIdentifier, const uint32_t inIdentifier,
@ -141,7 +141,7 @@ class ACAN2517FDFilters {
mFilterCount += 1 ; mFilterCount += 1 ;
} }
//------------------------------------------------------------------------------ //······················································································································
public: void appendFilter (const tFrameFormat inFormat, public: void appendFilter (const tFrameFormat inFormat,
const uint32_t inMask, const uint32_t inMask,
@ -196,9 +196,9 @@ class ACAN2517FDFilters {
mFilterCount += 1 ; mFilterCount += 1 ;
} }
//------------------------------------------------------------------------------ //······················································································································
// ACCESSORS // ACCESSORS
//------------------------------------------------------------------------------ //······················································································································
public: FilterStatus filterStatus (void) const { return mFilterStatus ; } public: FilterStatus filterStatus (void) const { return mFilterStatus ; }
@ -206,9 +206,9 @@ class ACAN2517FDFilters {
public: uint8_t filterCount (void) const { return mFilterCount ; } public: uint8_t filterCount (void) const { return mFilterCount ; }
//------------------------------------------------------------------------------ //······················································································································
// PRIVATE PROPERTIES // PRIVATE PROPERTIES
//------------------------------------------------------------------------------ //······················································································································
private: uint8_t mFilterCount = 0 ; private: uint8_t mFilterCount = 0 ;
private: Filter * mFirstFilter = NULL ; private: Filter * mFirstFilter = NULL ;
@ -216,23 +216,23 @@ class ACAN2517FDFilters {
private: FilterStatus mFilterStatus = kFiltersOk ; private: FilterStatus mFilterStatus = kFiltersOk ;
private: uint8_t mFilterErrorIndex = 0 ; private: uint8_t mFilterErrorIndex = 0 ;
//------------------------------------------------------------------------------ //······················································································································
// NO COPY // NO COPY
//------------------------------------------------------------------------------ //······················································································································
private: ACAN2517FDFilters (const ACAN2517FDFilters &) = delete ; private: ACAN2517FDFilters (const ACAN2517FDFilters &) = delete ;
private: ACAN2517FDFilters & operator = (const ACAN2517FDFilters &) = delete ; private: ACAN2517FDFilters & operator = (const ACAN2517FDFilters &) = delete ;
//------------------------------------------------------------------------------ //······················································································································
// Friend // Friend
//------------------------------------------------------------------------------ //······················································································································
friend class ACAN2517FD ; friend class ACAN2517FD ;
//------------------------------------------------------------------------------ //······················································································································
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#endif #endif

View file

@ -1,19 +1,19 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD (CANFD mode) // A CAN driver for MCP2517FD (CANFD mode)
// by Pierre Molinaro // by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FDSettings.h" #include "ACAN2517FDSettings.h"
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#pragma GCC diagnostic error "-Wswitch-enum" #pragma GCC diagnostic error "-Wswitch-enum"
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// sysClock // sysClock
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) { uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) {
uint32_t sysClock = 40UL * 1000 * 1000 ; uint32_t sysClock = 40UL * 1000 * 1000 ;
@ -39,9 +39,9 @@ uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) {
return sysClock ; return sysClock ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// CONSTRUCTOR // CONSTRUCTOR
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
ACAN2517FDSettings::ACAN2517FDSettings (const Oscillator inOscillator, ACAN2517FDSettings::ACAN2517FDSettings (const Oscillator inOscillator,
const uint32_t inDesiredArbitrationBitRate, const uint32_t inDesiredArbitrationBitRate,
@ -51,7 +51,61 @@ mOscillator (inOscillator),
mSysClock (sysClock (inOscillator)), mSysClock (sysClock (inOscillator)),
mDesiredArbitrationBitRate (inDesiredArbitrationBitRate), mDesiredArbitrationBitRate (inDesiredArbitrationBitRate),
mDataBitRateFactor (inDataBitRateFactor) { mDataBitRateFactor (inDataBitRateFactor) {
// First compute data bit rate if (inDataBitRateFactor == DataBitRateFactor::x1) { // Single bit rate
const uint32_t maxTQCount = MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1 ; // Setting for slowest bit rate
uint32_t BRP = MAX_BRP ;
uint32_t smallestError = UINT32_MAX ;
uint32_t bestBRP = 1 ; // Setting for highest bit rate
uint32_t bestTQCount = 4 ; // Setting for highest bit rate
uint32_t TQCount = mSysClock / inDesiredArbitrationBitRate / BRP ;
//--- Loop for finding best BRP and best TQCount
while ((TQCount <= (MAX_ARBITRATION_PHASE_SEGMENT_1 + MAX_ARBITRATION_PHASE_SEGMENT_2 + 1)) && (BRP > 0)) {
//--- Compute error using TQCount
if ((TQCount >= 4) && (TQCount <= maxTQCount)) {
const uint32_t error = mSysClock - inDesiredArbitrationBitRate * TQCount * BRP ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = BRP ;
bestTQCount = TQCount ;
}
}
//--- Compute error using TQCount+1
if ((TQCount >= 3) && (TQCount < maxTQCount)) {
const uint32_t error = inDesiredArbitrationBitRate * (TQCount + 1) * BRP - mSysClock ; // error is always >= 0
if (error <= smallestError) {
smallestError = error ;
bestBRP = BRP ;
bestTQCount = TQCount + 1 ;
}
}
//--- Continue with next value of BRP
BRP -- ;
TQCount = (BRP == 0) ? (maxTQCount + 1) : (mSysClock / inDesiredArbitrationBitRate / BRP) ;
}
//--- Compute PS2 (1 <= PS2 <= 128)
uint32_t PS2 = bestTQCount / 5 ; // For sampling point at 80%
if (PS2 == 0) {
PS2 = 1 ;
}else if (PS2 > MAX_ARBITRATION_PHASE_SEGMENT_2) {
PS2 = MAX_ARBITRATION_PHASE_SEGMENT_2 ;
}
//--- Compute PS1 (1 <= PS1 <= 256)
uint32_t PS1 = bestTQCount - PS2 - 1 /* Sync Seg */ ;
if (PS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) {
PS2 += PS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ;
PS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ;
}
//---
mBitRatePrescaler = (uint16_t) bestBRP ;
mArbitrationPhaseSegment1 = (uint16_t) PS1 ;
mArbitrationPhaseSegment2 = (uint8_t) PS2 ;
mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2
//--- Final check of the nominal configuration
const uint32_t W = bestTQCount * mDesiredArbitrationBitRate * bestBRP ;
const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ;
const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno
mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ;
}else{ // Dual bit rate, first compute data bit rate
const uint32_t maxDataTQCount = MAX_DATA_PHASE_SEGMENT_1 + MAX_DATA_PHASE_SEGMENT_2 ; // Setting for slowest bit rate const uint32_t maxDataTQCount = MAX_DATA_PHASE_SEGMENT_1 + MAX_DATA_PHASE_SEGMENT_2 ; // Setting for slowest bit rate
const uint32_t desiredDataBitRate = inDesiredArbitrationBitRate * uint8_t (inDataBitRateFactor) ; const uint32_t desiredDataBitRate = inDesiredArbitrationBitRate * uint8_t (inDataBitRateFactor) ;
uint32_t smallestError = UINT32_MAX ; uint32_t smallestError = UINT32_MAX ;
@ -105,7 +159,7 @@ mDataBitRateFactor (inDataBitRateFactor) {
mDataPhaseSegment2 = (uint8_t) dataPS2 ; mDataPhaseSegment2 = (uint8_t) dataPS2 ;
mDataSJW = mDataPhaseSegment2 ; mDataSJW = mDataPhaseSegment2 ;
const uint32_t arbitrationTQCount = bestDataTQCount * uint8_t (mDataBitRateFactor) ; const uint32_t arbitrationTQCount = bestDataTQCount * uint8_t (mDataBitRateFactor) ;
//--- Compute arbitration PS2 (1 <= PS2 <= 128) //--- Compute arbiration PS2 (1 <= PS2 <= 128)
uint32_t arbitrationPS2 = arbitrationTQCount / 5 ; // For sampling point at 80% uint32_t arbitrationPS2 = arbitrationTQCount / 5 ; // For sampling point at 80%
if (arbitrationPS2 == 0) { if (arbitrationPS2 == 0) {
arbitrationPS2 = 1 ; arbitrationPS2 = 1 ;
@ -126,18 +180,19 @@ mDataBitRateFactor (inDataBitRateFactor) {
const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ; const uint64_t diff = (mSysClock > W) ? (mSysClock - W) : (W - mSysClock) ;
const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno const uint64_t ppm = (uint64_t) (1000UL * 1000UL) ; // UL suffix is required for Arduino Uno
mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ; mArbitrationBitRateClosedToDesiredRate = (diff * ppm) <= (((uint64_t) W) * inTolerancePPM) ;
}
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// ACCESSORS // ACCESSORS
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::actualArbitrationBitRate (void) const { uint32_t ACAN2517FDSettings::actualArbitrationBitRate (void) const {
const uint32_t arbitrationTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; const uint32_t arbitrationTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
return mSysClock / mBitRatePrescaler / arbitrationTQCount ; return mSysClock / mBitRatePrescaler / arbitrationTQCount ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::actualDataBitRate (void) const { uint32_t ACAN2517FDSettings::actualDataBitRate (void) const {
if (mDataBitRateFactor == DataBitRateFactor::x1) { if (mDataBitRateFactor == DataBitRateFactor::x1) {
@ -148,14 +203,14 @@ uint32_t ACAN2517FDSettings::actualDataBitRate (void) const {
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::exactArbitrationBitRate (void) const { bool ACAN2517FDSettings::exactArbitrationBitRate (void) const {
const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
return mSysClock == (mBitRatePrescaler * mDesiredArbitrationBitRate * TQCount) ; return mSysClock == (mBitRatePrescaler * mDesiredArbitrationBitRate * TQCount) ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::exactDataBitRate (void) const { bool ACAN2517FDSettings::exactDataBitRate (void) const {
if (mDataBitRateFactor == DataBitRateFactor::x1) { if (mDataBitRateFactor == DataBitRateFactor::x1) {
@ -166,7 +221,7 @@ bool ACAN2517FDSettings::exactDataBitRate (void) const {
} }
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const { bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const {
bool result = mDataBitRateFactor == DataBitRateFactor::x1 ; bool result = mDataBitRateFactor == DataBitRateFactor::x1 ;
@ -178,7 +233,7 @@ bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::ppmFromDesiredArbitrationBitRate (void) const { uint32_t ACAN2517FDSettings::ppmFromDesiredArbitrationBitRate (void) const {
const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
@ -188,7 +243,7 @@ uint32_t ACAN2517FDSettings::ppmFromDesiredArbitrationBitRate (void) const {
return (uint32_t) ((diff * ppm) / W) ; return (uint32_t) ((diff * ppm) / W) ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const { uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const {
const uint32_t nominalTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ; const uint32_t nominalTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
@ -197,7 +252,7 @@ uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const {
return (samplePoint * partPerCent) / nominalTQCount ; return (samplePoint * partPerCent) / nominalTQCount ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const { uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const {
const uint32_t nominalTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ; const uint32_t nominalTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ;
@ -206,7 +261,7 @@ uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const {
return (samplePoint * partPerCent) / nominalTQCount ; return (samplePoint * partPerCent) / nominalTQCount ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const { uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const {
uint32_t errorCode = 0 ; // Means no error uint32_t errorCode = 0 ; // Means no error
@ -274,9 +329,9 @@ uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const {
return errorCode ; return errorCode ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// RAM USAGE // RAM USAGE
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::ramUsage (void) const { uint32_t ACAN2517FDSettings::ramUsage (void) const {
uint32_t result = 0 ; uint32_t result = 0 ;
@ -290,11 +345,11 @@ uint32_t ACAN2517FDSettings::ramUsage (void) const {
return result ; return result ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::objectSizeForPayload (const PayloadSize inPayload) { uint32_t ACAN2517FDSettings::objectSizeForPayload (const PayloadSize inPayload) {
static const uint8_t kPayload [8] = {16, 20, 24, 28, 32, 40, 56, 72} ; static const uint8_t kPayload [8] = {16, 20, 24, 28, 32, 40, 56, 72} ;
return kPayload [inPayload] ; return kPayload [inPayload] ;
} }
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------

View file

@ -1,25 +1,25 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD (CANFD mode) // A CAN driver for MCP2517FD (CANFD mode)
// by Pierre Molinaro // by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#pragma once #pragma once
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FD_DataBitRateFactor.h" #include "ACANFD_DataBitRateFactor.h"
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// ACAN2517FDSettings class // ACAN2517FDSettings class
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
class ACAN2517FDSettings { class ACAN2517FDSettings {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// ENUMERATED TYPES // ENUMERATED TYPES
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: typedef enum : uint8_t { public: typedef enum : uint8_t {
OSC_4MHz, OSC_4MHz,
@ -64,9 +64,9 @@ class ACAN2517FDSettings {
PAYLOAD_64 = 7 PAYLOAD_64 = 7
} PayloadSize ; } PayloadSize ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Deprecated enumeration (now use DataBitRateFactor declared in ACANFD_DataBitRateFactor.h) // Deprecated enumeration (now use DataBitRateFactor declared in ACANFD_DataBitRateFactor.h)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public : typedef enum : uint8_t { public : typedef enum : uint8_t {
DATA_BITRATE_x1 = 1, DATA_BITRATE_x1 = 1,
@ -81,18 +81,18 @@ class ACAN2517FDSettings {
DATA_BITRATE_x10 = 10 DATA_BITRATE_x10 = 10
} DataBitRateFactor_Deprecated ; } DataBitRateFactor_Deprecated ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// CONSTRUCTOR // CONSTRUCTOR
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: ACAN2517FDSettings (const Oscillator inOscillator, public: ACAN2517FDSettings (const Oscillator inOscillator,
const uint32_t inDesiredArbitrationBitRate, const uint32_t inDesiredArbitrationBitRate,
const DataBitRateFactor inDataBitRateFactor, const DataBitRateFactor inDataBitRateFactor,
const uint32_t inTolerancePPM = 1000) ; const uint32_t inTolerancePPM = 1000) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// DEPRECATED CONSTRUCTOR (for compatibility with version < 2.1.0) // DEPRECATED CONSTRUCTOR (for compatibility with version < 2.1.0)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: ACAN2517FDSettings (const Oscillator inOscillator, public: ACAN2517FDSettings (const Oscillator inOscillator,
const uint32_t inDesiredArbitrationBitRate, const uint32_t inDesiredArbitrationBitRate,
@ -101,9 +101,9 @@ class ACAN2517FDSettings {
ACAN2517FDSettings (inOscillator, inDesiredArbitrationBitRate, DataBitRateFactor (inDataBitRateFactor), inTolerancePPM) { ACAN2517FDSettings (inOscillator, inDesiredArbitrationBitRate, DataBitRateFactor (inDataBitRateFactor), inTolerancePPM) {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// CAN BIT TIMING // CAN BIT TIMING
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
private: Oscillator mOscillator ; private: Oscillator mOscillator ;
private: uint32_t mSysClock ; // In Hz private: uint32_t mSysClock ; // In Hz
@ -123,44 +123,44 @@ class ACAN2517FDSettings {
//--- Transmitter Delay Compensation Offset //--- Transmitter Delay Compensation Offset
public: int8_t mTDCO = 0 ; // -64 ... +63 public: int8_t mTDCO = 0 ; // -64 ... +63
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// MCP2517FD TXCAN pin is Open Drain ? // MCP2517FD TXCAN pin is Open Drain ?
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool mTXCANIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output public: bool mTXCANIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// MCP2517FD INT pin is Open Drain ? // MCP2517FD INT pin is Open Drain ?
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: bool mINTIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output public: bool mINTIsOpenDrain = false ; // false --> Push/Pull Output, true --> Open Drain Output
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// ISO CRC Enable // ISO CRC Enable
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// false --> Do NOT include Stuff Bit Count in CRC Field and use CRC Initialization Vector with all zeros // false --> Do NOT include Stuff Bit Count in CRC Field and use CRC Initialization Vector with all zeros
// true --> Include Stuff Bit Count in CRC Field and use Non-Zero CRC Initialization Vector according to ISO 11898-1:2015 // true --> Include Stuff Bit Count in CRC Field and use Non-Zero CRC Initialization Vector according to ISO 11898-1:2015
public: bool mISOCRCEnabled = true ; public: bool mISOCRCEnabled = true ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// CLKO pin function (default value is MCP2517FD power on setting) // CLKO pin function (default value is MCP2517FD power on setting)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: CLKOpin mCLKOPin = CLKO_DIVIDED_BY_10 ; public: CLKOpin mCLKOPin = CLKO_DIVIDED_BY_10 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Requested mode // Requested mode
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: OperationMode mRequestedMode = NormalFD ; public: OperationMode mRequestedMode = NormalFD ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// TRANSMIT FIFO // TRANSMIT FIFO
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
//--- Driver transmit buffer size //--- Driver transmit buffer size
public: uint16_t mDriverTransmitFIFOSize = 16 ; // >= 0 public: uint16_t mDriverTransmitFIFOSize = 22 ; // >= 0
//--- Controller transmit FIFO size //--- Controller transmit FIFO size
public: uint8_t mControllerTransmitFIFOSize = 1 ; // 1 ... 32 public: uint8_t mControllerTransmitFIFOSize = 1 ; // 1 ... 32
@ -174,9 +174,9 @@ class ACAN2517FDSettings {
//--- Controller transmit FIFO retransmission attempts //--- Controller transmit FIFO retransmission attempts
public: RetransmissionAttempts mControllerTransmitFIFORetransmissionAttempts = UnlimitedNumber ; public: RetransmissionAttempts mControllerTransmitFIFORetransmissionAttempts = UnlimitedNumber ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// TXQ BUFFER // TXQ BUFFER
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
//--- TXQ buffer size (0 --> TXQ disabled) //--- TXQ buffer size (0 --> TXQ disabled)
public: uint8_t mControllerTXQSize = 0 ; // 0 ... 32 public: uint8_t mControllerTXQSize = 0 ; // 0 ... 32
@ -191,9 +191,9 @@ class ACAN2517FDSettings {
public: RetransmissionAttempts mControllerTXQBufferRetransmissionAttempts = UnlimitedNumber ; public: RetransmissionAttempts mControllerTXQBufferRetransmissionAttempts = UnlimitedNumber ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// RECEIVE FIFO // RECEIVE FIFO
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
//--- Driver receive buffer size //--- Driver receive buffer size
public: uint16_t mDriverReceiveFIFOSize = 32 ; // > 0 public: uint16_t mDriverReceiveFIFOSize = 32 ; // > 0
@ -204,15 +204,15 @@ class ACAN2517FDSettings {
//--- Controller receive FIFO size //--- Controller receive FIFO size
public: uint8_t mControllerReceiveFIFOSize = 27 ; // 1 ... 32 public: uint8_t mControllerReceiveFIFOSize = 27 ; // 1 ... 32
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// SYSCLOCK frequency computation // SYSCLOCK frequency computation
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: static uint32_t sysClock (const Oscillator inOscillator) ; public: static uint32_t sysClock (const Oscillator inOscillator) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Accessors // Accessors
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: Oscillator oscillator (void) const { return mOscillator ; } public: Oscillator oscillator (void) const { return mOscillator ; }
public: uint32_t sysClock (void) const { return mSysClock ; } public: uint32_t sysClock (void) const { return mSysClock ; }
@ -222,61 +222,61 @@ class ACAN2517FDSettings {
public: bool exactDataBitRate (void) const ; public: bool exactDataBitRate (void) const ;
public: bool dataBitRateIsAMultipleOfArbitrationBitRate (void) const ; public: bool dataBitRateIsAMultipleOfArbitrationBitRate (void) const ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// RAM USAGE // RAM USAGE
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t ramUsage (void) const ; public: uint32_t ramUsage (void) const ;
public: static uint32_t objectSizeForPayload (const PayloadSize inPayload) ; public: static uint32_t objectSizeForPayload (const PayloadSize inPayload) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Distance between actual bit rate and requested bit rate (in ppm, part-per-million) // Distance between actual bit rate and requested bit rate (in ppm, part-per-million)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t ppmFromDesiredArbitrationBitRate (void) const ; public: uint32_t ppmFromDesiredArbitrationBitRate (void) const ;
public: uint32_t ppmFromDesiredDataBitRate (void) const ; public: uint32_t ppmFromDesiredDataBitRate (void) const ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Distance of sample point from bit start (in ppc, part-per-cent, denoted by %) // Distance of sample point from bit start (in ppc, part-per-cent, denoted by %)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t arbitrationSamplePointFromBitStart (void) const ; public: uint32_t arbitrationSamplePointFromBitStart (void) const ;
public: uint32_t dataSamplePointFromBitStart (void) const ; public: uint32_t dataSamplePointFromBitStart (void) const ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Bit settings are consistent ? (returns 0 if ok) // Bit settings are consistent ? (returns 0 if ok)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: uint32_t CANBitSettingConsistency (void) const ; public: uint32_t CANBitSettingConsistency (void) const ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Constants returned by CANBitSettingConsistency // Constants returned by CANBitSettingConsistency
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: static const uint32_t kBitRatePrescalerIsZero = uint32_t (1) << 0 ; public: static const uint32_t kBitRatePrescalerIsZero = ((uint32_t) 1) << 0 ;
public: static const uint32_t kBitRatePrescalerIsGreaterThan256 = uint32_t (1) << 1 ; public: static const uint32_t kBitRatePrescalerIsGreaterThan256 = ((uint32_t) 1) << 1 ;
public: static const uint32_t kArbitrationPhaseSegment1IsLowerThan2 = uint32_t (1) << 2 ; public: static const uint32_t kArbitrationPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 2 ;
public: static const uint32_t kArbitrationPhaseSegment1IsGreaterThan256 = uint32_t (1) << 3 ; public: static const uint32_t kArbitrationPhaseSegment1IsGreaterThan256 = ((uint32_t) 1) << 3 ;
public: static const uint32_t kArbitrationPhaseSegment2IsZero = uint32_t (1) << 4 ; public: static const uint32_t kArbitrationPhaseSegment2IsZero = ((uint32_t) 1) << 4 ;
public: static const uint32_t kArbitrationPhaseSegment2IsGreaterThan128 = uint32_t (1) << 5 ; public: static const uint32_t kArbitrationPhaseSegment2IsGreaterThan128 = ((uint32_t) 1) << 5 ;
public: static const uint32_t kArbitrationSJWIsZero = uint32_t (1) << 6 ; public: static const uint32_t kArbitrationSJWIsZero = ((uint32_t) 1) << 6 ;
public: static const uint32_t kArbitrationSJWIsGreaterThan128 = uint32_t (1) << 7 ; public: static const uint32_t kArbitrationSJWIsGreaterThan128 = ((uint32_t) 1) << 7 ;
public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment1 = uint32_t (1) << 8 ; public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 8 ;
public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment2 = uint32_t (1) << 9 ; public: static const uint32_t kArbitrationSJWIsGreaterThanPhaseSegment2 = ((uint32_t) 1) << 9 ;
public: static const uint32_t kArbitrationTQCountNotDivisibleByDataBitRateFactor = uint32_t (1) << 10 ; public: static const uint32_t kArbitrationTQCountNotDivisibleByDataBitRateFactor = ((uint32_t) 1) << 10 ;
public: static const uint32_t kDataPhaseSegment1IsLowerThan2 = uint32_t (1) << 11 ; public: static const uint32_t kDataPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 11 ;
public: static const uint32_t kDataPhaseSegment1IsGreaterThan32 = uint32_t (1) << 12 ; public: static const uint32_t kDataPhaseSegment1IsGreaterThan32 = ((uint32_t) 1) << 12 ;
public: static const uint32_t kDataPhaseSegment2IsZero = uint32_t (1) << 13 ; public: static const uint32_t kDataPhaseSegment2IsZero = ((uint32_t) 1) << 13 ;
public: static const uint32_t kDataPhaseSegment2IsGreaterThan16 = uint32_t (1) << 14 ; public: static const uint32_t kDataPhaseSegment2IsGreaterThan16 = ((uint32_t) 1) << 14 ;
public: static const uint32_t kDataSJWIsZero = uint32_t (1) << 15 ; public: static const uint32_t kDataSJWIsZero = ((uint32_t) 1) << 15 ;
public: static const uint32_t kDataSJWIsGreaterThan16 = uint32_t (1) << 16 ; public: static const uint32_t kDataSJWIsGreaterThan16 = ((uint32_t) 1) << 16 ;
public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment1 = uint32_t (1) << 17 ; public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 17 ;
public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment2 = uint32_t (1) << 18 ; public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment2 = ((uint32_t) 1) << 18 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
// Max values // Max values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
public: static const uint16_t MAX_BRP = 256 ; public: static const uint16_t MAX_BRP = 256 ;
@ -288,9 +288,9 @@ class ACAN2517FDSettings {
public: static const uint8_t MAX_DATA_PHASE_SEGMENT_2 = 16 ; public: static const uint8_t MAX_DATA_PHASE_SEGMENT_2 = 16 ;
public: static const uint8_t MAX_DATA_SJW = 16 ; public: static const uint8_t MAX_DATA_SJW = 16 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //······················································································································
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------

View file

@ -1,122 +0,0 @@
//------------------------------------------------------------------------------
// A CAN driver for MCP2517FD CAN Controller in CANFD mode
// by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD
//
//------------------------------------------------------------------------------
#ifndef ACANFD_BUFFER_CLASS_DEFINED
#define ACANFD_BUFFER_CLASS_DEFINED
//------------------------------------------------------------------------------
#include "ACAN2517FD_CANFDMessage.h"
//------------------------------------------------------------------------------
class ACANFDBuffer {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Default constructor
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: ACANFDBuffer (void) :
mBuffer (NULL),
mSize (0),
mReadIndex (0),
mCount (0),
mPeakCount (0) {
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Destructor
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: ~ ACANFDBuffer (void) {
delete [] mBuffer ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Private properties
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private: CANFDMessage * mBuffer ;
private: uint32_t mSize ;
private: uint32_t mReadIndex ;
private: uint32_t mCount ;
private: uint32_t mPeakCount ; // > mSize if overflow did occur
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Accessors
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: inline uint32_t size (void) const { return mSize ; }
public: inline uint32_t count (void) const { return mCount ; }
public: inline bool isFull (void) const { return mCount == mSize ; } // Added in release 2.17 (thanks to Flole998)
public: inline uint32_t peakCount (void) const { return mPeakCount ; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// initWithSize
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: void initWithSize (const uint32_t inSize) {
delete [] mBuffer ; mBuffer = new CANFDMessage [inSize] ;
mSize = inSize ;
mReadIndex = 0 ;
mCount = 0 ;
mPeakCount = 0 ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// append
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: bool append (const CANFDMessage & inMessage) {
const bool ok = mCount < mSize ;
if (ok) {
uint32_t writeIndex = mReadIndex + mCount ;
if (writeIndex >= mSize) {
writeIndex -= mSize ;
}
mBuffer [writeIndex] = inMessage ;
mCount += 1 ;
if (mPeakCount < mCount) {
mPeakCount = mCount ;
}
}else{
mPeakCount = mSize + 1 ;
}
return ok ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Remove
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
public: bool remove (CANFDMessage & outMessage) {
const bool ok = mCount > 0 ;
if (ok) {
outMessage = mBuffer [mReadIndex] ;
mCount -= 1 ;
mReadIndex += 1 ;
if (mReadIndex == mSize) {
mReadIndex = 0 ;
}
}
return ok ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// No copy
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
private: ACANFDBuffer (const ACANFDBuffer &) = delete ;
private: ACANFDBuffer & operator = (const ACANFDBuffer &) = delete ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
} ;
//------------------------------------------------------------------------------
#endif

View file

@ -0,0 +1,119 @@
//----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD CAN Controller in CANFD mode
// by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD
//
//----------------------------------------------------------------------------------------------------------------------
#ifndef ACANFD_BUFFER_CLASS_DEFINED
#define ACANFD_BUFFER_CLASS_DEFINED
//----------------------------------------------------------------------------------------------------------------------
#include "CANFDMessage.h"
//----------------------------------------------------------------------------------------------------------------------
class ACANFDBuffer {
//······················································································································
// Default constructor
//······················································································································
public: ACANFDBuffer (void) :
mBuffer (NULL),
mSize (0),
mReadIndex (0),
mCount (0),
mPeakCount (0) {
}
//······················································································································
// Destructor
//······················································································································
public: ~ ACANFDBuffer (void) {
delete [] mBuffer ;
}
//······················································································································
// Private properties
//······················································································································
private: CANFDMessage * mBuffer ;
private: uint32_t mSize ;
private: uint32_t mReadIndex ;
private: uint32_t mCount ;
private: uint32_t mPeakCount ; // > mSize if overflow did occur
//······················································································································
// Accessors
//······················································································································
public: inline uint32_t size (void) const { return mSize ; }
public: inline uint32_t count (void) const { return mCount ; }
public: inline bool isFull (void) const { return mCount == mSize ; } // Added in release 2.17 (thanks to Flole998)
public: inline uint32_t peakCount (void) const { return mPeakCount ; }
//······················································································································
// initWithSize
//······················································································································
public: void initWithSize (const uint32_t inSize) {
delete [] mBuffer ; mBuffer = new CANFDMessage [inSize] ;
mSize = inSize ;
mReadIndex = 0 ;
mCount = 0 ;
mPeakCount = 0 ;
}
//······················································································································
// append
//······················································································································
public: bool append (const CANFDMessage & inMessage) {
const bool ok = mCount < mSize ;
if (ok) {
uint32_t writeIndex = mReadIndex + mCount ;
if (writeIndex >= mSize) {
writeIndex -= mSize ;
}
mBuffer [writeIndex] = inMessage ;
mCount += 1 ;
if (mPeakCount < mCount) {
mPeakCount = mCount ;
}
}else{
mPeakCount = mSize + 1 ;
}
return ok ;
}
//······················································································································
// Remove
//······················································································································
public: bool remove (CANFDMessage & outMessage) {
const bool ok = mCount > 0 ;
if (ok) {
outMessage = mBuffer [mReadIndex] ;
mCount -= 1 ;
mReadIndex += 1 ;
if (mReadIndex == mSize) {
mReadIndex = 0 ;
}
}
return ok ;
}
//······················································································································
// No copy
//······················································································································
private: ACANFDBuffer (const ACANFDBuffer &) = delete ;
private: ACANFDBuffer & operator = (const ACANFDBuffer &) = delete ;
} ;
//----------------------------------------------------------------------------------------------------------------------
#endif

View file

@ -1,4 +1,4 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// A CANFD driver // A CANFD driver
// by Pierre Molinaro // by Pierre Molinaro
@ -6,16 +6,16 @@
// https://github.com/pierremolinaro/ACAN_T4 // https://github.com/pierremolinaro/ACAN_T4
// https://github.com/pierremolinaro/ACAN2517FD // https://github.com/pierremolinaro/ACAN2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifndef ACANFD_DATA_BIT_RATE_FACTOR_DEFINED #ifndef ACANFD_DATA_BIT_RATE_FACTOR_DEFINED
#define ACANFD_DATA_BIT_RATE_FACTOR_DEFINED #define ACANFD_DATA_BIT_RATE_FACTOR_DEFINED
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include <stdint.h> #include <stdint.h>
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
enum class DataBitRateFactor : uint8_t { enum class DataBitRateFactor : uint8_t {
x1 = 1, x1 = 1,
@ -30,6 +30,6 @@ enum class DataBitRateFactor : uint8_t {
x10 = 10 x10 = 10
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#endif #endif

View file

@ -1,21 +1,21 @@
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
// Generic CANFD Message // Generic CANFD Message
// by Pierre Molinaro // by Pierre Molinaro
// //
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
#ifndef GENERIC_CANFD_MESSAGE_DEFINED #ifndef GENERIC_CANFD_MESSAGE_DEFINED
#define GENERIC_CANFD_MESSAGE_DEFINED #define GENERIC_CANFD_MESSAGE_DEFINED
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
#include "ACAN2517FD_CANMessage.h" #include "CANMessage.h"
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
// CANFDMessage class // CANFDMessage class
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
// Note that "len" field contains the actual length, not its encoding in CANFD frames // Note that "len" field contains the actual length, not its encoding in CANFD frames
// Valid values are: 0, 1, ..., 8, 12, 16, 20, 24, 32, 48, 64. // Valid values are: 0, 1, ..., 8, 12, 16, 20, 24, 32, 48, 64.
// Having other values is an error that prevents frame to be sent by tryToSend // Having other values is an error that prevents frame to be sent by tryToSend
@ -23,9 +23,9 @@
class CANFDMessage { class CANFDMessage {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
// Constructors // Constructors
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public : CANFDMessage (void) : public : CANFDMessage (void) :
id (0), // Frame identifier id (0), // Frame identifier
@ -36,7 +36,7 @@ class CANFDMessage {
data () { data () {
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public : CANFDMessage (const CANMessage & inMessage) : public : CANFDMessage (const CANMessage & inMessage) :
id (inMessage.id), // Frame identifier id (inMessage.id), // Frame identifier
@ -48,9 +48,9 @@ class CANFDMessage {
data64 [0] = inMessage.data64 ; data64 [0] = inMessage.data64 ;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
// Enumerated Type // Enumerated Type
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public: typedef enum : uint8_t { public: typedef enum : uint8_t {
CAN_REMOTE, CAN_REMOTE,
@ -59,9 +59,9 @@ class CANFDMessage {
CANFD_WITH_BIT_RATE_SWITCH CANFD_WITH_BIT_RATE_SWITCH
} Type ; } Type ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
// Properties // Properties
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public : uint32_t id ; // Frame identifier public : uint32_t id ; // Frame identifier
public : bool ext ; // false -> base frame, true -> extended frame public : bool ext ; // false -> base frame, true -> extended frame
@ -80,9 +80,9 @@ class CANFDMessage {
uint8_t data [64] ; uint8_t data [64] ;
} ; } ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
// Methods // Methods
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public: void pad (void) { public: void pad (void) {
uint8_t paddedLength = len ; uint8_t paddedLength = len ;
@ -107,7 +107,7 @@ class CANFDMessage {
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
public: bool isValid (void) const { public: bool isValid (void) const {
if ((type == CAN_REMOTE) || (type == CAN_DATA)) { // Remote frame if ((type == CAN_REMOTE) || (type == CAN_DATA)) { // Remote frame
@ -121,14 +121,14 @@ class CANFDMessage {
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - //·············································································
} ; } ;
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
typedef void (*ACANFDCallBackRoutine) (const CANFDMessage & inMessage) ; typedef void (*ACANFDCallBackRoutine) (const CANFDMessage & inMessage) ;
//------------------------------------------------------------------------------ //-----------------------------------------------------------------------------
#endif #endif

View file

@ -1,4 +1,4 @@
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
// Generic CAN Message // Generic CAN Message
// by Pierre Molinaro // by Pierre Molinaro
// //
@ -8,16 +8,16 @@
// https://github.com/pierremolinaro/acan2517 // https://github.com/pierremolinaro/acan2517
// https://github.com/pierremolinaro/acan2517FD // https://github.com/pierremolinaro/acan2517FD
// //
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#ifndef GENERIC_CAN_MESSAGE_DEFINED #ifndef GENERIC_CAN_MESSAGE_DEFINED
#define GENERIC_CAN_MESSAGE_DEFINED #define GENERIC_CAN_MESSAGE_DEFINED
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#include <Arduino.h> #include <Arduino.h>
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
class CANMessage { class CANMessage {
public : uint32_t id = 0 ; // Frame identifier public : uint32_t id = 0 ; // Frame identifier
@ -38,12 +38,12 @@ class CANMessage {
} ; } ;
} ; } ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
typedef enum {kStandard, kExtended} tFrameFormat ; typedef enum {kStandard, kExtended} tFrameFormat ;
typedef enum {kData, kRemote} tFrameKind ; typedef enum {kData, kRemote} tFrameKind ;
typedef void (*ACANCallBackRoutine) (const CANMessage & inMessage) ; typedef void (*ACANCallBackRoutine) (const CANMessage & inMessage) ;
//------------------------------------------------------------------------------ //----------------------------------------------------------------------------------------------------------------------
#endif #endif

0
Software/src/lib/pierremolinaro-ACAN2517FD/README.md Executable file → Normal file
View file

View file

@ -1,9 +0,0 @@
name=ACAN2517FD
version=2.1.16
author=Pierre Molinaro
maintainer=Pierre Molinaro <Pierre.Molinaro@pcmolinaro.name>
sentence=Driver for MCP2517FD and MCP2518FD CAN Controller (CAN FD mode)
paragraph=This library is an Arduino CAN network driver for the MCP2517FD, the MCP2518FD and the MCP251863 CAN Controller, in CAN FD mode. Compatible with ACAN, ACAN2515, ACAN2517 libraries, with ACAN_T4 library from version 2.1.0. Default configuration sends and receives any frame no default filter to provide. Reception filters (up to 32) can be easily defined. Compatible with ESP32 from version 1.1.0.
category=Communication
url=https://github.com/pierremolinaro/acan2517FD
architectures=*