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>&copy; 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