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


