16FXlib
can3.c
1 //*****************************************************************************
2 // Author : Nicolas Weber
3 // Created : 23.04.2010
4 // Target MCU : Fujitsu MB96300 series
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program. If not, see <http://www.gnu.org/licenses/>.
18 //
19 //*****************************************************************************
20 
21 #include "can3.h"
22 #include "can3.cfg.h"
23 #include "../util.h"
24 #include "../interrupts.h"
25 #include "mb96348hs.h"
26 
27 #define _AC(x) (((uint32_t)x) << 22)
28 #define _SC(x) (((uint32_t)x) << 16)
29 #define CAN3_RETURN_ERROR(x,y) if(x) return y
30 #define CAN3_RETURN_UBOUNDS(x,max,out) if(x > max) return out
31 #define CAN3_RETURN_SBOUNDS(x,min,max,out) if(x < min || x > max) return out
32 #define CAN3_EXTRACT_DESTINATION(id) (uint8_t)((id & 0x0FC00000) >> 22)
33 #define CAN3_EXTRACT_SOURCE(id) (uint8_t)((id & 0x003F0000) >> 16)
34 #define CAN3_EXTRACT_ID(id) (uint16_t)(id & 0x0000FFFF)
35 #define CAN3_EXTRACT_MULTICAST(id) (uint8_t)((id & 0x10000000) >> 28)
36 #define CAN3_FREE_BUFFER 255
37 
38 __interrupt void IRQHandler_CAN (void);
39 
40 struct DataBuffer {
41  uint8_t buffer;
42  uint8_t data[8];
43  uint8_t source;
44  uint8_t len;
45  uint16_t id;
46 };
47 
48 struct DataBuffer databuffer[CAN3_DATABUFFER_SIZE];
49 
50 IRQHandler irqHandler[CAN3_MAX_IRQHANDLER];
51 
52 uint8_t can3_address;
53 uint32_t can3_usedbuffer;
54 
55 static void can3_internal_block(uint8_t buffer) {
56  can3_usedbuffer |= _BV(buffer - 1);
57 }
58 
59 static uint8_t can3_internal_getFreeBuffer(void) {
60  uint32_t check;
61  uint8_t buffer;
62 
63  //check vars
64  CAN3_RETURN_UBOUNDS(can3_usedbuffer,0xFFFD,0); //no free buffer
65 
66  //init vars
67  check = 1;
68  buffer = 1; //offset, 1-32
69 
70  while(check < 0xFFFF) {
71  if(!(check & can3_usedbuffer)) {
72  return buffer;
73  }
74 
75  //increment
76  check = check << 1;
77  buffer++;
78  }
79 
80  //should never happen
81  return 0;
82 }
83 
84 static struct DataBuffer* can3_internal_getFreeDataBuffer(void) {
85  uint8_t i;
86 
87  for(i = 0; i < CAN3_DATABUFFER_SIZE; i++) {
88  if(databuffer[i].buffer == CAN3_FREE_BUFFER)
89  return &databuffer[i];
90  }
91 
92  return 0;
93 }
94 
95 static void can3_irqHandler(void) {
96  struct DataBuffer* data;
97  uint32_t received_id = 0;
98  uint8_t buffer = INTR0;
99 
100  if(!(_BV(buffer - 1) & can3_usedbuffer)) return;
101  if(!(data = can3_internal_getFreeDataBuffer())) return;
102 
103  if(can_buffer_newData(buffer)) {
104  data->len = can_buffer_getData(buffer, data->data, &received_id);
105 
106  //no data or unmatching multicast?
107 #ifndef CAN3_SKIP_ADDRESS_CHECK
108  if(data->len == 0 || (CAN3_EXTRACT_MULTICAST(received_id) == 0 && CAN3_EXTRACT_DESTINATION(received_id) != can3_address)) {
109  return;
110  }
111 #endif
112 
113  //extract data
114  data->buffer = buffer;
115  data->source = CAN3_EXTRACT_SOURCE(received_id);
116  data->id = CAN3_EXTRACT_ID(received_id);
117  }
118 }
119 
121  uint8_t i;
123 
124  CAN3_RETURN_ERROR(!can_init(CAN3_BAUDRATE,1),0); //Auto enable interrupts
125 
126  interrupts_init();
128  interrupts_setHandler(33, 2, IRQHandler_CAN);
130 
131  //address
132  can3_address = address;
133 
134  //buffer
135  can3_usedbuffer = 0x0000;
136 
137  //init buffer
138  for(i = 0; i < CAN3_DATABUFFER_SIZE; i++)
139  databuffer[i].buffer = CAN3_FREE_BUFFER;
140 
141  //init IRQ Handler
142  for(i = 0; i < CAN3_MAX_IRQHANDLER; i++)
143  irqHandler[i] = 0;
144 
145  can3_registerIRQHandler(&can3_irqHandler);
146 
147  return 1;
148 }
149 
150 uint8_t can3_send(uint8_t dest, uint16_t uid, uint8_t* data, uint8_t len, uint8_t interrupt) {
151  uint8_t buffer;
152  uint16_t timeout = 0;
153  uint32_t id;
155 
156  //checks
157  RETURN_ERROR(can3_address,CAN3_MAX_ADDRESS); //wrong source address
158 
159  if(dest != CAN3_MULTICAST) {
160  RETURN_ERROR(dest,CAN3_MAX_ADDRESS); //wrong destination address
161  id = _AC(dest) | _SC(can3_address) | (uint32_t)uid;
162  } else {
163  id = _BV(28) | _SC(can3_address) | (uint32_t)uid;
164  }
165 
166  buffer = can3_internal_getFreeBuffer();
167 
168  //cancel if no buffer is free
169  if(buffer == 0) return 0;
170 
171  if(interrupt) options |= CAN_BUF_OPT_TX_INTERRUPT;
172 
173  //configure buffer
174  CAN3_RETURN_ERROR(!can_config_buffer(buffer,id,options,0,0),0);
175 
176  //set data
177  CAN3_RETURN_ERROR(!can_set_buffer_data(buffer,data,len),0);
178 
179  //send data
180  CAN3_RETURN_ERROR(!can_send_buffer(buffer),0);
181 
182  //wait for data be send
183  while(((STATR0_TXOK == 0)|| (TREQR0 & _BV(buffer -1) != 0)/* || (INTPND0 != buffer)*/)
184  && (timeout++ < CAN3_SEND_TIMEOUT))
185  delay_us(1);
186 
187  if(timeout >= CAN3_SEND_TIMEOUT) //Send Timeout
188  return 1;
189 
190  return 1;
191 }
192 
194  return can3_maskedOpen(uid,0x0000FFFF);
195 }
196 
198  uint32_t id, mask;
199  uint8_t buffer;
201 
202  //check vars
203  CAN3_RETURN_UBOUNDS(can3_usedbuffer,0xFFFD,0); //no free buffer
204  CAN3_RETURN_UBOUNDS(can3_address,CAN3_MAX_ADDRESS,0); //wrong address
205 
206  //init addressed id
207  id = (uint32_t)uid;
208  mask = 0x00000000 | idMask;
209 
210  //set interrupts
211  options = options | CAN_BUF_OPT_RX_INTERRUPT;
212 
213  //search free buffer
214  buffer = can3_internal_getFreeBuffer();
215 
216  //lock buffer
217  can3_internal_block(buffer);
218 
219  //check if everything is right
220  CAN3_RETURN_ERROR(!can_config_buffer(buffer,id,options, CAN_BUF_MASK_USE | CAN_BUF_MASK_EXTENDED,idMask),0);
221 
222  return buffer;
223 }
224 
225 uint8_t can3_getData(uint8_t buffer, uint8_t* data, uint8_t* source, uint16_t* id) {
226  uint8_t i, n;
227 
228  if(!(_BV(buffer - 1) & can3_usedbuffer)) return 0; //unused buffer
229 
230  for(i = 0; i < CAN3_DATABUFFER_SIZE; i++) {
231  if(databuffer[i].buffer == buffer) {
232  for(n = 0; n < databuffer[i].len; n++) {
233  data[n] = databuffer[i].data[n];
234  }
235 
236  *id = databuffer[i].id;
237  *source = databuffer[i].source;
238 
239  databuffer[i].buffer = CAN3_FREE_BUFFER;
240 
241  return databuffer[i].len;
242  }
243  }
244 
245  return 0;
246 }
247 
249  return can3_address;
250 }
251 
253  if(addr > CAN3_MAX_ADDRESS) return;
254  can3_address = addr;
255 }
256 
257 void can3_close(uint8_t buffer) {
258  uint8_t i;
259  uint32_t check = _BV(buffer-1);
260 
261  if(check & can3_usedbuffer) {
262  can3_usedbuffer ^= check;
263  can_config_buffer(buffer,0,0,0,0);
264 
265  //dismiss data left in databuffer for this canbuffer
266  for(i = 0; i < CAN3_DATABUFFER_SIZE; i++) {
267  if(databuffer[i].buffer == buffer)
268  databuffer[i].buffer = CAN3_FREE_BUFFER;
269  }
270  }
271 }
272 
274  uint8_t i;
275 
276  for(i = 0; i < CAN3_MAX_IRQHANDLER; i++) {
277  if(irqHandler[i] == 0) {
278  irqHandler[i] = func;
279  return 1;
280  }
281  }
282 
283  return 0;
284 }
285 
286 uint8_t can3_removeIRQHandler(IRQHandler func) {
287  uint8_t i;
288 
289  for(i = 0; i < CAN3_MAX_IRQHANDLER; i++) {
290  if(irqHandler[i] == func) {
291  irqHandler[i] = 0;
292  return 1;
293  }
294  }
295 
296  return 0;
297 }
298 
299 __interrupt
300 void IRQHandler_CAN (void) {
301  uint16_t source = INTR0;
302 
303  if (source == 0x8000) {
304  //STATUS INTERRUPT
305  source = STATR0;
306 
307  // Read the Status Register
308  // This will also clear pending Status/Error Interrupt
309  if ((source & 0x80) == 0x80) { // BusOff??
310  // Busoff handling
311  }
312 
313  if ((source & 0x40) == 0x40) { // Error Warning??
314  // Error Warning handling
315  }
316 
317  if ((source & 0x20) == 0x20) { // Error Passive??
318  // Error Passive handling
319  }
320 
321  if ((source & 0x10) == 0x10) { // RXOK??
322  // Clear RXOK Flag in Status register
323  STATR0_RXOK = 0;
324  }
325 
326  if ((source & 0x08) == 0x08) { // TXOK??
327  // Clear TXOK Flag in Status register
328  STATR0_TXOK = 0;
329  }
330 
331  if ((source & 0x07) != 0x00) { // LEC??
332  // Clear LEC in Status register
333  STATR0_LEC = 0;
334  }
335  } else if ((source - 1) < 32) {
336  uint8_t i;
337 
338  for(i = 0; i < CAN3_MAX_IRQHANDLER; i++) {
339  if(irqHandler[i] != 0) {
340  (*irqHandler[i])();
341  }
342  }
343  }
344 }
uint8_t can3_removeIRQHandler(IRQHandler func)
Definition: can3.c:286
uint8_t can3_maskedOpen(uint16_t uid, uint16_t idMask)
Definition: can3.c:197
#define interrupts_enable()
Definition: interrupts.h:63
unsigned long uint32_t
Definition: inttypes.h:60
#define CAN3_MAX_ADDRESS
Definition: can3.h:123
uint8_t can_config_buffer(uint8_t buffer, uint32_t id, uint8_t options, uint8_t maskOptions, uint32_t idMask)
Definition: can.c:80
uint8_t can3_getAddress(void)
Definition: can3.c:248
void interrupts_init(void)
Definition: interrupts.c:33
#define CAN_BUF_OPT_TRANSMIT
Definition: can.h:188
uint8_t can3_getData(uint8_t buffer, uint8_t *data, uint8_t *source, uint16_t *id)
Definition: can3.c:225
unsigned int uint16_t
Definition: inttypes.h:50
#define _BV(bit)
Definition: util.h:39
void delay_us(uint16_t us)
Definition: util.c:34
unsigned char uint8_t
Definition: inttypes.h:35
#define CAN_BUF_OPT_TX_INTERRUPT
Definition: can.h:206
uint8_t can3_registerIRQHandler(IRQHandler func)
Definition: can3.c:273
uint8_t can3_init(uint8_t address)
Definition: can3.c:120
uint8_t can3_open(uint16_t uid)
Definition: can3.c:193
#define CAN_BUF_OPT_ENABLED
Definition: can.h:181
#define CAN_BUF_MASK_USE
Definition: can.h:223
uint8_t can_set_buffer_data(uint8_t buffer, uint8_t *data, uint8_t len)
Definition: can.c:158
#define CAN_BUF_OPT_EXTENDED
Definition: can.h:194
#define interrupts_setLevel(maxLevel)
Definition: interrupts.h:58
uint8_t can3_send(uint8_t dest, uint16_t uid, uint8_t *data, uint8_t len, uint8_t interrupt)
Definition: can3.c:150
int8_t can_buffer_getData(uint8_t buffer, uint8_t *data, uint32_t *id)
Definition: can.c:219
#define CAN3_MULTICAST
Definition: can3.h:133
void can3_close(uint8_t buffer)
Definition: can3.c:257
#define CAN_BUF_MASK_EXTENDED
Definition: can.h:230
uint8_t can_init(uint8_t prescaler, uint8_t propSeg, uint8_t phSeg1, uint8_t phSeg2, uint8_t jumpWidth, uint8_t interrupts)
Definition: can.c:37
uint8_t can_buffer_newData(uint8_t buffer)
Definition: can.c:203
#define RETURN_ERROR(value, max)
Definition: util.h:46
#define CAN_BUF_OPT_RX_INTERRUPT
Definition: can.h:200
void interrupts_setHandler(uint8_t interruptNr, uint8_t interruptLevel, IRQHandler handler)
Definition: interrupts.c:52
void can3_setAddress(uint8_t addr)
Definition: can3.c:252
uint8_t can_send_buffer(uint8_t buffer)
Definition: can.c:184