Skip to content

Commit 5b86a8c

Browse files
Version 2.1.5, Fixed retransmission attempts setting bug, Added NoRetransmissionAttemptsDemoTeensy3x.ino sketch.
1 parent 8a83c2a commit 5b86a8c

File tree

5 files changed

+230
-55
lines changed

5 files changed

+230
-55
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
//——————————————————————————————————————————————————————————————————————————————
2+
// ACAN2517FD Demo for "ThreeAttempts" and "Disabled" setting,
3+
// using hardware SPI1, with an external interrupt
4+
// For this sketch, the MCP2517FD should be alone on the CAN bus.
5+
//
6+
// A CAN message should be acknowledged by a receiver.
7+
// By default, no receiver -> no acknnowledge, the message is sent indefinitely
8+
// The settings.mControllerTransmitFIFORetransmissionAttempts can be used for
9+
// specifying:
10+
// - only one attempt (ACAN2517Settings::Disabled);
11+
// - three attempts (ACAN2517Settings::ThreeAttempts);
12+
// - unlimited number of attempts (ACAN2517Settings::Unlimited, default setting).
13+
//——————————————————————————————————————————————————————————————————————————————
14+
15+
#include <ACAN2517FD.h>
16+
17+
//——————————————————————————————————————————————————————————————————————————————
18+
// MCP2517 connections: adapt theses settings to your design
19+
// As hardware SPI is used, you should select pins that support SPI functions.
20+
// This sketch is designed for a Teensy 3.5, using SPI1
21+
// But standard Teensy 3.5 SPI1 pins are not used
22+
// SCK input of MCP2517 is connected to pin #32
23+
// SDI input of MCP2517 is connected to pin #0
24+
// SDO output of MCP2517 is connected to pin #1
25+
// CS input of MCP2517 should be connected to a digital output port
26+
// INT output of MCP2517 should be connected to a digital input port, with interrupt capability
27+
//——————————————————————————————————————————————————————————————————————————————
28+
29+
static const byte MCP2517_SCK = 32 ; // SCK input of MCP2517
30+
static const byte MCP2517_SDI = 0 ; // SDI input of MCP2517
31+
static const byte MCP2517_SDO = 1 ; // SDO output of MCP2517
32+
33+
static const byte MCP2517_CS = 31 ; // CS input of MCP2517
34+
static const byte MCP2517_INT = 38 ; // INT output of MCP2517
35+
36+
//——————————————————————————————————————————————————————————————————————————————
37+
// MCP2517 Driver object
38+
//——————————————————————————————————————————————————————————————————————————————
39+
40+
ACAN2517FD can (MCP2517_CS, SPI1, MCP2517_INT) ;
41+
42+
//——————————————————————————————————————————————————————————————————————————————
43+
// SETUP
44+
//——————————————————————————————————————————————————————————————————————————————
45+
46+
void setup () {
47+
//--- Switch on builtin led
48+
pinMode (LED_BUILTIN, OUTPUT) ;
49+
digitalWrite (LED_BUILTIN, HIGH) ;
50+
//--- Start serial
51+
Serial.begin (38400) ;
52+
//--- Wait for serial (blink led at 10 Hz during waiting)
53+
while (!Serial) {
54+
delay (50) ;
55+
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
56+
}
57+
//--- Define alternate pins for SPI1 (see https://www.pjrc.com/teensy/td_libs_SPI.html)
58+
Serial.print ("Using pin #") ;
59+
Serial.print (MCP2517_SDI) ;
60+
Serial.print (" for MOSI: ") ;
61+
Serial.println (SPI1.pinIsMOSI (MCP2517_SDI) ? "yes" : "NO!!!") ;
62+
Serial.print ("Using pin #") ;
63+
Serial.print (MCP2517_SDO) ;
64+
Serial.print (" for MISO: ") ;
65+
Serial.println (SPI1.pinIsMISO (MCP2517_SDO) ? "yes" : "NO!!!") ;
66+
Serial.print ("Using pin #") ;
67+
Serial.print (MCP2517_SCK) ;
68+
Serial.print (" for SCK: ") ;
69+
Serial.println (SPI1.pinIsSCK (MCP2517_SCK) ? "yes" : "NO!!!") ;
70+
SPI1.setMOSI (MCP2517_SDI) ;
71+
SPI1.setMISO (MCP2517_SDO) ;
72+
SPI1.setSCK (MCP2517_SCK) ;
73+
//----------------------------------- Begin SPI1
74+
SPI1.begin () ;
75+
//--- Configure ACAN2517
76+
Serial.print ("sizeof (ACAN2517Settings): ") ;
77+
Serial.print (sizeof (ACAN2517FDSettings)) ;
78+
Serial.println (" bytes") ;
79+
Serial.println ("Configure ACAN2517") ;
80+
ACAN2517FDSettings settings (ACAN2517FDSettings::OSC_4MHz10xPLL, 125 * 1000, DataBitRateFactor::x4) ;
81+
//--- The MCP2517FD internal RAM is limited, the size of the receive buffer is reduced
82+
settings.mControllerReceiveFIFOSize = 2 ;
83+
//--- Configure regular transmit chain (used when message.idx == 0, default)
84+
settings.mDriverTransmitFIFOSize = 0 ;
85+
settings.mControllerTransmitFIFOSize = 1 ;
86+
settings.mControllerTransmitFIFORetransmissionAttempts = ACAN2517FDSettings::Disabled ;
87+
//--- Configure TXQ transmit chain (used when message.idx == 255)
88+
settings.mControllerTXQSize = 1 ;
89+
settings.mControllerTXQBufferRetransmissionAttempts = ACAN2517FDSettings::Disabled ;
90+
const uint32_t errorCode = can.begin (settings, [] { can.isr () ; }) ;
91+
if (errorCode == 0) {
92+
Serial.print ("Bit Rate prescaler: ") ;
93+
Serial.println (settings.mBitRatePrescaler) ;
94+
Serial.print ("Arbitration Phase segment 1: ") ;
95+
Serial.println (settings.mArbitrationPhaseSegment1) ;
96+
Serial.print ("Arbitration Phase segment 2: ") ;
97+
Serial.println (settings.mArbitrationPhaseSegment2) ;
98+
Serial.print ("Arbitration SJW:") ;
99+
Serial.println (settings.mArbitrationSJW) ;
100+
Serial.print ("Actual Arbitration Bit Rate: ") ;
101+
Serial.print (settings.actualArbitrationBitRate ()) ;
102+
Serial.println (" bit/s") ;
103+
Serial.print ("Exact Arbitration Bit Rate ? ") ;
104+
Serial.println (settings.exactArbitrationBitRate () ? "yes" : "no") ;
105+
Serial.print ("Arbitration Sample point: ") ;
106+
Serial.print (settings.arbitrationSamplePointFromBitStart ()) ;
107+
Serial.println ("%") ;
108+
Serial.print ("Data Phase segment 1: ") ;
109+
Serial.println (settings.mDataPhaseSegment1) ;
110+
Serial.print ("Data Phase segment 2: ") ;
111+
Serial.println (settings.mDataPhaseSegment2) ;
112+
Serial.print ("Data SJW:") ;
113+
Serial.println (settings.mDataSJW) ;
114+
}else{
115+
Serial.print ("Configuration error 0x") ;
116+
Serial.println (errorCode, HEX) ;
117+
}
118+
}
119+
120+
//----------------------------------------------------------------------------------------------------------------------
121+
122+
static uint32_t gBlinkLedDate = 1000 ;
123+
static uint32_t gReceivedFrameCount = 0 ;
124+
static uint32_t gSentFrameCount = 0 ;
125+
126+
//——————————————————————————————————————————————————————————————————————————————
127+
128+
void loop() {
129+
CANFDMessage frame ;
130+
if (gBlinkLedDate < millis ()) {
131+
gBlinkLedDate += 500 ;
132+
digitalWrite (LED_BUILTIN, !digitalRead (LED_BUILTIN)) ;
133+
frame.len = 64 ;
134+
for (uint8_t i=0 ; i<frame.len ; i++) {
135+
frame.data [i] = i ;
136+
}
137+
// frame.idx = 255 ; // Uncomment this for sending throught TXQ
138+
const bool ok = can.tryToSend (frame) ;
139+
if (ok) {
140+
gSentFrameCount += 1 ;
141+
Serial.print ("Sent: ") ;
142+
Serial.println (gSentFrameCount) ;
143+
}else{
144+
Serial.println ("Send failure") ;
145+
}
146+
}
147+
if (can.available ()) {
148+
can.receive (frame) ;
149+
gReceivedFrameCount ++ ;
150+
Serial.print ("Received: ") ;
151+
Serial.println (gReceivedFrameCount) ;
152+
}
153+
}
154+
155+
//——————————————————————————————————————————————————————————————————————————————

extras/acan2517FD.pdf

1.09 KB
Binary file not shown.

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=ACAN2517FD
2-
version=2.1.4
2+
version=2.1.5
33
author=Pierre Molinaro
44
maintainer=Pierre Molinaro <Pierre.Molinaro@pcmolinaro.name>
55
sentence=Driver for MCP2517FD and MCP2518FD CAN Controller (CAN FD mode)

src/ACAN2517FD.cpp

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
412412
// Bit 0: RTXAT ---> 1: Enable CiFIFOCONm.TXAT to control retransmission attempts
413413
data8 = 0x01 ; // Enable RTXAT to limit retransmissions (Flole)
414414
data8 |= mUsesTXQ ? (1 << 4) : 0x00 ; // Bug fix in 1.1.4 (thanks to danielhenz)
415-
writeRegister8 (CON_REGISTER + 2, data8); // DS20005688B, page 24
415+
writeRegister8 (CON_REGISTER + 2, data8) ; // DS20005688B, page 24
416416
//----------------------------------- Configure RX FIFO (FIFOCON, DS20005688B, page 52)
417417
data8 = inSettings.mControllerReceiveFIFOSize - 1 ; // Set receive FIFO size
418418
data8 |= inSettings.mControllerReceiveFIFOPayload << 5 ; // Payload
@@ -430,6 +430,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
430430
data8 |= inSettings.mControllerTransmitFIFOPayload << 5 ; // Payload
431431
writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX) + 3, data8) ;
432432
data8 = 1 << 7 ; // FIFO is a Tx FIFO
433+
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
433434
writeRegister8 (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
434435
mTransmitFIFOPayload = ACAN2517FDSettings::objectSizeForPayload (inSettings.mControllerTransmitFIFOPayload) ;
435436
//----------------------------------- Configure receive filters
@@ -450,6 +451,8 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
450451
data8 = (1 << 1) ; // Receive FIFO Interrupt Enable
451452
data8 |= (1 << 0) ; // Transmit FIFO Interrupt Enable
452453
writeRegister8 (INT_REGISTER + 2, data8) ;
454+
data8 = (1 << 2) ; // TXATIE ---> 1: Transmit Attempt Interrupt Enable bit
455+
writeRegister8 (INT_REGISTER + 3, data8) ;
453456
//----------------------------------- Program nominal bit rate (NBTCFG register)
454457
// bits 31-24: BRP - 1
455458
// bits 23-16: TSEG1 - 1
@@ -484,7 +487,7 @@ uint32_t ACAN2517FD::begin (const ACAN2517FDSettings & inSettings,
484487
data |= inSettings.mDataSJW - 1 ;
485488
writeRegister32 (DBTCFG_REGISTER, data) ;
486489
}
487-
//----------------------------------- Request mode (CON_REGISTER + 3)
490+
//----------------------------------- Request mode (CON_REGISTER + 3, DS20005688B, page 24)
488491
// bits 7-4: Transmit Bandwith Sharing Bits ---> 0
489492
// bit 3: Abort All Pending Transmissions bit --> 0
490493
mTXBWS_RequestedMode = inSettings.mRequestedMode | (TXBWS << 4) ;
@@ -571,6 +574,7 @@ bool ACAN2517FD::enterInTransmitBuffer (const CANFDMessage & inMessage) {
571574
if ((status & 1) == 0) { // FIFO is full
572575
uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
573576
data8 |= 1 ; // Enable "FIFO not full" interrupt
577+
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
574578
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
575579
mHardwareTxFIFOFull = true ;
576580
}
@@ -650,59 +654,69 @@ void ACAN2517FD::appendInControllerTxFIFO (const CANFDMessage & inMessage) {
650654
//----------------------------------------------------------------------------------------------------------------------
651655

652656
bool ACAN2517FD::sendViaTXQ (const CANFDMessage & inMessage) {
653-
//--- Enter message only if TXQ FIFO is not full (see DS20005688B, page 50)
654-
const bool TXQNotFull = mUsesTXQ && (readRegister8Assume_SPI_transaction (TXQSTA_REGISTER) & 1) != 0 ;
655-
if (TXQNotFull) {
656-
const uint16_t ramAddress = (uint16_t) (0x400 + readRegister32Assume_SPI_transaction (TXQUA_REGISTER)) ;
657-
//--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27)
658-
uint32_t idf = inMessage.id ;
659-
if (inMessage.ext) {
660-
idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ;
661-
}
662-
//--- Write DLC field, FDF, BRS, RTR, IDE bits
663-
uint32_t flags = lengthCodeForLength (inMessage.len) ;
664-
if (inMessage.ext) {
665-
flags |= 1 << 4 ; // Set EXT bit
657+
bool ok = mUsesTXQ ;
658+
if (ok) {
659+
uint8_t sta = readRegister8Assume_SPI_transaction (TXQSTA_REGISTER) ;
660+
//--- Check Transmit Attempts Exhausted Interrupt Pending bit
661+
ok = (sta & (1 << 4)) != 0 ;
662+
if (ok) {
663+
writeRegister8Assume_SPI_transaction (TXQSTA_REGISTER, ~ (1 << 4)) ;
664+
}else{
665+
//--- Enter message only if TXQ FIFO is not full (see DS20005688B, page 50)
666+
ok = (sta & 1) != 0 ;
666667
}
667-
switch (inMessage.type) {
668-
case CANFDMessage::CAN_REMOTE :
669-
flags |= 1 << 5 ; // Set RTR bit
670-
break ;
671-
case CANFDMessage::CAN_DATA :
672-
break ;
673-
case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH :
674-
flags |= 1 << 7 ; // Set FDF bit
675-
break ;
676-
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
677-
flags |= 1 << 7 ; // Set FDF bit
678-
if (mHasDataBitRate) {
679-
flags |= 1 << 6 ; // Set BRS bit
668+
if (ok) {
669+
const uint16_t ramAddress = (uint16_t) (0x400 + readRegister32Assume_SPI_transaction (TXQUA_REGISTER)) ;
670+
//--- Write identifier: if an extended frame is sent, identifier bits sould be reordered (see DS20005678B, page 27)
671+
uint32_t idf = inMessage.id ;
672+
if (inMessage.ext) {
673+
idf = ((inMessage.id >> 18) & 0x7FF) | ((inMessage.id & 0x3FFFF) << 11) ;
680674
}
681-
break ;
682-
}
683-
//--- Word count
684-
const uint32_t wordCount = (inMessage.len + 3) / 4 ;
685-
//--- Transfer frame to the MCP2517FD
686-
uint8_t buff[74] = {0} ;
687-
//--- Enter command
688-
const uint16_t writeCommand = (ramAddress & 0x0FFF) | (0b0010 << 12) ;
689-
buff[0] = writeCommand >> 8 ;
690-
buff[1] = writeCommand & 0xFF ;
691-
//--- Enter values
692-
enterU32InBufferAtIndex (idf, buff, 2) ;
693-
enterU32InBufferAtIndex (flags, buff, 6) ;
694-
for (uint32_t i=0 ; i < wordCount ; i++) {
695-
enterU32InBufferAtIndex (inMessage.data32 [i], buff, 10 + 4 * i) ;
675+
//--- Write DLC field, FDF, BRS, RTR, IDE bits
676+
uint32_t flags = lengthCodeForLength (inMessage.len) ;
677+
if (inMessage.ext) {
678+
flags |= 1 << 4 ; // Set EXT bit
679+
}
680+
switch (inMessage.type) {
681+
case CANFDMessage::CAN_REMOTE :
682+
flags |= 1 << 5 ; // Set RTR bit
683+
break ;
684+
case CANFDMessage::CAN_DATA :
685+
break ;
686+
case CANFDMessage::CANFD_NO_BIT_RATE_SWITCH :
687+
flags |= 1 << 7 ; // Set FDF bit
688+
break ;
689+
case CANFDMessage::CANFD_WITH_BIT_RATE_SWITCH :
690+
flags |= 1 << 7 ; // Set FDF bit
691+
if (mHasDataBitRate) {
692+
flags |= 1 << 6 ; // Set BRS bit
693+
}
694+
break ;
695+
}
696+
//--- Word count
697+
const uint32_t wordCount = (inMessage.len + 3) / 4 ;
698+
//--- Transfer frame to the MCP2517FD
699+
uint8_t buff[74] = {0} ;
700+
//--- Enter command
701+
const uint16_t writeCommand = (ramAddress & 0x0FFF) | (0b0010 << 12) ;
702+
buff[0] = writeCommand >> 8 ;
703+
buff[1] = writeCommand & 0xFF ;
704+
//--- Enter values
705+
enterU32InBufferAtIndex (idf, buff, 2) ;
706+
enterU32InBufferAtIndex (flags, buff, 6) ;
707+
for (uint32_t i=0 ; i < wordCount ; i++) {
708+
enterU32InBufferAtIndex (inMessage.data32 [i], buff, 10 + 4 * i) ;
709+
}
710+
//--- SPI transfer
711+
assertCS () ;
712+
mSPI.transfer (buff, 10 + 4 * wordCount) ;
713+
deassertCS () ;
714+
//--- Increment FIFO, send message (see DS20005688B, page 48)
715+
const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit
716+
writeRegister8Assume_SPI_transaction (TXQCON_REGISTER + 1, data8);
696717
}
697-
//--- SPI transfer
698-
assertCS () ;
699-
mSPI.transfer (buff, 10 + 4 * wordCount) ;
700-
deassertCS () ;
701-
//--- Increment FIFO, send message (see DS20005688B, page 48)
702-
const uint8_t data8 = (1 << 0) | (1 << 1) ; // Set UINC bit, TXREQ bit
703-
writeRegister8Assume_SPI_transaction (TXQCON_REGISTER + 1, data8);
704718
}
705-
return TXQNotFull ;
719+
return ok ;
706720
}
707721

708722
//----------------------------------------------------------------------------------------------------------------------
@@ -825,7 +839,12 @@ bool ACAN2517FD::isr_core (void) {
825839
receiveInterrupt () ;
826840
handled = true ;
827841
}
828-
if ((it & (1 << 0)) != 0) { // Transmit FIFO interrupt
842+
if ((it & (1 << 10)) != 0) { // Transmit Attempt interrupt
843+
//--- Clear Pending Transmit Attempt interrupt bit
844+
writeRegister8Assume_SPI_transaction (FIFOSTA_REGISTER (TRANSMIT_FIFO_INDEX), ~ (1 << 4)) ;
845+
transmitInterrupt () ;
846+
handled = true ;
847+
}else if ((it & (1 << 0)) != 0) { // Transmit FIFO interrupt
829848
transmitInterrupt () ;
830849
handled = true ;
831850
}
@@ -863,7 +882,8 @@ void ACAN2517FD::transmitInterrupt (void) { // Generated if hardware transmit FI
863882
if (hasMessage) {
864883
appendInControllerTxFIFO (message) ;
865884
}else{ // No message in transmit FIFO: disable "FIFO not full" interrupt
866-
const uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
885+
uint8_t data8 = 1 << 7 ; // FIFO is a transmit FIFO
886+
data8 |= 1 << 4 ; // TXATIE ---> 1: Enable Transmit Attempts Exhausted Interrupt
867887
writeRegister8Assume_SPI_transaction (FIFOCON_REGISTER (TRANSMIT_FIFO_INDEX), data8) ;
868888
mHardwareTxFIFOFull = false ;
869889
}

src/ACAN2517FDSettings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class ACAN2517FDSettings {
6161
} PayloadSize ;
6262

6363
//······················································································································
64-
// Deprecated enumeration (now use DataBitRateFactor declared in ACANFD_DataBitRateFactor.h
64+
// Deprecated enumeration (now use DataBitRateFactor declared in ACANFD_DataBitRateFactor.h)
6565
//······················································································································
6666

6767
public : typedef enum : uint8_t {

0 commit comments

Comments
 (0)