can.c 73.3 KB
Newer Older
qiuyiuestc's avatar
qiuyiuestc 已提交
1 2 3 4
//*****************************************************************************
//
// can.c - Driver for the CAN module.
//
qiuyiuestc's avatar
qiuyiuestc 已提交
5
// Copyright (c) 2006-2010 Texas Instruments Incorporated.  All rights reserved.
qiuyiuestc's avatar
qiuyiuestc 已提交
6 7
// Software License Agreement
// 
qiuyiuestc's avatar
qiuyiuestc 已提交
8 9 10 11 12
// 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.
qiuyiuestc's avatar
qiuyiuestc 已提交
13
// 
qiuyiuestc's avatar
qiuyiuestc 已提交
14 15 16 17 18 19
// 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.
qiuyiuestc's avatar
qiuyiuestc 已提交
20
// 
qiuyiuestc's avatar
qiuyiuestc 已提交
21
// This is part of revision 6459 of the Stellaris Peripheral Driver Library.
qiuyiuestc's avatar
qiuyiuestc 已提交
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
//
//*****************************************************************************

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

#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "inc/hw_memmap.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.
//
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
47
#define CAN_MAX_11BIT_MSG_ID    0x7ff
qiuyiuestc's avatar
qiuyiuestc 已提交
48 49 50 51 52 53

//*****************************************************************************
//
// This is used as the loop delay for accessing the CAN controller registers.
//
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
54
#define CAN_RW_DELAY            5
qiuyiuestc's avatar
qiuyiuestc 已提交
55

qiuyiuestc's avatar
qiuyiuestc 已提交
56
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
57
//
qiuyiuestc's avatar
qiuyiuestc 已提交
58
// The maximum CAN bit timing divisor is 19.
qiuyiuestc's avatar
qiuyiuestc 已提交
59
//
qiuyiuestc's avatar
qiuyiuestc 已提交
60 61
//*****************************************************************************
#define CAN_MAX_BIT_DIVISOR     19
qiuyiuestc's avatar
qiuyiuestc 已提交
62

qiuyiuestc's avatar
qiuyiuestc 已提交
63
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
64
//
qiuyiuestc's avatar
qiuyiuestc 已提交
65
// The minimum CAN bit timing divisor is 4.
qiuyiuestc's avatar
qiuyiuestc 已提交
66
//
qiuyiuestc's avatar
qiuyiuestc 已提交
67 68
//*****************************************************************************
#define CAN_MIN_BIT_DIVISOR     4
qiuyiuestc's avatar
qiuyiuestc 已提交
69

qiuyiuestc's avatar
qiuyiuestc 已提交
70
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
71 72 73
//
// The maximum CAN pre-divisor is 1024.
//
qiuyiuestc's avatar
qiuyiuestc 已提交
74 75 76 77 78 79 80 81 82
//*****************************************************************************
#define CAN_MAX_PRE_DIVISOR     1024

//*****************************************************************************
//
// The minimum CAN pre-divisor is 1.
//
//*****************************************************************************
#define CAN_MIN_PRE_DIVISOR     1
qiuyiuestc's avatar
qiuyiuestc 已提交
83

qiuyiuestc's avatar
qiuyiuestc 已提交
84
//*****************************************************************************
qiuyiuestc's avatar
qiuyiuestc 已提交
85
//
qiuyiuestc's avatar
qiuyiuestc 已提交
86 87
// 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.
qiuyiuestc's avatar
qiuyiuestc 已提交
88
//
qiuyiuestc's avatar
qiuyiuestc 已提交
89 90 91 92 93 94 95 96
//*****************************************************************************
#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))
qiuyiuestc's avatar
qiuyiuestc 已提交
97 98 99 100 101 102 103 104 105

//*****************************************************************************
//
// This table is used by the CANBitRateSet() API as the register defaults for
// the bit timing values.
//
//*****************************************************************************
static const unsigned short g_usCANBitValues[] =
{
qiuyiuestc's avatar
qiuyiuestc 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
    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
qiuyiuestc's avatar
qiuyiuestc 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
};

//*****************************************************************************
//
//! \internal
//! Checks a CAN base address.
//!
//! \param ulBase 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 tBoolean
CANBaseValid(unsigned long ulBase)
{
    return((ulBase == CAN0_BASE) || (ulBase == CAN1_BASE) ||
           (ulBase == CAN2_BASE));
}
#endif

//*****************************************************************************
//
//! \internal
//!
//! Returns the CAN controller interrupt number.
//!
//! \param ulBase is the base address of the selected CAN controller
//!
//! Given a CAN controller base address, returns the corresponding interrupt
//! number.
//!
//! This function replaces the original CANGetIntNumber() API and performs the
//! same actions.  A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return Returns a CAN interrupt number, or -1 if \e ulPort is invalid.
//
//*****************************************************************************
static long
CANIntNumberGet(unsigned long ulBase)
{
    long lIntNumber;

    //
    // Return the interrupt number for the given CAN controller.
    //
    switch(ulBase)
    {
        //
        // Return the interrupt number for CAN 0
        //
        case CAN0_BASE:
        {
            lIntNumber = INT_CAN0;
            break;
        }

        //
        // Return the interrupt number for CAN 1
        //
        case CAN1_BASE:
        {
            lIntNumber = INT_CAN1;
            break;
        }

        //
        // Return the interrupt number for CAN 2
        //
        case CAN2_BASE:
        {
            lIntNumber = INT_CAN2;
            break;
        }

        //
        // Return -1 to indicate a bad address was passed in.
        //
        default:
        {
            lIntNumber = -1;
        }
    }
    return(lIntNumber);
}

//*****************************************************************************
//
//! \internal
//!
//! Reads a CAN controller register.
//!
//! \param ulRegAddress is the full address of the CAN register to be read.
//!
//! This function performs the necessary synchronization to read from a CAN
//! controller register.
//!
//! This function replaces the original CANReadReg() API and performs the same
//! actions.  A macro is provided in <tt>can.h</tt> to map the original API to
//! this API.
//!
//! \note This function provides the delay required to access CAN registers.
//! This delay is required when accessing CAN registers directly.
//!
//! \return Returns the value read from the register.
//
//*****************************************************************************
static unsigned long
CANRegRead(unsigned long ulRegAddress)
{
    volatile int iDelay;
    unsigned long ulRetVal;
    unsigned long ulIntNumber;
    unsigned long ulReenableInts;

    //
    // Get the CAN interrupt number from the register base address.
    //
    ulIntNumber = CANIntNumberGet(ulRegAddress & 0xfffff000);

    //
    // Make sure that the CAN base address was valid.
    //
    ASSERT(ulIntNumber != (unsigned long)-1);

    //
    // Remember current state so that CAN interrupts are only re-enabled if
    // they were already enabled.
    //
    ulReenableInts = HWREG(NVIC_EN1) & (1 << (ulIntNumber - 48));

    //
    // If the CAN interrupt was enabled then disable it.
    //
    if(ulReenableInts)
    {
        IntDisable(ulIntNumber);
    }

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
266
    // Trigger the initial read to the CAN controller.  The value returned at
qiuyiuestc's avatar
qiuyiuestc 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
    // this point is not valid.
    //
    HWREG(ulRegAddress);

    //
    // This delay is necessary for the CAN have the correct data on the bus.
    //
    for(iDelay = 0; iDelay < CAN_RW_DELAY; iDelay++)
    {
    }

    //
    // Do the final read that has the valid value of the register.
    //
    ulRetVal = HWREG(ulRegAddress);

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
284
    // Enable CAN interrupts if they were enabled before this call.
qiuyiuestc's avatar
qiuyiuestc 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
    //
    if(ulReenableInts)
    {
        IntEnable(ulIntNumber);
    }

    return(ulRetVal);
}

//*****************************************************************************
//
//! \internal
//!
//! Writes a CAN controller register.
//!
//! \param ulRegAddress is the full address of the CAN register to be written.
//! \param ulRegValue is the value to write into the register specified by
//! \e ulRegAddress.
//!
//! This function takes care of the synchronization necessary to write to a
//! CAN controller register.
//!
//! This function replaces the original CANWriteReg() API and performs the same
//! actions.  A macro is provided in <tt>can.h</tt> to map the original API to
//! this API.
//!
//! \note The delays in this function are required when accessing CAN registers
//! directly.
//!
//! \return None.
//
//*****************************************************************************
static void
CANRegWrite(unsigned long ulRegAddress, unsigned long ulRegValue)
{
    volatile int iDelay;

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
323
    // Trigger the initial write to the CAN controller.  The value will not make
qiuyiuestc's avatar
qiuyiuestc 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
    // it out to the CAN controller for CAN_RW_DELAY cycles.
    //
    HWREG(ulRegAddress) = ulRegValue;

    //
    // Delay to allow the CAN controller to receive the new data.
    //
    for(iDelay = 0; iDelay < CAN_RW_DELAY; iDelay++)
    {
    }
}

//*****************************************************************************
//
//! \internal
//!
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pucData is a pointer to the data to be written out to the CAN
//! controller's data registers.
//! \param pulRegister is an unsigned long 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.
//!
//! This function replaces the original CANWriteDataReg() API and performs the
//! same actions.  A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
static void
CANDataRegWrite(unsigned char *pucData, unsigned long *pulRegister, int iSize)
{
    int iIdx;
    unsigned long ulValue;

    //
    // Loop always copies 1 or 2 bytes per iteration.
    //
    for(iIdx = 0; iIdx < iSize; )
    {

        //
        // Write out the data 16 bits at a time since this is how the registers
        // are aligned in memory.
        //
        ulValue = pucData[iIdx++];

        //
        // Only write the second byte if needed otherwise it will be zero.
        //
        if(iIdx < iSize)
        {
            ulValue |= (pucData[iIdx++] << 8);
        }
        CANRegWrite((unsigned long)(pulRegister++), ulValue);
    }
}

//*****************************************************************************
//
//! \internal
//!
//! Copies data from a buffer to the CAN Data registers.
//!
//! \param pucData is a pointer to the location to store the data read from the
//! CAN controller's data registers.
//! \param pulRegister is an unsigned long 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.
//!
//! This function replaces the original CANReadDataReg() API and performs the
//! same actions.  A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
static void
CANDataRegRead(unsigned char *pucData, unsigned long *pulRegister, int iSize)
{
    int iIdx;
    unsigned long ulValue;

    //
    // Loop always copies 1 or 2 bytes per iteration.
    //
    for(iIdx = 0; iIdx < iSize; )
    {
        //
        // Read out the data 16 bits at a time since this is how the registers
        // are aligned in memory.
        //
        ulValue = CANRegRead((unsigned long)(pulRegister++));

        //
        // Store the first byte.
        //
        pucData[iIdx++] = (unsigned char)ulValue;

        //
        // Only read the second byte if needed.
        //
        if(iIdx < iSize)
        {
            pucData[iIdx++] = (unsigned char)(ulValue >> 8);
        }
    }
}

//*****************************************************************************
//
//! Initializes the CAN controller after reset.
//!
//! \param ulBase 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(unsigned long ulBase)
{
    int iMsg;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Place CAN controller in init state, regardless of previous state.  This
    // will put controller in idle, and allow the message object RAM to be
    // programmed.
    //
    CANRegWrite(ulBase + CAN_O_CTL, CAN_CTL_INIT);

    //
    // Wait for busy bit to clear
    //
    while(CANRegRead(ulBase + 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.
    //
    CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_WRNRD | CAN_IF1CMSK_ARB |
                CAN_IF1CMSK_CONTROL);
    CANRegWrite(ulBase + CAN_O_IF1ARB2, 0);
    CANRegWrite(ulBase + CAN_O_IF1MCTL, 0);

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

        //
        // Initiate programming the message object
        //
        CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
    }

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

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

        //
        // Initiate programming the message object
        //
        CANRegWrite(ulBase + CAN_O_IF1CRQ, iMsg);
    }

    //
    // Acknowledge any pending status interrupts.
    //
    CANRegRead(ulBase + CAN_O_STS);
}

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

    //
    // Clear the init bit in the control register.
    //
    CANRegWrite(ulBase + CAN_O_CTL,
                CANRegRead(ulBase + CAN_O_CTL) & ~CAN_CTL_INIT);
}

//*****************************************************************************
//
//! Disables the CAN controller.
//!
//! \param ulBase is the base address of the CAN controller to disable.
//!
//! Disables the CAN controller for message processing.  When disabled, the
//! controller will no longer automatically process 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(unsigned long ulBase)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Set the init bit in the control register.
    //
    CANRegWrite(ulBase + CAN_O_CTL,
                CANRegRead(ulBase + CAN_O_CTL) | CAN_CTL_INIT);
}

//*****************************************************************************
//
//! Reads the current settings for the CAN controller bit timing.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pClkParms 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 pClkParms.
//!
//! This function replaces the original CANGetBitTiming() API and performs the
//! same actions.  A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingGet(unsigned long ulBase, tCANBitClkParms *pClkParms)
{
    unsigned int uBitReg;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT(pClkParms != 0);

    //
    // Read out all the bit timing values from the CAN controller registers.
    //
    uBitReg = CANRegRead(ulBase + CAN_O_BIT);

    //
    // Set the phase 2 segment.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
647 648
    pClkParms->uPhase2Seg =
        ((uBitReg & CAN_BIT_TSEG2_M) >> CAN_BIT_TSEG2_S) + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
649 650 651 652

    //
    // Set the phase 1 segment.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
653 654
    pClkParms->uSyncPropPhase1Seg =
        ((uBitReg & CAN_BIT_TSEG1_M) >> CAN_BIT_TSEG1_S) + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
655 656

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
657
    // Set the synchronous jump width.
qiuyiuestc's avatar
qiuyiuestc 已提交
658
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
659
    pClkParms->uSJW = ((uBitReg & CAN_BIT_SJW_M) >> CAN_BIT_SJW_S) + 1;
qiuyiuestc's avatar
qiuyiuestc 已提交
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681

    //
    // Set the pre-divider for the CAN bus bit clock.
    //
    pClkParms->uQuantumPrescaler =
        ((uBitReg & CAN_BIT_BRP_M) |
         ((CANRegRead(ulBase + CAN_O_BRPE) & CAN_BRPE_BRPE_M) << 6)) + 1;
}

//*****************************************************************************
//
//! This function is used to set the CAN bit timing values to a nominal setting
//! based on a desired bit rate.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulSourceClock is the system clock for the device in Hz.
//! \param ulBitRate is the desired bit rate.
//!
//! This function will set the CAN bit timing for the bit rate passed in the
//! \e ulBitRate parameter based on the \e ulSourceClock parameter.  Since the
//! CAN clock is based off of the system clock the calling function should pass
//! in the source clock rate either by retrieving it from SysCtlClockGet() or
qiuyiuestc's avatar
qiuyiuestc 已提交
682 683 684 685 686 687 688 689
//! using a specific value in Hz.  The CAN bit timing is calculated assuming a
//! minimal amount of propagation delay, which will work 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.
//! Since 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 ulBitRate value.
qiuyiuestc's avatar
qiuyiuestc 已提交
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
//!
//! \note On some devices the source clock is fixed at 8MHz so the
//! \e ulSourceClock should 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.
//!
//*****************************************************************************
unsigned long
CANBitRateSet(unsigned long ulBase, unsigned long ulSourceClock,
              unsigned long ulBitRate)
{
    unsigned long ulDesiredRatio;
    unsigned long ulCANBits;
    unsigned long ulPreDivide;
    unsigned long ulRegValue;
    unsigned short usCANCTL;

qiuyiuestc's avatar
qiuyiuestc 已提交
709 710 711 712 713
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT(ulSourceClock != 0);
qiuyiuestc's avatar
qiuyiuestc 已提交
714 715 716
    ASSERT(ulBitRate != 0);

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
717
    // Calculate the desired clock rate.
qiuyiuestc's avatar
qiuyiuestc 已提交
718 719 720 721
    //
    ulDesiredRatio = ulSourceClock / ulBitRate;

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
722 723
    // Make sure that the ratio of CAN bit rate to processor clock is not too
    // small or too large.
qiuyiuestc's avatar
qiuyiuestc 已提交
724
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
725 726
    ASSERT(ulDesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR));
    ASSERT(ulDesiredRatio >= (CAN_MIN_PRE_DIVISOR * CAN_MIN_BIT_DIVISOR));
qiuyiuestc's avatar
qiuyiuestc 已提交
727 728 729 730 731 732 733 734 735 736 737 738 739

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

    //
    // Check all possible values to find a matching value.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
740
    while(ulDesiredRatio <= (CAN_MAX_PRE_DIVISOR * CAN_MAX_BIT_DIVISOR))
qiuyiuestc's avatar
qiuyiuestc 已提交
741 742 743 744 745 746 747 748 749 750 751 752 753
    {
        //
        // Loop through all possible CAN bit divisors.
        //
        for(ulCANBits = CAN_MAX_BIT_DIVISOR; ulCANBits >= CAN_MIN_BIT_DIVISOR;
            ulCANBits--)
        {
            //
            // For a given CAN bit divisor save the pre divisor.
            //
            ulPreDivide = ulDesiredRatio / ulCANBits;

            //
qiuyiuestc's avatar
qiuyiuestc 已提交
754
            // If the calculated divisors match the desired clock ratio then
qiuyiuestc's avatar
qiuyiuestc 已提交
755 756 757 758 759 760 761 762 763 764 765 766 767
            // return these bit rate and set the CAN bit timing.
            //
            if((ulPreDivide * ulCANBits) == ulDesiredRatio)
            {
                //
                // Start building the bit timing value by adding the bit timing
                // in time quanta.
                //
                ulRegValue = g_usCANBitValues[ulCANBits - 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
qiuyiuestc's avatar
qiuyiuestc 已提交
768
                // bit enabled.  The state of the register should be saved
qiuyiuestc's avatar
qiuyiuestc 已提交
769 770 771
                // so it can be restored.
                //
                usCANCTL = CANRegRead(ulBase + CAN_O_CTL);
qiuyiuestc's avatar
qiuyiuestc 已提交
772 773
                CANRegWrite(ulBase + CAN_O_CTL,
                            usCANCTL | CAN_CTL_INIT | CAN_CTL_CCE);
qiuyiuestc's avatar
qiuyiuestc 已提交
774 775 776 777

                //
                // Now add in the pre-scalar on the bit rate.
                //
qiuyiuestc's avatar
qiuyiuestc 已提交
778
                ulRegValue |= ((ulPreDivide - 1) & CAN_BIT_BRP_M);
qiuyiuestc's avatar
qiuyiuestc 已提交
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809

                //
                // Set the clock bits in the and the lower bits of the
                // pre-scalar.
                //
                CANRegWrite(ulBase + CAN_O_BIT, ulRegValue);

                //
                // Set the divider upper bits in the extension register.
                //
                CANRegWrite(ulBase + CAN_O_BRPE,
                            ((ulPreDivide - 1) >> 6) & CAN_BRPE_BRPE_M);

                //
                // Restore the saved CAN Control register.
                //
                CANRegWrite(ulBase + CAN_O_CTL, usCANCTL);

                //
                // Return the computed bit rate.
                //
                return(ulSourceClock / ( ulPreDivide * ulCANBits));
            }
        }

        //
        // Move the divisor up one and look again.  Only in rare cases are
        // more than 2 loops required to find the value.
        //
        ulDesiredRatio++;
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
810 811 812 813 814

    //
    // A valid combination could not be found, so return 0 to indicate that the
    // bit rate was not changed.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903
    return(0);
}

//*****************************************************************************
//
//! Configures the CAN controller bit timing.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pClkParms 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 pClkParms->uSyncPropPhase1Seg parameter.  Phase Buffer 2 is determined
//! from the \e pClkParms->uPhase2Seg parameter.  These two parameters, along
//! with \e pClkParms->uSJW are based in units of bit time quanta.  The actual
//! quantum time is determined by the \e pClkParms->uQuantumPrescaler value,
//! which specifies the divisor for the CAN module clock.
//!
//! The total bit time, in quanta, will be the sum of the two Seg parameters,
//! as follows:
//!
//! bit_time_q = uSyncPropPhase1Seg + uPhase2Seg + 1
//!
//! Note that the Sync_Seg is always one quantum in duration, and will be 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 uSyncPropPhase1Seg + \e uPhase2Seg + 1) * (\e uQuantumPrescaler))
//!
//! This means that with \e uSyncPropPhase1Seg = 4, \e uPhase2Seg = 1,
//! \e uQuantumPrescaler = 2 and an 8 MHz CAN clock, that the bit rate will be
//! (8 MHz) / ((5 + 2 + 1) * 2) or 500 Kbit/sec.
//!
//! This function replaces the original CANSetBitTiming() API and performs the
//! same actions.  A macro is provided in <tt>can.h</tt> to map the original
//! API to this API.
//!
//! \return None.
//
//*****************************************************************************
void
CANBitTimingSet(unsigned long ulBase, tCANBitClkParms *pClkParms)
{
    unsigned int uBitReg;
    unsigned int uSavedInit;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT(pClkParms != 0);

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

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

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

    //
    // The CAN clock pre-divider must be in the range from 1 to 1024.
    //
    ASSERT((pClkParms->uQuantumPrescaler <= 1024) &&
           (pClkParms->uQuantumPrescaler >= 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 should be saved so it can be restored at the end.
    //
    uSavedInit = CANRegRead(ulBase + CAN_O_CTL);
    CANRegWrite(ulBase + CAN_O_CTL, uSavedInit | CAN_CTL_INIT | CAN_CTL_CCE);

    //
    // Set the bit fields of the bit timing register according to the parms.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
904 905 906 907 908
    uBitReg = (((pClkParms->uPhase2Seg - 1) << CAN_BIT_TSEG2_S) &
               CAN_BIT_TSEG2_M);
    uBitReg |= (((pClkParms->uSyncPropPhase1Seg - 1) << CAN_BIT_TSEG1_S) &
                CAN_BIT_TSEG1_M);
    uBitReg |= ((pClkParms->uSJW - 1) << CAN_BIT_SJW_S) & CAN_BIT_SJW_M;
qiuyiuestc's avatar
qiuyiuestc 已提交
909 910 911 912 913 914 915 916
    uBitReg |= (pClkParms->uQuantumPrescaler - 1) & CAN_BIT_BRP_M;
    CANRegWrite(ulBase + CAN_O_BIT, uBitReg);

    //
    // Set the divider upper bits in the extension register.
    //
    CANRegWrite(ulBase + CAN_O_BRPE,
                ((pClkParms->uQuantumPrescaler - 1) >> 6) & CAN_BRPE_BRPE_M);
qiuyiuestc's avatar
qiuyiuestc 已提交
917

qiuyiuestc's avatar
qiuyiuestc 已提交
918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598
    //
    // Clear the config change bit, and restore the init bit.
    //
    uSavedInit &= ~CAN_CTL_CCE;

    //
    // If Init was not set before, then clear it.
    //
    if(uSavedInit & CAN_CTL_INIT)
    {
        uSavedInit &= ~CAN_CTL_INIT;
    }
    CANRegWrite(ulBase + CAN_O_CTL, uSavedInit);
}

//*****************************************************************************
//
//! Registers an interrupt handler for the CAN controller.
//!
//! \param ulBase 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() should be used to enable CAN interrupts on the
//! interrupt controller.
//!
//! \sa IntRegister() for important information about registering interrupt
//! handlers.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntRegister(unsigned long ulBase, void (*pfnHandler)(void))
{
    unsigned long ulIntNumber;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Get the actual interrupt number for this CAN controller.
    //
    ulIntNumber = CANIntNumberGet(ulBase);

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

    //
    // Enable the Ethernet interrupt.
    //
    IntEnable(ulIntNumber);
}

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

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Get the actual interrupt number for this CAN controller.
    //
    ulIntNumber = CANIntNumberGet(ulBase);

    //
    // Register the interrupt handler.
    //
    IntUnregister(ulIntNumber);

    //
    // Disable the CAN interrupt.
    //
    IntDisable(ulIntNumber);
}

//*****************************************************************************
//
//! Enables individual CAN controller interrupt sources.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulIntFlags is the bit mask of the interrupt sources to be enabled.
//!
//! Enables specific interrupt sources of the CAN controller.  Only enabled
//! sources will cause a processor interrupt.
//!
//! The \e ulIntFlags 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 will generate an interrupt if the
//! controller enters the ``bus off'' condition, or if the error counters reach
//! a limit.  \b CAN_INT_STATUS will generate 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(unsigned long ulBase, unsigned long ulIntFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulIntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);

    //
    // Enable the specified interrupts.
    //
    CANRegWrite(ulBase + CAN_O_CTL,
                CANRegRead(ulBase + CAN_O_CTL) | ulIntFlags);
}

//*****************************************************************************
//
//! Disables individual CAN controller interrupt sources.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulIntFlags 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 ulIntFlags parameter has the same definition as in the
//! CANIntEnable() function.
//!
//! \return None.
//
//*****************************************************************************
void
CANIntDisable(unsigned long ulBase, unsigned long ulIntFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulIntFlags & ~(CAN_CTL_EIE | CAN_CTL_SIE | CAN_CTL_IE)) == 0);

    //
    // Disable the specified interrupts.
    //
    CANRegWrite(ulBase + CAN_O_CTL,
                CANRegRead(ulBase + CAN_O_CTL) & ~(ulIntFlags));
}

//*****************************************************************************
//
//! Returns the current CAN controller interrupt status.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param eIntStsReg indicates which interrupt status register to read
//!
//! 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.  It will be a value of
//! \b CAN_INT_INTID_STATUS if the cause is a status interrupt.  In this case,
//! the status register should be read with the CANStatusGet() function.
//! Calling this function to read the status will also clear 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 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.
//
//*****************************************************************************
unsigned long
CANIntStatus(unsigned long ulBase, tCANIntStsReg eIntStsReg)
{
    unsigned long ulStatus;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // See which status the caller is looking for.
    //
    switch(eIntStsReg)
    {
        //
        // The caller wants the global interrupt status for the CAN controller
        // specified by ulBase.
        //
        case CAN_INT_STS_CAUSE:
        {
            ulStatus = CANRegRead(ulBase + 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.
            //
            ulStatus = (CANRegRead(ulBase + CAN_O_MSG1INT) &
                        CAN_MSG1INT_INTPND_M);
            ulStatus |= (CANRegRead(ulBase + CAN_O_MSG2INT) << 16);
            break;
        }

        //
        // Request was for unknown status so just return 0.
        //
        default:
        {
            ulStatus = 0;
            break;
        }
    }
    //
    // Return the interrupt status value
    //
    return(ulStatus);
}

//*****************************************************************************
//
//! Clears a CAN interrupt source.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulIntClr is a value indicating which interrupt source to clear.
//!
//! This function can be used to clear a specific interrupt source.  The
//! \e ulIntClr parameter should 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
//! should only be 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 Since there is a write buffer in the Cortex-M3 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 (since NVIC still sees the interrupt source
//! asserted).
//!
//! \return None.
//
//*****************************************************************************
void
CANIntClear(unsigned long ulBase, unsigned long ulIntClr)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulIntClr == CAN_INT_INTID_STATUS) ||
           ((ulIntClr>=1) && (ulIntClr <=32)));

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

        //
        // Only change the interrupt pending state by setting only the
        // CAN_IF1CMSK_CLRINTPND bit.
        //
        CANRegWrite(ulBase + CAN_O_IF1CMSK, CAN_IF1CMSK_CLRINTPND);

        //
        // Send the clear pending interrupt command to the CAN controller.
        //
        CANRegWrite(ulBase + CAN_O_IF1CRQ, ulIntClr & CAN_IF1CRQ_MNUM_M);

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

//*****************************************************************************
//
//! Sets the CAN controller automatic retransmission behavior.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param bAutoRetry enables automatic retransmission.
//!
//! 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(unsigned long ulBase, tBoolean bAutoRetry)
{
    unsigned long ulCtlReg;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    ulCtlReg = CANRegRead(ulBase + 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.
        //
        ulCtlReg &= ~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.
        //
        ulCtlReg |= CAN_CTL_DAR;
    }

    CANRegWrite(ulBase + CAN_O_CTL, ulCtlReg);
}

//*****************************************************************************
//
//! Returns the current setting for automatic retransmission.
//!
//! \param ulBase is the base address of the CAN controller.
//!
//! Reads the current setting for the automatic retransmission in the CAN
//! controller and returns it to the caller.
//!
//! \return Returns \b true if automatic retransmission is enabled, \b false
//! otherwise.
//
//*****************************************************************************
tBoolean
CANRetryGet(unsigned long ulBase)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Read the disable automatic retry setting from the CAN controller.
    //
    if(CANRegRead(ulBase + 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 ulBase is the base address of the CAN controller.
//! \param eStatusReg is the status register to read.
//!
//! 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 will be cleared.  This should be 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 are 32-bit 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 TxRequest bit is set, that
//! means that a transmission is pending on that object.  The application can
//! use this to determine which objects are still waiting to send a message.
//! - \b CAN_STS_NEWDAT - if a message object's NewDat bit is set, that means
//! that 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, that means
//! it has a valid configuration programmed.  The host application can use this
//! to determine which message objects are empty/unused.
//!
//! \return Returns the value of the status register.
//
//*****************************************************************************
unsigned long
CANStatusGet(unsigned long ulBase, tCANStsReg eStatusReg)
{
    unsigned long ulStatus;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    switch(eStatusReg)
    {
        //
        // Just return the global CAN status register since that is what was
        // requested.
        //
        case CAN_STS_CONTROL:
        {
            ulStatus = CANRegRead(ulBase + CAN_O_STS);
            CANRegWrite(ulBase + 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:
        {
            ulStatus = CANRegRead(ulBase + CAN_O_TXRQ1);
            ulStatus |= CANRegRead(ulBase + CAN_O_TXRQ2) << 16;
            break;
        }

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

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

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

//*****************************************************************************
//
//! Reads the CAN controller error counter register.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param pulRxCount is a pointer to storage for the receive error counter.
//! \param pulTxCount is a pointer to storage for the transmit error counter.
//!
//! 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 *pulRxCount will hold the current receive error count
//! and \e *pulTxCount will hold 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.
//
//*****************************************************************************
tBoolean
CANErrCntrGet(unsigned long ulBase, unsigned long *pulRxCount,
              unsigned long *pulTxCount)
{
    unsigned long ulCANError;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));

    //
    // Read the current count of transmit/receive errors.
    //
    ulCANError = CANRegRead(ulBase + CAN_O_ERR);

    //
    // Extract the error numbers from the register value.
    //
    *pulRxCount = (ulCANError & CAN_ERR_REC_M) >> CAN_ERR_REC_S;
    *pulTxCount = (ulCANError & CAN_ERR_TEC_M) >> CAN_ERR_TEC_S;

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

//*****************************************************************************
//
//! Configures a message object in the CAN controller.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID is the object number to configure (1-32).
//! \param pMsgObject 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 as any type of CAN
//! message object as well as several options for 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 pMsgObject must be populated by the
//! caller, as follows:
//!
//! - \e ulMsgID - contains the message ID, either 11 or 29 bits.
//! - \e ulMsgIDMask - mask of bits from \e ulMsgID that must match if
//! identifier filtering is enabled.
//! - \e ulFlags
//!   - 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 ulMsgIDMask.
//! - \e ulMsgLen - the number of bytes in the message data.  This should be
//! non-zero even for a remote frame; it should match the expected bytes of the
//! data responding data frame.
//! - \e pucMsgData - 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 pMsgObject->ulMsgID to the message ID.
//! -# Set \e pMsgObject->ulFlags. Make sure to set \b MSG_OBJ_TX_INT_ENABLE to
//! allow an interrupt to be generated when the message is sent.
//! -# Set \e pMsgObject->ulMsgLen to the number of bytes in the data frame.
//! -# Set \e pMsgObject->pucMsgData to point to an array containing the bytes
//! to send in the message.
//! -# Call this function with \e ulObjID 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 pMsgObject->ulMsgID to the full message ID, or a partial mask to
//! use partial ID matching.
//! -# Set \e pMsgObject->ulMsgIDMask bits that should be used for masking
//! during comparison.
//! -# Set \e pMsgObject->ulFlags as follows:
qiuyiuestc's avatar
qiuyiuestc 已提交
1599
//!   - Set \b MSG_OBJ_RX_INT_ENABLE flag to be interrupted when the data frame
qiuyiuestc's avatar
qiuyiuestc 已提交
1600 1601 1602 1603
//!   is received.
//!   - Set \b MSG_OBJ_USE_ID_FILTER flag to enable identifier based filtering.
//! -# Set \e pMsgObject->ulMsgLen to the number of bytes in the expected data
//! frame.
qiuyiuestc's avatar
qiuyiuestc 已提交
1604 1605
//! -# The buffer pointed to by \e pMsgObject->pucMsgData is not used by this
//! call as no data is present at the time of the call.
qiuyiuestc's avatar
qiuyiuestc 已提交
1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
//! -# Call this function with \e ulObjID set to one of the 32 object buffers.
//!
//! If you specify a message object buffer that already contains a message
//! definition, it will be overwritten.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageSet(unsigned long ulBase, unsigned long ulObjID,
              tCANMsgObject *pMsgObject, tMsgObjType eMsgType)
{
    unsigned short usCmdMaskReg;
qiuyiuestc's avatar
qiuyiuestc 已提交
1619 1620
    unsigned short usMaskReg0, usMaskReg1;
    unsigned short usArbReg0, usArbReg1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671
    unsigned short usMsgCtrl;
    tBoolean bTransferData;
    tBoolean bUseExtendedID;

    bTransferData = 0;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulObjID <= 32) && (ulObjID != 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(CANRegRead(ulBase + CAN_O_IF1CRQ) & CAN_IF1CRQ_BUSY)
    {
    }

    //
    // See if we need to use an extended identifier or not.
    //
    if((pMsgObject->ulMsgID > CAN_MAX_11BIT_MSG_ID) ||
       (pMsgObject->ulFlags & 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 will also always set all size bits so it sets
    // both data bits.  The call will use the CONTROL register to set control
    // bits so this bit needs to be set as well.
    //
    usCmdMaskReg = (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.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
1672 1673
    usArbReg0 = 0;
    usArbReg1 = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1674
    usMsgCtrl = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1675 1676
    usMaskReg0 = 0;
    usMaskReg1 = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688

    switch(eMsgType)
    {
        //
        // Transmit message object.
        //
        case MSG_OBJ_TYPE_TX:
        {
            //
            // Set the TXRQST bit and the reset the rest of the register.
            //
            usMsgCtrl |= CAN_IF1MCTL_TXRQST;
qiuyiuestc's avatar
qiuyiuestc 已提交
1689
            usArbReg1 = CAN_IF1ARB2_DIR;
qiuyiuestc's avatar
qiuyiuestc 已提交
1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702
            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.
            //
            usMsgCtrl |= CAN_IF1MCTL_TXRQST;
qiuyiuestc's avatar
qiuyiuestc 已提交
1703
            usArbReg1 = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1704 1705 1706 1707 1708 1709 1710 1711 1712
            break;
        }

        //
        // Receive message object.
        //
        case MSG_OBJ_TYPE_RX:
        {
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1713 1714
            // This clears the DIR bit along with everything else.  The TXRQST
            // bit was cleared by defaulting usMsgCtrl to 0.
qiuyiuestc's avatar
qiuyiuestc 已提交
1715
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1716
            usArbReg1 = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726
            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
qiuyiuestc's avatar
qiuyiuestc 已提交
1727
            // was cleared by defaulting usMsgCtrl to 0.
qiuyiuestc's avatar
qiuyiuestc 已提交
1728
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1729
            usArbReg1 = CAN_IF1ARB2_DIR;
qiuyiuestc's avatar
qiuyiuestc 已提交
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740

            //
            // 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.
            //
            usMsgCtrl = CAN_IF1MCTL_UMASK;

            //
            // Use the full Identifier by default.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1741 1742
            usMaskReg0 = 0xffff;
            usMaskReg1 = 0x1fff;
qiuyiuestc's avatar
qiuyiuestc 已提交
1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758

            //
            // Make sure to send the mask to the message object.
            //
            usCmdMaskReg |= 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.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1759
            usArbReg1 = CAN_IF1ARB2_DIR;
qiuyiuestc's avatar
qiuyiuestc 已提交
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792

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

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

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

    //
    // Configure the Mask Registers.
    //
    if(pMsgObject->ulFlags & MSG_OBJ_USE_ID_FILTER)
    {
        if(bUseExtendedID)
        {
            //
            // Set the 29 bits of Identifier mask that were requested.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1793 1794
            usMaskReg0 = pMsgObject->ulMsgIDMask & CAN_IF1MSK1_IDMSK_M;
            usMaskReg1 = ((pMsgObject->ulMsgIDMask >> 16) &
qiuyiuestc's avatar
qiuyiuestc 已提交
1795 1796 1797 1798 1799 1800 1801
                            CAN_IF1MSK2_IDMSK_M);
        }
        else
        {
            //
            // Lower 16 bit are unused so set them to zero.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1802
            usMaskReg0 = 0;
qiuyiuestc's avatar
qiuyiuestc 已提交
1803 1804 1805 1806 1807

            //
            // Put the 11 bit Mask Identifier into the upper bits of the field
            // in the register.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
1808
            usMaskReg1 = ((pMsgObject->ulMsgIDMask << 2) &
qiuyiuestc's avatar
qiuyiuestc 已提交
1809 1810 1811 1812 1813 1814 1815 1816 1817 1818
                            CAN_IF1MSK2_IDMSK_M);
        }
    }

    //
    // If the caller wants to filter on the extended ID bit then set it.
    //
    if((pMsgObject->ulFlags & MSG_OBJ_USE_EXT_FILTER) ==
       MSG_OBJ_USE_EXT_FILTER)
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1819
        usMaskReg1 |= CAN_IF1MSK2_MXTD;
qiuyiuestc's avatar
qiuyiuestc 已提交
1820 1821 1822 1823 1824 1825 1826 1827
    }

    //
    // The caller wants to filter on the message direction field.
    //
    if((pMsgObject->ulFlags & MSG_OBJ_USE_DIR_FILTER) ==
       MSG_OBJ_USE_DIR_FILTER)
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
1828
        usMaskReg1 |= CAN_IF1MSK2_MDIR;
qiuyiuestc's avatar
qiuyiuestc 已提交
1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839
    }

    if(pMsgObject->ulFlags & (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.
        //
        usMsgCtrl |= CAN_IF1MCTL_UMASK;

        //
qiuyiuestc's avatar
qiuyiuestc 已提交
1840
        // Set the MASK bit so that this gets transferred to the Message Object.
qiuyiuestc's avatar
qiuyiuestc 已提交
1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857
        //
        usCmdMaskReg |= CAN_IF1CMSK_MASK;
    }

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

    //
    // Configure the Arbitration registers.
    //
    if(bUseExtendedID)
    {
        //
        // Set the 29 bit version of the Identifier for this message object.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
1858 1859
        usArbReg0 |= pMsgObject->ulMsgID & CAN_IF1ARB1_ID_M;
        usArbReg1 |= (pMsgObject->ulMsgID >> 16) & CAN_IF1ARB2_ID_M;
qiuyiuestc's avatar
qiuyiuestc 已提交
1860 1861 1862 1863

        //
        // Mark the message as valid and set the extended ID bit.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
1864
        usArbReg1 |= CAN_IF1ARB2_MSGVAL | CAN_IF1ARB2_XTD;
qiuyiuestc's avatar
qiuyiuestc 已提交
1865 1866 1867 1868 1869 1870 1871
    }
    else
    {
        //
        // Set the 11 bit version of the Identifier for this message object.
        // The lower 18 bits are set to zero.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
1872
        usArbReg1 |= (pMsgObject->ulMsgID << 2) & CAN_IF1ARB2_ID_M;
qiuyiuestc's avatar
qiuyiuestc 已提交
1873 1874 1875 1876

        //
        // Mark the message as valid.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
1877
        usArbReg1 |= CAN_IF1ARB2_MSGVAL;
qiuyiuestc's avatar
qiuyiuestc 已提交
1878 1879 1880 1881 1882 1883
    }

    //
    // 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.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
1884 1885 1886 1887 1888 1889 1890 1891 1892
    usMsgCtrl |= (pMsgObject->ulMsgLen & CAN_IF1MCTL_DLC_M);

    //
    // Mark this as the last entry if this is not the last entry in a FIFO.
    //
    if((pMsgObject->ulFlags & MSG_OBJ_FIFO) == 0)
    {
        usMsgCtrl |= CAN_IF1MCTL_EOB;
    }
qiuyiuestc's avatar
qiuyiuestc 已提交
1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923

    //
    // Enable transmit interrupts if they should be enabled.
    //
    if(pMsgObject->ulFlags & MSG_OBJ_TX_INT_ENABLE)
    {
        usMsgCtrl |= CAN_IF1MCTL_TXIE;
    }

    //
    // Enable receive interrupts if they should be enabled.
    //
    if(pMsgObject->ulFlags & MSG_OBJ_RX_INT_ENABLE)
    {
        usMsgCtrl |= CAN_IF1MCTL_RXIE;
    }

    //
    // Write the data out to the CAN Data registers if needed.
    //
    if(bTransferData)
    {
        CANDataRegWrite(pMsgObject->pucMsgData,
                        (unsigned long *)(ulBase + CAN_O_IF1DA1),
                        pMsgObject->ulMsgLen);
    }

    //
    // Write out the registers to program the message object.
    //
    CANRegWrite(ulBase + CAN_O_IF1CMSK, usCmdMaskReg);
qiuyiuestc's avatar
qiuyiuestc 已提交
1924 1925 1926 1927
    CANRegWrite(ulBase + CAN_O_IF1MSK1, usMaskReg0);
    CANRegWrite(ulBase + CAN_O_IF1MSK2, usMaskReg1);
    CANRegWrite(ulBase + CAN_O_IF1ARB1, usArbReg0);
    CANRegWrite(ulBase + CAN_O_IF1ARB2, usArbReg1);
qiuyiuestc's avatar
qiuyiuestc 已提交
1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
    CANRegWrite(ulBase + CAN_O_IF1MCTL, usMsgCtrl);

    //
    // Transfer the message object to the message object specifiec by ulObjID.
    //
    CANRegWrite(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);

    return;
}

//*****************************************************************************
//
//! Reads a CAN message from one of the message object buffers.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID is the object number to read (1-32).
//! \param pMsgObject 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 pMsgObject.  The data consists of all of the parts of a CAN message,
//! plus some control and status information.
//!
//! Normally this is used to read a message object that has received and stored
//! a CAN message with a certain identifier.  However, this 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 needs to 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 pMsgObject->ulFlags:
//!
//! - \b MSG_OBJ_NEW_DATA indicates if this is new data 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.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageGet(unsigned long ulBase, unsigned long ulObjID,
              tCANMsgObject *pMsgObject, tBoolean bClrPendingInt)
{
    unsigned short usCmdMaskReg;
qiuyiuestc's avatar
qiuyiuestc 已提交
1979 1980
    unsigned short usMaskReg0, usMaskReg1;
    unsigned short usArbReg0, usArbReg1;
qiuyiuestc's avatar
qiuyiuestc 已提交
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
    unsigned short usMsgCtrl;

    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulObjID <= 32) && (ulObjID != 0));

    //
    // This is always a read to the Message object as this call is setting a
    // message object.
    //
    usCmdMaskReg = (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)
    {
        usCmdMaskReg |= CAN_IF1CMSK_CLRINTPND;
    }

    //
    // Set up the request for data from the message object.
    //
    CANRegWrite(ulBase + CAN_O_IF2CMSK, usCmdMaskReg);

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
2010
    // Transfer the message object to the message object specified by ulObjID.
qiuyiuestc's avatar
qiuyiuestc 已提交
2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023
    //
    CANRegWrite(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);

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

    //
    // Read out the IF Registers.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
2024 2025 2026 2027
    usMaskReg0 = CANRegRead(ulBase + CAN_O_IF2MSK1);
    usMaskReg1 = CANRegRead(ulBase + CAN_O_IF2MSK2);
    usArbReg0 = CANRegRead(ulBase + CAN_O_IF2ARB1);
    usArbReg1 = CANRegRead(ulBase + CAN_O_IF2ARB2);
qiuyiuestc's avatar
qiuyiuestc 已提交
2028 2029 2030 2031 2032 2033 2034
    usMsgCtrl = CANRegRead(ulBase + CAN_O_IF2MCTL);

    pMsgObject->ulFlags = MSG_OBJ_NO_FLAGS;

    //
    // Determine if this is a remote frame by checking the TXRQST and DIR bits.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
2035 2036
    if((!(usMsgCtrl & CAN_IF1MCTL_TXRQST) && (usArbReg1 & CAN_IF1ARB2_DIR)) ||
       ((usMsgCtrl & CAN_IF1MCTL_TXRQST) && (!(usArbReg1 & CAN_IF1ARB2_DIR))))
qiuyiuestc's avatar
qiuyiuestc 已提交
2037 2038 2039 2040 2041 2042 2043 2044
    {
        pMsgObject->ulFlags |= MSG_OBJ_REMOTE_FRAME;
    }

    //
    // Get the identifier out of the register, the format depends on size of
    // the mask.
    //
qiuyiuestc's avatar
qiuyiuestc 已提交
2045
    if(usArbReg1 & CAN_IF1ARB2_XTD)
qiuyiuestc's avatar
qiuyiuestc 已提交
2046 2047 2048 2049
    {
        //
        // Set the 29 bit version of the Identifier for this message object.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
2050 2051
        pMsgObject->ulMsgID = ((usArbReg1 & CAN_IF1ARB2_ID_M) << 16) |
            usArbReg0;
qiuyiuestc's avatar
qiuyiuestc 已提交
2052 2053 2054 2055 2056 2057 2058 2059

        pMsgObject->ulFlags |= MSG_OBJ_EXTENDED_ID;
    }
    else
    {
        //
        // The Identifier is an 11 bit value.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
2060
        pMsgObject->ulMsgID = (usArbReg1 & CAN_IF1ARB2_ID_M) >> 2;
qiuyiuestc's avatar
qiuyiuestc 已提交
2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075
    }

    //
    // Indicate that we lost some data.
    //
    if(usMsgCtrl & CAN_IF1MCTL_MSGLST)
    {
        pMsgObject->ulFlags |= MSG_OBJ_DATA_LOST;
    }

    //
    // Set the flag to indicate if ID masking was used.
    //
    if(usMsgCtrl & CAN_IF1MCTL_UMASK)
    {
qiuyiuestc's avatar
qiuyiuestc 已提交
2076
        if(usArbReg1 & CAN_IF1ARB2_XTD)
qiuyiuestc's avatar
qiuyiuestc 已提交
2077 2078 2079 2080 2081
        {
            //
            // The Identifier Mask is assumed to also be a 29 bit value.
            //
            pMsgObject->ulMsgIDMask =
qiuyiuestc's avatar
qiuyiuestc 已提交
2082 2083
                ((usMaskReg1 & CAN_IF1MSK2_IDMSK_M) << 16) | usMaskReg0;

qiuyiuestc's avatar
qiuyiuestc 已提交
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
            //
            // 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((pMsgObject->ulMsgIDMask != 0x1fffffff) ||
               ((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
            {
                pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
            }
        }
        else
        {
            //
            // The Identifier Mask is assumed to also be an 11 bit value.
            //
qiuyiuestc's avatar
qiuyiuestc 已提交
2100
            pMsgObject->ulMsgIDMask = ((usMaskReg1 & CAN_IF1MSK2_IDMSK_M) >>
qiuyiuestc's avatar
qiuyiuestc 已提交
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117
                                       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((pMsgObject->ulMsgIDMask != 0x7ff) ||
               ((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0))
            {
                pMsgObject->ulFlags |= MSG_OBJ_USE_ID_FILTER;
            }
        }

        //
        // Indicate if the extended bit was used in filtering.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
2118
        if(usMaskReg1 & CAN_IF1MSK2_MXTD)
qiuyiuestc's avatar
qiuyiuestc 已提交
2119 2120 2121 2122 2123 2124 2125
        {
            pMsgObject->ulFlags |= MSG_OBJ_USE_EXT_FILTER;
        }

        //
        // Indicate if direction filtering was enabled.
        //
qiuyiuestc's avatar
qiuyiuestc 已提交
2126
        if(usMaskReg1 & CAN_IF1MSK2_MDIR)
qiuyiuestc's avatar
qiuyiuestc 已提交
2127 2128 2129 2130 2131 2132
        {
            pMsgObject->ulFlags |= MSG_OBJ_USE_DIR_FILTER;
        }
    }

    //
qiuyiuestc's avatar
qiuyiuestc 已提交
2133
    // Set the interrupt flags.
qiuyiuestc's avatar
qiuyiuestc 已提交
2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
    //
    if(usMsgCtrl & CAN_IF1MCTL_TXIE)
    {
        pMsgObject->ulFlags |= MSG_OBJ_TX_INT_ENABLE;
    }
    if(usMsgCtrl & CAN_IF1MCTL_RXIE)
    {
        pMsgObject->ulFlags |= MSG_OBJ_RX_INT_ENABLE;
    }

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

        //
        // Don't read any data for a remote frame, there is nothing valid in
        // that buffer anyway.
        //
        if((pMsgObject->ulFlags & MSG_OBJ_REMOTE_FRAME) == 0)
        {
            //
            // Read out the data from the CAN registers.
            //
            CANDataRegRead(pMsgObject->pucMsgData,
                           (unsigned long *)(ulBase + CAN_O_IF2DA1),
                           pMsgObject->ulMsgLen);
        }

        //
        // Now clear out the new data flag.
        //
        CANRegWrite(ulBase + CAN_O_IF2CMSK, CAN_IF1CMSK_NEWDAT);

        //
qiuyiuestc's avatar
qiuyiuestc 已提交
2174
        // Transfer the message object to the message object specified by
qiuyiuestc's avatar
qiuyiuestc 已提交
2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250
        // ulObjID.
        //
        CANRegWrite(ulBase + CAN_O_IF2CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);

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

        //
        // Indicate that there is new data in this message.
        //
        pMsgObject->ulFlags |= 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.
        //
        pMsgObject->ulMsgLen = 0;
    }
}

//*****************************************************************************
//
//! Clears a message object so that it is no longer used.
//!
//! \param ulBase is the base address of the CAN controller.
//! \param ulObjID 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 will no longer automatically send or
//! receive messages, or generate interrupts.
//!
//! \return None.
//
//*****************************************************************************
void
CANMessageClear(unsigned long ulBase, unsigned long ulObjID)
{
    //
    // Check the arguments.
    //
    ASSERT(CANBaseValid(ulBase));
    ASSERT((ulObjID >= 1) && (ulObjID <= 32));

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

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

    //
    // Initiate programming the message object
    //
    CANRegWrite(ulBase + CAN_O_IF1CRQ, ulObjID & CAN_IF1CRQ_MNUM_M);
}

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