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