16FXlib
can.c
Go to the documentation of this file.
1 
2 //*****************************************************************************
3 // Author : Christian Illy
4 // Created : 04.05.2009
5 // Revised : 05.07.2009
6 // Version : 0.1
7 // Target MCU : Fujitsu MB96300 series
8 //
9 // This program is free software: you can redistribute it and/or modify
10 // it under the terms of the GNU General Public License as published by
11 // the Free Software Foundation, either version 3 of the License, or
12 // (at your option) any later version.
13 //
14 // This program 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
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, see <http://www.gnu.org/licenses/>.
21 //
22 //*****************************************************************************
23 
24 
25 #include "../util.h"
26 #include "can.h"
27 #include "can.cfg.h"
28 
29 
30 void accessBuffer(uint8_t buffer) {
31  CAN_IF1CREQ = buffer;
32  while ((CAN_IF1CREQ & _BV(CAN_IFCREQ_BUSY))) {};
33 }
34 #pragma inline accessBuffer
35 
36 
37 uint8_t can_init(uint8_t prescaler, uint8_t propSeg, uint8_t phSeg1, uint8_t phSeg2,
38  uint8_t jumpWidth, uint8_t interrupts) {
39  uint8_t i;
40 
41  RETURN_ERROR(phSeg2 - 1, 7)
42  RETURN_ERROR(phSeg1 - 1, 7)
43  RETURN_ERROR(propSeg - 1, 7)
44  RETURN_ERROR(jumpWidth - 1, 3)
45  RETURN_ERROR(prescaler - 1, 63)
46 
47  // Enable CAN output pin
48  CAN_COER |= _BV(CAN_COER_OE);
49 
50  // Enable CAN input pin
52 
53  // Stop CAN operation and set to initialization mode
54  CAN_CTRLR = _BV(CAN_CTRLR_INIT);
55 
56  // Setup CAN channel Configuration
57  CAN_CTRLR |= _BV(CAN_CTRLR_CCE);
58  if (interrupts)
59  CAN_CTRLR |= _BV(CAN_CTRLR_EIE) | _BV(CAN_CTRLR_IE) | _BV(CAN_CTRLR_SIE);
60  CAN_BTR = (prescaler - 1) & CAN_BTR_BRP_MASK;
61  CAN_BTR |= ((propSeg + phSeg1 - 1) << CAN_BTR_TSEG1_SHIFT) & CAN_BTR_TSEG1_MASK;
62  CAN_BTR |= ((phSeg2 - 1) << CAN_BTR_TSEG2_SHIFT) & CAN_BTR_TSEG2_MASK;
63  CAN_BTR |= ((jumpWidth - 1) << CAN_BTR_SJW_SHIFT) & CAN_BTR_SJW_MASK;
64  // CAN_BTR = btr;
65  CAN_CTRLR &= ~_BV(CAN_CTRLR_CCE);
66 
67  // Disable Message buffers
68  for (i = 0; i < CAN_BUFFERCOUNT; i++) {
69  CAN_IF1ARB &= ~_BV(CAN_IFARB_MSGVAL);
70  CAN_IF1CMSK = _BV(CAN_IFCMSK_WRRD) | _BV(CAN_IFCMSK_ARB);
71  accessBuffer(i+1);
72  }
73 
74  // Start CAN operation
75  CAN_CTRLR &= ~_BV(CAN_CTRLR_INIT);
76 
77  return 1;
78 }
79 
80 uint8_t can_config_buffer(uint8_t buffer, uint32_t id, uint8_t options, uint8_t maskOptions,
81  uint32_t idMask) {
82  CAN_IF1MCTR = 0;
83 
84  RETURN_ERROR(buffer - 1, 31)
85  RETURN_ERROR(id, 0x1FFFFFFF)
86  RETURN_ERROR(idMask, 0x1FFFFFFF)
87 
88  // Set CAN-ID
89  if ((options & CAN_BUF_OPT_EXTENDED)) {
90  CAN_IF1ARB = ID_TO_EXTFRAME(id) & CAN_IFARB_ID_MASK;
91  CAN_IF1ARB |= _BV(CAN_IFARB_XTD);
92  CAN_IF1MSK = ID_TO_EXTFRAME(idMask) & CAN_IFMSK_MSK_MASK;
93  } else {
94  CAN_IF1ARB = ID_TO_STDFRAME(id);
95  CAN_IF1MSK = ID_TO_STDFRAME(idMask) & CAN_IFMSK_MSK_MASK;
96  }
97 
98  // Set direction
99  if ((options & CAN_BUF_OPT_TRANSMIT))
100  CAN_IF1ARB |= _BV(CAN_IFARB_DIR);
101 
102  // Enable buffer
103  if ((options & CAN_BUF_OPT_ENABLED))
104  CAN_IF1ARB |= _BV(CAN_IFARB_MSGVAL);
105 
106  // Use filter mask
107  if ((maskOptions & CAN_BUF_MASK_USE))
108  CAN_IF1MCTR |= _BV(CAN_IFMCTR_UMASK);
109  // Mask direction bit
110  if ((maskOptions & CAN_BUF_MASK_DIRECTION))
111  CAN_IF1MSK |= _BV(CAN_IFMSK_MDIR);
112  // Mask extended bit
113  if ((maskOptions & CAN_BUF_MASK_EXTENDED))
114  CAN_IF1MSK |= _BV(CAN_IFMSK_MXTD);
115 
116  // Enable RX interrupt
117  if ((options & CAN_BUF_OPT_RX_INTERRUPT))
118  CAN_IF1MCTR |= _BV(CAN_IFMCTR_RXIE);
119  // Enable TX interrupt
120  if ((options & CAN_BUF_OPT_TX_INTERRUPT))
121  CAN_IF1MCTR |= _BV(CAN_IFMCTR_TXIE);
122 
123  // Set buffer to single buffer mode
124  CAN_IF1MCTR |= _BV(CAN_IFMCTR_EOB);
125 
126  // Interface to buffer transfer setup
127  CAN_IF1CMSK = _BV(CAN_IFCMSK_WRRD) | _BV(CAN_IFCMSK_MASK) | _BV(CAN_IFCMSK_ARB)
128  | _BV(CAN_IFCMSK_CONTROL);
129 
130  // Start transfer from interface register to message buffer
131  accessBuffer(buffer);
132 
133  return 1;
134 }
135 
137  RETURN_ERROR(buffer - 1, 31)
138 
139  // Read current state of MCTR
140  CAN_IF1CMSK = _BV(CAN_IFCMSK_CONTROL);
141  accessBuffer(buffer);
142 
143  // Enable auto reply for RTR
144  if (enable)
145  CAN_IF1MCTR |= _BV(CAN_IFMCTR_RMTEN);
146  else
147  CAN_IF1MCTR &= ~_BV(CAN_IFMCTR_RMTEN);
148 
149  // Interface to buffer transfer setup
150  CAN_IF1CMSK = _BV(CAN_IFCMSK_WRRD) | _BV(CAN_IFCMSK_CONTROL);
151 
152  // Start transfer from interface register to message buffer
153  accessBuffer(buffer);
154 
155  return 1;
156 }
157 
159  RETURN_ERROR(buffer - 1, 31)
160  RETURN_ERROR(len, 8)
161 
162  // Read current state of MCTR
163  CAN_IF1CMSK = _BV(CAN_IFCMSK_CONTROL);
164  accessBuffer(buffer);
165 
166  // Clear DLC bits and set new value
167  CAN_IF1MCTR &= ~CAN_IFMCTR_DLC_MASK;
168  CAN_IF1MCTR |= len & CAN_IFMCTR_DLC_MASK;
169 
170  // Set Data
171  CAN_IF1DTA = *((uint32_t*) data);
172  CAN_IF1DTB = *((uint32_t*) (data + 4));
173 
174  // Interface to buffer transfer setup
175  CAN_IF1CMSK = _BV(CAN_IFCMSK_WRRD) | _BV(CAN_IFCMSK_CONTROL) | _BV(CAN_IFCMSK_DATAA)
176  | _BV(CAN_IFCMSK_DATAB);
177 
178  // Start transfer from interface register to message buffer
179  accessBuffer(buffer);
180 
181  return 1;
182 }
183 
185  RETURN_ERROR(buffer - 1, 31)
186 
187  CAN_IF1CMSK = _BV(CAN_IFCMSK_CONTROL);
188  accessBuffer(buffer);
189 
190  // TODO: check if newdat should always be set
191  CAN_IF1MCTR |= _BV(CAN_IFMCTR_NEWDAT);
192 
193  // Interface to buffer transfer setup
194  CAN_IF1CMSK = _BV(CAN_IFCMSK_WRRD) | _BV(CAN_IFCMSK_CONTROL) | _BV(CAN_IFCMSK_TXREQ);
195 
196  // Start transfer from interface register to message buffer
197  accessBuffer(buffer);
198 
199  return 1;
200 }
201 
202 
204  uint8_t i = 1;
205  uint32_t tmp = CAN_NEWDT;
206 
207  if (buffer > CAN_BUFFERCOUNT)
208  return 0;
209  if (buffer > 0)
210  return (tmp & _BV(buffer-1)) > 0 ? buffer : 0;
211 
212  if (tmp) {
213  for (; (tmp & 1) == 0; tmp >> 1, i++);
214  return i;
215  }
216  return 0;
217 }
218 
220  uint8_t len;
221 
222  if (buffer - 1 > 31)
223  return -1;
224 
225  CAN_IF1CMSK = _BV(CAN_IFCMSK_CONTROL) | _BV(CAN_IFCMSK_ARB) | _BV(CAN_IFCMSK_CIP) | _BV(CAN_IFCMSK_TXREQ) | _BV(CAN_IFCMSK_DATAB) | _BV(CAN_IFCMSK_DATAA);
226  accessBuffer(buffer);
227 
228  len = (uint8_t)(CAN_IF1MCTR & CAN_IFMCTR_DLC_MASK);
229 
230  *((uint32_t*) data) = CAN_IF1DTA;
231  *((uint32_t*) (data + 4)) = CAN_IF1DTB;
232 
233  *id = CAN_IF1ARB & CAN_IFARB_ID_MASK;
234 
235  return len;
236 }
237 
#define CAN_BUF_MASK_DIRECTION
Definition: can.h:237
unsigned long uint32_t
Definition: inttypes.h:60
uint8_t can_config_buffer(uint8_t buffer, uint32_t id, uint8_t options, uint8_t maskOptions, uint32_t idMask)
Definition: can.c:80
#define CAN_BUF_OPT_TRANSMIT
Definition: can.h:188
#define CAN_RX_BIT
Bit in the input enable register of the CAN input pin.
Definition: can.cfg.h:39
#define _BV(bit)
Definition: util.h:39
unsigned char uint8_t
Definition: inttypes.h:35
#define CAN_BUF_OPT_TX_INTERRUPT
Definition: can.h:206
#define ID_TO_STDFRAME(id)
Definition: can.h:124
#define CAN_RX_ENABLE
Input enable register which contains the CAN input pin.
Definition: can.cfg.h:37
uint8_t can_set_buffer_autoreply(uint8_t buffer, uint8_t enable)
Definition: can.c:136
char int8_t
Definition: inttypes.h:45
#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 ID_TO_EXTFRAME(id)
Definition: can.h:129
int8_t can_buffer_getData(uint8_t buffer, uint8_t *data, uint32_t *id)
Definition: can.c:219
#define CAN_BUFFERCOUNT
Number of CAN buffers in the CAN engine of the controller.
Definition: can.cfg.h:44
#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
uint8_t can_send_buffer(uint8_t buffer)
Definition: can.c:184