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.

DRV 8301 eCAN-A Clock Speed

Other Parts Discussed in Thread: DRV8301, CONTROLSUITE

I'm trying to implement CAN on my DRV8301-69M development kit. I'm referencing the ECANBack2Back example project. If I run the example project on the board I can get CAN working just fine. When I try and port the code over to proj_lab05a, I can't seem to get it to work. I believe the issue is stemming from an incorrect CANBTC register setting. I can get the CAN bus to show data Txing, but the bus is showing bit stuff errors. Can anyone tell me what speed the CAN clock is running at if I have a SYSCLOCK running at 90 Mhz?

Thanks,

Drew

  • For reference here is the initialization code and the send message code.

    The processor always hangs on this segment of code and won't proceed further:

    --------------------------------------------------------------------------------------------------------------------

    // Wait until the CPU no longer has permission to change the configuration registers
    do
    {
    ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared..

    --------------------------------------------------------------------------------------------------------------------

    volatile struct ECAN_MBOXES ECanaMboxes;
    volatile struct ECAN_REGS ECanaRegs;
    volatile struct GPIO_CTRL_REGS GpioCtrlRegs;
    volatile struct SYS_CTRL_REGS SysCtrlRegs;

    void InitECana(void) // Initialize eCAN-A module
    {

    /* Create a shadow register structure for the CAN control registers. This is
    needed, since only 32-bit access is allowed to these registers. 16-bit access
    to these registers could potentially corrupt the register contents or return
    false data. */

    struct ECAN_REGS ECanaShadow;

    EALLOW; // EALLOW enables access to protected bits

    /* Configure eCAN RX and TX pins for CAN operation using eCAN regs*/

    ECanaShadow.CANTIOC.all = ECanaRegs.CANTIOC.all;
    ECanaShadow.CANTIOC.bit.TXFUNC = 1;
    ECanaRegs.CANTIOC.all = ECanaShadow.CANTIOC.all;

    ECanaShadow.CANRIOC.all = ECanaRegs.CANRIOC.all;
    ECanaShadow.CANRIOC.bit.RXFUNC = 1;
    ECanaRegs.CANRIOC.all = ECanaShadow.CANRIOC.all;

    /* Configure eCAN for HECC mode - (reqd to access mailboxes 16 thru 31) */
    // HECC mode also enables time-stamping feature

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.SCB = 1;
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    /* Initialize all bits of 'Message Control Register' to zero */
    // Some bits of MSGCTRL register come up in an unknown state. For proper operation,
    // all bits (including reserved bits) of MSGCTRL must be initialized to zero

    ECanaMboxes.MBOX0.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX1.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX2.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX3.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX4.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX5.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX6.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX7.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX8.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX9.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX10.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX11.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX12.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX13.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX14.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX15.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX16.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX17.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX18.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX19.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX20.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX21.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX22.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX23.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX24.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX25.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX26.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX27.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX28.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX29.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX30.MSGCTRL.all = 0x00000000;
    ECanaMboxes.MBOX31.MSGCTRL.all = 0x00000000;

    // TAn, RMPn, GIFn bits are all zero upon reset and are cleared again
    // as a matter of precaution.

    ECanaRegs.CANTA.all = 0xFFFFFFFF; /* Clear all TAn bits */

    ECanaRegs.CANRMP.all = 0xFFFFFFFF; /* Clear all RMPn bits */

    ECanaRegs.CANGIF0.all = 0xFFFFFFFF; /* Clear all interrupt flag bits */
    ECanaRegs.CANGIF1.all = 0xFFFFFFFF;

    /* Configure bit timing parameters for eCANA*/

    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 1 ; // Set CCR = 1
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    // Wait until the CPU has been granted permission to change the configuration registers
    do
    {
    ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 1 ); // Wait for CCE bit to be set..

    ECanaShadow.CANBTC.all = 0;
    /* The following block is for 80 MHz SYSCLKOUT. (40 MHz CAN module clock Bit rate = 1 Mbps
    See Note at end of file. */

    ECanaShadow.CANBTC.bit.BRPREG = 8;
    ECanaShadow.CANBTC.bit.TSEG2REG = 3;
    ECanaShadow.CANBTC.bit.TSEG1REG = 4;
    ECanaShadow.CANBTC.bit.SJWREG = 1;

    ECanaShadow.CANBTC.bit.SAM = 1;
    ECanaRegs.CANBTC.all = ECanaShadow.CANBTC.all;

    EALLOW;
    ECanaShadow.CANMC.all = ECanaRegs.CANMC.all;
    ECanaShadow.CANMC.bit.CCR = 0 ; // Set CCR = 0
    ECanaRegs.CANMC.all = ECanaShadow.CANMC.all;

    // Wait until the CPU no longer has permission to change the configuration registers
    do
    {
    ECanaShadow.CANES.all = ECanaRegs.CANES.all;
    } while(ECanaShadow.CANES.bit.CCE != 0 ); // Wait for CCE bit to be cleared..

    /* Disable all Mailboxes */
    ECanaRegs.CANME.all = 0; // Required before writing the MSGIDs

    EDIS;
    }

    void InitECanaGpio(void)
    {
    EALLOW;

    /* Enable internal pull-up for the selected CAN pins */
    // Pull-ups can be enabled or disabled by the user.
    // This will enable the pullups for the specified pins.
    // Comment out other unwanted lines.

    GpioCtrlRegs.GPAPUD.bit.GPIO30 = 0; // Enable pull-up for GPIO30 (CANRXA)
    GpioCtrlRegs.GPAPUD.bit.GPIO31 = 0; // Enable pull-up for GPIO31 (CANTXA)

    /* Set qualification for selected CAN pins to asynch only */
    // Inputs are synchronized to SYSCLKOUT by default.
    // This will select asynch (no qualification) for the selected pins.

    GpioCtrlRegs.GPAQSEL2.bit.GPIO30 = 3; // Asynch qual for GPIO30 (CANRXA)

    /* Configure eCAN-A pins using GPIO regs*/
    // This specifies which of the possible GPIO pins will be eCAN functional pins.

    GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 1; // Configure GPIO30 for CANRXA operation
    GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 1; // Configure GPIO31 for CANTXA operation

    EDIS;
    }

    void SendMessage(void) {
    ECanaMboxes.MBOX0.MSGID.all = 0x9555AAA0;
    // Configure Mailboxes 0-15 as Tx, 16-31 as Rx
    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    ECanaRegs.CANMD.all = 0xFFFF0000;

    // Enable all Mailboxes */
    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    ECanaRegs.CANME.all = 0xFFFFFFFF;

    // Specify that 8 bits will be sent/received
    ECanaMboxes.MBOX0.MSGCTRL.bit.DLC = 8;

    // Write to the mailbox RAM field of MBOX0 - 15
    ECanaMboxes.MBOX0.MDL.all = 0x9555AAA0;
    ECanaMboxes.MBOX0.MDH.all = 0x89ABCDEF;

    // Since this write is to the entire register (instead of a bit
    // field) a shadow register is not required.
    EALLOW;
    ECanaRegs.CANMIM.all = 0xFFFFFFFF;
    EDIS;

    ECanaRegs.CANTRS.all = 0x00000001; // Set TRS for all transmit mailboxes
    while(ECanaRegs.CANTA.all != 0x00000001 ) {} // Wait for all TAn bits to be set..
    ECanaRegs.CANTA.all = 0x00000001; // Clear all TAn
    }
  • Any thoughts on this issue? I'm not really sure if this post is best for this category or if the more general C2000 category. I figured since I'm trying to use this on a DRV8301 dev that this category would probably be best. I've tried just about everything I can think of to solve this problem in the last couple days.

  • Drew,

    The non-motor stuff is out of my area of knowledge also. I tagged this for our software team to try to answer.

  • Drew,

    On the one hand, you say "The processor always hangs on this segment of code and won't proceed further", implying that the CCE bit is never set, but on the other hand you say "bus is showing bit stuff errors". What is correct?

    In the F28069 device, clock to the CAN module = SYSCLK/2. So, it is 45 MHz on a 90 MHz device. Looking at the CANBTC values you are using, you are operating the bust at 500 kbps. What is the bit-time you are seeing? Can you share an oscilloscope image of the traffic?

    How did you determine the error to be "bit-stuff" error?

    Hareesh

  • Hareesh,

    I think I'm getting close to solving the problem. The DRV8301 uses a completely different HAL structure to setup the different devices than the example code (for instance ECanBack2Back). I believe the issue stems from the fact that my ECanaRegs and ECanaMboxes variables are not linking to the proper locations in RAM. If I include a #pragma DATA_SECTION(ECanaRegs,"ECanaRegsFile"); and #pragma DATA_SECTION(ECanaMboxes,"ECanaMboxesFile"); before the variables everything works fine. If I don't include that #pragma then I get stuck at the same spot in the code mentioned above and the CAN does not work at all. If I include those #pragma's then I have to include F2806x_Headers_nonBIOS.cmd. @ Do you know how the hal.c is linking the hardware registers to the proper register memory locations? I have the CAN working now, but I'd like to follow the same conventions the project is using by incorporating my code into the hal.c file.

    #include "sw/drivers/can/src/32b/f28x/f2806x/ecan.h"
    #include "sw/drivers/gpio/src/32b/f28x/f2806x/gpio.h"

    #pragma DATA_SECTION(ECanaRegs,"ECanaRegsFile"); <----- won't work unless this is included.
    volatile struct ECAN_REGS ECanaRegs;
    #pragma DATA_SECTION(ECanaMboxes,"ECanaMboxesFile"); <----- won't work unless this is included.
    volatile struct ECAN_MBOXES ECanaMboxes;

     

  • Drew,

    In hal.c, the registers get mapped to the hardware when their respective initialization function within the driver gets called. Looking within HAL_init function, take ADC for example, it passes the peripheral base memory address and struct object size. That ADC_init function returns a handle that points to a structure that is mapped to the ADC registers. That handle then is how the HAL and ADC drivers modify the registers. This differs from how structure mapping in controlSUITE is handled. controlSUITE uses a combination of the linker command file, such as F2806x_Headers_nonBIOS.cmd and F2806x_GlobalVariableDefs.c, which includes the pragmas as you are using, to link the the structure to the register. The F2806x_GlobalVariableDefs.c can be included to provide the pragmas, if desired. 

    Best Regards,

    Chris

  • Chris,

    That makes a lot more sense. I didn't think to look into the init functions for the memory mapping. I will maybe try to design an init function and a similar structure for the canbus to try and replicate the hal functionality. Once I mapped the structure to memory everything seems to be working nicely now. Thanks for helping me understand the HAL structure. I will consider this thread answered now.

    Thanks,

    Drew