1 /**
2   ******************************************************************************
3   * @file    stm32f2xx_hal_can.c
4   * @author  MCD Application Team
5   * @brief   This file provides firmware functions to manage the following
6   *          functionalities of the Controller Area Network (CAN) peripheral:
7   *           + Initialization and de-initialization functions
8   *           + IO operation functions
9   *           + Peripheral Control functions
10   *           + Peripheral State and Error functions
11   *
12   @verbatim
13   ==============================================================================
14                                  ##### User NOTE #####
15   ==============================================================================
16     [..]
17       (#) This HAL CAN driver is deprecated, it contains some CAN Tx/Rx FIFO management limitations.
18           Another HAL CAN driver version has been designed with new API's, to fix these limitations.
19 
20   ==============================================================================
21                         ##### How to use this driver #####
22   ==============================================================================
23     [..]
24       (#) Enable the CAN controller interface clock using
25           __HAL_RCC_CAN1_CLK_ENABLE() for CAN1 and __HAL_RCC_CAN2_CLK_ENABLE() for CAN2
26       -@- In case you are using CAN2 only, you have to enable the CAN1 clock.
27 
28       (#) CAN pins configuration
29         (++) Enable the clock for the CAN GPIOs using the following function:
30              __HAL_RCC_GPIOx_CLK_ENABLE()
31         (++) Connect and configure the involved CAN pins to AF9 using the
32               following function HAL_GPIO_Init()
33 
34       (#) Initialize and configure the CAN using HAL_CAN_Init() function.
35 
36       (#) Transmit the desired CAN frame using HAL_CAN_Transmit() function.
37 
38       (#) Or transmit the desired CAN frame using HAL_CAN_Transmit_IT() function.
39 
40       (#) Receive a CAN frame using HAL_CAN_Receive() function.
41 
42       (#) Or receive a CAN frame using HAL_CAN_Receive_IT() function.
43 
44      *** Polling mode IO operation ***
45      =================================
46      [..]
47        (+) Start the CAN peripheral transmission and wait the end of this operation
48            using HAL_CAN_Transmit(), at this stage user can specify the value of timeout
49            according to his end application
50        (+) Start the CAN peripheral reception and wait the end of this operation
51            using HAL_CAN_Receive(), at this stage user can specify the value of timeout
52            according to his end application
53 
54      *** Interrupt mode IO operation ***
55      ===================================
56      [..]
57        (+) Start the CAN peripheral transmission using HAL_CAN_Transmit_IT()
58        (+) Start the CAN peripheral reception using HAL_CAN_Receive_IT()
59        (+) Use HAL_CAN_IRQHandler() called under the used CAN Interrupt subroutine
60        (+) At CAN end of transmission HAL_CAN_TxCpltCallback() function is executed and user can
61             add his own code by customization of function pointer HAL_CAN_TxCpltCallback
62        (+) In case of CAN Error, HAL_CAN_ErrorCallback() function is executed and user can
63             add his own code by customization of function pointer HAL_CAN_ErrorCallback
64 
65      *** CAN HAL driver macros list ***
66      =============================================
67      [..]
68        Below the list of most used macros in CAN HAL driver.
69 
70       (+) __HAL_CAN_ENABLE_IT: Enable the specified CAN interrupts
71       (+) __HAL_CAN_DISABLE_IT: Disable the specified CAN interrupts
72       (+) __HAL_CAN_GET_IT_SOURCE: Check if the specified CAN interrupt source is enabled or disabled
73       (+) __HAL_CAN_CLEAR_FLAG: Clear the CAN's pending flags
74       (+) __HAL_CAN_GET_FLAG: Get the selected CAN's flag status
75 
76      [..]
77       (@) You can refer to the CAN Legacy HAL driver header file for more useful macros
78 
79   @endverbatim
80 
81   ******************************************************************************
82   * @attention
83   *
84   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
85   * All rights reserved.</center></h2>
86   *
87   * This software component is licensed by ST under BSD 3-Clause license,
88   * the "License"; You may not use this file except in compliance with the
89   * License. You may obtain a copy of the License at:
90   *                        opensource.org/licenses/BSD-3-Clause
91   *
92   ******************************************************************************
93   */
94 
95 /* Includes ------------------------------------------------------------------*/
96 #include "stm32f2xx_hal.h"
97 
98 /** @addtogroup STM32F2xx_HAL_Driver
99   * @{
100   */
101 
102 /** @defgroup CAN CAN
103   * @brief CAN driver modules
104   * @{
105   */
106 
107 #ifdef HAL_CAN_LEGACY_MODULE_ENABLED
108 #ifdef HAL_CAN_MODULE_ENABLED
109 /* Select HAL CAN module in stm32f2xx_hal_conf.h file:
110    (#) HAL_CAN_MODULE_ENABLED for new HAL CAN driver fixing FIFO limitations
111    (#) HAL_CAN_LEGACY_MODULE_ENABLED for legacy HAL CAN driver */
112 #error 'The HAL CAN driver cannot be used with its legacy, Please ensure to enable only one HAL CAN module at once in stm32f2xx_hal_conf.h file'
113 #endif /* HAL_CAN_MODULE_ENABLED */
114 
115 #warning 'Legacy HAL CAN driver is enabled! It can be used with known limitations, refer to the release notes. However it is recommended to use rather the new HAL CAN driver'
116 
117 /* Private typedef -----------------------------------------------------------*/
118 /* Private define ------------------------------------------------------------*/
119 /** @addtogroup CAN_Private_Constants
120   * @{
121   */
122 #define CAN_TIMEOUT_VALUE  10U
123 /**
124   * @}
125   */
126 /* Private macro -------------------------------------------------------------*/
127 /* Private variables ---------------------------------------------------------*/
128 /* Private function prototypes -----------------------------------------------*/
129 /** @addtogroup CAN_Private_Functions
130   * @{
131   */
132 static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber);
133 static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan);
134 /**
135   * @}
136   */
137 
138 /* Exported functions --------------------------------------------------------*/
139 /** @defgroup CAN_Exported_Functions CAN Exported Functions
140   * @{
141   */
142 
143 /** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions
144  *  @brief    Initialization and Configuration functions
145  *
146 @verbatim
147   ==============================================================================
148               ##### Initialization and de-initialization functions #####
149   ==============================================================================
150     [..]  This section provides functions allowing to:
151       (+) Initialize and configure the CAN.
152       (+) De-initialize the CAN.
153 
154 @endverbatim
155   * @{
156   */
157 
158 /**
159   * @brief  Initializes the CAN peripheral according to the specified
160   *         parameters in the CAN_InitStruct.
161   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
162   *         the configuration information for the specified CAN.
163   * @retval HAL status
164   */
HAL_CAN_Init(CAN_HandleTypeDef * hcan)165 HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef* hcan)
166 {
167   uint32_t InitStatus = CAN_INITSTATUS_FAILED;
168   uint32_t tickstart = 0U;
169 
170   /* Check CAN handle */
171   if(hcan == NULL)
172   {
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   {
193     /* Allocate lock resource and initialize it */
194     hcan->Lock = HAL_UNLOCKED;
195     /* Init the low level hardware */
196     HAL_CAN_MspInit(hcan);
197   }
198 
199   /* Initialize the CAN state*/
200   hcan->State = HAL_CAN_STATE_BUSY;
201 
202   /* Exit from sleep mode */
203   hcan->Instance->MCR &= (~(uint32_t)CAN_MCR_SLEEP);
204 
205   /* Request initialisation */
206   hcan->Instance->MCR |= CAN_MCR_INRQ ;
207 
208   /* Get tick */
209   tickstart = HAL_GetTick();
210 
211   /* Wait the acknowledge */
212   while((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
213   {
214     if((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE)
215     {
216       hcan->State= HAL_CAN_STATE_TIMEOUT;
217       /* Process unlocked */
218       __HAL_UNLOCK(hcan);
219       return HAL_TIMEOUT;
220     }
221   }
222 
223   /* Check acknowledge */
224   if ((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
225   {
226     /* Set the time triggered communication mode */
227     if (hcan->Init.TTCM == ENABLE)
228     {
229       hcan->Instance->MCR |= CAN_MCR_TTCM;
230     }
231     else
232     {
233       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TTCM;
234     }
235 
236     /* Set the automatic bus-off management */
237     if (hcan->Init.ABOM == ENABLE)
238     {
239       hcan->Instance->MCR |= CAN_MCR_ABOM;
240     }
241     else
242     {
243       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_ABOM;
244     }
245 
246     /* Set the automatic wake-up mode */
247     if (hcan->Init.AWUM == ENABLE)
248     {
249       hcan->Instance->MCR |= CAN_MCR_AWUM;
250     }
251     else
252     {
253       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_AWUM;
254     }
255 
256     /* Set the no automatic retransmission */
257     if (hcan->Init.NART == ENABLE)
258     {
259       hcan->Instance->MCR |= CAN_MCR_NART;
260     }
261     else
262     {
263       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_NART;
264     }
265 
266     /* Set the receive FIFO locked mode */
267     if (hcan->Init.RFLM == ENABLE)
268     {
269       hcan->Instance->MCR |= CAN_MCR_RFLM;
270     }
271     else
272     {
273       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_RFLM;
274     }
275 
276     /* Set the transmit FIFO priority */
277     if (hcan->Init.TXFP == ENABLE)
278     {
279       hcan->Instance->MCR |= CAN_MCR_TXFP;
280     }
281     else
282     {
283       hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_TXFP;
284     }
285 
286     /* Set the bit timing register */
287     hcan->Instance->BTR = (uint32_t)((uint32_t)hcan->Init.Mode) | \
288                 ((uint32_t)hcan->Init.SJW) | \
289                 ((uint32_t)hcan->Init.BS1) | \
290                 ((uint32_t)hcan->Init.BS2) | \
291                 ((uint32_t)hcan->Init.Prescaler - 1U);
292 
293     /* Request leave initialisation */
294     hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_INRQ;
295 
296     /* Get tick */
297     tickstart = HAL_GetTick();
298 
299     /* Wait the acknowledge */
300     while((hcan->Instance->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
301     {
302       if((HAL_GetTick() - tickstart ) > CAN_TIMEOUT_VALUE)
303       {
304         hcan->State= HAL_CAN_STATE_TIMEOUT;
305         /* Process unlocked */
306         __HAL_UNLOCK(hcan);
307         return HAL_TIMEOUT;
308       }
309     }
310 
311     /* Check acknowledged */
312     if ((hcan->Instance->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
313     {
314       InitStatus = CAN_INITSTATUS_SUCCESS;
315     }
316   }
317 
318   if(InitStatus == CAN_INITSTATUS_SUCCESS)
319   {
320     /* Set CAN error code to none */
321     hcan->ErrorCode = HAL_CAN_ERROR_NONE;
322 
323     /* Initialize the CAN state */
324     hcan->State = HAL_CAN_STATE_READY;
325 
326     /* Return function status */
327     return HAL_OK;
328   }
329   else
330   {
331     /* Initialize the CAN state */
332     hcan->State = HAL_CAN_STATE_ERROR;
333 
334     /* Return function status */
335     return HAL_ERROR;
336   }
337 }
338 
339 /**
340   * @brief  Configures the CAN reception filter according to the specified
341   *         parameters in the CAN_FilterInitStruct.
342   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
343   *         the configuration information for the specified CAN.
344   * @param  sFilterConfig pointer to a CAN_FilterConfTypeDef structure that
345   *         contains the filter configuration information.
346   * @retval None
347   */
HAL_CAN_ConfigFilter(CAN_HandleTypeDef * hcan,CAN_FilterConfTypeDef * sFilterConfig)348 HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)
349 {
350   uint32_t filternbrbitpos = 0U;
351 
352   /* Prevent unused argument(s) compilation warning */
353   UNUSED(hcan);
354 
355   /* Check the parameters */
356   assert_param(IS_CAN_FILTER_NUMBER(sFilterConfig->FilterNumber));
357   assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode));
358   assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale));
359   assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment));
360   assert_param(IS_FUNCTIONAL_STATE(sFilterConfig->FilterActivation));
361   assert_param(IS_CAN_BANKNUMBER(sFilterConfig->BankNumber));
362 
363   filternbrbitpos = 1U << sFilterConfig->FilterNumber;
364 
365   /* Initialisation mode for the filter */
366   CAN1->FMR |= (uint32_t)CAN_FMR_FINIT;
367 
368   /* Select the start slave bank */
369   CAN1->FMR &= ~((uint32_t)CAN_FMR_CAN2SB);
370   CAN1->FMR |= (uint32_t)(sFilterConfig->BankNumber << 8U);
371 
372   /* Filter Deactivation */
373   CAN1->FA1R &= ~(uint32_t)filternbrbitpos;
374 
375   /* Filter Scale */
376   if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
377   {
378     /* 16-bit scale for the filter */
379     CAN1->FS1R &= ~(uint32_t)filternbrbitpos;
380 
381     /* First 16-bit identifier and First 16-bit mask */
382     /* Or First 16-bit identifier and Second 16-bit identifier */
383     CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
384        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) |
385         (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
386 
387     /* Second 16-bit identifier and Second 16-bit mask */
388     /* Or Third 16-bit identifier and Fourth 16-bit identifier */
389     CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
390        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
391         (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh);
392   }
393 
394   if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)
395   {
396     /* 32-bit scale for the filter */
397     CAN1->FS1R |= filternbrbitpos;
398     /* 32-bit identifier or First 32-bit identifier */
399     CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR1 =
400        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |
401         (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
402     /* 32-bit mask or Second 32-bit identifier */
403     CAN1->sFilterRegister[sFilterConfig->FilterNumber].FR2 =
404        ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |
405         (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow);
406   }
407 
408   /* Filter Mode */
409   if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK)
410   {
411     /*Id/Mask mode for the filter*/
412     CAN1->FM1R &= ~(uint32_t)filternbrbitpos;
413   }
414   else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
415   {
416     /*Identifier list mode for the filter*/
417     CAN1->FM1R |= (uint32_t)filternbrbitpos;
418   }
419 
420   /* Filter FIFO assignment */
421   if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0)
422   {
423     /* FIFO 0 assignation for the filter */
424     CAN1->FFA1R &= ~(uint32_t)filternbrbitpos;
425   }
426 
427   if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO1)
428   {
429     /* FIFO 1 assignation for the filter */
430     CAN1->FFA1R |= (uint32_t)filternbrbitpos;
431   }
432 
433   /* Filter activation */
434   if (sFilterConfig->FilterActivation == ENABLE)
435   {
436     CAN1->FA1R |= filternbrbitpos;
437   }
438 
439   /* Leave the initialisation mode for the filter */
440   CAN1->FMR &= ~((uint32_t)CAN_FMR_FINIT);
441 
442   /* Return function status */
443   return HAL_OK;
444 }
445 
446 /**
447   * @brief  Deinitializes the CANx peripheral registers to their default reset values.
448   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
449   *         the configuration information for the specified CAN.
450   * @retval HAL status
451   */
HAL_CAN_DeInit(CAN_HandleTypeDef * hcan)452 HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef* hcan)
453 {
454   /* Check CAN handle */
455   if(hcan == NULL)
456   {
457      return HAL_ERROR;
458   }
459 
460   /* Check the parameters */
461   assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance));
462 
463   /* Change CAN state */
464   hcan->State = HAL_CAN_STATE_BUSY;
465 
466   /* DeInit the low level hardware */
467   HAL_CAN_MspDeInit(hcan);
468 
469   /* Change CAN state */
470   hcan->State = HAL_CAN_STATE_RESET;
471 
472   /* Release Lock */
473   __HAL_UNLOCK(hcan);
474 
475   /* Return function status */
476   return HAL_OK;
477 }
478 
479 /**
480   * @brief  Initializes the CAN MSP.
481   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
482   *         the configuration information for the specified CAN.
483   * @retval None
484   */
HAL_CAN_MspInit(CAN_HandleTypeDef * hcan)485 __weak void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
486 {
487   /* Prevent unused argument(s) compilation warning */
488   UNUSED(hcan);
489   /* NOTE : This function Should not be modified, when the callback is needed,
490             the HAL_CAN_MspInit could be implemented in the user file
491    */
492 }
493 
494 /**
495   * @brief  DeInitializes the CAN MSP.
496   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
497   *         the configuration information for the specified CAN.
498   * @retval None
499   */
HAL_CAN_MspDeInit(CAN_HandleTypeDef * hcan)500 __weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef* hcan)
501 {
502   /* Prevent unused argument(s) compilation warning */
503   UNUSED(hcan);
504   /* NOTE : This function Should not be modified, when the callback is needed,
505             the HAL_CAN_MspDeInit could be implemented in the user file
506    */
507 }
508 
509 /**
510   * @}
511   */
512 
513 /** @defgroup CAN_Exported_Functions_Group2 IO operation functions
514  *  @brief    IO operation functions
515  *
516 @verbatim
517   ==============================================================================
518                       ##### IO operation functions #####
519   ==============================================================================
520     [..]  This section provides functions allowing to:
521       (+) Transmit a CAN frame message.
522       (+) Receive a CAN frame message.
523       (+) Enter CAN peripheral in sleep mode.
524       (+) Wake up the CAN peripheral from sleep mode.
525 
526 @endverbatim
527   * @{
528   */
529 
530 /**
531   * @brief  Initiates and transmits a CAN frame message.
532   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
533   *         the configuration information for the specified CAN.
534   * @param  Timeout Specify Timeout value
535   * @retval HAL status
536   */
HAL_CAN_Transmit(CAN_HandleTypeDef * hcan,uint32_t Timeout)537 HAL_StatusTypeDef HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
538 {
539   uint32_t transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
540   uint32_t tickstart = 0U;
541 
542   /* Check the parameters */
543   assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
544   assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
545   assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
546 
547   if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \
548      ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \
549      ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))
550   {
551     /* Process locked */
552     __HAL_LOCK(hcan);
553 
554     /* Change CAN state */
555     switch(hcan->State)
556     {
557       case(HAL_CAN_STATE_BUSY_RX0):
558           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
559           break;
560       case(HAL_CAN_STATE_BUSY_RX1):
561           hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
562           break;
563       case(HAL_CAN_STATE_BUSY_RX0_RX1):
564           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
565           break;
566       default: /* HAL_CAN_STATE_READY */
567           hcan->State = HAL_CAN_STATE_BUSY_TX;
568           break;
569     }
570 
571     /* Select one empty transmit mailbox */
572     if ((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
573     {
574       transmitmailbox = CAN_TXMAILBOX_0;
575     }
576     else if ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
577     {
578       transmitmailbox = CAN_TXMAILBOX_1;
579     }
580     else
581     {
582       transmitmailbox = CAN_TXMAILBOX_2;
583     }
584 
585     /* Set up the Id */
586     hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
587     if (hcan->pTxMsg->IDE == CAN_ID_STD)
588     {
589       assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
590       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \
591                                                   hcan->pTxMsg->RTR);
592     }
593     else
594     {
595       assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
596       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \
597                                                   hcan->pTxMsg->IDE | \
598                                                   hcan->pTxMsg->RTR);
599     }
600 
601     /* Set up the DLC */
602     hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
603     hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= (uint32_t)0xFFFFFFF0U;
604     hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
605 
606     /* Set up the data field */
607     hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) |
608                                              ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) |
609                                              ((uint32_t)hcan->pTxMsg->Data[1U] << 8U) |
610                                              ((uint32_t)hcan->pTxMsg->Data[0U]));
611     hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) |
612                                              ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) |
613                                              ((uint32_t)hcan->pTxMsg->Data[5U] << 8U) |
614                                              ((uint32_t)hcan->pTxMsg->Data[4U]));
615     /* Request transmission */
616     hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
617 
618     /* Get tick */
619     tickstart = HAL_GetTick();
620 
621     /* Check End of transmission flag */
622     while(!(__HAL_CAN_TRANSMIT_STATUS(hcan, transmitmailbox)))
623     {
624       /* Check for the Timeout */
625       if(Timeout != HAL_MAX_DELAY)
626       {
627         if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
628         {
629           hcan->State = HAL_CAN_STATE_TIMEOUT;
630           __HAL_CAN_CANCEL_TRANSMIT(hcan, transmitmailbox);
631           /* Process unlocked */
632           __HAL_UNLOCK(hcan);
633           return HAL_TIMEOUT;
634         }
635       }
636     }
637 
638     /* Change CAN state */
639     switch(hcan->State)
640     {
641       case(HAL_CAN_STATE_BUSY_TX_RX0):
642           hcan->State = HAL_CAN_STATE_BUSY_RX0;
643           break;
644       case(HAL_CAN_STATE_BUSY_TX_RX1):
645           hcan->State = HAL_CAN_STATE_BUSY_RX1;
646           break;
647       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
648           hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
649           break;
650       default: /* HAL_CAN_STATE_BUSY_TX */
651           hcan->State = HAL_CAN_STATE_READY;
652           break;
653     }
654 
655     /* Process unlocked */
656     __HAL_UNLOCK(hcan);
657 
658     /* Return function status */
659     return HAL_OK;
660   }
661   else
662   {
663     /* Change CAN state */
664     hcan->State = HAL_CAN_STATE_ERROR;
665 
666     /* Return function status */
667     return HAL_ERROR;
668   }
669 }
670 
671 /**
672   * @brief  Initiates and transmits a CAN frame message.
673   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
674   *         the configuration information for the specified CAN.
675   * @retval HAL status
676   */
HAL_CAN_Transmit_IT(CAN_HandleTypeDef * hcan)677 HAL_StatusTypeDef HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
678 {
679   uint32_t  transmitmailbox = CAN_TXSTATUS_NOMAILBOX;
680 
681   /* Check the parameters */
682   assert_param(IS_CAN_IDTYPE(hcan->pTxMsg->IDE));
683   assert_param(IS_CAN_RTR(hcan->pTxMsg->RTR));
684   assert_param(IS_CAN_DLC(hcan->pTxMsg->DLC));
685 
686   if(((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0) || \
687      ((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1) || \
688      ((hcan->Instance->TSR&CAN_TSR_TME2) == CAN_TSR_TME2))
689   {
690     /* Process Locked */
691     __HAL_LOCK(hcan);
692 
693     /* Select one empty transmit mailbox */
694     if((hcan->Instance->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
695     {
696       transmitmailbox = CAN_TXMAILBOX_0;
697     }
698     else if((hcan->Instance->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
699     {
700       transmitmailbox = CAN_TXMAILBOX_1;
701     }
702     else
703     {
704       transmitmailbox = CAN_TXMAILBOX_2;
705     }
706 
707     /* Set up the Id */
708     hcan->Instance->sTxMailBox[transmitmailbox].TIR &= CAN_TI0R_TXRQ;
709     if(hcan->pTxMsg->IDE == CAN_ID_STD)
710     {
711       assert_param(IS_CAN_STDID(hcan->pTxMsg->StdId));
712       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->StdId << 21U) | \
713                                                            hcan->pTxMsg->RTR);
714     }
715     else
716     {
717       assert_param(IS_CAN_EXTID(hcan->pTxMsg->ExtId));
718       hcan->Instance->sTxMailBox[transmitmailbox].TIR |= ((hcan->pTxMsg->ExtId << 3U) | \
719                                                            hcan->pTxMsg->IDE | \
720                                                            hcan->pTxMsg->RTR);
721     }
722 
723     /* Set up the DLC */
724     hcan->pTxMsg->DLC &= (uint8_t)0x0000000F;
725     hcan->Instance->sTxMailBox[transmitmailbox].TDTR &= 0xFFFFFFF0U;
726     hcan->Instance->sTxMailBox[transmitmailbox].TDTR |= hcan->pTxMsg->DLC;
727 
728     /* Set up the data field */
729     hcan->Instance->sTxMailBox[transmitmailbox].TDLR = (((uint32_t)hcan->pTxMsg->Data[3U] << 24U) |
730                                                         ((uint32_t)hcan->pTxMsg->Data[2U] << 16U) |
731                                                         ((uint32_t)hcan->pTxMsg->Data[1U] << 8U)  |
732                                                         ((uint32_t)hcan->pTxMsg->Data[0U]));
733     hcan->Instance->sTxMailBox[transmitmailbox].TDHR = (((uint32_t)hcan->pTxMsg->Data[7U] << 24U) |
734                                                         ((uint32_t)hcan->pTxMsg->Data[6U] << 16U) |
735                                                         ((uint32_t)hcan->pTxMsg->Data[5U] << 8U)  |
736                                                         ((uint32_t)hcan->pTxMsg->Data[4U]));
737 
738     /* Change CAN state */
739     switch(hcan->State)
740     {
741       case(HAL_CAN_STATE_BUSY_RX0):
742           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
743           break;
744       case(HAL_CAN_STATE_BUSY_RX1):
745           hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
746           break;
747       case(HAL_CAN_STATE_BUSY_RX0_RX1):
748           hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
749           break;
750       default: /* HAL_CAN_STATE_READY */
751           hcan->State = HAL_CAN_STATE_BUSY_TX;
752           break;
753     }
754 
755     /* Set CAN error code to none */
756     hcan->ErrorCode = HAL_CAN_ERROR_NONE;
757 
758     /* Process Unlocked */
759     __HAL_UNLOCK(hcan);
760 
761     /* Request transmission */
762     hcan->Instance->sTxMailBox[transmitmailbox].TIR |= CAN_TI0R_TXRQ;
763 
764     /* Enable Error warning, Error passive, Bus-off,
765        Last error and Error Interrupts */
766     __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
767                               CAN_IT_EPV |
768                               CAN_IT_BOF |
769                               CAN_IT_LEC |
770                               CAN_IT_ERR |
771                               CAN_IT_TME);
772   }
773   else
774   {
775     /* Change CAN state */
776     hcan->State = HAL_CAN_STATE_ERROR;
777 
778     /* Return function status */
779     return HAL_ERROR;
780   }
781 
782   return HAL_OK;
783 }
784 
785 /**
786   * @brief  Receives a correct CAN frame.
787   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
788   *         the configuration information for the specified CAN.
789   * @param  FIFONumber FIFO Number value
790   * @param  Timeout Specify Timeout value
791   * @retval HAL status
792   */
HAL_CAN_Receive(CAN_HandleTypeDef * hcan,uint8_t FIFONumber,uint32_t Timeout)793 HAL_StatusTypeDef HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout)
794 {
795   uint32_t tickstart = 0U;
796   CanRxMsgTypeDef* pRxMsg = NULL;
797 
798   /* Check the parameters */
799   assert_param(IS_CAN_FIFO(FIFONumber));
800 
801   /* Check if CAN state is not busy for RX FIFO0 */
802   if ((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) ||         \
803                                     (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) ||      \
804                                     (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
805                                     (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
806   {
807     return HAL_BUSY;
808   }
809 
810   /* Check if CAN state is not busy for RX FIFO1 */
811   if ((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) ||         \
812                                     (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) ||      \
813                                     (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
814                                     (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
815   {
816     return HAL_BUSY;
817   }
818 
819   /* Process locked */
820   __HAL_LOCK(hcan);
821 
822   /* Change CAN state */
823   if (FIFONumber == CAN_FIFO0)
824   {
825     switch(hcan->State)
826     {
827       case(HAL_CAN_STATE_BUSY_TX):
828         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
829         break;
830       case(HAL_CAN_STATE_BUSY_RX1):
831         hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
832         break;
833       case(HAL_CAN_STATE_BUSY_TX_RX1):
834         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
835         break;
836       default: /* HAL_CAN_STATE_READY */
837         hcan->State = HAL_CAN_STATE_BUSY_RX0;
838         break;
839     }
840   }
841   else /* FIFONumber == CAN_FIFO1 */
842   {
843     switch(hcan->State)
844     {
845       case(HAL_CAN_STATE_BUSY_TX):
846         hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
847         break;
848       case(HAL_CAN_STATE_BUSY_RX0):
849         hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
850         break;
851       case(HAL_CAN_STATE_BUSY_TX_RX0):
852         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
853         break;
854       default: /* HAL_CAN_STATE_READY */
855         hcan->State = HAL_CAN_STATE_BUSY_RX1;
856         break;
857     }
858   }
859 
860   /* Get tick */
861   tickstart = HAL_GetTick();
862 
863   /* Check pending message */
864   while(__HAL_CAN_MSG_PENDING(hcan, FIFONumber) == 0U)
865   {
866     /* Check for the Timeout */
867     if(Timeout != HAL_MAX_DELAY)
868     {
869       if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout))
870       {
871         hcan->State = HAL_CAN_STATE_TIMEOUT;
872         /* Process unlocked */
873         __HAL_UNLOCK(hcan);
874         return HAL_TIMEOUT;
875       }
876     }
877   }
878 
879   /* Set RxMsg pointer */
880   if(FIFONumber == CAN_FIFO0)
881   {
882     pRxMsg = hcan->pRxMsg;
883   }
884   else /* FIFONumber == CAN_FIFO1 */
885   {
886     pRxMsg = hcan->pRx1Msg;
887   }
888 
889   /* Get the Id */
890   pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
891   if (pRxMsg->IDE == CAN_ID_STD)
892   {
893     pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
894   }
895   else
896   {
897     pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
898   }
899 
900   pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
901   /* Get the DLC */
902   pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
903   /* Get the FMI */
904   pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
905   /* Get the FIFONumber */
906   pRxMsg->FIFONumber = FIFONumber;
907   /* Get the data field */
908   pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
909   pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
910   pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
911   pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
912   pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
913   pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
914   pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
915   pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
916 
917   /* Release the FIFO */
918   if(FIFONumber == CAN_FIFO0)
919   {
920     /* Release FIFO0 */
921     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
922   }
923   else /* FIFONumber == CAN_FIFO1 */
924   {
925     /* Release FIFO1 */
926     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
927   }
928 
929   /* Change CAN state */
930   if (FIFONumber == CAN_FIFO0)
931   {
932     switch(hcan->State)
933     {
934       case(HAL_CAN_STATE_BUSY_TX_RX0):
935         hcan->State = HAL_CAN_STATE_BUSY_TX;
936         break;
937       case(HAL_CAN_STATE_BUSY_RX0_RX1):
938         hcan->State = HAL_CAN_STATE_BUSY_RX1;
939         break;
940       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
941         hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
942         break;
943       default: /* HAL_CAN_STATE_BUSY_RX0 */
944         hcan->State = HAL_CAN_STATE_READY;
945         break;
946     }
947   }
948   else /* FIFONumber == CAN_FIFO1 */
949   {
950     switch(hcan->State)
951     {
952       case(HAL_CAN_STATE_BUSY_TX_RX1):
953         hcan->State = HAL_CAN_STATE_BUSY_TX;
954         break;
955       case(HAL_CAN_STATE_BUSY_RX0_RX1):
956         hcan->State = HAL_CAN_STATE_BUSY_RX0;
957         break;
958       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
959         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
960         break;
961       default: /* HAL_CAN_STATE_BUSY_RX1 */
962         hcan->State = HAL_CAN_STATE_READY;
963         break;
964     }
965   }
966 
967   /* Process unlocked */
968   __HAL_UNLOCK(hcan);
969 
970   /* Return function status */
971   return HAL_OK;
972 }
973 
974 /**
975   * @brief  Receives a correct CAN frame.
976   * @param  hcan       Pointer to a CAN_HandleTypeDef structure that contains
977   *         the configuration information for the specified CAN.
978   * @param  FIFONumber Specify the FIFO number
979   * @retval HAL status
980   */
HAL_CAN_Receive_IT(CAN_HandleTypeDef * hcan,uint8_t FIFONumber)981 HAL_StatusTypeDef HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
982 {
983   /* Check the parameters */
984   assert_param(IS_CAN_FIFO(FIFONumber));
985 
986   /* Check if CAN state is not busy for RX FIFO0 */
987   if((FIFONumber == CAN_FIFO0) && ((hcan->State == HAL_CAN_STATE_BUSY_RX0) ||         \
988                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0) ||      \
989                                    (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
990                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
991   {
992     return HAL_BUSY;
993   }
994 
995   /* Check if CAN state is not busy for RX FIFO1 */
996   if((FIFONumber == CAN_FIFO1) && ((hcan->State == HAL_CAN_STATE_BUSY_RX1) ||         \
997                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX1) ||      \
998                                    (hcan->State == HAL_CAN_STATE_BUSY_RX0_RX1) ||     \
999                                    (hcan->State == HAL_CAN_STATE_BUSY_TX_RX0_RX1)))
1000   {
1001     return HAL_BUSY;
1002   }
1003 
1004   /* Process locked */
1005   __HAL_LOCK(hcan);
1006 
1007   /* Change CAN state */
1008   if(FIFONumber == CAN_FIFO0)
1009   {
1010     switch(hcan->State)
1011     {
1012       case(HAL_CAN_STATE_BUSY_TX):
1013         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
1014         break;
1015       case(HAL_CAN_STATE_BUSY_RX1):
1016         hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
1017         break;
1018       case(HAL_CAN_STATE_BUSY_TX_RX1):
1019         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
1020         break;
1021       default: /* HAL_CAN_STATE_READY */
1022         hcan->State = HAL_CAN_STATE_BUSY_RX0;
1023         break;
1024     }
1025   }
1026   else /* FIFONumber == CAN_FIFO1 */
1027   {
1028     switch(hcan->State)
1029     {
1030       case(HAL_CAN_STATE_BUSY_TX):
1031         hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
1032         break;
1033       case(HAL_CAN_STATE_BUSY_RX0):
1034         hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
1035         break;
1036       case(HAL_CAN_STATE_BUSY_TX_RX0):
1037         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0_RX1;
1038         break;
1039       default: /* HAL_CAN_STATE_READY */
1040         hcan->State = HAL_CAN_STATE_BUSY_RX1;
1041         break;
1042     }
1043   }
1044   /* Set CAN error code to none */
1045   hcan->ErrorCode = HAL_CAN_ERROR_NONE;
1046 
1047   /* Enable interrupts: */
1048   /*  - Enable Error warning Interrupt */
1049   /*  - Enable Error passive Interrupt */
1050   /*  - Enable Bus-off Interrupt */
1051   /*  - Enable Last error code Interrupt */
1052   /*  - Enable Error Interrupt */
1053   /*  - Enable Transmit mailbox empty Interrupt */
1054   __HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG |
1055                             CAN_IT_EPV |
1056                             CAN_IT_BOF |
1057                             CAN_IT_LEC |
1058                             CAN_IT_ERR |
1059                             CAN_IT_TME);
1060 
1061   /* Process unlocked */
1062    __HAL_UNLOCK(hcan);
1063 
1064   if(FIFONumber == CAN_FIFO0)
1065   {
1066     /* Enable FIFO 0 overrun and message pending Interrupt */
1067     __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0);
1068   }
1069   else
1070   {
1071     /* Enable FIFO 1 overrun and message pending Interrupt */
1072     __HAL_CAN_ENABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1);
1073   }
1074 
1075   /* Return function status */
1076   return HAL_OK;
1077 }
1078 
1079 /**
1080   * @brief  Enters the Sleep (low power) mode.
1081   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1082   *         the configuration information for the specified CAN.
1083   * @retval HAL status.
1084   */
HAL_CAN_Sleep(CAN_HandleTypeDef * hcan)1085 HAL_StatusTypeDef HAL_CAN_Sleep(CAN_HandleTypeDef* hcan)
1086 {
1087   uint32_t tickstart = 0U;
1088 
1089   /* Process locked */
1090   __HAL_LOCK(hcan);
1091 
1092   /* Change CAN state */
1093   hcan->State = HAL_CAN_STATE_BUSY;
1094 
1095   /* Request Sleep mode */
1096    hcan->Instance->MCR = (((hcan->Instance->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
1097 
1098   /* Sleep mode status */
1099   if ((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK)
1100   {
1101     /* Process unlocked */
1102     __HAL_UNLOCK(hcan);
1103 
1104     /* Return function status */
1105     return HAL_ERROR;
1106   }
1107 
1108   /* Get tick */
1109   tickstart = HAL_GetTick();
1110 
1111   /* Wait the acknowledge */
1112   while((hcan->Instance->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) != CAN_MSR_SLAK)
1113   {
1114     if((HAL_GetTick()  - tickstart) > CAN_TIMEOUT_VALUE)
1115     {
1116       hcan->State = HAL_CAN_STATE_TIMEOUT;
1117       /* Process unlocked */
1118       __HAL_UNLOCK(hcan);
1119       return HAL_TIMEOUT;
1120     }
1121   }
1122 
1123   /* Change CAN state */
1124   hcan->State = HAL_CAN_STATE_READY;
1125 
1126   /* Process unlocked */
1127   __HAL_UNLOCK(hcan);
1128 
1129   /* Return function status */
1130   return HAL_OK;
1131 }
1132 
1133 /**
1134   * @brief  Wakes up the CAN peripheral from sleep mode, after that the CAN peripheral
1135   *         is in the normal mode.
1136   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1137   *         the configuration information for the specified CAN.
1138   * @retval HAL status.
1139   */
HAL_CAN_WakeUp(CAN_HandleTypeDef * hcan)1140 HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan)
1141 {
1142   uint32_t tickstart = 0U;
1143 
1144   /* Process locked */
1145   __HAL_LOCK(hcan);
1146 
1147   /* Change CAN state */
1148   hcan->State = HAL_CAN_STATE_BUSY;
1149 
1150   /* Wake up request */
1151   hcan->Instance->MCR &= ~(uint32_t)CAN_MCR_SLEEP;
1152 
1153   /* Get tick */
1154   tickstart = HAL_GetTick();
1155 
1156   /* Sleep mode status */
1157   while((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)
1158   {
1159     if((HAL_GetTick()  - tickstart) > CAN_TIMEOUT_VALUE)
1160     {
1161       hcan->State= HAL_CAN_STATE_TIMEOUT;
1162       /* Process unlocked */
1163       __HAL_UNLOCK(hcan);
1164       return HAL_TIMEOUT;
1165     }
1166   }
1167   if((hcan->Instance->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)
1168   {
1169     /* Process unlocked */
1170     __HAL_UNLOCK(hcan);
1171 
1172     /* Return function status */
1173     return HAL_ERROR;
1174   }
1175 
1176   /* Change CAN state */
1177   hcan->State = HAL_CAN_STATE_READY;
1178 
1179   /* Process unlocked */
1180   __HAL_UNLOCK(hcan);
1181 
1182   /* Return function status */
1183   return HAL_OK;
1184 }
1185 
1186 /**
1187   * @brief  Handles CAN interrupt request
1188   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1189   *         the configuration information for the specified CAN.
1190   * @retval None
1191   */
HAL_CAN_IRQHandler(CAN_HandleTypeDef * hcan)1192 void HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
1193 {
1194   uint32_t tmp1 = 0U, tmp2 = 0U, tmp3 = 0U;
1195   uint32_t errorcode = HAL_CAN_ERROR_NONE;
1196 
1197   /* Check Overrun flag for FIFO0 */
1198   tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV0);
1199   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV0);
1200   if(tmp1 && tmp2)
1201   {
1202     /* Set CAN error code to FOV0 error */
1203     errorcode |= HAL_CAN_ERROR_FOV0;
1204 
1205     /* Clear FIFO0 Overrun Flag */
1206     __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0);
1207   }
1208   /* Check Overrun flag for FIFO1 */
1209   tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_FOV1);
1210   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FOV1);
1211 
1212   if(tmp1 && tmp2)
1213   {
1214     /* Set CAN error code to FOV1 error */
1215     errorcode |= HAL_CAN_ERROR_FOV1;
1216 
1217     /* Clear FIFO1 Overrun Flag */
1218     __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1);
1219   }
1220 
1221   /* Check End of transmission flag */
1222   if(__HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_TME))
1223   {
1224     tmp1 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_0);
1225     tmp2 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_1);
1226     tmp3 = __HAL_CAN_TRANSMIT_STATUS(hcan, CAN_TXMAILBOX_2);
1227     if(tmp1 || tmp2 || tmp3)
1228     {
1229       tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK0);
1230       tmp2 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK1);
1231       tmp3 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_TXOK2);
1232       /* Check Transmit success */
1233       if(tmp1 || tmp2 || tmp3)
1234       {
1235         /* Call transmit function */
1236         CAN_Transmit_IT(hcan);
1237       }
1238       else /* Transmit failure */
1239       {
1240         /* Set CAN error code to TXFAIL error */
1241         errorcode |= HAL_CAN_ERROR_TXFAIL;
1242       }
1243 
1244       /* Clear transmission status flags (RQCPx and TXOKx) */
1245       SET_BIT(hcan->Instance->TSR, CAN_TSR_RQCP0  | CAN_TSR_RQCP1  | CAN_TSR_RQCP2 | \
1246                                    CAN_FLAG_TXOK0 | CAN_FLAG_TXOK1 | CAN_FLAG_TXOK2);
1247     }
1248   }
1249 
1250   tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO0);
1251   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP0);
1252   /* Check End of reception flag for FIFO0 */
1253   if((tmp1 != 0U) && tmp2)
1254   {
1255     /* Call receive function */
1256     CAN_Receive_IT(hcan, CAN_FIFO0);
1257   }
1258 
1259   tmp1 = __HAL_CAN_MSG_PENDING(hcan, CAN_FIFO1);
1260   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_FMP1);
1261   /* Check End of reception flag for FIFO1 */
1262   if((tmp1 != 0U) && tmp2)
1263   {
1264     /* Call receive function */
1265     CAN_Receive_IT(hcan, CAN_FIFO1);
1266   }
1267 
1268   /* Set error code in handle */
1269   hcan->ErrorCode |= errorcode;
1270 
1271   tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EWG);
1272   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EWG);
1273   tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1274   /* Check Error Warning Flag */
1275   if(tmp1 && tmp2 && tmp3)
1276   {
1277     /* Set CAN error code to EWG error */
1278     hcan->ErrorCode |= HAL_CAN_ERROR_EWG;
1279   }
1280 
1281   tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_EPV);
1282   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_EPV);
1283   tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1284   /* Check Error Passive Flag */
1285   if(tmp1 && tmp2 && tmp3)
1286   {
1287     /* Set CAN error code to EPV error */
1288     hcan->ErrorCode |= HAL_CAN_ERROR_EPV;
1289   }
1290 
1291   tmp1 = __HAL_CAN_GET_FLAG(hcan, CAN_FLAG_BOF);
1292   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_BOF);
1293   tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1294   /* Check Bus-Off Flag */
1295   if(tmp1 && tmp2 && tmp3)
1296   {
1297     /* Set CAN error code to BOF error */
1298     hcan->ErrorCode |= HAL_CAN_ERROR_BOF;
1299   }
1300 
1301   tmp1 = HAL_IS_BIT_CLR(hcan->Instance->ESR, CAN_ESR_LEC);
1302   tmp2 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_LEC);
1303   tmp3 = __HAL_CAN_GET_IT_SOURCE(hcan, CAN_IT_ERR);
1304   /* Check Last error code Flag */
1305   if((!tmp1) && tmp2 && tmp3)
1306   {
1307     tmp1 = (hcan->Instance->ESR) & CAN_ESR_LEC;
1308     switch(tmp1)
1309     {
1310       case(CAN_ESR_LEC_0):
1311           /* Set CAN error code to STF error */
1312           hcan->ErrorCode |= HAL_CAN_ERROR_STF;
1313           break;
1314       case(CAN_ESR_LEC_1):
1315           /* Set CAN error code to FOR error */
1316           hcan->ErrorCode |= HAL_CAN_ERROR_FOR;
1317           break;
1318       case(CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
1319           /* Set CAN error code to ACK error */
1320           hcan->ErrorCode |= HAL_CAN_ERROR_ACK;
1321           break;
1322       case(CAN_ESR_LEC_2):
1323           /* Set CAN error code to BR error */
1324           hcan->ErrorCode |= HAL_CAN_ERROR_BR;
1325           break;
1326       case(CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
1327           /* Set CAN error code to BD error */
1328           hcan->ErrorCode |= HAL_CAN_ERROR_BD;
1329           break;
1330       case(CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
1331           /* Set CAN error code to CRC error */
1332           hcan->ErrorCode |= HAL_CAN_ERROR_CRC;
1333           break;
1334       default:
1335           break;
1336     }
1337 
1338     /* Clear Last error code Flag */
1339     hcan->Instance->ESR &= ~(CAN_ESR_LEC);
1340   }
1341 
1342   /* Call the Error call Back in case of Errors */
1343   if(hcan->ErrorCode != HAL_CAN_ERROR_NONE)
1344   {
1345     /* Clear ERRI Flag */
1346     hcan->Instance->MSR = CAN_MSR_ERRI;
1347     /* Set the CAN state ready to be able to start again the process */
1348     hcan->State = HAL_CAN_STATE_READY;
1349 
1350     /* Disable interrupts: */
1351     /*  - Disable Error warning Interrupt */
1352     /*  - Disable Error passive Interrupt */
1353     /*  - Disable Bus-off Interrupt */
1354     /*  - Disable Last error code Interrupt */
1355     /*  - Disable Error Interrupt */
1356     /*  - Disable FIFO 0 message pending Interrupt */
1357     /*  - Disable FIFO 0 Overrun Interrupt */
1358     /*  - Disable FIFO 1 message pending Interrupt */
1359     /*  - Disable FIFO 1 Overrun Interrupt */
1360     /*  - Disable Transmit mailbox empty Interrupt */
1361     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
1362                                CAN_IT_EPV |
1363                                CAN_IT_BOF |
1364                                CAN_IT_LEC |
1365                                CAN_IT_ERR |
1366                                CAN_IT_FMP0|
1367                                CAN_IT_FOV0|
1368                                CAN_IT_FMP1|
1369                                CAN_IT_FOV1|
1370                                CAN_IT_TME);
1371 
1372     /* Call Error callback function */
1373     HAL_CAN_ErrorCallback(hcan);
1374   }
1375 }
1376 
1377 /**
1378   * @brief  Transmission  complete callback in non blocking mode
1379   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1380   *         the configuration information for the specified CAN.
1381   * @retval None
1382   */
HAL_CAN_TxCpltCallback(CAN_HandleTypeDef * hcan)1383 __weak void HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
1384 {
1385   /* Prevent unused argument(s) compilation warning */
1386   UNUSED(hcan);
1387   /* NOTE : This function Should not be modified, when the callback is needed,
1388             the HAL_CAN_TxCpltCallback could be implemented in the user file
1389    */
1390 }
1391 
1392 /**
1393   * @brief  Transmission  complete callback in non blocking mode
1394   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1395   *         the configuration information for the specified CAN.
1396   * @retval None
1397   */
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef * hcan)1398 __weak void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
1399 {
1400   /* Prevent unused argument(s) compilation warning */
1401   UNUSED(hcan);
1402   /* NOTE : This function Should not be modified, when the callback is needed,
1403             the HAL_CAN_RxCpltCallback could be implemented in the user file
1404    */
1405 }
1406 
1407 /**
1408   * @brief  Error CAN callback.
1409   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1410   *         the configuration information for the specified CAN.
1411   * @retval None
1412   */
HAL_CAN_ErrorCallback(CAN_HandleTypeDef * hcan)1413 __weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
1414 {
1415   /* Prevent unused argument(s) compilation warning */
1416   UNUSED(hcan);
1417   /* NOTE : This function Should not be modified, when the callback is needed,
1418             the HAL_CAN_ErrorCallback could be implemented in the user file
1419    */
1420 }
1421 
1422 /**
1423   * @}
1424   */
1425 
1426 /** @defgroup CAN_Exported_Functions_Group3 Peripheral State and Error functions
1427   *  @brief   CAN Peripheral State functions
1428   *
1429 @verbatim
1430   ==============================================================================
1431             ##### Peripheral State and Error functions #####
1432   ==============================================================================
1433     [..]
1434     This subsection provides functions allowing to :
1435       (+) Check the CAN state.
1436       (+) Check CAN Errors detected during interrupt process
1437 
1438 @endverbatim
1439   * @{
1440   */
1441 
1442 /**
1443   * @brief  return the CAN state
1444   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1445   *         the configuration information for the specified CAN.
1446   * @retval HAL state
1447   */
HAL_CAN_GetState(CAN_HandleTypeDef * hcan)1448 HAL_CAN_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef* hcan)
1449 {
1450   /* Return CAN state */
1451   return hcan->State;
1452 }
1453 
1454 /**
1455   * @brief  Return the CAN error code
1456   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1457   *         the configuration information for the specified CAN.
1458   * @retval CAN Error Code
1459   */
HAL_CAN_GetError(CAN_HandleTypeDef * hcan)1460 uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan)
1461 {
1462   return hcan->ErrorCode;
1463 }
1464 
1465 /**
1466   * @}
1467   */
1468 /**
1469   * @brief  Initiates and transmits a CAN frame message.
1470   * @param  hcan pointer to a CAN_HandleTypeDef structure that contains
1471   *         the configuration information for the specified CAN.
1472   * @retval HAL status
1473   */
CAN_Transmit_IT(CAN_HandleTypeDef * hcan)1474 static HAL_StatusTypeDef CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
1475 {
1476   /* Disable Transmit mailbox empty Interrupt */
1477   __HAL_CAN_DISABLE_IT(hcan, CAN_IT_TME);
1478 
1479   if(hcan->State == HAL_CAN_STATE_BUSY_TX)
1480   {
1481     /* Disable Error warning, Error passive, Bus-off, Last error code
1482        and Error Interrupts */
1483     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
1484                                CAN_IT_EPV |
1485                                CAN_IT_BOF |
1486                                CAN_IT_LEC |
1487                                CAN_IT_ERR );
1488   }
1489 
1490   /* Change CAN state */
1491   switch(hcan->State)
1492   {
1493     case(HAL_CAN_STATE_BUSY_TX_RX0):
1494       hcan->State = HAL_CAN_STATE_BUSY_RX0;
1495       break;
1496     case(HAL_CAN_STATE_BUSY_TX_RX1):
1497       hcan->State = HAL_CAN_STATE_BUSY_RX1;
1498       break;
1499     case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
1500       hcan->State = HAL_CAN_STATE_BUSY_RX0_RX1;
1501       break;
1502     default: /* HAL_CAN_STATE_BUSY_TX */
1503       hcan->State = HAL_CAN_STATE_READY;
1504       break;
1505   }
1506 
1507   /* Transmission complete callback */
1508   HAL_CAN_TxCpltCallback(hcan);
1509 
1510   return HAL_OK;
1511 }
1512 
1513 /**
1514   * @brief  Receives a correct CAN frame.
1515   * @param  hcan       Pointer to a CAN_HandleTypeDef structure that contains
1516   *         the configuration information for the specified CAN.
1517   * @param  FIFONumber Specify the FIFO number
1518   * @retval HAL status
1519   * @retval None
1520   */
CAN_Receive_IT(CAN_HandleTypeDef * hcan,uint8_t FIFONumber)1521 static HAL_StatusTypeDef CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
1522 {
1523   uint32_t tmp1 = 0U;
1524   CanRxMsgTypeDef* pRxMsg = NULL;
1525 
1526   /* Set RxMsg pointer */
1527   if(FIFONumber == CAN_FIFO0)
1528   {
1529     pRxMsg = hcan->pRxMsg;
1530   }
1531   else /* FIFONumber == CAN_FIFO1 */
1532   {
1533     pRxMsg = hcan->pRx1Msg;
1534   }
1535 
1536   /* Get the Id */
1537   pRxMsg->IDE = (uint8_t)0x04 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
1538   if (pRxMsg->IDE == CAN_ID_STD)
1539   {
1540     pRxMsg->StdId = 0x000007FFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 21U);
1541   }
1542   else
1543   {
1544     pRxMsg->ExtId = 0x1FFFFFFFU & (hcan->Instance->sFIFOMailBox[FIFONumber].RIR >> 3U);
1545   }
1546 
1547   pRxMsg->RTR = (uint8_t)0x02 & hcan->Instance->sFIFOMailBox[FIFONumber].RIR;
1548   /* Get the DLC */
1549   pRxMsg->DLC = (uint8_t)0x0F & hcan->Instance->sFIFOMailBox[FIFONumber].RDTR;
1550   /* Get the FIFONumber */
1551   pRxMsg->FIFONumber = FIFONumber;
1552   /* Get the FMI */
1553   pRxMsg->FMI = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDTR >> 8U);
1554   /* Get the data field */
1555   pRxMsg->Data[0] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDLR;
1556   pRxMsg->Data[1] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 8U);
1557   pRxMsg->Data[2] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 16U);
1558   pRxMsg->Data[3] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDLR >> 24U);
1559   pRxMsg->Data[4] = (uint8_t)0xFF & hcan->Instance->sFIFOMailBox[FIFONumber].RDHR;
1560   pRxMsg->Data[5] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 8U);
1561   pRxMsg->Data[6] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 16U);
1562   pRxMsg->Data[7] = (uint8_t)0xFF & (hcan->Instance->sFIFOMailBox[FIFONumber].RDHR >> 24U);
1563   /* Release the FIFO */
1564   /* Release FIFO0 */
1565   if (FIFONumber == CAN_FIFO0)
1566   {
1567     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO0);
1568 
1569     /* Disable FIFO 0 overrun and message pending Interrupt */
1570     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV0 | CAN_IT_FMP0);
1571   }
1572   /* Release FIFO1 */
1573   else /* FIFONumber == CAN_FIFO1 */
1574   {
1575     __HAL_CAN_FIFO_RELEASE(hcan, CAN_FIFO1);
1576 
1577     /* Disable FIFO 1 overrun and message pending Interrupt */
1578     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_FOV1 | CAN_IT_FMP1);
1579   }
1580 
1581   tmp1 = hcan->State;
1582   if((tmp1 == HAL_CAN_STATE_BUSY_RX0) || (tmp1 == HAL_CAN_STATE_BUSY_RX1))
1583   {
1584     /* Disable Error warning, Error passive, Bus-off, Last error code
1585        and Error Interrupts */
1586     __HAL_CAN_DISABLE_IT(hcan, CAN_IT_EWG |
1587                                CAN_IT_EPV |
1588                                CAN_IT_BOF |
1589                                CAN_IT_LEC |
1590                                CAN_IT_ERR);
1591   }
1592 
1593   /* Change CAN state */
1594   if (FIFONumber == CAN_FIFO0)
1595   {
1596     switch(hcan->State)
1597     {
1598       case(HAL_CAN_STATE_BUSY_TX_RX0):
1599         hcan->State = HAL_CAN_STATE_BUSY_TX;
1600         break;
1601       case(HAL_CAN_STATE_BUSY_RX0_RX1):
1602         hcan->State = HAL_CAN_STATE_BUSY_RX1;
1603         break;
1604       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
1605         hcan->State = HAL_CAN_STATE_BUSY_TX_RX1;
1606         break;
1607       default: /* HAL_CAN_STATE_BUSY_RX0 */
1608         hcan->State = HAL_CAN_STATE_READY;
1609         break;
1610     }
1611   }
1612   else /* FIFONumber == CAN_FIFO1 */
1613   {
1614     switch(hcan->State)
1615     {
1616       case(HAL_CAN_STATE_BUSY_TX_RX1):
1617         hcan->State = HAL_CAN_STATE_BUSY_TX;
1618         break;
1619       case(HAL_CAN_STATE_BUSY_RX0_RX1):
1620         hcan->State = HAL_CAN_STATE_BUSY_RX0;
1621         break;
1622       case(HAL_CAN_STATE_BUSY_TX_RX0_RX1):
1623         hcan->State = HAL_CAN_STATE_BUSY_TX_RX0;
1624         break;
1625       default: /* HAL_CAN_STATE_BUSY_RX1 */
1626         hcan->State = HAL_CAN_STATE_READY;
1627         break;
1628     }
1629   }
1630 
1631   /* Receive complete callback */
1632   HAL_CAN_RxCpltCallback(hcan);
1633 
1634   /* Return function status */
1635   return HAL_OK;
1636 }
1637 
1638 /**
1639   * @}
1640   */
1641 
1642 #endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
1643 /**
1644   * @}
1645   */
1646 
1647 /**
1648   * @}
1649   */
1650 
1651 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1652