This is a follow up question on RX FIFO example in the SDK. While we got that operational now on our hardware talking to the EVKB, there does not appear to be anything in the SDK FLSCAN drivers for CANFD ENHANCED FIFO which allows you to use FIFO with CAN FD messages. In trying to stick with the SDK drivers and reading the RM I have gotten this far but stuck on how to modify the interrupt driver to support CANFD FIFO. Surprised you all didn't put the support for the FD ENHANCED FIFO - its a big part of the chapter along with legacy RX FIFO.
As I said this is what I have so far.
/*! @brief CAN FDmessage frame structure. */
typedef struct _flexcan_fd_fifo_frame
{
struct
{
uint32_t timestamp : 16; /*!< FlexCAN internal Free-Running Counter Time Stamp. */
uint32_t length : 4; /*!< CAN frame payload length in bytes(Range: 0~8). */
uint32_t type : 1; /*!< CAN Frame Type(DATA or REMOTE). */
uint32_t format : 1; /*!< CAN Frame Identifier(STD or EXT format). */
uint32_t : 1;
uint32_t code : 4; /*!< Message Buffer Code. */
uint32_t srr : 1; /*!< Substitute Remote request. */
uint32_t : 6;
uint32_t esi : 1; /*!< Error State Indicator. */
uint32_t brs : 1; /*!< Bit Rate Switch. */
uint32_t edl : 1; /*!< Extended Data Length. */
};
struct
{
uint32_t ext_id : 18; /*!< CAN Frame Identifier, should be set using FLEXCAN_ID_EXT() or FLEXCAN_ID_STD() macro. */
uint32_t std_id : 11
uint32_t : 3; /*!< Reserved. */
};
union
{
struct
{
uint32_t dataWord[16]; /*!< CAN FD Frame payload, 16 double word maximum. */
};
/* Note: the maximum databyte* below is actually 64, user can add them if needed,
or just use dataWord[*] instead. */
struct
{
uint8_t dataByte3; /*!< CAN Frame payload byte3. */
uint8_t dataByte2; /*!< CAN Frame payload byte2. */
uint8_t dataByte1; /*!< CAN Frame payload byte1. */
uint8_t dataByte0; /*!< CAN Frame payload byte0. */
uint8_t dataByte7; /*!< CAN Frame payload byte7. */
uint8_t dataByte6; /*!< CAN Frame payload byte6. */
uint8_t dataByte5; /*!< CAN Frame payload byte5. */
uint8_t dataByte4; /*!< CAN Frame payload byte4. */
};
};
} flexcan_fd_fifo_frame_t;
/*! @brief CAN FDmessage frame structure. */
typedef struct _flexcan_fd_fifo_filter_b01
{
struct
{
uint32_t std_id_flt1 : 11;
uint32_t RTRmsk : 1;
uint32_t : 4;
uint32_t std_id_flt2 : 11;
uint32_t RTRfilt : 1;
uint32_t code : 4;
uint32_t : 2;
uint32_t fsch : 2;
};
} flexcan_fd_fifo_filter_b01_t
/*!
* brief Configures the FlexCAN Enhanced Rx FIFO.
*
* This function configures the Rx FIFO with given Rx FIFO configuration.
*
* param base FlexCAN peripheral base address.
* param config Pointer to the FlexCAN Rx FIFO configuration structure.
* param enable Enable/disable Rx FIFO.
* - true: Enable Rx FIFO.
* - false: Disable Rx FIFO.
*/
void FLEXCAN_SetRxEnhancedFifoConfig(bool enable)
{
//only valid for Flexcan3..........
/* Assertion. */
//assert((config) || (false == enable));
/* Enter Freeze Mode. */
FLEXCAN_EnterFreezeMode(base);
if (enable)
{
FLEXCAN3_ERFCR = CAN_ERFCR_ERFEN(1); //Enable enhanced FIFO
FLEXCAN3_ERFSR = CAN_ERFSR_ERFCLR(1); //Reset RxFIFO engine
//Clear EFRSR bits
FLEXCAN3_ERRSR = CAN_ERFSR_ERFUFW(0) | CAN_ERFSR_ERFOVF(0) | CAN_ERFSR_ERFWMI(0) | CAN_ERFSR_ERFDA(0);
FLEXCAN3_ERFCR |= CAN_ERFCR_NFE(2); //Configure total number of Rx FIFO filter elements
FLEXCAN3_ERFCR |= CAN_ERFCR_NEXIF(3); // number of extended ID & standard ID filter elements
FLEXCAN3_ERFCR |= CAN_ERFSR_ERFWMI(1); // number of messages in FIFO greater than the watermark
FLEXCAN3_ERFIER = 0x01; // Enable interrupts if they are to be used
// TBD // Enable DMA operation in MCR[DMA]
//FLEXCAN3_ERFCR |= CAN_ERFCR_DMALW(1); // to configure number of words to be transfered for each data element
//Configure filter elements by writing to the ERFFELn registers?
//FLEXCAN3_ERFFEL0...127
flexcan_fd_fifo_filter_b01_t b01;
b01.fsch = 0b01;
b01.RTRfilt = 0;
b01.std_id_flt1 = 0x000;
b01.RTRmsk = 0;
b01.std_id_flt1 = 0x650;
FLEXCAN3_ERFFEL0 = CAN_ERFFEL_FEL(&b01);
FLEXCAN3_ERFFEL1 = CAN_ERFFEL_FEL(&b01);
}
/* Exit Freeze Mode. */
FLEXCAN_ExitFreezeMode(base);
}
//enable interrupts
void FLEXCAN_EnableEnhancedFIFOInterrupts()
{
/*
erfier register
bit 31 - erfufwie, underflow interrupt enable
bit 30 - erfovfie, overflow interrupt enable
bit 29 - erfwmie, watermark indication interrupt enable
bit 28 - erfdaie, fifo data available interrupt enable
*/
FLEXCAN3_ERFIER |= CAN_ERFIER_ERFDAIE(1) | CAN_ERFIER_ERFWMIE(1) | CAN_ERFIER_ERFOVFIE(1) | CAN_ERFIER_ERFUFWIE(1);
}
But now do not know how to handle:
/*!
* brief FlexCAN IRQ handle function.
*
* This function handles the FlexCAN Error, the Message Buffer, and the Rx FIFO IRQ request.
*
* param base FlexCAN peripheral base address.
* param handle FlexCAN handle pointer.
*/
void FLEXCAN_TransferHandleIRQ(CAN_Type *base, flexcan_handle_t *handle)
{
/* Assertion. */
assert(handle);
status_t status = kStatus_FLEXCAN_UnHandled;
uint32_t result;
/* Store Current FlexCAN Module Error and Status. */
result = base->ESR1;
do
{
/* Solve FlexCAN Error and Status Interrupt. */
if (result &
(kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag))
{
status = kStatus_FLEXCAN_ErrorStatus;
/* Clear FlexCAN Error and Status Interrupt. */
FLEXCAN_ClearStatusFlags(base, kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag |
kFLEXCAN_BusOffIntFlag | kFLEXCAN_ErrorIntFlag);
}
else if (result & kFLEXCAN_WakeUpIntFlag)
{
status = kStatus_FLEXCAN_WakeUp;
FLEXCAN_ClearStatusFlags(base, kFLEXCAN_WakeUpIntFlag);
}
/* Solve FlexCAN Rx FIFO & Message Buffer Interrupt. */
else
{
/* For this implementation, we solve the Message with lowest MB index first. */
for (result = 0; result < FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base); result++)
{
/* Get the lowest unhandled Message Buffer */
#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
if ((FLEXCAN_GetMbStatusFlags(base, (uint64_t)1 << result)) && (FLEXCAN_IsMbIntEnabled(base, result)))
#else
if ((FLEXCAN_GetMbStatusFlags(base, 1 << result)) && (FLEXCAN_IsMbIntEnabled(base, result)))
#endif
{
break;
}
}
/* Does not find Message to deal with. */
if (result == FSL_FEATURE_FLEXCAN_HAS_MESSAGE_BUFFER_MAX_NUMBERn(base))
{
break;
}
/* Solve Rx FIFO interrupt. */
if ((kFLEXCAN_StateIdle != handle->rxFifoState) && ((1 << result) <= kFLEXCAN_RxFifoOverflowFlag))
{
switch (1 << result)
{
case kFLEXCAN_RxFifoOverflowFlag:
status = kStatus_FLEXCAN_RxFifoOverflow;
break;
case kFLEXCAN_RxFifoWarningFlag:
status = kStatus_FLEXCAN_RxFifoWarning;
break;
case kFLEXCAN_RxFifoFrameAvlFlag:
status = FLEXCAN_ReadRxFifo(base, handle->rxFifoFrameBuf);
if (kStatus_Success == status)
{
status = kStatus_FLEXCAN_RxFifoIdle;
}
FLEXCAN_TransferAbortReceiveFifo(base, handle);
break;
default:
status = kStatus_FLEXCAN_UnHandled;
break;
}
}
else
{
/* Get current State of Message Buffer. */
switch (handle->mbState[result])
{
/* Solve Rx Data Frame. */
case kFLEXCAN_StateRxData:
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
if (base->MCR & CAN_MCR_FDEN_MASK)
{
status = FLEXCAN_ReadFDRxMb(base, result, handle->mbFDFrameBuf[result]);
}
else
{
status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]);
}
#else
status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]);
#endif
if (kStatus_Success == status)
{
status = kStatus_FLEXCAN_RxIdle;
}
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
if (base->MCR & CAN_MCR_FDEN_MASK)
{
FLEXCAN_TransferFDAbortReceive(base, handle, result);
}
else
{
FLEXCAN_TransferAbortReceive(base, handle, result);
}
#else
FLEXCAN_TransferAbortReceive(base, handle, result);
#endif
break;
/* Solve Rx Remote Frame. */
case kFLEXCAN_StateRxRemote:
status = FLEXCAN_ReadRxMb(base, result, handle->mbFrameBuf[result]);
if (kStatus_Success == status)
{
status = kStatus_FLEXCAN_RxIdle;
}
FLEXCAN_TransferAbortReceive(base, handle, result);
break;
/* Solve Tx Data Frame. */
case kFLEXCAN_StateTxData:
status = kStatus_FLEXCAN_TxIdle;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
if (base->MCR & CAN_MCR_FDEN_MASK)
{
FLEXCAN_TransferFDAbortSend(base, handle, result);
}
else
{
FLEXCAN_TransferAbortSend(base, handle, result);
}
#else
FLEXCAN_TransferAbortSend(base, handle, result);
#endif
break;
/* Solve Tx Remote Frame. */
case kFLEXCAN_StateTxRemote:
handle->mbState[result] = kFLEXCAN_StateRxRemote;
status = kStatus_FLEXCAN_TxSwitchToRx;
#if (defined(FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE) && FSL_FEATURE_FLEXCAN_HAS_FLEXIBLE_DATA_RATE)
if (base->MCR & CAN_MCR_FDEN_MASK)
{
FLEXCAN_TransferFDAbortReceive(base, handle, result);
}
else
{
FLEXCAN_TransferAbortReceive(base, handle, result);
}
#else
FLEXCAN_TransferAbortReceive(base, handle, result);
#endif
break;
default:
status = kStatus_FLEXCAN_UnHandled;
break;
}
}
/* Clear resolved Message Buffer IRQ. */
#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
FLEXCAN_ClearMbStatusFlags(base, (uint64_t)1 << result);
#else
FLEXCAN_ClearMbStatusFlags(base, 1 << result);
#endif
}
/* Calling Callback Function if has one. */
if (handle->callback != NULL)
{
handle->callback(base, handle, status, result, handle->userData);
}
/* Reset return status */
status = kStatus_FLEXCAN_UnHandled;
/* Store Current FlexCAN Module Error and Status. */
result = base->ESR1;
}
#if (defined(FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER)) && (FSL_FEATURE_FLEXCAN_HAS_EXTENDED_FLAG_REGISTER > 0)
while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFFFFFFFFFU)) ||
(0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag |
kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag))));
#else
while ((0 != FLEXCAN_GetMbStatusFlags(base, 0xFFFFFFFFU)) ||
(0 != (result & (kFLEXCAN_TxWarningIntFlag | kFLEXCAN_RxWarningIntFlag | kFLEXCAN_BusOffIntFlag |
kFLEXCAN_ErrorIntFlag | kFLEXCAN_WakeUpIntFlag))));
#endif
}