the FIFO of CAN can't receive frames

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

the FIFO of CAN can't receive frames

962 Views
chensiyan618
Contributor I

I'm utilizing the LPCOpen libraries called "ccan_rom.c," "rom_can_15xx.h," and "romapi_15xx.h" to set up a basic CAN interface for the LPC1549.

Firstly,when I initialize the FIFO of CAN, I have finished the configuration the filter. Secondly, I made it work normally. However, good times don't last long, a question happened that when the frames of CAN reached 500,000 , the FIFO of CAN can not receive it and more. Then I attempt to reconfigure the filter, the FIFO continue to receiving the frame of CAN again. 

So, which measure can prevent this phenomenon coming into being ? Can you help me to solve this problem ?

Labels (1)
Tags (1)
0 Kudos
3 Replies

778 Views
Alexis_A
NXP TechSupport
NXP TechSupport

Hi Sean,

 

Could you please more details about this error? Is always after reaching this package amount or is there a condition that stops the receiving packages?

 

Best Regards,

Alexis Andalon

0 Kudos

778 Views
chensiyan618
Contributor I

Here is the old version of the souce code called can.c.

#include <stdio.h>
#include <string.h>
#include "chip.h"
#include "bsp_conf.h"
#include "can.h"


/**
--------------------------------------------
说明:
LPC1549的can驱动程序是集成在ROM里的,不需要操作寄存器。
有32组滤波器和32个FIFO (对应CAN_MSG_OBJ结构里的msgobj)[0~31]
一组滤波器对应一个FIFO[0~31]
必须配置滤波器FIFO才能正确接收!!!
--------------------------------------------
通过配置mode_id和mask可以实现一组ID的过滤
过滤规则:
<received_mode_id> & mask == mode_id & mask
例如: Configure FIFO_1 to receive all 11-bit messages 0x400-0x4FF
msg_obj.msgobj = 1;
msg_obj.mode_id = 0x400;
msg_obj.mask = 0x700;
--------------------------------------------
强制帧类型过滤,即只有一种"帧类型"允许通过,可以通过mode_id和mask确定帧类型
mode_id: C_CAN operation mode
#define CAN_MSGOBJ_STD 0x00000000UL //CAN 2.0a 11-bit ID
#define CAN_MSGOBJ_EXT 0x20000000UL //CAN 2.0b 29-bit ID
#define CAN_MSGOBJ_DAT 0x00000000UL //data frame
#define CAN_MSGOBJ_RTR 0x40000000UL //rtr frame
mask:
bit29为1时, mask[29] & mode_id[29]确定扩展帧还是标准帧
bit30位1时, mask[30] & mode_id[30]确定数据帧还是远程帧
mask的以上两位为0时没有意义!!!
例如:
msg.msgobj = 31;
msg.mode_id = CAN_RTR_FLAG|0x00 ;
msg.mask = CAN_EFF_FLAG|0x00;
结果:
mask[29] & mode_id[29] = 0; //即标准帧
滤波器31允许所有的"标准远程帧"通过
总体来说,mask的bit29和bit30没有什么利用价值,编码时不要考虑过多!!!
只需要利用bit0~bit28即可
--------------------------------------------
--------------------------------------------
波特率计算方法:
//CAN_CLK = systemclock / (DIVVAL +1) = 12MHZ
can_config.clkdiv = 5;
//14:12(TSEG2) 11:8(TSEG1) 7:6(SJW) 5:0(BRP)
can_config.btr = 0x0502; //TSEG2=0, TSEG1=5, SJW=0, BRP=2
//计算
Bit rate = CAN_CLK/((BRP + 1) x (TSEG1+2+TSEG2+1))
= 12MHZ /((2+1) x (5+2+0+1))
= 500KHZ
Sample point = (TSEG1+2) / (TSEG1+2+TSEG2+1) x 100
= 7 / (5+2+0+1) x 100
= 87.5%(建议值)
--------------------------------------------
*/


#define MAX_FILTER_FIFO_COUNT 32 //32组滤波器(一组滤波器对应一个FIFO)
/* Memory for CAN API */
#define MAX_CAN0_PARAM_SIZE 512
static uint32_t can0_api_mem[MAX_CAN0_PARAM_SIZE]={0};
/* CAN handle */
static CAN_HANDLE_T pCan0Handle;


/* 波特率定义 */
enum
{
CAN_RATE_125K = 0x050B,
CAN_RATE_250K = 0x0505,
CAN_RATE_500K = 0x0502,
};
/* 发送FIFO忙标志 */
static uint8_t can0_tx_busy[MAX_FILTER_FIFO_COUNT] = {0};
/* CAN初始化参数 */
static can_param_t can0_param = {0};


/**
----------------------------------------
@brief 接收到数据后先进入该函数,然后根据滤波器号去对应FIFO里取数
@param[in] msg_obj FIFO号
@return none
----------------------------------------
*/
static void _can0_rx(uint8_t msg_obj)
{
//printf("%s msg_obj[%d]\r\n", __func__, msg_obj);
CAN_MSG_OBJ msg = {0};
msg.msgobj= msg_obj; //选择从哪个FIFO接收数据[0~31]
/* Now load up the msg_obj structure with the CAN message */
LPC_CAND_API->hwCAN_MsgReceive(pCan0Handle, &msg);
if(can0_param.irq_rcv)
{
can_frame_t frame = {0};
frame.can_id = msg.mode_id;
frame.can_dlc = msg.dlc;
memcpy(frame.data, msg.data, sizeof(frame.data));
can0_param.irq_rcv(frame);
}
}

/**
---------------------------------------
@brief 发送完数据后,再进入该函数
@param[in] msg_obj FIFO号
@return none
---------------------------------------
*/
static void _can0_tx(uint8_t msg_obj)
{
//printf("%s msg_obj[%d]\r\n", __func__, msg_obj);
if(msg_obj < MAX_FILTER_FIFO_COUNT)
can0_tx_busy[msg_obj] = 0;
}

/**
---------------------------------------
@brief 错误处理
@param[in] error_info 错误码
@return none
---------------------------------------
*/
static void _can0_error(uint32_t error_info)
{
if (error_info & CAN_ERROR_BOFF)
{
}
printf("%s error_info[0x%X]\r\n", __func__, error_info);
}

/**
----------------------------------------------------------
@brief can_init
@param[in] param CAN的初始化参数
@param[in] filter 滤波器配置
@param[in] len 滤波器数量
@return none
-----------------------------------------------------------
*/
void can0_init(can_param_t *param, can_filter_t *filter, int len)
{
if(param==NULL)
{
can0_param.rate = 125000;
can0_param.isIrq = 1;
can0_param.irq_rcv = NULL;
}
else
{
can0_param = *param;
}
uint32_t btr = CAN_RATE_125K;
switch(can0_param.rate)
{
case 125000 : btr = CAN_RATE_125K; break;
case 250000 : btr = CAN_RATE_250K; break;
case 500000 : btr = CAN_RATE_500K; break;
default: btr = CAN_RATE_125K; break;
}

/* Enable clocking for CAN and reset the controller */
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_CAN);
Chip_SYSCTL_PeriphReset(RESET_CAN);
/* Assign the pins rx 0[28] and tx 0[29] */
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 28, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 29, (IOCON_MODE_INACT | IOCON_DIGMODE_EN));
Chip_SWM_MovablePortPinAssign(SWM_CAN_RD1_I, 0, 28); /* Rx P0.28 */
Chip_SWM_MovablePortPinAssign(SWM_CAN_TD1_O, 0, 29); /* Tx P0.29 */

/* CAN initialization structure */
CAN_CFG can_config = {0};
/* Set the Can peripheral to run at 12Mhz. Was used to calculate the btr value in next line. */
/* CPU runs from Xtal at 72Mhz so the divisor should be 6 but clkdiv is divisor - 1 */
can_config.clkdiv = 5;
/* btr values can be obtained from www.bittiming.can-wiki.info (use Bosch C_CAN / D_CAN) */
can_config.btr = btr;
can_config.isr_ena = TRUE;

/* Publish CAN Callback Functions */
CAN_CALLBACKS callbacks = {
_can0_rx,
_can0_tx,
_can0_error
};

CAN_API_INIT_PARAM_T init_param = {
.mem_base = (uint32_t)&can0_api_mem[0],
.can_reg_base = LPC_C_CAN0_BASE,
.can_cfg = &can_config,
.callbacks = &callbacks,
.canopen_cfg = NULL, //canOpen不涉及
.co_callbacks = NULL, //canOpen不涉及
};

/* Validate that we reserved enough memory */
uint32_t maxParamSize = LPC_CAND_API->hwCAN_GetMemSize(&init_param);
if (maxParamSize > MAX_CAN0_PARAM_SIZE / 4)
{
printf("can init fail\r\n");
return;
}
/* Initialize the ROM with specific configuration */
uint32_t status = LPC_CAND_API->hwCAN_Init(&pCan0Handle, &init_param);
if (status != CAN_ERROR_NONE)
{
printf("can init fail\r\n");
return;
}
if (can_config.isr_ena == TRUE)
{
NVIC_EnableIRQ(CAN_IRQn);
}

/* Config filter */
CAN_MSG_OBJ msg = {0};
if(filter==NULL)
{
for(int i=0; i<MAX_FILTER_FIFO_COUNT; i++)
{
memset(&msg, 0 ,sizeof(msg));
msg.msgobj = i;
//默认0~23处理扩展数据帧,24~31处理扩展远程帧
//msg.mode_id = i>=24? (CAN_EFF_FLAG|CAN_RTR_FLAG|0x00) : (CAN_EFF_FLAG|0x00);
msg.mode_id = (CAN_EFF_FLAG|0x00); //只接收扩展数据帧
msg.mask = 0x00;
LPC_CAND_API->hwCAN_ConfigRxmsgobj(pCan0Handle, &msg);
//printf("can init filter[%d] mode_id [0x%X] mask[0x%X]\r\n", i, msg.mode_id, msg.mask);
}
}
else
{
len = len>MAX_FILTER_FIFO_COUNT? MAX_FILTER_FIFO_COUNT : len;
for(int i=0; i<len; i++)
{
memset(&msg, 0 ,sizeof(msg));
msg.msgobj = i;
msg.mode_id = filter[i].mode_id;
msg.mask = filter[i].mask;
LPC_CAND_API->hwCAN_ConfigRxmsgobj(pCan0Handle, &msg);
//printf("can init filter[%d] mode_id [0x%X] mask[0x%X]\r\n", i, msg.mode_id, msg.mask);
}
}
}

/**
----------------------------------------------------------
@brief can_send
@param[in] frame can帧结构
@return 0(ok) -1(fail)
-----------------------------------------------------------
*/
int can0_send(can_frame_t frame)
{
int ret = -1;
CAN_MSG_OBJ msg = {0};
for(int i=0; i<MAX_FILTER_FIFO_COUNT;i++)
{
if(can0_tx_busy[i]==0)
{
msg.msgobj = i;
msg.mode_id = frame.can_id;
msg.mask = 0x00;
msg.dlc = frame.can_dlc;
memcpy(msg.data, frame.data, sizeof(msg.data));
LPC_CAND_API->hwCAN_MsgTransmit(pCan0Handle, &msg);
can0_tx_busy[i]=1;
ret = 0;
break;
}
}
return ret;
}


void CAN_IRQHandler(void)
{
LPC_CAND_API->hwCAN_Isr(pCan0Handle);
}

0 Kudos

778 Views
chensiyan618
Contributor I

Hi Alexis,

   I am very glad to hear from you. It always stopped when the package reached 500,000. These days, I have been looking up the chip manual, I found here's the situation that I was used to utilizing the Full_CAN, such as the LPC1768. There is some difference between them, because the operating mode of LPC1549 is called C_CAN. The detail of reception of a data frame in LPC1549 : 

pastedImage_1.png

I didn't divide the FIFO into two part before, because I think the FIFO can handle this problem itself as the LPC1768. After checking the context above, I doubt that it may not receive and send frame in same FIFO at the same time. So I re-configure the FIFO, I made the FIFO 0 to FIFO 15 the Receive FIFO, and the FIFO 16 to FIFO 31 for Send FIFO. Luckily, It has been up and running for about one week, and nothing unusual happened. It seems that this approach can  work it out. I will continue to observing it's running condition continuously. If you have any other solution, please give me a message.

Best Wishes,

Sean Chen

0 Kudos