From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- peripherals/can/can.c | 1066 +++++++++++++++++++++++++++++++++++++++++++++++++ peripherals/can/can.h | 113 ++++++ 2 files changed, 1179 insertions(+) create mode 100644 peripherals/can/can.c create mode 100644 peripherals/can/can.h (limited to 'peripherals/can') diff --git a/peripherals/can/can.c b/peripherals/can/can.c new file mode 100644 index 0000000..5486fcf --- /dev/null +++ b/peripherals/can/can.c @@ -0,0 +1,1066 @@ +/* ---------------------------------------------------------------------------- + * 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 +#include +#include +#include +#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; + CAN_InitMailboxRegisters( pCAN0Transfer ); + } +#endif +#if defined (AT91C_BASE_CAN0_MB8) + for( i=0; i<8; i++ ) { + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = i+8; + 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; + CAN_InitMailboxRegisters( pCAN0Transfer ); + } +#endif + +#if defined (AT91C_BASE_CAN1_MB0) + if( pCAN1Transfer != NULL ) { + CAN_ResetTransfer( pCAN1Transfer ); + for( i=0; i<8; i++ ) { + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = i; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_DIS; + pCAN1Transfer->acceptance_mask_reg = 0; + pCAN1Transfer->identifier = 0; + pCAN1Transfer->data_low_reg = 0x00000000; + pCAN1Transfer->data_high_reg = 0x00000000; + pCAN1Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN1Transfer ); + } + } +#endif +#if defined (AT91C_BASE_CAN1_MB8) + if( pCAN1Transfer != NULL ) { + for( i=0; i<8; i++ ) { + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = i+8; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_DIS; + pCAN1Transfer->acceptance_mask_reg = 0; + pCAN1Transfer->identifier = 0; + pCAN1Transfer->data_low_reg = 0x00000000; + pCAN1Transfer->data_high_reg = 0x00000000; + pCAN1Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN1Transfer ); + } + } +#endif + +} + +//------------------------------------------------------------------------------ +/// CAN reset Transfer descriptor +/// \param pTransfer can transfer structure +//------------------------------------------------------------------------------ +void CAN_ResetTransfer( CanTransfer *pTransfer ) +{ + pTransfer->state = CAN_IDLE; + pTransfer->can_number = 0; + pTransfer->mailbox_number = 0; + pTransfer->test_can = 0; + pTransfer->mode_reg = 0; + pTransfer->acceptance_mask_reg = 0; + pTransfer->identifier = 0; + pTransfer->data_low_reg = 0; + pTransfer->data_high_reg = 0; + pTransfer->control_reg = 0; + pTransfer->mailbox_in_use = 0; + pTransfer->size = 0; +} + +//------------------------------------------------------------------------------ +/// Wait for CAN synchronisation +/// \return return 1 for good initialisation, otherwise return 0 +//------------------------------------------------------------------------------ +static unsigned char CAN_Synchronisation( void ) +{ + unsigned int tick=0; + + TRACE_INFO("CAN_Synchronisation\n\r"); + + pCAN0Transfer->test_can = AT91C_TEST_NOK; +#ifdef AT91C_BASE_CAN1 + if( pCAN1Transfer != NULL ) { + pCAN1Transfer->test_can = AT91C_TEST_NOK; + } +#endif + // Enable CAN and Wait for WakeUp Interrupt + AT91C_BASE_CAN0->CAN_IER = AT91C_CAN_WAKEUP; + // CAN Controller Enable + AT91C_BASE_CAN0->CAN_MR = AT91C_CAN_CANEN; + // Enable Autobaud/Listen mode + // dangerous, CAN not answer in this mode + + while( (pCAN0Transfer->test_can != AT91C_TEST_OK) + && (tick < AT91C_CAN_TIMEOUT) ) { + tick++; + } + if (tick == AT91C_CAN_TIMEOUT) { + TRACE_ERROR("CAN0 Initialisations FAILED\n\r"); + return 0; + } else { + TRACE_INFO("CAN0 Initialisations Completed\n\r"); + } + +#if defined AT91C_BASE_CAN1 + if( pCAN1Transfer != NULL ) { + AT91C_BASE_CAN1->CAN_IER = AT91C_CAN_WAKEUP; + // CAN Controller Enable + AT91C_BASE_CAN1->CAN_MR = AT91C_CAN_CANEN; + + tick = 0; + // Wait for WAKEUP flag raising <=> 11-recessive-bit were scanned by the transceiver + while( ((pCAN1Transfer->test_can != AT91C_TEST_OK)) + && (tick < AT91C_CAN_TIMEOUT) ) { + tick++; + } + + if (tick == AT91C_CAN_TIMEOUT) { + TRACE_ERROR("CAN1 Initialisations FAILED\n\r"); + return 0; + } else { + TRACE_INFO("CAN1 Initialisations Completed\n\r"); + } + } +#endif + return 1; +} + +//------------------------------------------------------------------------------ +/// Write a CAN transfer +/// \param pTransfer can transfer structure +/// \return return CAN_STATUS_SUCCESS if command passed, otherwise +/// return CAN_STATUS_LOCKED +//------------------------------------------------------------------------------ +unsigned char CAN_Write( CanTransfer *pTransfer ) +{ + AT91PS_CAN base_can; + + if (pTransfer->state == CAN_RECEIVING) { + pTransfer->state = CAN_IDLE; + } + + if (pTransfer->state != CAN_IDLE) { + return CAN_STATUS_LOCKED; + } + + TRACE_DEBUG("CAN_Write\n\r"); + pTransfer->state = CAN_SENDING; + if( pTransfer->can_number == 0 ) { + base_can = AT91C_BASE_CAN0; + } +#ifdef AT91C_BASE_CAN1 + else { + base_can = AT91C_BASE_CAN1; + } +#endif + base_can->CAN_TCR = pTransfer->mailbox_in_use; + base_can->CAN_IER = pTransfer->mailbox_in_use; + + return CAN_STATUS_SUCCESS; + +} + + +//------------------------------------------------------------------------------ +/// Read a CAN transfer +/// \param pTransfer can transfer structure +/// \return return CAN_STATUS_SUCCESS if command passed, otherwise +/// return CAN_STATUS_LOCKED +//------------------------------------------------------------------------------ +unsigned char CAN_Read( CanTransfer *pTransfer ) +{ + AT91PS_CAN base_can; + + if (pTransfer->state != CAN_IDLE) { + return CAN_STATUS_LOCKED; + } + + TRACE_DEBUG("CAN_Read\n\r"); + pTransfer->state = CAN_RECEIVING; + + + if( pTransfer->can_number == 0 ) { + base_can = AT91C_BASE_CAN0; + } +#ifdef AT91C_BASE_CAN1 + else { + base_can = AT91C_BASE_CAN1; + } +#endif + // enable interrupt + base_can->CAN_IER = pTransfer->mailbox_in_use; + + return CAN_STATUS_SUCCESS; +} + +//------------------------------------------------------------------------------ +/// Test if CAN is in IDLE state +/// \param pTransfer can transfer structure +/// \return return 0 if CAN is in IDLE, otherwise return 1 +//------------------------------------------------------------------------------ +unsigned char CAN_IsInIdle( CanTransfer *pTransfer ) +{ + return( pTransfer->state != CAN_IDLE ); +} + +//------------------------------------------------------------------------------ +/// Basic CAN test without Interrupt +//------------------------------------------------------------------------------ +void CAN_BasicTestSuiteWithoutInterrupt(void) +{ +#if defined AT91C_BASE_CAN1 + unsigned int status; + unsigned int tick=0; + + TRACE_INFO("Without Interrupt "); + TRACE_INFO("CAN0 Mailbox 0 transmitting to CAN1 Mailbox 0\n\r"); + // Init CAN0 Mailbox 0, transmit + CAN_ResetTransfer( pCAN0Transfer ); + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 0; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR; + pCAN0Transfer->acceptance_mask_reg = 0x00000000; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x07<<18); + pCAN0Transfer->data_low_reg = 0x11223344; + pCAN0Transfer->data_high_reg = 0x01234567; + pCAN0Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN1 Mailbox 0, receive, + CAN_ResetTransfer( pCAN1Transfer ); + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = 0; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_RX; + pCAN1Transfer->acceptance_mask_reg = AT91C_CAN_MIDvA | AT91C_CAN_MIDvB; + pCAN1Transfer->identifier = AT91C_CAN_MIDvA & (0x07<<18); + pCAN1Transfer->data_low_reg = 0x00000000; + pCAN1Transfer->data_high_reg = 0x00000000; + pCAN1Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN1Transfer ); + + // Transfer Request for Mailbox 0 + AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB0; + + tick = 0; + do { + // CAN Message Status Register + status = AT91C_BASE_CAN0_MB0->CAN_MB_MSR; + } + while( !(status & AT91C_CAN_MRDY) && (++tick < AT91C_CAN_TIMEOUT) ); + + if (tick == AT91C_CAN_TIMEOUT) { + TRACE_ERROR("Test FAILED\n\r"); + } + else { + TRACE_DEBUG("Transfer completed: CAN1 Mailbox 0 MRDY flag has raised\n\r"); + if( AT91C_BASE_CAN0_MB0->CAN_MB_MDL != AT91C_BASE_CAN1_MB0->CAN_MB_MDL ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else if( AT91C_BASE_CAN0_MB0->CAN_MB_MDH != AT91C_BASE_CAN1_MB0->CAN_MB_MDH ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else { + TRACE_INFO("Test passed\n\r"); + } + } + + CAN_ResetAllMailbox(); + + TRACE_INFO("Without Interrupt "); + TRACE_INFO("CAN0 Mailboxes 1 & 2 transmitting to CAN1 Mailbox 15\n\r"); + // Init CAN0 Mailbox 1, transmit + CAN_ResetTransfer( pCAN0Transfer ); + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 1; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR; + pCAN0Transfer->acceptance_mask_reg = 0x00000000; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x09<<18); // ID 9 + pCAN0Transfer->data_low_reg = 0xAABBCCDD; + pCAN0Transfer->data_high_reg = 0xCAFEDECA; + pCAN0Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); // Mailbox Data Length Code + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN0 Mailbox 2, transmit + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 2; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_TX | (AT91C_CAN_PRIOR-(1<<16)); + pCAN0Transfer->acceptance_mask_reg = 0x00000000; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x0A<<18); // ID 10 + pCAN0Transfer->data_low_reg = 0x55667788; + pCAN0Transfer->data_high_reg = 0x99AABBCC; + pCAN0Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); // Mailbox Data Length Code + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN1 Mailbox 15, reception with overwrite + CAN_ResetTransfer( pCAN1Transfer ); + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = 15; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_RXOVERWRITE; + pCAN1Transfer->acceptance_mask_reg = 0; + pCAN1Transfer->identifier = 0x0; + pCAN1Transfer->data_low_reg = 0x00000000; + pCAN1Transfer->data_high_reg = 0x00000000; + pCAN1Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN1Transfer ); + + // Ask Transmissions on Mailbox 1 & 2 --> AT91C_CAN_MRDY & AT91C_CAN_MMI raises for Mailbox 15 CAN_MB_SR + AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB1 | AT91C_CAN_MB2; + + // Wait for Last Transmit Mailbox + tick = 0; + do { + status = AT91C_BASE_CAN1_MB15->CAN_MB_MSR; + } + while( !(status & AT91C_CAN_MMI) && (++tick < AT91C_CAN_TIMEOUT) ); + + if (tick == AT91C_CAN_TIMEOUT) { + } + else { + TRACE_DEBUG("Transfer completed: CAN1 Mailbox 15 MRDY and MMI flags have raised\n\r"); + if( AT91C_BASE_CAN0_MB1->CAN_MB_MDL != AT91C_BASE_CAN1_MB15->CAN_MB_MDL ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else if( AT91C_BASE_CAN0_MB1->CAN_MB_MDH != AT91C_BASE_CAN1_MB15->CAN_MB_MDH ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else { + TRACE_INFO("Test passed\n\r"); + } + } + + CAN_ResetAllMailbox(); + TRACE_INFO("Without Interrupt "); + TRACE_INFO("CAN0 Mailboxes 1 & 2 transmitting to CAN1 Mailbox 15\n\r"); + // Init CAN0 Mailbox 1, transmit + CAN_ResetTransfer( pCAN0Transfer ); + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 1; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_TX | AT91C_CAN_PRIOR; + pCAN0Transfer->acceptance_mask_reg = 0x00000000; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x09<<18); // ID 9 + pCAN0Transfer->data_low_reg = 0xAABBCCDD; + pCAN0Transfer->data_high_reg = 0xCAFEDECA; + pCAN0Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); // Mailbox Data Length Code + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN0 Mailbox 2, transmit + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 2; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_TX | (AT91C_CAN_PRIOR-(1<<16)); + pCAN0Transfer->acceptance_mask_reg = 0x00000000; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x0A<<18); // ID 10 + pCAN0Transfer->data_low_reg = 0x55667788; + pCAN0Transfer->data_high_reg = 0x99AABBCC; + pCAN0Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); // Mailbox Data Length Code + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN1 Mailbox 15, reception with overwrite + CAN_ResetTransfer( pCAN1Transfer ); + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = 15; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_RX; + pCAN1Transfer->acceptance_mask_reg = 0; + pCAN1Transfer->identifier = 0x0; + pCAN1Transfer->data_low_reg = 0x00000000; + pCAN1Transfer->data_high_reg = 0x00000000; + pCAN1Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN1Transfer ); + + // Ask Transmissions on Mailbox 1 & 2 --> AT91C_CAN_MRDY & AT91C_CAN_MMI raises for Mailbox 15 CAN_MB_SR + AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB1 | AT91C_CAN_MB2; + + // Wait for Last Transmit Mailbox + tick = 0; + do { + status = AT91C_BASE_CAN1_MB15->CAN_MB_MSR; + } + while( !(status & AT91C_CAN_MMI) && (++tick < AT91C_CAN_TIMEOUT) ); + + if (tick == AT91C_CAN_TIMEOUT) { + TRACE_ERROR("Test FAILED\n\r"); + } + else { + TRACE_DEBUG("Transfer completed: CAN1 Mailbox 15 MRDY and MMI flags have raised\n\r"); + TRACE_DEBUG("MB_MDL: 0x%X\n\r", AT91C_BASE_CAN1_MB15->CAN_MB_MDL); + TRACE_DEBUG("MB_MDLH: 0x%X\n\r", AT91C_BASE_CAN1_MB15->CAN_MB_MDH); + if( AT91C_BASE_CAN0_MB2->CAN_MB_MDL != AT91C_BASE_CAN1_MB15->CAN_MB_MDL ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else if( AT91C_BASE_CAN0_MB2->CAN_MB_MDH != AT91C_BASE_CAN1_MB15->CAN_MB_MDH ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else { + TRACE_INFO("Test passed\n\r"); + } + } + + CAN_ResetAllMailbox(); + TRACE_INFO("Without Interrupt "); + TRACE_INFO("CAN0 Mailbox 3 asking for CAN1 Mailbox 3 transmission\n\r"); + // Init CAN0 Mailbox 3, consumer mailbox + // Sends a remote frame and waits for an answer + CAN_ResetTransfer( pCAN0Transfer ); + pCAN0Transfer->can_number = 0; + pCAN0Transfer->mailbox_number = 3; + pCAN0Transfer->mode_reg = AT91C_CAN_MOT_CONSUMER | AT91C_CAN_PRIOR; + pCAN0Transfer->acceptance_mask_reg = AT91C_CAN_MIDvA | AT91C_CAN_MIDvB; + pCAN0Transfer->identifier = AT91C_CAN_MIDvA & (0x0B<<18); // ID 11 + pCAN0Transfer->data_low_reg = 0x00000000; + pCAN0Transfer->data_high_reg = 0x00000000; + pCAN0Transfer->control_reg = 0x00000000; + CAN_InitMailboxRegisters( pCAN0Transfer ); + + // Init CAN1 Mailbox 3, porducer mailbox + // Waits to receive a Remote Frame before sending its contents + CAN_ResetTransfer( pCAN1Transfer ); + pCAN1Transfer->can_number = 1; + pCAN1Transfer->mailbox_number = 3; + pCAN1Transfer->mode_reg = AT91C_CAN_MOT_PRODUCER | AT91C_CAN_PRIOR; + pCAN1Transfer->acceptance_mask_reg = 0; + pCAN1Transfer->identifier = AT91C_CAN_MIDvA & (0x0B<<18); // ID 11 + pCAN1Transfer->data_low_reg = 0xEEDDFF00; + pCAN1Transfer->data_high_reg = 0x34560022; + pCAN1Transfer->control_reg = (AT91C_CAN_MDLC & (0x8<<16)); + CAN_InitMailboxRegisters( pCAN1Transfer ); + + // Ask Transmissions on Mailbox 3 --> AT91C_CAN_MRDY raises for Mailbox 3 CAN_MB_SR + AT91C_BASE_CAN1->CAN_TCR = AT91C_CAN_MB3; + AT91C_BASE_CAN0->CAN_TCR = AT91C_CAN_MB3; + + // Wait for Last Transmit Mailbox + tick = 0; + do { + status = AT91C_BASE_CAN0_MB3->CAN_MB_MSR; + } + while( !(status & AT91C_CAN_MRDY) && (++tick < AT91C_CAN_TIMEOUT) ); + + if (tick == AT91C_CAN_TIMEOUT) { + TRACE_ERROR("Test FAILED\n\r"); + } + else { + TRACE_DEBUG("Transfer Completed: CAN0 & CAN1 Mailboxes 3 MRDY flags have raised\n\r"); + if( AT91C_BASE_CAN0_MB3->CAN_MB_MDL != AT91C_BASE_CAN1_MB3->CAN_MB_MDL ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else if( AT91C_BASE_CAN0_MB3->CAN_MB_MDH != AT91C_BASE_CAN1_MB3->CAN_MB_MDH ) { + TRACE_ERROR("Data Corrupted\n\r"); + } + else { + TRACE_INFO("Test passed\n\r"); + } + } +#endif // AT91C_BASE_CAN1 + + return; +} + + +//------------------------------------------------------------------------------ +/// Disable CAN and enter in low power +//------------------------------------------------------------------------------ +void CAN_disable( void ) +{ + // Disable the interrupt on the interrupt controller + IRQ_DisableIT(AT91C_ID_CAN0); + // disable all IT + AT91C_BASE_CAN0->CAN_IDR = 0x1FFFFFFF; +#if defined AT91C_BASE_CAN1 + IRQ_DisableIT(AT91C_ID_CAN1); + // disable all IT + AT91C_BASE_CAN1->CAN_IDR = 0x1FFFFFFF; +#endif + + // Enable Low Power mode + AT91C_BASE_CAN0->CAN_MR |= AT91C_CAN_LPM; + + // Disable CANs Transceivers + // Enter standby mode + PIO_Set(&pin_can_transceiver_rs); +#if defined (PIN_CAN_TRANSCEIVER_RXEN) + // Enable ultra Low Power mode + PIO_Clear(&pin_can_transceiver_rxen); +#endif + + // Disable clock for CAN PIO +#if defined(AT91C_ID_PIOA) + AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOA); +#elif defined(AT91C_ID_PIOABCD) + AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOABCD); +#elif defined(AT91C_ID_PIOABCDE) + AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_PIOABCDE); +#endif + + // Disable the CAN0 controller peripheral clock + AT91C_BASE_PMC->PMC_PCDR = (1 << AT91C_ID_CAN0); + +} + +//------------------------------------------------------------------------------ +/// baudrate calcul +/// \param base_CAN CAN base address +/// \param baudrate Baudrate value (kB/s) +/// allowed values: 1000, 800, 500, 250, 125, 50, 25, 10 +/// \return return 1 in success, otherwise return 0 +//------------------------------------------------------------------------------ +unsigned char CAN_BaudRateCalculate( AT91PS_CAN base_CAN, + unsigned int baudrate ) +{ + unsigned int BRP; + unsigned int PROPAG; + unsigned int PHASE1; + unsigned int PHASE2; + unsigned int SJW; + unsigned int t1t2; + unsigned char TimeQuanta; + + base_CAN->CAN_BR = 0; + + if( baudrate == 1000) { + TimeQuanta = 8; + } + else { + TimeQuanta = 16; + } + + BRP = (BOARD_MCK / (baudrate*1000*TimeQuanta))-1; + //TRACE_DEBUG("BRP = 0x%X\n\r", BRP); + // timing Delay: + // Delay Bus Driver: 50 ns + // Delay Receiver: 30 ns + // Delay Bus Line (20m): 110 ns + if( (TimeQuanta*baudrate*2*(50+30+110)/1000000) >= 1) { + PROPAG = (TimeQuanta*baudrate*2*(50+30+110)/1000000)-1; + } + else { + PROPAG = 0; + } + //TRACE_DEBUG("PROPAG = 0x%X\n\r", PROPAG); + + t1t2 = TimeQuanta-1-(PROPAG+1); + //TRACE_DEBUG("t1t2 = 0x%X\n\r", t1t2); + + if( (t1t2 & 0x01) == 0x01 ) { + // ODD + //TRACE_DEBUG("ODD\n\r"); + PHASE1 = ((t1t2-1)/2)-1; + PHASE2 = PHASE1+1; + } + else { + // EVEN + //TRACE_DEBUG("EVEN\n\r"); + PHASE1 = (t1t2/2)-1; + PHASE2 = PHASE1; + } + //TRACE_DEBUG("PHASE1 = 0x%X\n\r", PHASE1); + //TRACE_DEBUG("PHASE2 = 0x%X\n\r", PHASE2); + + if( 1 > (4/(PHASE1+1)) ) { + //TRACE_DEBUG("4*Tcsc\n\r"); + SJW = 3; + } + else { + //TRACE_DEBUG("Tphs1\n\r"); + SJW = PHASE1; + } + //TRACE_DEBUG("SJW = 0x%X\n\r", SJW); + // Verif + if( BRP == 0 ) { + TRACE_DEBUG("BRP = 0 is not authorized\n\r"); + return 0; + } + + if( (PROPAG + PHASE1 + PHASE2) != (TimeQuanta-4) ) { + TRACE_DEBUG("Pb (PROPAG + PHASE1 + PHASE2) = %d\n\r", PROPAG + PHASE1 + PHASE2); + TRACE_DEBUG("with TimeQuanta-4 = %d\n\r", TimeQuanta-4); + return 0; + } + base_CAN->CAN_BR = (AT91C_CAN_PHASE2 & (PHASE2 << 0)) + + (AT91C_CAN_PHASE1 & (PHASE1 << 4)) + + (AT91C_CAN_PROPAG & (PROPAG << 8)) + + (AT91C_CAN_SYNC & (SJW << 12)) + + (AT91C_CAN_BRP & (BRP << 16)) + + (AT91C_CAN_SMP & (0 << 24)); + return 1; + +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +/// Init of the CAN peripheral +/// \param baudrate Baudrate value (kB/s) +/// allowed values: 1000, 800, 500, 250, 125, 50, 25, 10 +/// \param canTransfer0 CAN0 structure transfer +/// \param canTransfer1 CAN1 structure transfer +/// \return return 1 if CAN has good baudrate and CAN is synchronized, +/// otherwise return 0 +//------------------------------------------------------------------------------ +unsigned char CAN_Init( unsigned int baudrate, + CanTransfer *canTransfer0, + CanTransfer *canTransfer1 ) +{ + unsigned char ret; + + // CAN Transmit Serial Data +#if defined (PINS_CAN_TRANSCEIVER_TXD) + PIO_Configure(pins_can_transceiver_txd, PIO_LISTSIZE(pins_can_transceiver_txd)); +#endif +#if defined (PINS_CAN_TRANSCEIVER_RXD) + // CAN Receive Serial Data + PIO_Configure(pins_can_transceiver_rxd, PIO_LISTSIZE(pins_can_transceiver_rxd)); +#endif + // CAN RS + PIO_Configure(&pin_can_transceiver_rs, PIO_LISTSIZE(pin_can_transceiver_rs)); +#if defined (PIN_CAN_TRANSCEIVER_RXEN) + // CAN RXEN + PIO_Configure(&pin_can_transceiver_rxen, PIO_LISTSIZE(pin_can_transceiver_rxen)); +#endif + + // Enable clock for CAN PIO +#if defined(AT91C_ID_PIOA) + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA); +#elif defined(AT91C_ID_PIOABCD) + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOABCD); +#elif defined(AT91C_ID_PIOABCDE) + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOABCDE); +#endif + + // Enable the CAN0 controller peripheral clock + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN0); + + // disable all IT + AT91C_BASE_CAN0->CAN_IDR = 0x1FFFFFFF; + + // Enable CANs Transceivers +#if defined (PIN_CAN_TRANSCEIVER_RXEN) + // Disable ultra Low Power mode + PIO_Set(&pin_can_transceiver_rxen); +#endif + // Normal Mode (versus Standby mode) + PIO_Clear(&pin_can_transceiver_rs); + + // Configure the AIC for CAN interrupts + IRQ_ConfigureIT(AT91C_ID_CAN0, 0x7, CAN0_Handler); + + // Enable the interrupt on the interrupt controller + IRQ_EnableIT(AT91C_ID_CAN0); + + if( CAN_BaudRateCalculate(AT91C_BASE_CAN0, baudrate) == 0 ) { + // Baudrate problem + TRACE_DEBUG("Baudrate CAN0 problem\n\r"); + return 0; + } + + pCAN0Transfer = canTransfer0; + +#if defined AT91C_BASE_CAN1 + if( canTransfer1 != NULL ) { + pCAN1Transfer = canTransfer1; + // Enable CAN1 Clocks + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_CAN1); + + // disable all IT + AT91C_BASE_CAN1->CAN_IDR = 0x1FFFFFFF; + + // Configure the AIC for CAN interrupts + IRQ_ConfigureIT(AT91C_ID_CAN1, 0x7, CAN1_Handler); + + // Enable the interrupt on the interrupt controller + IRQ_EnableIT(AT91C_ID_CAN1); + + if( CAN_BaudRateCalculate(AT91C_BASE_CAN1, baudrate) == 0 ) { + // Baudrate problem + TRACE_DEBUG("Baudrate CAN1 problem\n\r"); + return 0; + } + } +#endif + // Reset all mailbox + CAN_ResetAllMailbox(); + + // Enable the interrupt with all error cases + AT91C_BASE_CAN0->CAN_IER = AT91C_CAN_CERR // (CAN) CRC Error + | AT91C_CAN_SERR // (CAN) Stuffing Error + | AT91C_CAN_BERR // (CAN) Bit Error + | AT91C_CAN_FERR // (CAN) Form Error + | AT91C_CAN_AERR; // (CAN) Acknowledgment Error + +#if defined AT91C_BASE_CAN1 + if( canTransfer1 != NULL ) { + AT91C_BASE_CAN1->CAN_IER = AT91C_CAN_CERR // (CAN) CRC Error + | AT91C_CAN_SERR // (CAN) Stuffing Error + | AT91C_CAN_BERR // (CAN) Bit Error + | AT91C_CAN_FERR // (CAN) Form Error + | AT91C_CAN_AERR; // (CAN) Acknowledgment Error + } +#endif + + // Wait for CAN synchronisation + if( CAN_Synchronisation( ) == 1 ) { + ret = 1; + } + else { + ret = 0; + } + + return ret; +} + diff --git a/peripherals/can/can.h b/peripherals/can/can.h new file mode 100644 index 0000000..63a83b3 --- /dev/null +++ b/peripherals/can/can.h @@ -0,0 +1,113 @@ +/* ---------------------------------------------------------------------------- + * 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. + * ---------------------------------------------------------------------------- + */ + +#ifndef _CAN_H +#define _CAN_H + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +#define AT91C_CAN_TIMEOUT 100000 + +#define AT91C_TEST_NOK 0 +#define AT91C_TEST_OK 1 + +#define CAN_STATUS_SUCCESS 0 +#define CAN_STATUS_LOCKED 1 +#define CAN_STATUS_ABORTED 2 +#define CAN_STATUS_RESET 3 + +#if defined (AT91C_BASE_CAN) + #define AT91C_BASE_CAN0 AT91C_BASE_CAN +#endif +#if defined (AT91C_ID_CAN) + #define AT91C_ID_CAN0 AT91C_ID_CAN +#endif +#if defined (AT91C_BASE_CAN_MB0) + #define AT91C_BASE_CAN0_MB0 AT91C_BASE_CAN_MB0 + #define AT91C_BASE_CAN0_MB1 AT91C_BASE_CAN_MB1 + #define AT91C_BASE_CAN0_MB2 AT91C_BASE_CAN_MB2 + #define AT91C_BASE_CAN0_MB3 AT91C_BASE_CAN_MB3 + #define AT91C_BASE_CAN0_MB4 AT91C_BASE_CAN_MB4 + #define AT91C_BASE_CAN0_MB5 AT91C_BASE_CAN_MB5 + #define AT91C_BASE_CAN0_MB6 AT91C_BASE_CAN_MB6 + #define AT91C_BASE_CAN0_MB7 AT91C_BASE_CAN_MB7 +#endif +#if defined (AT91C_BASE_CAN_MB8) + #define AT91C_BASE_CAN0_MB8 AT91C_BASE_CAN_MB8 + #define AT91C_BASE_CAN0_MB9 AT91C_BASE_CAN_MB9 + #define AT91C_BASE_CAN0_MB10 AT91C_BASE_CAN_MB10 + #define AT91C_BASE_CAN0_MB11 AT91C_BASE_CAN_MB11 + #define AT91C_BASE_CAN0_MB12 AT91C_BASE_CAN_MB12 + #define AT91C_BASE_CAN0_MB13 AT91C_BASE_CAN_MB13 + #define AT91C_BASE_CAN0_MB14 AT91C_BASE_CAN_MB14 + #define AT91C_BASE_CAN0_MB15 AT91C_BASE_CAN_MB15 +#endif + +#define NUM_MAILBOX_MAX 16 + +//------------------------------------------------------------------------------ +// Types +//------------------------------------------------------------------------------ +typedef struct +{ + volatile unsigned char state; + volatile unsigned char can_number; + volatile unsigned char mailbox_number; + volatile unsigned char test_can; + volatile unsigned int mode_reg; + volatile unsigned int acceptance_mask_reg; + volatile unsigned int identifier; + volatile unsigned int data_low_reg; + volatile unsigned int data_high_reg; + volatile unsigned int control_reg; + volatile unsigned int mailbox_in_use; + volatile int size; +} CanTransfer; + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ +extern unsigned char CAN_Init( unsigned int baudrate, + CanTransfer *canTransferRead, + CanTransfer *canTransferWrite ); +extern void CAN_BasicTestSuite(void); +extern void CAN_disable( void ); +extern void CAN_ResetAllMailbox( void ); +extern void CAN_ResetTransfer( CanTransfer *pTransfer ); +extern void CAN_InitMailboxRegisters( CanTransfer *pTransfer ); +extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer ); + +extern unsigned char CAN_Write( CanTransfer *pTransfer ); +extern unsigned char CAN_Read( CanTransfer *pTransfer ); + +extern void CAN_BasicTestSuiteWithoutInterrupt( void ); +extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer ); +#endif // _CAN_H + -- cgit v1.2.3