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