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