|
1 /* |
|
2 This file is part of CanFestival, a library implementing CanOpen Stack. |
|
3 |
|
4 Copyright (C): Edouard TISSERANT and Francis DUPIN |
|
5 AVR Port: Andreas GLAUSER and 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_AVR.h" |
|
28 #include "canfestival.h" |
|
29 |
|
30 volatile unsigned char msg_received = 0; |
|
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 bitrate bitrate in kilobit |
|
37 OUTPUT 1 if successful |
|
38 ******************************************************************************/ |
|
39 { |
|
40 unsigned char i,k; |
|
41 //- Pull-up on TxCAN & RxCAN one by one to use bit-addressing |
|
42 CAN_PORT_DIR &= ~(1<<CAN_INPUT_PIN ); |
|
43 CAN_PORT_DIR &= ~(1<<CAN_OUTPUT_PIN); |
|
44 CAN_PORT_OUT |= (1<<CAN_INPUT_PIN ); |
|
45 CAN_PORT_OUT |= (1<<CAN_OUTPUT_PIN); |
|
46 |
|
47 Can_reset(); // Reset the CAN controller |
|
48 |
|
49 if (bitrate <= 500) |
|
50 { |
|
51 // CANopen 10..500 kbit with 16 tq, sample point is at 14 tq |
|
52 // all values are added to 1 by hardware |
|
53 // Resynchronisation jump width (SJW) = 1 tq |
|
54 // Propagation Time Segment (PRS) = 5 tq |
|
55 // Phase Segment 1 (PHS1) = 8 tq |
|
56 // Phase Segment 2 (PHS2) = 2 tq |
|
57 // Total = 16 tq |
|
58 CANBT1 = ((F_CPU/16/1000/bitrate-1) << BRP); // set bitrate |
|
59 CANBT2 = ((1-1) << SJW) |((5-1) << PRS); // set SJW, PRS |
|
60 CANBT3 = (((2-1) << PHS2) | ((8-1) << PHS1) | (1<<SMP)); // set PHS1, PHS2, 3 sample points |
|
61 } |
|
62 else |
|
63 return 0; |
|
64 |
|
65 // Reset all mailsboxes (MObs), filters are zero (accept all) by clear all MOb |
|
66 // Set the lower MObs as rx buffer |
|
67 for (i = 0; i < NB_MOB; i++) |
|
68 { |
|
69 Can_set_mob(i); // Change to MOb with the received message |
|
70 Can_clear_mob(); // All MOb Registers=0 |
|
71 for (k = 0; k < NB_DATA_MAX; k++) |
|
72 CANMSG = 0; // MOb data FIFO |
|
73 if (i < NB_RX_MOB) // Is receive MOb |
|
74 Can_config_rx_buffer(); // configure as receive buffer |
|
75 } |
|
76 // The tx MOb is still disabled, it will be set to tx mode when the first message will be sent |
|
77 // Enable the general CAN interrupts |
|
78 CANGIE = (1 << ENIT) | (1 << ENRX) | (1 << ENTX) | (0 << ENERR) | (0 << ENERG) | (0 << ENOVRT); |
|
79 CANIE1 = 0x7F; // Enable the interrupts of all MObs (0..14) |
|
80 CANIE2 = 0xFF; |
|
81 Can_enable(); // Enable the CAN bus controller |
|
82 return 1; |
|
83 } |
|
84 |
|
85 unsigned char canSend(CAN_PORT notused, Message *m) |
|
86 /****************************************************************************** |
|
87 The driver send a CAN message passed from the CANopen stack |
|
88 INPUT CAN_PORT is not used (only 1 avaiable) |
|
89 Message *m pointer to message to send |
|
90 OUTPUT 1 if hardware -> CAN frame |
|
91 ******************************************************************************/ |
|
92 { |
|
93 unsigned char i; |
|
94 |
|
95 for (i = START_TX_MOB; i < NB_MOB; i++) // Search the first free MOb |
|
96 { |
|
97 Can_set_mob(i); // Change to MOb |
|
98 if ((CANCDMOB & CONMOB_MSK) == 0) // MOb disabled = free |
|
99 { |
|
100 break; |
|
101 } |
|
102 } |
|
103 if (i < NB_MOB) // free MOb found |
|
104 { |
|
105 Can_set_mob(i); // Switch to the sending messagebox |
|
106 Can_set_std_id(m->cob_id); // Set cob id |
|
107 if (m->rtr) // Set remote transmission request |
|
108 Can_set_rtr(); |
|
109 Can_set_dlc(m->len); // Set data lenght code |
|
110 |
|
111 for (i= 0; i < (m->len); i++) // Add data bytes to the MOb |
|
112 CANMSG = m->data[i]; |
|
113 // Start sending by writing the MB configuration register to transmit |
|
114 Can_config_tx(); // Set the last MOb to transmit mode |
|
115 return 1; // succesful |
|
116 } |
|
117 else |
|
118 return 0; // not succesful |
|
119 } |
|
120 |
|
121 unsigned char canReceive(Message *m) |
|
122 /****************************************************************************** |
|
123 The driver pass a received CAN message to the stack |
|
124 INPUT Message *m pointer to received CAN message |
|
125 OUTPUT 1 if a message received |
|
126 ******************************************************************************/ |
|
127 { |
|
128 unsigned char i; |
|
129 |
|
130 if (msg_received == 0) |
|
131 return 0; // Nothing received |
|
132 |
|
133 for (i = 0; i < NB_RX_MOB; i++) // Search the first MOb received |
|
134 { |
|
135 Can_set_mob(i); // Change to MOb |
|
136 if ((CANCDMOB & CONMOB_MSK) == 0) // MOb disabled = received |
|
137 { |
|
138 msg_received--; |
|
139 break; |
|
140 } |
|
141 } |
|
142 if (i < NB_RX_MOB) // message found |
|
143 { |
|
144 Can_get_std_id(m->cob_id); // Get cob id |
|
145 m->rtr = Can_get_rtr(); // Get remote transmission request |
|
146 m->len = Can_get_dlc(); // Get data lenght code |
|
147 for (i= 0; i < (m->len); i++) // get data bytes from the MOb |
|
148 m->data[i] = CANMSG; |
|
149 Can_config_rx_buffer(); // reset the MOb for receive |
|
150 return 1; // message received |
|
151 } |
|
152 else // no message found |
|
153 { |
|
154 msg_received = 0; // reset counter |
|
155 return 0; // no message received |
|
156 } |
|
157 } |
|
158 |
|
159 #ifdef __IAR_SYSTEMS_ICC__ |
|
160 #pragma type_attribute = __interrupt |
|
161 #pragma vector=CANIT_vect |
|
162 void CANIT_interrupt(void) |
|
163 #else // GCC |
|
164 ISR(CANIT_vect) |
|
165 #endif // GCC |
|
166 /****************************************************************************** |
|
167 CAN Interrupt |
|
168 ******************************************************************************/ |
|
169 { |
|
170 unsigned char i; |
|
171 |
|
172 if (CANGIT & (1 << CANIT)) // is a messagebox interrupt |
|
173 { |
|
174 if ((CANSIT1 & TX_INT_MSK) == 0) // is a Rx interrupt |
|
175 { |
|
176 for (i = 0; (i < NB_RX_MOB) && (CANGIT & (1 << CANIT)); i++) // Search the first MOb received |
|
177 { |
|
178 Can_set_mob(i); // Change to MOb |
|
179 if (CANSTMOB & MOB_RX_COMPLETED) // receive ok |
|
180 { |
|
181 Can_clear_status_mob(); // Clear status register |
|
182 Can_mob_abort(); // disable the MOb = received |
|
183 msg_received++; |
|
184 } |
|
185 else if (CANSTMOB & ~MOB_RX_COMPLETED) // error |
|
186 { |
|
187 Can_clear_status_mob(); // Clear status register |
|
188 Can_config_rx_buffer(); // reconfigure as receive buffer |
|
189 } |
|
190 } |
|
191 } |
|
192 else // is a Tx interrupt |
|
193 { |
|
194 for (i = NB_RX_MOB; i < NB_MOB; i++) // Search the first MOb transmitted |
|
195 { |
|
196 Can_set_mob(i); // change to MOb |
|
197 if (CANSTMOB) // transmission ok or error |
|
198 { |
|
199 Can_clear_status_mob(); // clear status register |
|
200 CANCDMOB = 0; // disable the MOb |
|
201 break; |
|
202 } |
|
203 } |
|
204 } |
|
205 } |
|
206 |
|
207 // Bus Off Interrupt Flag |
|
208 if (CANGIT & (1 << BOFFIT)) // Finaly clear the interrupt status register |
|
209 { |
|
210 CANGIT |= (1 << BOFFIT); // Clear the interrupt flag |
|
211 } |
|
212 else |
|
213 CANGIT |= (1 << BXOK) | (1 << SERG) | (1 << CERG) | (1 << FERG) | (1 << AERG);// Finaly clear other interrupts |
|
214 } |
|
215 |
|
216 #ifdef __IAR_SYSTEMS_ICC__ |
|
217 #pragma type_attribute = __interrupt |
|
218 #pragma vector=OVRIT_vect |
|
219 void OVRIT_interrupt(void) |
|
220 #else // GCC |
|
221 ISR(OVRIT_vect) |
|
222 #endif // GCC |
|
223 /****************************************************************************** |
|
224 CAN Timer Interrupt |
|
225 ******************************************************************************/ |
|
226 { |
|
227 CANGIT |= (1 << OVRTIM); |
|
228 } |
|
229 |