Skip to content

Commit

Permalink
Version 2.1.5, Fixed retransmission attempts setting bug, Added NoRet…
Browse files Browse the repository at this point in the history
…ransmissionAttemptsDemoTeensy3x.ino sketch.
  • Loading branch information
pierremolinaro committed Jan 27, 2021
1 parent 8a83c2a commit 5b86a8c
Show file tree
Hide file tree
Showing 5 changed files with 230 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
//——————————————————————————————————————————————————————————————————————————————
// ACAN2517FD Demo for "ThreeAttempts" and "Disabled" setting,
// using hardware SPI1, with an external interrupt
// For this sketch, the MCP2517FD should be alone on the CAN bus.
//
// A CAN message should be acknowledged by a receiver.
// By default, no receiver -> no acknnowledge, the message is sent indefinitely
// The settings.mControllerTransmitFIFORetransmissionAttempts can be used for
// specifying:
// - only one attempt (ACAN2517Settings::Disabled);
// - three attempts (ACAN2517Settings::ThreeAttempts);
// - unlimited number of attempts (ACAN2517Settings::Unlimited, default setting).
//——————————————————————————————————————————————————————————————————————————————

#include <ACAN2517FD.h>

//——————————————————————————————————————————————————————————————————————————————
// MCP2517 connections: adapt theses settings to your design
// As hardware SPI is used, you should select pins that support SPI functions.
// This sketch is designed for a Teensy 3.5, using SPI1
// But standard Teensy 3.5 SPI1 pins are not used
// SCK input of MCP2517 is connected to pin #32
// SDI input of MCP2517 is connected to pin #0
// SDO output of MCP2517 is connected to pin #1
// CS input of MCP2517 should be connected to a digital output port
// INT output of MCP2517 should be connected to a digital input port, with interrupt capability
//——————————————————————————————————————————————————————————————————————————————

static const byte MCP2517_SCK = 32 ; // SCK input of MCP2517
static const byte MCP2517_SDI = 0 ; // SDI input of MCP2517
static const byte MCP2517_SDO = 1 ; // SDO output of MCP2517

static const byte MCP2517_CS = 31 ; // CS input of MCP2517
static const byte MCP2517_INT = 38 ; // INT output of MCP2517

//——————————————————————————————————————————————————————————————————————————————
// MCP2517 Driver object
//——————————————————————————————————————————————————————————————————————————————

ACAN2517FD can (MCP2517_CS, SPI1, MCP2517_INT) ;

//——————————————————————————————————————————————————————————————————————————————
// SETUP
//——————————————————————————————————————————————————————————————————————————————

void setup () {
//--- Switch on builtin led
pinMode (LED_BUILTIN, OUTPUT) ;
digitalWrite (LED_BUILTIN, HIGH) ;
//--- Start serial
Serial.begin (38400) ;
//--- Wait for serial (blink led at 10 Hz during waiting)
while (!Serial) {
delay (50) ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
}
//--- Define alternate pins for SPI1 (see https://www.pjrc.com/teensy/td_libs_SPI.html)
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SDI) ;
Serial.print (" for MOSI: ") ;
Serial.println (SPI1.pinIsMOSI (MCP2517_SDI) ? "yes" : "NO!!!") ;
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SDO) ;
Serial.print (" for MISO: ") ;
Serial.println (SPI1.pinIsMISO (MCP2517_SDO) ? "yes" : "NO!!!") ;
Serial.print ("Using pin #") ;
Serial.print (MCP2517_SCK) ;
Serial.print (" for SCK: ") ;
Serial.println (SPI1.pinIsSCK (MCP2517_SCK) ? "yes" : "NO!!!") ;
SPI1.setMOSI (MCP2517_SDI) ;
SPI1.setMISO (MCP2517_SDO) ;
SPI1.setSCK (MCP2517_SCK) ;
//----------------------------------- Begin SPI1
SPI1.begin () ;
//--- Configure ACAN2517
Serial.print ("sizeof (ACAN2517Settings): ") ;
Serial.print (sizeof (ACAN2517FDSettings)) ;
Serial.println (" bytes") ;
Serial.println ("Configure ACAN2517") ;
ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, 125 * 1000, DataBitRateFactor::x4) ;
//--- The MCP2517FD internal RAM is limited, the size of the receive buffer is reduced
settings.mControllerReceiveFIFOSize = 2 ;
//--- Configure regular transmit chain (used when message.idx == 0, default)
settings.mDriverTransmitFIFOSize = 0 ;
settings.mControllerTransmitFIFOSize = 1 ;
settings.mControllerTransmitFIFORetransmissionAttempts = ACAN2517FDSettings::Disabled ;
//--- Configure TXQ transmit chain (used when message.idx == 255)
settings.mControllerTXQSize = 1 ;
settings.mControllerTXQBufferRetransmissionAttempts = ACAN2517FDSettings::Disabled ;
const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }) ;
if (errorCode == 0) {
Serial.print ("Bit Rate prescaler: ") ;
Serial.println (settings.mBitRatePrescaler) ;
Serial.print ("Arbitration Phase segment 1: ") ;
Serial.println (settings.mArbitrationPhaseSegment1) ;
Serial.print ("Arbitration Phase segment 2: ") ;
Serial.println (settings.mArbitrationPhaseSegment2) ;
Serial.print ("Arbitration SJW:") ;
Serial.println (settings.mArbitrationSJW) ;
Serial.print ("Actual Arbitration Bit Rate: ") ;
Serial.print (settings.actualArbitrationBitRate ()) ;
Serial.println (" bit/s") ;
Serial.print ("Exact Arbitration Bit Rate ? ") ;
Serial.println (settings.exactArbitrationBitRate () ? "yes" : "no") ;
Serial.print ("Arbitration Sample point: ") ;
Serial.print (settings.arbitrationSamplePointFromBitStart ()) ;
Serial.println ("%") ;
Serial.print ("Data Phase segment 1: ") ;
Serial.println (settings.mDataPhaseSegment1) ;
Serial.print ("Data Phase segment 2: ") ;
Serial.println (settings.mDataPhaseSegment2) ;
Serial.print ("Data SJW:") ;
Serial.println (settings.mDataSJW) ;
}else{
Serial.print ("Configuration error 0x") ;
Serial.println (errorCode, HEX) ;
}
}

//----------------------------------------------------------------------------------------------------------------------

static uint32_t gBlinkLedDate = 1000 ;
static uint32_t gReceivedFrameCount = 0 ;
static uint32_t gSentFrameCount = 0 ;

//——————————————————————————————————————————————————————————————————————————————

void loop() {
CANFDMessage frame ;
if (gBlinkLedDate < millis ()) {
gBlinkLedDate += 500 ;
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
frame.len = 64 ;
for (uint8_t i=0 ; i<frame.len ; i++) {
frame.data [i] = i ;
}
// frame.idx = 255 ; // Uncomment this for sending throught TXQ
const bool ok = can.tryToSend (frame) ;
if (ok) {
gSentFrameCount += 1 ;
Serial.print ("Sent: ") ;
Serial.println (gSentFrameCount) ;
}else{
Serial.println ("Send failure") ;
}
}
if (can.available ()) {
can.receive (frame) ;
gReceivedFrameCount ++ ;
Serial.print ("Received: ") ;
Serial.println (gReceivedFrameCount) ;
}
}

//——————————————————————————————————————————————————————————————————————————————
Binary file modified extras/acan2517FD.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ACAN2517FD
version=2.1.4
version=2.1.5
author=Pierre Molinaro
maintainer=Pierre Molinaro <Pierre.Molinaro@pcmolinaro.name>
sentence=Driver for MCP2517FD and MCP2518FD CAN Controller (CAN FD mode)
Expand Down
126 changes: 73 additions & 53 deletions src/ACAN2517FD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
// Bit 0: RTXAT ---> 1: Enable CiFIFOCONm.TXAT to control retransmission attempts
data8 = 0x01 ; // Enable RTXAT to limit retransmissions (Flole)
data8 |= mUsesTXQ ? (1 << 4) : 0x00 ; // Bug fix in 1.1.4 (thanks to danielhenz)
writeRegister8 (CON_REGISTER + 2, data8); // DS20005688B, page 24
writeRegister8 (CON_REGISTER + 2, data8) ; // DS20005688B, page 24
//----------------------------------- Configure RX FIFO (FIFOCON, DS20005688B, page 52)
data8 = inSettings.mControllerReceiveFIFOSize - 1 ; // Set receive FIFO size
data8 |= inSettings.mControllerReceiveFIFOPayload << 5 ; // Payload
Expand All @@ -430,6 +430,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
data8 |= inSettings.mControllerTransmitFIFOPayload << 5 ; // Payload
writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 3, data8) ;
data8 = 1 << 7 ; // FIFO is a Tx FIFO
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
mTransmitFIFOPayload = ACAN2517FDSettings::objectSizeForPayload (inSettings.mControllerTransmitFIFOPayload) ;
//----------------------------------- Configure receive filters
Expand All @@ -450,6 +451,8 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
data8 = (1 << 1) ; // Receive FIFO Interrupt Enable
data8 |= (1 << 0) ; // Transmit FIFO Interrupt Enable
writeRegister8 (INT_REGISTER + 2, data8) ;
data8 = (1 << 2) ; // TXATIE ---> 1: Transmit Attempt Interrupt Enable bit
writeRegister8 (INT_REGISTER + 3, data8) ;
//----------------------------------- Program nominal bit rate (NBTCFG register)
// bits 31-24: BRP - 1
// bits 23-16: TSEG1 - 1
Expand Down Expand Up @@ -484,7 +487,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
data |= inSettings.mDataSJW - 1 ;
writeRegister32 (DBTCFG_REGISTER, data) ;
}
//----------------------------------- Request mode (CON_REGISTER + 3)
//----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24)
// bits 7-4: Transmit Bandwith Sharing Bits ---> 0
// bit 3: Abort All Pending Transmissions bit --> 0
mTXBWS_RequestedMode = inSettings.mRequestedMode | (TXBWS << 4) ;
Expand Down Expand Up @@ -571,6 +574,7 @@ bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
if ((status & 1) == 0) { // FIFO is full
uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
data8 |= 1 ; // Enable "FIFO not full" interrupt
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
mHardwareTxFIFOFull = true ;
}
Expand Down Expand Up @@ -650,59 +654,69 @@ void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
//----------------------------------------------------------------------------------------------------------------------

bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
//--- Enter message only if TXQ FIFO is not full (see DS20005688B, page 50)
const bool TXQNotFull = mUsesTXQ && (readRegister8Assume_SPI_transaction (TXQSTA_REGISTER) & 1) != 0 ;
if (TXQNotFull) {
const uint16_t ramAddress = (uint16_t) (0x400 + readRegister32Assume_SPI_transaction (TXQUA_REGISTER)) ;
//--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27)
uint32_t idf = inMessage.id ;
if (inMessage.ext) {
idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ;
}
//--- Write DLC field, FDF, BRS, RTR, IDE bits
uint32_t flags = lengthCodeForLength (inMessage.len) ;
if (inMessage.ext) {
flags |= 1 << 4 ; // Set EXT bit
bool ok = mUsesTXQ ;
if (ok) {
uint8_t sta = readRegister8Assume_SPI_transaction (TXQSTA_REGISTER) ;
//--- Check Transmit Attempts Exhausted Interrupt Pending bit
ok = (sta & (1 << 4)) != 0 ;
if (ok) {
writeRegister8Assume_SPI_transaction (TXQSTA_REGISTER, ~ (1 << 4)) ;
}else{
//--- Enter message only if TXQ FIFO is not full (see DS20005688B, page 50)
ok = (sta & 1) != 0 ;
}
switch (inMessage.type) {
case CANFDMessage::CAN_REMOTE :
flags |= 1 << 5 ; // Set RTR bit
break ;
case CANFDMessage::CAN_DATA :
break ;
case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit
break ;
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit
if (mHasDataBitRate) {
flags |= 1 << 6 ; // Set BRS bit
if (ok) {
const uint16_t ramAddress = (uint16_t) (0x400 + readRegister32Assume_SPI_transaction (TXQUA_REGISTER)) ;
//--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27)
uint32_t idf = inMessage.id ;
if (inMessage.ext) {
idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ;
}
break ;
}
//--- Word count
const uint32_t wordCount = (inMessage.len + 3) / 4 ;
//--- Transfer frame to the MCP2517FD
uint8_t buff[74] = {0} ;
//--- Enter command
const uint16_t writeCommand = (ramAddress & 0x0FFF) | (0b0010 << 12) ;
buff[0] = writeCommand >> 8 ;
buff[1] = writeCommand & 0xFF ;
//--- Enter values
enterU32InBufferAtIndex (idf, buff, 2) ;
enterU32InBufferAtIndex (flags, buff, 6) ;
for (uint32_t i=0 ; i < wordCount ; i++) {
enterU32InBufferAtIndex (inMessage.data32 [i], buff, 10 + 4 * i) ;
//--- Write DLC field, FDF, BRS, RTR, IDE bits
uint32_t flags = lengthCodeForLength (inMessage.len) ;
if (inMessage.ext) {
flags |= 1 << 4 ; // Set EXT bit
}
switch (inMessage.type) {
case CANFDMessage::CAN_REMOTE :
flags |= 1 << 5 ; // Set RTR bit
break ;
case CANFDMessage::CAN_DATA :
break ;
case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH :
flags |= 1 << 7 ; // Set FDF bit
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
const uint32_t wordCount = (inMessage.len + 3) / 4 ;
//--- Transfer frame to the MCP2517FD
uint8_t buff[74] = {0} ;
//--- Enter command
const uint16_t writeCommand = (ramAddress & 0x0FFF) | (0b0010 << 12) ;
buff[0] = writeCommand >> 8 ;
buff[1] = writeCommand & 0xFF ;
//--- Enter values
enterU32InBufferAtIndex (idf, buff, 2) ;
enterU32InBufferAtIndex (flags, buff, 6) ;
for (uint32_t i=0 ; i < wordCount ; i++) {
enterU32InBufferAtIndex (inMessage.data32 [i], buff, 10 + 4 * i) ;
}
//--- SPI transfer
assertCS () ;
mSPI.transfer (buff, 10 + 4 * wordCount) ;
deassertCS () ;
//--- Increment FIFO, send message (see DS20005688B, page 48)
const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit
writeRegister8Assume_SPI_transaction (TXQCON_REGISTER + 1, data8);
}
//--- SPI transfer
assertCS () ;
mSPI.transfer (buff, 10 + 4 * wordCount) ;
deassertCS () ;
//--- Increment FIFO, send message (see DS20005688B, page 48)
const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit
writeRegister8Assume_SPI_transaction (TXQCON_REGISTER + 1, data8);
}
return TXQNotFull ;
return ok ;
}

//----------------------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -825,7 +839,12 @@ bool ACAN2517FD::isr_core (void) {
receiveInterrupt () ;
handled = true ;
}
if ((it & (1 << 0)) != 0) { // Transmit FIFO interrupt
if ((it & (1 << 10)) != 0) { // Transmit Attempt interrupt
//--- Clear Pending Transmit Attempt interrupt bit
writeRegister8Assume_SPI_transaction (FIFOSTA_REGISTER (TRANSMIT_FIFO_INDEX), ~ (1 << 4)) ;
transmitInterrupt () ;
handled = true ;
}else if ((it & (1 << 0)) != 0) { // Transmit FIFO interrupt
transmitInterrupt () ;
handled = true ;
}
Expand Down Expand Up @@ -863,7 +882,8 @@ void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FI
if (hasMessage) {
appendInControllerTxFIFO (message) ;
}else{ // No message in transmit FIFO: disable "FIFO not full" interrupt
const uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
mHardwareTxFIFOFull = false ;
}
Expand Down
2 changes: 1 addition & 1 deletion src/ACAN2517FDSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ACAN2517FDSettings {
} 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 {
Expand Down

0 comments on commit 5b86a8c

Please sign in to comment.