2 This file is part of CanFestival, a library implementing CanOpen Stack.
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
5 AT91 Port: Peter CHRISTEN
7 See COPYING file for copyrights details.
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 2.1 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 //#define DEBUG_WAR_CONSOLE_ON
25 //#define DEBUG_ERR_CONSOLE_ON
28 #include "canfestival.h"
30 void can_irq_handler(void);
32 unsigned char canInit(unsigned int bitrate)
33 /******************************************************************************
34 Initialize the hardware to receive CAN messages and start the timer for the
38 ******************************************************************************/
41 AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
48 // Enable CAN Transceiver
51 // Init CAN Interrupt Source Level
52 AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, // CAN base address
53 AT91C_ID_CAN, // CAN ID
54 AT91C_AIC_PRIOR_HIGHEST, // Max priority
55 AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, // Level sensitive
56 can_irq_handler); // C Handler
58 AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_CAN);
62 // CANopen 10..500 kbit with 16 tq, sample point is at 14 tq
63 // all values are added to 1 by hardware
64 // Resynchronisation jump width (SJW) = 1 tq
65 // Propagation Time Segment (PRS) = 5 tq
66 // Phase Segment 1 (PHS1) = 8 tq
67 // Phase Segment 2 (PHS2) = 2 tq
69 AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN,
70 (AT91C_MASTER_CLOCK/16/1000/bitrate - 1) << 16 | 0x0471);
75 // Enable CAN and Wait for WakeUp Interrupt
76 // AT91F_CAN_EnableIt(AT91C_BASE_CAN, AT91C_CAN_WAKEUP);
77 AT91F_CAN_CfgModeReg(AT91C_BASE_CAN, AT91C_CAN_CANEN);
79 // Reset all mailsboxes (MBs), filters are zero (accept all) by clear all MB
80 // Set the lower MBs as rx buffer
81 for (i = 0; i < NB_RX_MB; i++, mb_ptr++)
82 // Configure receive MBs as receive buffer, last as receive overwrite
83 AT91F_InitMailboxRegisters(mb_ptr,
84 ((i < (NB_RX_MB - 1)) ? AT91C_CAN_MOT_RX : AT91C_CAN_MOT_RXOVERWRITE)
85 | AT91C_CAN_PRIOR, // Mailbox Mode Reg
86 0x00000000, // Mailbox Acceptance Mask Reg
87 0x00000000, // Mailbox ID Reg
88 0x00000000, // Mailbox Data Low Reg
89 0x00000000, // Mailbox Data High Reg
90 0x00000000); // Mailbox Control Reg
91 for ( ; i < NB_MB; i++, mb_ptr++)
92 // Configure transmit MBs
93 AT91F_InitMailboxRegisters(mb_ptr,
95 | AT91C_CAN_PRIOR, // Mailbox Mode Reg
96 0x00000000, // Mailbox Acceptance Mask Reg
97 0x00000000, // Mailbox ID Reg
98 0x00000000, // Mailbox Data Low Reg
99 0x00000000, // Mailbox Data High Reg
100 0x00000000); // Mailbox Control Reg
101 // Enable Reception on all receive Mailboxes
102 AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, RX_INT_MSK);
103 // Enable all receive interrupts
104 AT91F_CAN_EnableIt(AT91C_BASE_CAN, RX_INT_MSK);
108 unsigned char canSend(CAN_PORT notused, Message *m)
109 /******************************************************************************
110 The driver send a CAN message passed from the CANopen stack
111 INPUT CAN_PORT is not used (only 1 avaiable)
112 Message *m pointer to message to send
113 OUTPUT 1 if hardware -> CAN frame
114 ******************************************************************************/
117 AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0 + START_TX_MB;
119 if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & TX_INT_MSK) == 0)
120 return 0; // No free MB for sending
122 for (mask = 1 << START_TX_MB;
123 (mask & TX_INT_MSK) && !(AT91F_CAN_GetStatus(AT91C_BASE_CAN) & mask);
124 mask <<= 1, mb_ptr++) // Search the first free MB
127 AT91F_CAN_CfgMessageIDReg(mb_ptr, m->cob_id, 0); // Set cob id
128 // Mailbox Control Register, set remote transmission request and data lenght code
129 AT91F_CAN_CfgMessageCtrlReg(mb_ptr, m->rtr ? AT91C_CAN_MRTR : 0 | (m->len << 16));
130 AT91F_CAN_CfgMessageDataLow(mb_ptr, *(UNS32*)(&m->data[0]));// Mailbox Data Low Reg
131 AT91F_CAN_CfgMessageDataHigh(mb_ptr, *(UNS32*)(&m->data[4]));// Mailbox Data High Reg
132 // Start sending by writing the MB configuration register to transmit
133 AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, mask);
134 return 1; // successful
137 unsigned char canReceive(Message *m)
138 /******************************************************************************
139 The driver passes a received CAN message to the stack
140 INPUT Message *m pointer to received CAN message
141 OUTPUT 1 if a message received
142 ******************************************************************************/
145 AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
147 if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & RX_INT_MSK) == 0)
148 return 0; // Nothing received
151 (mask & RX_INT_MSK) && !(AT91F_CAN_GetStatus(AT91C_BASE_CAN) & mask);
152 mask <<= 1, mb_ptr++) // Search the first MB received
155 m->cob_id = AT91F_CAN_GetFamilyID(mb_ptr);
156 m->len = (AT91F_CAN_GetMessageStatus(mb_ptr) & AT91C_CAN_MDLC) >> 16;
157 m->rtr = (AT91F_CAN_GetMessageStatus(mb_ptr) & AT91C_CAN_MRTR) ? 1 : 0;
158 *(UNS32*)(&m->data[0]) = AT91F_CAN_GetMessageDataLow(mb_ptr);
159 *(UNS32*)(&m->data[4]) = AT91F_CAN_GetMessageDataHigh(mb_ptr);
160 // Enable Reception on Mailbox
161 AT91F_CAN_CfgMessageModeReg(mb_ptr, AT91C_CAN_MOT_RX | AT91C_CAN_PRIOR);
162 AT91F_CAN_InitTransferRequest(AT91C_BASE_CAN, mask);
163 return 1; // message received
166 /******************************************************************************
168 ******************************* CAN INTERRUPT *******************************/
170 void can_irq_handler(void)
171 /******************************************************************************
173 ******************************************************************************/
175 volatile unsigned int status;
176 static Message m = Message_Initializer; // contain a CAN message
178 status = AT91F_CAN_GetStatus(AT91C_BASE_CAN) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN);
180 if(status & RX_INT_MSK)
182 if (canReceive(&m)) // a message received
183 canDispatch(&ObjDict_Data, &m); // process it