author | Edouard Tisserant |
Sat, 12 Oct 2013 09:09:04 +0900 | |
changeset 788 | 6121ebff4da6 |
parent 601 | efb6e88ad27f |
permissions | -rw-r--r-- |
375 | 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 |
||
384 | 159 |
/***************************************************************************/ |
160 |
unsigned char canChangeBaudRate_driver( CAN_HANDLE fd, char* baud) |
|
161 |
{ |
|
162 |
||
163 |
return 0; |
|
164 |
} |
|
165 |
||
375 | 166 |
#ifdef __IAR_SYSTEMS_ICC__ |
167 |
#pragma type_attribute = __interrupt |
|
168 |
#pragma vector=CANIT_vect |
|
169 |
void CANIT_interrupt(void) |
|
170 |
#else // GCC |
|
171 |
ISR(CANIT_vect) |
|
172 |
#endif // GCC |
|
173 |
/****************************************************************************** |
|
174 |
CAN Interrupt |
|
175 |
******************************************************************************/ |
|
176 |
{ |
|
601
efb6e88ad27f
Fixed bug in the AVR-CAN driver: the CAN interrupt changes the
edouard
parents:
384
diff
changeset
|
177 |
unsigned char saved_page = CANPAGE; |
375 | 178 |
unsigned char i; |
179 |
||
180 |
if (CANGIT & (1 << CANIT)) // is a messagebox interrupt |
|
181 |
{ |
|
182 |
if ((CANSIT1 & TX_INT_MSK) == 0) // is a Rx interrupt |
|
183 |
{ |
|
184 |
for (i = 0; (i < NB_RX_MOB) && (CANGIT & (1 << CANIT)); i++) // Search the first MOb received |
|
185 |
{ |
|
186 |
Can_set_mob(i); // Change to MOb |
|
187 |
if (CANSTMOB & MOB_RX_COMPLETED) // receive ok |
|
188 |
{ |
|
189 |
Can_clear_status_mob(); // Clear status register |
|
190 |
Can_mob_abort(); // disable the MOb = received |
|
191 |
msg_received++; |
|
192 |
} |
|
193 |
else if (CANSTMOB & ~MOB_RX_COMPLETED) // error |
|
194 |
{ |
|
195 |
Can_clear_status_mob(); // Clear status register |
|
196 |
Can_config_rx_buffer(); // reconfigure as receive buffer |
|
197 |
} |
|
198 |
} |
|
199 |
} |
|
200 |
else // is a Tx interrupt |
|
201 |
{ |
|
202 |
for (i = NB_RX_MOB; i < NB_MOB; i++) // Search the first MOb transmitted |
|
203 |
{ |
|
204 |
Can_set_mob(i); // change to MOb |
|
205 |
if (CANSTMOB) // transmission ok or error |
|
206 |
{ |
|
207 |
Can_clear_status_mob(); // clear status register |
|
208 |
CANCDMOB = 0; // disable the MOb |
|
209 |
break; |
|
210 |
} |
|
211 |
} |
|
212 |
} |
|
213 |
} |
|
214 |
||
601
efb6e88ad27f
Fixed bug in the AVR-CAN driver: the CAN interrupt changes the
edouard
parents:
384
diff
changeset
|
215 |
CANPAGE = saved_page; |
efb6e88ad27f
Fixed bug in the AVR-CAN driver: the CAN interrupt changes the
edouard
parents:
384
diff
changeset
|
216 |
|
375 | 217 |
// Bus Off Interrupt Flag |
218 |
if (CANGIT & (1 << BOFFIT)) // Finaly clear the interrupt status register |
|
219 |
{ |
|
220 |
CANGIT |= (1 << BOFFIT); // Clear the interrupt flag |
|
221 |
} |
|
222 |
else |
|
223 |
CANGIT |= (1 << BXOK) | (1 << SERG) | (1 << CERG) | (1 << FERG) | (1 << AERG);// Finaly clear other interrupts |
|
224 |
} |
|
225 |
||
226 |
#ifdef __IAR_SYSTEMS_ICC__ |
|
227 |
#pragma type_attribute = __interrupt |
|
228 |
#pragma vector=OVRIT_vect |
|
229 |
void OVRIT_interrupt(void) |
|
230 |
#else // GCC |
|
231 |
ISR(OVRIT_vect) |
|
232 |
#endif // GCC |
|
233 |
/****************************************************************************** |
|
234 |
CAN Timer Interrupt |
|
235 |
******************************************************************************/ |
|
236 |
{ |
|
237 |
CANGIT |= (1 << OVRTIM); |
|
238 |
} |
|
239 |