//*****************************************************************************
//
// can.c - Driver for the CAN module.
//
// Copyright (c) 2006-2020 Texas Instruments Incorporated.  All rights reserved.
// Software License Agreement
// 
//   Redistribution and use in source and binary forms, with or without
//   modification, are permitted provided that the following conditions
//   are met:
// 
//   Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the  
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
// This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
//
//*****************************************************************************

//*****************************************************************************
//
//! \addtogroup can_api
//! @{
//
//*****************************************************************************

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_types.h"
#include "driverlib/can.h"
#include "driverlib/debug.h"
#include "driverlib/interrupt.h"

//*****************************************************************************
//
// This is the maximum number that can be stored as an 11bit Message
// identifier.
//
//*****************************************************************************
#define CAN_MAX_11BIT_MSG_ID    0x7ff

//*****************************************************************************
//
// The maximum CAN bit timing divisor is 19.
//
//*****************************************************************************
#define CAN_MAX_BIT_DIVISOR     19

//*****************************************************************************
//
// The minimum CAN bit timing divisor is 4.
//
//*****************************************************************************
#define CAN_MIN_BIT_DIVISOR     4

//*****************************************************************************
//
// The maximum CAN pre-divisor is 1024.
//
//*****************************************************************************
#define CAN_MAX_PRE_DIVISOR     1024

//*****************************************************************************
//
// The minimum CAN pre-divisor is 1.
//
//*****************************************************************************
#define CAN_MIN_PRE_DIVISOR     1

//*****************************************************************************
//
// Converts a set of CAN bit timing values into the value that needs to be
// programmed into the CAN_BIT register to achieve those timings.
//
//*****************************************************************************
#define CAN_BIT_VALUE(seg1, seg2, sjw)                                        \
                                ((((seg1 - 1) << CAN_BIT_TSEG1_S) &           \
                                  CAN_BIT_TSEG1_M) |                          \
                                 (((seg2 - 1) << CAN_BIT_TSEG2_S) &           \
                                  CAN_BIT_TSEG2_M) |                          \
                                 (((sjw - 1) << CAN_BIT_SJW_S) &              \
                                  CAN_BIT_SJW_M))

//*****************************************************************************
//
// This table is used by the CANBitRateSet() API as the register defaults for
// the bit timing values.
//
//*****************************************************************************
static const uint16_t g_ui16CANBitValues[] =
{
    CAN_BIT_VALUE(2, 1, 1),     // 4 clocks/bit
    CAN_BIT_VALUE(3, 1, 1),     // 5 clocks/bit
    CAN_BIT_VALUE(3, 2, 2),     // 6 clocks/bit
    CAN_BIT_VALUE(4, 2, 2),     // 7 clocks/bit
    CAN_BIT_VALUE(4, 3, 3),     // 8 clocks/bit
    CAN_BIT_VALUE(5, 3, 3),     // 9 clocks/bit
    CAN_BIT_VALUE(5, 4, 4),     // 10 clocks/bit
    CAN_BIT_VALUE(6, 4, 4),     // 11 clocks/bit
    CAN_BIT_VALUE(6, 5, 4),     // 12 clocks/bit
    CAN_BIT_VALUE(7, 5, 4),     // 13 clocks/bit
    CAN_BIT_VALUE(7, 6, 4),     // 14 clocks/bit
    CAN_BIT_VALUE(8, 6, 4),     // 15 clocks/bit
    CAN_BIT_VALUE(8, 7, 4),     // 16 clocks/bit
    CAN_BIT_VALUE(9, 7, 4),     // 17 clocks/bit
    CAN_BIT_VALUE(9, 8, 4),     // 18 clocks/bit
    CAN_BIT_VALUE(10, 8, 4)     // 19 clocks/bit
};

//*****************************************************************************
//
//! \internal
//! Checks a CAN base address.
//!
//! \param ui32Base is the base address of the CAN controller.
//!
//! This function determines if a CAN controller base address is valid.
//!
//! \return Returns \b true if the base address is valid and \b false
//! otherwise.
//
//*****************************************************************************
#ifdef DEBUG
static bool
_CANBaseValid(uint32_t ui32Base)
{
    return((ui32Base == CAN0_BASE) || (ui32Base == CAN1_BASE));
}
#endif

//*****************************************************************************
//
//! Returns the CAN controller interrupt number.
//!
//! \param ui32Base is the base address of the selected CAN controller
//!
//! This function returns the interrupt number for the CAN module with the base
//! address passed in the \e ui32Base parameter.
//!
//! \return Returns a CAN interrupt number or 0 if the interrupt does not
//! exist.
//
//*****************************************************************************
static uint_fast8_t
_CANIntNumberGet(uint32_t ui32Base)
{
    uint_fast8_t ui8Int;

    ASSERT((ui32Base == CAN0_BASE) || (ui32Base == CAN1_BASE));

    ui8Int = 0;

    //
    // Find the valid interrupt number for this CAN controller.
    //
    if(CLASS_IS_TM4C123)
    {
        if(ui32Base == CAN0_BASE)
        {
            ui8Int = INT_CAN0_TM4C123;
        }
        else if(ui32Base == CAN1_BASE)
        {
            ui8Int = INT_CAN1_TM4C123;
        }
    }
    else if(CLASS_IS_TM4C129)
    {
        if(ui32Base == CAN0_BASE)
        {
            ui8Int = INT_CAN0_TM4C129;
        }
        else if(ui32Base == CAN1_BASE)
        {
            ui8Int = INT_CAN1_TM4C129;
        }
    }

    return(ui8Int);
}

//*****************************************************************************
//
//! \internal
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pui8Data is a pointer to the data to be written out to the CAN
//! controller's data registers.
//! \param pui32Register is an uint32_t pointer to the first register of the
//! CAN controller's data registers.  For example, in order to use the IF1
//! register set on CAN controller 0, the value would be: \b CAN0_BASE \b +
//! \b CAN_O_IF1DA1.
//! \param iSize is the number of bytes to copy into the CAN controller.
//!
//! This function takes the steps necessary to copy data from a contiguous
//! buffer in memory into the non-contiguous data registers used by the CAN
//! controller.  This function is rarely used outside of the CANMessageSet()
//! function.
//!
//! \return None.
//
//*****************************************************************************
static void
_CANDataRegWrite(uint8_t *pui8Data, uint32_t *pui32Register, uint32_t ui32Size)
{
    uint32_t ui32Idx, ui32Value;

    //
    // Loop always copies 1 or 2 bytes per iteration.
    //
    for(ui32Idx = 0; ui32Idx < ui32Size; )
    {
        //
        // Write out the data 16 bits at a time since this is how the registers
        // are aligned in memory.
        //
        ui32Value = pui8Data[ui32Idx++];

        //
        // Only write the second byte if needed otherwise the value is zero.
        //
        if(ui32Idx < ui32Size)
        {
            ui32Value |= (pui8Data[ui32Idx++] << 8);
        }

        HWREG(pui32Register++) = ui32Value;
    }
}

//*****************************************************************************
//
//! \internal
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pui8Data is a pointer to the location to store the data read from
//! the CAN controller's data registers.
//! \param pui32Register is an uint32_t pointer to the first register of the
//! CAN controller's data registers.  For example, in order to use the IF1
//! register set on CAN controller 1, the value would be: \b CAN0_BASE \b +
//! \b CAN_O_IF1DA1.
//! \param iSize is the number of bytes to copy from the CAN controller.
//!
//! This function takes the steps necessary to copy data to a contiguous buffer
//! in memory from the non-contiguous data registers used by the CAN
//! controller.  This function is rarely used outside of the CANMessageGet()
//! function.
//!
//! \return None.
//
//*****************************************************************************
static void
_CANDataRegRead(uint8_t *pui8Data, uint32_t *pui32Register, uint32_t ui32Size)
{
    uint32_t ui32Idx, ui32Value;

    //
    // Loop always copies 1 or 2 bytes per iteration.
    //
    for(ui32Idx = 0; ui32Idx < ui32Size; )
    {
        //
        // Read out the data 16 bits at a time since this is how the registers
        // are aligned in memory.
        //
        ui32Value = HWREG(pui32Register++);

        //
        // Store the first byte.
        //
        pui8Data[ui32Idx++] = (uint8_t)ui32Value;

        //
        // Only read the second byte if needed.
        //
        if(ui32Idx < ui32Size)
        {
            pui8Data[ui32Idx++] = (uint8_t)(ui32Value >> 8);
        }
    }
}

//*****************************************************************************
//
//! Initializes the CAN controller after reset.
//!
//! \param ui32Base is the base address of the CAN controller.
//!
//! After reset, the CAN controller is left in the disabled state.  However,
//! the memory used for message objects contains undefined values and must be
//! cleared prior to enabling the CAN controller the first time.  This prevents
//! unwanted transmission or reception of data before the message objects are
//! configured.  This function must be called before enabling the controller
//! the first time.
//!
//! \return None.
//
//*****************************************************************************
void
CANInit(uint32_t ui32Base)
{
    uint32_t ui32Msg;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Place CAN controller in init state, regardless of previous state.  This
    // puts controller in idle, and allow the message object RAM to be
    // programmed.
    //
    HWREG(ui32Base + CAN_O_CTL) = CAN_CTL_INIT;

    //
    // Wait for busy bit to clear
    //
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // Clear the message value bit in the arbitration register.  This indicates
    // the message is not valid and is a "safe" condition to leave the message
    // object.  The same arb reg is used to program all the message objects.
    //
    HWREG(ui32Base + CAN_O_IF1CMSK) = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
                                       CAN_IF1CMSK_CONTROL);
    HWREG(ui32Base + CAN_O_IF1ARB2) = 0;
    HWREG(ui32Base + CAN_O_IF1MCTL) = 0;

    //
    // Loop through to program all 32 message objects
    //
    for(ui32Msg = 1; ui32Msg <= 32; ui32Msg++)
    {
        //
        // Wait for busy bit to clear
        //
        while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
        {
        }

        //
        // Initiate programming the message object
        //
        HWREG(ui32Base + CAN_O_IF1CRQ) = ui32Msg;
    }

    //
    // Make sure that the interrupt and new data flags are updated for the
    // message objects.
    //
    HWREG(ui32Base + CAN_O_IF1CMSK) = (CAN_IF1CMSK_NEWDAT |
                                       CAN_IF1CMSK_CLRINTPND);

    //
    // Loop through to program all 32 message objects
    //
    for(ui32Msg = 1; ui32Msg <= 32; ui32Msg++)
    {
        //
        // Wait for busy bit to clear.
        //
        while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
        {
        }

        //
        // Initiate programming the message object
        //
        HWREG(ui32Base + CAN_O_IF1CRQ) = ui32Msg;
    }

    //
    // Acknowledge any pending status interrupts.
    //
    HWREG(ui32Base + CAN_O_STS);
}

//*****************************************************************************
//
//! Enables the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller to enable.
//!
//! Enables the CAN controller for message processing.  Once enabled, the
//! controller automatically transmits any pending frames, and processes any
//! received frames.  The controller can be stopped by calling CANDisable().
//! Prior to calling CANEnable(), CANInit() must have been called to
//! initialize the controller and the CAN bus clock must be configured by
//! calling CANBitTimingSet().
//!
//! \return None.
//
//*****************************************************************************
void
CANEnable(uint32_t ui32Base)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Clear the init bit in the control register.
    //
    HWREG(ui32Base + CAN_O_CTL) &= ~CAN_CTL_INIT;
}

//*****************************************************************************
//
//! Disables the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller to disable.
//!
//! Disables the CAN controller for message processing.  When disabled, the
//! controller no longer automatically processes data on the CAN bus.  The
//! controller can be restarted by calling CANEnable().  The state of the CAN
//! controller and the message objects in the controller are left as they were
//! before this call was made.
//!
//! \return None.
//
//*****************************************************************************
void
CANDisable(uint32_t ui32Base)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Set the init bit in the control register.
    //
    HWREG(ui32Base + CAN_O_CTL) |= CAN_CTL_INIT;
}

//*****************************************************************************
//
//! Reads the current settings for the CAN controller bit timing.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param psClkParms is a pointer to a structure to hold the timing
//! parameters.
//!
//! This function reads the current configuration of the CAN controller bit
//! clock timing and stores the resulting information in the structure
//! supplied by the caller.  Refer to CANBitTimingSet() for the meaning of the
//! values that are returned in the structure pointed to by \e psClkParms.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingGet(uint32_t ui32Base, tCANBitClkParms *psClkParms)
{
    uint32_t ui32BitReg;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT(psClkParms);

    //
    // Read out all the bit timing values from the CAN controller registers.
    //
    ui32BitReg = HWREG(ui32Base + CAN_O_BIT);

    //
    // Set the phase 2 segment.
    //
    psClkParms->ui32Phase2Seg =
        ((ui32BitReg & CAN_BIT_TSEG2_M) >> CAN_BIT_TSEG2_S) + 1;

    //
    // Set the phase 1 segment.
    //
    psClkParms->ui32SyncPropPhase1Seg =
        ((ui32BitReg & CAN_BIT_TSEG1_M) >> CAN_BIT_TSEG1_S) + 1;

    //
    // Set the synchronous jump width.
    //
    psClkParms->ui32SJW = ((ui32BitReg & CAN_BIT_SJW_M) >> CAN_BIT_SJW_S) + 1;

    //
    // Set the pre-divider for the CAN bus bit clock.
    //
    psClkParms->ui32QuantumPrescaler =
        ((ui32BitReg & CAN_BIT_BRP_M) |
         ((HWREG(ui32Base + CAN_O_BRPE) & CAN_BRPE_BRPE_M) << 6)) + 1;
}

//*****************************************************************************
//
//! Sets the CAN bit timing values to a nominal setting based on a desired
//! bit rate.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32SourceClock is the system clock for the device in Hz.
//! \param ui32BitRate is the desired bit rate.
//!
//! This function sets the CAN bit timing for the bit rate passed in the
//! \e ui32BitRate parameter based on the \e ui32SourceClock parameter.
//! Because the CAN clock is based off of the system clock, the calling
//! function must pass in the source clock rate either by retrieving it from
//! SysCtlClockGet() or using a specific value in Hz.  The CAN bit timing is
//! calculated assuming a minimal amount of propagation delay, which works for
//! most cases where the network length is short.  If tighter timing
//! requirements or longer network lengths are needed, then the
//! CANBitTimingSet() function is available for full customization of all of
//! the CAN bit timing values.  Because not all bit rates can be matched
//! exactly, the bit rate is set to the value closest to the desired bit rate
//! without being higher than the \e ui32BitRate value.
//!
//! \note On some devices the source clock is fixed at 8MHz so the
//! \e ui32SourceClock must be set to 8000000.
//!
//! \return This function returns the bit rate that the CAN controller was
//! configured to use or it returns 0 to indicate that the bit rate was not
//! changed because the requested bit rate was not valid.
//!
//*****************************************************************************
uint32_t
CANBitRateSet(uint32_t ui32Base, uint32_t ui32SourceClock,
              uint32_t ui32BitRate)
{
    uint32_t ui32DesiredRatio;
    uint32_t ui32CANBits;
    uint32_t ui32PreDivide;
    uint32_t ui32RegValue;
    uint16_t ui16CANCTL;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT(ui32SourceClock);
    ASSERT(ui32BitRate);

    //
    // Calculate the desired clock rate.
    //
    ui32DesiredRatio = ui32SourceClock / ui32BitRate;

    //
    // Make sure that the ratio of CAN bit rate to processor clock is not too
    // small or too large.
    //
    ASSERT(ui32DesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));
    ASSERT(ui32DesiredRatio >= (CAN_MIN_PRE_DIVISOR * CAN_MIN_BIT_DIVISOR));

    //
    // Make sure that the Desired Ratio is not too large.  This enforces the
    // requirement that the bit rate is larger than requested.
    //
    if((ui32SourceClock / ui32DesiredRatio) > ui32BitRate)
    {
        ui32DesiredRatio += 1;
    }

    //
    // Check all possible values to find a matching value.
    //
    while(ui32DesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR))
    {
        //
        // Loop through all possible CAN bit divisors.
        //
        for(ui32CANBits = CAN_MAX_BIT_DIVISOR;
            ui32CANBits >= CAN_MIN_BIT_DIVISOR; ui32CANBits--)
        {
            //
            // For a given CAN bit divisor save the pre divisor.
            //
            ui32PreDivide = ui32DesiredRatio / ui32CANBits;

            //
            // If the calculated divisors match the desired clock ratio then
            // return these bit rate and set the CAN bit timing.
            //
            if((ui32PreDivide * ui32CANBits) == ui32DesiredRatio)
            {
                //
                // Start building the bit timing value by adding the bit timing
                // in time quanta.
                //
                ui32RegValue = g_ui16CANBitValues[ui32CANBits -
                                                  CAN_MIN_BIT_DIVISOR];

                //
                // To set the bit timing register, the controller must be
                // placed in init mode (if not already), and also configuration
                // change bit enabled.  The state of the register must be
                // saved so it can be restored.
                //
                ui16CANCTL = HWREG(ui32Base + CAN_O_CTL);
                HWREG(ui32Base + CAN_O_CTL) = ui16CANCTL | CAN_CTL_INIT |
                                              CAN_CTL_CCE;

                //
                // Now add in the pre-scalar on the bit rate.
                //
                ui32RegValue |= ((ui32PreDivide - 1) & CAN_BIT_BRP_M);

                //
                // Set the clock bits in the and the lower bits of the
                // pre-scalar.
                //
                HWREG(ui32Base + CAN_O_BIT) = ui32RegValue;

                //
                // Set the divider upper bits in the extension register.
                //
                HWREG(ui32Base + CAN_O_BRPE) = ((ui32PreDivide - 1) >> 6) &
                                               CAN_BRPE_BRPE_M;

                //
                // Restore the saved CAN Control register.
                //
                HWREG(ui32Base + CAN_O_CTL) = ui16CANCTL;

                //
                // Return the computed bit rate.
                //
                return(ui32SourceClock / (ui32PreDivide * ui32CANBits));
            }
        }

        //
        // Move the divisor up one and look again.  Only in rare cases are
        // more than 2 loops required to find the value.
        //
        ui32DesiredRatio++;
    }

    //
    // A valid combination could not be found, so return 0 to indicate that the
    // bit rate was not changed.
    //
    return(0);
}

//*****************************************************************************
//
//! Configures the CAN controller bit timing.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param psClkParms points to the structure with the clock parameters.
//!
//! Configures the various timing parameters for the CAN bus bit timing:
//! Propagation segment, Phase Buffer 1 segment, Phase Buffer 2 segment, and
//! the Synchronization Jump Width.  The values for Propagation and Phase
//! Buffer 1 segments are derived from the combination
//! \e psClkParms->ui32SyncPropPhase1Seg parameter.  Phase Buffer 2 is
//! determined from the \e psClkParms->ui32Phase2Seg parameter.  These two
//! parameters, along with \e psClkParms->ui32SJW are based in units of bit
//! time quanta.  The actual quantum time is determined by the
//! \e psClkParms->ui32QuantumPrescaler value, which specifies the divisor for
//! the CAN module clock.
//!
//! The total bit time, in quanta, is the sum of the two Seg parameters,
//! as follows:
//!
//! bit_time_q = ui32SyncPropPhase1Seg + ui32Phase2Seg + 1
//!
//! Note that the Sync_Seg is always one quantum in duration, and is added
//! to derive the correct duration of Prop_Seg and Phase1_Seg.
//!
//! The equation to determine the actual bit rate is as follows:
//!
//! CAN Clock /
//! ((\e ui32SyncPropPhase1Seg + \e ui32Phase2Seg + 1) *
//! (\e ui32QuantumPrescaler))
//!
//! Thus with \e ui32SyncPropPhase1Seg = 4, \e ui32Phase2Seg = 1,
//! \e ui32QuantumPrescaler = 2 and an 8 MHz CAN clock, the bit rate is
//! (8 MHz) / ((5 + 2 + 1) * 2) or 500 Kbit/sec.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingSet(uint32_t ui32Base, tCANBitClkParms *psClkParms)
{
    uint32_t ui32BitReg, ui32SavedInit;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT(psClkParms);

    //
    // The phase 1 segment must be in the range from 2 to 16.
    //
    ASSERT((psClkParms->ui32SyncPropPhase1Seg >= 2) &&
           (psClkParms->ui32SyncPropPhase1Seg <= 16));

    //
    // The phase 2 segment must be in the range from 1 to 8.
    //
    ASSERT((psClkParms->ui32Phase2Seg >= 1) &&
           (psClkParms->ui32Phase2Seg <= 8));

    //
    // The synchronous jump windows must be in the range from 1 to 4.
    //
    ASSERT((psClkParms->ui32SJW >= 1) && (psClkParms->ui32SJW <= 4));

    //
    // The CAN clock pre-divider must be in the range from 1 to 1024.
    //
    ASSERT((psClkParms->ui32QuantumPrescaler <= 1024) &&
           (psClkParms->ui32QuantumPrescaler >= 1));

    //
    // To set the bit timing register, the controller must be placed in init
    // mode (if not already), and also configuration change bit enabled.  State
    // of the init bit must be saved so it can be restored at the end.
    //
    ui32SavedInit = HWREG(ui32Base + CAN_O_CTL);
    HWREG(ui32Base + CAN_O_CTL) = ui32SavedInit | CAN_CTL_INIT | CAN_CTL_CCE;

    //
    // Set the bit fields of the bit timing register according to the parms.
    //
    ui32BitReg = (((psClkParms->ui32Phase2Seg - 1) << CAN_BIT_TSEG2_S) &
                  CAN_BIT_TSEG2_M);
    ui32BitReg |= (((psClkParms->ui32SyncPropPhase1Seg - 1) <<
                    CAN_BIT_TSEG1_S) & CAN_BIT_TSEG1_M);
    ui32BitReg |= ((psClkParms->ui32SJW - 1) << CAN_BIT_SJW_S) & CAN_BIT_SJW_M;
    ui32BitReg |= (psClkParms->ui32QuantumPrescaler - 1) & CAN_BIT_BRP_M;
    HWREG(ui32Base + CAN_O_BIT) = ui32BitReg;

    //
    // Set the divider upper bits in the extension register.
    //
    HWREG(ui32Base + CAN_O_BRPE) =
        ((psClkParms->ui32QuantumPrescaler - 1) >> 6) & CAN_BRPE_BRPE_M;

    //
    // Clear the config change bit, and restore the init bit.
    //
    ui32SavedInit &= ~CAN_CTL_CCE;

    //
    // If Init was not set before, then clear it.
    //
    if(ui32SavedInit & CAN_CTL_INIT)
    {
        ui32SavedInit &= ~CAN_CTL_INIT;
    }

    HWREG(ui32Base + CAN_O_CTL) = ui32SavedInit;
}

//*****************************************************************************
//
//! Registers an interrupt handler for the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param pfnHandler is a pointer to the function to be called when the
//! enabled CAN interrupts occur.
//!
//! This function registers the interrupt handler in the interrupt vector
//! table, and enables CAN interrupts on the interrupt controller; specific CAN
//! interrupt sources must be enabled using CANIntEnable().  The interrupt
//! handler being registered must clear the source of the interrupt using
//! CANIntClear().
//!
//! If the application is using a static interrupt vector table stored in
//! flash, then it is not necessary to register the interrupt handler this way.
//! Instead, IntEnable() is used to enable CAN interrupts on the
//! interrupt controller.
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntRegister(uint32_t ui32Base, void (*pfnHandler)(void))
{
    uint_fast8_t ui8IntNumber;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Get the actual interrupt number for this CAN controller.
    //
    ui8IntNumber = _CANIntNumberGet(ui32Base);
    ASSERT(ui8IntNumber != 0);

    //
    // Register the interrupt handler.
    //
    IntRegister(ui8IntNumber, pfnHandler);

    //
    // Enable the CAN interrupt.
    //
    IntEnable(ui8IntNumber);
}

//*****************************************************************************
//
//! Unregisters an interrupt handler for the CAN controller.
//!
//! \param ui32Base is the base address of the controller.
//!
//! This function unregisters the previously registered interrupt handler and
//! disables the interrupt in the interrupt controller.
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntUnregister(uint32_t ui32Base)
{
    uint_fast8_t ui8IntNumber;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Get the actual interrupt number for this CAN controller.
    //
    ui8IntNumber = _CANIntNumberGet(ui32Base);
    ASSERT(ui8IntNumber != 0);

    //
    // Disable the CAN interrupt.
    //
    IntDisable(ui8IntNumber);

    //
    // Register the interrupt handler.
    //
    IntUnregister(ui8IntNumber);
}

//*****************************************************************************
//
//! Enables individual CAN controller interrupt sources.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! This function enables specific interrupt sources of the CAN controller.
//! Only enabled sources cause a processor interrupt.
//!
//! The \e ui32IntFlags parameter is the logical OR of any of the following:
//!
//! - \b CAN_INT_ERROR - a controller error condition has occurred
//! - \b CAN_INT_STATUS - a message transfer has completed, or a bus error has
//!   been detected
//! - \b CAN_INT_MASTER - allow CAN controller to generate interrupts
//!
//! In order to generate any interrupts, \b CAN_INT_MASTER must be enabled.
//! Further, for any particular transaction from a message object to generate
//! an interrupt, that message object must have interrupts enabled (see
//! CANMessageSet()).  \b CAN_INT_ERROR generates an interrupt if the
//! controller enters the ``bus off'' condition, or if the error counters reach
//! a limit.  \b CAN_INT_STATUS generates an interrupt under quite a few
//! status conditions and may provide more interrupts than the application
//! needs to handle.  When an interrupt occurs, use CANIntStatus() to determine
//! the cause.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntEnable(uint32_t ui32Base, uint32_t ui32IntFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32IntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);

    //
    // Enable the specified interrupts.
    //
    HWREG(ui32Base + CAN_O_CTL) |= ui32IntFlags;
}

//*****************************************************************************
//
//! Disables individual CAN controller interrupt sources.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntFlags is the bit mask of the interrupt sources to be
//! disabled.
//!
//! Disables the specified CAN controller interrupt sources.  Only enabled
//! interrupt sources can cause a processor interrupt.
//!
//! The \e ui32IntFlags parameter has the same definition as in the
//! CANIntEnable() function.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntDisable(uint32_t ui32Base, uint32_t ui32IntFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32IntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);

    //
    // Disable the specified interrupts.
    //
    HWREG(ui32Base + CAN_O_CTL) &= ~ui32IntFlags;
}

//*****************************************************************************
//
//! Returns the current CAN controller interrupt status.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param eIntStsReg indicates which interrupt status register to read
//!
//! This function returns the value of one of two interrupt status registers.
//! The interrupt status register read is determined by the \e eIntStsReg
//! parameter, which can have one of the following values:
//!
//! - \b CAN_INT_STS_CAUSE - indicates the cause of the interrupt
//! - \b CAN_INT_STS_OBJECT - indicates pending interrupts of all message
//! objects
//!
//! \b CAN_INT_STS_CAUSE returns the value of the controller interrupt register
//! and indicates the cause of the interrupt.  The value returned is
//! \b CAN_INT_INTID_STATUS if the cause is a status interrupt.  In this case,
//! the status register is read with the CANStatusGet() function.
//! Calling this function to read the status also clears the status
//! interrupt.  If the value of the interrupt register is in the range 1-32,
//! then this indicates the number of the highest priority message object that
//! has an interrupt pending.  The message object interrupt can be cleared by
//! using the CANIntClear() function, or by reading the message using
//! CANMessageGet() in the case of a received message.  The interrupt handler
//! can read the interrupt status again to make sure all pending interrupts are
//! cleared before returning from the interrupt.
//!
//! \b CAN_INT_STS_OBJECT returns a bit mask indicating which message objects
//! have pending interrupts.  This value can be used to discover all of the
//! pending interrupts at once, as opposed to repeatedly reading the interrupt
//! register by using \b CAN_INT_STS_CAUSE.
//!
//! \return Returns the value of one of the interrupt status registers.
//
//*****************************************************************************
uint32_t
CANIntStatus(uint32_t ui32Base, tCANIntStsReg eIntStsReg)
{
    uint32_t ui32Status;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // See which status the caller is looking for.
    //
    switch(eIntStsReg)
    {
        //
        // The caller wants the global interrupt status for the CAN controller
        // specified by ui32Base.
        //
        case CAN_INT_STS_CAUSE:
        {
            ui32Status = HWREG(ui32Base + CAN_O_INT);
            break;
        }

        //
        // The caller wants the current message status interrupt for all
        // messages.
        //
        case CAN_INT_STS_OBJECT:
        {
            //
            // Read and combine both 16 bit values into one 32bit status.
            //
            ui32Status = (HWREG(ui32Base + CAN_O_MSG1INT) &
                          CAN_MSG1INT_INTPND_M);
            ui32Status |= (HWREG(ui32Base + CAN_O_MSG2INT) << 16);
            break;
        }

        //
        // Request was for unknown status so just return 0.
        //
        default:
        {
            ui32Status = 0;
            break;
        }
    }

    //
    // Return the interrupt status value
    //
    return(ui32Status);
}

//*****************************************************************************
//
//! Clears a CAN interrupt source.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32IntClr is a value indicating which interrupt source to clear.
//!
//! This function can be used to clear a specific interrupt source.  The
//! \e ui32IntClr parameter must be one of the following values:
//!
//! - \b CAN_INT_INTID_STATUS - Clears a status interrupt.
//! - 1-32 - Clears the specified message object interrupt
//!
//! It is not necessary to use this function to clear an interrupt.  This
//! function is only used if the application wants to clear an interrupt
//! source without taking the normal interrupt action.
//!
//! Normally, the status interrupt is cleared by reading the controller status
//! using CANStatusGet().  A specific message object interrupt is normally
//! cleared by reading the message object using CANMessageGet().
//!
//! \note Because there is a write buffer in the Cortex-M processor, it may
//! take several clock cycles before the interrupt source is actually cleared.
//! Therefore, it is recommended that the interrupt source be cleared early in
//! the interrupt handler (as opposed to the very last action) to avoid
//! returning from the interrupt handler before the interrupt source is
//! actually cleared.  Failure to do so may result in the interrupt handler
//! being immediately reentered (because the interrupt controller still sees
//! the interrupt source asserted).
//!
//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear()
//! are not re-entrant.  If any of these functions are used in the main
//! application code and if any of them are also used within an interrupt
//! routine, then the corresponding interrupt for that interrupt routine should
//! be disabled prior to the call for any of these functions.  The interrupt
//! can be re-enabled immediately after the function call has returned.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntClear(uint32_t ui32Base, uint32_t ui32IntClr)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32IntClr == CAN_INT_INTID_STATUS) ||
           ((ui32IntClr >= 1) && (ui32IntClr <= 32)));

    if(ui32IntClr == CAN_INT_INTID_STATUS)
    {
        //
        // Simply read and discard the status to clear the interrupt.
        //
        HWREG(ui32Base + CAN_O_STS);
    }
    else
    {
        //
        // Wait to be sure that this interface is not busy.
        //
        while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
        {
        }

        //
        // Only change the interrupt pending state by setting only the
        // CAN_IF1CMSK_CLRINTPND bit.
        //
        HWREG(ui32Base + CAN_O_IF1CMSK) = CAN_IF1CMSK_CLRINTPND;

        //
        // Send the clear pending interrupt command to the CAN controller.
        //
        HWREG(ui32Base + CAN_O_IF1CRQ) = ui32IntClr & CAN_IF1CRQ_MNUM_M;

        //
        // Wait to be sure that this interface is not busy.
        //
        while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
        {
        }
    }
}

//*****************************************************************************
//
//! Sets the CAN controller automatic retransmission behavior.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param bAutoRetry enables automatic retransmission.
//!
//! This function enables or disables automatic retransmission of messages with
//! detected errors.  If \e bAutoRetry is \b true, then automatic
//! retransmission is enabled, otherwise it is disabled.
//!
//! \return None.
//
//*****************************************************************************
void
CANRetrySet(uint32_t ui32Base, bool bAutoRetry)
{
    uint32_t ui32CtlReg;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    ui32CtlReg = HWREG(ui32Base + CAN_O_CTL);

    //
    // Conditionally set the DAR bit to enable/disable auto-retry.
    //
    if(bAutoRetry)
    {
        //
        // Clearing the DAR bit tells the controller to not disable the
        // auto-retry of messages which were not transmitted or received
        // correctly.
        //
        ui32CtlReg &= ~CAN_CTL_DAR;
    }
    else
    {
        //
        // Setting the DAR bit tells the controller to disable the auto-retry
        // of messages which were not transmitted or received correctly.
        //
        ui32CtlReg |= CAN_CTL_DAR;
    }

    HWREG(ui32Base + CAN_O_CTL) = ui32CtlReg;
}

//*****************************************************************************
//
//! Returns the current setting for automatic retransmission.
//!
//! \param ui32Base is the base address of the CAN controller.
//!
//! This function reads the current setting for automatic retransmission in the
//! CAN controller and returns it to the caller.
//!
//! \return Returns \b true if automatic retransmission is enabled, \b false
//! otherwise.
//
//*****************************************************************************
bool
CANRetryGet(uint32_t ui32Base)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Read the disable automatic retry setting from the CAN controller.
    //
    if(HWREG(ui32Base + CAN_O_CTL) & CAN_CTL_DAR)
    {
        //
        // Automatic data retransmission is not enabled.
        //
        return(false);
    }

    //
    // Automatic data retransmission is enabled.
    //
    return(true);
}

//*****************************************************************************
//
//! Reads one of the controller status registers.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param eStatusReg is the status register to read.
//!
//! This function reads a status register of the CAN controller and returns it
//! to the caller.
//! The different status registers are:
//!
//! - \b CAN_STS_CONTROL - the main controller status
//! - \b CAN_STS_TXREQUEST - bit mask of objects pending transmission
//! - \b CAN_STS_NEWDAT - bit mask of objects with new data
//! - \b CAN_STS_MSGVAL - bit mask of objects with valid configuration
//!
//! When reading the main controller status register, a pending status
//! interrupt is cleared.  This parameter is used in the interrupt
//! handler for the CAN controller if the cause is a status interrupt.  The
//! controller status register fields are as follows:
//!
//! - \b CAN_STATUS_BUS_OFF - controller is in bus-off condition
//! - \b CAN_STATUS_EWARN - an error counter has reached a limit of at least 96
//! - \b CAN_STATUS_EPASS - CAN controller is in the error passive state
//! - \b CAN_STATUS_RXOK - a message was received successfully (independent of
//!   any message filtering).
//! - \b CAN_STATUS_TXOK - a message was successfully transmitted
//! - \b CAN_STATUS_LEC_MSK - mask of last error code bits (3 bits)
//! - \b CAN_STATUS_LEC_NONE - no error
//! - \b CAN_STATUS_LEC_STUFF - stuffing error detected
//! - \b CAN_STATUS_LEC_FORM - a format error occurred in the fixed format part
//!   of a message
//! - \b CAN_STATUS_LEC_ACK - a transmitted message was not acknowledged
//! - \b CAN_STATUS_LEC_BIT1 - dominant level detected when trying to send in
//!   recessive mode
//! - \b CAN_STATUS_LEC_BIT0 - recessive level detected when trying to send in
//!   dominant mode
//! - \b CAN_STATUS_LEC_CRC - CRC error in received message
//!
//! The remaining status registers consist of 32-bit-wide bit maps to the
//! message objects.  They can be used to quickly obtain information about the
//! status of all the message objects without needing to query each one.  They
//! contain the following information:
//!
//! - \b CAN_STS_TXREQUEST - if a message object's TXRQST bit is set, a
//!   transmission is pending on that object.  The application can use this
//!   information to determine which objects are still waiting to send a
//!   message.
//! - \b CAN_STS_NEWDAT - if a message object's NEWDAT bit is set, a new
//!   message has been received in that object, and has not yet been picked up
//!   by the host application
//! - \b CAN_STS_MSGVAL - if a message object's MSGVAL bit is set, the object
//!   has a valid configuration programmed.  The host application can use this
//!   information to determine which message objects are empty/unused.
//!
//! \return Returns the value of the status register.
//
//*****************************************************************************
uint32_t
CANStatusGet(uint32_t ui32Base, tCANStsReg eStatusReg)
{
    uint32_t ui32Status;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    switch(eStatusReg)
    {
        //
        // Just return the global CAN status register since that is what was
        // requested.
        //
        case CAN_STS_CONTROL:
        {
            ui32Status = HWREG(ui32Base + CAN_O_STS);
            HWREG(ui32Base + CAN_O_STS) = ~(CAN_STS_RXOK | CAN_STS_TXOK |
                                            CAN_STS_LEC_M);
            break;
        }

        //
        // Combine the Transmit status bits into one 32bit value.
        //
        case CAN_STS_TXREQUEST:
        {
            ui32Status = HWREG(ui32Base + CAN_O_TXRQ1);
            ui32Status |= HWREG(ui32Base + CAN_O_TXRQ2) << 16;
            break;
        }

        //
        // Combine the New Data status bits into one 32bit value.
        //
        case CAN_STS_NEWDAT:
        {
            ui32Status = HWREG(ui32Base + CAN_O_NWDA1);
            ui32Status |= HWREG(ui32Base + CAN_O_NWDA2) << 16;
            break;
        }

        //
        // Combine the Message valid status bits into one 32bit value.
        //
        case CAN_STS_MSGVAL:
        {
            ui32Status = HWREG(ui32Base + CAN_O_MSG1VAL);
            ui32Status |= HWREG(ui32Base + CAN_O_MSG2VAL) << 16;
            break;
        }

        //
        // Unknown CAN status requested so return 0.
        //
        default:
        {
            ui32Status = 0;
            break;
        }
    }
    return(ui32Status);
}

//*****************************************************************************
//
//! Reads the CAN controller error counter register.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param pui32RxCount is a pointer to storage for the receive error counter.
//! \param pui32TxCount is a pointer to storage for the transmit error counter.
//!
//! This function reads the error counter register and returns the transmit and
//! receive error counts to the caller along with a flag indicating if the
//! controller receive counter has reached the error passive limit.  The values
//! of the receive and transmit error counters are returned through the
//! pointers provided as parameters.
//!
//! After this call, \e *pui32RxCount holds the current receive error count
//! and \e *pui32TxCount holds the current transmit error count.
//!
//! \return Returns \b true if the receive error count has reached the error
//! passive limit, and \b false if the error count is below the error passive
//! limit.
//
//*****************************************************************************
bool
CANErrCntrGet(uint32_t ui32Base, uint32_t *pui32RxCount,
              uint32_t *pui32TxCount)
{
    uint32_t ui32CANError;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));

    //
    // Read the current count of transmit/receive errors.
    //
    ui32CANError = HWREG(ui32Base + CAN_O_ERR);

    //
    // Extract the error numbers from the register value.
    //
    *pui32RxCount = (ui32CANError & CAN_ERR_REC_M) >> CAN_ERR_REC_S;
    *pui32TxCount = (ui32CANError & CAN_ERR_TEC_M) >> CAN_ERR_TEC_S;

    if(ui32CANError & CAN_ERR_RP)
    {
        return(true);
    }
    return(false);
}

//*****************************************************************************
//
//! Configures a message object in the CAN controller.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the object number to configure (1-32).
//! \param psMsgObject is a pointer to a structure containing message object
//! settings.
//! \param eMsgType indicates the type of message for this object.
//!
//! This function is used to configure any one of the 32 message objects in the
//! CAN controller.  A message object can be configured to be any type of CAN
//! message object as well as to use automatic transmission and reception.
//! This call also allows the message object to be configured to generate
//! interrupts on completion of message receipt or transmission.  The
//! message object can also be configured with a filter/mask so that actions
//! are only taken when a message that meets certain parameters is seen on the
//! CAN bus.
//!
//! The \e eMsgType parameter must be one of the following values:
//!
//! - \b MSG_OBJ_TYPE_TX - CAN transmit message object.
//! - \b MSG_OBJ_TYPE_TX_REMOTE - CAN transmit remote request message object.
//! - \b MSG_OBJ_TYPE_RX - CAN receive message object.
//! - \b MSG_OBJ_TYPE_RX_REMOTE - CAN receive remote request message object.
//! - \b MSG_OBJ_TYPE_RXTX_REMOTE - CAN remote frame receive remote, then
//!   transmit message object.
//!
//! The message object pointed to by \e psMsgObject must be populated by the
//! caller, as follows:
//!
//! - \e ui32MsgID - contains the message ID, either 11 or 29 bits.
//! - \e ui32MsgIDMask - mask of bits from \e ui32MsgID that must match if
//!   identifier filtering is enabled.
//! - \e ui32Flags
//!   - Set \b MSG_OBJ_TX_INT_ENABLE flag to enable interrupt on transmission.
//!   - Set \b MSG_OBJ_RX_INT_ENABLE flag to enable interrupt on receipt.
//!   - Set \b MSG_OBJ_USE_ID_FILTER flag to enable filtering based on the
//!     identifier mask specified by \e ui32MsgIDMask.
//! - \e ui32MsgLen - the number of bytes in the message data.  This parameter
//!   must be non-zero even for a remote frame; it must match the expected
//!   bytes of data in the responding data frame.
//! - \e pui8MsgData - points to a buffer containing up to 8 bytes of data for
//!   a data frame.
//!
//! \b Example: To send a data frame or remote frame (in response to a remote
//! request), take the following steps:
//!
//! -# Set \e eMsgType to \b MSG_OBJ_TYPE_TX.
//! -# Set \e psMsgObject->ui32MsgID to the message ID.
//! -# Set \e psMsgObject->ui32Flags.  Make sure to set
//!    \b MSG_OBJ_TX_INT_ENABLE to allow an interrupt to be generated when the
//!    message is sent.
//! -# Set \e psMsgObject->ui32MsgLen to the number of bytes in the data frame.
//! -# Set \e psMsgObject->pui8MsgData to point to an array containing the
//!    bytes to send in the message.
//! -# Call this function with \e ui32ObjID set to one of the 32 object
//!    buffers.
//!
//! \b Example: To receive a specific data frame, take the following steps:
//!
//! -# Set \e eMsgObjType to \b MSG_OBJ_TYPE_RX.
//! -# Set \e psMsgObject->ui32MsgID to the full message ID, or a partial mask
//!    to use partial ID matching.
//! -# Set \e psMsgObject->ui32MsgIDMask bits that are used for masking
//!    during comparison.
//! -# Set \e psMsgObject->ui32Flags as follows:
//!    - Set \b MSG_OBJ_RX_INT_ENABLE flag to be interrupted when the data
//!      frame is received.
//!    - Set \b MSG_OBJ_USE_ID_FILTER flag to enable identifier-based
//!      filtering.
//! -# Set \e psMsgObject->ui32MsgLen to the number of bytes in the expected
//!    data frame.
//! -# The buffer pointed to by \e psMsgObject->pui8MsgData is not used by this
//!    call as no data is present at the time of the call.
//! -# Call this function with \e ui32ObjID set to one of the 32 object
//!    buffers.
//!
//! If you specify a message object buffer that already contains a message
//! definition, it is overwritten.
//!
//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear()
//! are not re-entrant.  If any of these functions are used in the main
//! application code and if any of them are also used within an interrupt
//! routine, then the corresponding interrupt for that interrupt routine should
//! be disabled prior to the call for any of these functions.  The interrupt
//! can be re-enabled immediately after the function call has returned.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageSet(uint32_t ui32Base, uint32_t ui32ObjID,
              tCANMsgObject *psMsgObject, tMsgObjType eMsgType)
{
    uint16_t ui16CmdMaskReg;
    uint16_t ui16MaskReg0, ui16MaskReg1;
    uint16_t ui16ArbReg0, ui16ArbReg1;
    uint16_t ui16MsgCtrl;
    bool bTransferData;
    bool bUseExtendedID;

    bTransferData = 0;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));
    ASSERT((eMsgType == MSG_OBJ_TYPE_TX) ||
           (eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
           (eMsgType == MSG_OBJ_TYPE_RX) ||
           (eMsgType == MSG_OBJ_TYPE_RX_REMOTE) ||
           (eMsgType == MSG_OBJ_TYPE_TX_REMOTE) ||
           (eMsgType == MSG_OBJ_TYPE_RXTX_REMOTE));

    //
    // Wait for busy bit to clear
    //
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // See if we need to use an extended identifier or not.
    //
    if((psMsgObject->ui32MsgID > CAN_MAX_11BIT_MSG_ID) ||
       (psMsgObject->ui32Flags & MSG_OBJ_EXTENDED_ID))
    {
        bUseExtendedID = 1;
    }
    else
    {
        bUseExtendedID = 0;
    }

    //
    // This is always a write to the Message object as this call is setting a
    // message object.  This call always sets all size bits so it sets
    // both data bits.  The call uses the CONTROL register to set control
    // bits so this bit needs to be set as well.
    //
    ui16CmdMaskReg = (CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_DATAA |
                      CAN_IF1CMSK_DATAB | CAN_IF1CMSK_CONTROL);

    //
    // Initialize the values to a known state before filling them in based on
    // the type of message object that is being configured.
    //
    ui16ArbReg0 = 0;
    ui16ArbReg1 = 0;
    ui16MsgCtrl = 0;
    ui16MaskReg0 = 0;
    ui16MaskReg1 = 0;

    switch(eMsgType)
    {
        //
        // Transmit message object.
        //
        case MSG_OBJ_TYPE_TX:
        {
            //
            // Set the TXRQST bit and the reset the rest of the register.
            //
            ui16MsgCtrl |= CAN_IF1MCTL_TXRQST;
            ui16ArbReg1 = CAN_IF1ARB2_DIR;
            bTransferData = 1;
            break;
        }

        //
        // Transmit remote request message object
        //
        case MSG_OBJ_TYPE_TX_REMOTE:
        {
            //
            // Set the TXRQST bit and the reset the rest of the register.
            //
            ui16MsgCtrl |= CAN_IF1MCTL_TXRQST;
            ui16ArbReg1 = 0;
            break;
        }

        //
        // Receive message object.
        //
        case MSG_OBJ_TYPE_RX:
        {
            //
            // This clears the DIR bit along with everything else.  The TXRQST
            // bit was cleared by defaulting ui16MsgCtrl to 0.
            //
            ui16ArbReg1 = 0;
            break;
        }

        //
        // Receive remote request message object.
        //
        case MSG_OBJ_TYPE_RX_REMOTE:
        {
            //
            // The DIR bit is set to one for remote receivers.  The TXRQST bit
            // was cleared by defaulting ui16MsgCtrl to 0.
            //
            ui16ArbReg1 = CAN_IF1ARB2_DIR;

            //
            // Set this object so that it only indicates that a remote frame
            // was received and allow for software to handle it by sending back
            // a data frame.
            //
            ui16MsgCtrl = CAN_IF1MCTL_UMASK;

            //
            // Use the full Identifier by default.
            //
            ui16MaskReg0 = 0xffff;
            ui16MaskReg1 = 0x1fff;

            //
            // Make sure to send the mask to the message object.
            //
            ui16CmdMaskReg |= CAN_IF1CMSK_MASK;
            break;
        }

        //
        // Remote frame receive remote, with auto-transmit message object.
        //
        case MSG_OBJ_TYPE_RXTX_REMOTE:
        {
            //
            // Oddly the DIR bit is set to one for remote receivers.
            //
            ui16ArbReg1 = CAN_IF1ARB2_DIR;

            //
            // Set this object to auto answer if a matching identifier is seen.
            //
            ui16MsgCtrl = CAN_IF1MCTL_RMTEN | CAN_IF1MCTL_UMASK;

            //
            // The data to be returned needs to be filled in.
            //
            bTransferData = 1;
            break;
        }

        //
        // This case never happens due to the ASSERT statement at the
        // beginning of this function.
        //
        default:
        {
            return;
        }
    }

    //
    // Configure the Mask Registers.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_USE_ID_FILTER)
    {
        if(bUseExtendedID)
        {
            //
            // Set the 29 bits of Identifier mask that were requested.
            //
            ui16MaskReg0 = psMsgObject->ui32MsgIDMask & CAN_IF1MSK1_IDMSK_M;
            ui16MaskReg1 = ((psMsgObject->ui32MsgIDMask >> 16) &
                            CAN_IF1MSK2_IDMSK_M);
        }
        else
        {
            //
            // Lower 16 bit are unused so set them to zero.
            //
            ui16MaskReg0 = 0;

            //
            // Put the 11 bit Mask Identifier into the upper bits of the field
            // in the register.
            //
            ui16MaskReg1 = ((psMsgObject->ui32MsgIDMask << 2) &
                            CAN_IF1MSK2_IDMSK_M);
        }
    }

    //
    // If the caller wants to filter on the extended ID bit then set it.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_USE_EXT_FILTER) ==
       MSG_OBJ_USE_EXT_FILTER)
    {
        ui16MaskReg1 |= CAN_IF1MSK2_MXTD;
    }

    //
    // The caller wants to filter on the message direction field.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_USE_DIR_FILTER) ==
       MSG_OBJ_USE_DIR_FILTER)
    {
        ui16MaskReg1 |= CAN_IF1MSK2_MDIR;
    }

    if(psMsgObject->ui32Flags &
       (MSG_OBJ_USE_ID_FILTER | MSG_OBJ_USE_DIR_FILTER |
        MSG_OBJ_USE_EXT_FILTER))
    {
        //
        // Set the UMASK bit to enable using the mask register.
        //
        ui16MsgCtrl |= CAN_IF1MCTL_UMASK;

        //
        // Set the MASK bit so that this gets transferred to the Message
        // Object.
        //
        ui16CmdMaskReg |= CAN_IF1CMSK_MASK;
    }

    //
    // Set the Arb bit so that this gets transferred to the Message object.
    //
    ui16CmdMaskReg |= CAN_IF1CMSK_ARB;

    //
    // Configure the Arbitration registers.
    //
    if(bUseExtendedID)
    {
        //
        // Set the 29 bit version of the Identifier for this message object.
        //
        ui16ArbReg0 |= psMsgObject->ui32MsgID & CAN_IF1ARB1_ID_M;
        ui16ArbReg1 |= (psMsgObject->ui32MsgID >> 16) & CAN_IF1ARB2_ID_M;

        //
        // Mark the message as valid and set the extended ID bit.
        //
        ui16ArbReg1 |= CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD;
    }
    else
    {
        //
        // Set the 11 bit version of the Identifier for this message object.
        // The lower 18 bits are set to zero.
        //
        ui16ArbReg1 |= (psMsgObject->ui32MsgID << 2) & CAN_IF1ARB2_ID_M;

        //
        // Mark the message as valid.
        //
        ui16ArbReg1 |= CAN_IF1ARB2_MSGVAL;
    }

    //
    // Set the data length since this is set for all transfers.  This is also a
    // single transfer and not a FIFO transfer so set EOB bit.
    //
    ui16MsgCtrl |= (psMsgObject->ui32MsgLen & CAN_IF1MCTL_DLC_M);

    //
    // Mark this as the last entry if this is not the last entry in a FIFO.
    //
    if((psMsgObject->ui32Flags & MSG_OBJ_FIFO) == 0)
    {
        ui16MsgCtrl |= CAN_IF1MCTL_EOB;
    }

    //
    // Enable transmit interrupts if they should be enabled.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_TX_INT_ENABLE)
    {
        ui16MsgCtrl |= CAN_IF1MCTL_TXIE;
    }

    //
    // Enable receive interrupts if they should be enabled.
    //
    if(psMsgObject->ui32Flags & MSG_OBJ_RX_INT_ENABLE)
    {
        ui16MsgCtrl |= CAN_IF1MCTL_RXIE;
    }

    //
    // Write the data out to the CAN Data registers if needed.
    //
    if(bTransferData)
    {
        _CANDataRegWrite(psMsgObject->pui8MsgData,
                         (uint32_t *)(ui32Base + CAN_O_IF1DA1),
                         psMsgObject->ui32MsgLen);
    }

    //
    // Write out the registers to program the message object.
    //
    HWREG(ui32Base + CAN_O_IF1CMSK) = ui16CmdMaskReg;
    HWREG(ui32Base + CAN_O_IF1MSK1) = ui16MaskReg0;
    HWREG(ui32Base + CAN_O_IF1MSK2) = ui16MaskReg1;
    HWREG(ui32Base + CAN_O_IF1ARB1) = ui16ArbReg0;
    HWREG(ui32Base + CAN_O_IF1ARB2) = ui16ArbReg1;
    HWREG(ui32Base + CAN_O_IF1MCTL) = ui16MsgCtrl;

    //
    // Transfer the message object to the message object specified by
    // ui32ObjID.
    //
    HWREG(ui32Base + CAN_O_IF1CRQ) = ui32ObjID & CAN_IF1CRQ_MNUM_M;
}

//*****************************************************************************
//
//! Reads a CAN message from one of the message object buffers.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the object number to read (1-32).
//! \param psMsgObject points to a structure containing message object fields.
//! \param bClrPendingInt indicates whether an associated interrupt should be
//! cleared.
//!
//! This function is used to read the contents of one of the 32 message objects
//! in the CAN controller and return it to the caller.  The data returned is
//! stored in the fields of the caller-supplied structure pointed to by
//! \e psMsgObject.  The data consists of all of the parts of a CAN message,
//! plus some control and status information.
//!
//! Normally, this function is used to read a message object that has received
//! and stored a CAN message with a certain identifier.  However, this function
//! could also be used to read the contents of a message object in order to
//! load the fields of the structure in case only part of the structure must
//! be changed from a previous setting.
//!
//! When using CANMessageGet(), all of the same fields of the structure are
//! populated in the same way as when the CANMessageSet() function is used,
//! with the following exceptions:
//!
//! \e psMsgObject->ui32Flags:
//!
//! - \b MSG_OBJ_NEW_DATA indicates if this data is new since the last time it
//!   was read
//! - \b MSG_OBJ_DATA_LOST indicates that at least one message was received on
//!   this message object and not read by the host before being overwritten.
//!
//! \note This function is not re-entrant.  If it is used in both main
//! application code and in an interrupt routine, then the corresponding
//! interrupt should be disabled prior to the call for CANMessageGet().
//! The interrupt can be re-enabled immediately after the function call has
//! returned.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageGet(uint32_t ui32Base, uint32_t ui32ObjID,
              tCANMsgObject *psMsgObject, bool bClrPendingInt)
{
    uint16_t ui16CmdMaskReg;
    uint16_t ui16MaskReg0, ui16MaskReg1;
    uint16_t ui16ArbReg0, ui16ArbReg1;
    uint16_t ui16MsgCtrl;

    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32ObjID <= 32) && (ui32ObjID != 0));

    //
    // This is always a read to the Message object as this call is setting a
    // message object.
    //
    ui16CmdMaskReg = (CAN_IF1CMSK_DATAA | CAN_IF1CMSK_DATAB |
                      CAN_IF1CMSK_CONTROL | CAN_IF1CMSK_MASK |
                      CAN_IF1CMSK_ARB);

    //
    // Clear a pending interrupt and new data in a message object.
    //
    if(bClrPendingInt)
    {
        ui16CmdMaskReg |= CAN_IF1CMSK_CLRINTPND;
    }

    //
    // Set up the request for data from the message object.
    //
    HWREG(ui32Base + CAN_O_IF2CMSK) = ui16CmdMaskReg;

    //
    // Transfer the message object to the message object specified by
    // ui32ObjID.
    //
    HWREG(ui32Base + CAN_O_IF2CRQ) = ui32ObjID & CAN_IF1CRQ_MNUM_M;

    //
    // Wait for busy bit to clear
    //
    while(HWREG(ui32Base + CAN_O_IF2CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // Read out the IF Registers.
    //
    ui16MaskReg0 = HWREG(ui32Base + CAN_O_IF2MSK1);
    ui16MaskReg1 = HWREG(ui32Base + CAN_O_IF2MSK2);
    ui16ArbReg0 = HWREG(ui32Base + CAN_O_IF2ARB1);
    ui16ArbReg1 = HWREG(ui32Base + CAN_O_IF2ARB2);
    ui16MsgCtrl = HWREG(ui32Base + CAN_O_IF2MCTL);

    psMsgObject->ui32Flags = MSG_OBJ_NO_FLAGS;

    //
    // Determine if this is a remote frame by checking the TXRQST and DIR bits.
    //
    if((!(ui16MsgCtrl & CAN_IF1MCTL_TXRQST) &&
        (ui16ArbReg1 & CAN_IF1ARB2_DIR)) ||
       ((ui16MsgCtrl & CAN_IF1MCTL_TXRQST) &&
        (!(ui16ArbReg1 & CAN_IF1ARB2_DIR))))
    {
        psMsgObject->ui32Flags |= MSG_OBJ_REMOTE_FRAME;
    }

    //
    // Get the identifier out of the register, the format depends on size of
    // the mask.
    //
    if(ui16ArbReg1 & CAN_IF1ARB2_XTD)
    {
        //
        // Set the 29 bit version of the Identifier for this message object.
        //
        psMsgObject->ui32MsgID = (((ui16ArbReg1 & CAN_IF1ARB2_ID_M) << 16) |
                                  ui16ArbReg0);

        psMsgObject->ui32Flags |= MSG_OBJ_EXTENDED_ID;
    }
    else
    {
        //
        // The Identifier is an 11 bit value.
        //
        psMsgObject->ui32MsgID = (ui16ArbReg1 & CAN_IF1ARB2_ID_M) >> 2;
    }

    //
    // Indicate that we lost some data.
    //
    if(ui16MsgCtrl & CAN_IF1MCTL_MSGLST)
    {
        psMsgObject->ui32Flags |= MSG_OBJ_DATA_LOST;
    }

    //
    // Set the flag to indicate if ID masking was used.
    //
    if(ui16MsgCtrl & CAN_IF1MCTL_UMASK)
    {
        if(ui16ArbReg1 & CAN_IF1ARB2_XTD)
        {
            //
            // The Identifier Mask is assumed to also be a 29 bit value.
            //
            psMsgObject->ui32MsgIDMask =
                ((ui16MaskReg1 & CAN_IF1MSK2_IDMSK_M) << 16) | ui16MaskReg0;

            //
            // If this is a fully specified Mask and a remote frame then don't
            // set the MSG_OBJ_USE_ID_FILTER because the ID was not really
            // filtered.
            //
            if((psMsgObject->ui32MsgIDMask != 0x1fffffff) ||
               ((psMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0))
            {
                psMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER;
            }
        }
        else
        {
            //
            // The Identifier Mask is assumed to also be an 11 bit value.
            //
            psMsgObject->ui32MsgIDMask =
                (ui16MaskReg1 & CAN_IF1MSK2_IDMSK_M) >> 2;

            //
            // If this is a fully specified Mask and a remote frame then don't
            // set the MSG_OBJ_USE_ID_FILTER because the ID was not really
            // filtered.
            //
            if((psMsgObject->ui32MsgIDMask != 0x7ff) ||
               ((psMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0))
            {
                psMsgObject->ui32Flags |= MSG_OBJ_USE_ID_FILTER;
            }
        }

        //
        // Indicate if the extended bit was used in filtering.
        //
        if(ui16MaskReg1 & CAN_IF1MSK2_MXTD)
        {
            psMsgObject->ui32Flags |= MSG_OBJ_USE_EXT_FILTER;
        }

        //
        // Indicate if direction filtering was enabled.
        //
        if(ui16MaskReg1 & CAN_IF1MSK2_MDIR)
        {
            psMsgObject->ui32Flags |= MSG_OBJ_USE_DIR_FILTER;
        }
    }

    //
    // Set the interrupt flags.
    //
    if(ui16MsgCtrl & CAN_IF1MCTL_TXIE)
    {
        psMsgObject->ui32Flags |= MSG_OBJ_TX_INT_ENABLE;
    }
    if(ui16MsgCtrl & CAN_IF1MCTL_RXIE)
    {
        psMsgObject->ui32Flags |= MSG_OBJ_RX_INT_ENABLE;
    }

    //
    // See if there is new data available.
    //
    if(ui16MsgCtrl & CAN_IF1MCTL_NEWDAT)
    {
        //
        // Get the amount of data needed to be read.
        //
        psMsgObject->ui32MsgLen = (ui16MsgCtrl & CAN_IF1MCTL_DLC_M);

        //
        // Don't read any data for a remote frame, there is nothing valid in
        // that buffer anyway.
        //
        if((psMsgObject->ui32Flags & MSG_OBJ_REMOTE_FRAME) == 0)
        {
            //
            // Read out the data from the CAN registers.
            //
            _CANDataRegRead(psMsgObject->pui8MsgData,
                            (uint32_t *)(ui32Base + CAN_O_IF2DA1),
                            psMsgObject->ui32MsgLen);
        }

        //
        // Now clear out the new data flag.
        //
        HWREG(ui32Base + CAN_O_IF2CMSK) = CAN_IF1CMSK_NEWDAT;

        //
        // Transfer the message object to the message object specified by
        // ui32ObjID.
        //
        HWREG(ui32Base + CAN_O_IF2CRQ) = ui32ObjID & CAN_IF1CRQ_MNUM_M;

        //
        // Wait for busy bit to clear
        //
        while(HWREG(ui32Base + CAN_O_IF2CRQ) & CAN_IF1CRQ_BUSY)
        {
        }

        //
        // Indicate that there is new data in this message.
        //
        psMsgObject->ui32Flags |= MSG_OBJ_NEW_DATA;
    }
    else
    {
        //
        // Along with the MSG_OBJ_NEW_DATA not being set the amount of data
        // needs to be set to zero if none was available.
        //
        psMsgObject->ui32MsgLen = 0;
    }
}

//*****************************************************************************
//
//! Clears a message object so that it is no longer used.
//!
//! \param ui32Base is the base address of the CAN controller.
//! \param ui32ObjID is the message object number to disable (1-32).
//!
//! This function frees the specified message object from use.  Once a message
//! object has been ``cleared,'' it no longer automatically sends or receives
//! messages, nor does it generate interrupts.
//!
//! \note The functions CANIntClear(), CANMessageSet(), and CANMessageClear()
//! are not re-entrant.  If any of these functions are used in the main
//! application code and if any of them are also used within an interrupt
//! routine, then the corresponding interrupt for that interrupt routine should
//! be disabled prior to the call for any of these functions.  The interrupt
//! can be re-enabled immediately after the function call has returned.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageClear(uint32_t ui32Base, uint32_t ui32ObjID)
{
    //
    // Check the arguments.
    //
    ASSERT(_CANBaseValid(ui32Base));
    ASSERT((ui32ObjID >= 1) && (ui32ObjID <= 32));

    //
    // Wait for busy bit to clear
    //
    while(HWREG(ui32Base + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // Clear the message value bit in the arbitration register.  This indicates
    // the message is not valid.
    //
    HWREG(ui32Base + CAN_O_IF1CMSK) = CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB;
    HWREG(ui32Base + CAN_O_IF1ARB1) = 0;
    HWREG(ui32Base + CAN_O_IF1ARB2) = 0;

    //
    // Initiate programming the message object
    //
    HWREG(ui32Base + CAN_O_IF1CRQ) = ui32ObjID & CAN_IF1CRQ_MNUM_M;
}

//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************
