1 /**
2 *****************************************************************************
3 * @file cmem7_can.c
4 *
5 * @brief CMEM7 CAN source file
6 *
7 *
8 * @version V1.0
9 * @date 3. September 2013
10 *
11 * @note
12 *
13 *****************************************************************************
14 * @attention
15 *
16 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
17 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
18 * TIME. AS A RESULT, CAPITAL-MICRO SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
20 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
21 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
22 *
23 * <h2><center>© COPYRIGHT 2013 Capital-micro </center></h2>
24 *****************************************************************************
25 */
26
27 #include "cmem7_can.h"
28
29 typedef struct {
30 union {
31 __IO uint8_t FI; /*!< Transmit Frame Information if writting or Receive Frame Information
32 if reading, ACR[0] if reset mode */
33
34 struct {
35 __IO uint8_t DLC : 4; /*!< byte number in the data */
36 uint8_t : 2;
37 __IO uint8_t RTR : 1; /*!< 1 indicates a remote frame; 0 indicates a data frame */
38 __IO uint8_t FF : 1; /*!< 1 selects Extended Frame Format (EFF); 0 selects Standard Frame
39 Format (SFF) */
40 } FI_b; /*!< BitSize */
41 } U;
42 } CAN_FRAME_INFO;
43
44 typedef struct {
45 union {
46 uint16_t ID; /*!< ID */
47
48 struct {
49 uint16_t ID28_21 : 8; /*!< ID28 to ID21 */
50 uint16_t : 4;
51 uint16_t RTR : 1; /*!< if remote frame */
52 uint16_t ID20_18 : 3; /*!< ID20 to ID18 */
53 } ID_b; /*!< BitSize */
54 } U;
55 } CAN_STANDARD_ID;
56
57 typedef struct {
58 union {
59 uint32_t ID; /*!< ID */
60
61 struct {
62 uint32_t ID28_21 : 8; /*!< ID28 to ID21 */
63 uint32_t ID20_13 : 8; /*!< ID20 to ID13 */
64 uint32_t ID12_5 : 8; /*!< ID12 to ID5 */
65 uint32_t : 2;
66 uint32_t RTR : 1; /*!< if remote frame */
67 uint32_t ID4_0 : 5; /*!< ID4 to ID0 */
68 } ID_b; /*!< BitSize */
69 } U;
70 } CAN_EXTENDED_ID;
71
72 #define CAN_MODE_NORMAL 0x00000000
73 #define CAN_MODE_RESET 0x00000001
74 #define CAN_MODE_LISTEN_ONLY 0x00000002
75 #define CAN_MODE_SELF_TEST 0x00000004
76 #define CAN_MODE_SINGLE_FILTER 0x00000008
77 #define CAN_MODE_SLEEP 0x00000010
78
79 #define CAN_OCR_NORMAL 0x02
80 #define CAN_OCR_CLOCK 0x03
81
can_SetFilter(CAN0_Type * CANx,CAN_FILTER * f1,CAN_FILTER * f2)82 static BOOL can_SetFilter(CAN0_Type* CANx, CAN_FILTER *f1, CAN_FILTER *f2) {
83 if (!f1) {
84 return FALSE;
85 }
86
87 if (!IS_CAN_FLT_TYPE(f1->type)) {
88 return FALSE;
89 }
90
91 if(IS_CAN_FLT_DUAL(f1->type)) {
92 if (!f2 || IS_CAN_FLT_SINGLE(f2->type)) {
93 return FALSE;
94 }
95 }
96
97 if (f1->type == CAN_FLT_STANDARD_SINGLE) {
98 CANx->FI_OR_ACR0 = f1->ACCEPT.sf.ID28_18 >> 3;
99 CANx->DI0_OR_ACR1 = (f1->ACCEPT.sf.ID28_18 & 0x07) << 5;
100 CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.RTR << 4;
101 CANx->DI1_OR_ACR2 = f1->ACCEPT.sf.data1;
102 CANx->DI2_OR_ACR3 = f1->ACCEPT.sf.data2;
103
104 CANx->DI3_OR_AMR0 = f1->MASK.sf.ID28_18 >> 3;
105 CANx->DI4_OR_AMR1 = (f1->MASK.sf.ID28_18 & 0x07) << 5;
106 CANx->DI4_OR_AMR1 |= f1->MASK.sf.RTR << 4;
107 CANx->DI5_OR_AMR2 = f1->MASK.sf.data1;
108 CANx->DI6_OR_AMR3 = f1->MASK.sf.data2;
109 } else if (f1->type == CAN_FLT_STANDARD_DUAL) {
110 CANx->FI_OR_ACR0 = f1->ACCEPT.sf.ID28_18 >> 3;
111 CANx->DI0_OR_ACR1 = (f1->ACCEPT.sf.ID28_18 & 0x07) << 5;
112 CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.RTR << 4;
113 CANx->DI0_OR_ACR1 |= f1->ACCEPT.sf.data1 >> 4;
114 CANx->DI2_OR_ACR3 = f1->ACCEPT.sf.data1 & 0x0F;
115
116 CANx->DI3_OR_AMR0 = f1->MASK.sf.ID28_18 >> 3;
117 CANx->DI4_OR_AMR1 = (f1->MASK.sf.ID28_18 & 0x07) << 5;
118 CANx->DI4_OR_AMR1 |= f1->MASK.sf.RTR << 4;
119 CANx->DI4_OR_AMR1 = f1->MASK.sf.data1 >> 4;
120 CANx->DI6_OR_AMR3 = f1->MASK.sf.data1 & 0x0F;
121 } else if (f1->type == CAN_FLT_EXTENDED_SINGLE) {
122 CANx->FI_OR_ACR0 = f1->ACCEPT.ef.ID28_13 >> 8;
123 CANx->DI0_OR_ACR1 = f1->ACCEPT.ef.ID28_13 & 0xFF;
124 CANx->DI1_OR_ACR2 = f1->ACCEPT.ef.ID12_0 >> 5;
125 CANx->DI2_OR_ACR3 = (f1->ACCEPT.ef.ID12_0 & 0x1F) << 3;
126 CANx->DI2_OR_ACR3 |= f1->ACCEPT.ef.RTR << 2;
127
128 CANx->DI3_OR_AMR0 = f1->MASK.ef.ID28_13 >> 8;
129 CANx->DI4_OR_AMR1 = f1->MASK.ef.ID28_13 & 0xFF;
130 CANx->DI5_OR_AMR2 = f1->MASK.ef.ID12_0 >> 5;
131 CANx->DI6_OR_AMR3 = (f1->MASK.ef.ID12_0 & 0x1F) << 3;
132 CANx->DI6_OR_AMR3 |= f1->MASK.ef.RTR << 2;
133 } else {
134 CANx->FI_OR_ACR0 = f1->ACCEPT.ef.ID28_13 >> 8;
135 CANx->DI0_OR_ACR1 = f1->ACCEPT.ef.ID28_13 & 0xFF;
136
137 CANx->DI3_OR_AMR0 = f1->MASK.ef.ID28_13 >> 8;
138 CANx->DI4_OR_AMR1 = f1->MASK.ef.ID28_13 & 0xFF;
139 }
140
141 if (IS_CAN_FLT_DUAL(f1->type)) {
142 if (f2->type == CAN_FLT_STANDARD_DUAL) {
143 CANx->DI1_OR_ACR2 = f2->ACCEPT.sf.ID28_18 >> 3;
144 CANx->DI2_OR_ACR3 |= (f2->ACCEPT.sf.ID28_18 & 0x07) << 5;
145 CANx->DI2_OR_ACR3 |= f2->ACCEPT.sf.RTR << 4;
146
147 CANx->DI5_OR_AMR2 = f2->MASK.sf.ID28_18 >> 3;
148 CANx->DI6_OR_AMR3 |= (f2->MASK.sf.ID28_18 & 0x07) << 5;
149 CANx->DI6_OR_AMR3 |= f2->MASK.sf.RTR << 4;
150 } else {
151 CANx->DI1_OR_ACR2 = f2->ACCEPT.ef.ID28_13 >> 8;
152 CANx->DI2_OR_ACR3 = f2->ACCEPT.ef.ID28_13 & 0xFF;
153
154 CANx->DI5_OR_AMR2 = f2->MASK.ef.ID28_13 >> 8;
155 CANx->DI6_OR_AMR3 = f2->MASK.ef.ID28_13 & 0xFF;
156 }
157 }
158
159 if (IS_CAN_FLT_SINGLE(f1->type)) {
160 CANx->MODE_b.AFM = 1;
161 } else {
162 CANx->MODE_b.AFM = 0;
163 }
164
165 return TRUE;
166 }
167
CAN_Init(CAN0_Type * CANx,CAN_InitTypeDef * Init,CAN_FILTER * f1,CAN_FILTER * f2)168 BOOL CAN_Init(CAN0_Type* CANx, CAN_InitTypeDef* Init,
169 CAN_FILTER *f1, CAN_FILTER *f2) {
170 assert_param(IS_CAN_ALL_PERIPH(CANx));
171 assert_param(Init);
172 assert_param(IS_CAN_CDR_DIV(Init->CAN_ClockDiv));
173
174 /* Quit to sleep mode in operation mode */
175 if (CANx->MODE_b.SM) {
176 CANx->MODE_b.RM = FALSE;
177 CANx->MODE_b.SM = FALSE;
178 }
179
180 /* switch to reset mode to set parameter */
181 CANx->MODE_b.RM = TRUE;
182
183 /* disable all interrupts and clear except receive interrupt */
184 {
185 uint8_t tmp;
186 CANx->INT_EN &= ~CAN_INT_All;
187 tmp = CANx->INT;
188 tmp = tmp;
189 }
190
191 CANx->MODE_b.LOM = (Init->CAN_TxEn) ? FALSE : TRUE;
192
193 CANx->MODE_b.STM = Init->CAN_Loopback;
194
195 CANx->CDR_b.OFF = FALSE;
196 CANx->CDR_b.DIVIDER = Init->CAN_ClockDiv;
197
198 CANx->BTR0_b.BRP = Init->CAN_Prescaler;
199 CANx->BTR0_b.SJW = Init->CAN_SJW;
200
201 CANx->BTR1_b.TSEG1 = Init->CAN_TSEG1;
202 CANx->BTR1_b.TSEG2 = Init->CAN_TSEG2;
203 CANx->BTR1_b.SAM = !Init->CAN_HighSpeed;
204
205 CANx->OCR_b.MODE = CAN_OCR_CLOCK;
206
207 if (!can_SetFilter(CANx, f1, f2)) {
208 return FALSE;
209 }
210
211 /* switch to operation mode */
212 CANx->MODE_b.RM = FALSE;
213
214 return TRUE;
215 }
216
CAN_SetSleepMode(CAN0_Type * CANx,BOOL enable)217 void CAN_SetSleepMode(CAN0_Type* CANx, BOOL enable) {
218 assert_param(IS_CAN_ALL_PERIPH(CANx));
219
220 /* switch to operation mode */
221 CANx->MODE_b.RM = FALSE;
222
223 CANx->MODE_b.SM = enable;
224 }
225
CAN_EnableInt(CAN0_Type * CANx,uint32_t Int,BOOL enable)226 void CAN_EnableInt(CAN0_Type* CANx, uint32_t Int, BOOL enable) {
227 assert_param(IS_CAN_ALL_PERIPH(CANx));
228 assert_param(IS_CAN_INT(Int));
229
230 if (enable) {
231 CANx->INT_EN |= CAN_INT_All;
232 } else {
233 CANx->INT_EN &= ~CAN_INT_All;
234 }
235 }
236
CAN_GetIntStatus(CAN0_Type * CANx)237 uint8_t CAN_GetIntStatus(CAN0_Type* CANx) {
238 assert_param(IS_CAN_ALL_PERIPH(CANx));
239
240 return CANx->INT;
241 }
242
CAN_Transmit(CAN0_Type * CANx,CAN_Frame * frame)243 BOOL CAN_Transmit(CAN0_Type* CANx, CAN_Frame* frame) {
244 assert_param(IS_CAN_ALL_PERIPH(CANx));
245
246 if (!frame) {
247 return FALSE;
248 }
249
250 if (CANx->MODE_b.LOM) {
251 return FALSE;
252 }
253
254 if (CANx->MODE_b.SM) {
255 CANx->MODE_b.RM = FALSE;
256 CANx->MODE_b.SM = FALSE;
257 }
258
259 {
260 CAN_FRAME_INFO fi;
261
262 fi.U.FI_b.FF = !frame->SFF;
263 fi.U.FI_b.RTR = frame->RTR;
264 fi.U.FI_b.DLC = frame->DLC;
265
266 CANx->FI_OR_ACR0 = fi.U.FI;
267 }
268
269 if (frame->SFF) {
270 CAN_STANDARD_ID id;
271
272 id.U.ID_b.ID28_21 = frame->Id >> 3;
273 id.U.ID_b.RTR = frame->RTR;
274 id.U.ID_b.ID20_18 = frame->Id & 0x07;
275
276 CANx->DI0_OR_ACR1 = id.U.ID & 0xFF;
277 CANx->DI1_OR_ACR2 = id.U.ID >> 8;
278
279 CANx->DI2_OR_ACR3 = frame->Data[0];
280 CANx->DI3_OR_AMR0 = frame->Data[1];
281 CANx->DI4_OR_AMR1 = frame->Data[2];
282 CANx->DI5_OR_AMR2 = frame->Data[3];
283 CANx->DI6_OR_AMR3 = frame->Data[4];
284 CANx->DI7 = frame->Data[5];
285 CANx->DI8 = frame->Data[6];
286 CANx->DI9 = frame->Data[7];
287 } else {
288 CAN_EXTENDED_ID id;
289
290 id.U.ID_b.ID28_21 = frame->Id >> 21;
291 id.U.ID_b.ID20_13 = (frame->Id >> 13) & 0xFF;
292 id.U.ID_b.ID12_5 = (frame->Id >> 5) & 0xFF;
293 id.U.ID_b.RTR = frame->RTR;
294 id.U.ID_b.ID4_0 = frame->Id & 0x1F;
295
296 CANx->DI0_OR_ACR1 = id.U.ID & 0xFF;
297 CANx->DI1_OR_ACR2 = (id.U.ID >> 8) & 0xFF;
298 CANx->DI2_OR_ACR3 = (id.U.ID >> 16) & 0xFF;
299 CANx->DI3_OR_AMR0 = (id.U.ID >> 24) & 0xFF;
300
301 CANx->DI4_OR_AMR1 = frame->Data[0];
302 CANx->DI5_OR_AMR2 = frame->Data[1];
303 CANx->DI6_OR_AMR3 = frame->Data[2];
304 CANx->DI7 = frame->Data[3];
305 CANx->DI8 = frame->Data[4];
306 CANx->DI9 = frame->Data[5];
307 CANx->DI10 = frame->Data[6];
308 CANx->DI11 = frame->Data[7];
309 }
310
311 if (CANx->MODE_b.STM) {
312 CANx->CMD_b.SSR = TRUE;
313 } else {
314 CANx->CMD_b.TR = TRUE;
315 }
316
317 return TRUE;
318 }
319
CAN_Receive(CAN0_Type * CANx,CAN_Frame * frame)320 BOOL CAN_Receive(CAN0_Type* CANx, CAN_Frame* frame) {
321 assert_param(IS_CAN_ALL_PERIPH(CANx));
322
323 if (!frame) {
324 return FALSE;
325 }
326
327 if (CANx->MODE_b.SM) {
328 CANx->MODE_b.RM = FALSE;
329 CANx->MODE_b.SM = FALSE;
330 }
331
332 {
333 CAN_FRAME_INFO fi;
334
335 fi.U.FI = CANx->FI_OR_ACR0;
336
337 frame->SFF = fi.U.FI_b.FF ? FALSE : TRUE;
338 frame->RTR = fi.U.FI_b.RTR ? TRUE : FALSE;
339 frame->DLC = fi.U.FI_b.DLC;
340 }
341
342 if (frame->SFF) {
343 CAN_STANDARD_ID id;
344
345 id.U.ID = CANx->DI0_OR_ACR1;
346 id.U.ID |= CANx->DI1_OR_ACR2 << 8;
347
348 frame->Id = id.U.ID_b.ID28_21 << 3;
349 frame->Id |= id.U.ID_b.ID20_18;
350
351 frame->Data[0] = CANx->DI2_OR_ACR3;
352 frame->Data[1] = CANx->DI3_OR_AMR0;
353 frame->Data[2] = CANx->DI4_OR_AMR1;
354 frame->Data[3] = CANx->DI5_OR_AMR2;
355 frame->Data[4] = CANx->DI6_OR_AMR3;
356 frame->Data[5] = CANx->DI7;
357 frame->Data[6] = CANx->DI8;
358 frame->Data[7] = CANx->DI9;
359 } else {
360 CAN_EXTENDED_ID id;
361
362 id.U.ID = CANx->DI0_OR_ACR1;
363 id.U.ID |= CANx->DI1_OR_ACR2 << 8;
364 id.U.ID |= CANx->DI2_OR_ACR3 << 16;
365 id.U.ID |= CANx->DI3_OR_AMR0 << 24;
366
367 frame->Id = id.U.ID_b.ID28_21 << 21;
368 frame->Id |= id.U.ID_b.ID20_13 << 13;
369 frame->Id |= id.U.ID_b.ID12_5 << 5;
370 frame->Id |= id.U.ID_b.ID4_0;
371
372 frame->Data[0] = CANx->DI4_OR_AMR1;
373 frame->Data[1] = CANx->DI5_OR_AMR2;
374 frame->Data[2] = CANx->DI6_OR_AMR3;
375 frame->Data[3] = CANx->DI7;
376 frame->Data[4] = CANx->DI8;
377 frame->Data[5] = CANx->DI9;
378 frame->Data[6] = CANx->DI10;
379 frame->Data[7] = CANx->DI11;
380 }
381
382 CANx->CMD_b.RRB = TRUE;
383
384 return TRUE;
385 }
386
387