| /** |
| ****************************************************************************** |
| * @file stm32f0xx_hal_can.c |
| * @author MCD Application Team |
| * @brief CAN HAL module driver. |
| * This file provides firmware functions to manage the following |
| * functionalities of the Controller Area Network (CAN) peripheral: |
| * + Initialization and de-initialization functions |
| * + Configuration functions |
| * + Control functions |
| * + Interrupts management |
| * + Callbacks functions |
| * + Peripheral State and Error functions |
| * |
| ****************************************************************************** |
| * @attention |
| * |
| * Copyright (c) 2016 STMicroelectronics. |
| * All rights reserved. |
| * |
| * This software is licensed under terms that can be found in the LICENSE file |
| * in the root directory of this software component. |
| * If no LICENSE file comes with this software, it is provided AS-IS. |
| * |
| ****************************************************************************** |
| @verbatim |
| ============================================================================== |
| ##### How to use this driver ##### |
| ============================================================================== |
| [..] |
| (#) Initialize the CAN low level resources by implementing the |
| HAL_CAN_MspInit(): |
| (++) Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE() |
| (++) Configure CAN pins |
| (+++) Enable the clock for the CAN GPIOs |
| (+++) Configure CAN pins as alternate function open-drain |
| (++) In case of using interrupts (e.g. HAL_CAN_ActivateNotification()) |
| (+++) Configure the CAN interrupt priority using |
| HAL_NVIC_SetPriority() |
| (+++) Enable the CAN IRQ handler using HAL_NVIC_EnableIRQ() |
| (+++) In CAN IRQ handler, call HAL_CAN_IRQHandler() |
| |
| (#) Initialize the CAN peripheral using HAL_CAN_Init() function. This |
| function resorts to HAL_CAN_MspInit() for low-level initialization. |
| |
| (#) Configure the reception filters using the following configuration |
| functions: |
| (++) HAL_CAN_ConfigFilter() |
| |
| (#) Start the CAN module using HAL_CAN_Start() function. At this level |
| the node is active on the bus: it receive messages, and can send |
| messages. |
| |
| (#) To manage messages transmission, the following Tx control functions |
| can be used: |
| (++) HAL_CAN_AddTxMessage() to request transmission of a new |
| message. |
| (++) HAL_CAN_AbortTxRequest() to abort transmission of a pending |
| message. |
| (++) HAL_CAN_GetTxMailboxesFreeLevel() to get the number of free Tx |
| mailboxes. |
| (++) HAL_CAN_IsTxMessagePending() to check if a message is pending |
| in a Tx mailbox. |
| (++) HAL_CAN_GetTxTimestamp() to get the timestamp of Tx message |
| sent, if time triggered communication mode is enabled. |
| |
| (#) When a message is received into the CAN Rx FIFOs, it can be retrieved |
| using the HAL_CAN_GetRxMessage() function. The function |
| HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are |
| stored in the Rx Fifo. |
| |
| (#) Calling the HAL_CAN_Stop() function stops the CAN module. |
| |
| (#) The deinitialization is achieved with HAL_CAN_DeInit() function. |
| |
| |
| *** Polling mode operation *** |
| ============================== |
| [..] |
| (#) Reception: |
| (++) Monitor reception of message using HAL_CAN_GetRxFifoFillLevel() |
| until at least one message is received. |
| (++) Then get the message using HAL_CAN_GetRxMessage(). |
| |
| (#) Transmission: |
| (++) Monitor the Tx mailboxes availability until at least one Tx |
| mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel(). |
| (++) Then request transmission of a message using |
| HAL_CAN_AddTxMessage(). |
| |
| |
| *** Interrupt mode operation *** |
| ================================ |
| [..] |
| (#) Notifications are activated using HAL_CAN_ActivateNotification() |
| function. Then, the process can be controlled through the |
| available user callbacks: HAL_CAN_xxxCallback(), using same APIs |
| HAL_CAN_GetRxMessage() and HAL_CAN_AddTxMessage(). |
| |
| (#) Notifications can be deactivated using |
| HAL_CAN_DeactivateNotification() function. |
| |
| (#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and |
| CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig |
| the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and |
| HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options |
| here. |
| (++) Directly get the Rx message in the callback, using |
| HAL_CAN_GetRxMessage(). |
| (++) Or deactivate the notification in the callback without |
| getting the Rx message. The Rx message can then be got later |
| using HAL_CAN_GetRxMessage(). Once the Rx message have been |
| read, the notification can be activated again. |
| |
| |
| *** Sleep mode *** |
| ================== |
| [..] |
| (#) The CAN peripheral can be put in sleep mode (low power), using |
| HAL_CAN_RequestSleep(). The sleep mode will be entered as soon as the |
| current CAN activity (transmission or reception of a CAN frame) will |
| be completed. |
| |
| (#) A notification can be activated to be informed when the sleep mode |
| will be entered. |
| |
| (#) It can be checked if the sleep mode is entered using |
| HAL_CAN_IsSleepActive(). |
| Note that the CAN state (accessible from the API HAL_CAN_GetState()) |
| is HAL_CAN_STATE_SLEEP_PENDING as soon as the sleep mode request is |
| submitted (the sleep mode is not yet entered), and become |
| HAL_CAN_STATE_SLEEP_ACTIVE when the sleep mode is effective. |
| |
| (#) The wake-up from sleep mode can be triggered by two ways: |
| (++) Using HAL_CAN_WakeUp(). When returning from this function, |
| the sleep mode is exited (if return status is HAL_OK). |
| (++) When a start of Rx CAN frame is detected by the CAN peripheral, |
| if automatic wake up mode is enabled. |
| |
| *** Callback registration *** |
| ============================================= |
| |
| The compilation define USE_HAL_CAN_REGISTER_CALLBACKS when set to 1 |
| allows the user to configure dynamically the driver callbacks. |
| Use Function HAL_CAN_RegisterCallback() to register an interrupt callback. |
| |
| Function HAL_CAN_RegisterCallback() allows to register following callbacks: |
| (+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback. |
| (+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback. |
| (+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback. |
| (+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback. |
| (+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback. |
| (+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback. |
| (+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback. |
| (+) RxFifo0FullCallback : Rx Fifo 0 Full Callback. |
| (+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback. |
| (+) RxFifo1FullCallback : Rx Fifo 1 Full Callback. |
| (+) SleepCallback : Sleep Callback. |
| (+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback. |
| (+) ErrorCallback : Error Callback. |
| (+) MspInitCallback : CAN MspInit. |
| (+) MspDeInitCallback : CAN MspDeInit. |
| This function takes as parameters the HAL peripheral handle, the Callback ID |
| and a pointer to the user callback function. |
| |
| Use function HAL_CAN_UnRegisterCallback() to reset a callback to the default |
| weak function. |
| HAL_CAN_UnRegisterCallback takes as parameters the HAL peripheral handle, |
| and the Callback ID. |
| This function allows to reset following callbacks: |
| (+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback. |
| (+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback. |
| (+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback. |
| (+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback. |
| (+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback. |
| (+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback. |
| (+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback. |
| (+) RxFifo0FullCallback : Rx Fifo 0 Full Callback. |
| (+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback. |
| (+) RxFifo1FullCallback : Rx Fifo 1 Full Callback. |
| (+) SleepCallback : Sleep Callback. |
| (+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback. |
| (+) ErrorCallback : Error Callback. |
| (+) MspInitCallback : CAN MspInit. |
| (+) MspDeInitCallback : CAN MspDeInit. |
| |
| By default, after the HAL_CAN_Init() and when the state is HAL_CAN_STATE_RESET, |
| all callbacks are set to the corresponding weak functions: |
| example HAL_CAN_ErrorCallback(). |
| Exception done for MspInit and MspDeInit functions that are |
| reset to the legacy weak function in the HAL_CAN_Init()/ HAL_CAN_DeInit() only when |
| these callbacks are null (not registered beforehand). |
| if not, MspInit or MspDeInit are not null, the HAL_CAN_Init()/ HAL_CAN_DeInit() |
| keep and use the user MspInit/MspDeInit callbacks (registered beforehand) |
| |
| Callbacks can be registered/unregistered in HAL_CAN_STATE_READY state only. |
| Exception done MspInit/MspDeInit that can be registered/unregistered |
| in HAL_CAN_STATE_READY or HAL_CAN_STATE_RESET state, |
| thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit. |
| In that case first register the MspInit/MspDeInit user callbacks |
| using HAL_CAN_RegisterCallback() before calling HAL_CAN_DeInit() |
| or HAL_CAN_Init() function. |
| |
| When The compilation define USE_HAL_CAN_REGISTER_CALLBACKS is set to 0 or |
| not defined, the callback registration feature is not available and all callbacks |
| are set to the corresponding weak functions. |
| |
| @endverbatim |
| ****************************************************************************** |
| */ |
| |
| /* Includes ------------------------------------------------------------------*/ |
| #include "stm32f0xx_hal.h" |
| |
| /** @addtogroup STM32F0xx_HAL_Driver |
| * @{ |
| */ |
| |
| #if defined(CAN) |
| |
| /** @defgroup CAN CAN |
| * @brief CAN driver modules |
| * @{ |
| */ |
| |
| #ifdef HAL_CAN_MODULE_ENABLED |
| |
| #ifdef HAL_CAN_LEGACY_MODULE_ENABLED |
| #error "The CAN driver cannot be used with its legacy, Please enable only one CAN module at once" |
| #endif /* HAL_CAN_LEGACY_MODULE_ENABLED */ |
| |
| /* Private typedef -----------------------------------------------------------*/ |
| /* Private define ------------------------------------------------------------*/ |
| /** @defgroup CAN_Private_Constants CAN Private Constants |
| * @{ |
| */ |
| #define CAN_TIMEOUT_VALUE 10U |
| /** |
| * @} |
| */ |
| /* Private macro -------------------------------------------------------------*/ |
| /* Private variables ---------------------------------------------------------*/ |
| /* Private function prototypes -----------------------------------------------*/ |
| /* Exported functions --------------------------------------------------------*/ |
| |
| /** @defgroup CAN_Exported_Functions CAN Exported Functions |
| * @{ |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group1 Initialization and de-initialization functions |
| * @brief Initialization and Configuration functions |
| * |
| @verbatim |
| ============================================================================== |
| ##### Initialization and de-initialization functions ##### |
| ============================================================================== |
| [..] This section provides functions allowing to: |
| (+) HAL_CAN_Init : Initialize and configure the CAN. |
| (+) HAL_CAN_DeInit : De-initialize the CAN. |
| (+) HAL_CAN_MspInit : Initialize the CAN MSP. |
| (+) HAL_CAN_MspDeInit : DeInitialize the CAN MSP. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Initializes the CAN peripheral according to the specified |
| * parameters in the CAN_InitStruct. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_Init(CAN_HandleTypeDef *hcan) |
| { |
| uint32_t tickstart; |
| |
| /* Check CAN handle */ |
| if (hcan == NULL) |
| { |
| return HAL_ERROR; |
| } |
| |
| /* Check the parameters */ |
| assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TimeTriggeredMode)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoBusOff)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoWakeUp)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoRetransmission)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ReceiveFifoLocked)); |
| assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TransmitFifoPriority)); |
| assert_param(IS_CAN_MODE(hcan->Init.Mode)); |
| assert_param(IS_CAN_SJW(hcan->Init.SyncJumpWidth)); |
| assert_param(IS_CAN_BS1(hcan->Init.TimeSeg1)); |
| assert_param(IS_CAN_BS2(hcan->Init.TimeSeg2)); |
| assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler)); |
| |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| if (hcan->State == HAL_CAN_STATE_RESET) |
| { |
| /* Reset callbacks to legacy functions */ |
| hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback; /* Legacy weak RxFifo0MsgPendingCallback */ |
| hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback; /* Legacy weak RxFifo0FullCallback */ |
| hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback; /* Legacy weak RxFifo1MsgPendingCallback */ |
| hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback; /* Legacy weak RxFifo1FullCallback */ |
| hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback; /* Legacy weak TxMailbox0CompleteCallback */ |
| hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback; /* Legacy weak TxMailbox1CompleteCallback */ |
| hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback; /* Legacy weak TxMailbox2CompleteCallback */ |
| hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback; /* Legacy weak TxMailbox0AbortCallback */ |
| hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback; /* Legacy weak TxMailbox1AbortCallback */ |
| hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback; /* Legacy weak TxMailbox2AbortCallback */ |
| hcan->SleepCallback = HAL_CAN_SleepCallback; /* Legacy weak SleepCallback */ |
| hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback; /* Legacy weak WakeUpFromRxMsgCallback */ |
| hcan->ErrorCallback = HAL_CAN_ErrorCallback; /* Legacy weak ErrorCallback */ |
| |
| if (hcan->MspInitCallback == NULL) |
| { |
| hcan->MspInitCallback = HAL_CAN_MspInit; /* Legacy weak MspInit */ |
| } |
| |
| /* Init the low level hardware: CLOCK, NVIC */ |
| hcan->MspInitCallback(hcan); |
| } |
| |
| #else |
| if (hcan->State == HAL_CAN_STATE_RESET) |
| { |
| /* Init the low level hardware: CLOCK, NVIC */ |
| HAL_CAN_MspInit(hcan); |
| } |
| #endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ |
| |
| /* Request initialisation */ |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait initialisation acknowledge */ |
| while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U) |
| { |
| if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; |
| |
| /* Change CAN state */ |
| hcan->State = HAL_CAN_STATE_ERROR; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /* Exit from sleep mode */ |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Check Sleep mode leave acknowledge */ |
| while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) |
| { |
| if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; |
| |
| /* Change CAN state */ |
| hcan->State = HAL_CAN_STATE_ERROR; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /* Set the time triggered communication mode */ |
| if (hcan->Init.TimeTriggeredMode == ENABLE) |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_TTCM); |
| } |
| else |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TTCM); |
| } |
| |
| /* Set the automatic bus-off management */ |
| if (hcan->Init.AutoBusOff == ENABLE) |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_ABOM); |
| } |
| else |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_ABOM); |
| } |
| |
| /* Set the automatic wake-up mode */ |
| if (hcan->Init.AutoWakeUp == ENABLE) |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_AWUM); |
| } |
| else |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_AWUM); |
| } |
| |
| /* Set the automatic retransmission */ |
| if (hcan->Init.AutoRetransmission == ENABLE) |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_NART); |
| } |
| else |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_NART); |
| } |
| |
| /* Set the receive FIFO locked mode */ |
| if (hcan->Init.ReceiveFifoLocked == ENABLE) |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_RFLM); |
| } |
| else |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_RFLM); |
| } |
| |
| /* Set the transmit FIFO priority */ |
| if (hcan->Init.TransmitFifoPriority == ENABLE) |
| { |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_TXFP); |
| } |
| else |
| { |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TXFP); |
| } |
| |
| /* Set the bit timing register */ |
| WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode | |
| hcan->Init.SyncJumpWidth | |
| hcan->Init.TimeSeg1 | |
| hcan->Init.TimeSeg2 | |
| (hcan->Init.Prescaler - 1U))); |
| |
| /* Initialize the error code */ |
| hcan->ErrorCode = HAL_CAN_ERROR_NONE; |
| |
| /* Initialize the CAN state */ |
| hcan->State = HAL_CAN_STATE_READY; |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Deinitializes the CAN peripheral registers to their default |
| * reset values. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_DeInit(CAN_HandleTypeDef *hcan) |
| { |
| /* Check CAN handle */ |
| if (hcan == NULL) |
| { |
| return HAL_ERROR; |
| } |
| |
| /* Check the parameters */ |
| assert_param(IS_CAN_ALL_INSTANCE(hcan->Instance)); |
| |
| /* Stop the CAN module */ |
| (void)HAL_CAN_Stop(hcan); |
| |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| if (hcan->MspDeInitCallback == NULL) |
| { |
| hcan->MspDeInitCallback = HAL_CAN_MspDeInit; /* Legacy weak MspDeInit */ |
| } |
| |
| /* DeInit the low level hardware: CLOCK, NVIC */ |
| hcan->MspDeInitCallback(hcan); |
| |
| #else |
| /* DeInit the low level hardware: CLOCK, NVIC */ |
| HAL_CAN_MspDeInit(hcan); |
| #endif /* (USE_HAL_CAN_REGISTER_CALLBACKS) */ |
| |
| /* Reset the CAN peripheral */ |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_RESET); |
| |
| /* Reset the CAN ErrorCode */ |
| hcan->ErrorCode = HAL_CAN_ERROR_NONE; |
| |
| /* Change CAN state */ |
| hcan->State = HAL_CAN_STATE_RESET; |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| |
| /** |
| * @brief Initializes the CAN MSP. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_MspInit could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief DeInitializes the CAN MSP. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_MspDeInit could be implemented in the user file |
| */ |
| } |
| |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /** |
| * @brief Register a CAN CallBack. |
| * To be used instead of the weak predefined callback |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for CAN module |
| * @param CallbackID ID of the callback to be registered |
| * This parameter can be one of the following values: |
| * @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID |
| * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID |
| * @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID |
| * @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID |
| * @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID |
| * @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID |
| * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID |
| * @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID |
| * @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID |
| * @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID |
| * @param pCallback pointer to the Callback function |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID, |
| void (* pCallback)(CAN_HandleTypeDef *_hcan)) |
| { |
| HAL_StatusTypeDef status = HAL_OK; |
| |
| if (pCallback == NULL) |
| { |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| return HAL_ERROR; |
| } |
| |
| if (hcan->State == HAL_CAN_STATE_READY) |
| { |
| switch (CallbackID) |
| { |
| case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID : |
| hcan->TxMailbox0CompleteCallback = pCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID : |
| hcan->TxMailbox1CompleteCallback = pCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID : |
| hcan->TxMailbox2CompleteCallback = pCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID : |
| hcan->TxMailbox0AbortCallback = pCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID : |
| hcan->TxMailbox1AbortCallback = pCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID : |
| hcan->TxMailbox2AbortCallback = pCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID : |
| hcan->RxFifo0MsgPendingCallback = pCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO0_FULL_CB_ID : |
| hcan->RxFifo0FullCallback = pCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID : |
| hcan->RxFifo1MsgPendingCallback = pCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO1_FULL_CB_ID : |
| hcan->RxFifo1FullCallback = pCallback; |
| break; |
| |
| case HAL_CAN_SLEEP_CB_ID : |
| hcan->SleepCallback = pCallback; |
| break; |
| |
| case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID : |
| hcan->WakeUpFromRxMsgCallback = pCallback; |
| break; |
| |
| case HAL_CAN_ERROR_CB_ID : |
| hcan->ErrorCallback = pCallback; |
| break; |
| |
| case HAL_CAN_MSPINIT_CB_ID : |
| hcan->MspInitCallback = pCallback; |
| break; |
| |
| case HAL_CAN_MSPDEINIT_CB_ID : |
| hcan->MspDeInitCallback = pCallback; |
| break; |
| |
| default : |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| break; |
| } |
| } |
| else if (hcan->State == HAL_CAN_STATE_RESET) |
| { |
| switch (CallbackID) |
| { |
| case HAL_CAN_MSPINIT_CB_ID : |
| hcan->MspInitCallback = pCallback; |
| break; |
| |
| case HAL_CAN_MSPDEINIT_CB_ID : |
| hcan->MspDeInitCallback = pCallback; |
| break; |
| |
| default : |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| break; |
| } |
| } |
| else |
| { |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| } |
| |
| return status; |
| } |
| |
| /** |
| * @brief Unregister a CAN CallBack. |
| * CAN callback is redirected to the weak predefined callback |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for CAN module |
| * @param CallbackID ID of the callback to be unregistered |
| * This parameter can be one of the following values: |
| * @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID |
| * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID |
| * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID |
| * @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID |
| * @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID |
| * @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID |
| * @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID |
| * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID |
| * @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID |
| * @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID |
| * @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID) |
| { |
| HAL_StatusTypeDef status = HAL_OK; |
| |
| if (hcan->State == HAL_CAN_STATE_READY) |
| { |
| switch (CallbackID) |
| { |
| case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID : |
| hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID : |
| hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID : |
| hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID : |
| hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID : |
| hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback; |
| break; |
| |
| case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID : |
| hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID : |
| hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO0_FULL_CB_ID : |
| hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID : |
| hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback; |
| break; |
| |
| case HAL_CAN_RX_FIFO1_FULL_CB_ID : |
| hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback; |
| break; |
| |
| case HAL_CAN_SLEEP_CB_ID : |
| hcan->SleepCallback = HAL_CAN_SleepCallback; |
| break; |
| |
| case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID : |
| hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback; |
| break; |
| |
| case HAL_CAN_ERROR_CB_ID : |
| hcan->ErrorCallback = HAL_CAN_ErrorCallback; |
| break; |
| |
| case HAL_CAN_MSPINIT_CB_ID : |
| hcan->MspInitCallback = HAL_CAN_MspInit; |
| break; |
| |
| case HAL_CAN_MSPDEINIT_CB_ID : |
| hcan->MspDeInitCallback = HAL_CAN_MspDeInit; |
| break; |
| |
| default : |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| break; |
| } |
| } |
| else if (hcan->State == HAL_CAN_STATE_RESET) |
| { |
| switch (CallbackID) |
| { |
| case HAL_CAN_MSPINIT_CB_ID : |
| hcan->MspInitCallback = HAL_CAN_MspInit; |
| break; |
| |
| case HAL_CAN_MSPDEINIT_CB_ID : |
| hcan->MspDeInitCallback = HAL_CAN_MspDeInit; |
| break; |
| |
| default : |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| break; |
| } |
| } |
| else |
| { |
| /* Update the error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK; |
| |
| /* Return error status */ |
| status = HAL_ERROR; |
| } |
| |
| return status; |
| } |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group2 Configuration functions |
| * @brief Configuration functions. |
| * |
| @verbatim |
| ============================================================================== |
| ##### Configuration functions ##### |
| ============================================================================== |
| [..] This section provides functions allowing to: |
| (+) HAL_CAN_ConfigFilter : Configure the CAN reception filters |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Configures the CAN reception filter according to the specified |
| * parameters in the CAN_FilterInitStruct. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param sFilterConfig pointer to a CAN_FilterTypeDef structure that |
| * contains the filter configuration information. |
| * @retval None |
| */ |
| HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig) |
| { |
| uint32_t filternbrbitpos; |
| CAN_TypeDef *can_ip = hcan->Instance; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check the parameters */ |
| assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdHigh)); |
| assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdLow)); |
| assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdHigh)); |
| assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdLow)); |
| assert_param(IS_CAN_FILTER_MODE(sFilterConfig->FilterMode)); |
| assert_param(IS_CAN_FILTER_SCALE(sFilterConfig->FilterScale)); |
| assert_param(IS_CAN_FILTER_FIFO(sFilterConfig->FilterFIFOAssignment)); |
| assert_param(IS_CAN_FILTER_ACTIVATION(sFilterConfig->FilterActivation)); |
| |
| /* CAN is single instance with 14 dedicated filters banks */ |
| |
| /* Check the parameters */ |
| assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank)); |
| |
| /* Initialisation mode for the filter */ |
| SET_BIT(can_ip->FMR, CAN_FMR_FINIT); |
| |
| /* Convert filter number into bit position */ |
| filternbrbitpos = (uint32_t)1 << (sFilterConfig->FilterBank & 0x1FU); |
| |
| /* Filter Deactivation */ |
| CLEAR_BIT(can_ip->FA1R, filternbrbitpos); |
| |
| /* Filter Scale */ |
| if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT) |
| { |
| /* 16-bit scale for the filter */ |
| CLEAR_BIT(can_ip->FS1R, filternbrbitpos); |
| |
| /* First 16-bit identifier and First 16-bit mask */ |
| /* Or First 16-bit identifier and Second 16-bit identifier */ |
| can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 = |
| ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) | |
| (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); |
| |
| /* Second 16-bit identifier and Second 16-bit mask */ |
| /* Or Third 16-bit identifier and Fourth 16-bit identifier */ |
| can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 = |
| ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | |
| (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh); |
| } |
| |
| if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT) |
| { |
| /* 32-bit scale for the filter */ |
| SET_BIT(can_ip->FS1R, filternbrbitpos); |
| |
| /* 32-bit identifier or First 32-bit identifier */ |
| can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 = |
| ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) | |
| (0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow); |
| |
| /* 32-bit mask or Second 32-bit identifier */ |
| can_ip->sFilterRegister[sFilterConfig->FilterBank].FR2 = |
| ((0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) | |
| (0x0000FFFFU & (uint32_t)sFilterConfig->FilterMaskIdLow); |
| } |
| |
| /* Filter Mode */ |
| if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK) |
| { |
| /* Id/Mask mode for the filter*/ |
| CLEAR_BIT(can_ip->FM1R, filternbrbitpos); |
| } |
| else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */ |
| { |
| /* Identifier list mode for the filter*/ |
| SET_BIT(can_ip->FM1R, filternbrbitpos); |
| } |
| |
| /* Filter FIFO assignment */ |
| if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0) |
| { |
| /* FIFO 0 assignation for the filter */ |
| CLEAR_BIT(can_ip->FFA1R, filternbrbitpos); |
| } |
| else |
| { |
| /* FIFO 1 assignation for the filter */ |
| SET_BIT(can_ip->FFA1R, filternbrbitpos); |
| } |
| |
| /* Filter activation */ |
| if (sFilterConfig->FilterActivation == CAN_FILTER_ENABLE) |
| { |
| SET_BIT(can_ip->FA1R, filternbrbitpos); |
| } |
| |
| /* Leave the initialisation mode for the filter */ |
| CLEAR_BIT(can_ip->FMR, CAN_FMR_FINIT); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group3 Control functions |
| * @brief Control functions |
| * |
| @verbatim |
| ============================================================================== |
| ##### Control functions ##### |
| ============================================================================== |
| [..] This section provides functions allowing to: |
| (+) HAL_CAN_Start : Start the CAN module |
| (+) HAL_CAN_Stop : Stop the CAN module |
| (+) HAL_CAN_RequestSleep : Request sleep mode entry. |
| (+) HAL_CAN_WakeUp : Wake up from sleep mode. |
| (+) HAL_CAN_IsSleepActive : Check is sleep mode is active. |
| (+) HAL_CAN_AddTxMessage : Add a message to the Tx mailboxes |
| and activate the corresponding |
| transmission request |
| (+) HAL_CAN_AbortTxRequest : Abort transmission request |
| (+) HAL_CAN_GetTxMailboxesFreeLevel : Return Tx mailboxes free level |
| (+) HAL_CAN_IsTxMessagePending : Check if a transmission request is |
| pending on the selected Tx mailbox |
| (+) HAL_CAN_GetRxMessage : Get a CAN frame from the Rx FIFO |
| (+) HAL_CAN_GetRxFifoFillLevel : Return Rx FIFO fill level |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Start the CAN module. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan) |
| { |
| uint32_t tickstart; |
| |
| if (hcan->State == HAL_CAN_STATE_READY) |
| { |
| /* Change CAN peripheral state */ |
| hcan->State = HAL_CAN_STATE_LISTENING; |
| |
| /* Request leave initialisation */ |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait the acknowledge */ |
| while ((hcan->Instance->MSR & CAN_MSR_INAK) != 0U) |
| { |
| /* Check for the Timeout */ |
| if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; |
| |
| /* Change CAN state */ |
| hcan->State = HAL_CAN_STATE_ERROR; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /* Reset the CAN ErrorCode */ |
| hcan->ErrorCode = HAL_CAN_ERROR_NONE; |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_READY; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Stop the CAN module and enable access to configuration registers. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan) |
| { |
| uint32_t tickstart; |
| |
| if (hcan->State == HAL_CAN_STATE_LISTENING) |
| { |
| /* Request initialisation */ |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ); |
| |
| /* Get tick */ |
| tickstart = HAL_GetTick(); |
| |
| /* Wait the acknowledge */ |
| while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U) |
| { |
| /* Check for the Timeout */ |
| if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; |
| |
| /* Change CAN state */ |
| hcan->State = HAL_CAN_STATE_ERROR; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /* Exit from sleep mode */ |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); |
| |
| /* Change CAN peripheral state */ |
| hcan->State = HAL_CAN_STATE_READY; |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_STARTED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Request the sleep mode (low power) entry. |
| * When returning from this function, Sleep mode will be entered |
| * as soon as the current CAN activity (transmission or reception |
| * of a CAN frame) has been completed. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status. |
| */ |
| HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Request Sleep mode */ |
| SET_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| /* Return function status */ |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Wake up from sleep mode. |
| * When returning with HAL_OK status from this function, Sleep mode |
| * is exited. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status. |
| */ |
| HAL_StatusTypeDef HAL_CAN_WakeUp(CAN_HandleTypeDef *hcan) |
| { |
| __IO uint32_t count = 0; |
| uint32_t timeout = 1000000U; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Wake up request */ |
| CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP); |
| |
| /* Wait sleep mode is exited */ |
| do |
| { |
| /* Increment counter */ |
| count++; |
| |
| /* Check if timeout is reached */ |
| if (count > timeout) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT; |
| |
| return HAL_ERROR; |
| } |
| } |
| while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Check is sleep mode is active. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval Status |
| * - 0 : Sleep mode is not active. |
| * - 1 : Sleep mode is active. |
| */ |
| uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan) |
| { |
| uint32_t status = 0U; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check Sleep mode */ |
| if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) |
| { |
| status = 1U; |
| } |
| } |
| |
| /* Return function status */ |
| return status; |
| } |
| |
| /** |
| * @brief Add a message to the first free Tx mailbox and activate the |
| * corresponding transmission request. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param pHeader pointer to a CAN_TxHeaderTypeDef structure. |
| * @param aData array containing the payload of the Tx frame. |
| * @param pTxMailbox pointer to a variable where the function will return |
| * the TxMailbox used to store the Tx message. |
| * This parameter can be a value of @arg CAN_Tx_Mailboxes. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader, |
| const uint8_t aData[], uint32_t *pTxMailbox) |
| { |
| uint32_t transmitmailbox; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| uint32_t tsr = READ_REG(hcan->Instance->TSR); |
| |
| /* Check the parameters */ |
| assert_param(IS_CAN_IDTYPE(pHeader->IDE)); |
| assert_param(IS_CAN_RTR(pHeader->RTR)); |
| assert_param(IS_CAN_DLC(pHeader->DLC)); |
| if (pHeader->IDE == CAN_ID_STD) |
| { |
| assert_param(IS_CAN_STDID(pHeader->StdId)); |
| } |
| else |
| { |
| assert_param(IS_CAN_EXTID(pHeader->ExtId)); |
| } |
| assert_param(IS_FUNCTIONAL_STATE(pHeader->TransmitGlobalTime)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check that all the Tx mailboxes are not full */ |
| if (((tsr & CAN_TSR_TME0) != 0U) || |
| ((tsr & CAN_TSR_TME1) != 0U) || |
| ((tsr & CAN_TSR_TME2) != 0U)) |
| { |
| /* Select an empty transmit mailbox */ |
| transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos; |
| |
| /* Check transmit mailbox value */ |
| if (transmitmailbox > 2U) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_INTERNAL; |
| |
| return HAL_ERROR; |
| } |
| |
| /* Store the Tx mailbox */ |
| *pTxMailbox = (uint32_t)1 << transmitmailbox; |
| |
| /* Set up the Id */ |
| if (pHeader->IDE == CAN_ID_STD) |
| { |
| hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) | |
| pHeader->RTR); |
| } |
| else |
| { |
| hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) | |
| pHeader->IDE | |
| pHeader->RTR); |
| } |
| |
| /* Set up the DLC */ |
| hcan->Instance->sTxMailBox[transmitmailbox].TDTR = (pHeader->DLC); |
| |
| /* Set up the Transmit Global Time mode */ |
| if (pHeader->TransmitGlobalTime == ENABLE) |
| { |
| SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT); |
| } |
| |
| /* Set up the data field */ |
| WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR, |
| ((uint32_t)aData[7] << CAN_TDH0R_DATA7_Pos) | |
| ((uint32_t)aData[6] << CAN_TDH0R_DATA6_Pos) | |
| ((uint32_t)aData[5] << CAN_TDH0R_DATA5_Pos) | |
| ((uint32_t)aData[4] << CAN_TDH0R_DATA4_Pos)); |
| WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR, |
| ((uint32_t)aData[3] << CAN_TDL0R_DATA3_Pos) | |
| ((uint32_t)aData[2] << CAN_TDL0R_DATA2_Pos) | |
| ((uint32_t)aData[1] << CAN_TDL0R_DATA1_Pos) | |
| ((uint32_t)aData[0] << CAN_TDL0R_DATA0_Pos)); |
| |
| /* Request transmission */ |
| SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; |
| |
| return HAL_ERROR; |
| } |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Abort transmission requests |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param TxMailboxes List of the Tx Mailboxes to abort. |
| * This parameter can be any combination of @arg CAN_Tx_Mailboxes. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check Tx Mailbox 0 */ |
| if ((TxMailboxes & CAN_TX_MAILBOX0) != 0U) |
| { |
| /* Add cancellation request for Tx Mailbox 0 */ |
| SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ0); |
| } |
| |
| /* Check Tx Mailbox 1 */ |
| if ((TxMailboxes & CAN_TX_MAILBOX1) != 0U) |
| { |
| /* Add cancellation request for Tx Mailbox 1 */ |
| SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ1); |
| } |
| |
| /* Check Tx Mailbox 2 */ |
| if ((TxMailboxes & CAN_TX_MAILBOX2) != 0U) |
| { |
| /* Add cancellation request for Tx Mailbox 2 */ |
| SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ2); |
| } |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Return Tx Mailboxes free level: number of free Tx Mailboxes. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval Number of free Tx Mailboxes. |
| */ |
| uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan) |
| { |
| uint32_t freelevel = 0U; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check Tx Mailbox 0 status */ |
| if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U) |
| { |
| freelevel++; |
| } |
| |
| /* Check Tx Mailbox 1 status */ |
| if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U) |
| { |
| freelevel++; |
| } |
| |
| /* Check Tx Mailbox 2 status */ |
| if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U) |
| { |
| freelevel++; |
| } |
| } |
| |
| /* Return Tx Mailboxes free level */ |
| return freelevel; |
| } |
| |
| /** |
| * @brief Check if a transmission request is pending on the selected Tx |
| * Mailboxes. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param TxMailboxes List of Tx Mailboxes to check. |
| * This parameter can be any combination of @arg CAN_Tx_Mailboxes. |
| * @retval Status |
| * - 0 : No pending transmission request on any selected Tx Mailboxes. |
| * - 1 : Pending transmission request on at least one of the selected |
| * Tx Mailbox. |
| */ |
| uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes) |
| { |
| uint32_t status = 0U; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check pending transmission request on the selected Tx Mailboxes */ |
| if ((hcan->Instance->TSR & (TxMailboxes << CAN_TSR_TME0_Pos)) != (TxMailboxes << CAN_TSR_TME0_Pos)) |
| { |
| status = 1U; |
| } |
| } |
| |
| /* Return status */ |
| return status; |
| } |
| |
| /** |
| * @brief Return timestamp of Tx message sent, if time triggered communication |
| mode is enabled. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param TxMailbox Tx Mailbox where the timestamp of message sent will be |
| * read. |
| * This parameter can be one value of @arg CAN_Tx_Mailboxes. |
| * @retval Timestamp of message sent from Tx Mailbox. |
| */ |
| uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox) |
| { |
| uint32_t timestamp = 0U; |
| uint32_t transmitmailbox; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_TX_MAILBOX(TxMailbox)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Select the Tx mailbox */ |
| /* Select the Tx mailbox */ |
| if (TxMailbox == CAN_TX_MAILBOX0) |
| { |
| transmitmailbox = 0U; |
| } |
| else if (TxMailbox == CAN_TX_MAILBOX1) |
| { |
| transmitmailbox = 1U; |
| } |
| else /* (TxMailbox == CAN_TX_MAILBOX2) */ |
| { |
| transmitmailbox = 2U; |
| } |
| |
| /* Get timestamp */ |
| timestamp = (hcan->Instance->sTxMailBox[transmitmailbox].TDTR & CAN_TDT0R_TIME) >> CAN_TDT0R_TIME_Pos; |
| } |
| |
| /* Return the timestamp */ |
| return timestamp; |
| } |
| |
| /** |
| * @brief Get an CAN frame from the Rx FIFO zone into the message RAM. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param RxFifo Fifo number of the received message to be read. |
| * This parameter can be a value of @arg CAN_receive_FIFO_number. |
| * @param pHeader pointer to a CAN_RxHeaderTypeDef structure where the header |
| * of the Rx frame will be stored. |
| * @param aData array where the payload of the Rx frame will be stored. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, |
| CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| assert_param(IS_CAN_RX_FIFO(RxFifo)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check the Rx FIFO */ |
| if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */ |
| { |
| /* Check that the Rx FIFO 0 is not empty */ |
| if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) == 0U) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; |
| |
| return HAL_ERROR; |
| } |
| } |
| else /* Rx element is assigned to Rx FIFO 1 */ |
| { |
| /* Check that the Rx FIFO 1 is not empty */ |
| if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) == 0U) |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_PARAM; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /* Get the header */ |
| pHeader->IDE = CAN_RI0R_IDE & hcan->Instance->sFIFOMailBox[RxFifo].RIR; |
| if (pHeader->IDE == CAN_ID_STD) |
| { |
| pHeader->StdId = (CAN_RI0R_STID & hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_TI0R_STID_Pos; |
| } |
| else |
| { |
| pHeader->ExtId = ((CAN_RI0R_EXID | CAN_RI0R_STID) & |
| hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_RI0R_EXID_Pos; |
| } |
| pHeader->RTR = (CAN_RI0R_RTR & hcan->Instance->sFIFOMailBox[RxFifo].RIR); |
| pHeader->DLC = (CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos; |
| pHeader->FilterMatchIndex = (CAN_RDT0R_FMI & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_FMI_Pos; |
| pHeader->Timestamp = (CAN_RDT0R_TIME & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_TIME_Pos; |
| |
| /* Get the data */ |
| aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos); |
| aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos); |
| aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos); |
| aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos); |
| aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos); |
| aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos); |
| aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos); |
| aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos); |
| |
| /* Release the FIFO */ |
| if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */ |
| { |
| /* Release RX FIFO 0 */ |
| SET_BIT(hcan->Instance->RF0R, CAN_RF0R_RFOM0); |
| } |
| else /* Rx element is assigned to Rx FIFO 1 */ |
| { |
| /* Release RX FIFO 1 */ |
| SET_BIT(hcan->Instance->RF1R, CAN_RF1R_RFOM1); |
| } |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Return Rx FIFO fill level. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param RxFifo Rx FIFO. |
| * This parameter can be a value of @arg CAN_receive_FIFO_number. |
| * @retval Number of messages available in Rx FIFO. |
| */ |
| uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo) |
| { |
| uint32_t filllevel = 0U; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_RX_FIFO(RxFifo)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| if (RxFifo == CAN_RX_FIFO0) |
| { |
| filllevel = hcan->Instance->RF0R & CAN_RF0R_FMP0; |
| } |
| else /* RxFifo == CAN_RX_FIFO1 */ |
| { |
| filllevel = hcan->Instance->RF1R & CAN_RF1R_FMP1; |
| } |
| } |
| |
| /* Return Rx FIFO fill level */ |
| return filllevel; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group4 Interrupts management |
| * @brief Interrupts management |
| * |
| @verbatim |
| ============================================================================== |
| ##### Interrupts management ##### |
| ============================================================================== |
| [..] This section provides functions allowing to: |
| (+) HAL_CAN_ActivateNotification : Enable interrupts |
| (+) HAL_CAN_DeactivateNotification : Disable interrupts |
| (+) HAL_CAN_IRQHandler : Handles CAN interrupt request |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Enable interrupts. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param ActiveITs indicates which interrupts will be enabled. |
| * This parameter can be any combination of @arg CAN_Interrupts. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_IT(ActiveITs)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Enable the selected interrupts */ |
| __HAL_CAN_ENABLE_IT(hcan, ActiveITs); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Disable interrupts. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @param InactiveITs indicates which interrupts will be disabled. |
| * This parameter can be any combination of @arg CAN_Interrupts. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| /* Check function parameters */ |
| assert_param(IS_CAN_IT(InactiveITs)); |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Disable the selected interrupts */ |
| __HAL_CAN_DISABLE_IT(hcan, InactiveITs); |
| |
| /* Return function status */ |
| return HAL_OK; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| return HAL_ERROR; |
| } |
| } |
| |
| /** |
| * @brief Handles CAN interrupt request |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| void HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan) |
| { |
| uint32_t errorcode = HAL_CAN_ERROR_NONE; |
| uint32_t interrupts = READ_REG(hcan->Instance->IER); |
| uint32_t msrflags = READ_REG(hcan->Instance->MSR); |
| uint32_t tsrflags = READ_REG(hcan->Instance->TSR); |
| uint32_t rf0rflags = READ_REG(hcan->Instance->RF0R); |
| uint32_t rf1rflags = READ_REG(hcan->Instance->RF1R); |
| uint32_t esrflags = READ_REG(hcan->Instance->ESR); |
| |
| /* Transmit Mailbox empty interrupt management *****************************/ |
| if ((interrupts & CAN_IT_TX_MAILBOX_EMPTY) != 0U) |
| { |
| /* Transmit Mailbox 0 management *****************************************/ |
| if ((tsrflags & CAN_TSR_RQCP0) != 0U) |
| { |
| /* Clear the Transmission Complete flag (and TXOK0,ALST0,TERR0 bits) */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP0); |
| |
| if ((tsrflags & CAN_TSR_TXOK0) != 0U) |
| { |
| /* Transmission Mailbox 0 complete callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox0CompleteCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox0CompleteCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| else |
| { |
| if ((tsrflags & CAN_TSR_ALST0) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_ALST0; |
| } |
| else if ((tsrflags & CAN_TSR_TERR0) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_TERR0; |
| } |
| else |
| { |
| /* Transmission Mailbox 0 abort callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox0AbortCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox0AbortCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| } |
| |
| /* Transmit Mailbox 1 management *****************************************/ |
| if ((tsrflags & CAN_TSR_RQCP1) != 0U) |
| { |
| /* Clear the Transmission Complete flag (and TXOK1,ALST1,TERR1 bits) */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP1); |
| |
| if ((tsrflags & CAN_TSR_TXOK1) != 0U) |
| { |
| /* Transmission Mailbox 1 complete callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox1CompleteCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox1CompleteCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| else |
| { |
| if ((tsrflags & CAN_TSR_ALST1) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_ALST1; |
| } |
| else if ((tsrflags & CAN_TSR_TERR1) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_TERR1; |
| } |
| else |
| { |
| /* Transmission Mailbox 1 abort callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox1AbortCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox1AbortCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| } |
| |
| /* Transmit Mailbox 2 management *****************************************/ |
| if ((tsrflags & CAN_TSR_RQCP2) != 0U) |
| { |
| /* Clear the Transmission Complete flag (and TXOK2,ALST2,TERR2 bits) */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP2); |
| |
| if ((tsrflags & CAN_TSR_TXOK2) != 0U) |
| { |
| /* Transmission Mailbox 2 complete callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox2CompleteCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox2CompleteCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| else |
| { |
| if ((tsrflags & CAN_TSR_ALST2) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_ALST2; |
| } |
| else if ((tsrflags & CAN_TSR_TERR2) != 0U) |
| { |
| /* Update error code */ |
| errorcode |= HAL_CAN_ERROR_TX_TERR2; |
| } |
| else |
| { |
| /* Transmission Mailbox 2 abort callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->TxMailbox2AbortCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_TxMailbox2AbortCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| } |
| } |
| |
| /* Receive FIFO 0 overrun interrupt management *****************************/ |
| if ((interrupts & CAN_IT_RX_FIFO0_OVERRUN) != 0U) |
| { |
| if ((rf0rflags & CAN_RF0R_FOVR0) != 0U) |
| { |
| /* Set CAN error code to Rx Fifo 0 overrun error */ |
| errorcode |= HAL_CAN_ERROR_RX_FOV0; |
| |
| /* Clear FIFO0 Overrun Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0); |
| } |
| } |
| |
| /* Receive FIFO 0 full interrupt management ********************************/ |
| if ((interrupts & CAN_IT_RX_FIFO0_FULL) != 0U) |
| { |
| if ((rf0rflags & CAN_RF0R_FULL0) != 0U) |
| { |
| /* Clear FIFO 0 full Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF0); |
| |
| /* Receive FIFO 0 full Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->RxFifo0FullCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_RxFifo0FullCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* Receive FIFO 0 message pending interrupt management *********************/ |
| if ((interrupts & CAN_IT_RX_FIFO0_MSG_PENDING) != 0U) |
| { |
| /* Check if message is still pending */ |
| if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) != 0U) |
| { |
| /* Receive FIFO 0 message pending Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->RxFifo0MsgPendingCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_RxFifo0MsgPendingCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* Receive FIFO 1 overrun interrupt management *****************************/ |
| if ((interrupts & CAN_IT_RX_FIFO1_OVERRUN) != 0U) |
| { |
| if ((rf1rflags & CAN_RF1R_FOVR1) != 0U) |
| { |
| /* Set CAN error code to Rx Fifo 1 overrun error */ |
| errorcode |= HAL_CAN_ERROR_RX_FOV1; |
| |
| /* Clear FIFO1 Overrun Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1); |
| } |
| } |
| |
| /* Receive FIFO 1 full interrupt management ********************************/ |
| if ((interrupts & CAN_IT_RX_FIFO1_FULL) != 0U) |
| { |
| if ((rf1rflags & CAN_RF1R_FULL1) != 0U) |
| { |
| /* Clear FIFO 1 full Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF1); |
| |
| /* Receive FIFO 1 full Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->RxFifo1FullCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_RxFifo1FullCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* Receive FIFO 1 message pending interrupt management *********************/ |
| if ((interrupts & CAN_IT_RX_FIFO1_MSG_PENDING) != 0U) |
| { |
| /* Check if message is still pending */ |
| if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) != 0U) |
| { |
| /* Receive FIFO 1 message pending Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->RxFifo1MsgPendingCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_RxFifo1MsgPendingCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* Sleep interrupt management *********************************************/ |
| if ((interrupts & CAN_IT_SLEEP_ACK) != 0U) |
| { |
| if ((msrflags & CAN_MSR_SLAKI) != 0U) |
| { |
| /* Clear Sleep interrupt Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_SLAKI); |
| |
| /* Sleep Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->SleepCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_SleepCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* WakeUp interrupt management *********************************************/ |
| if ((interrupts & CAN_IT_WAKEUP) != 0U) |
| { |
| if ((msrflags & CAN_MSR_WKUI) != 0U) |
| { |
| /* Clear WakeUp Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_WKU); |
| |
| /* WakeUp Callback */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->WakeUpFromRxMsgCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_WakeUpFromRxMsgCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /* Error interrupts management *********************************************/ |
| if ((interrupts & CAN_IT_ERROR) != 0U) |
| { |
| if ((msrflags & CAN_MSR_ERRI) != 0U) |
| { |
| /* Check Error Warning Flag */ |
| if (((interrupts & CAN_IT_ERROR_WARNING) != 0U) && |
| ((esrflags & CAN_ESR_EWGF) != 0U)) |
| { |
| /* Set CAN error code to Error Warning */ |
| errorcode |= HAL_CAN_ERROR_EWG; |
| |
| /* No need for clear of Error Warning Flag as read-only */ |
| } |
| |
| /* Check Error Passive Flag */ |
| if (((interrupts & CAN_IT_ERROR_PASSIVE) != 0U) && |
| ((esrflags & CAN_ESR_EPVF) != 0U)) |
| { |
| /* Set CAN error code to Error Passive */ |
| errorcode |= HAL_CAN_ERROR_EPV; |
| |
| /* No need for clear of Error Passive Flag as read-only */ |
| } |
| |
| /* Check Bus-off Flag */ |
| if (((interrupts & CAN_IT_BUSOFF) != 0U) && |
| ((esrflags & CAN_ESR_BOFF) != 0U)) |
| { |
| /* Set CAN error code to Bus-Off */ |
| errorcode |= HAL_CAN_ERROR_BOF; |
| |
| /* No need for clear of Error Bus-Off as read-only */ |
| } |
| |
| /* Check Last Error Code Flag */ |
| if (((interrupts & CAN_IT_LAST_ERROR_CODE) != 0U) && |
| ((esrflags & CAN_ESR_LEC) != 0U)) |
| { |
| switch (esrflags & CAN_ESR_LEC) |
| { |
| case (CAN_ESR_LEC_0): |
| /* Set CAN error code to Stuff error */ |
| errorcode |= HAL_CAN_ERROR_STF; |
| break; |
| case (CAN_ESR_LEC_1): |
| /* Set CAN error code to Form error */ |
| errorcode |= HAL_CAN_ERROR_FOR; |
| break; |
| case (CAN_ESR_LEC_1 | CAN_ESR_LEC_0): |
| /* Set CAN error code to Acknowledgement error */ |
| errorcode |= HAL_CAN_ERROR_ACK; |
| break; |
| case (CAN_ESR_LEC_2): |
| /* Set CAN error code to Bit recessive error */ |
| errorcode |= HAL_CAN_ERROR_BR; |
| break; |
| case (CAN_ESR_LEC_2 | CAN_ESR_LEC_0): |
| /* Set CAN error code to Bit Dominant error */ |
| errorcode |= HAL_CAN_ERROR_BD; |
| break; |
| case (CAN_ESR_LEC_2 | CAN_ESR_LEC_1): |
| /* Set CAN error code to CRC error */ |
| errorcode |= HAL_CAN_ERROR_CRC; |
| break; |
| default: |
| break; |
| } |
| |
| /* Clear Last error code Flag */ |
| CLEAR_BIT(hcan->Instance->ESR, CAN_ESR_LEC); |
| } |
| } |
| |
| /* Clear ERRI Flag */ |
| __HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_ERRI); |
| } |
| |
| /* Call the Error call Back in case of Errors */ |
| if (errorcode != HAL_CAN_ERROR_NONE) |
| { |
| /* Update error code in handle */ |
| hcan->ErrorCode |= errorcode; |
| |
| /* Call Error callback function */ |
| #if USE_HAL_CAN_REGISTER_CALLBACKS == 1 |
| /* Call registered callback*/ |
| hcan->ErrorCallback(hcan); |
| #else |
| /* Call weak (surcharged) callback */ |
| HAL_CAN_ErrorCallback(hcan); |
| #endif /* USE_HAL_CAN_REGISTER_CALLBACKS */ |
| } |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group5 Callback functions |
| * @brief CAN Callback functions |
| * |
| @verbatim |
| ============================================================================== |
| ##### Callback functions ##### |
| ============================================================================== |
| [..] |
| This subsection provides the following callback functions: |
| (+) HAL_CAN_TxMailbox0CompleteCallback |
| (+) HAL_CAN_TxMailbox1CompleteCallback |
| (+) HAL_CAN_TxMailbox2CompleteCallback |
| (+) HAL_CAN_TxMailbox0AbortCallback |
| (+) HAL_CAN_TxMailbox1AbortCallback |
| (+) HAL_CAN_TxMailbox2AbortCallback |
| (+) HAL_CAN_RxFifo0MsgPendingCallback |
| (+) HAL_CAN_RxFifo0FullCallback |
| (+) HAL_CAN_RxFifo1MsgPendingCallback |
| (+) HAL_CAN_RxFifo1FullCallback |
| (+) HAL_CAN_SleepCallback |
| (+) HAL_CAN_WakeUpFromRxMsgCallback |
| (+) HAL_CAN_ErrorCallback |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Transmission Mailbox 0 complete callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox0CompleteCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Transmission Mailbox 1 complete callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox1CompleteCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Transmission Mailbox 2 complete callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox2CompleteCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Transmission Mailbox 0 Cancellation callback. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox0AbortCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox0AbortCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Transmission Mailbox 1 Cancellation callback. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox1AbortCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox1AbortCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Transmission Mailbox 2 Cancellation callback. |
| * @param hcan pointer to an CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_TxMailbox2AbortCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_TxMailbox2AbortCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Rx FIFO 0 message pending callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_RxFifo0MsgPendingCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Rx FIFO 0 full callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_RxFifo0FullCallback could be implemented in the user |
| file |
| */ |
| } |
| |
| /** |
| * @brief Rx FIFO 1 message pending callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_RxFifo1MsgPendingCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Rx FIFO 1 full callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_RxFifo1FullCallback could be implemented in the user |
| file |
| */ |
| } |
| |
| /** |
| * @brief Sleep callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_SleepCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_SleepCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @brief WakeUp from Rx message callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_WakeUpFromRxMsgCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_WakeUpFromRxMsgCallback could be implemented in the |
| user file |
| */ |
| } |
| |
| /** |
| * @brief Error CAN callback. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval None |
| */ |
| __weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan) |
| { |
| /* Prevent unused argument(s) compilation warning */ |
| UNUSED(hcan); |
| |
| /* NOTE : This function Should not be modified, when the callback is needed, |
| the HAL_CAN_ErrorCallback could be implemented in the user file |
| */ |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** @defgroup CAN_Exported_Functions_Group6 Peripheral State and Error functions |
| * @brief CAN Peripheral State functions |
| * |
| @verbatim |
| ============================================================================== |
| ##### Peripheral State and Error functions ##### |
| ============================================================================== |
| [..] |
| This subsection provides functions allowing to : |
| (+) HAL_CAN_GetState() : Return the CAN state. |
| (+) HAL_CAN_GetError() : Return the CAN error codes if any. |
| (+) HAL_CAN_ResetError(): Reset the CAN error codes if any. |
| |
| @endverbatim |
| * @{ |
| */ |
| |
| /** |
| * @brief Return the CAN state. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL state |
| */ |
| HAL_CAN_StateTypeDef HAL_CAN_GetState(const CAN_HandleTypeDef *hcan) |
| { |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Check sleep mode acknowledge flag */ |
| if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U) |
| { |
| /* Sleep mode is active */ |
| state = HAL_CAN_STATE_SLEEP_ACTIVE; |
| } |
| /* Check sleep mode request flag */ |
| else if ((hcan->Instance->MCR & CAN_MCR_SLEEP) != 0U) |
| { |
| /* Sleep mode request is pending */ |
| state = HAL_CAN_STATE_SLEEP_PENDING; |
| } |
| else |
| { |
| /* Neither sleep mode request nor sleep mode acknowledge */ |
| } |
| } |
| |
| /* Return CAN state */ |
| return state; |
| } |
| |
| /** |
| * @brief Return the CAN error code. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval CAN Error Code |
| */ |
| uint32_t HAL_CAN_GetError(const CAN_HandleTypeDef *hcan) |
| { |
| /* Return CAN error code */ |
| return hcan->ErrorCode; |
| } |
| |
| /** |
| * @brief Reset the CAN error code. |
| * @param hcan pointer to a CAN_HandleTypeDef structure that contains |
| * the configuration information for the specified CAN. |
| * @retval HAL status |
| */ |
| HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan) |
| { |
| HAL_StatusTypeDef status = HAL_OK; |
| HAL_CAN_StateTypeDef state = hcan->State; |
| |
| if ((state == HAL_CAN_STATE_READY) || |
| (state == HAL_CAN_STATE_LISTENING)) |
| { |
| /* Reset CAN error code */ |
| hcan->ErrorCode = 0U; |
| } |
| else |
| { |
| /* Update error code */ |
| hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED; |
| |
| status = HAL_ERROR; |
| } |
| |
| /* Return the status */ |
| return status; |
| } |
| |
| /** |
| * @} |
| */ |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* HAL_CAN_MODULE_ENABLED */ |
| |
| /** |
| * @} |
| */ |
| |
| #endif /* CAN */ |
| |
| /** |
| * @} |
| */ |