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.

TM4C129XNCZAD: CAN bus loopback mode issue

Part Number: TM4C129XNCZAD
Other Parts Discussed in Thread: EK-TM4C1294XL

Hi all,

I am trying to create a program for CAN bus loop back  testing. However, my program below does not seems to work. Please advise.

int main(void)
{
//Enable clock to CAN and GPIO Port A
//Wait for the CAN Module and GPIO Port A Peripheral to be ready
*((uint32_t *)(SYSCTL_RCGCCAN)) |= (0x01 << 0);
*((uint32_t *)(SYSCTL_RCGCGPIO)) |= (0x00001 << 0);
while(!(*(uint32_t *)(SYSCTL_PRCAN) & (0x01 << 0)));
while(!(*(uint32_t *)(SYSCTL_PRGPIO) & (0x00001 << 0)));

//Configure the GPIO alternate function as UART
*((uint32_t *)(GPIO_PORTA_AHB + GPIO_O_AFSEL)) |= (0x03 << 0);
*((uint32_t *)(GPIO_PORTA_AHB + GPIO_O_DEN)) |= (0x03 << 0);
*((uint32_t *)(GPIO_PORTA_AHB + GPIO_O_PCTL)) |= (0x07 << 4 | 0x07 << 0);

//Initialize and configure CAN Module Bit Timing
*((uint32_t *)(CAN0 + CAN_O_CTL)) |= (0x1 << 0);
*((uint32_t *)(CAN0 + CAN_O_CTL)) |= (0x1 << 6);
*((uint32_t *)(CAN0 + CAN_O_BIT)) = (0x2 << 12 | 0x3 << 8 |
0x2 << 6 | 0x2 << 0);
*((uint32_t *)(CAN0 + CAN_O_CTL)) &= ~(0x1 << 0);
*((uint32_t *)(CAN0 + CAN_O_CTL)) &= ~(0x1 << 6);

//Configure CAN Module to Loopback Mode
*((uint32_t *)(CAN0 + CAN_O_CTL)) |= (0x1 << 7);
*((uint32_t *)(CAN0 + CAN_O_TST)) |= (0x1 << 4);

*((uint32_t *)(CAN0 + CAN_O_CTL)) |= (0x1 << 1);

//Configure Receive Message Object
*((uint32_t *)(CAN0 + CAN_O_IF1CMSK)) = (0x0 << 7 | 0x1 << 4 | 0x1 << 1 | 0x1 << 0);
*((uint32_t *)(CAN0 + CAN_O_IF1MSK1)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1MSK2)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB1)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB2)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1MCTL)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB2)) = (0x1 << 15 | 0x5 << 2);
*((uint32_t *)(CAN0 + CAN_O_IF1MCTL)) = (0x1 << 7 | 0x8 << 0);
*((uint32_t *)(CAN0 + CAN_O_IF1CRQ)) = 1;
while(*(uint32_t *)(CAN_O_IF1CRQ) & 0x8000);

//Configure Transmit Message Object
*((uint32_t *)(CAN0 + CAN_O_IF1CMSK)) = (0x1 << 7 | 0x1 << 4 | 0x1 << 1 | 0x1 << 0);
*((uint32_t *)(CAN0 + CAN_O_IF1MSK1)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1MSK2)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB1)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB2)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1MCTL)) = 0;
*((uint32_t *)(CAN0 + CAN_O_IF1ARB2)) = (0x1 << 15 | 0x1 << 13 | 0x5 << 2);
*((uint32_t *)(CAN0 + CAN_O_IF1MCTL)) = (0x1 << 8 | 0x1 << 7 | 0x8 << 0);
*((uint32_t *)(CAN0 + CAN_O_IF1DA1)) = 0x1111;
*((uint32_t *)(CAN0 + CAN_O_IF1DA2)) = 0x2222;
*((uint32_t *)(CAN0 + CAN_O_IF1DB1)) = 0x3333;
*((uint32_t *)(CAN0 + CAN_O_IF1DB2)) = 0x4444;
*((uint32_t *)(CAN0 + CAN_O_IF1CRQ)) = 2;
while(*(uint32_t *)(CAN_O_IF1CRQ) & 0x8000);

//Initiate a Transmit Request
*((uint32_t *)(CAN0 + CAN_O_IF1MCTL)) |= (0x1 << 8);

*((uint32_t *)(CAN0 + CAN_O_IF2CMSK)) = (0x0 << 7 | 0x1 << 6 | 0x1 << 5 | 0x1 << 4 | 0x1 << 1 | 0x1 << 0);
*((uint32_t *)(CAN0 + CAN_O_IF2CRQ)) = 1;
while(*(uint32_t *)(CAN_O_IF2CRQ) & 0x8000);

while(1);
}

  • First - may I note that your English is,  "Simply Terrific!"    It proves embarrassing how skilled you are - and how "Language Limited" most in the west - are...

    To your issue - Vendor Reps (and outsiders - such as me) always prefer your use of the API (which includes MANY CAN Programming Examples.)     You have employed the 'DRM' style of coding (Direct Register Manipulation) which surely CAN work - yet is substantially HARDER to DEVELOP - TAKES LONGER - and has NONE of the "Record of Success" of the Vendor's,  "Well Tested, PROVEN, EXTENSIVE and Massively Exampled" API.

    The MUCH INCREASED 'Time & Effort' required - to debug your code - usually discourages Vendor Agents (as I believe it should) and humble outsiders - from "Diving In - to your Rescue!"    Even when - and especially when - we'd LIKE TO!

    I would also advise that any such "Loopback" - in my opinion - proves NOT as USEFUL as a REAL CAN TRANSACTION - which involves (at least two) CAN DEVICES and two CAN TRANSCEIVERS!    (3V3, please)

    You will find suitable examples under:  "TWare\examples\peripherals\CAN."     MY small firm finds "Simple.RX and Simple.TX" to prove ideal - for (both) your Can Testing AND further Development...

    Again - simply great post...   Bon chance mon ami.    (some, slight 2nd language capability...)

  • By design the CAN module will not "receive" the message that it transmits unless you enable the test loop back mode. You must first set the TEST bit in the CANCTL register and then set the LBACK bit in the CANTST register.

    I have not reviewed your code implementation in detail. As CB1 has pointed out, we strongly encourage the use of the TivaWare API instead of writing your own routines with direct register writes. The use of known working functions greatly increases your productivity, and the productivity of those who help you.
  • Hi bob,

    Both test and loop back bits have been set in my code.

  • Do you have access to an EK-TM4C1294XL evaluation board? I have attached a CCS7 project that does the CAN loopback. It was designed for the EK-TM4C1294XL in that it uses UART0 to print messages to the terminal and configures CAN1 (PB0 and PB1) for loopback. You can "Import" this project into CCS and see how the TivaWare functions are used to setup, read and write to the CAN module.

    /cfs-file/__key/communityserver-discussions-components-files/908/CanLoopback.zip

  • Hi Bob,

    After going through your sample code, I manage to get it work! Thanks!