diff options
author | Harald Welte <laforge@gnumonks.org> | 2011-07-04 20:52:54 +0200 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2011-07-04 20:52:54 +0200 |
commit | 044ad7c3987460ede48ff27afd6bdb0ca05a0432 (patch) | |
tree | 924818cdb0d39ca08aec540d18da7bd406eaae8c /peripherals/can |
import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v1501120100901_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
Diffstat (limited to 'peripherals/can')
-rw-r--r-- | peripherals/can/can.c | 1066 | ||||
-rw-r--r-- | peripherals/can/can.h | 113 |
2 files changed, 1179 insertions, 0 deletions
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 <board.h>
+#include <pio/pio.h>
+#include <utility/trace.h>
+#include <irq/irq.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
+ 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
+
|