at90can.c
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 /*
3  * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $Id: at90can.c 7538 2009-04-16 13:07:33Z fabian $
28  */
29 // ----------------------------------------------------------------------------
30 
31 #include "at90can_private.h"
32 #ifdef SUPPORT_FOR_AT90CAN__
33 
34 #include <avr/pgmspace.h>
35 #include "can_buffer.h"
36 
37 // ----------------------------------------------------------------------------
38 
39 const uint8_t _at90can_cnf[8][3] PROGMEM = {
40  // 10 kbps
41  { 0x7E,
42  0x6E,
43  0x7F
44  },
45  // 20 kbps
46  { 0x62,
47  0x0C,
48  0x37
49  },
50  // 50 kbps
51  { 0x26,
52  0x0C,
53  0x37
54  },
55  // 100 kbps
56  { 0x12,
57  0x0C,
58  0x37
59  },
60  // 125 kbps
61  { 0x0E,
62  0x0C,
63  0x37
64  },
65  // 250 kbps
66  { 0x06,
67  0x0C,
68  0x37
69  },
70  // 500 kbps
71  { 0x02,
72  0x0C,
73  0x37
74  },
75  // 1 Mbps
76  { 0x00,
77  0x0C,
78  0x36
79  }
80 };
81 
82 // ----------------------------------------------------------------------------
83 
84 #if CAN_RX_BUFFER_SIZE > 0
85 can_buffer_t can_rx_buffer;
86 can_t can_rx_list[CAN_RX_BUFFER_SIZE];
87 #else
88 volatile uint8_t _messages_waiting;
89 #endif
90 
91 #if CAN_TX_BUFFER_SIZE > 0
92 can_buffer_t can_tx_buffer;
93 can_t can_tx_list[CAN_TX_BUFFER_SIZE];
94 
95 volatile uint8_t _transmission_in_progress = 0;
96 #else
97 volatile uint8_t _free_buffer;
98 #endif
99 
100 // ----------------------------------------------------------------------------
101 // get next free MOb
102 
103 uint8_t _find_free_mob(void)
104 {
105  #if CAN_TX_BUFFER_SIZE == 0
106  if (_free_buffer == 0)
107  return 0xff;
108  #elif CAN_FORCE_TX_ORDER
109  if (_transmission_in_progress)
110  return 0xff;
111  #endif
112 
113  uint8_t i;
114  for (i = 0;i < 15;i++)
115  {
116  // load MOb page
117  CANPAGE = i << 4;
118 
119  // check if MOb is in use
120  if ((CANCDMOB & ((1 << CONMOB1) | (1 << CONMOB0))) == 0)
121  return i;
122  }
123 
124  return 0xff;
125 }
126 
127 // ----------------------------------------------------------------------------
128 // disable interrupt of corresponding MOb
129 
130 void _disable_mob_interrupt(uint8_t mob)
131 {
132  if (mob < 8)
133  CANIE2 &= ~(1 << mob);
134  else
135  CANIE1 &= ~(1 << (mob - 8));
136 }
137 
138 // ----------------------------------------------------------------------------
139 // enable interrupt of corresponding MOb
140 
141 void _enable_mob_interrupt(uint8_t mob)
142 {
143  if (mob < 8)
144  CANIE2 |= (1 << mob);
145  else
146  CANIE1 |= (1 << (mob - 8));
147 }
148 
149 // ----------------------------------------------------------------------------
150 
151 bool at90can_init(uint8_t bitrate)
152 {
153  if (bitrate >= 8)
154  return false;
155 
156  // switch CAN controller to reset mode
157  CANGCON |= (1 << SWRES);
158 
159  // set CAN Bit Timing
160  // (see datasheet page 260)
161  CANBT1 = pgm_read_byte(&_at90can_cnf[bitrate][0]);
162  CANBT2 = pgm_read_byte(&_at90can_cnf[bitrate][1]);
163  CANBT3 = pgm_read_byte(&_at90can_cnf[bitrate][2]);
164 
165  // activate CAN transmit- and receive-interrupt
166  CANGIT = 0;
167  CANGIE = (1 << ENIT) | (1 << ENRX) | (1 << ENTX);
168 
169  // set timer prescaler to 199 which results in a timer
170  // frequency of 10 kHz (at 16 MHz)
171  CANTCON = 199;
172 
173  // disable all filters
174  at90can_disable_filter( 0xff );
175 
176  #if CAN_RX_BUFFER_SIZE > 0
177  can_buffer_init( &can_rx_buffer, CAN_RX_BUFFER_SIZE, can_rx_list );
178  #endif
179 
180  #if CAN_TX_BUFFER_SIZE > 0
181  can_buffer_init( &can_tx_buffer, CAN_TX_BUFFER_SIZE, can_tx_list );
182  #endif
183 
184  // activate CAN controller
185  CANGCON = (1 << ENASTB);
186 
187  return true;
188 }
189 
190 // ----------------------------------------------------------------------------
191 // The CANPAGE register have to be restored after usage, otherwise it
192 // could cause trouble in the application programm.
193 
194 ISR(CANIT_vect)
195 {
196  uint8_t canpage;
197  uint8_t mob;
198 
199  if ((CANHPMOB & 0xF0) != 0xF0)
200  {
201  // save MOb page register
202  canpage = CANPAGE;
203 
204  // select MOb page with the highest priority
205  CANPAGE = CANHPMOB & 0xF0;
206  mob = (CANHPMOB >> 4);
207 
208  // a interrupt is only generated if a message was transmitted or received
209  if (CANSTMOB & (1 << TXOK))
210  {
211  // clear MOb
212  CANSTMOB &= 0;
213  CANCDMOB = 0;
214 
215  #if CAN_TX_BUFFER_SIZE > 0
216  can_t *buf = can_buffer_get_dequeue_ptr(&can_tx_buffer);
217 
218  // check if there are any another messages waiting
219  if (buf != NULL)
220  {
221  at90can_copy_message_to_mob( buf );
222  can_buffer_dequeue(&can_tx_buffer);
223 
224  // enable transmission
225  CANCDMOB |= (1<<CONMOB0);
226  }
227  else {
228  // buffer underflow => no more messages to send
229  _disable_mob_interrupt(mob);
230  _transmission_in_progress = 0;
231  }
232  #else
233  _free_buffer++;
234 
235  // reset interrupt
236  if (mob < 8)
237  CANIE2 &= ~(1 << mob);
238  else
239  CANIE1 &= ~(1 << (mob - 8));
240  #endif
241 
243  }
244  else {
245  // a message was received successfully
246  #if CAN_RX_BUFFER_SIZE > 0
247  can_t *buf = can_buffer_get_enqueue_ptr(&can_rx_buffer);
248 
249  if (buf != NULL)
250  {
251  // read message
252  at90can_copy_mob_to_message( buf );
253 
254  // push it to the list
255  can_buffer_enqueue(&can_rx_buffer);
256  }
257  else {
258  // buffer overflow => reject message
259  // FIXME inform the user
260  }
261 
262  // clear flags
263  CANSTMOB &= 0;
264  CANCDMOB = (1 << CONMOB1) | (CANCDMOB & (1 << IDE));
265  #else
266  _messages_waiting++;
267 
268  // reset interrupt
269  if (mob < 8)
270  CANIE2 &= ~(1 << mob);
271  else
272  CANIE1 &= ~(1 << (mob - 8));
273  #endif
274 
276  }
277 
278  // restore MOb page register
279  CANPAGE = canpage;
280  }
281  else
282  {
283  // no MOb matches with the interrupt => general interrupt
284  CANGIT |= 0;
285  }
286 }
287 
288 // ----------------------------------------------------------------------------
289 // Overflow of CAN timer
290 ISR(OVRIT_vect) {}
291 
292 #endif // SUPPORT_FOR_AT90CAN__
CAN_INDICATE_TX_TRAFFIC_FUNCTION
#define CAN_INDICATE_TX_TRAFFIC_FUNCTION
Definition: can_private.h:133
can_t
Datenstruktur zum Aufnehmen von CAN Nachrichten.
Definition: can.h:177
can_buffer_dequeue
void can_buffer_dequeue(can_buffer_t *buf)
can_buffer_get_enqueue_ptr
can_t * can_buffer_get_enqueue_ptr(can_buffer_t *buf)
IDE
#define IDE
Definition: mcp2515_defs.h:296
can_buffer.h
can_buffer_get_dequeue_ptr
can_t * can_buffer_get_dequeue_ptr(can_buffer_t *buf)
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
at90can_private.h
can_buffer_enqueue
void can_buffer_enqueue(can_buffer_t *buf)
can_buffer_t
Definition: can_buffer.h:39
CAN_TX_BUFFER_SIZE
#define CAN_TX_BUFFER_SIZE
Definition: can_private.h:42
can_buffer_init
void can_buffer_init(can_buffer_t *buf, uint8_t size, can_t *list)
NULL
#define NULL
Nullzeiger.
Definition: utils.h:64
CAN_RX_BUFFER_SIZE
#define CAN_RX_BUFFER_SIZE
Definition: can_private.h:50
PROGMEM
const uint8_t can_filter[] PROGMEM
Definition: main.c:60
CAN_INDICATE_RX_TRAFFIC_FUNCTION
#define CAN_INDICATE_RX_TRAFFIC_FUNCTION
Definition: can_private.h:137


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:02