text: //*****************************************************************************
  //
  // simple_tx.c - Example demonstrating simple CAN message transmission.
  //
  // Copyright (c) 2010-2012 Texas Instruments Incorporated.  All rights reserved.
  // Software License Agreement
  // 
  // Texas Instruments (TI) is supplying this software for use solely and
  // exclusively on TI's microcontroller products. The software is owned by
  // TI and/or its suppliers, and is protected under applicable copyright
  // laws. You may not combine this software with "viral" open-source
  // software in order to form a larger program.
  // 
  // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  // DAMAGES, FOR ANY REASON WHATSOEVER.
  // 
  // This is part of revision 9453 of the Stellaris Firmware Development Package.
  //
  //*****************************************************************************
  
  #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 "utils/uartstdio.h"
  
  //*****************************************************************************
  //
  //! \addtogroup can_examples_list
  //! <h1>Simple CAN TX (simple_tx)</h1>
  //!
  //! This example shows the basic setup of CAN in order to transmit messages
  //! on the CAN bus.  The CAN peripheral is configured to transmit messages
  //! with a specific CAN ID.  A message is then transmitted once per second,
  //! using a simple delay loop for timing.  The message that is sent is a 4
  //! byte message that contains an incrementing pattern.  A CAN interrupt
  //! handler is used to confirm message transmission and count the number of
  //! messages that have been sent.
  //!
  //! This example uses the following peripherals and I/O signals.  You must
  //! review these and change as needed for your own board:
  //! - CAN0 peripheral
  //! - GPIO Port D peripheral (for CAN0 pins)
  //! - CAN0RX - PD0
  //! - CAN0TX - PD1
  //!
  //! The following UART signals are configured only for displaying console
  //! messages for this example.  These are not required for operation of CAN.
  //! - GPIO port A peripheral (for UART0 pins)
  //! - UART0RX - PA0
  //! - UART0TX - PA1
  //!
  //! This example uses the following interrupt handlers.  To use this example
  //! in your own application you must add these interrupt handlers to your
  //! vector table.
  //! - INT_CAN0 - CANIntHandler
  //!
  //
  //*****************************************************************************
  
  //*****************************************************************************
  //
  // 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;
  
  //*****************************************************************************
  //
  // This function sets up UART0 to be used for a console to display information
  // as the example is running.
  //
  //*****************************************************************************
  void
  InitConsole(void)
  {
      //
      // Enable GPIO port A which is used for UART0 pins
      //
      SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
  
      //
      // Configure the pin muxing for UART0 functions on port A0 and A1.
      // This step is not necessary if your part does not support pin muxing.
      //
      GPIOPinConfigure(GPIO_PA0_U0RX);
      GPIOPinConfigure(GPIO_PA1_U0TX);
  
      //
      // Select the alternate (UART) function for these pins.
      //
      GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
  
      //
      // Initialize the UART for console I/O.
      //
      UARTStdioInit(0);
  }
  
  //*****************************************************************************
  //
  // This function provides a 1 second delay using a simple polling method.
  //
  //*****************************************************************************
  void
  SimpleDelay(void)
  {
      //
      // Delay cycles for 1 second
      //
      SysCtlDelay(16000000 / 3);
  }
  
  //*****************************************************************************
  //
  // 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;
  
      //
      // Read the CAN interrupt status to find the cause of the interrupt
      //
      ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
  
      //
      // 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);
  
          //
          // 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)
      {
          //
          // 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;
      }
  
      //
      // Otherwise, something unexpected caused the interrupt.  This should
      // never happen.
      //
      else
      {
          //
          // Spurious interrupt handling can go here.
          //
      }
  }
  
  //*****************************************************************************
  //
  // Configure the CAN and enter a loop to transmit periodic CAN messages.
  //
  //*****************************************************************************
  int
  main(void)
  {
      tCANMsgObject sCANMessage;
      unsigned char ucMsgData[4];
  
      //
      // 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_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
                     SYSCTL_XTAL_16MHZ);
  
      //
      // Set up the serial console to use for displaying messages.  This is
      // just for this example program and is not needed for CAN operation.
      //
      InitConsole();
  
      //
      // For this example CAN0 is used with RX and TX pins on port D0 and D1.
      // 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_GPIOD);
  
      //
      // 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_PD0_CAN0RX);
      GPIOPinConfigure(GPIO_PD1_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_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);
  
      //
      // 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);
  
      //
      // 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 console showing the message count and the
          // contents of the message being sent.
          //
          UARTprintf("Sending msg: 0x%02X %02X %02X %02X",
                     ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]);
  
          //
          // 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.
          //
          CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
  
          //
          // Now wait 1 second before continuing
          //
          SimpleDelay();
  
          //
          // Check the error flag to see if errors occurred
          //
          if(g_bErrFlag)
          {
              UARTprintf(" error - cable connected?\n");
          }
          else
          {
              //
              // If no errors then print the count of message sent
              //
              UARTprintf(" total count = %u\n", g_ulMsgCount);
          }
  
          //
          // Increment the value in the message data.
          //
          (*(unsigned long *)ucMsgData)++;
      }
  
      //
      // Return no errors
      //
      return(0);
  }
  
  