2465 lines
79 KiB
C
2465 lines
79 KiB
C
/**
|
|
******************************************************************************
|
|
* @file stm32f4xx_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
|
|
(++) 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 "stm32f4xx_hal.h"
|
|
|
|
/** @addtogroup STM32F4xx_HAL_Driver
|
|
* @{
|
|
*/
|
|
|
|
#if defined(CAN1)
|
|
|
|
/** @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
|
|
#define CAN_WAKEUP_TIMEOUT_COUNTER 1000000U
|
|
/**
|
|
* @}
|
|
*/
|
|
/* 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));
|
|
|
|
#if defined(CAN3)
|
|
/* Check the CAN instance */
|
|
if (hcan->Instance == CAN3)
|
|
{
|
|
/* CAN3 is single instance with 14 dedicated filters banks */
|
|
|
|
/* Check the parameters */
|
|
assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank));
|
|
}
|
|
else
|
|
{
|
|
/* CAN1 and CAN2 are dual instances with 28 common filters banks */
|
|
/* Select master instance to access the filter banks */
|
|
can_ip = CAN1;
|
|
|
|
/* Check the parameters */
|
|
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank));
|
|
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank));
|
|
}
|
|
#elif defined(CAN2)
|
|
/* CAN1 and CAN2 are dual instances with 28 common filters banks */
|
|
/* Select master instance to access the filter banks */
|
|
can_ip = CAN1;
|
|
|
|
/* Check the parameters */
|
|
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank));
|
|
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank));
|
|
#else
|
|
/* CAN1 is single instance with 14 dedicated filters banks */
|
|
|
|
/* Check the parameters */
|
|
assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank));
|
|
#endif /* CAN3 */
|
|
|
|
/* Initialisation mode for the filter */
|
|
SET_BIT(can_ip->FMR, CAN_FMR_FINIT);
|
|
|
|
#if defined(CAN3)
|
|
/* Check the CAN instance */
|
|
if (can_ip == CAN1)
|
|
{
|
|
/* Select the start filter number of CAN2 slave instance */
|
|
CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB);
|
|
SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos);
|
|
}
|
|
|
|
#elif defined(CAN2)
|
|
/* Select the start filter number of CAN2 slave instance */
|
|
CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB);
|
|
SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos);
|
|
|
|
#endif /* CAN3 */
|
|
/* 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;
|
|
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 > CAN_WAKEUP_TIMEOUT_COUNTER)
|
|
{
|
|
/* 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;
|
|
|
|
/* 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 */
|
|
transmitmailbox = POSITION_VAL(TxMailbox);
|
|
|
|
/* 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);
|
|
if (((CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos) >= 8U)
|
|
{
|
|
/* Truncate DLC to 8 if received field is over range */
|
|
pHeader->DLC = 8U;
|
|
}
|
|
else
|
|
{
|
|
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 /* CAN1 */
|
|
|
|
/**
|
|
* @}
|
|
*/
|