]> rtime.felk.cvut.cz Git - CanFestival-3.git/blob - drivers/AT91/can_AT91.c
V0.8
[CanFestival-3.git] / drivers / AT91 / can_AT91.c
1 /*
2 This file is part of CanFestival, a library implementing CanOpen Stack.
3
4 Copyright (C): Edouard TISSERANT and Francis DUPIN
5 AT91 Port: Peter CHRISTEN
6
7 See COPYING file for copyrights details.
8
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.
13
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.
18
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
22 */
23
24 //#define DEBUG_WAR_CONSOLE_ON
25 //#define DEBUG_ERR_CONSOLE_ON
26
27 #include "can_AT91.h"
28 #include "canfestival.h"
29
30 void can_irq_handler(void);
31
32 unsigned char canInit(unsigned int bitrate)
33 /******************************************************************************
34 Initialize the hardware to receive CAN messages and start the timer for the
35 CANopen stack.
36 INPUT   
37 OUTPUT  
38 ******************************************************************************/
39 {
40   unsigned char i;
41   AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
42
43   // Enable CAN PIOs
44   AT91F_CAN_CfgPIO();
45   // Enable CAN Clock
46   AT91F_CAN_CfgPMC();
47
48   // Enable CAN Transceiver
49   AT91F_PIOA_CfgPMC();
50
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
57
58   AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_CAN);
59
60   if (bitrate <= 500)
61   {
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
68     // Total                                    = 16 tq
69     AT91F_CAN_CfgBaudrateReg(AT91C_BASE_CAN,
70                              (AT91C_MASTER_CLOCK/16/1000/bitrate - 1) << 16 | 0x0471);
71   }
72   else
73     return 0;
74
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);
78
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,
94                                 AT91C_CAN_MOT_TX
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);
105   return 1;
106 }
107
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 ******************************************************************************/
115 {
116   unsigned int mask;
117   AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0 + START_TX_MB;
118
119   if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & TX_INT_MSK) == 0)
120     return 0;                   // No free MB for sending
121
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
125   {
126   }
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
135 }
136
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 ******************************************************************************/
143 {
144   unsigned int mask;
145   AT91S_CAN_MB *mb_ptr = AT91C_BASE_CAN_MB0;
146
147   if ((AT91F_CAN_GetStatus(AT91C_BASE_CAN) & RX_INT_MSK) == 0)
148     return 0;           // Nothing received
149
150   for (mask = 1;
151        (mask & RX_INT_MSK) && !(AT91F_CAN_GetStatus(AT91C_BASE_CAN) & mask);
152         mask <<= 1, mb_ptr++)   // Search the first MB received
153   {
154   }
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
164 }
165
166 /******************************************************************************
167
168  ******************************* CAN INTERRUPT  *******************************/
169
170 void can_irq_handler(void)
171 /******************************************************************************
172 CAN Interrupt
173 ******************************************************************************/
174 {
175   volatile unsigned int status;
176   static Message m = Message_Initializer;               // contain a CAN message
177                 
178   status = AT91F_CAN_GetStatus(AT91C_BASE_CAN) & AT91F_CAN_GetInterruptMaskStatus(AT91C_BASE_CAN);
179
180   if(status & RX_INT_MSK)
181   {     // Rx Interrupt
182     if (canReceive(&m))                 // a message received
183       canDispatch(&ObjDict_Data, &m);         // process it
184   }
185 }