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
// by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD
//
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#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 ;
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// Note about ESP32
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//
// It appears that Arduino ESP32 interrupts are managed in a completely different way from "usual" Arduino:
// - SPI.usingInterrupt is not implemented;
@ -43,7 +43,7 @@ static const uint8_t TXBWS = 0 ;
// #endif
// mSPI.endTransaction () ;
//
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32
static void myESP32Task (void * pData) {
@ -55,9 +55,9 @@ static const uint8_t TXBWS = 0 ;
}
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// ACAN2517FD register addresses
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
static const uint16_t CON_REGISTER = 0x000 ;
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 BDIAG1_REGISTER = 0x03C ;
//------------------------------------------------------------------------------
//······················································································································
// TXQ REGISTERS
//------------------------------------------------------------------------------
//······················································································································
static const uint16_t TXQCON_REGISTER = 0x050 ;
static const uint16_t TXQSTA_REGISTER = 0x054 ;
static const uint16_t TXQUA_REGISTER = 0x058 ;
//------------------------------------------------------------------------------
//······················································································································
// INTERRUPT REGISTERS
//------------------------------------------------------------------------------
//······················································································································
static const uint16_t INT_REGISTER = 0x01C ;
//------------------------------------------------------------------------------
//······················································································································
// FIFO REGISTERS
//------------------------------------------------------------------------------
//······················································································································
static uint16_t FIFOCON_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x05C + 12 * (inFIFOIndex - 1) ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint16_t FIFOSTA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x060 + 12 * (inFIFOIndex - 1) ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint16_t FIFOUA_REGISTER (const uint16_t inFIFOIndex) { // 1 ... 31
return 0x064 + 12 * (inFIFOIndex - 1) ;
}
//------------------------------------------------------------------------------
//······················································································································
// FILTER REGISTERS
//------------------------------------------------------------------------------
//······················································································································
static uint16_t FLTCON_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 58)
return 0x1D0 + inFilterIndex ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint16_t FLTOBJ_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 60)
return 0x1F0 + 8 * inFilterIndex ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint16_t MASK_REGISTER (const uint16_t inFilterIndex) { // 0 ... 31 (DS20005688B, page 61)
return 0x1F4 + 8 * inFilterIndex ;
}
//------------------------------------------------------------------------------
//······················································································································
// OSCILLATOR REGISTER
//------------------------------------------------------------------------------
//······················································································································
static const uint16_t OSC_REGISTER = 0xE00 ;
//------------------------------------------------------------------------------
//······················································································································
// INPUT / OUPUT CONTROL REGISTER
//------------------------------------------------------------------------------
//······················································································································
static const uint16_t IOCON_REGISTER_00_07 = 0xE04 ;
static const uint16_t IOCON_REGISTER_08_15 = 0xE05 ;
static const uint16_t IOCON_REGISTER_16_23 = 0xE06 ;
static const uint16_t IOCON_REGISTER_24_31 = 0xE07 ;
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// RECEIVE FIFO INDEX
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
static const uint8_t RECEIVE_FIFO_INDEX = 1 ;
static const uint8_t TRANSMIT_FIFO_INDEX = 2 ;
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// BYTE BUFFER UTILITY FUNCTIONS
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
static void enterU32InBufferAtIndex (const uint32_t inValue, uint8_t ioBuffer [], const uint8_t inIndex) {
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) ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint32_t u32FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) {
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 ;
}
//------------------------------------------------------------------------------
//······················································································································
static uint16_t u16FromBufferAtIndex (uint8_t ioBuffer [], const uint8_t inIndex) {
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 ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
static inline void turnOffInterrupts () {
#ifndef DISABLEMCP2517FDCOMPAT
#ifdef ARDUINO_ARCH_ESP32
@ -208,6 +209,7 @@ mINT (inINT),
mUsesTXQ (false),
mHardwareTxFIFOFull (false),
mRxInterruptEnabled (true),
mHasDataBitRate (false),
mTransmitFIFOPayload (0),
mTXQBufferPayload (0),
mReceiveFIFOPayload (0),
@ -221,7 +223,7 @@ mDriverTransmitBuffer ()
{
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
void (* inInterruptServiceRoutine) (void)) {
@ -232,7 +234,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
return begin (inSettings, inInterruptServiceRoutine, filters) ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
void (* inInterruptServiceRoutine) (void),
@ -501,6 +503,8 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
// bits 11-8: TSEG2 - 1
// bits 7-4: unused
// bits 3-0: SJW - 1
mHasDataBitRate = inSettings.mDataBitRateFactor != ::DataBitRateFactor::x1 ;
if (mHasDataBitRate) {
data = inSettings.mBitRatePrescaler - 1 ;
data <<= 8 ;
data |= inSettings.mDataPhaseSegment1 - 1 ;
@ -509,6 +513,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
data <<= 8 ;
data |= inSettings.mDataSJW - 1 ;
writeRegister32 (DBTCFG_REGISTER, data) ;
}
//----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24)
// bits 7-4: Transmit Bandwith Sharing Bits ---> 0
// bit 3: Abort All Pending Transmissions bit --> 0
@ -526,14 +531,14 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
}
}
#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
if (mINT != 255) { // 255 means interrupt is not used
#ifdef ARDUINO_ARCH_ESP32
attachInterrupt (itPin, inInterruptServiceRoutine, FALLING) ;
#else
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
attachInterrupt (itPin, inInterruptServiceRoutine, LOW) ; // Thank to Flole998
mSPI.usingInterrupt (itPin) ; // usingInterrupt is not implemented in Arduino ESP32
#endif
}
// If you begin() multiple times without constructor,
@ -545,9 +550,9 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
return errorCode ;
}
//------------------------------------------------------------------------------
//······················································································································
// end method (resets the MCP2517FD, deallocate buffers, and detach interrupt pin)
//------------------------------------------------------------------------------
//······················································································································
bool ACAN2517FD::end (void) {
mSPI.beginTransaction (mSPISettings) ;
@ -592,19 +597,15 @@ bool ACAN2517FD::end (void) {
return ok ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// SEND FRAME
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) {
bool ok = inMessage.isValid () ;
if (ok) {
mSPI.beginTransaction (mSPISettings) ;
#ifdef ARDUINO_ARCH_ESP32
taskDISABLE_INTERRUPTS () ;
#else
noInterrupts () ;
#endif
turnOffInterrupts () ;
if (inMessage.idx == 0) {
ok = inMessage.len <= mTransmitFIFOPayload ;
if (ok) {
@ -616,13 +617,13 @@ bool ACAN2517FD::tryToSend (const CANFDMessage & inMessage) {
ok = sendViaTXQ (inMessage) ;
}
}
turnOnInterrupts () ;
turnOnInterrupts();
mSPI.endTransaction () ;
}
return ok ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
bool result ;
@ -644,7 +645,7 @@ bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
static uint32_t lengthCodeForLength (const uint8_t inLength) {
uint32_t result = inLength & 0x0F ;
@ -660,7 +661,7 @@ static uint32_t lengthCodeForLength (const uint8_t inLength) {
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
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 ;
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit
if (mHasDataBitRate) {
flags |= 1 << 6 ; // Set BRS bit
}
break ;
}
//--- Word count
@ -711,7 +714,7 @@ void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 1, data8);
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
bool ok = mUsesTXQ ;
@ -748,7 +751,9 @@ bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
break ;
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit
if (mHasDataBitRate) {
flags |= 1 << 6 ; // Set BRS bit
}
break ;
}
//--- Word count
@ -777,48 +782,41 @@ bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
return ok ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// RECEIVE FRAME
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::available (void) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const bool hasReceivedMessage = mDriverReceiveBuffer.count () > 0 ;
turnOnInterrupts () ;
turnOnInterrupts();
mSPI.endTransaction () ;
return hasReceivedMessage ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::receive (CANFDMessage & outMessage) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const bool hasReceivedMessage = mDriverReceiveBuffer.remove (outMessage) ;
//--- If receive interrupt is disabled, enable it (added in release 2.17)
if (mINT == 255) { // No interrupt pin
mRxInterruptEnabled = true ;
isr_poll_core () ; // Perform polling
}else if (!mRxInterruptEnabled) {
mSPI.beginTransaction (mSPISettings) ;
#ifdef ARDUINO_ARCH_ESP32
taskDISABLE_INTERRUPTS () ;
#else
noInterrupts () ;
#endif
mRxInterruptEnabled = true ;
uint8_t data8 = readRegister8Assume_SPI_transaction (INT_REGISTER + 2) ;
data8 |= (1 << 1) ; // Receive FIFO Interrupt Enable
writeRegister8Assume_SPI_transaction (INT_REGISTER + 2, data8) ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
}
turnOnInterrupts();
mSPI.endTransaction () ;
return hasReceivedMessage ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMatchCallBack) {
CANFDMessage receivedMessage ;
@ -836,9 +834,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
return hasReceived ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// POLLING (ESP32)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) {
@ -848,22 +846,22 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
}
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// POLLING (other than ESP32)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifndef ARDUINO_ARCH_ESP32
void ACAN2517FD::poll (void) {
noInterrupts () ;
turnOffInterrupts () ;
isr_poll_core () ;
interrupts () ;
turnOnInterrupts () ;
}
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINE (ESP32)
// https://stackoverflow.com/questions/51750377/how-to-disable-interrupt-watchdog-in-esp32-or-increase-isr-time-limit
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifdef ARDUINO_ARCH_ESP32
void ACAN2517FD::isr (void) {
@ -873,9 +871,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
}
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINE (other than ESP32)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifndef ARDUINO_ARCH_ESP32
void ACAN2517FD::isr (void) {
@ -883,9 +881,9 @@ bool ACAN2517FD::dispatchReceivedMessage (const tFilterMatchCallBack inFilterMat
}
#endif
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// INTERRUPT SERVICE ROUTINES (common)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::isr_poll_core (void) {
mSPI.beginTransaction (mSPISettings) ;
@ -935,7 +933,7 @@ void ACAN2517FD::isr_poll_core (void) {
mSPI.endTransaction () ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FIFO is not full
CANFDMessage message ;
@ -950,7 +948,7 @@ void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FI
}
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::receiveInterrupt (void) {
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)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress,
const uint32_t inValue) {
@ -1029,7 +1027,7 @@ void ACAN2517FD::writeRegister32Assume_SPI_transaction (const uint16_t inRegiste
deassertCS () ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress,
const uint8_t inValue) {
@ -1044,7 +1042,7 @@ void ACAN2517FD::writeRegister8Assume_SPI_transaction (const uint16_t inRegister
deassertCS () ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::readRegister32Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- 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 ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint16_t ACAN2517FD::readRegister16Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- 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 ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint8_t ACAN2517FD::readRegister8Assume_SPI_transaction (const uint16_t inRegisterAddress) {
//--- 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] ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// MCP2517FD REGISTER ACCESS, THIRD LEVEL FUNCTIONS (HANDLE CS AND SPI TRANSACTION)
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t inValue) {
mSPI.beginTransaction (mSPISettings) ;
@ -1108,59 +1106,59 @@ void ACAN2517FD::writeRegister8 (const uint16_t inRegisterAddress, const uint8_t
mSPI.endTransaction () ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint8_t ACAN2517FD::readRegister8 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const uint8_t result = readRegister8Assume_SPI_transaction (inRegisterAddress) ;
turnOnInterrupts () ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint16_t ACAN2517FD::readRegister16 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const uint16_t result = readRegister16Assume_SPI_transaction (inRegisterAddress) ;
turnOnInterrupts () ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::writeRegister32 (const uint16_t inRegisterAddress, const uint32_t inValue) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
writeRegister32Assume_SPI_transaction (inRegisterAddress, inValue) ;
turnOnInterrupts () ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::readRegister32 (const uint16_t inRegisterAddress) {
mSPI.beginTransaction (mSPISettings) ;
turnOffInterrupts () ;
const uint32_t result = readRegister32Assume_SPI_transaction (inRegisterAddress) ;
turnOnInterrupts () ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
return result ;
}
//------------------------------------------------------------------------------
//······················································································································
// Current MCP2517FD Operation Mode
//------------------------------------------------------------------------------
//······················································································································
ACAN2517FDSettings::OperationMode ACAN2517FD::currentOperationMode (void) {
const uint8_t mode = readRegister8 (CON_REGISTER + 2) >> 5 ;
return ACAN2517FDSettings::OperationMode (mode) ;
}
//------------------------------------------------------------------------------
//······················································································································
bool ACAN2517FD::recoverFromRestrictedOperationMode (void) {
bool recoveryDone = false ;
@ -1184,9 +1182,9 @@ bool ACAN2517FD::recoverFromRestrictedOperationMode (void) {
return recoveryDone ;
}
//------------------------------------------------------------------------------
//······················································································································
// Set MCP2517FD Operation Mode
//------------------------------------------------------------------------------
//······················································································································
void ACAN2517FD::setOperationMode (const ACAN2517FDSettings::OperationMode inOperationMode) {
// 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));
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::reset2517FD (void) {
mSPI.beginTransaction (mSPISettings) ; // Check RESET is performed with 800 kHz clock
@ -1202,14 +1200,14 @@ void ACAN2517FD::reset2517FD (void) {
assertCS () ;
mSPI.transfer16 (0x00) ; // Reset instruction: 0x0000
deassertCS () ;
turnOnInterrupts () ;
turnOnInterrupts () ;
mSPI.endTransaction () ;
}
//------------------------------------------------------------------------------
//······················································································································
// Sleep Mode to Configuration 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 module will transition automatically to Configuration mode.
@ -1228,21 +1226,21 @@ bool ACAN2517FD::performSleepModeToConfigurationMode (void) {
return inSleepMode ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::errorCounters (void) {
return readRegister32 (TREC_REGISTER) ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FD::diagInfos (const int inIndex) { // thanks to Flole998 and turmary
return readRegister32 (inIndex ? BDIAG1_REGISTER: BDIAG0_REGISTER) ;
}
//------------------------------------------------------------------------------
//······················································································································
// GPIO
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::gpioSetMode (const uint8_t inPin, const uint8_t inMode) {
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) {
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) {
const uint8_t value = readRegister8 (IOCON_REGISTER_16_23) ;
return (value >> inPin) & 1 ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
void ACAN2517FD::configureGPIO0AsXSTBY (void) {
uint8_t value = readRegister8 (IOCON_REGISTER_00_07) ;
@ -1291,4 +1289,4 @@ void ACAN2517FD::configureGPIO0AsXSTBY (void) {
writeRegister8 (IOCON_REGISTER_00_07, value) ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------

View file

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

View file

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

View file

@ -1,19 +1,19 @@
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD (CANFD mode)
// by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD
//
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FDSettings.h"
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#pragma GCC diagnostic error "-Wswitch-enum"
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// sysClock
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) {
uint32_t sysClock = 40UL * 1000 * 1000 ;
@ -39,9 +39,9 @@ uint32_t ACAN2517FDSettings::sysClock (const Oscillator inOscillator) {
return sysClock ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// CONSTRUCTOR
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
ACAN2517FDSettings::ACAN2517FDSettings (const Oscillator inOscillator,
const uint32_t inDesiredArbitrationBitRate,
@ -51,7 +51,61 @@ mOscillator (inOscillator),
mSysClock (sysClock (inOscillator)),
mDesiredArbitrationBitRate (inDesiredArbitrationBitRate),
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 desiredDataBitRate = inDesiredArbitrationBitRate * uint8_t (inDataBitRateFactor) ;
uint32_t smallestError = UINT32_MAX ;
@ -59,7 +113,7 @@ mDataBitRateFactor (inDataBitRateFactor) {
uint32_t bestDataTQCount = maxDataTQCount ; // Setting for lowest bit rate
uint32_t dataTQCount = 4 ;
uint32_t brp = mSysClock / desiredDataBitRate / dataTQCount ;
//--- Loop for finding best BRP and best TQCount
//--- Loop for finding best BRP and best TQCount
while ((dataTQCount <= maxDataTQCount) && (brp > 0)) {
//--- Compute error using brp
if (brp <= MAX_BRP) {
@ -83,18 +137,18 @@ mDataBitRateFactor (inDataBitRateFactor) {
dataTQCount += 1 ;
brp = mSysClock / desiredDataBitRate / dataTQCount ;
}
//--- Compute data PS2 (1 <= PS2 <= 16)
//--- Compute data PS2 (1 <= PS2 <= 16)
uint32_t dataPS2 = bestDataTQCount / 5 ; // For sampling point at 80%
if (dataPS2 == 0) {
dataPS2 = 1 ;
}
//--- Compute data PS1 (1 <= PS1 <= 32)
//--- Compute data PS1 (1 <= PS1 <= 32)
uint32_t dataPS1 = bestDataTQCount - dataPS2 - 1 /* Sync Seg */ ;
if (dataPS1 > MAX_DATA_PHASE_SEGMENT_1) {
dataPS2 += dataPS1 - MAX_DATA_PHASE_SEGMENT_1 ;
dataPS1 = MAX_DATA_PHASE_SEGMENT_1 ;
}
//---
//---
if ((mDesiredArbitrationBitRate * uint32_t (inDataBitRateFactor)) <= (1000UL * 1000)) {
mTDCO = 0 ;
}else{
@ -105,39 +159,40 @@ mDataBitRateFactor (inDataBitRateFactor) {
mDataPhaseSegment2 = (uint8_t) dataPS2 ;
mDataSJW = mDataPhaseSegment2 ;
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%
if (arbitrationPS2 == 0) {
arbitrationPS2 = 1 ;
}
//--- Compute PS1 (1 <= PS1 <= 256)
//--- Compute PS1 (1 <= PS1 <= 256)
uint32_t arbitrationPS1 = arbitrationTQCount - arbitrationPS2 - 1 /* Sync Seg */ ;
if (arbitrationPS1 > MAX_ARBITRATION_PHASE_SEGMENT_1) {
arbitrationPS2 += arbitrationPS1 - MAX_ARBITRATION_PHASE_SEGMENT_1 ;
arbitrationPS1 = MAX_ARBITRATION_PHASE_SEGMENT_1 ;
}
//---
//---
mBitRatePrescaler = (uint16_t) bestBRP ;
mArbitrationPhaseSegment1 = (uint16_t) arbitrationPS1 ;
mArbitrationPhaseSegment2 = (uint8_t) arbitrationPS2 ;
mArbitrationSJW = mArbitrationPhaseSegment2 ; // Always 1 <= SJW <= 128, and SJW <= mArbitrationPhaseSegment2
//--- Final check of the nominal configuration
//--- Final check of the nominal configuration
const uint32_t W = arbitrationTQCount * 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) ;
}
} ;
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// ACCESSORS
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::actualArbitrationBitRate (void) const {
const uint32_t arbitrationTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
return mSysClock / mBitRatePrescaler / arbitrationTQCount ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::actualDataBitRate (void) const {
if (mDataBitRateFactor == DataBitRateFactor::x1) {
@ -148,14 +203,14 @@ uint32_t ACAN2517FDSettings::actualDataBitRate (void) const {
}
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::exactArbitrationBitRate (void) const {
const uint32_t TQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
return mSysClock == (mBitRatePrescaler * mDesiredArbitrationBitRate * TQCount) ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::exactDataBitRate (void) const {
if (mDataBitRateFactor == DataBitRateFactor::x1) {
@ -166,7 +221,7 @@ bool ACAN2517FDSettings::exactDataBitRate (void) const {
}
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const {
bool result = mDataBitRateFactor == DataBitRateFactor::x1 ;
@ -178,7 +233,7 @@ bool ACAN2517FDSettings::dataBitRateIsAMultipleOfArbitrationBitRate (void) const
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::ppmFromDesiredArbitrationBitRate (void) const {
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) ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const {
const uint32_t nominalTQCount = 1 /* Sync Seg */ + mArbitrationPhaseSegment1 + mArbitrationPhaseSegment2 ;
@ -197,7 +252,7 @@ uint32_t ACAN2517FDSettings::arbitrationSamplePointFromBitStart (void) const {
return (samplePoint * partPerCent) / nominalTQCount ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const {
const uint32_t nominalTQCount = 1 /* Sync Seg */ + mDataPhaseSegment1 + mDataPhaseSegment2 ;
@ -206,7 +261,7 @@ uint32_t ACAN2517FDSettings::dataSamplePointFromBitStart (void) const {
return (samplePoint * partPerCent) / nominalTQCount ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const {
uint32_t errorCode = 0 ; // Means no error
@ -274,9 +329,9 @@ uint32_t ACAN2517FDSettings::CANBitSettingConsistency (void) const {
return errorCode ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// RAM USAGE
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::ramUsage (void) const {
uint32_t result = 0 ;
@ -290,11 +345,11 @@ uint32_t ACAN2517FDSettings::ramUsage (void) const {
return result ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
uint32_t ACAN2517FDSettings::objectSizeForPayload (const PayloadSize inPayload) {
static const uint8_t kPayload [8] = {16, 20, 24, 28, 32, 40, 56, 72} ;
return kPayload [inPayload] ;
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------

View file

@ -1,25 +1,25 @@
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// A CAN driver for MCP2517FD (CANFD mode)
// by Pierre Molinaro
// https://github.com/pierremolinaro/acan2517FD
//
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#pragma once
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#include "ACAN2517FD_DataBitRateFactor.h"
#include "ACANFD_DataBitRateFactor.h"
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// ACAN2517FDSettings class
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
class ACAN2517FDSettings {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// ENUMERATED TYPES
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// ENUMERATED TYPES
//······················································································································
public: typedef enum : uint8_t {
OSC_4MHz,
@ -64,9 +64,9 @@ class ACAN2517FDSettings {
PAYLOAD_64 = 7
} 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 {
DATA_BITRATE_x1 = 1,
@ -81,18 +81,18 @@ class ACAN2517FDSettings {
DATA_BITRATE_x10 = 10
} DataBitRateFactor_Deprecated ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// CONSTRUCTOR
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// CONSTRUCTOR
//······················································································································
public: ACAN2517FDSettings (const Oscillator inOscillator,
const uint32_t inDesiredArbitrationBitRate,
const DataBitRateFactor inDataBitRateFactor,
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,
const uint32_t inDesiredArbitrationBitRate,
@ -101,9 +101,9 @@ class ACAN2517FDSettings {
ACAN2517FDSettings (inOscillator, inDesiredArbitrationBitRate, DataBitRateFactor (inDataBitRateFactor), inTolerancePPM) {
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// CAN BIT TIMING
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// CAN BIT TIMING
//······················································································································
private: Oscillator mOscillator ;
private: uint32_t mSysClock ; // In Hz
@ -123,44 +123,44 @@ class ACAN2517FDSettings {
//--- Transmitter Delay Compensation Offset
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
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// MCP2517FD INT pin is Open Drain ?
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// MCP2517FD INT pin is Open Drain ?
//······················································································································
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
// 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 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 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 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Requested mode
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// Requested mode
//······················································································································
public: OperationMode mRequestedMode = NormalFD ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// TRANSMIT FIFO
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// TRANSMIT FIFO
//······················································································································
//--- Driver transmit buffer size
public: uint16_t mDriverTransmitFIFOSize = 16 ; // >= 0
public: uint16_t mDriverTransmitFIFOSize = 22 ; // >= 0
//--- Controller transmit FIFO size
public: uint8_t mControllerTransmitFIFOSize = 1 ; // 1 ... 32
@ -174,9 +174,9 @@ class ACAN2517FDSettings {
//--- Controller transmit FIFO retransmission attempts
public: RetransmissionAttempts mControllerTransmitFIFORetransmissionAttempts = UnlimitedNumber ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// TXQ BUFFER
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// TXQ BUFFER
//······················································································································
//--- TXQ buffer size (0 --> TXQ disabled)
public: uint8_t mControllerTXQSize = 0 ; // 0 ... 32
@ -191,9 +191,9 @@ class ACAN2517FDSettings {
public: RetransmissionAttempts mControllerTXQBufferRetransmissionAttempts = UnlimitedNumber ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// RECEIVE FIFO
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// RECEIVE FIFO
//······················································································································
//--- Driver receive buffer size
public: uint16_t mDriverReceiveFIFOSize = 32 ; // > 0
@ -204,15 +204,15 @@ class ACAN2517FDSettings {
//--- Controller receive FIFO size
public: uint8_t mControllerReceiveFIFOSize = 27 ; // 1 ... 32
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// SYSCLOCK frequency computation
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// SYSCLOCK frequency computation
//······················································································································
public: static uint32_t sysClock (const Oscillator inOscillator) ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Accessors
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// Accessors
//······················································································································
public: Oscillator oscillator (void) const { return mOscillator ; }
public: uint32_t sysClock (void) const { return mSysClock ; }
@ -222,61 +222,61 @@ class ACAN2517FDSettings {
public: bool exactDataBitRate (void) const ;
public: bool dataBitRateIsAMultipleOfArbitrationBitRate (void) const ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// RAM USAGE
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// RAM USAGE
//······················································································································
public: uint32_t ramUsage (void) const ;
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 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 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 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Constants returned by CANBitSettingConsistency
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// Constants returned by CANBitSettingConsistency
//······················································································································
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 kArbitrationPhaseSegment1IsLowerThan2 = uint32_t (1) << 2 ;
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 kArbitrationPhaseSegment2IsGreaterThan128 = uint32_t (1) << 5 ;
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 kArbitrationSJWIsGreaterThanPhaseSegment1 = uint32_t (1) << 8 ;
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 kDataPhaseSegment1IsLowerThan2 = uint32_t (1) << 11 ;
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 kDataPhaseSegment2IsGreaterThan16 = uint32_t (1) << 14 ;
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 kDataSJWIsGreaterThanPhaseSegment1 = uint32_t (1) << 17 ;
public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment2 = uint32_t (1) << 18 ;
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 kArbitrationPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 2 ;
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 kArbitrationPhaseSegment2IsGreaterThan128 = ((uint32_t) 1) << 5 ;
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 kArbitrationSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 8 ;
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 kDataPhaseSegment1IsLowerThan2 = ((uint32_t) 1) << 11 ;
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 kDataPhaseSegment2IsGreaterThan16 = ((uint32_t) 1) << 14 ;
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 kDataSJWIsGreaterThanPhaseSegment1 = ((uint32_t) 1) << 17 ;
public: static const uint32_t kDataSJWIsGreaterThanPhaseSegment2 = ((uint32_t) 1) << 18 ;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Max values
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//······················································································································
// Max values
//······················································································································
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_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
// by Pierre Molinaro
@ -6,16 +6,16 @@
// https://github.com/pierremolinaro/ACAN_T4
// https://github.com/pierremolinaro/ACAN2517FD
//
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#ifndef ACANFD_DATA_BIT_RATE_FACTOR_DEFINED
#define ACANFD_DATA_BIT_RATE_FACTOR_DEFINED
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#include <stdint.h>
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
enum class DataBitRateFactor : uint8_t {
x1 = 1,
@ -30,6 +30,6 @@ enum class DataBitRateFactor : uint8_t {
x10 = 10
} ;
//------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
#endif

View file

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

View file

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