]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/can.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / can.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2012, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /** \file\r
31  *  Implements functions for Controller Area Network (CAN)\r
32  *  peripheral operations.\r
33  */\r
34 /** \addtogroup can_module\r
35  *@{*/\r
36 \r
37 /*----------------------------------------------------------------------------\r
38  *        Headers\r
39  *----------------------------------------------------------------------------*/\r
40 \r
41 #include "chip.h"\r
42 \r
43 #include <assert.h>\r
44 \r
45 #if defined(REG_CAN0_MR) || defined(REG_CAN_MR)\r
46 \r
47 /* ----------- CAN_MR Operations --------------- */\r
48 /**\r
49  * \brief Set CAN Mode Register (CAN_MR)\r
50  * \param pCan Pointer to Can instance.\r
51  * \param dwMr Mode register settings.\r
52  */\r
53 void CAN_ConfigureMode(Can *pCan, uint32_t dwMr)\r
54 {\r
55     pCan->CAN_MR = dwMr;\r
56 }\r
57 \r
58 /**\r
59  * \brief CAN Controller Enable/Disable\r
60  * \param pCan   Pointer to Can instance.\r
61  * \param bEnDis 1 to enable and 0 to disable.\r
62  */\r
63 void CAN_Enable(Can *pCan, uint8_t bEnDis)\r
64 {\r
65     if (bEnDis) pCan->CAN_MR |=  CAN_MR_CANEN;\r
66     else        pCan->CAN_MR &= ~CAN_MR_CANEN;\r
67 }\r
68 \r
69 /**\r
70  * \brief CAN Low Power Mode Enable/Disable\r
71  * \param pCan   Pointer to Can instance.\r
72  * \param bEnDis 1 to enable and 0 to disable.\r
73  */\r
74 void CAN_EnableLowPower(Can *pCan, uint8_t bEnDis)\r
75 {\r
76     if (bEnDis) pCan->CAN_MR |=  CAN_MR_LPM;\r
77     else        pCan->CAN_MR &= ~CAN_MR_LPM;\r
78 }\r
79 \r
80 /**\r
81  * \brief CAN Autobaud/Listen mode\r
82  * \param pCan   Pointer to Can instance.\r
83  * \param bEnDis 1 to enable and 0 to disable.\r
84  */\r
85 void CAN_EnableAutobaud(Can *pCan, uint8_t bEnDis)\r
86 {\r
87     if (bEnDis) pCan->CAN_MR |=  CAN_MR_ABM;\r
88     else        pCan->CAN_MR &= ~CAN_MR_ABM;\r
89 }\r
90 \r
91 /**\r
92  * \brief CAN Overload Frame Enable/Disable\r
93  * \param pCan   Pointer to Can instance.\r
94  * \param bEnDis 1 to enable and 0 to disable.\r
95  */\r
96 void CAN_EnableOverloadFrame(Can *pCan, uint8_t bEnDis)\r
97 {\r
98     if (bEnDis) pCan->CAN_MR |=  CAN_MR_OVL;\r
99     else        pCan->CAN_MR &= ~CAN_MR_OVL;\r
100 }\r
101 \r
102 /**\r
103  * \brief CAN Timestamp capture mode (@EOF/@SOF).\r
104  * \param pCan      Pointer to Can instance.\r
105  * \param bEofSof   1 for EOF/0 for SOF.\r
106  */\r
107 void CAN_EnableTimeStampEof(Can *pCan, uint8_t bEofSof)\r
108 {\r
109     if (bEofSof) pCan->CAN_MR |=  CAN_MR_TEOF;\r
110     else         pCan->CAN_MR &= ~CAN_MR_TEOF;\r
111 }\r
112 \r
113 /**\r
114  * \brief CAN Time Triggered Mode Enable/Disable\r
115  * \param pCan      Pointer to Can instance.\r
116  * \param bEnDis    Enable/Disable Time Trigger Mode.\r
117  */\r
118 void CAN_EnableTimeTriggerMode(Can *pCan, uint8_t bEnDis)\r
119 {\r
120     if (bEnDis) pCan->CAN_MR |=  CAN_MR_TTM;\r
121     else        pCan->CAN_MR &= ~CAN_MR_TTM;\r
122 }\r
123 \r
124 /**\r
125  * \brief CAN Timer Freeze Enable/Disable\r
126  * \param pCan      Pointer to Can instance.\r
127  * \param bEnDis    Enable/Disable Timer Freeze.\r
128  */\r
129 void CAN_EnableTimerFreeze(Can *pCan, uint8_t bEnDis)\r
130 {\r
131     if (bEnDis) pCan->CAN_MR |=  CAN_MR_TIMFRZ;\r
132     else        pCan->CAN_MR &= ~CAN_MR_TIMFRZ;\r
133 }\r
134 \r
135 /**\r
136  * \brief CAN Repeat Disable/Enable.\r
137  * \param pCan      Pointer to Can instance.\r
138  * \param bEnDis    Disable/Enable Repeat.\r
139  */\r
140 void CAN_DisableRepeat(Can *pCan, uint8_t bDisEn)\r
141 {\r
142     if (bDisEn) pCan->CAN_MR |=  CAN_MR_DRPT;\r
143     else        pCan->CAN_MR &= ~CAN_MR_DRPT;\r
144 }\r
145 \r
146 /* ---------- Interrupt settings ------------- */\r
147 \r
148 /**\r
149  * \brief CAN Interrupts Enable\r
150  * \param pCan      Pointer to Can instance.\r
151  * \param dwSources Interrupt sources bits.\r
152  */\r
153 void CAN_EnableIt(Can *pCan, uint32_t dwSources)\r
154 {\r
155     pCan->CAN_IER = dwSources;\r
156 }\r
157 \r
158 /**\r
159  * \brief CAN Interrupts Disable\r
160  * \param pCan      Pointer to Can instance.\r
161  * \param dwSources Interrupt sources bits.\r
162  */\r
163 void CAN_DisableIt(Can *pCan, uint32_t dwSources)\r
164 {\r
165     pCan->CAN_IDR = dwSources;\r
166 }\r
167 \r
168 /**\r
169  * \brief Return CAN Interrupts Masks\r
170  * \param pCan      Pointer to Can instance.\r
171  */\r
172 uint32_t CAN_GetItMask(Can *pCan)\r
173 {\r
174     return pCan->CAN_IMR;\r
175 }\r
176 \r
177 /**\r
178  * \brief Return CAN Statuses\r
179  * \param pCan      Pointer to Can instance.\r
180  */\r
181 uint32_t CAN_GetStatus(Can *pCan)\r
182 {\r
183     return pCan->CAN_SR;\r
184 }\r
185 \r
186 /**\r
187  * \brief Calculate and configure the baudrate\r
188  * \param pCan       Pointer to Can instance.\r
189  * \param dwBaudrate Baudrate value (kB/s)\r
190  *                   allowed: 100, 800, 500, 250, 125, 50, 25, 10\r
191  * \param dwMck      MCK.\r
192  * \return 1 in success, otherwise return 0.\r
193  */\r
194 uint8_t CAN_CalcBaudrate(Can *pCan, uint32_t dwBaudrate, uint32_t dwMck)\r
195 {\r
196     uint32_t BRP, PROPAG, PHASE1, PHASE2, SJW;\r
197     uint8_t  TQ;\r
198     uint32_t t1t2;\r
199     uint32_t maxClock;\r
200     uint32_t id = ID_CAN0;\r
201 \r
202     if ((uint32_t)pCan == (uint32_t)CAN0) id = ID_CAN0;\r
203        else if ((uint32_t)pCan == (uint32_t)CAN1) id = ID_CAN1;\r
204     maxClock = PMC_SetPeriMaxClock(id, dwMck);\r
205 \r
206     if (dwBaudrate >= 1000) TQ = 8;\r
207     else                    TQ = 16;\r
208     BRP = (maxClock / (dwBaudrate * 1000 * TQ)) - 1;\r
209     if (BRP == 0) {\r
210         return 0;\r
211     }\r
212 \r
213     /* Timing delay:\r
214        Delay Bus Driver     - 50ns\r
215        Delay Receiver       - 30ns\r
216        Delay Bus Line (20m) - 110ns */\r
217     if ( (TQ * dwBaudrate * 2 * (50+30+110)/1000000) >= 1 )\r
218         PROPAG = (TQ * dwBaudrate * 2 * (50+30+110)/1000000) - 1;\r
219     else\r
220         PROPAG = 0;\r
221     t1t2 = TQ - 1 - (PROPAG + 1);\r
222 \r
223     if ( (t1t2 & 0x01) == 0x01 ) {\r
224         PHASE1 = ((t1t2 - 1) / 2) - 1;\r
225         PHASE2 = PHASE1 + 1;\r
226     }\r
227     else {\r
228         PHASE1 = ((t1t2) / 2) - 1;\r
229         PHASE2 = PHASE1;\r
230     }\r
231 \r
232     if ( 1 > (4/(PHASE1 + 1)) ) SJW = 3;\r
233     else                        SJW = PHASE1;\r
234 \r
235     if ( (PROPAG + PHASE1 + PHASE2) != (uint32_t)(TQ - 4) ) {\r
236         return 0;\r
237     }\r
238 \r
239     pCan->CAN_BR = CAN_BR_PHASE2(PHASE2)\r
240                  | CAN_BR_PHASE1(PHASE1)\r
241                  | CAN_BR_PROPAG(PROPAG)\r
242                  | CAN_BR_SJW(SJW)\r
243                  | CAN_BR_BRP(BRP)\r
244                  | CAN_BR_SMP_ONCE;\r
245     return 1;\r
246 }\r
247 \r
248 /**\r
249  * \brief Set CAN baudrate register\r
250  * \param pCan      Pointer to Can instance.\r
251  * \param dwBr      Setting value for CAN_BR.\r
252  */\r
253 void CAN_ConfigureBaudrate(Can *pCan, uint32_t dwBr)\r
254 {\r
255     pCan->CAN_BR = dwBr;\r
256 }\r
257 \r
258 /**\r
259  * \brief Set CAN Sampling Mode\r
260  * \param pCan      Pointer to Can instance.\r
261  * \param bAvg3     Sample 3 times/sample once at sample point.\r
262  */\r
263 void CAN_SetSamplingMode(Can *pCan, uint8_t bAvg3)\r
264 {\r
265     if (bAvg3) pCan->CAN_BR |=  CAN_BR_SMP;\r
266     else       pCan->CAN_BR &= ~CAN_BR_SMP;\r
267 }\r
268 \r
269 /**\r
270  * \brief Return CAN Timer Register\r
271  * \param pCan      Pointer to Can instance.\r
272  */\r
273 uint32_t CAN_GetTimer(Can *pCan)\r
274 {\r
275     return pCan->CAN_TIM;\r
276 }\r
277 \r
278 /**\r
279  * \brief Return CAN TimeStamp Register\r
280  * \param pCan      Pointer to Can instance.\r
281  */\r
282 uint32_t CAN_GetTimestamp(Can *pCan)\r
283 {\r
284     return pCan->CAN_TIMESTP;\r
285 }\r
286 \r
287 /**\r
288  * \brief Return Error Count (TEC << 16) + REC\r
289  * \param pCan      Pointer to Can instance.\r
290  */\r
291 uint32_t CAN_GetErrorCount(Can *pCan)\r
292 {\r
293     return pCan->CAN_ECR;\r
294 }\r
295 \r
296 /**\r
297  * \brief Return Receive Error Count\r
298  * \param pCan      Pointer to Can instance.\r
299  */\r
300 uint32_t CAN_GetRxErrorCount(Can *pCan)\r
301 {\r
302     return (pCan->CAN_ECR & CAN_ECR_REC_Msk) >> CAN_ECR_REC_Pos;\r
303 }\r
304 \r
305 /**\r
306  * \brief Return Transmit Error Count\r
307  * \param pCan      Pointer to Can instance.\r
308  */\r
309 uint32_t CAN_GetTxErrorCount(Can *pCan)\r
310 {\r
311     return (pCan->CAN_ECR & CAN_ECR_TEC_Msk) >> CAN_ECR_TEC_Pos;\r
312 }\r
313 \r
314 /**\r
315  * \brief Set Transfer Command Register to initialize transfer requests.\r
316  * \param pCan       Pointer to Can instance.\r
317  * \param dwRequests Transfer Command Requests.\r
318  */\r
319 void CAN_Command(Can *pCan, uint32_t dwRequests)\r
320 {\r
321     pCan->CAN_TCR = dwRequests;\r
322 }\r
323 \r
324 /**\r
325  * \brief Resets CAN internal timer counter.\r
326  * \param pCan       Pointer to Can instance.\r
327  */\r
328 void CAN_ResetTimer(Can *pCan)\r
329 {\r
330     pCan->CAN_TCR = CAN_TCR_TIMRST;\r
331 }\r
332 \r
333 /**\r
334  * \brief Request transfer on mailbox.\r
335  * \param pCan       Pointer to Can instance.\r
336  * \param bMb        Mailbox number.\r
337  */\r
338 void CAN_Tx(Can *pCan, uint8_t bMb)\r
339 {\r
340     pCan->CAN_TCR = CAN_TCR_MB0 << bMb;\r
341 }\r
342 \r
343 /**\r
344  * \brief Abort transfer on several mailboxes.\r
345  * \param pCan       Pointer to Can instance.\r
346  * \param dwAborts   Abort requests.\r
347  */\r
348 void CAN_Abort(Can *pCan, uint32_t dwAborts)\r
349 {\r
350     pCan->CAN_ACR = dwAborts;\r
351 }\r
352 \r
353 /**\r
354  * \brief Abort transfer on single mailbox.\r
355  * \param pCan       Pointer to Can instance.\r
356  * \param bMb        Mailbox number.\r
357  */\r
358 void CAN_AbortMailbox(Can *pCan, uint8_t bMb)\r
359 {\r
360     pCan->CAN_ACR = CAN_ACR_MB0 << bMb;\r
361 }\r
362 \r
363 /**\r
364  * \brief Configure CAN Message Mode (_MMRx)\r
365  * \param pCan       Pointer to Can instance.\r
366  * \param bMb        Mailbox number.\r
367  * \param dwMr       Mode settings.\r
368  */\r
369 void CAN_ConfigureMessageMode(Can *pCan, uint8_t bMb, uint32_t dwMr)\r
370 {\r
371     pCan->CAN_MB[bMb].CAN_MMR = dwMr;\r
372 }\r
373 \r
374 /**\r
375  * \brief Return CAN Message Mode (_MMRx)\r
376  * \param pCan       Pointer to Can instance.\r
377  * \param bMb        Mailbox number.\r
378  */\r
379 uint32_t CAN_GetMessageMode(Can *pCan, uint8_t bMb)\r
380 {\r
381     return pCan->CAN_MB[bMb].CAN_MMR;\r
382 }\r
383 \r
384 /**\r
385  * \brief Set Mailbox Timemark for Time Triggered Mode.\r
386  * \param pCan       Pointer to Can instance.\r
387  * \param bMb        Mailbox number.\r
388  * \param bTimemarks Mailbox timemarks.\r
389  */\r
390 void CAN_SetTimemark(Can *pCan, uint8_t bMb, uint8_t bTimemarks)\r
391 {\r
392     uint32_t dwMmr = (pCan->CAN_MB[bMb].CAN_MMR) & (~0xFFu);\r
393     pCan->CAN_MB[bMb].CAN_MMR = dwMmr | ((bTimemarks << 0) & 0xFF);\r
394 }\r
395 \r
396 /**\r
397  * \brief Set Mailbox Priority.\r
398  * \param pCan       Pointer to Can instance.\r
399  * \param bMb        Mailbox number.\r
400  * \param bPriority  Mailbox Priority.\r
401  */\r
402 void CAN_SetPriority(Can *pCan, uint8_t bMb, uint8_t bPriority)\r
403 {\r
404     uint32_t dwMmr = (pCan->CAN_MB[bMb].CAN_MMR & ~CAN_MMR_PRIOR_Msk);\r
405     pCan->CAN_MB[bMb].CAN_MMR = dwMmr | CAN_MMR_PRIOR(bPriority);\r
406 }\r
407 \r
408 /**\r
409  * \brief Set Mailbox Object Type.\r
410  * \param pCan       Pointer to Can instance.\r
411  * \param bMb        Mailbox number.\r
412  * \param bType      Mailbox Object Type.\r
413  */\r
414 void CAN_SetObjectType(Can *pCan, uint8_t bMb, uint8_t bType)\r
415 {\r
416     uint32_t dwMr = (pCan->CAN_MB[bMb].CAN_MMR & CAN_MMR_MOT_Msk) >> CAN_MMR_MOT_Pos;\r
417     pCan->CAN_MB[bMb].CAN_MMR |= dwMr | ((bType << CAN_MMR_MOT_Pos) & CAN_MMR_MOT_Msk);\r
418 }\r
419 \r
420 /**\r
421  * \brief Configure CAN Message Acceptance Mask (_MAMx)\r
422  * \param pCan       Pointer to Can instance.\r
423  * \param bMb        Mailbox number.\r
424  * \param dwMam      The setting value for _MAMx.\r
425  */\r
426 void CAN_ConfigureMessageAcceptanceMask(Can *pCan, uint8_t bMb, uint32_t dwMAM)\r
427 {\r
428     pCan->CAN_MB[bMb].CAN_MAM = dwMAM;\r
429 }\r
430 \r
431 /**\r
432  * \brief Return CAN Message Acceptance Mask (_MAMx)\r
433  * \param pCan       Pointer to Can instance.\r
434  * \param bMb        Mailbox number.\r
435  */\r
436 uint32_t CAN_GetMessageAcceptanceMask(Can *pCan, uint8_t bMb)\r
437 {\r
438     return pCan->CAN_MB[bMb].CAN_MAM;\r
439 }\r
440 \r
441 /**\r
442  * \brief Configure Identifier Version in CAN Message Acceptance Mask (_MAMx)\r
443  * \param pCan       Pointer to Can instance.\r
444  * \param bMb        Mailbox number.\r
445  * \param bIdCfg     IDvA and IDvB/IDvA only Identify.\r
446  */\r
447 void CAN_ConfigureIdentifierMask(Can *pCan, uint8_t bMb, uint8_t bIdCfg)\r
448 {\r
449     if (bIdCfg) pCan->CAN_MB[bMb].CAN_MAM |=  CAN_MAM_MIDE;\r
450     else        pCan->CAN_MB[bMb].CAN_MAM &= ~CAN_MAM_MIDE;\r
451 }\r
452 \r
453 /**\r
454  * \brief Set Identifier for standard frame mode (MIDvA) mask\r
455  * \param pCan       Pointer to Can instance.\r
456  * \param bMb        Mailbox number.\r
457  * \param dwMIDvA    Identifier for standard frame mode.\r
458  */\r
459 void CAN_SetMIDvAMask(Can *pCan, uint8_t bMb, uint32_t dwIDvA)\r
460 {\r
461     uint32_t dwMam = pCan->CAN_MB[bMb].CAN_MAM & CAN_MAM_MIDvA_Msk;\r
462     pCan->CAN_MB[bMb].CAN_MAM = dwMam | CAN_MAM_MIDvA(dwIDvA);\r
463 }\r
464 \r
465 /**\r
466  * \brief Set Complementary bits for identifier in extended frame mode (MIDvB) mask\r
467  * \param pCan       Pointer to Can instance.\r
468  * \param bMb        Mailbox number.\r
469  * \param dwMIDvB    Identifier for extended frame mode.\r
470  */\r
471 void CAN_SetMIDvBMask(Can *pCan, uint8_t bMb, uint32_t dwIDvA)\r
472 {\r
473     uint32_t dwMam = pCan->CAN_MB[bMb].CAN_MAM & CAN_MAM_MIDvB_Msk;\r
474     pCan->CAN_MB[bMb].CAN_MAM = dwMam | CAN_MAM_MIDvB(dwIDvA);\r
475 }\r
476 \r
477 /**\r
478  * \brief Configure CAN Message ID (_MIDx)\r
479  * \param pCan       Pointer to Can instance.\r
480  * \param bMb        Mailbox number.\r
481  * \param dwMID      The setting value for _MIDx.\r
482  */\r
483 void CAN_ConfigureMessageID(Can *pCan, uint8_t bMb, uint32_t dwMID)\r
484 {\r
485     pCan->CAN_MB[bMb].CAN_MID = dwMID;\r
486 }\r
487 \r
488 /**\r
489  * \brief Return CAN Message ID (_MIDx)\r
490  * \param pCan       Pointer to Can instance.\r
491  * \param bMb        Mailbox number.\r
492  */\r
493 uint32_t CAN_GetMessageID(Can *pCan, uint8_t bMb)\r
494 {\r
495     return pCan->CAN_MB[bMb].CAN_MID;\r
496 }\r
497 \r
498 /**\r
499  * \brief Configure Identifier Version in CAN Message ID register (_MIDx)\r
500  * \param pCan       Pointer to Can instance.\r
501  * \param bMb        Mailbox number.\r
502  * \param bIdVer     2.0 Part B/2.0 Part A.\r
503  */\r
504 void CAN_ConfigureIdVer(Can *pCan, uint8_t bMb, uint8_t bIdVer)\r
505 {\r
506     uint32_t dwMid = pCan->CAN_MB[bMb].CAN_MID & CAN_MID_MIDE;\r
507     pCan->CAN_MB[bMb].CAN_MID = dwMid | (bIdVer ? CAN_MID_MIDE : 0);\r
508 }\r
509 \r
510 /**\r
511  * \brief Set Identifier for standard frame mode (MIDvA) value\r
512  * \param pCan       Pointer to Can instance.\r
513  * \param bMb        Mailbox number.\r
514  * \param dwMIDvA    Identifier for standard frame mode.\r
515  */\r
516 void CAN_SetMIDvA(Can *pCan, uint8_t bMb, uint32_t dwIDvA)\r
517 {\r
518     uint32_t dwMam = pCan->CAN_MB[bMb].CAN_MID & CAN_MID_MIDvA_Msk;\r
519     pCan->CAN_MB[bMb].CAN_MID = dwMam | CAN_MID_MIDvA(dwIDvA);\r
520 }\r
521 \r
522 /**\r
523  * \brief Set Complementary bits for identifier in extended frame mode (MIDvB) value\r
524  * \param pCan       Pointer to Can instance.\r
525  * \param bMb        Mailbox number.\r
526  * \param dwMIDvB    Identifier for extended frame mode.\r
527  */\r
528 void CAN_SetMIDvB(Can *pCan, uint8_t bMb, uint32_t dwIDvA)\r
529 {\r
530     uint32_t dwMam = pCan->CAN_MB[bMb].CAN_MID & CAN_MID_MIDvB_Msk;\r
531     pCan->CAN_MB[bMb].CAN_MID = dwMam | CAN_MID_MIDvB(dwIDvA);\r
532 }\r
533 \r
534 /**\r
535  * \brief Return CAN Message Family ID (Masked ID)\r
536  * \param pCan       Pointer to Can instance.\r
537  * \param bMb        Mailbox number.\r
538  */\r
539 uint32_t CAN_GetFamilyID(Can *pCan, uint8_t bMb)\r
540 {\r
541     return pCan->CAN_MB[bMb].CAN_MFID;\r
542 }\r
543 \r
544 /**\r
545  * \brief Return CAN Message Status\r
546  * \param pCan       Pointer to Can instance.\r
547  * \param bMb        Mailbox number.\r
548  */\r
549 uint32_t CAN_GetMessageStatus(Can *pCan, uint8_t bMb)\r
550 {\r
551     return pCan->CAN_MB[bMb].CAN_MSR;\r
552 }\r
553 \r
554 /**\r
555  * \brief Return CAN Message Data Low\r
556  * \param pCan       Pointer to Can instance.\r
557  * \param bMb        Mailbox number.\r
558  */\r
559 uint32_t CAN_GetMessageDataL(Can *pCan, uint8_t bMb)\r
560 {\r
561     return pCan->CAN_MB[bMb].CAN_MDL;\r
562 }\r
563 \r
564 /**\r
565  * \brief Set CAN Message Data Low\r
566  * \param pCan       Pointer to Can instance.\r
567  * \param bMb        Mailbox number.\r
568  * \param dwL        Data Low Value.\r
569  */\r
570 void CAN_SetMessageDataL(Can *pCan, uint8_t bMb, uint32_t dwL)\r
571 {\r
572     pCan->CAN_MB[bMb].CAN_MDL = dwL;\r
573 }\r
574 \r
575 /**\r
576  * \brief Set CAN Message Data High\r
577  * \param pCan       Pointer to Can instance.\r
578  * \param bMb        Mailbox number.\r
579  * \param dwH        Data High Value.\r
580  */\r
581 void CAN_SetMessageDataH(Can *pCan, uint8_t bMb, uint32_t dwH)\r
582 {\r
583     pCan->CAN_MB[bMb].CAN_MDH = dwH;\r
584 }\r
585 \r
586 /**\r
587  * \brief Return CAN Message Data High\r
588  * \param pCan       Pointer to Can instance.\r
589  * \param bMb        Mailbox number.\r
590  */\r
591 uint32_t CAN_GetMessageDataH(Can *pCan, uint8_t bMb)\r
592 {\r
593     return pCan->CAN_MB[bMb].CAN_MDH;\r
594 }\r
595 \r
596 /**\r
597  * \brief Copy DW array to CAN Message Data.\r
598  * \param pCan       Pointer to Can instance.\r
599  * \param bMb        Mailbox number.\r
600  * \param pDwData    Pointer to a buffer for data.\r
601  */\r
602 void CAN_SetMessage(Can *pCan, uint8_t bMb, uint32_t *pDwData)\r
603 {\r
604     pCan->CAN_MB[bMb].CAN_MDL = pDwData[0];\r
605     pCan->CAN_MB[bMb].CAN_MDH = pDwData[1];\r
606 }\r
607 \r
608 /**\r
609  * \brief Copy CAN Message Data to DW array.\r
610  * \param pCan       Pointer to Can instance.\r
611  * \param bMb        Mailbox number.\r
612  * \param pDwData    Pointer to a buffer for data.\r
613  */\r
614 void CAN_GetMessage(Can *pCan, uint8_t bMb, uint32_t *pDwData)\r
615 {\r
616     pDwData[0] = pCan->CAN_MB[bMb].CAN_MDL;\r
617     pDwData[1] = pCan->CAN_MB[bMb].CAN_MDH;\r
618 }\r
619 \r
620 /**\r
621  * \brief Set CAN Message Data in u64\r
622  * \param pCan       Pointer to Can instance.\r
623  * \param bMb        Mailbox number.\r
624  */\r
625 void CAN_SetMessageData64(Can *pCan, uint8_t bMb, uint64_t u64)\r
626 {\r
627     pCan->CAN_MB[bMb].CAN_MDL = (uint32_t)u64;\r
628     pCan->CAN_MB[bMb].CAN_MDH = (u64 >> 32);\r
629 }\r
630 \r
631 /**\r
632  * \brief Return CAN Message Data in u64\r
633  * \param pCan       Pointer to Can instance.\r
634  * \param bMb        Mailbox number.\r
635  */\r
636 uint64_t CAN_GetMessageData64(Can *pCan, uint8_t bMb)\r
637 {\r
638     uint64_t ddwMd = (uint64_t)pCan->CAN_MB[bMb].CAN_MDH << 32;\r
639     ddwMd += pCan->CAN_MB[bMb].CAN_MDL;\r
640     return ddwMd;\r
641 }\r
642 \r
643 /**\r
644  * \brief Set CAN Message Control Register (_MCRx).\r
645  * \param pCan       Pointer to Can instance.\r
646  * \param bMb        Mailbox number.\r
647  * \param dwCtrl     Control value.\r
648  */\r
649 void CAN_MessageControl(Can *pCan, uint8_t bMb, uint32_t dwCtrl)\r
650 {\r
651     pCan->CAN_MB[bMb].CAN_MCR = dwCtrl;\r
652 }\r
653 \r
654 /**\r
655  * \brief Start remote frame.\r
656  * \param pCan       Pointer to Can instance.\r
657  * \param bMb        Mailbox number.\r
658  */\r
659 void CAN_MessageRemote(Can *pCan, uint8_t bMb)\r
660 {\r
661     pCan->CAN_MB[bMb].CAN_MCR = CAN_MCR_MRTR;\r
662 }\r
663 \r
664 /**\r
665  * \brief Abort transmission.\r
666  * \param pCan       Pointer to Can instance.\r
667  * \param bMb        Mailbox number.\r
668  */\r
669 void CAN_MessageAbort(Can *pCan, uint8_t bMb)\r
670 {\r
671     pCan->CAN_MB[bMb].CAN_MCR = CAN_MCR_MACR;\r
672 }\r
673 \r
674 /**\r
675  * \brief Start transmission.\r
676  * \param pCan       Pointer to Can instance.\r
677  * \param bMb        Mailbox number.\r
678  * \param bLen       Message length.\r
679  */\r
680 void CAN_MessageTx(Can *pCan, uint8_t bMb, uint8_t bLen)\r
681 {\r
682     pCan->CAN_MB[bMb].CAN_MCR = CAN_MCR_MTCR | CAN_MCR_MDLC(bLen);\r
683 }\r
684 \r
685 /**\r
686  * \brief Start reception.\r
687  * \param pCan       Pointer to Can instance.\r
688  * \param bMb        Mailbox number.\r
689  */\r
690 void CAN_MessageRx(Can *pCan, uint8_t bMb)\r
691 {\r
692     pCan->CAN_MB[bMb].CAN_MCR = CAN_MCR_MTCR;\r
693 }\r
694 \r
695 #endif\r
696 /**@}*/\r
697 \r