Hi
I am using the simple_tx code provided in the LM4F232 evaluation kit for testing the CAN functionality of the board. I am using the graphics display for debugging. I am using port E pins 4 and 5 for CAN0 functionality. i have also added the CANIntHandler in the startup code. i am getting the following errors in the CAN interrupt handler
(i have used #1 and #2 to indicate the error code location)
- #1 = 0x8000
-#2 = 0x63
and it doesnt come out of the interrupt.
i have interconnected the pins 4 and 5 using a wire.
when the wire is shaken #2 becomes 0xe2 and comes out of the interrupt.
Kindly help me understand what i am doing wrong with this setup.
Thank you
Richin Johns
//*****************************************************************************
//
// simple_tx.c - Example demonstrating simple CAN message transmission.
//
//
//*****************************************************************************
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "driverlib/can.h"
#include "driverlib/interrupt.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "grlib/grlib.h"
#include "drivers/cfal96x64x16.h"
#include "utils/ustdlib.h"
//#include "driverlib/debug.h"
//#include "driverlib/systick.h"
//*****************************************************************************
//
// A counter that keeps track of the number of times the TX interrupt has
// occurred, which should match the number of TX messages that were sent.
//
//*****************************************************************************
volatile unsigned long g_ulMsgCount = 0;
//*****************************************************************************
//
// A flag to indicate that some transmission error occurred.
//
//*****************************************************************************
volatile unsigned long g_bErrFlag = 0;
volatile unsigned long g_bMsgObjSent = 0;
//*****************************************************************************
//
// This function sets up Graphics Display to be used for displaying information
// as the example is running.
//
//*****************************************************************************
char disp_buffer[20];
tContext sContext;
unsigned char ucXCenter;
void
InitDisplay(void)
{
//
// Initialize the display driver.
//
CFAL96x64x16Init();
//
// Initialize the graphics context.
//
GrContextInit(&sContext, &g_sCFAL96x64x16);
GrContextForegroundSet(&sContext, ClrWhite);
GrContextFontSet(&sContext, g_pFontFixed6x8);
ucXCenter = GrContextDpyWidthGet(&sContext) / 2;
}
//*****************************************************************************
//
// This function prints some information about the CAN message to the
// graphics display for information purposes only.
//
//*****************************************************************************
void
DisplayInfo(char * contents, unsigned char ucX, unsigned char ucY)
{
GrStringDraw(&sContext, contents, -1, ucX, ucY, true);
}
//*****************************************************************************
//
// This function is the interrupt handler for the CAN peripheral. It checks
// for the cause of the interrupt, and maintains a count of all messages that
// have been transmitted.
//
//*****************************************************************************
void
CANIntHandler(void)
{
unsigned long ulStatus;
GrStringDraw(&sContext, "In INT", -1, 10, 14, true);
//
// Read the CAN interrupt status to find the cause of the interrupt
//
ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
usnprintf(disp_buffer, sizeof(disp_buffer), "Error = %x", ulStatus);
DisplayInfo(disp_buffer, 10, 44); <-------------------------------------- #1
//
// If the cause is a controller status interrupt, then get the status
//
if(ulStatus == CAN_INT_INTID_STATUS)
{
//
// Read the controller status. This will return a field of status
// error bits that can indicate various errors. Error processing
// is not done in this example for simplicity. Refer to the
// API documentation for details about the error status bits.
// The act of reading this status will clear the interrupt. If the
// CAN peripheral is not connected to a CAN bus with other CAN devices
// present, then errors will occur and will be indicated in the
// controller status.
//
ulStatus = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
usnprintf(disp_buffer, sizeof(disp_buffer), "Error = %x", ulStatus); <--------------#2
if(ulStatus == CAN_STATUS_BUS_OFF){
DisplayInfo("1", 10, 54);
}
else if(ulStatus == CAN_STATUS_EWARN){
DisplayInfo("2", 10, 54);
}
else if(ulStatus == CAN_STATUS_EPASS){
DisplayInfo("3", 10, 54);
}
else if(ulStatus == CAN_STATUS_RXOK){
DisplayInfo("4", 10, 54);
}
else if(ulStatus == CAN_STATUS_TXOK){
DisplayInfo("5", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_MSK){
DisplayInfo("6", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_NONE){
DisplayInfo("7", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_STUFF){
DisplayInfo("8", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_FORM){
DisplayInfo("9", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_ACK){
DisplayInfo("10", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_BIT1){
DisplayInfo("11", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_BIT0){
DisplayInfo("12", 10, 54);
}
else if(ulStatus == CAN_STATUS_LEC_CRC){
DisplayInfo("13", 10, 54);
}
else{
//UARTprintf("rage\n");
DisplayInfo(disp_buffer, 10, 54);
}
//
// Set a flag to indicate some errors may have occurred.
//
g_bErrFlag = 1;
}
//
// Check if the cause is message object 1, which what we are using for
// sending messages.
//
else if(ulStatus == 1)
{
//GrStringDraw(&sContext, "Msg TX'ing", -1, 10, 54, true);
DisplayInfo("Msg TX'ing", 10, 54);
//
// Getting to this point means that the TX interrupt occurred on
// message object 1, and the message TX is complete. Clear the
// message object interrupt.
//
CANIntClear(CAN0_BASE, 1);
//
// Increment a counter to keep track of how many messages have been
// sent. In a real application this could be used to set flags to
// indicate when a message is sent.
//
g_ulMsgCount++;
//
// Since the message was sent, clear any error flags.
//
g_bErrFlag = 0;
g_bMsgObjSent = 1;
}
//
// Otherwise, something unexpected caused the interrupt. This should
// never happen.
//
else
{
//
// Spurious interrupt handling can go here.
//
//UARTprintf("other\n");
DisplayInfo("Not In INT", 10, 14);
}
}
//*****************************************************************************
//
// This function sets up CAN Pins for CAN Rx and CAN Tx operation with dynamic
// interrupt handling enabled.
//
//*****************************************************************************
void
CAN_Initialize(void)
{
//
// For this example CAN0 is used with RX and TX pins on port E4 and E5.
// The actual port and pins used may be different on your part, consult
// the data sheet for more information.
// GPIO port D needs to be enabled so these pins can be used.
// TODO: change this to whichever GPIO port you are using
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
//
// Configure the GPIO pin muxing to select CAN0 functions for these pins.
// This step selects which alternate function is available for these pins.
// This is necessary if your part supports GPIO pin function muxing.
// Consult the data sheet to see which functions are allocated per pin.
// TODO: change this to select the port/pin you are using
//
GPIOPinConfigure(GPIO_PE4_CAN0RX);
GPIOPinConfigure(GPIO_PE5_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.
// TODO: change this to match the port/pin you are using
//
GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//
// 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. In the function below,
// the call to SysCtlClockGet() is used to determine the clock rate that
// is used for clocking the CAN peripheral. This can be replaced with a
// fixed value if you know the value of the system clock, saving the extra
// function call. For some parts, the CAN peripheral is clocked by a fixed
// 8 MHz regardless of the system clock in which case the call to
// SysCtlClockGet() should be replaced with 8000000. Consult the data
// sheet for more information about CAN peripheral clocking.
//
CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
//
// 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. If you want to use dynamic
// allocation of the vector table, then you must also call CANIntRegister()
// here.
//
//CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors//?
//
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);
IntMasterEnable();
}
//*****************************************************************************
//
// This function provides a 1 milli-second delay using a simple polling method.
//
//*****************************************************************************
void delay_ms(int del)
{
del = (SysCtlClockGet()/3.0)*del/1000.0;
SysCtlDelay(del);
}
//*****************************************************************************
//
// Configure the CAN and enter a loop to transmit periodic CAN messages.
//
//*****************************************************************************
void
main(void)
{
tCANMsgObject sCANMessage;
unsigned char ucMsgData[4];
//unsigned char ucYCenter = GrContextDpyHeightGet(&sContext) / 2;
//
// Set the clocking to run directly from the external crystal/oscillator.
// TODO: The SYSCTL_XTAL_ value must be changed to match the value of the
// crystal on your board.
//
SysCtlClockSet(SYSCTL_SYSDIV_4|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
//
// Set up the graphic display to use for displaying messages.
//
InitDisplay();
//
// Set up the CAN Port-E pins 4 and 5 for Rx and Tx
//
CAN_Initialize();
//
//Display Program Name
//
DisplayInfo("CAN TX", ucXCenter - 15, 4);
//
// Initialize the message object that will be used for sending CAN
// messages. The message will be 4 bytes that will contain an incrementing
// value. Initially it will be set to 0.
//
*(unsigned long *)ucMsgData = 0;
sCANMessage.ulMsgID = 1; // CAN message ID - use 1
sCANMessage.ulMsgIDMask = 0; // no mask needed for TX
sCANMessage.ulFlags = MSG_OBJ_TX_INT_ENABLE; // enable interrupt on TX
sCANMessage.ulMsgLen = sizeof(ucMsgData); // size of message is 4
sCANMessage.pucMsgData = ucMsgData; // ptr to message content
//
// Enter loop to send messages. A new message will be sent once per
// second. The 4 bytes of message content will be treated as an unsigned
// long and incremented by one each time.
//
for(;;)
{
//
// Print a message to the display showing the message count and the
// contents of the message being sent.
//
usnprintf(disp_buffer, sizeof(disp_buffer), "0x %02X %02X %02X %02X", ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]);
DisplayInfo(disp_buffer, 10, 24);
//
// Send the CAN message using object number 1 (not the same thing as
// CAN ID, which is also 1 in this example). This function will cause
// the message to be transmitted right away.
//
g_bMsgObjSent = 0;
//CANIntClear(CAN0_BASE, CAN_INT_INTID_STATUS);
//CANIntClear(CAN0_BASE, 1);
CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
//
// Now wait 1 second before continuing
//
delay_ms(1000);
while(!g_bMsgObjSent)
{
DisplayInfo("In Loop", 10, 34);
}
DisplayInfo("Outside Loop", 10, 34);
//
// Check the error flag to see if errors occurred
//
if(g_bErrFlag)
{
DisplayInfo("error - cable connected?", 10, 34);
}
else
{
//
// If no errors then print the count of message sent
//
usnprintf(disp_buffer, sizeof(disp_buffer), "tc = %u", g_ulMsgCount);
DisplayInfo(disp_buffer, 10, 44);
}
//
// Increment the value in the message data.
//
(*(unsigned long *)ucMsgData)++;
}
//
// Return no errors
//
//return(0);
}