大家好:
AM335X的DCAN驱动遇到丢包问题,现象为发送长帧(数据帧大于8字节)会只收到后边几个字节,例如:发送数据为 1 2 3 4 5 6 7 8 9 a b c 只能收到 9 a b c ,发送单帧8字节及以内都能收到
static void DCANIsr0(void) {unsigned char *dataPtr;unsigned int index = 0;unsigned int errVal;unsigned int msgNum;int ret = 0;char tmp[12] = "receive ok!";printk("dcan isr\n");while(ret = DCANIntRegStatusGet(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT)){printk("intRegStatus:%x\n", ret);if(DCANIntRegStatusGet(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) == DCAN_ERROR_OCCURED){/* Check the status of DCAN Status and error register */errVal = DCANErrAndStatusRegInfoGet(g_SOC_DCAN_1_REGS);printk("ESReg:%x\n", errVal);if(errVal & DCAN_MOD_IN_BUS_OFF_STATE){printk("**DCAN is in Bus-off state**\n");/*** This feature will automatically get the CAN bus to bus-on** state once the error counters are below the error warning** limit.*/DCANAutoBusOnControl(g_SOC_DCAN_1_REGS, DCAN_AUTO_BUS_ON_ENABLE);}if(errVal & DCAN_ERR_WARN_STATE_RCHD){printk("Atleast one of the error counters have");printk(" reached the error warning limit\n");}}if((DCANIntRegStatusGet(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) != DCAN_NO_INT_PENDING) &&((DCANIntRegStatusGet(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT) != DCAN_ERROR_OCCURED))){/* Get the number of the message object which caused the interrupt */msgNum = DCANIntRegStatusGet(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0_STAT);printk("msgNum:%d\n", msgNum);/* Interrupt handling for transmit objects */if(msgNum < (CAN_NUM_OF_MSG_OBJS/2)){/* Clear the Interrupt pending status */CANClrIntPndStat(g_SOC_DCAN_1_REGS, msgNum, DCAN_IF1_REG);printk("%d\n", __LINE__);}if((msgNum >= (CAN_NUM_OF_MSG_OBJS/2)) && (msgNum < CAN_NUM_OF_MSG_OBJS)){/* Read a received message from message RAM to interface register */CANReadMsgObjData(g_SOC_DCAN_1_REGS, msgNum, (unsigned int*) canData, DCAN_IF2_REG);#if 1/* The 29-bit (extended) Identifier is used for this message** object.*/if((DCANIFArbStatusGet(g_SOC_DCAN_1_REGS, DCAN_IF2_REG) &DCAN_EXT_ID_READ) == DCAN_29_BIT_ID){entry.flag = (CAN_EXT_FRAME | CAN_DATA_FRAME | CAN_MSG_DIR_TX);entry.id = CAN_TX_MSG_EXTD_ID;}else{entry.flag = (CAN_DATA_FRAME | CAN_MSG_DIR_TX);entry.id = CAN_TX_MSG_STD_ID;}#endif/* Clear the Interrupt pending status */CANClrIntPndStat(g_SOC_DCAN_1_REGS, msgNum, DCAN_IF2_REG);dataPtr = (unsigned char*) canData;printk("Data received = ");/*Data length code.**Note: The data length code of a message object must be defined the**same as in all the corresponding objects with the same identifier at**other nodes.**When the message handler stores a data frame, it will write the DLC**to the value given by the received message.*/bytes = (DCANIFMsgCtlStatusGet(g_SOC_DCAN_1_REGS, DCAN_IF2_REG) & DCAN_DAT_LEN_CODE_READ);printk("bytes:%d,index:%d\n",bytes, index);/* Print the received data bytes on the UART console */for(index = 0; index < 20/*bytes*/; index++){printk("%d ", *dataPtr++);}printk("\r\n");isrFlag = 0;#if 1/* Populate the can_frame structure with the CAN frame information *///entry.dlc = 12;//entry.data = tmp;entry.dlc = bytes;entry.data = (unsigned int*)canData;/* Configure a transmit message object */CANMsgObjectConfig(g_SOC_DCAN_1_REGS, &entry);#endif}}} } int can_init(void) {int ret;unsigned int index = 0;void __iomem *p_REGS;p_REGS = ioremap(SOC_DCAN_1_REGS, SZ_4K);if(!p_REGS){printk("%s:ioremap(%x) error\r\n", __func__, SOC_DCAN_1_REGS);iounmap((void __iomem *)g_CONTROL_REGS);return -1;}g_SOC_DCAN_1_REGS = (unsigned int)p_REGS;DCANPinMuxSetUp(0);DCANMsgRAMInit(1);DCANReset(g_SOC_DCAN_1_REGS);DCANInitModeSet(g_SOC_DCAN_1_REGS);DCANConfigRegWriteAccessControl(g_SOC_DCAN_1_REGS, DCAN_CONF_REG_WR_ACCESS_ENABLE);CANSetBitTiming(g_SOC_DCAN_1_REGS, DCAN_IN_CLK, DCAN_BIT_RATE);DCANConfigRegWriteAccessControl(g_SOC_DCAN_1_REGS, DCAN_CONF_REG_WR_ACCESS_DISABLE);index = CAN_NUM_OF_MSG_OBJS;while(index--){/* Invalidate all message objects in the message RAM */CANInValidateMsgObject(g_SOC_DCAN_1_REGS, index, DCAN_IF2_REG);}entry.flag = rxflag;entry.id = canId;entry.data = recv_tmp;CANMsgObjectConfig(g_SOC_DCAN_1_REGS, &entry);/* Start the CAN transfer */DCANNormalModeSet(g_SOC_DCAN_1_REGS);ret=request_irq(SYS_INT_DCAN1_INT0, DCANIsr0, NULL, "dcan_isr_end", 0);if (ret < 0){printk("request err\n");}/* Enable the interrupt line 0 of DCAN module */DCANIntLineEnable(g_SOC_DCAN_1_REGS, DCAN_INT_LINE0);/* Enable the error interrupts */DCANIntEnable(g_SOC_DCAN_1_REGS, DCAN_STATUS_CHANGE_INT); }
yongqing wang:
在那块板子上测试?啥版本SDK
user6200184:
回复 yongqing wang:
没用SDKAM3352芯片linux系统上跑的
yongqing wang:
回复 user6200184:
参考这个教程看看: processors.wiki.ti.com/…/AM335X_DCAN_Driver_Guide
user6200184:
回复 yongqing wang:
这个资料不行,我这没可调试得命令行,内核改了没问题 ifconfig能看到两个can,驱动上单帧也能收到数据,就是连续的话只能收到后边的最后一帧
yongqing wang:
回复 user6200184:
实际跟一下驱动的收发代码吧
user6200184:
回复 yongqing wang:
您官方的用过dcan库吗
yongqing wang:
回复 user6200184:
没有,但是估计这个应该没啥坑,这个帖子你也可以参考一下:www.cnblogs.com/…/8795831.html
user6200184:
回复 yongqing wang:
长帧数据会在FIFO buffer中覆盖,只留下最后一帧,有什么需要配置吗
user6200184:
自发自收的长帧(大于八字节)的数据能接收完全(如下图红色部分),但来自can调试器终端的长帧数据就只能收到一部分(如下图绿色部分),来自其他CAN设备的长帧数据同样存在丢包(能收到第一个8字节和最后一帧数据)(如下图绿色部分),过程如下图数据 其中下图ID为can数据id,bytes为帧数据长度,msgnum为int寄存器的line0值如下下图中寄存器表。