Hello,
I want to add CAN-FD support to an existing project, the application is a simple Echo, when it receive a CAN message on a Node it will echo it back. the Standard CAN works fine, i modified the init function to support CAN-FD based on project shared by PeterS and updated the register CBT and FDCBT based on this excel sheet.
this is the init function
AbstractCANTransceiver::ErrorCode FlexCANDevice::init()
{
Io::setDefaultConfiguration(fConfig.txPort);
Io::setDefaultConfiguration(fConfig.rxPort);
fPhy.init(fConfig.BusId);
/* CAN FD init config */
if(fConfig.fd_enable)
{
/* enable the FlexCAN module, reset and freeze */
fpDevice->MCR.R = (0
| CAN_MCR_FRZ /* enabled to enter Freeze mode */
| CAN_MCR_HALT /* enter freeze mode if FRZ bit is set */
| CAN_MCR_BCC /* individual Rx masking and queue */
| 0x0000003F);
/* double check that we are actually in freeze mode */
while(0 == fpDevice->MCR.B.FRZACK) {};
while(0 == fpDevice->MCR.B.NOTRDY) {};
fpDevice->MCR.R = (0
| CAN_MCR_FRZ /* enabled to enter Freeze mode */
| CAN_MCR_HALT /* enter freeze mode if FRZ bit is set */
| CAN_MCR_BCC /* individual Rx masking and queue */
| CAN_MCR_AEN /* Safe Tx abort enable */
| CAN_MCR_FDEN /* CAN FD enabled */
| 0x0000003F); /* enable 64 MBs */
// Set CAN Bit Timing Register (CAN_CBT. P-1747)
fpDevice->CBT.B.BTF = 1; // Enable extended bit time definitions
fpDevice->CBT.B.EPRESDIV = fConfig.bitrate_cbt.presDiv;
fpDevice->CBT.B.ERJW = fConfig.bitrate_cbt.rjw;
fpDevice->CBT.B.EPROPSEG = fConfig.bitrate_cbt.propSeg;
fpDevice->CBT.B.EPSEG1 = fConfig.bitrate_cbt.pSeg1;
fpDevice->CBT.B.EPSEG2 = fConfig.bitrate_cbt.pSeg2;
// Set CAN FD Bit Timing register (CAN_FDCBT. P-1768)
fpDevice->FDCBT.B.FPRESDIV = fConfig.bitrate.presDiv;
fpDevice->FDCBT.B.FRJW = fConfig.bitrate.rjw;
fpDevice->FDCBT.B.FPROPSEG = fConfig.bitrate.propSeg;
fpDevice->FDCBT.B.FPSEG1 = fConfig.bitrate.pSeg1;
fpDevice->FDCBT.B.FPSEG2 = fConfig.bitrate.pSeg2;
// Set CAN FD Control register (CAN_FDCTRL .P-1766)
fpDevice->FDCTRL.R = 0;
fpDevice->FDCTRL.B.FDRATE = 1; // bit rate switching enable
fpDevice->FDCTRL.B.MBDSR0 = fConfig.payload;
}
/* Standard CAN init config */
else
{
fpDevice->MCR.B.MDIS = 0; // Enable module
fpDevice->MCR.R |= MCR_SOFT_RESET_MASK; // Soft reset
if (isEqualAfterTimeout<vuint32_t>(
&fpDevice->MCR.R,
MCR_SOFT_RESET_MASK,
MCR_SOFT_RESET_MASK,
INIT_DELAY_TIMEOUT_US))
{
return AbstractCANTransceiver::CAN_ERR_INIT_FAILED;
}
fpDevice->MCR.B.FRZ = 1; // Enter freeze mode
fpDevice->MCR.B.HALT = 1;
if (isEqualAfterTimeout<vuint32_t>(
&fpDevice->MCR.R,
MCR_FREEZE_ACK_MASK,
0UL, INIT_DELAY_TIMEOUT_US))
{
return AbstractCANTransceiver::CAN_ERR_INIT_FAILED;
}
// Setup MCR
fpDevice->MCR.B.SRXDIS = 1; // Disable self reception
fpDevice->MCR.B.MAXMB = 0x3f; // Use all 64 message buffers
fpDevice->MCR.B.IRMQ = 1; //have to be switch On
fpDevice->CTRL1.R |= CTRL_TIMING_HIGHSPEED; // 500KB
fpDevice->CTRL2.B.MRP = 1;
}
// Setup message buffers (Both for Standard CAN and CAN-FD instances)
fRxInterruptMask = 0;
uint32_t mask = 1;
for (uint8_t i = 0; i < fConfig.numRxBufsStd; ++i)
{
setupMessageBuffer(i, CANRxBuffer::CODE_EMPTY, false);
fRxInterruptMask |= mask;
mask <<= 1;
}
mask = (1 << fConfig.numRxBufsStd);
for (uint8_t i = fConfig.numRxBufsStd;
i < fConfig.numRxBufsStd + fConfig.numRxBufsExt; ++i)
{
setupMessageBuffer(i, CANRxBuffer::CODE_EMPTY, true);
fRxInterruptMask |= mask;
mask <<= 1;
}
for (uint8_t i = FIRST_TRANSMIT_BUFFER;
i < FIRST_TRANSMIT_BUFFER + fConfig.numTxBufsApp; ++i)
{
setupMessageBuffer(i, CANTxBuffer::CODE_INACTIVE, false);
}
setupMessageBuffer(CALLBACK_TRANSMIT_BUFFER, CANTxBuffer::CODE_INACTIVE, false);
// Clear and disable interrupts
fpDevice->RXMGMASK.R = 0;
fpDevice->RX14MASK.R = 0;
fpDevice->RX15MASK.R = 0;
fpDevice->IMASK1.R = 0;
fpDevice->IMASK2.R = 0;
fpDevice->IFLAG1.R = 0xffffffff;
fpDevice->IFLAG2.R = 0xffffffff;
fpDevice->ESR1.R = 0xffffffff;
fFirstRxId = 0;
fFramesReceived = 0;
return AbstractCANTransceiver::CAN_ERR_OK;
}
void setupMessageBuffer(uint8_t bufIdx, uint8_t code, bool extended)
{
fpDevice->MB[bufIdx].CS.R = 0;
fpDevice->MB[bufIdx].CS.B.IDE = extended ? 1 : 0;
fpDevice->MB[bufIdx].CS.B.CODE = code;
fpDevice->MB[bufIdx].ID.R = 0;
fpDevice->MB[bufIdx].DATA.W[0] = 0;
fpDevice->MB[bufIdx].DATA.W[1] = 0;
fpDevice->RXIMR[bufIdx].R = 0;
}
namespace CANRxBuffer
{
enum Code
{
CODE_INACTIVE = 0,
CODE_FULL = 2,
CODE_EMPTY = 4,
CODE_OVERRUN = 5
};
static const uint32_t FLAG_BUSY = (1UL << 24);
}
The receive interrupt handler
uint8_t FlexCANDevice::receiveISR(const uint8_t* filterMap)
{
if(fConfig.fd_enable)
{
TransmitMsgFD(0,0x155,8);
}
else
{
TransmitMsgSTD(0,0x155,8);
}
}
and the CAN node configuration
const ::bios::FlexCANDevice::Config Can1Config =
{
(0xFBEC0000UL),
::can::AbstractCANTransceiver::BAUDRATE_HIGHSPEED,
::bios::Io::canGS1Tx,
::bios::Io::canGS1Rx,
NUM_RX_STD_MAILBOXES,
NUM_RX_EXT_MAILBOXES,
NUM_TX_MAILBOXES,
::cgw3::busid::BusId::KCAN(), //busid
::bios::EdgeWakeUp::KWUP_5, //wakeUp
true, // CAN-FD enabled
::can::AbstractCANTransceiver::FLEXCAN_PAYLOAD_SIZE_8,
// for exact configuration refer to xls file ..\tools\CAN Bit Timing calculation v2.1
// Arbitration phase, CANx_CBT = 0x80242AC4; bitrate=500kbps, CPI clk=40 MHz; Prescaler= 2, PROPSEG=11, PSEG1=23, PSEG2=5, RJW=5, smp=87,5%
{
1, /*!< Prescaler Division Factor*/
4, /*!< Resync Jump Width*/
10, /*!< Propagation Segment*/
22, /*!< Phase Segment 1*/
4 /*!< Phase Segment 2*/
},
// Data Phase, CANx_FDCBT = 0x00111421; // bitrateFD=2000kbps, CPI clk=40 MHz; fPrescaler= 2, fPROPSEG=5, fPSEG1=2, fPSEG2=2, fRJW=2, smp=80%
{
1, /*!< Prescaler Division Factor*/
1, /*!< Resync Jump Width*/
5, /*!< Propagation Segment*/
1, /*!< Phase Segment 1*/
1 /*!< Phase Segment 2*/
},
};
when i switch to CAN-FD the receive interrupt never happen. probably something wrong with the init or buffer config ?
Thanks a lot.