1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_hal_can.c
4   * @author  MCD Application Team
5   * @version V1.0.1
6   * @date    25-June-2015
7   * @brief   CAN HAL module driver.
8   *          This file provides firmware functions to manage the following
9   *          functionalities of the Controller Area Network (CAN) peripheral:
10   *           + Initialization and de-initialization functions
11   *           + IO operation functions
12   *           + Peripheral Control functions
13   *           + Peripheral State and Error functions
14   *
15   @verbatim
16   ==============================================================================
17                         ##### How to use this driver #####
18   ==============================================================================
19     [..]
20       (#) Enable the CAN controller interface clock using
21           __HAL_RCC_CAN1_CLK_ENABLE() for CAN1 and __HAL_RCC_CAN2_CLK_ENABLE() for CAN2
22       -@- In case you are using CAN2 only, you have to enable the CAN1 clock.
23 
24       (#) CAN pins configuration
25         (++) Enable the clock for the CAN GPIOs using the following function:
26              __HAL_RCC_GPIOx_CLK_ENABLE()
27         (++) Connect and configure the involved CAN pins to AF9 using the
28               following function HAL_GPIO_Init()
29 
30       (#) Initialize and configure the CAN using HAL_CAN_Init() function.
31 
32       (#) Transmit the desired CAN frame using HAL_CAN_Transmit() function.
33 
34       (#) Receive a CAN frame using HAL_CAN_Receive() function.
35 
36      *** Polling mode IO operation ***
37      =================================
38      [..]
39        (+) Start the CAN peripheral transmission and wait the end of this operation
40            using HAL_CAN_Transmit(), at this stage user can specify the value of timeout
41            according to his end application
42        (+) Start the CAN peripheral reception and wait the end of this operation
43            using HAL_CAN_Receive(), at this stage user can specify the value of timeout
44            according to his end application
45 
46      *** Interrupt mode IO operation ***
47      ===================================
48      [..]
49        (+) Start the CAN peripheral transmission using HAL_CAN_Transmit_IT()
50        (+) Start the CAN peripheral reception using HAL_CAN_Receive_IT()
51        (+) Use HAL_CAN_IRQHandler() called under the used CAN Interrupt subroutine
52        (+) At CAN end of transmission HAL_CAN_TxCpltCallback() function is executed and user can
53             add his own code by customization of function pointer HAL_CAN_TxCpltCallback
54        (+) In case of CAN Error, HAL_CAN_ErrorCallback() function is executed and user can
55             add his own code by customization of function pointer HAL_CAN_ErrorCallback
56 
57      *** CAN HAL driver macros list ***
58      =============================================
59      [..]
60        Below the list of most used macros in CAN HAL driver.
61 
62       (+) __HAL_CAN_ENABLE_IT: Enable the specified CAN interrupts
63       (+) __HAL_CAN_DISABLE_IT: Disable the specified CAN interrupts
64       (+) __HAL_CAN_GET_IT_SOURCE: Check if the specified CAN interrupt source is enabled or disabled
65       (+) __HAL_CAN_CLEAR_FLAG: Clear the CAN's pending flags
66       (+) __HAL_CAN_GET_FLAG: Get the selected CAN's flag status
67 
68      [..]
69       (@) You can refer to the CAN HAL driver header file for more useful macros
70 
71   @endverbatim
72 
73   ******************************************************************************
74   * @attention
75   *
76   * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
77   *
78   * Redistribution and use in source and binary forms, with or without modification,
79   * are permitted provided that the following conditions are met:
80   *   1. Redistributions of source code must retain the above copyright notice,
81   *      this list of conditions and the following disclaimer.
82   *   2. Redistributions in binary form must reproduce the above copyright notice,
83   *      this list of conditions and the following disclaimer in the documentation
84   *      and/or other materials provided with the distribution.
85   *   3. Neither the name of STMicroelectronics nor the names of its contributors
86   *      may be used to endorse or promote products derived from this software
87   *      without specific prior written permission.
88   *
89   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
90   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
91   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
92   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
93   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
94   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
95   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
96   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
97   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
98   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
99   *
100   ******************************************************************************
101   */
102 
103 /* Includes ------------------------------------------------------------------*/
104 #include "stm32f7xx_hal.h"
105 
106 /** @addtogroup STM32F7xx_HAL_Driver
107   * @{
108   */
109 
110 /** @defgroup CAN CAN
111   * @brief CAN driver modules
112   * @{
113   */
114 
115 #ifdef HAL_CAN_MODULE_ENABLED
116 
117 
118 /* Private typedef -----------------------------------------------------------*/
119 /* Private define ------------------------------------------------------------*/
120 /** @addtogroup CAN_Private_Constants
121   * @{
122   */
123 #define CAN_TIMEOUT_VALUE  10
124 /**
125   * @}
126   */
127 /* Private macro -------------------------------------------------------------*/
128 /* Private variables ---------------------------------------------------------*/
129 /* Private function prototypes -----------------------------------------------*/
130 /** @addtogroup CAN_Private_Functions
131   * @{
132   */
133 static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber);
134 static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan);
135 /**
136   * @}
137   */
138 
139 /* Exported functions --------------------------------------------------------*/
140 /** @defgroup CAN_Exported_Functions CAN Exported Functions
141   * @{
142   */
143 
144 /** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions
145  *  @brief    Initialization and Configuration functions
146  *
147 @verbatim
148   ==============================================================================
149               ##### Initialization and de-initialization functions #####
150   ==============================================================================
151     [..]  This section provides functions allowing to:
152       (+) Initialize and configure the CAN.
153       (+) De-initialize the CAN.
154 
155 @endverbatim
156   * @{
157   */
158 
159 /**
160   * @brief  Initializes the CAN peripheral according to the specified
161   *         parameters in the CAN_InitStruct.
162   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
163   *         the configuration information for the specified CAN.
164   * @retval HAL status
165   */
HAL_CAN_Init(CAN_HandleTypeDef * hcan)166 HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
167 {
168     uint32_t InitStatus = 3;
169     uint32_t tickstart = 0;
170 
171     /* Check CAN handle */
172     if (hcan == NULL) {
173         return HAL_ERROR;
174     }
175 
176     /* Check the parameters */
177     assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
178     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TTCM));
179     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ABOM));
180     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AWUM));
181     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.NART));
182     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.RFLM));
183     assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TXFP));
184     assert_param(IS_CAN_MODE(hcan->Init.Mode));
185     assert_param(IS_CAN_SJW(hcan->Init.SJW));
186     assert_param(IS_CAN_BS1(hcan->Init.BS1));
187     assert_param(IS_CAN_BS2(hcan->Init.BS2));
188     assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler));
189 
190 
191     if (hcan->State == HAL_CAN_STATE_RESET) {
192         /* Allocate lock resource and initialize it */
193         hcan->Lock = HAL_UNLOCKED;
194         /* Init the low level hardware */
195         HAL_CAN_MspInit(hcan);
196     }
197 
198     /* Initialize the CAN state*/
199     hcan->State = HAL_CAN_STATE_BUSY;
200 
201     /* Exit from sleep mode */
202     hcan->Instance->MCR &= (~(uint32_t)CAN_MCR_SLEEP);
203 
204     /* Request initialisation */
205     hcan->Instance->MCR |= CAN_MCR_INRQ ;
206 
207     /* Get tick */
208     tickstart = HAL_GetTick();
209 
210     /* Wait the acknowledge */
211     while ((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
212         if ((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE) {
213             hcan->State= HAL_CAN_STATE_TIMEOUT;
214             /* Process unlocked */
215             __HAL_UNLOCK(hcan);
216             return HAL_TIMEOUT;
217         }
218     }
219 
220     /* Check acknowledge */
221     if ((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) {
222         InitStatus = CAN_INITSTATUS_FAILED;
223     } else {
224         /* Set the time triggered communication mode */
225         if (hcan->Init.TTCM == ENABLE) {
226             hcan->Instance->MCR |= CAN_MCR_TTCM;
227         } else {
228             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TTCM;
229         }
230 
231         /* Set the automatic bus-off management */
232         if (hcan->Init.ABOM == ENABLE) {
233             hcan->Instance->MCR |= CAN_MCR_ABOM;
234         } else {
235             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_ABOM;
236         }
237 
238         /* Set the automatic wake-up mode */
239         if (hcan->Init.AWUM == ENABLE) {
240             hcan->Instance->MCR |= CAN_MCR_AWUM;
241         } else {
242             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_AWUM;
243         }
244 
245         /* Set the no automatic retransmission */
246         if (hcan->Init.NART == ENABLE) {
247             hcan->Instance->MCR |= CAN_MCR_NART;
248         } else {
249             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_NART;
250         }
251 
252         /* Set the receive FIFO locked mode */
253         if (hcan->Init.RFLM == ENABLE) {
254             hcan->Instance->MCR |= CAN_MCR_RFLM;
255         } else {
256             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_RFLM;
257         }
258 
259         /* Set the transmit FIFO priority */
260         if (hcan->Init.TXFP == ENABLE) {
261             hcan->Instance->MCR |= CAN_MCR_TXFP;
262         } else {
263             hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TXFP;
264         }
265 
266         /* Set the bit timing register */
267         hcan->Instance->BTR = (uint32_t)((uint32_t)hcan->Init.Mode) | \
268                               ((uint32_t)hcan->Init.SJW) | \
269                               ((uint32_t)hcan->Init.BS1) | \
270                               ((uint32_t)hcan->Init.BS2) | \
271                               ((uint32_t)hcan->Init.Prescaler - 1);
272 
273         /* Request leave initialisation */
274         hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_INRQ;
275 
276         /* Get tick */
277         tickstart = HAL_GetTick();
278 
279         /* Wait the acknowledge */
280         while ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
281             if ((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE) {
282                 hcan->State= HAL_CAN_STATE_TIMEOUT;
283                 /* Process unlocked */
284                 __HAL_UNLOCK(hcan);
285                 return HAL_TIMEOUT;
286             }
287         }
288 
289         /* Check acknowledged */
290         if ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) {
291             InitStatus = CAN_INITSTATUS_FAILED;
292         } else {
293             InitStatus = CAN_INITSTATUS_SUCCESS;
294         }
295     }
296 
297     if (InitStatus == CAN_INITSTATUS_SUCCESS) {
298         /* Set CAN error code to none */
299         hcan->ErrorCode = HAL_CAN_ERROR_NONE;
300 
301         /* Initialize the CAN state */
302         hcan->State = HAL_CAN_STATE_READY;
303 
304         /* Return function status */
305         return HAL_OK;
306     } else {
307         /* Initialize the CAN state */
308         hcan->State = HAL_CAN_STATE_ERROR;
309 
310         /* Return function status */
311         return HAL_ERROR;
312     }
313 }
314 
315 /**
316   * @brief  Configures the CAN reception filter according to the specified
317   *         parameters in the CAN_FilterInitStruct.
318   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
319   *         the configuration information for the specified CAN.
320   * @param  sFilterConfig: pointer to a CAN_FilterConfTypeDef structure that
321   *         contains the filter configuration information.
322   * @retval None
323   */
HAL_CAN_ConfigFilter(CAN_HandleTypeDef * hcan,CAN_FilterConfTypeDef * sFilterConfig)324 HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)
325 {
326     uint32_t filternbrbitpos = 0;
327 
328     /* Check the parameters */
329     assert_param(IS_CAN_FILTER_NUMBER(sFilterConfig->FilterNumber));
330     assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode));
331     assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale));
332     assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment));
333     assert_param(IS_FUNCTIONAL_STATE(sFilterConfig->FilterActivation));
334     assert_param(IS_CAN_BANKNUMBER(sFilterConfig->BankNumber));
335 
336     filternbrbitpos = ((uint32_t)1) << sFilterConfig->FilterNumber;
337 
338     /* Initialisation mode for the filter */
339     CAN1->FMR |= (uint32_t)CAN_FMR_FINIT;
340 
341     /* Select the start slave bank */
342     CAN1->FMR &= ~((uint32_t)CAN_FMR_CAN2SB);
343     CAN1->FMR |= (uint32_t)(sFilterConfig->BankNumber << 8);
344 
345     /* Filter Deactivation */
346     CAN1->FA1R &= ~(uint32_t)filternbrbitpos;
347 
348     /* Filter Scale */
349     if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT) {
350         /* 16-bit scale for the filter */
351         CAN1->FS1R &= ~(uint32_t)filternbrbitpos;
352 
353         /* First 16-bit identifier and First 16-bit mask */
354         /* Or First 16-bit identifier and Second 16-bit identifier */
355         CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
356             ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16) |
357             (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);
358 
359         /* Second 16-bit identifier and Second 16-bit mask */
360         /* Or Third 16-bit identifier and Fourth 16-bit identifier */
361         CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
362             ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16) |
363             (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh);
364     }
365 
366     if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT) {
367         /* 32-bit scale for the filter */
368         CAN1->FS1R |= filternbrbitpos;
369         /* 32-bit identifier or First 32-bit identifier */
370         CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
371             ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) << 16) |
372             (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);
373         /* 32-bit mask or Second 32-bit identifier */
374         CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
375             ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16) |
376             (0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow);
377     }
378 
379     /* Filter Mode */
380     if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK) {
381         /*Id/Mask mode for the filter*/
382         CAN1->FM1R &= ~(uint32_t)filternbrbitpos;
383     } else { /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
384         /*Identifier list mode for the filter*/
385         CAN1->FM1R |= (uint32_t)filternbrbitpos;
386     }
387 
388     /* Filter FIFO assignment */
389     if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0) {
390         /* FIFO 0 assignation for the filter */
391         CAN1->FFA1R &= ~(uint32_t)filternbrbitpos;
392     }
393 
394     if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO1) {
395         /* FIFO 1 assignation for the filter */
396         CAN1->FFA1R |= (uint32_t)filternbrbitpos;
397     }
398 
399     /* Filter activation */
400     if (sFilterConfig->FilterActivation == ENABLE) {
401         CAN1->FA1R |= filternbrbitpos;
402     }
403 
404     /* Leave the initialisation mode for the filter */
405     CAN1->FMR &= ~((uint32_t)CAN_FMR_FINIT);
406 
407     /* Return function status */
408     return HAL_OK;
409 }
410 
411 /**
412   * @brief  Deinitializes the CANx peripheral registers to their default reset values.
413   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
414   *         the configuration information for the specified CAN.
415   * @retval HAL status
416   */
HAL_CAN_DeInit(CAN_HandleTypeDef * hcan)417 HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan)
418 {
419     /* Check CAN handle */
420     if (hcan == NULL) {
421         return HAL_ERROR;
422     }
423 
424     /* Check the parameters */
425     assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
426 
427     /* Change CAN state */
428     hcan->State = HAL_CAN_STATE_BUSY;
429 
430     /* DeInit the low level hardware */
431     HAL_CAN_MspDeInit(hcan);
432 
433     /* Change CAN state */
434     hcan->State = HAL_CAN_STATE_RESET;
435 
436     /* Release Lock */
437     __HAL_UNLOCK(hcan);
438 
439     /* Return function status */
440     return HAL_OK;
441 }
442 
443 /**
444   * @brief  Initializes the CAN MSP.
445   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
446   *         the configuration information for the specified CAN.
447   * @retval None
448   */
HAL_CAN_MspInit(CAN_HandleTypeDef * hcan)449 __weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
450 {
451     /* NOTE : This function Should not be modified, when the callback is needed,
452               the HAL_CAN_MspInit could be implemented in the user file
453      */
454 }
455 
456 /**
457   * @brief  DeInitializes the CAN MSP.
458   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
459   *         the configuration information for the specified CAN.
460   * @retval None
461   */
HAL_CAN_MspDeInit(CAN_HandleTypeDef * hcan)462 __weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
463 {
464     /* NOTE : This function Should not be modified, when the callback is needed,
465               the HAL_CAN_MspDeInit could be implemented in the user file
466      */
467 }
468 
469 /**
470   * @}
471   */
472 
473 /** @defgroup CAN_Exported_Functions_Group2 IO operation functions
474  *  @brief    IO operation functions
475  *
476 @verbatim
477   ==============================================================================
478                       ##### IO operation functions #####
479   ==============================================================================
480     [..]  This section provides functions allowing to:
481       (+) Transmit a CAN frame message.
482       (+) Receive a CAN frame message.
483       (+) Enter CAN peripheral in sleep mode.
484       (+) Wake up the CAN peripheral from sleep mode.
485 
486 @endverbatim
487   * @{
488   */
489 
490 /**
491   * @brief  Initiates and transmits a CAN frame message.
492   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
493   *         the configuration information for the specified CAN.
494   * @param  Timeout: Specify Timeout value
495   * @retval HAL status
496   */
HAL_CAN_Transmit(CAN_HandleTypeDef * hcan,uint32_t Timeout)497 HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
498 {
499     uint32_t  transmitmailbox = 5;
500     uint32_t tickstart = 0;
501 
502     /* Check the parameters */
503     assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
504     assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
505     assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
506 
507     /* Process locked */
508     __HAL_LOCK(hcan);
509 
510     if (hcan->State == HAL_CAN_STATE_BUSY_RX) {
511         /* Change CAN state */
512         hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
513     } else {
514         /* Change CAN state */
515         hcan->State = HAL_CAN_STATE_BUSY_TX;
516     }
517 
518     /* Select one empty transmit mailbox */
519     if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) {
520         transmitmailbox = 0;
521     } else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) {
522         transmitmailbox = 1;
523     } else if ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2) {
524         transmitmailbox = 2;
525     } else {
526         transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
527     }
528 
529     if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX) {
530         /* Set up the Id */
531         hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
532         if (hcan->pTxMsg->IDE == CAN_ID_STD) {
533             assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
534             hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \
535                     hcan->pTxMsg->RTR);
536         } else {
537             assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
538             hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \
539                     hcan->pTxMsg->IDE | \
540                     hcan->pTxMsg->RTR);
541         }
542 
543         /* Set up the DLC */
544         hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
545         hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
546         hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
547 
548         /* Set up the data field */
549         hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) |
550                 ((uint32_t)hcan->pTxMsg->Data[2] << 16) |
551                 ((uint32_t)hcan->pTxMsg->Data[1] << 8) |
552                 ((uint32_t)hcan->pTxMsg->Data[0]));
553         hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) |
554                 ((uint32_t)hcan->pTxMsg->Data[6] << 16) |
555                 ((uint32_t)hcan->pTxMsg->Data[5] << 8) |
556                 ((uint32_t)hcan->pTxMsg->Data[4]));
557         /* Request transmission */
558         hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
559 
560         /* Get tick */
561         tickstart = HAL_GetTick();
562 
563         /* Check End of transmission flag */
564         while (!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox))) {
565             /* Check for the Timeout */
566             if (Timeout != HAL_MAX_DELAY) {
567                 if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
568                     hcan->State = HAL_CAN_STATE_TIMEOUT;
569                     /* Process unlocked */
570                     __HAL_UNLOCK(hcan);
571                     return HAL_TIMEOUT;
572                 }
573             }
574         }
575         if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) {
576             /* Change CAN state */
577             hcan->State = HAL_CAN_STATE_BUSY_RX;
578 
579             /* Process unlocked */
580             __HAL_UNLOCK(hcan);
581         } else {
582             /* Change CAN state */
583             hcan->State = HAL_CAN_STATE_READY;
584 
585             /* Process unlocked */
586             __HAL_UNLOCK(hcan);
587         }
588 
589         /* Return function status */
590         return HAL_OK;
591     } else {
592         /* Change CAN state */
593         hcan->State = HAL_CAN_STATE_ERROR;
594 
595         /* Process unlocked */
596         __HAL_UNLOCK(hcan);
597 
598         /* Return function status */
599         return HAL_ERROR;
600     }
601 }
602 
603 /**
604   * @brief  Initiates and transmits a CAN frame message.
605   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
606   *         the configuration information for the specified CAN.
607   * @retval HAL status
608   */
HAL_CAN_Transmit_IT(CAN_HandleTypeDef * hcan)609 HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
610 {
611     uint32_t  transmitmailbox = 5;
612     uint32_t tmp = 0;
613 
614     /* Check the parameters */
615     assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
616     assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
617     assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
618 
619     tmp = hcan->State;
620     if ((tmp == HAL_CAN_STATE_READY) || (tmp == HAL_CAN_STATE_BUSY_RX)) {
621         /* Process Locked */
622         __HAL_LOCK(hcan);
623 
624         /* Select one empty transmit mailbox */
625         if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) {
626             transmitmailbox = 0;
627         } else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) {
628             transmitmailbox = 1;
629         } else if ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2) {
630             transmitmailbox = 2;
631         } else {
632             transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
633         }
634 
635         if (transmitmailbox != CAN_TXSTATUS_NOMAILBOX) {
636             /* Set up the Id */
637             hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
638             if (hcan->pTxMsg->IDE == CAN_ID_STD) {
639                 assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
640                 hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21) | \
641                         hcan->pTxMsg->RTR);
642             } else {
643                 assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
644                 hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3) | \
645                         hcan->pTxMsg->IDE | \
646                         hcan->pTxMsg->RTR);
647             }
648 
649             /* Set up the DLC */
650             hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
651             hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0;
652             hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
653 
654             /* Set up the data field */
655             hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3] << 24) |
656                     ((uint32_t)hcan->pTxMsg->Data[2] << 16) |
657                     ((uint32_t)hcan->pTxMsg->Data[1] << 8) |
658                     ((uint32_t)hcan->pTxMsg->Data[0]));
659             hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7] << 24) |
660                     ((uint32_t)hcan->pTxMsg->Data[6] << 16) |
661                     ((uint32_t)hcan->pTxMsg->Data[5] << 8) |
662                     ((uint32_t)hcan->pTxMsg->Data[4]));
663 
664             if (hcan->State == HAL_CAN_STATE_BUSY_RX) {
665                 /* Change CAN state */
666                 hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
667             } else {
668                 /* Change CAN state */
669                 hcan->State = HAL_CAN_STATE_BUSY_TX;
670             }
671 
672             /* Set CAN error code to none */
673             hcan->ErrorCode = HAL_CAN_ERROR_NONE;
674 
675             /* Process Unlocked */
676             __HAL_UNLOCK(hcan);
677 
678             /* Enable Error warning Interrupt */
679             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG);
680 
681             /* Enable Error passive Interrupt */
682             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV);
683 
684             /* Enable Bus-off Interrupt */
685             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF);
686 
687             /* Enable Last error code Interrupt */
688             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC);
689 
690             /* Enable Error Interrupt */
691             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR);
692 
693             /* Enable Transmit mailbox empty Interrupt */
694             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_TME);
695 
696             /* Request transmission */
697             hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
698         }
699     } else {
700         return HAL_BUSY;
701     }
702 
703     return HAL_OK;
704 }
705 
706 /**
707   * @brief  Receives a correct CAN frame.
708   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
709   *         the configuration information for the specified CAN.
710   * @param  FIFONumber: FIFO Number value
711   * @param  Timeout: Specify Timeout value
712   * @retval HAL status
713   */
HAL_CAN_Receive(CAN_HandleTypeDef * hcan,uint8_t FIFONumber,uint32_t Timeout)714 HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout)
715 {
716     uint32_t tickstart = 0;
717 
718     /* Check the parameters */
719     assert_param(IS_CAN_FIFO(FIFONumber));
720 
721     /* Process locked */
722     __HAL_LOCK(hcan);
723 
724     if (hcan->State == HAL_CAN_STATE_BUSY_TX) {
725         /* Change CAN state */
726         hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
727     } else {
728         /* Change CAN state */
729         hcan->State = HAL_CAN_STATE_BUSY_RX;
730     }
731 
732     /* Get tick */
733     tickstart = HAL_GetTick();
734 
735     /* Check pending message */
736     while (__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0) {
737         /* Check for the Timeout */
738         if (Timeout != HAL_MAX_DELAY) {
739             if ((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout)) {
740                 hcan->State = HAL_CAN_STATE_TIMEOUT;
741                 /* Process unlocked */
742                 __HAL_UNLOCK(hcan);
743                 return HAL_TIMEOUT;
744             }
745         }
746     }
747 
748     /* Get the Id */
749     hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
750     if (hcan->pRxMsg->IDE == CAN_ID_STD) {
751         hcan->pRxMsg->StdId = (uint32_t)0x000007FF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21);
752     } else {
753         hcan->pRxMsg->ExtId = (uint32_t)0x1FFFFFFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3);
754     }
755 
756     hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
757     /* Get the DLC */
758     hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
759     /* Get the FMI */
760     hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8);
761     /* Get the data field */
762     hcan->pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
763     hcan->pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8);
764     hcan->pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16);
765     hcan->pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24);
766     hcan->pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
767     hcan->pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8);
768     hcan->pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16);
769     hcan->pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24);
770 
771     /* Release the FIFO */
772     if (FIFONumber == CAN_FIFO0) {
773         /* Release FIFO0 */
774         __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
775     } else { /* FIFONumber == CAN_FIFO1 */
776         /* Release FIFO1 */
777         __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
778     }
779 
780     if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) {
781         /* Change CAN state */
782         hcan->State = HAL_CAN_STATE_BUSY_TX;
783 
784         /* Process unlocked */
785         __HAL_UNLOCK(hcan);
786     } else {
787         /* Change CAN state */
788         hcan->State = HAL_CAN_STATE_READY;
789 
790         /* Process unlocked */
791         __HAL_UNLOCK(hcan);
792     }
793 
794     /* Return function status */
795     return HAL_OK;
796 }
797 
798 /**
799   * @brief  Receives a correct CAN frame.
800   * @param  hcan:       Pointer to a CAN_HandleTypeDef structure that contains
801   *         the configuration information for the specified CAN.
802   * @param  FIFONumber: Specify the FIFO number
803   * @retval HAL status
804   */
HAL_CAN_Receive_IT(CAN_HandleTypeDef * hcan,uint8_t FIFONumber)805 HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
806 {
807     uint32_t tmp = 0;
808 
809     /* Check the parameters */
810     assert_param(IS_CAN_FIFO(FIFONumber));
811 
812     tmp = hcan->State;
813     if ((tmp == HAL_CAN_STATE_READY) || (tmp == HAL_CAN_STATE_BUSY_TX)) {
814         /* Process locked */
815         __HAL_LOCK(hcan);
816 
817         if (hcan->State == HAL_CAN_STATE_BUSY_TX) {
818             /* Change CAN state */
819             hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
820         } else {
821             /* Change CAN state */
822             hcan->State = HAL_CAN_STATE_BUSY_RX;
823         }
824 
825         /* Set CAN error code to none */
826         hcan->ErrorCode = HAL_CAN_ERROR_NONE;
827 
828         /* Enable Error warning Interrupt */
829         __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG);
830 
831         /* Enable Error passive Interrupt */
832         __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV);
833 
834         /* Enable Bus-off Interrupt */
835         __HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF);
836 
837         /* Enable Last error code Interrupt */
838         __HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC);
839 
840         /* Enable Error Interrupt */
841         __HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR);
842 
843         /* Process unlocked */
844         __HAL_UNLOCK(hcan);
845 
846         if (FIFONumber == CAN_FIFO0) {
847             /* Enable FIFO 0 message pending Interrupt */
848             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
849         } else {
850             /* Enable FIFO 1 message pending Interrupt */
851             __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP1);
852         }
853 
854     } else {
855         return HAL_BUSY;
856     }
857 
858     /* Return function status */
859     return HAL_OK;
860 }
861 
862 /**
863   * @brief  Enters the Sleep (low power) mode.
864   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
865   *         the configuration information for the specified CAN.
866   * @retval HAL status.
867   */
HAL_CAN_Sleep(CAN_HandleTypeDef * hcan)868 HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef* hcan)
869 {
870     uint32_t tickstart = 0;
871 
872     /* Process locked */
873     __HAL_LOCK(hcan);
874 
875     /* Change CAN state */
876     hcan->State = HAL_CAN_STATE_BUSY;
877 
878     /* Request Sleep mode */
879     hcan->Instance->MCR = (((hcan->Instance->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
880 
881     /* Sleep mode status */
882     if ((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK) {
883         /* Process unlocked */
884         __HAL_UNLOCK(hcan);
885 
886         /* Return function status */
887         return HAL_ERROR;
888     }
889 
890     /* Get tick */
891     tickstart = HAL_GetTick();
892 
893     /* Wait the acknowledge */
894     while ((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK) {
895         if ((HAL_GetTick()  - tickstart) > CAN_TIMEOUT_VALUE) {
896             hcan->State = HAL_CAN_STATE_TIMEOUT;
897             /* Process unlocked */
898             __HAL_UNLOCK(hcan);
899             return HAL_TIMEOUT;
900         }
901     }
902 
903     /* Change CAN state */
904     hcan->State = HAL_CAN_STATE_READY;
905 
906     /* Process unlocked */
907     __HAL_UNLOCK(hcan);
908 
909     /* Return function status */
910     return HAL_OK;
911 }
912 
913 /**
914   * @brief  Wakes up the CAN peripheral from sleep mode, after that the CAN peripheral
915   *         is in the normal mode.
916   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
917   *         the configuration information for the specified CAN.
918   * @retval HAL status.
919   */
HAL_CAN_WakeUp(CAN_HandleTypeDef * hcan)920 HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan)
921 {
922     uint32_t tickstart = 0;
923 
924     /* Process locked */
925     __HAL_LOCK(hcan);
926 
927     /* Change CAN state */
928     hcan->State = HAL_CAN_STATE_BUSY;
929 
930     /* Wake up request */
931     hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_SLEEP;
932 
933     /* Get tick */
934     tickstart = HAL_GetTick();
935 
936     /* Sleep mode status */
937     while ((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK) {
938         if ((HAL_GetTick()  - tickstart) > CAN_TIMEOUT_VALUE) {
939             hcan->State= HAL_CAN_STATE_TIMEOUT;
940             /* Process unlocked */
941             __HAL_UNLOCK(hcan);
942             return HAL_TIMEOUT;
943         }
944     }
945     if ((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK) {
946         /* Process unlocked */
947         __HAL_UNLOCK(hcan);
948 
949         /* Return function status */
950         return HAL_ERROR;
951     }
952 
953     /* Change CAN state */
954     hcan->State = HAL_CAN_STATE_READY;
955 
956     /* Process unlocked */
957     __HAL_UNLOCK(hcan);
958 
959     /* Return function status */
960     return HAL_OK;
961 }
962 
963 /**
964   * @brief  Handles CAN interrupt request
965   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
966   *         the configuration information for the specified CAN.
967   * @retval None
968   */
HAL_CAN_IRQHandler(CAN_HandleTypeDef * hcan)969 void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
970 {
971     uint32_t tmp1 = 0, tmp2 = 0, tmp3 = 0;
972 
973     /* Check End of transmission flag */
974     if (__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME)) {
975         tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
976         tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
977         tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
978         if (tmp1 || tmp2 || tmp3) {
979             /* Call transmit function */
980             CAN_Transmit_IT(hcan);
981         }
982     }
983 
984     tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0);
985     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0);
986     /* Check End of reception flag for FIFO0 */
987     if ((tmp1 != 0) && tmp2) {
988         /* Call receive function */
989         CAN_Receive_IT(hcan, CAN_FIFO0);
990     }
991 
992     tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1);
993     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1);
994     /* Check End of reception flag for FIFO1 */
995     if ((tmp1 != 0) && tmp2) {
996         /* Call receive function */
997         CAN_Receive_IT(hcan, CAN_FIFO1);
998     }
999 
1000     tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG);
1001     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG);
1002     tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1003     /* Check Error Warning Flag */
1004     if (tmp1 && tmp2 && tmp3) {
1005         /* Set CAN error code to EWG error */
1006         hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
1007         /* Clear Error Warning Flag */
1008         __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_EWG);
1009     }
1010 
1011     tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV);
1012     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV);
1013     tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1014     /* Check Error Passive Flag */
1015     if (tmp1 && tmp2 && tmp3) {
1016         /* Set CAN error code to EPV error */
1017         hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
1018         /* Clear Error Passive Flag */
1019         __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_EPV);
1020     }
1021 
1022     tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF);
1023     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF);
1024     tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1025     /* Check Bus-Off Flag */
1026     if (tmp1 && tmp2 && tmp3) {
1027         /* Set CAN error code to BOF error */
1028         hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
1029         /* Clear Bus-Off Flag */
1030         __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_BOF);
1031     }
1032 
1033     tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC);
1034     tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC);
1035     tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1036     /* Check Last error code Flag */
1037     if ((!tmp1) && tmp2 && tmp3) {
1038         tmp1 = (hcan->Instance->ESR) & CAN_ESR_LEC;
1039         switch (tmp1) {
1040             case (CAN_ESR_LEC_0):
1041                 /* Set CAN error code to STF error */
1042                 hcan->ErrorCode |= HAL_CAN_ERROR_STF;
1043                 break;
1044             case (CAN_ESR_LEC_1):
1045                 /* Set CAN error code to FOR error */
1046                 hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
1047                 break;
1048             case (CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
1049                 /* Set CAN error code to ACK error */
1050                 hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
1051                 break;
1052             case (CAN_ESR_LEC_2):
1053                 /* Set CAN error code to BR error */
1054                 hcan->ErrorCode |= HAL_CAN_ERROR_BR;
1055                 break;
1056             case (CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
1057                 /* Set CAN error code to BD error */
1058                 hcan->ErrorCode |= HAL_CAN_ERROR_BD;
1059                 break;
1060             case (CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
1061                 /* Set CAN error code to CRC error */
1062                 hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
1063                 break;
1064             default:
1065                 break;
1066         }
1067 
1068         /* Clear Last error code Flag */
1069         hcan->Instance->ESR &= ~(CAN_ESR_LEC);
1070     }
1071 
1072     /* Call the Error call Back in case of Errors */
1073     if (hcan->ErrorCode != HAL_CAN_ERROR_NONE) {
1074         /* Set the CAN state ready to be able to start again the process */
1075         hcan->State = HAL_CAN_STATE_READY;
1076         /* Call Error callback function */
1077         HAL_CAN_ErrorCallback(hcan);
1078     }
1079 }
1080 
1081 /**
1082   * @brief  Transmission  complete callback in non blocking mode
1083   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1084   *         the configuration information for the specified CAN.
1085   * @retval None
1086   */
HAL_CAN_TxCpltCallback(CAN_HandleTypeDef * hcan)1087 __weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
1088 {
1089     /* NOTE : This function Should not be modified, when the callback is needed,
1090               the HAL_CAN_TxCpltCallback could be implemented in the user file
1091      */
1092 }
1093 
1094 /**
1095   * @brief  Transmission  complete callback in non blocking mode
1096   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1097   *         the configuration information for the specified CAN.
1098   * @retval None
1099   */
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef * hcan)1100 __weak void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
1101 {
1102     /* NOTE : This function Should not be modified, when the callback is needed,
1103               the HAL_CAN_RxCpltCallback could be implemented in the user file
1104      */
1105 }
1106 
1107 /**
1108   * @brief  Error CAN callback.
1109   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1110   *         the configuration information for the specified CAN.
1111   * @retval None
1112   */
HAL_CAN_ErrorCallback(CAN_HandleTypeDef * hcan)1113 __weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
1114 {
1115     /* NOTE : This function Should not be modified, when the callback is needed,
1116               the HAL_CAN_ErrorCallback could be implemented in the user file
1117      */
1118 }
1119 
1120 /**
1121   * @}
1122   */
1123 
1124 /** @defgroup CAN_Exported_Functions_Group3 Peripheral State and Error functions
1125  *  @brief   CAN Peripheral State functions
1126  *
1127 @verbatim
1128   ==============================================================================
1129             ##### Peripheral State and Error functions #####
1130   ==============================================================================
1131     [..]
1132     This subsection provides functions allowing to :
1133       (+) Check the CAN state.
1134       (+) Check CAN Errors detected during interrupt process
1135 
1136 @endverbatim
1137   * @{
1138   */
1139 
1140 /**
1141   * @brief  return the CAN state
1142   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1143   *         the configuration information for the specified CAN.
1144   * @retval HAL state
1145   */
HAL_CAN_GetState(CAN_HandleTypeDef * hcan)1146 HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan)
1147 {
1148     /* Return CAN state */
1149     return hcan->State;
1150 }
1151 
1152 /**
1153   * @brief  Return the CAN error code
1154   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1155   *         the configuration information for the specified CAN.
1156   * @retval CAN Error Code
1157   */
HAL_CAN_GetError(CAN_HandleTypeDef * hcan)1158 uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan)
1159 {
1160     return hcan->ErrorCode;
1161 }
1162 
1163 /**
1164   * @}
1165   */
1166 /**
1167   * @brief  Initiates and transmits a CAN frame message.
1168   * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
1169   *         the configuration information for the specified CAN.
1170   * @retval HAL status
1171   */
CAN_Transmit_IT(CAN_HandleTypeDef * hcan)1172 static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
1173 {
1174     /* Disable Transmit mailbox empty Interrupt */
1175     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME);
1176 
1177     if (hcan->State == HAL_CAN_STATE_BUSY_TX) {
1178         /* Disable Error warning Interrupt */
1179         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG);
1180 
1181         /* Disable Error passive Interrupt */
1182         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EPV);
1183 
1184         /* Disable Bus-off Interrupt */
1185         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_BOF);
1186 
1187         /* Disable Last error code Interrupt */
1188         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_LEC);
1189 
1190         /* Disable Error Interrupt */
1191         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_ERR);
1192     }
1193 
1194     if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) {
1195         /* Change CAN state */
1196         hcan->State = HAL_CAN_STATE_BUSY_RX;
1197     } else {
1198         /* Change CAN state */
1199         hcan->State = HAL_CAN_STATE_READY;
1200     }
1201 
1202     /* Transmission complete callback */
1203     HAL_CAN_TxCpltCallback(hcan);
1204 
1205     return HAL_OK;
1206 }
1207 
1208 /**
1209   * @brief  Receives a correct CAN frame.
1210   * @param  hcan:       Pointer to a CAN_HandleTypeDef structure that contains
1211   *         the configuration information for the specified CAN.
1212   * @param  FIFONumber: Specify the FIFO number
1213   * @retval HAL status
1214   * @retval None
1215   */
CAN_Receive_IT(CAN_HandleTypeDef * hcan,uint8_t FIFONumber)1216 static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
1217 {
1218     /* Get the Id */
1219     hcan->pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
1220     if (hcan->pRxMsg->IDE == CAN_ID_STD) {
1221         hcan->pRxMsg->StdId = (uint32_t)0x000007FF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21);
1222     } else {
1223         hcan->pRxMsg->ExtId = (uint32_t)0x1FFFFFFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3);
1224     }
1225 
1226     hcan->pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
1227     /* Get the DLC */
1228     hcan->pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
1229     /* Get the FMI */
1230     hcan->pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8);
1231     /* Get the data field */
1232     hcan->pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
1233     hcan->pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8);
1234     hcan->pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16);
1235     hcan->pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24);
1236     hcan->pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
1237     hcan->pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8);
1238     hcan->pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16);
1239     hcan->pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24);
1240     /* Release the FIFO */
1241     /* Release FIFO0 */
1242     if (FIFONumber == CAN_FIFO0) {
1243         __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
1244 
1245         /* Disable FIFO 0 message pending Interrupt */
1246         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP0);
1247     }
1248     /* Release FIFO1 */
1249     else { /* FIFONumber == CAN_FIFO1 */
1250         __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
1251 
1252         /* Disable FIFO 1 message pending Interrupt */
1253         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FMP1);
1254     }
1255 
1256     if (hcan->State == HAL_CAN_STATE_BUSY_RX) {
1257         /* Disable Error warning Interrupt */
1258         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG);
1259 
1260         /* Disable Error passive Interrupt */
1261         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EPV);
1262 
1263         /* Disable Bus-off Interrupt */
1264         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_BOF);
1265 
1266         /* Disable Last error code Interrupt */
1267         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_LEC);
1268 
1269         /* Disable Error Interrupt */
1270         __HAL_CAN_DISABLE_IT(hcan, CAN_IT_ERR);
1271     }
1272 
1273     if (hcan->State == HAL_CAN_STATE_BUSY_TX_RX) {
1274         /* Disable CAN state */
1275         hcan->State = HAL_CAN_STATE_BUSY_TX;
1276     } else {
1277         /* Change CAN state */
1278         hcan->State = HAL_CAN_STATE_READY;
1279     }
1280 
1281     /* Receive complete callback */
1282     HAL_CAN_RxCpltCallback(hcan);
1283 
1284     /* Return function status */
1285     return HAL_OK;
1286 }
1287 
1288 /**
1289  * @}
1290  */
1291 
1292 #endif /* HAL_CAN_MODULE_ENABLED */
1293 /**
1294   * @}
1295   */
1296 
1297 /**
1298   * @}
1299   */
1300 
1301 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1302