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