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.

DCAN initialization and usage

Part Number: TMS320F280049
Other Parts Discussed in Thread: UNIFLASH, C2000WARE

Hello,

We have recently used DCAN drivers from the 'driverlib'. But we have written our own based on the 'device_support' library ("f28004x_can.h").

The problem that if I flash it using debugger (UniFlash tool or CCS debugger) the project works as expected (all frames match their mailboxes). But when I use customer bootloader that also use the same CAN module, the bootloader works, but when application starts the CAN sends only one remote frame: ID 0x0, DLC 0x0, Data 0x0. I do CAN RAM and CAN module reset, but I have still only one remote frame when I send any data over CAN.

    CanaRegs.CAN_CTL.bit.Init = 1u;

    CanaRegs.CAN_RAM_INIT.all =
            (uint32_t)CAN_ACCESS_TO_RAM_KEY | ((uint32_t)1uL << CAN_RAM_INIT_BIT_POSITION);

    while (CanaRegs.CAN_RAM_INIT.bit.RAM_INIT_DONE != 1u) {}

    /* Force module to reset state */
    EALLOW;
    CanaRegs.CAN_CTL.bit.SWR = 1u;
    EDIS;
    __asm(" RPT #14 || NOP");

    CanaRegs.CAN_CTL.bit.CCE = 1u;

After some investigation I have found that the CAN mailboxes are not actually the same as I configured them, so I cannot even receive any data.

There are few questions:

1. why CAN message RAM is not initialized (the same way as it is done in the 'driverlib', except of register access, we use bit access, like CanaRegs.CAN_RAM_INIT.all = (uint32_t)CAN_ACCESS_TO_RAM_KEY | ((uint32_t)1uL << CAN_RAM_INIT_BIT_POSITION); and while (CanaRegs.CAN_RAM_INIT.bit.RAM_INIT_DONE != 1u) {}). And it work are direct flashing.

2. can we actually use bit access for CAN configuration registers: CAN_CTL, CAN_BTR, CAN_TEST, CAN_RAM_INIT, CAN_IP_MUX21 and to CAN interface registers: CAN_IF1CMD (shall be written only via .all when other are configured), CAN_IF1MSK, CAN_IF1ARB, CAN_IF1MCTL?

3. in the 'driverlib' can.c, in the function CAN_setBitTiming, at the end is mentioned that we want to save Init bit if it was set before, but in fact we clear it, so Init bit will be cleared in when bit rate updates. Right, or I skipped something?

    //
    // If Init was not set before, then clear it.
    //
    if((savedInit & CAN_CTL_INIT) == CAN_CTL_INIT)
    {
        savedInit &= ~((uint16_t)CAN_CTL_INIT);
    }
    HWREGH(base + CAN_O_CTL) = savedInit;

Thank you

Best regards,
Viacheslav Potapov

  • Viacheslav, 

    We are looking into it and will let you know soon.

    Thanks.

  • Hello Sahil,

    Do you have any progress on these issues, at least some of them?

    What I can see, if I change this line:

    while (CanaRegs.CAN_RAM_INIT.bit.RAM_INIT_DONE != 1u) {}

    on this:

        while (!((p_Regs->CAN_RAM_INIT.all & CAN_RAM_INIT_MASK)
              == (CAN_RAM_INIT_RAM_INIT_DONE | CAN_RAM_INIT_KEY2 | CAN_RAM_INIT_KEY0)))

    (where p_Regs is pointer to CanaRegs)

    then RAM reset seems to be working, but again, can we use bit access for CAN (DCAN) registers or not? And where can I found description which registers are bit-accessible?

    Thank you

    Best regards,

    Viacheslav Potapov

  • Viacheslav, 

    2. can we actually use bit access for CAN configuration registers: CAN_CTL, CAN_BTR, CAN_TEST, CAN_RAM_INIT, CAN_IP_MUX21 and to CAN interface registers: CAN_IF1CMD (shall be written only via .all when other are configured), CAN_IF1MSK, CAN_IF1ARB, CAN_IF1MCTL?

    It is possible to use bit access as long as the bit-field header files from C2000ware are used which use the special bp_16 and bp_32 types. Please let us know if you face any issues with the same.

    3. in the 'driverlib' can.c, in the function CAN_setBitTiming, at the end is mentioned that we want to save Init bit if it was set before, but in fact we clear it, so Init bit will be cleared in when bit rate updates. Right, or I skipped something?

    The init bit is to be set which disables the CAN module when the bit rate updates, after which the init bit is cleared, leading to normal operation. 

    Thanks.

  • Hello Sahil,

    thank you for your answer.

    It seems all CAN registers defined via bp_16 and bp_32 types, I will double check MsgLst reset, if I can do bit access there. Can I just write like this when NewDat and MsgLst  are set?

    CanaRegs.CAN_IF2MCTL.bit.MsgLst = 0u;
    CanaRegs.CAN_IF2CMD.all = 
        (uint32_t)(CAN_CMD_MASK_DIR
                 | CAN_CMD_MASK_CTRL
                 | Mailbox);

    Regarding the bit rate initialization:

    The init bit is to be set which disables the CAN module when the bit rate updates, after which the init bit is cleared, leading to normal operation. 

    In the code you have this comment (line 21) "State of the init bit should be saved so it can be restored at the end.", but in fact you don't restore this bit, you just clear it if it WAS set (lines 48-51). If it wasn't set you keep it disabled, so the comment and the condition on the line 48 they don't match. If you want to reset this bit why you check if it was set? If you want to restore this bit why you reset it? So which behaviour is correct, do you want to restore Init or not?

    void CAN_setBitTiming(uint32_t base, uint16_t prescaler,
                          prescalerExtension, uint16_t tSeg1, uint16_t tSeg2,
                          uint16_t sjw)
    {
        uint16_t savedInit;
        uint32_t bitReg;
    
        //
        // Check the arguments.
        //
        ASSERT(CAN_isBaseValid(base));
        ASSERT(prescaler < 64U);
        ASSERT((tSeg1 > 0U) && (tSeg1 < 16U));
        ASSERT(tSeg2 < 8U);
        ASSERT(sjw < 4U);
        ASSERT(prescalerExtension < 16U);
    
        //
        // To set the bit timing register, the controller must be placed in init
        // mode (if not already), and also configuration change bit enabled.
        // State of the init bit should be saved so it can be restored at the end.
        //
        savedInit = HWREGH(base + CAN_O_CTL);
        HWREGH(base + CAN_O_CTL) = savedInit | CAN_CTL_INIT | CAN_CTL_CCE;
    
        //
        // Set the bit fields of the bit timing register
        //
        bitReg = (uint32_t)((uint32_t)prescaler & CAN_BTR_BRP_M);
        bitReg |= (uint32_t)(((uint32_t)sjw << CAN_BTR_SJW_S) & CAN_BTR_SJW_M);
        bitReg |= (uint32_t)(((uint32_t)tSeg1 << CAN_BTR_TSEG1_S) &
                             CAN_BTR_TSEG1_M);
        bitReg |= (uint32_t)(((uint32_t)tSeg2 << CAN_BTR_TSEG2_S) &
                             CAN_BTR_TSEG2_M);
        bitReg |= (uint32_t)(((uint32_t)prescalerExtension << CAN_BTR_BRPE_S) &
                             CAN_BTR_BRPE_M);
    
        HWREG_BP(base + CAN_O_BTR) = bitReg;
    
        //
        // Clear the config change bit, and restore the init bit.
        //
        savedInit &= ~((uint16_t)CAN_CTL_CCE);
    
        //
        // If Init was not set before, then clear it.
        //
        if((savedInit & CAN_CTL_INIT) == CAN_CTL_INIT)
        {
            savedInit &= ~((uint16_t)CAN_CTL_INIT);
        }
        HWREGH(base + CAN_O_CTL) = savedInit;
    }