From 6ab94e0b318884bbcb95e2ea3835f951502e1d99 Mon Sep 17 00:00:00 2001 From: jaseg Date: Wed, 14 Oct 2020 12:47:28 +0200 Subject: Move firmware into subdirectory --- .../STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c | 2432 ++++++++++++++++++++ 1 file changed, 2432 insertions(+) create mode 100644 fw/hid-dials/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c (limited to 'fw/hid-dials/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c') diff --git a/fw/hid-dials/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c b/fw/hid-dials/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c new file mode 100644 index 0000000..c2fe2fe --- /dev/null +++ b/fw/hid-dials/Drivers/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_can.c @@ -0,0 +1,2432 @@ +/** + ****************************************************************************** + * @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 + * + @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 trigged 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 @ref HAL_CAN_RegisterCallback() to register an interrupt callback. + + Function @ref 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 @ref HAL_CAN_UnRegisterCallback() to reset a callback to the default + weak function. + @ref 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 @ref HAL_CAN_Init() and when the state is HAL_CAN_STATE_RESET, + all callbacks are set to the corresponding weak functions: + example @ref HAL_CAN_ErrorCallback(). + Exception done for MspInit and MspDeInit functions that are + reset to the legacy weak function in the @ref HAL_CAN_Init()/ @ref HAL_CAN_DeInit() only when + these callbacks are null (not registered beforehand). + if not, MspInit or MspDeInit are not null, the @ref HAL_CAN_Init()/ @ref 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 @ref HAL_CAN_RegisterCallback() before calling @ref HAL_CAN_DeInit() + or @ref 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 + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + +/* 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 + +/* 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) */ + + /* 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; + } + } + + /* 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; + } + } + + /* 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_CALLBACK_CB_ID Tx Mailbox 0 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CALLBACK_CB_ID Tx Mailbox 1 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CALLBACK_CB_ID Tx Mailbox 2 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CALLBACK_CB_ID Tx Mailbox 0 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CALLBACK_CB_ID Tx Mailbox 1 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CALLBACK_CB_ID Tx Mailbox 2 Abort callback ID + * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CALLBACK_CB_ID Rx Fifo 0 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO0_FULL_CALLBACK_CB_ID Rx Fifo 0 full callback ID + * @arg @ref HAL_CAN_RX_FIFO1_MSGPENDING_CALLBACK_CB_ID Rx Fifo 1 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO1_FULL_CALLBACK_CB_ID Rx Fifo 1 full callback ID + * @arg @ref HAL_CAN_SLEEP_CALLBACK_CB_ID Sleep callback ID + * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CALLBACK_CB_ID Wake Up from Rx message callback ID + * @arg @ref HAL_CAN_ERROR_CALLBACK_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 callabck 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_CALLBACK_CB_ID Tx Mailbox 0 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CALLBACK_CB_ID Tx Mailbox 1 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CALLBACK_CB_ID Tx Mailbox 2 Complete callback ID + * @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CALLBACK_CB_ID Tx Mailbox 0 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CALLBACK_CB_ID Tx Mailbox 1 Abort callback ID + * @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CALLBACK_CB_ID Tx Mailbox 2 Abort callback ID + * @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CALLBACK_CB_ID Rx Fifo 0 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO0_FULL_CALLBACK_CB_ID Rx Fifo 0 full callback ID + * @arg @ref HAL_CAN_RX_FIFO1_MSGPENDING_CALLBACK_CB_ID Rx Fifo 1 message pending callback ID + * @arg @ref HAL_CAN_RX_FIFO1_FULL_CALLBACK_CB_ID Rx Fifo 1 full callback ID + * @arg @ref HAL_CAN_SLEEP_CALLBACK_CB_ID Sleep callback ID + * @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CALLBACK_CB_ID Wake Up from Rx message callback ID + * @arg @ref HAL_CAN_ERROR_CALLBACK_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, 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(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, CAN_TxHeaderTypeDef *pHeader, 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(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(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(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(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 mesage 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 mesage 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(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(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 */ + +/** + * @} + */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ -- cgit