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.

TM4C1230H6PM CAN Bus TX problem

Other Parts Discussed in Thread: TM4C1230H6PM

My TM4C1230H6PM system has a CAN bus  , I am setup CAN bus on Loopback mode ,The following program only TX once, but will continue to receive a continuous repeated "ABC" CAN message , What is the problem?

compiler option :   -mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me --include_path="C:/ti/ccsv6/tools/compiler/ti-cgt-arm_5.2.2/include" --include_path="C:/ti/TivaWare_C_Series-2.1.3.156" -g --gcc --define=ccs="ccs" --define=TARGET_IS_TM4C123_RB2 --define=PART_TM4C1230H6PM --display_error_number --diag_warning=225 --diag_wrap=off

link option :-mv7M4 --code_state=16 --float_support=FPv4SPD16 --abi=eabi -me -g --gcc --define=ccs="ccs" --define=TARGET_IS_TM4C123_RB2 --define=PART_TM4C1230H6PM --display_error_number --diag_warning=225 --diag_wrap=off -z -m"HM-HSMARTS8Z.map" --heap_size=0 --stack_size=512 -i"C:/ti/ccsv6/tools/compiler/ti-cgt-arm_5.2.2/lib" -i"C:/ti/ccsv6/tools/compiler/ti-cgt-arm_5.2.2/include" --reread_libs --warn_sections --display_error_number --diag_wrap=off --xml_link_info="HM-HSMARTS8Z_linkInfo.xml" --rom_model

//*****************************************************************************
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "driverlib/fpu.h"
#include "inc/hw_memmap.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"

#include "inc/hw_can.h"
#include "driverlib/can.h"


#include "inc/hw_ints.h"
#include "inc/hw_gpio.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"

#include "driverlib/debug.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/timer.h"
#include "driverlib/uart.h"
#include "driverlib/watchdog.h"


int nCANAddr;


volatile uint32_t g_ui32RXMsgCount = 0;
volatile uint32_t g_ui32TXMsgCount = 0;

volatile bool g_bRXFlag = 0;

volatile uint32_t g_ui32ErrFlag = 0;

tCANMsgObject g_sCAN0RxMessage;
tCANMsgObject g_sCAN0TxMessage;

#define CAN_TRA_SIZE 8
#define CAN_REC_SIZE 8
uint8_t g_nTXMsgData[CAN_TRA_SIZE];
uint8_t g_nRXMsgData[CAN_REC_SIZE];


#define RXOBJECT                1
#define TXOBJECT                2


void CAN0_IntHandler(void);
void CANErrorLED(bool state)
{
 if(state)
  GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_0, 0x0);
 else
  GPIOPinWrite(GPIO_PORTE_BASE, GPIO_PIN_0, GPIO_PIN_0);
}

void CAN0_Init(void)
{
 //CAN 0 config
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) = 0x1;

 // For this example CAN0 is used with RX and TX pins on port F0 and F3.
    // GPIO port E needs to be enabled so these pins can be used.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));
    // Configure the GPIO pin muxing to select CAN0 functions for these pins.
    // This step selects which alternate function is available for these pins.
    GPIOPinConfigure(GPIO_PF0_CAN0RX);
    GPIOPinConfigure(GPIO_PF3_CAN0TX);

    // Enable the alternate function on the GPIO pins.  The above step selects
    // which alternate function is available.  This step actually enables the
    // alternate function instead of GPIO for these pins.
    GPIOPinTypeCAN(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_3);
    // The GPIO port and pins have been set up for CAN.  The CAN peripheral
    // must be enabled.
    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
    // Initialize the CAN controller
    CANInit(CAN0_BASE);

    // Set up the bit rate for the CAN bus.  This function sets up the CAN
    // bus timing for a nominal configuration.  You can achieve more control
    // over the CAN bus timing by using the function CANBitTimingSet() instead
    // of this one, if needed.
    // In this example, the CAN bus is set to 500 kHz.
    CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 250000);
//lopback
    HWREG(CAN0_BASE + CAN_O_CTL) = HWREG(CAN0_BASE + CAN_O_CTL) | CAN_CTL_TEST;
    HWREG(CAN0_BASE + CAN_O_TST) = HWREG(CAN0_BASE + CAN_O_TST) | CAN_TST_LBACK;
///

    IntMasterEnable();
    CANIntRegister(CAN0_BASE, CAN0_IntHandler);
    // Enable interrupts on the CAN peripheral.  This example uses static
    // allocation of interrupt handlers which means the name of the handler
    // is in the vector table of startup code.
    CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    // Enable the CAN interrupt on the processor (NVIC).
    IntEnable(INT_CAN0);
    // Enable the CAN for operation.
    CANEnable(CAN0_BASE);

    g_sCAN0RxMessage.ui32MsgID = nCANAddr;
    g_sCAN0RxMessage.ui32MsgIDMask = 0xFFFF;
    g_sCAN0RxMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;

    g_sCAN0RxMessage.ui32MsgLen = CAN_REC_SIZE ;
    g_sCAN0RxMessage.pui8MsgData = g_nRXMsgData;
    CANMessageSet(CAN0_BASE, RXOBJECT, &g_sCAN0RxMessage, MSG_OBJ_TYPE_RX);
}


void CAN0_IntHandler(void)
{
    uint32_t ui32Status;

    // Read the CAN interrupt status to find the cause of the interrupt
    // CAN_INT_STS_CAUSE register values
    // 0x0000        = No Interrupt Pending
    // 0x0001-0x0020 = Number of message object that caused the interrupt
    // 0x8000        = Status interrupt
    // all other numbers are reserved and have no meaning in this system
    ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
    if(ui32Status == CAN_INT_INTID_STATUS)
    {
        ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
        g_ui32ErrFlag |= ui32Status;
    }
    else if(ui32Status == RXOBJECT)
    {
     //CANIntClear(CAN0_BASE, RXOBJECT);
     g_sCAN0RxMessage.pui8MsgData = g_nRXMsgData;
        CANMessageGet(CAN0_BASE, RXOBJECT, &g_sCAN0RxMessage, 1);
        g_ui32RXMsgCount++;
        g_bRXFlag = true;
        g_ui32ErrFlag = 0;
        CANErrorLED(false);
    }
    else if(ui32Status == TXOBJECT)
    {
        CANIntClear(CAN0_BASE, TXOBJECT);
        g_ui32TXMsgCount++;
        g_ui32ErrFlag = 0;
        CANErrorLED(false);
    }
    else
    {
        // Spurious interrupt handling can go here.
    }
}

//*****************************************************************************
void CAN0_ErrorCheck(void)
{
    // CAN controller has entered a Bus Off state.
    if(g_ui32ErrFlag & CAN_STATUS_BUS_OFF)
    {
     g_ui32ErrFlag &= ~(CAN_STATUS_BUS_OFF);
     CANErrorLED(true);
    }
    // CAN controller error level has reached warning level.
    if(g_ui32ErrFlag & CAN_STATUS_EWARN)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_EWARN);
        CANErrorLED(true);
    }
    // CAN controller error level has reached error passive level.
    if(g_ui32ErrFlag & CAN_STATUS_EPASS)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_EPASS);
        CANErrorLED(true);
    }
    // A message was received successfully since the last read of this status.
    if(g_ui32ErrFlag & CAN_STATUS_RXOK)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_RXOK);
        CANErrorLED(true);
    }
    // A message was transmitted successfully since the last read of this  status.
    if(g_ui32ErrFlag & CAN_STATUS_TXOK)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_TXOK);
        CANErrorLED(true);
    }
    // This is the mask for the last error code field.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_MSK)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MSK);
        CANErrorLED(true);
    }
    // A bit stuffing error has occurred.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_STUFF)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_STUFF);
        CANErrorLED(true);
    }
    // A formatting error has occurred.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_FORM)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_FORM);
        CANErrorLED(true);
    }
    // An acknowledge error has occurred.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_ACK)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_ACK);
        CANErrorLED(true);
    }
    // The bus remained a bit level of 1 for longer than is allowed.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT1)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT1);
        CANErrorLED(true);
    }
    // The bus remained a bit level of 0 for longer than is allowed.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT0)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT0);
        CANErrorLED(true);
    }
    // A CRC error has occurred.
    if(g_ui32ErrFlag & CAN_STATUS_LEC_CRC)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_CRC);
        CANErrorLED(true);
    }
    // This is the mask for the CAN Last Error Code (LEC).
    if(g_ui32ErrFlag & CAN_STATUS_LEC_MASK)
    {
        g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MASK);
        CANErrorLED(true);
    }
    // If there are any bits still set in g_ui32ErrFlag then something unhandled
    // has happened. Print the value of g_ui32ErrFlag.
    if(g_ui32ErrFlag !=0)
    {
     CANErrorLED(true);
    }
}

bool CAN0_send(int nTxId,uint8_t *dptr, int len)
{
 if(len >8)
  return false;
 memcpy(g_nTXMsgData,dptr,len);
    g_sCAN0TxMessage.ui32MsgID = nTxId;
    g_sCAN0TxMessage.ui32MsgIDMask = 0;
    g_sCAN0TxMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
    g_sCAN0TxMessage.ui32MsgLen = len ;
    g_sCAN0TxMessage.pui8MsgData = (uint8_t *)g_nTXMsgData;
 CANMessageSet(CAN0_BASE, TXOBJECT, &g_sCAN0TxMessage, MSG_OBJ_TYPE_TX);
 return true;
}

int32_t CAN0_rec(uint8_t *dptr)
{
 if(!g_bRXFlag)
     return 0;
    g_bRXFlag = 0;
    if(g_sCAN0RxMessage.ui32Flags & MSG_OBJ_DATA_LOST)
    {
    }
    memcpy(dptr,g_nRXMsgData,CAN_REC_SIZE);
    return g_sCAN0RxMessage.ui32MsgLen;
}


void HSMARTS8Z_init()
{
    FPUEnable();
    FPULazyStackingEnable();

    SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    //
    // Check if the peripheral access is enabled.
    //
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOG));
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));

}
int main(void)
{
    volatile uint32_t ui32Loop;
    uint32_t ret;
    uint8_t str[8];
    int32_t len;
    int nRecCount=0;


    HSMARTS8Z_init();
    nCANAddr=0x06;

    CAN0_Init();
    strcpy(str,"ABC");
 CAN0_send(6,str, 3);
 while(1)
    {
      CAN0_ErrorCheck();
      len=CAN0_rec(str);
     if(len!=0)
     {
      if(str[0]=='A' && str[1]=='B' && str[2]=='C')
      {
       nRecCount++;
      }
     }

    }
}

  • Hello user627750

    If you are using TivaWare 2.1.3.156, then there is an issue with the can.c driverlib file that has been identified to be incorrectly fixed which causes repeated transmission.

    Please use the can.c as provided in the following E2E post. Do note that you would have to recompile the driverlib file and use the new driverlib file during linker phase of your project.

    e2e.ti.com/.../1997682