⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 can.c

📁 Tried to make CAN logger on AT91sam7X-ek, but have no idea how to implement FATFs... -( I m just a
💻 C
📖 第 1 页 / 共 3 页
字号:
/* ----------------------------------------------------------------------------
 *         ATMEL Microcontroller Software Support 
 * ----------------------------------------------------------------------------
 * Copyright (c) 2008, Atmel Corporation
 *
 * All rights reserved.
 *
 * 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 disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
 * ----------------------------------------------------------------------------
 */

//------------------------------------------------------------------------------
//         Headers
//------------------------------------------------------------------------------

#include <board.h>
#include <pio/pio.h>
#include <utility/trace.h>
#include <aic/aic.h>
#include "can.h"

//------------------------------------------------------------------------------
//         Local definitions
//------------------------------------------------------------------------------
// CAN state
#define CAN_DISABLED       0
#define CAN_HALTED         1
#define CAN_IDLE           2
#define CAN_SENDING        3
#define CAN_RECEIVING      4

// MOT: Mailbox Object Type
#define CAN_MOT_DISABLE    0 // Mailbox is disabled
#define CAN_MOT_RECEPT     1 // Reception Mailbox
#define CAN_MOT_RECEPT_OW  2 // Reception mailbox with overwrite
#define CAN_MOT_TRANSMIT   3 // Transmit mailbox
#define CAN_MOT_CONSUMER   4 // Consumer mailbox
#define CAN_MOT_PRODUCER   5 // Producer mailbox

//------------------------------------------------------------------------------
//         Local variables
//------------------------------------------------------------------------------
#if defined (PINS_CAN_TRANSCEIVER_TXD)
static const Pin pins_can_transceiver_txd[] = {PINS_CAN_TRANSCEIVER_TXD};
#endif
#if defined (PINS_CAN_TRANSCEIVER_RXD)
static const Pin pins_can_transceiver_rxd[] = {PINS_CAN_TRANSCEIVER_RXD};
#endif
static const Pin pin_can_transceiver_rs   = PIN_CAN_TRANSCEIVER_RS;
#if defined (PIN_CAN_TRANSCEIVER_RXEN)
static const Pin pin_can_transceiver_rxen = PIN_CAN_TRANSCEIVER_RXEN;
#endif

static CanTransfer *pCAN0Transfer=NULL;
#ifdef AT91C_BASE_CAN1
static CanTransfer *pCAN1Transfer=NULL;
#endif

//------------------------------------------------------------------------------
//         Local functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// CAN Error Detection
/// \param status     error type
/// \param can_number can nulber
//------------------------------------------------------------------------------
static void CAN_ErrorHandling( unsigned int status, unsigned char can_number)
{
    if( (status&AT91C_CAN_ERRA) ==  AT91C_CAN_ERRA) {
        TRACE_ERROR("(CAN) CAN is in active Error Active mode\n\r");
    }
    else if( (status&AT91C_CAN_ERRP) ==  AT91C_CAN_ERRP) {
        TRACE_ERROR("(CAN) CAN is in Error Passive mode\n\r");
    }
    else if( (status&AT91C_CAN_BOFF) ==  AT91C_CAN_BOFF) {
        TRACE_ERROR("(CAN) CAN is in Buff Off mode\n\r");
        // CAN reset
        TRACE_ERROR("(CAN) CAN%d reset\n\r", can_number);
        // CAN Controller Disable
        if (can_number == 0) {
            AT91C_BASE_CAN0->CAN_MR &= ~AT91C_CAN_CANEN;
            // CAN Controller Enable
            AT91C_BASE_CAN0->CAN_MR |= AT91C_CAN_CANEN;
        }
#ifdef AT91C_BASE_CAN1
        else if (can_number == 1) {
            AT91C_BASE_CAN1->CAN_MR &= ~AT91C_CAN_CANEN;
            // CAN Controller Enable
            AT91C_BASE_CAN1->CAN_MR |= AT91C_CAN_CANEN;
        }
#endif
    }

    // Error for Frame dataframe
    // CRC error
    if( (status&AT91C_CAN_CERR) ==  AT91C_CAN_CERR) {
        TRACE_ERROR("(CAN) CRC Error\n\r");
    }
    // Bit-stuffing error
    else if( (status&AT91C_CAN_SERR) ==  AT91C_CAN_SERR) {
        TRACE_ERROR("(CAN) Stuffing Error\n\r");
    }
    // Bit error
    else if( (status&AT91C_CAN_BERR) ==  AT91C_CAN_BERR) {
        TRACE_ERROR("(CAN) Bit Error\n\r");
    }
    // Form error
    else if( (status&AT91C_CAN_FERR) ==  AT91C_CAN_FERR) {
        TRACE_ERROR("(CAN) Form Error\n\r");
    }
    // Acknowledgment error
    else if( (status&AT91C_CAN_AERR) ==  AT91C_CAN_AERR) {
        TRACE_ERROR("(CAN) Acknowledgment Error\n\r");
    }

    // Error interrupt handler
    // Represent the current status of the CAN bus and are not latched.
    // See CAN, par. Error Interrupt Handler
    // AT91C_CAN_WARN
    // AT91C_CAN_ERRA
}

//------------------------------------------------------------------------------
// Generic CAN Interrupt handler
/// \param can_number can nulber
//------------------------------------------------------------------------------
static void CAN_Handler( unsigned char can_number ) 
{
    AT91PS_CAN base_can;
    AT91PS_CAN_MB CAN_Mailbox;

    unsigned int status;
    unsigned int can_msr;
    unsigned int* pCan_mcr;
    unsigned int message_mode;
    unsigned char numMailbox;
    unsigned char state0=CAN_DISABLED;
    unsigned char state1=CAN_DISABLED;

    if( can_number == 0 ) {
        base_can = AT91C_BASE_CAN0;
        CAN_Mailbox = AT91C_BASE_CAN0_MB0;
        state0 = pCAN0Transfer->state;
    }
#ifdef AT91C_BASE_CAN1
    else {
        base_can = AT91C_BASE_CAN1;
        CAN_Mailbox = AT91C_BASE_CAN1_MB0;
        state1 = pCAN1Transfer->state;
    }
#endif
    status = (base_can->CAN_SR) & (base_can->CAN_IMR);
    base_can->CAN_IDR = status;

    TRACE_DEBUG("CAN0 status=0x%X\n\r", status);
    if(status & AT91C_CAN_WAKEUP) {
        if( can_number == 0 ) {
            pCAN0Transfer->test_can = AT91C_TEST_OK;
            pCAN0Transfer->state = CAN_IDLE;
        }
#ifdef AT91C_BASE_CAN1
        else {
            pCAN1Transfer->test_can = AT91C_TEST_OK;
            pCAN1Transfer->state = CAN_IDLE;
        }
#endif
    }
    // Mailbox event ?
    else if ((status&0x0000FFFF) != 0) {
        TRACE_DEBUG("Mailbox event\n\r");

        // Handle Mailbox interrupts
        for (numMailbox = 0; numMailbox < NUM_MAILBOX_MAX; numMailbox++) {

            can_msr = *(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x10+(0x20*numMailbox)));
            if ((AT91C_CAN_MRDY & can_msr) == AT91C_CAN_MRDY) {
                // Mailbox object type
                message_mode =  ((*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x00+(0x20*numMailbox))))>>24)&0x7;
                TRACE_DEBUG("message_mode 0x%X\n\r", message_mode);
                TRACE_DEBUG("numMailbox 0x%X\n\r", numMailbox);

                if( message_mode == 0 ) {
                    TRACE_ERROR("Error in MOT\n\r");
                }
                else if( ( message_mode == CAN_MOT_RECEPT ) 
                      || ( message_mode == CAN_MOT_RECEPT_OW ) 
                      || ( message_mode == CAN_MOT_PRODUCER ) ) {
                    TRACE_DEBUG("Mailbox is in RECEPTION\n\r");
                    TRACE_DEBUG("Length 0x%X\n\r", (can_msr>>16)&0xF);
                    TRACE_DEBUG("CAN_MB_MID 0x%X\n\r", ((*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x08+(0x20*numMailbox)))&AT91C_CAN_MIDvA)>>18));

                    TRACE_DEBUG("can_number %d\n\r", can_number);
                    if( can_number == 0 ) {
                        //CAN_MB_MDLx
                        pCAN0Transfer->data_low_reg = 
                           (*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x14+(0x20*numMailbox))));
                        //CAN_MB_MDHx
                        pCAN0Transfer->data_high_reg = 
                           (*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x18+(0x20*numMailbox))));
                        pCAN0Transfer->size = (can_msr>>16)&0xF;
                        pCAN0Transfer->mailbox_number = numMailbox;
                        state0 = CAN_IDLE;
                    }
#ifdef AT91C_BASE_CAN1
                    else {
                        //CAN_MB_MDLx
                        pCAN1Transfer->data_low_reg = 
                           (*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x14+(0x20*numMailbox))));
                        //CAN_MB_MDHx
                        pCAN1Transfer->data_high_reg = 
                           (*(unsigned int*)((unsigned int)CAN_Mailbox+(unsigned int)(0x18+(0x20*numMailbox))));
                        pCAN1Transfer->size = (can_msr>>16)&0xF;
                        pCAN1Transfer->mailbox_number = numMailbox;
                        state1 = CAN_IDLE;
                    }
#endif
                    // Message Data has been received
                    pCan_mcr = (unsigned int*)((unsigned int)CAN_Mailbox+0x1C+(0x20*numMailbox));
                    *pCan_mcr = AT91C_CAN_MTCR;

                }
                else {
                    TRACE_DEBUG("Mailbox is in TRANSMIT\n\r");
                    TRACE_DEBUG("Length 0x%X\n\r", (can_msr>>16)&0xF);
                    TRACE_DEBUG("can_number %d\n\r", can_number);
                    if( can_number == 0 ) {
                        state0 = CAN_IDLE;
                    }
                    else {
                        state1 = CAN_IDLE;
                    }
                }
            }
        }
        if( can_number == 0 ) {
            pCAN0Transfer->state = state0;
        }
#ifdef AT91C_BASE_CAN1
        else {
            pCAN1Transfer->state = state1;
        }
#endif
    }
    if ((status&0xFFCF0000) != 0) {
        CAN_ErrorHandling(status, 0);
    }
}

//------------------------------------------------------------------------------
/// CAN 0 Interrupt handler
//------------------------------------------------------------------------------
static void CAN0_Handler(void)
{
    CAN_Handler( 0 );
}

//------------------------------------------------------------------------------
/// CAN 1 Interrupt handler
//------------------------------------------------------------------------------
#if defined AT91C_BASE_CAN1
static void CAN1_Handler(void)
{
    CAN_Handler( 1 );
}
#endif

//------------------------------------------------------------------------------
//         Global functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
/// Configure the corresponding mailbox
/// \param pTransfer can transfer structure
//------------------------------------------------------------------------------
void CAN_InitMailboxRegisters( CanTransfer *pTransfer )
{
    AT91PS_CAN    base_can;
    AT91PS_CAN_MB CAN_Mailbox;

    if( pTransfer->can_number == 0 ) {
        base_can = AT91C_BASE_CAN0;
        CAN_Mailbox = AT91C_BASE_CAN0_MB0;
    }
#ifdef AT91C_BASE_CAN1
    else {
        base_can = AT91C_BASE_CAN1;
        CAN_Mailbox = AT91C_BASE_CAN1_MB0;
    }
#endif
    CAN_Mailbox = (AT91PS_CAN_MB)((unsigned int)CAN_Mailbox+(unsigned int)(0x20*pTransfer->mailbox_number));

    pTransfer->mailbox_in_use |= 1<<(pTransfer->mailbox_number);
    // MailBox Control Register
    CAN_Mailbox->CAN_MB_MCR = 0x0;
    // MailBox Mode Register
    CAN_Mailbox->CAN_MB_MMR = 0x00;
    // CAN Message Acceptance Mask Register
    CAN_Mailbox->CAN_MB_MAM = pTransfer->acceptance_mask_reg;
    // MailBox ID Register
    // Disable the mailbox before writing to CAN_MIDx registers
    if( (pTransfer->identifier & AT91C_CAN_MIDE) == AT91C_CAN_MIDE ) {
        // Extended
        CAN_Mailbox->CAN_MB_MAM |= AT91C_CAN_MIDE;
    }
    else {
        CAN_Mailbox->CAN_MB_MAM &= ~AT91C_CAN_MIDE;
    }
    CAN_Mailbox->CAN_MB_MID = pTransfer->identifier;

    // MailBox Mode Register
    CAN_Mailbox->CAN_MB_MMR = pTransfer->mode_reg;
    // MailBox Data Low Register
    CAN_Mailbox->CAN_MB_MDL = pTransfer->data_low_reg;
    // MailBox Data High Register
    CAN_Mailbox->CAN_MB_MDH = pTransfer->data_high_reg;
    // MailBox Control Register
    CAN_Mailbox->CAN_MB_MCR = pTransfer->control_reg;
}

//------------------------------------------------------------------------------
/// Reset the MBx
//------------------------------------------------------------------------------
void CAN_ResetAllMailbox( void )
{
    unsigned char i;
  
#if defined (AT91C_BASE_CAN0_MB0)
    CAN_ResetTransfer( pCAN0Transfer );
    for( i=0; i<8; i++ ) {
        pCAN0Transfer->can_number = 0;
        pCAN0Transfer->mailbox_number = i;
        pCAN0Transfer->mode_reg = AT91C_CAN_MOT_DIS;
        pCAN0Transfer->acceptance_mask_reg = 0;
        pCAN0Transfer->identifier = 0;
        pCAN0Transfer->data_low_reg = 0x00000000;
        pCAN0Transfer->data_high_reg = 0x00000000;
        pCAN0Transfer->control_reg = 0x00000000;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -