Simone Bonetti

kinetis k10 flexcan FIFO usage

Discussion created by Simone Bonetti on Jul 28, 2016
Latest reply on Sep 16, 2016 by Okan ERCAN

hello, i'm using KSDK 1.3 on MK10DX256VLQ10 microcontroller.

i'd like to have some clarifications on the usage of flexcan RX fifo.


here's my setup code:


 /*number of can 2 rx fifo filters id*/ #define CAN_2_RX_FIFO_ID_FILTER_NUM     kFlexCanRxFifoIDFilters_8    /*number of elements of can 2 rx fifo filters id array*/ #define CAN_2_RX_FIFO_ID_FILTER_ARRAY_SIZE  (CAN_2_RX_FIFO_ID_FILTER_NUM + 1) * 8   static flexcan_user_config_t can_2_config = {   16,   CAN_2_RX_FIFO_ID_FILTER_NUM,   true,   kFlexCanNormalMode };   static flexcan_state_t can_2_state; static flexcan_msgbuff_t can_2_fifo; static flexcan_id_table_t can_2_fifo_id_table; static uint32_t can_2_rx_fifo_id[CAN_2_RX_FIFO_ID_FILTER_ARRAY_SIZE];   static uint32_t can_2_rx_msg_ids[] = /*MUST be smaller than can_2_rx_fifo_id array*/ {     CAN_2_MSG_ID_1,     CAN_2_MSG_ID_2,     CAN_2_MSG_ID_3,     CAN_2_MSG_ID_4,     CAN_2_MSG_ID_5,     CAN_2_MSG_ID_6 };   void CAN_Init() {     configure_flexcan_pins(CAN_2_INSTANCE);      FLEXCAN_DRV_Init(CAN_2_INSTANCE, &can_2_state, &can_2_config);      FLEXCAN_DRV_SetBitrate(CAN_2_INSTANCE, &can_bit_rate_500kbs_50Mhz); /* 500kbs */      FLEXCAN_DRV_SetRxMaskType(CAN_2_INSTANCE, kFlexCanRxMaskGlobal);      FLEXCAN_DRV_SetRxFifoGlobalMask(CAN_2_INSTANCE, kFlexCanMsgIdStd, 0x7FF);      /*initialize can 2 fifo*/     can_2_fifo_id_table.isExtendedFrame = false;     can_2_fifo_id_table.isRemoteFrame = false;     for(int i = 0; i< NUM_ELEMS(can_2_rx_msg_ids) ;i++)     {         can_2_rx_fifo_id[i] = can_2_rx_msg_ids[i];     }      can_2_fifo_id_table.idFilter = can_2_rx_fifo_id;     FLEXCAN_DRV_ConfigRxFifo(CAN_2_INSTANCE, kFlexCanRxFifoIdElementFormatA, &can_2_fifo_id_table); }   void CAN_Receive() {     if(FLEXCAN_DRV_GetReceiveStatus(CAN_2_INSTANCE) == kStatus_FLEXCAN_Success)     {         FLEXCAN_DRV_RxFifo(CAN_2_INSTANCE, &can_2_fifo);    /* process message here...*/     } }   void CAN_Task() {    CAN_Init();     /*trigger MSG reception*/     FLEXCAN_DRV_RxFifo(CAN_2_INSTANCE, &can_2_fifo);     for (;;)     {         CAN_Receive();     } }   /* Implementation of CAN0 handler named in startup code. */ void CAN1_ORed_Message_buffer_IRQHandler(void) {     FLEXCAN_DRV_IRQHandler(1); }


i'm using freeRTOS and the CAN_Task() has a 10ms periodicity.

here's what i'm trying to achieve:

  1. Setup RX FIFO filters on order to trigger reception only on msg ID's listed inside can_2_rx_msg_ids[] array
  2. When the task gets scheduled, empty the FIFO and process ALL the arrived messages
  3. Setup an interrupt that notifies me when the FIFO is almost full and needs to be emptied (just in case the task is not fast enough to empty the FIFO when it's scheduled

i successfully got the CAN1_ORed_Message_buffer_IRQHandler interrupt to be called and i saw that when the task runs, it passed the check FLEXCAN_DRV_GetReceiveStatus == kStatus_FLEXCAN_Success and FLEXCAN_DRV_RxFifo returns me the msg received which i'm able to process.


here's some questions and doubts:

  1. Is CAN_Init() function correctly implemented considering the above requirements?
  2. How do i empty the FIFO? i saw that  a call to the FLEXCAN_DRV_RxFifo function fills the can_2_fifo with the received message. but what happens if there are two or more messages to be processed? shall i iterate over FLEXCAN_DRV_RxFifo?
  3. Any suggestion on how to know how many messages are stored in the FIFO?
  4. Do you see any potential problem in the approach i used? (it's based on the examples i found inside KSDK)


Thank you so much for your support, feel free to point me to any other discussions in the forum or to useful documentation.