| /* ---------------------------------------------------------------------------- | |
| * 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; | |
| 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 | |
| AIC_DisableIT(AT91C_ID_CAN0); | |
| // disable all IT | |
| AT91C_BASE_CAN0->CAN_IDR = 0x1FFFFFFF; | |
| #if defined AT91C_BASE_CAN1 | |
| AIC_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 | |
| AIC_ConfigureIT(AT91C_ID_CAN0, AT91C_AIC_PRIOR_HIGHEST, CAN0_Handler); | |
| // Enable the interrupt on the interrupt controller | |
| AIC_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 | |
| AIC_ConfigureIT(AT91C_ID_CAN1, AT91C_AIC_PRIOR_HIGHEST, CAN1_Handler); | |
| // Enable the interrupt on the interrupt controller | |
| AIC_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; | |
| } | |