1 /*!
2 * @file apm32f4xx_can.c
3 *
4 * @brief This file provides all the CAN firmware functions
5 *
6 * @version V1.0.2
7 *
8 * @date 2022-06-23
9 *
10 * @attention
11 *
12 * Copyright (C) 2021-2022 Geehy Semiconductor
13 *
14 * You may not use this file except in compliance with the
15 * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
16 *
17 * The program is only for reference, which is distributed in the hope
18 * that it will be usefull and instructional for customers to develop
19 * their software. Unless required by applicable law or agreed to in
20 * writing, the program is distributed on an "AS IS" BASIS, WITHOUT
21 * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
23 * and limitations under the License.
24 */
25
26 #include "apm32f4xx_can.h"
27 #include "apm32f4xx_rcm.h"
28
29 /** @addtogroup APM32F4xx_StdPeriphDriver
30 @{
31 */
32
33 /** @defgroup CAN_Driver
34 * @brief CAN driver modules
35 @{
36 */
37
38 /** @defgroup CAN_Functions
39 @{
40 */
41
42 /*!
43 * @brief Reset CAN registers
44 *
45 * @param can: Select the CAN peripheral.
46 *
47 * @retval None
48 */
CAN_Reset(CAN_T * can)49 void CAN_Reset(CAN_T *can)
50 {
51 if (can == CAN1)
52 {
53 RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CAN1);
54 RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CAN1);
55 }
56 else if (can == CAN2)
57 {
58 RCM_EnableAPB1PeriphReset(RCM_APB1_PERIPH_CAN2);
59 RCM_DisableAPB1PeriphReset(RCM_APB1_PERIPH_CAN2);
60 }
61 }
62
63 /*!
64 * @brief Initialization parameter configuration
65 *
66 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
67 *
68 * @param canConfig: Point to a CAN_Config_T structure.
69 *
70 * @retval ERROR or SUCCEESS
71 */
CAN_Config(CAN_T * can,CAN_Config_T * canConfig)72 uint8_t CAN_Config(CAN_T *can, CAN_Config_T *canConfig)
73 {
74 uint8_t initStatus = ERROR;
75 uint32_t wait_ack = 0x00000000;
76
77 /* Exit from sleep mode */
78 can->MCTRL_B.SLEEPREQ = BIT_RESET;
79 /* Request initialisation */
80 can->MCTRL_B.INITREQ = BIT_SET;
81
82 /* Wait the acknowledge */
83 while (((can->MSTS_B.INITFLG) != BIT_SET) && (wait_ack != 0x0000FFFF))
84 {
85 wait_ack++;
86 }
87 /* Check acknowledge */
88 if (((can->MSTS_B.INITFLG) != BIT_SET))
89 {
90 initStatus = ERROR;
91 }
92 else
93 {
94 if (canConfig->autoBusOffManage == ENABLE)
95 {
96 can->MCTRL_B.ALBOFFM = BIT_SET;
97 }
98 else
99 {
100 can->MCTRL_B.ALBOFFM = BIT_RESET;
101 }
102
103 if (canConfig->autoWakeUpMode == ENABLE)
104 {
105 can->MCTRL_B.AWUPCFG = BIT_SET;
106 }
107 else
108 {
109 can->MCTRL_B.AWUPCFG = BIT_RESET;
110 }
111
112 if (canConfig->nonAutoRetran == ENABLE)
113 {
114 can->MCTRL_B.ARTXMD = BIT_SET;
115 }
116 else
117 {
118 can->MCTRL_B.ARTXMD = BIT_RESET;
119 }
120
121 if (canConfig->rxFIFOLockMode == ENABLE)
122 {
123 can->MCTRL_B.RXFLOCK = BIT_SET;
124 }
125 else
126 {
127 can->MCTRL_B.RXFLOCK = BIT_RESET;
128 }
129
130 if (canConfig->txFIFOPriority == ENABLE)
131 {
132 can->MCTRL_B.TXFPCFG = BIT_SET;
133 }
134 else
135 {
136 can->MCTRL_B.TXFPCFG = BIT_RESET;
137 }
138
139 /* Set the bit timing register */
140 can->BITTIM &= (uint32_t)0x3fffffff;
141 can->BITTIM |= (uint32_t)canConfig->mode << 30;
142 can->BITTIM_B.RSYNJW = canConfig->syncJumpWidth;
143 can->BITTIM_B.TIMSEG1 = canConfig->timeSegment1;
144 can->BITTIM_B.TIMSEG2 = canConfig->timeSegment2;
145 can->BITTIM_B.BRPSC = canConfig->prescaler - 1;
146
147 /* Request leave initialisation */
148 can->MCTRL_B.INITREQ = BIT_RESET;
149
150 wait_ack = 0;
151 /* Wait the acknowledge */
152 while (((can->MSTS_B.INITFLG) != BIT_RESET) && (wait_ack != 0x0000FFFF))
153 {
154 wait_ack++;
155 }
156 /* Check acknowledge */
157 if (((can->MSTS_B.INITFLG) != BIT_RESET))
158 {
159 initStatus = ERROR;
160 }
161 else
162 {
163 initStatus = SUCCESS;
164 }
165 }
166 return initStatus;
167 }
168
169 /*!
170 * @brief Congig the CAN peripheral according to the specified parameters in the filterConfig.
171 *
172 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
173 *
174 * @param filterConfig :Point to a CAN_FilterConfig_T structure.
175 *
176 * @retval None
177 */
CAN_ConfigFilter(CAN_FilterConfig_T * filterConfig)178 void CAN_ConfigFilter(CAN_FilterConfig_T *filterConfig)
179 {
180 CAN1->FCTRL_B.FINITEN = BIT_SET;
181
182 CAN1->FACT &= ~(1 << filterConfig->filterNumber);
183
184 /* Filter Scale */
185 if (filterConfig->filterScale == CAN_FILTER_SCALE_16BIT)
186 {
187 /* 16-bit scale for the filter */
188 CAN1->FSCFG &= ~(1 << filterConfig->filterNumber);
189
190 CAN1->sFilterRegister[filterConfig->filterNumber].FBANK1 =
191 ((0x0000FFFF & filterConfig->filterMaskIdLow) << 16) |
192 (0x0000FFFF & filterConfig->filterIdLow);
193
194 CAN1->sFilterRegister[filterConfig->filterNumber].FBANK2 =
195 ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) |
196 (0x0000FFFF & filterConfig->filterIdHigh);
197 }
198
199 if (filterConfig->filterScale == CAN_FILTER_SCALE_32BIT)
200 {
201 CAN1->FSCFG |= (1 << filterConfig->filterNumber);
202
203 CAN1->sFilterRegister[filterConfig->filterNumber].FBANK1 =
204 ((0x0000FFFF & filterConfig->filterIdHigh) << 16) |
205 (0x0000FFFF & filterConfig->filterIdLow);
206
207 CAN1->sFilterRegister[filterConfig->filterNumber].FBANK2 =
208 ((0x0000FFFF & filterConfig->filterMaskIdHigh) << 16) |
209 (0x0000FFFF & filterConfig->filterMaskIdLow);
210 }
211
212 /* Filter Mode */
213 if (filterConfig->filterMode == CAN_FILTER_MODE_IDMASK)
214 {
215 CAN1->FMCFG &= ~(1 << filterConfig->filterNumber);
216 }
217 else
218 {
219 CAN1->FMCFG |= (1 << filterConfig->filterNumber);
220 }
221
222 /* Filter FIFO assignment */
223 if (filterConfig->filterFIFO == CAN_FILTER_FIFO_0)
224 {
225 CAN1->FFASS &= ~(1 << filterConfig->filterNumber);
226 }
227 if (filterConfig->filterFIFO == CAN_FILTER_FIFO_1)
228 {
229 CAN1->FFASS |= (1 << filterConfig->filterNumber);
230 }
231
232 /* Filter activation */
233 if (filterConfig->filterActivation == ENABLE)
234 {
235 CAN1->FACT |= (1 << filterConfig->filterNumber);
236 }
237 CAN1->FCTRL_B.FINITEN = BIT_RESET;
238 }
239
240 /*!
241 * @brief Initialize a CAN_Config_T structure with the initial value.
242 *
243 * @param canConfig :Point to a CAN_Config_T structure.
244 *
245 * @retval None
246 */
CAN_ConfigStructInit(CAN_Config_T * canConfig)247 void CAN_ConfigStructInit(CAN_Config_T *canConfig)
248 {
249 canConfig->autoBusOffManage = DISABLE;
250 canConfig->autoWakeUpMode = DISABLE;
251 canConfig->nonAutoRetran = DISABLE;
252 canConfig->rxFIFOLockMode = DISABLE;
253 canConfig->txFIFOPriority = DISABLE;
254 canConfig->mode = CAN_MODE_NORMAL;
255 canConfig->syncJumpWidth = CAN_SJW_1;
256 canConfig->timeSegment1 = CAN_TIME_SEGMENT1_4;
257 canConfig->timeSegment2 = CAN_TIME_SEGMENT2_3;
258 canConfig->prescaler = 1;
259 }
260
261 /*!
262 * @brief Select the start bank filter for slave CAN.
263 *
264 * @param bankNum: the start slave bank filter from 1..27.
265 *
266 * @retval None
267 */
CAN_SlaveStartBank(CAN_T * can,uint8_t bankNum)268 void CAN_SlaveStartBank(CAN_T *can, uint8_t bankNum)
269 {
270 can->FCTRL_B.FINITEN = SET;
271 can->FCTRL_B.CAN2BN = bankNum;
272 can->FCTRL_B.FINITEN = RESET;
273 }
274
275 /*!
276 * @brief Enables the DBG Freeze for CAN.
277 *
278 * @param can: Select the CAN peripheral.
279 *
280 * @retval None
281 *
282 * @note None
283 */
CAN_EnableDBGFreeze(CAN_T * can)284 void CAN_EnableDBGFreeze(CAN_T *can)
285 {
286 can->MCTRL_B.DBGFRZE = ENABLE;
287 }
288
289 /*!
290 * @brief Disable the DBG Freeze for CAN.
291 *
292 * @param can: Select the CAN peripheral.
293 *
294 * @retval None
295 *
296 * @note None
297 */
CAN_DisableDBGFreeze(CAN_T * can)298 void CAN_DisableDBGFreeze(CAN_T *can)
299 {
300 can->MCTRL_B.DBGFRZE = DISABLE;
301 }
302
303 /*!
304 * @brief Initiates the transmission of a message.
305 *
306 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
307 *
308 * @param TxMessage: pointer to a CAN_TX_MESSAGE structure.
309 *
310 * @retval The number of the mailbox which is used for transmission or 3 if No mailbox is empty.
311 */
CAN_TxMessage(CAN_T * can,CAN_TxMessage_T * TxMessage)312 uint8_t CAN_TxMessage(CAN_T *can, CAN_TxMessage_T *TxMessage)
313 {
314 uint8_t transmit_milbox = 0;
315
316 /* Select one empty transmit mailbox */
317 if ((can->TXSTS & 0x04000000) == 0x04000000)
318 {
319 transmit_milbox = 0;
320 }
321 else if ((can->TXSTS & 0x08000000) == 0x08000000)
322 {
323 transmit_milbox = 1;
324 }
325 else if ((can->TXSTS & 0x10000000) == 0x10000000)
326 {
327 transmit_milbox = 2;
328 }
329 else
330 {
331 /* No mailbox is empty*/
332 return 3;
333 }
334
335 /* Set up the Id */
336 can->sTxMailBox[transmit_milbox].TXMID &= 0x00000001;
337 if (TxMessage->typeID == CAN_TYPEID_STD)
338 {
339 can->sTxMailBox[transmit_milbox].TXMID |= (TxMessage->stdID << 21) | (TxMessage->remoteTxReq);
340 }
341 else
342 {
343 can->sTxMailBox[transmit_milbox].TXMID |= (TxMessage->extID << 3) | (TxMessage->typeID) | (TxMessage->remoteTxReq);
344 }
345
346 /* Set up the TXDLEN */
347 TxMessage->dataLengthCode &= 0x0F;
348 can->sTxMailBox[transmit_milbox].TXDLEN &= (uint32_t)0xFFFFFFF0;
349 can->sTxMailBox[transmit_milbox].TXDLEN |= TxMessage->dataLengthCode;
350
351 /* Set up the data field */
352 can->sTxMailBox[transmit_milbox].TXMDL = ((uint32_t)TxMessage->data[3] << 24) | ((uint32_t)TxMessage->data[2] << 16)
353 | ((uint32_t)TxMessage->data[1] << 8) | ((uint32_t)TxMessage->data[0]);
354 can->sTxMailBox[transmit_milbox].TXMDH = ((uint32_t)TxMessage->data[7] << 24) | ((uint32_t)TxMessage->data[6] << 16)
355 | ((uint32_t)TxMessage->data[5] << 8) | ((uint32_t)TxMessage->data[4]);
356 /* Request transmission */
357 can->sTxMailBox[transmit_milbox].TXMID |= 0x00000001;
358
359 return transmit_milbox;
360 }
361
362 /*!
363 * @brief Checks the transmission of a message.
364 *
365 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
366 *
367 * @param TxMailbox: the number of the mailbox
368 * This parameter can be one of the following values:
369 * @arg CAN_TX_MAILBIX_0 : Tx mailbox0
370 * @arg CAN_TX_MAILBIX_1 : Tx mailbox1
371 * @arg CAN_TX_MAILBIX_2 : Tx mailbox2
372 *
373 * @retval state: 0: Status of transmission is Failed
374 * 1: Status of transmission is Ok
375 * 2: transmit pending
376 */
CAN_TxMessageStatus(CAN_T * can,CAN_TX_MAILBIX_T TxMailbox)377 uint8_t CAN_TxMessageStatus(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox)
378 {
379 uint32_t state = 0;
380
381 switch (TxMailbox)
382 {
383 case (CAN_TX_MAILBIX_0):
384 state = can->TXSTS & (0x00000001 | 0x00000002 | 0x04000000);
385 break;
386 case (CAN_TX_MAILBIX_1):
387 state = can->TXSTS & (0x00000100 | 0x00000200 | 0x08000000);
388 break;
389 case (CAN_TX_MAILBIX_2):
390 state = can->TXSTS & (0x00010000 | 0x00020000 | 0x10000000);
391 break;
392 default:
393 state = 0;
394 break;
395 }
396 switch (state)
397 {
398 /** transmit pending */
399 case (0x0):
400 state = 2;
401 break;
402 /* transmit failed */
403 case (0x00000001 | 0x04000000):
404 state = 0;
405 break;
406 case (0x00000100 | 0x08000000):
407 state = 0;
408 break;
409 case (0x00010000 | 0x10000000):
410 state = 0;
411 break;
412 /* transmit succeeded */
413 case (0x00000001 | 0x00000002 | 0x04000000):
414 state = 1;
415 break;
416 case (0x00000100 | 0x00000200 | 0x08000000):
417 state = 1;
418 break;
419 case (0x00010000 | 0x00020000 | 0x10000000):
420 state = 1;
421 break;
422 default:
423 state = 0;
424 break;
425 }
426 return (uint8_t) state;
427 }
428
429 /*!
430 * @brief Cancels a transmit request.
431 *
432 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
433 *
434 * @param mailBox: the number of the mailbox
435 * This parameter can be one of the following values:
436 * @arg CAN_TX_MAILBIX_0 : Tx mailbox 0
437 * @arg CAN_TX_MAILBIX_1 : Tx mailbox 1
438 * @arg CAN_TX_MAILBIX_2 : Tx mailbox 2
439 *
440 * @retval None
441 */
CAN_CancelTxMailbox(CAN_T * can,CAN_TX_MAILBIX_T TxMailbox)442 void CAN_CancelTxMailbox(CAN_T *can, CAN_TX_MAILBIX_T TxMailbox)
443 {
444 switch (TxMailbox)
445 {
446 case CAN_TX_MAILBIX_0:
447 can->TXSTS_B.ABREQFLG0 = BIT_SET;
448 break;
449 case CAN_TX_MAILBIX_1:
450 can->TXSTS_B.ABREQFLG1 = BIT_SET;
451 break;
452 case CAN_TX_MAILBIX_2:
453 can->TXSTS_B.ABREQFLG2 = BIT_SET;
454 break;
455 default:
456 break;
457 }
458 }
459
460 /*!
461 * @brief Receives a message and save to a CAN_RxMessage_T structure.
462 *
463 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
464 *
465 * @param FIFONumber: Receive FIFO number.
466 * This parameter can be one of the following values:
467 * @arg CAN_RX_FIFO_0 : Receive FIFO 0
468 * @arg CAN_RX_FIFO_1 : Receive FIFO 1
469 *
470 * @param RxMessage: pointer to a structure to receive the message.
471 *
472 * @retval None
473 */
CAN_RxMessage(CAN_T * can,CAN_RX_FIFO_T FIFONumber,CAN_RxMessage_T * RxMessage)474 void CAN_RxMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber, CAN_RxMessage_T *RxMessage)
475 {
476 /* Get the Id */
477 RxMessage->typeID = ((uint8_t)0x04 & (can->sRxMailBox[FIFONumber].RXMID));
478 if (RxMessage->typeID == CAN_TYPEID_STD)
479 {
480 RxMessage->stdID = (can->sRxMailBox[FIFONumber].RXMID >> 21) & 0x000007FF;
481 }
482 else
483 {
484 RxMessage->extID = (can->sRxMailBox[FIFONumber].RXMID >> 3) & 0x1FFFFFFF;
485 }
486
487 RxMessage->remoteTxReq = can->sRxMailBox[FIFONumber].RXMID_B.RFTXREQ;
488 RxMessage->dataLengthCode = can->sRxMailBox[FIFONumber].RXDLEN_B.DLCODE;
489 RxMessage->filterMatchIndex = can->sRxMailBox[FIFONumber].RXDLEN_B.FMIDX;
490 /** Get the data field */
491 RxMessage->data[0] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE0;
492 RxMessage->data[1] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE1;
493 RxMessage->data[2] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE2;
494 RxMessage->data[3] = can->sRxMailBox[FIFONumber].RXMDL_B.DATABYTE3;
495 RxMessage->data[4] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE4;
496 RxMessage->data[5] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE5;
497 RxMessage->data[6] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE6;
498 RxMessage->data[7] = can->sRxMailBox[FIFONumber].RXMDH_B.DATABYTE7;
499
500 if (FIFONumber == CAN_RX_FIFO_0)
501 {
502 can->RXF0_B.RFOM0 = BIT_SET;
503 }
504 else
505 {
506 can->RXF1_B.RFOM1 = BIT_SET;
507 }
508 }
509
510 /*!
511 * @brief Releases the specified FIFO.
512 *
513 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
514 *
515 * @param FIFONumber: Receive FIFO number
516 * This parameter can be one of the following values:
517 * @arg CAN_RX_FIFO_0 : Receive FIFO 0
518 * @arg CAN_RX_FIFO_1 : Receive FIFO 1
519 *
520 * @retval None
521 */
CAN_ReleaseFIFO(CAN_T * can,CAN_RX_FIFO_T FIFONumber)522 void CAN_ReleaseFIFO(CAN_T *can, CAN_RX_FIFO_T FIFONumber)
523 {
524 if (FIFONumber == CAN_RX_FIFO_0)
525 {
526 can->RXF0_B.RFOM0 = BIT_SET;
527 }
528 else
529 {
530 can->RXF1_B.RFOM1 = BIT_SET;
531 }
532 }
533
534 /*!
535 * @brief Returns the number of pending messages.
536 *
537 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
538 *
539 * @param FIFONumber: Receive FIFO number
540 * This parameter can be one of the following values:
541 * @arg CAN_RX_FIFO_0 : Receive FIFO 0
542 * @arg CAN_RX_FIFO_1 : Receive FIFO 1
543 *
544 * @retval The number of pending message.
545 */
CAN_PendingMessage(CAN_T * can,CAN_RX_FIFO_T FIFONumber)546 uint8_t CAN_PendingMessage(CAN_T *can, CAN_RX_FIFO_T FIFONumber)
547 {
548 if (FIFONumber == CAN_RX_FIFO_0)
549 {
550 return can->RXF0 & 0x03;
551 }
552 else
553 {
554 return can->RXF1 & 0x03;
555 }
556 }
557
558 /*!
559 * @brief Select the CAN Operation mode
560 *
561 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
562 *
563 * @param operatingMode: CAN Operating Mode
564 * This parameter can be one of the following values:
565 * @arg CAN_OPERATING_MODE_INIT : Initialization mode
566 * @arg CAN_OPERATING_MODE_NORMAL: Normal mode
567 * @arg CAN_OPERATING_MODE_SLEEP : sleep mode
568 *
569 * @retval modeState:status of the requested mode
570 * 0:CAN failed entering the specific mode
571 * 1:CAN Succeed entering the specific mode
572 */
CAN_OperatingMode(CAN_T * can,CAN_OPERATING_MODE_T operatingMode)573 uint8_t CAN_OperatingMode(CAN_T *can, CAN_OPERATING_MODE_T operatingMode)
574 {
575 uint8_t states = 0;
576 uint32_t time_out = 0x0000FFFF;
577
578 if (operatingMode == CAN_OPERATING_MODE_INIT)
579 {
580 /** Request initialisation */
581 can->MCTRL_B.SLEEPREQ = BIT_RESET;
582 can->MCTRL_B.INITREQ = BIT_SET;
583
584 /* Wait the acknowledge */
585 while ((can->MSTS_B.INITFLG != BIT_SET && can->MSTS_B.SLEEPFLG != BIT_RESET) && (time_out != 0))
586 {
587 time_out --;
588 }
589 if ((can->MSTS_B.INITFLG == BIT_SET && can->MSTS_B.SLEEPFLG == BIT_RESET))
590 {
591 states = 1;
592 }
593 }
594 else if (operatingMode == CAN_OPERATING_MODE_NORMAL)
595 {
596 /** Request leave initialisation and sleep mode and enter Normal mode */
597 can->MCTRL_B.SLEEPREQ = BIT_RESET;
598 can->MCTRL_B.INITREQ = BIT_RESET;
599
600 time_out = 0x0000FFFF;
601
602 while ((can->MSTS_B.INITFLG != BIT_RESET || can->MSTS_B.SLEEPFLG != BIT_RESET) && (time_out != 0))
603 {
604 time_out --;
605 }
606 if ((can->MSTS_B.INITFLG == BIT_RESET || can->MSTS_B.SLEEPFLG == BIT_RESET))
607 {
608 states = 1;
609 }
610 }
611 else if (operatingMode == CAN_OPERATING_MODE_SLEEP)
612 {
613 /** Request Sleep mode */
614 can->MCTRL_B.SLEEPREQ = BIT_SET;
615 can->MCTRL_B.INITREQ = BIT_RESET;
616
617 time_out = 0x0000FFFF;
618
619 while ((can->MSTS_B.INITFLG != BIT_RESET && can->MSTS_B.SLEEPFLG != BIT_SET) && (time_out != 0))
620 {
621 time_out --;
622 }
623 if ((can->MSTS_B.INITFLG == BIT_RESET && can->MSTS_B.SLEEPFLG == BIT_SET))
624 {
625 states = 1;
626 }
627 }
628 return states ;
629 }
630
631 /*!
632 * @brief Into the low power mode.
633 *
634 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
635 *
636 * @retval status: Status of entering sleep mode.
637 * 0: Enter sleep fail
638 * 1: Enter sleep success
639 */
CAN_SleepMode(CAN_T * can)640 uint8_t CAN_SleepMode(CAN_T *can)
641 {
642 /** Request Sleep mode */
643 can->MCTRL_B.SLEEPREQ = BIT_SET;
644 can->MCTRL_B.INITREQ = BIT_RESET;
645
646 if ((can->MSTS_B.INITFLG == BIT_RESET && can->MSTS_B.SLEEPFLG == BIT_SET))
647 {
648 return 1;
649 }
650 return 0;
651 }
652
653 /*!
654 * @brief Wakes the CAN up.
655 *
656 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
657 *
658 * @retval status: Status of waking the CAN up
659 * 0: WakeUp CAN fail,
660 * 1: WakeUp CAN success
661 */
CAN_WakeUpMode(CAN_T * can)662 uint8_t CAN_WakeUpMode(CAN_T *can)
663 {
664 uint32_t time_out = 0x0000FFFF;
665
666 /** Wake up request */
667 can->MCTRL_B.SLEEPREQ = BIT_RESET;
668 while ((can->MSTS_B.SLEEPFLG == BIT_SET) && (time_out != 0))
669 {
670 time_out --;
671 }
672 if (can->MSTS_B.SLEEPFLG != BIT_SET)
673 {
674 return 1;
675 }
676 return 0;
677 }
678
679 /*!
680 * @brief Read the can's last error code (LERRC)
681 *
682 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
683 *
684 * @retval The Last Error Code.
685 */
CAN_ReadLastErrorCode(CAN_T * can)686 uint8_t CAN_ReadLastErrorCode(CAN_T *can)
687 {
688 return can->ERRSTS_B.LERRC;
689 }
690
691 /*!
692 * @brief Read the can Receive Error Counter(RXERRCNT)
693 *
694 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
695 *
696 * @retval CAN Receive Error Counter.
697 */
CAN_ReadRxErrorCounter(CAN_T * can)698 uint8_t CAN_ReadRxErrorCounter(CAN_T *can)
699 {
700 return can->ERRSTS_B.RXERRCNT;
701 }
702
703 /*!
704 * @brief Read the LSB of the 9-bit can Transmit Error Counter(TXERRCNT).
705 *
706 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
707 *
708 * @retval Least Significant Byte Of The 9-Bit Transmit Error Counter.
709 */
CAN_ReadLSBTxErrorCounter(CAN_T * can)710 uint8_t CAN_ReadLSBTxErrorCounter(CAN_T *can)
711 {
712 return can->ERRSTS_B.TXERRCNT;
713 }
714
715 /*!
716 * @brief Enables the specified can interrupts.
717 *
718 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
719 *
720 * @param interrupts: specifies the CAN interrupt sources
721 * This parameter can be any combination of the following values:
722 * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt
723 * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt
724 * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt
725 * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt
726 * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt
727 * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt
728 * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt
729 * @arg CAN_INT_ERRW : Error warning Interrupt
730 * @arg CAN_INT_ERRP : Error passive Interrupt
731 * @arg CAN_INT_BOF : Bus-off Interrupt
732 * @arg CAN_INT_LEC : Last error record code Interrupt
733 * @arg CAN_INT_ERR : Error Interrupt
734 * @arg CAN_INT_WUP : Wake-up Interrupt
735 * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt
736 *
737 * @retval None
738 */
CAN_EnableInterrupt(CAN_T * can,uint32_t interrupts)739 void CAN_EnableInterrupt(CAN_T *can, uint32_t interrupts)
740 {
741 can->INTEN |= interrupts;
742 }
743
744 /*!
745 * @brief Disable the specified can interrupts.
746 *
747 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
748 *
749 * @param interrupts: specifies the CAN interrupt sources
750 * This parameter can be any combination of the following values:
751 * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt
752 * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt
753 * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt
754 * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt
755 * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt
756 * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt
757 * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt
758 * @arg CAN_INT_ERRW : Error warning Interrupt
759 * @arg CAN_INT_ERRP : Error passive Interrupt
760 * @arg CAN_INT_BOF : Bus-off Interrupt
761 * @arg CAN_INT_LEC : Last error record code Interrupt
762 * @arg CAN_INT_ERR : Error Interrupt
763 * @arg CAN_INT_WUP : Wake-up Interrupt
764 * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt
765 *
766 * @retval None
767 */
CAN_DisableInterrupt(CAN_T * can,uint32_t interrupts)768 void CAN_DisableInterrupt(CAN_T *can, uint32_t interrupts)
769 {
770 can->INTEN &= ~interrupts;
771 }
772
773 /*!
774 * @brief Read whether the specified CAN flag is set or not.
775 *
776 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
777 *
778 * @param flag: specifies the CAN flag.
779 * This parameter can be one of the following values:
780 * @arg CAN_FLAG_ERRW : Error Warning Flag
781 * @arg CAN_FLAG_ERRP : Error Passive Flag
782 * @arg CAN_FLAG_BOF : Bus-Off Flag
783 * @arg CAN_FLAG_LERRC : Last error record code Flag
784 * @arg CAN_FLAG_WUPI : Wake up Flag
785 * @arg CAN_FLAG_SLEEP : Sleep acknowledge Flag
786 * @arg CAN_FLAG_F0MP : FIFO 0 Message Pending Flag
787 * @arg CAN_FLAG_F0FULL : FIFO 0 Full Flag
788 * @arg CAN_FLAG_F0OVR : FIFO 0 Overrun Flag
789 * @arg CAN_FLAG_F1MP : FIFO 1 Message Pending Flag
790 * @arg CAN_FLAG_F1FULL : FIFO 1 Full Flag
791 * @arg CAN_FLAG_F1OVR : FIFO 1 Overrun Flag
792 * @arg CAN_FLAG_REQC0 : Request MailBox0 Flag
793 * @arg CAN_FLAG_REQC1 : Request MailBox1 Flag
794 * @arg CAN_FLAG_REQC2 : Request MailBox2 Flag
795 *
796 * @retval flag staus: RESET or SET
797 */
CAN_ReadStatusFlag(CAN_T * can,CAN_FLAG_T flag)798 uint8_t CAN_ReadStatusFlag(CAN_T *can, CAN_FLAG_T flag)
799 {
800 uint8_t status = 0;
801
802 if ((flag & 0x00F00000) != RESET)
803 {
804 if ((can->ERRSTS & (flag & 0x000FFFFF)) != RESET)
805 {
806 status = SET;
807 }
808 else
809 {
810 status = RESET;
811 }
812 }
813 else if ((flag & 0x01000000) != RESET)
814 {
815 if ((can->MSTS & (flag & 0x000FFFFF)) != RESET)
816 {
817 status = SET;
818 }
819 else
820 {
821 status = RESET ;
822 }
823 }
824 else if ((flag & 0x08000000) != RESET)
825 {
826 if ((can->TXSTS & (flag & 0x000FFFFF)) != RESET)
827 {
828 status = SET;
829 }
830 else
831 {
832 status = RESET;
833 }
834 }
835 else if ((flag & 0x02000000) != RESET)
836 {
837 if ((can->RXF0 & (flag & 0x000FFFFF)) != RESET)
838 {
839 status = SET;
840 }
841 else
842 {
843 status = RESET;
844 }
845 }
846 else
847 {
848 if ((can->RXF1 & (flag & 0x000FFFFF)) != RESET)
849 {
850 status = SET;
851 }
852 else
853 {
854 status = RESET;
855 }
856 }
857 return status;
858 }
859
860 /*!
861 * @brief Clears the CAN's pending flags.
862 *
863 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
864 *
865 * @param flag: specifies the CAN flag.
866 * This parameter can be one of the following values:
867 * @arg CAN_FLAG_LERRC : Last error record code Flag
868 * @arg CAN_FLAG_WUPI : Wake up Flag
869 * @arg CAN_FLAG_SLEEP : Sleep acknowledge Flag
870 * @arg CAN_FLAG_F0FULL: FIFO 0 Full Flag
871 * @arg CAN_FLAG_F0OVR : FIFO 0 Overrun Flag
872 * @arg CAN_FLAG_F1FULL: FIFO 1 Full Flag
873 * @arg CAN_FLAG_F1OVR : FIFO 1 Overrun Flag
874 * @arg CAN_FLAG_REQC0 : Request MailBox0 Flag
875 * @arg CAN_FLAG_REQC1 : Request MailBox1 Flag
876 * @arg CAN_FLAG_REQC2 : Request MailBox2 Flag
877 *
878 * @retval None
879 */
CAN_ClearStatusFlag(CAN_T * can,CAN_FLAG_T flag)880 void CAN_ClearStatusFlag(CAN_T *can, CAN_FLAG_T flag)
881 {
882 uint32_t flagtmp = 0;
883
884 /** ERRSTS register */
885 if (flag == 0x30F00070)
886 {
887 can->ERRSTS = RESET;
888 }
889 else
890 {
891 flagtmp = flag & 0x000FFFFF;
892 if ((flag & 0x02000000) != RESET)
893 {
894 can->RXF0 = flagtmp;
895 }
896 else if ((flag & 0x04000000) != RESET)
897 {
898 can->RXF1 = flagtmp;
899 }
900 else if ((flag & 0x08000000) != RESET)
901 {
902 can->TXSTS = flagtmp;
903 }
904 else
905 {
906 can->MSTS = flagtmp;
907 }
908 }
909 }
910
911 /*!
912 * @brief Read whether the specified can interrupt has occurred or not.
913 *
914 * @param can: Select the CAN peripheral.
915 *
916 * @param interrupts: specifies the CAN interrupt sources
917 * This parameter can be one of the following values:
918 * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt
919 * @arg CAN_INT_F0MP : FIFO 0 message pending Interrupt
920 * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt
921 * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt
922 * @arg CAN_INT_F1MP : FIFO 1 message pending Interrupt
923 * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt
924 * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt
925 * @arg CAN_INT_ERRW : Error warning Interrupt
926 * @arg CAN_INT_ERRP : Error passive Interrupt
927 * @arg CAN_INT_BOF : Bus-off Interrupt
928 * @arg CAN_INT_LEC : Last error record code Interrupt
929 * @arg CAN_INT_ERR : Error Interrupt
930 * @arg CAN_INT_WUP : Wake-up Interrupt
931 * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt
932 *
933 * @retval status : SET or RESET
934 */
CAN_ReadIntFlag(CAN_T * can,CAN_INT_T flag)935 uint8_t CAN_ReadIntFlag(CAN_T *can, CAN_INT_T flag)
936 {
937 uint8_t status = 0;
938
939 if ((can->INTEN & flag) != RESET)
940 {
941 switch (flag)
942 {
943 case CAN_INT_TXME:
944 status = can->TXSTS_B.REQCFLG0;
945 status |= can->TXSTS_B.REQCFLG1;
946 status |= can->TXSTS_B.REQCFLG2;
947 break;
948 case CAN_INT_F0MP:
949 status = can->RXF0_B.FMNUM0;
950 break;
951 case CAN_INT_F0FULL:
952 status = can->RXF0_B.FFULLFLG0;
953 break;
954 case CAN_INT_F0OVR:
955 status = can->RXF0_B.FOVRFLG0;
956 break;
957 case CAN_INT_F1MP:
958 status = can->RXF1_B.FMNUM1;
959 break;
960 case CAN_INT_F1FULL:
961 status = can->RXF1_B.FFULLFLG1;
962 break;
963 case CAN_INT_F1OVR:
964 status = can->RXF1_B.FOVRFLG1;
965 break;
966 case CAN_INT_WUP:
967 status = can->MSTS_B.WUPIFLG;
968 break;
969 case CAN_INT_SLEEP:
970 status = can->MSTS_B.SLEEPIFLG;
971 break;
972 case CAN_INT_ERRW:
973 status = can->ERRSTS_B.ERRWFLG;
974 break;
975 case CAN_INT_ERRP:
976 status = can->ERRSTS_B.ERRPFLG;
977 break;
978 case CAN_INT_BOF:
979 status = can->ERRSTS_B.BOFLG;
980 break;
981 case CAN_INT_LEC:
982 status = can->ERRSTS_B.LERRC;
983 break;
984 case CAN_INT_ERR:
985 status = can->MSTS_B.ERRIFLG;
986 break;
987 default:
988 status = RESET;
989 break;
990 }
991 }
992 else
993 {
994 status = RESET;
995 }
996 return status;
997 }
998
999 /*!
1000 * @brief Clears the can's interrupt flag.
1001 *
1002 * @param can: Select the CAN peripheral which can be CAN1 or CAN2.
1003 *
1004 * @param flag: Interrupt pending bit to clear
1005 * This parameter can be one of the following values:
1006 * @arg CAN_INT_TXME : Transmit mailbox empty Interrupt
1007 * @arg CAN_INT_F0FULL : FIFO 0 full Interrupt
1008 * @arg CAN_INT_F0OVR : FIFO 0 overrun Interrupt
1009 * @arg CAN_INT_F1FULL : FIFO 1 full Interrupt
1010 * @arg CAN_INT_F1OVR : FIFO 1 overrun Interrupt
1011 * @arg CAN_INT_ERRW : Error warning Interrupt
1012 * @arg CAN_INT_ERRP : Error passive Interrupt
1013 * @arg CAN_INT_BOF : Bus-off Interrupt
1014 * @arg CAN_INT_LEC : Last error record code Interrupt
1015 * @arg CAN_INT_ERR : Error Interrupt
1016 * @arg CAN_INT_WUP : Wake-up Interrupt
1017 * @arg CAN_INT_SLEEP : Sleep acknowledge Interrupt
1018 *
1019 * @retval None
1020 */
CAN_ClearIntFlag(CAN_T * can,CAN_INT_T flag)1021 void CAN_ClearIntFlag(CAN_T *can, CAN_INT_T flag)
1022 {
1023 switch (flag)
1024 {
1025 case CAN_INT_TXME:
1026 can->TXSTS_B.REQCFLG0 = BIT_SET;
1027 can->TXSTS_B.REQCFLG1 = BIT_SET;
1028 can->TXSTS_B.REQCFLG2 = BIT_SET;
1029 break;
1030 case CAN_INT_F0FULL:
1031 can->RXF0_B.FFULLFLG0 = BIT_SET;
1032 break;
1033 case CAN_INT_F0OVR:
1034 can->RXF0_B.FOVRFLG0 = BIT_SET;
1035 break;
1036 case CAN_INT_F1FULL:
1037 can->RXF1_B.FFULLFLG1 = BIT_SET;
1038 break;
1039 case CAN_INT_F1OVR:
1040 can->RXF1_B.FOVRFLG1 = BIT_SET;
1041 break;
1042 case CAN_INT_WUP:
1043 can->MSTS_B.WUPIFLG = BIT_SET;
1044 break;
1045 case CAN_INT_SLEEP:
1046 can->MSTS_B.SLEEPIFLG = BIT_SET;
1047 break;
1048 case CAN_INT_ERRW:
1049 can->MSTS_B.ERRIFLG = BIT_SET;
1050 break;
1051 case CAN_INT_ERRP:
1052 can->MSTS_B.ERRIFLG = BIT_SET;
1053 break;
1054 case CAN_INT_BOF:
1055 can->MSTS_B.ERRIFLG = BIT_SET;
1056 break;
1057 case CAN_INT_LEC:
1058 can->ERRSTS_B.LERRC = BIT_RESET;
1059 can->MSTS_B.ERRIFLG = BIT_SET;
1060 break;
1061 case CAN_INT_ERR:
1062 can->ERRSTS_B.LERRC = BIT_RESET;
1063 can->MSTS_B.ERRIFLG = BIT_SET;
1064 break;
1065 default:
1066 break;
1067 }
1068 }
1069
1070 /**@} end of group CAN_Functions */
1071 /**@} end of group CAN_Driver */
1072 /**@} end of group APM32F4xx_StdPeriphDriver */
1073