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.

TMS320F28377D: DCAN unable to enter receive interrupt during normal use

Part Number: TMS320F28377D


Hi Team,

Here's an issue from the customer may need your help:

I am using the communication function of the F28377D DCAN module,during normal use, there is a very low probability that the CAN communication module of F28377D cannot receive data sent from outside, but its sending function is normal at this time.After carefully checking the code, I found that the program had not been able to enter receive interrupt at this time. At this point, I attempted to reset the peripheral of DCAN and reinitialize the related functions, but it did not work. I tried to read the register CAN_ O_ ERRC searched for the specific error, but could not find the error flag. The relevant bits of this register are all 0, and I really don't know what caused it.

Here is my specific code:

volatile unsigned long g_CANATxMsgCount = 0;
volatile unsigned long g_CANARxMsgCount = 0;
volatile unsigned long g_CANAErrCount = 0;
volatile unsigned long g_CANAErrFlag = 0;

tCANMsgObject sRXCANAMessage[8];

unsigned char ucRXCANAMsgData[64];

volatile struct CAN_REG CAN[2];

volatile unsigned int CAN_RX_INT_Judge[2] = {0, 0};

volatile unsigned int ulStatusA = 0;
volatile unsigned int ulStatus_A = 0;
volatile unsigned int CANA_INT_Flag = 0;

void BSPCANAInitGpio(void)
{
    EALLOW; 
    GPIO_SetupPinMux(30, GPIO_MUX_CPU1, 1);//GPIO30 - CANRXA
    GPIO_SetupPinMux(31, GPIO_MUX_CPU1, 1);//GPIO31 - CANTXA
    EDIS;
    
    GPIO_SetupPinOptions(30, GPIO_INPUT, GPIO_ASYNC); //CANRXA
    GPIO_SetupPinOptions(31, GPIO_OUTPUT, GPIO_PUSHPULL);//CANTXA
}

void BSPCANAInit(void)//initialize the eCAN-A module
{
    Uint16 i, Length;
    Uint16 *Ptr_Obj;
    
    CANInit(CANA_BASE);
    
    CANClkSourceSelect(CANA_BASE, 0);
    
    CANBitRateSet(CANA_BASE, 200000000, (unsigned long)gBSPConfig.CanaBaudRate * 1000);//250k
    
    CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
    HWREG(CANA_BASE + CAN_O_CTL) |= CAN_CTL_ABO; //Auto-Bus-On Enable
    
    HWREG(CANA_BASE + CAN_O_CTL) |= CAN_CTL_WUBA;//Wake Up on Bus Activity
    
    HWREG(CANA_BASE + CAN_O_CTL) |= CAN_CTL_DAR;//Disable Automatic Retransmission
    
    CANEnable(CANA_BASE);
    
    CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);
    
    for(i = 24; i < 32; i++)
    {
        sRXCANAMessage[i - 24].ui32MsgID = 0x08FFF100 | i; // CAN message ID - use 1
        sRXCANAMessage[i - 24].ui32MsgIDMask = 0; // no mask needed for TX
        sRXCANAMessage[i - 24].ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_EXT_FILTER;// enable interrupt on RX
        sRXCANAMessage[i - 24].ui32MsgLen = 8; // size of message is 8
        sRXCANAMessage[i - 24].pucMsgData = (void *)&ucRXCANAMsgData[(i - 24) * 8];// ptr to message content
        
        
        CANMessageSet(CANA_BASE, (i + 1), (void *)&sRXCANAMessage[i - 24], MSG_OBJ_TYPE_RX);
    }
}

#pragma CODE_SECTION(canaISR, ".TI.ramfunc");
interrupt void canaISR(void)
{
    unsigned long ulStatus;
    
    ulStatusA++;
    
    CAN_RX_INT_Judge[1] = 0;
    
    // Read the CAN interrupt status to find the cause of the interrupt
    ulStatus = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);
    
    // If the cause is a controller status interrupt, then get the status
    if(ulStatus == CAN_INT_INT0ID_STATUS)
    {
        ulStatus = CANStatusGet(CANA_BASE, CAN_STS_CONTROL);
        
        //Check to see if an error occurred.
        if(((ulStatus & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 7)
        && ((ulStatus & ~(CAN_ES_TXOK | CAN_ES_RXOK)) != 0))
        {
            g_CANAErrCount++;
            
            g_CANAErrFlag = 1;
        }
    }
    else if(ulStatus == 1)
    {
        CANIntClear(CANA_BASE, 1);
        
        g_CANATxMsgCount++;
        
        g_CANAErrFlag = 0;
    }
    else if((ulStatus >= 25) && (ulStatus <= 32))
    {
        CANMessageGet(CANA_BASE, ulStatus, (void *)&sRXCANAMessage[ulStatus - 25], true);
        
        ulStatus_A = ulStatus;
        CANA_INT_Flag = 1;
        
        CANIntClear(CANA_BASE, ulStatus);
        
        g_CANARxMsgCount++;
        
        g_CANAErrFlag = 0;
    }
    else
    {
    
    }
    
    //canaRegs.CAN_GLB_INT_CLR.bit.INT0_FLG_CLR = 1;
    CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0);
    
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
}

void BSPCANTxDataBuffInByteAlterDlc(u8 CANNum, u8 DLC, u32 ID, u8* Data)
{
    tCANMsgObject sTXCANMessage;
    u16 i;
    Uint32 cmd_regdata = 0;
    
    if(CANNum >= 2){CANNum = 0;}//CAN路数错误,设为0
    if(DLC > 8){DLC = 8;} //dlc取值错误, 设为8
    
    sTXCANMessage.ui32MsgID = ID; // CAN message ID - use
    sTXCANMessage.ui32MsgIDMask = 0; // no mask needed for TX
    sTXCANMessage.ui32Flags = /*MSG_OBJ_EXTENDED_ID*/MSG_OBJ_NO_FLAGS;// an extended identifier
    sTXCANMessage.ui32MsgLen = DLC; // size of message is 8
    sTXCANMessage.pucMsgData = Data; // ptr to message content
    
    
    if(CANNum == 0)
    {
        //IF1 Command Register
        cmd_regdata = CAN_IF1CMD_ARB | CAN_IF1CMD_MASK | CAN_IF1CMD_CONTROL;
        HWREGH(CANB_BASE + CAN_O_IF1CMD + 2) = cmd_regdata >> 16;
        
        
        for(i = 1; i <= 24; i++)
        {
            HWREGH(CANB_BASE + CAN_O_IF1CMD) = i;
            
            while(HWREG(CANB_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
            
            
            if((HWREG(CANB_BASE + CAN_O_IF1MCTL) & CAN_IF1MCTL_TXRQST) == 0){break;}
        }
        if(i >= 25){return;}
        
        CANMessageSet(CANB_BASE, i, (void *)&sTXCANMessage, MSG_OBJ_TYPE_TX);
    }
    else
    {
        //IF1 Command Register
        cmd_regdata = CAN_IF1CMD_ARB | CAN_IF1CMD_MASK | CAN_IF1CMD_CONTROL;
        HWREGH(CANA_BASE + CAN_O_IF1CMD + 2) = cmd_regdata >> 16;
        
        for(i = 1; i <= 24; i++)
        {
            HWREGH(CANA_BASE + CAN_O_IF1CMD) = i;
            
            while(HWREG(CANA_BASE + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY);
            
            
            if((HWREG(CANA_BASE + CAN_O_IF1MCTL) & CAN_IF1MCTL_TXRQST) == 0){break;}
        }
        if(i >= 25){return;}
        
        CANMessageSet(CANA_BASE, i, (void *)&sTXCANMessage, MSG_OBJ_TYPE_TX);
    }
}

u8 CAN_WARN_Flag[2] = {0, 0};
void BSPCANS_WARN_Protect(u8 CANNum)
{
    Uint32 regbase;
    
    if(CANNum == 0){regbase = CANB_BASE;}
    else {regbase = CANA_BASE;}
    
    if(HWREG(regbase + CAN_O_ES) & CAN_ES_EWARN)
    {
        EALLOW;
        HWREG(regbase + CAN_O_CTL) = CAN_CTL_INIT;
        
        HWREG(regbase + CAN_O_CTL) |= CAN_CTL_SWR;
        HWREG(regbase + CAN_O_CTL) |= CAN_CTL_DAR;
        HWREG(regbase + CAN_O_CTL) |= CAN_CTL_ABO;
        HWREG(regbase + CAN_O_CTL) |= CAN_CTL_WUBA;
        
        if(CANNum == 0){BSPCANBInit();}
        else {BSPCANAInit();}
        
        HWREG(regbase + CAN_O_CTL) &= ~CAN_CTL_INIT;
        EDIS;
        
        CAN_WARN_Flag[CANNum] = 1;
    }
    else
    {
        CAN_WARN_Flag[CANNum] = 0;
    }
}


void BSPCANS_Err_Counter(u8 CANNum)
{
    Uint32 regbase;
    
    if(CANNum == 0){regbase = CANB_BASE;}
    else {regbase = CANA_BASE;}
    
    CAN[CANNum].CAN_Err.bit.TEC = (HWREG(regbase + CAN_O_ERRC) >> 0) & 0xff;
    CAN[CANNum].CAN_Err.bit.REC = (HWREG(regbase + CAN_O_ERRC) >> 8) & 0x7f;
    CAN[CANNum].CAN_Err.bit.RP = (HWREG(regbase + CAN_O_ERRC) >> 15) & 0x01;
    
    CAN[CANNum].CAN_Sta.bit.LEC = (HWREG(regbase + CAN_O_ES) >> 0) & 0x07;
    CAN[CANNum].CAN_Sta.bit.TxOk = (HWREG(regbase + CAN_O_ES) >> 3) & 0x01;
    CAN[CANNum].CAN_Sta.bit.RxOk = (HWREG(regbase + CAN_O_ES) >> 4) & 0x01;
    CAN[CANNum].CAN_Sta.bit.EPass = (HWREG(regbase + CAN_O_ES) >> 5) & 0x01;
    CAN[CANNum].CAN_Sta.bit.EWarn = (HWREG(regbase + CAN_O_ES) >> 6) & 0x01;
    CAN[CANNum].CAN_Sta.bit.BOff = (HWREG(regbase + CAN_O_ES) >> 7) & 0x01;
    CAN[CANNum].CAN_Sta.bit.PER = (HWREG(regbase + CAN_O_ES) >> 8) & 0x01;
}

--

Thanks & Regards

Yale

  • Yale, 

    We are looking into it and will get back to you soon.

    Thanks.

  • Hi Team,

    For this  problem, I would like to add something:

    Once this problem occurs, if I write an incorrect value to The Watchdog Register to force it to reset the CPU core or power off the CPU, and then power on and restart, this problem will disappear and the code can enter the CAN receive interrupt code.But we can not do this while the equipment is working, which is very dangerous, so I need to find a normal solution to this problem. Thank you!

  • Hi Sahil,

     -- This is the customer who asked this question.

    Hi Haiyang,

    You can discuss with our expert here directly.

    --

    Thanks & Regards

    Yale

  • Hi,Yale

    Have the TI experts found any errors in the code?

    Do them have any opinions or suggestions?

    Thankyou.

  • Haiyang, 

    I have a couple of followup questions:

    - Are the transmit interrupts working fine? As you have not included the initialisation code for interrupts, wanted you to check that. However, if the tx interrupts are calling the ISR properly and being cleared, then this section is performing as expected.

    - The code you have shared looks to be in order. Can you check whether the frames that are to be received are being transmitted properly? 

    - In case the two things listed above check out, could you carry out some testing and mention some details as to when the device is not able to receive data from outside and could you also read the contents of the CAN_O_ERRC register in that case without resetting the peripheral?

    Thanks. 

  • Hi Sahil,

    The reply from Haiyang:

    I only used receive interrupts and did not use send interrupts.

    My receive interrupt initialization code directly uses the library functions provided by TI official, as follows:

    In the vast majority of cases, receiving interrupts is normal, with only a few cases where the program suddenly becomes unable to enter receiving interrupts after running normally for a period of time.When the program can enter the receive interrupt normally, the received frame is completely correct and fully complies with our own communication protocol.

    We use CANA for data interaction with the outside world, and use CANB to send various statuses of CANA to the upper computer, including CAN_ O_ ERRC and CAN_ O_ ES, before resetting the peripheral, it was found that the value of bit LEC in the CAN_O_ES register of CANA was 7, and all other values were 0.

    --

    Thanks & Regards

  • Hi Sahil,

    The customer did the following tasks:

    1、After swapping the node IDs of two DSPs, I found that the node ID that could not enter receive interrupts was still the previous node ID number, node 61. Node 44  is still normal after swapping the DSP circuit board. This can prove that it is not related to hardware, the problem lies in software.
    2、After I removing the DSP node (node number: 44) that was able to enter receive interrupts normally all the time, leaving only the DSP node (node number: 61) that was sometimes unable to enter receive interrupts, I found that after doing this, node 61 was able to enter receive interrupts normally all the time, and there was no occurrence of being unable to enter receive interrupts afterwards.
    3、Through the above operation, I speculate that node 44 sent too many frames to the bus, which affected the reception of node 61. To verify this speculation, I deleted some messages sent by node 44 to the bus, and still connected nodes 44 and 61 to the bus. After powering on, the probability of node 61 being unable to enter the receive interrupt was greatly reduced.
    4、Through the above operation, I highly suspect that there is a problem with the configuration of the receiving mailboxes or the code for polling idle sending mailboxes, but I don't know where it is. I hope you can help me check if there are any issues with the receiving and sending mailbox operation codes.
    --
    Thanks & Regards
    Yale
  • Closing the thread here as this is being discussed offline.

    Thanks.