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