大家好:
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); }