This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM335x DCAN丢包

Other Parts Discussed in Thread: AM3352

大家好:

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);
}