How to recieve a CAN message using RX Interrupt (KEA128)?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

How to recieve a CAN message using RX Interrupt (KEA128)?

1,604 Views
emilioaronmoyer
Contributor III

Hello,

I'm using a kEA 128,I want to receive the CAN message by interruption (Receiver Full Interrupt). I'm using an example code that I download from https://community.nxp.com/thread/381639#comments  (Can_test), I have set the MSCAN_SetRxCallBack() funtion to a funtion I create in main but nothing happened.

what do I need to configure? Or do I need to clear the Receive Buffer Full?

Note: I can't write MSCAN_CANRFLG |= 0x1u; to clear the rxf flag

Regards,

Emilio

Labels (1)
0 Kudos
6 Replies

1,226 Views
egoodii
Senior Contributor III

From your opening title, can we assume that you have confirmed that your setup is receiving messages perfectly, but only that the interrupt environment isn't working for you?  That is, either the RxFIFO or RX MB(s) fill up with valid messages and you simply fail to process?

0 Kudos

1,226 Views
emilioaronmoyer
Contributor III

Hello Earl,

yes, I receive messages without using an interrupt. But I do'nt know how to clear the RX flag when a message arrive because I can't write MSCAN_CANRFLG |= 0x1u to clear it. I don't if it is the only thing I need to change or there are more.

Can you help me?

Regards,

Emilio

0 Kudos

1,226 Views
egoodii
Senior Contributor III

KE is built with the 'older, simpler' MsCAN peripheral, which I am familiar with only as from the Star08 parts.  You should be able to 'clear' (by set) that flag once you have read the top entry. My RxISR there was this, to copy from the hardware FIFO to a software FIFO (and unscramble the ID bits on an 8bit CPU without the single-cycle barrel-shifter):

typedef union{                 //Byte/DWord duality, big-endian

  struct{

uint8_t hi;
uint8_t mhi;
uint8_t mlo;
uint8_t lo;

  } u8;

  struct {

uint16_t hi;
uint16_t lo;

  }u16;

  uint32_t u32;

}u32u8_t;

typedef struct

{

  u32u8_t id;

  uint8_t buf[8];

  uint8_t buf_len;

} can_t;

void can_rx_isr ( void ) {

  u32u8_t tmp;

  can_t volatile *ptr;

  /* If the buffer is full, don't read message */

  if( can_buf_rx_cnt < CAN_BUF_RX_SIZE ) {

    /* Mark we have one more in the buffer */

    can_buf_rx_cnt++;

    /* Get pointer to the next open index */

    ptr = &can_buf_rx[ can_buf_rx_head ];

    /* Move on to next index in buffer */

    if( ++can_buf_rx_head >= CAN_BUF_RX_SIZE )

      can_buf_rx_head = 0;

    /* Is it extended frame? */

    /* Is it extended frame? */

    if( CANRIDR1_IDE ) {

      /* Re-Pack extended frame id.

         The 31st bit signifies it's extended */

         //First build it shifted << 1

      tmp.u8.hi = (CANRIDR0 >> 2);

      tmp.u8.mhi = ((CANRIDR0 & 0x03)<<6)              //Squeeze out the IDE and SRR bits

             | ((CANRIDR1 & CANRIDR1_ID_18_MASK) >> 2)   // by shifting IDR0 and IDR1 bits 2

             | (CANRIDR1 & CANRIDR1_ID_15_MASK);

      tmp.u8.mlo = CANRIDR2;

      tmp.u8.lo = CANRIDR3;

      tmp.u32 >>= 1;                 //Finally, lop-off RTR from the LSB

      tmp.u8.hi |= 0x80;

      ptr->id.u8.lo = tmp.u8.lo;

      ptr->id.u8.mlo = tmp.u8.mlo;

      ptr->id.u8.mhi = tmp.u8.mhi;

      ptr->id.u8.hi = tmp.u8.hi;

    } else {

      /* Get standard frame id */

      ptr->id.u32 = ((u32_t)CANRIDR0 << (8-CANRIDR1_ID_18_BITNUM))

                | (CANRIDR1 >> CANRIDR1_ID_18_BITNUM);

    }

    /* Load data */

    ptr->buf[0] = CANRDSR0;

    ptr->buf[1] = CANRDSR1;

    ptr->buf[2] = CANRDSR2;

    ptr->buf[3] = CANRDSR3;

    ptr->buf[4] = CANRDSR4;

    ptr->buf[5] = CANRDSR5;

    ptr->buf[6] = CANRDSR6;

    ptr->buf[7] = CANRDSR7;

    /* Get data length code (DLC) */

    ptr->buf_len = CANRDLR & CANRDLR_DLC_MASK;

  }

  /* Clear rx interrupt */

  CANRFLG = CANRFLG_RXF_MASK;

  return;

}

One other thing!!! DO NOT |= this MSCAN_CANRFLG register!!!! You will 'clear' ANY other 'active' indication therein all at the same time (in this case, I suppose, just the 'overrun' flag):

Write: Anytime when not in initialization mode, except

RSTAT[1:0] and TSTAT[1:0] flags which are read-only; write

of 1 clears flag; write of 0 is ignored.

0 Kudos

1,226 Views
emilioaronmoyer
Contributor III

Hello Earl,

Thanks, I know I need to clear the flag by setting it but I don't know which  command to used. Neither the CANRFLG = CANRFLG_RXF_MASK; nor the MSCAN_CANRFLG |= 0x1u, the programa doesn't recognize them and mark as an error (Undeclared).

Do you know to do it?

Regards,

Emilio

0 Kudos

1,226 Views
egoodii
Senior Contributor III

Your header file SKEAZ1284.h defines this:

MSCAN_CANRFLG_RXF_MASK              0x1u

Now your other file mscan.h defines this macro:

__STATIC_INLINE void CAN_ClearRXF_Flag(MSCAN_Type *pCANx)

{

    pCANx->CANRFLG |= MSCAN_CANRFLG_RXF_MASK;

}

but again that does the 'inappropriate' |=. So you can either 'fix' that macro and instantiate it, as:

CAN_ClearRXF_Flag(MSCAN);

OR put in your own

MSCAN.CANRFLG = MSCAN_CANRFLG_RXF_MASK;

Of course that mscan.c code also has the whole routine CAN_ReadOneFrameFromBuff that 'pulls' a frame and clears that flag at the end, not unlike my code above, although it lets the compiler shift&pack an EID to a single 29 bit quantity (and uses the above macro you would want to fix).

1,226 Views
emilioaronmoyer
Contributor III

I forgot to attached the code.

0 Kudos