commit
This commit is contained in:
2436
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c
Normal file
2436
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_can.c
Normal file
@@ -0,0 +1,2436 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_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 "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_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(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(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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
7669
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c
Normal file
7669
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c
Normal file
File diff suppressed because it is too large
Load Diff
1948
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c
Normal file
1948
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c
Normal file
@@ -0,0 +1,1948 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rtc.c
|
||||
* @author MCD Application Team
|
||||
* @brief RTC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Real Time Clock (RTC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + RTC Time and Date functions
|
||||
* + RTC Alarm functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) Enable the RTC domain access (see description in the section above).
|
||||
(+) Configure the RTC Prescaler (Asynchronous prescaler to generate RTC 1Hz time base)
|
||||
using the HAL_RTC_Init() function.
|
||||
|
||||
*** Time and Date configuration ***
|
||||
===================================
|
||||
[..]
|
||||
(+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
|
||||
and HAL_RTC_SetDate() functions.
|
||||
(+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
|
||||
|
||||
*** Alarm configuration ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
|
||||
You can also configure the RTC Alarm with interrupt mode using the HAL_RTC_SetAlarm_IT() function.
|
||||
(+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
|
||||
|
||||
*** Tamper configuration ***
|
||||
============================
|
||||
[..]
|
||||
(+) Enable the RTC Tamper and configure the Tamper Level using the
|
||||
HAL_RTCEx_SetTamper() function. You can configure RTC Tamper with interrupt
|
||||
mode using HAL_RTCEx_SetTamper_IT() function.
|
||||
(+) The TAMPER1 alternate function can be mapped to PC13
|
||||
|
||||
*** Backup Data Registers configuration ***
|
||||
===========================================
|
||||
[..]
|
||||
(+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
|
||||
function.
|
||||
(+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
|
||||
function.
|
||||
|
||||
##### WARNING: Drivers Restrictions #####
|
||||
==================================================================
|
||||
[..] RTC version used on STM32F1 families is version V1. All the features supported by V2
|
||||
(other families) will be not supported on F1.
|
||||
[..] As on V2, main RTC features are managed by HW. But on F1, date feature is completely
|
||||
managed by SW.
|
||||
[..] Then, there are some restrictions compared to other families:
|
||||
(+) Only format 24 hours supported in HAL (format 12 hours not supported)
|
||||
(+) Date is saved in SRAM. Then, when MCU is in STOP or STANDBY mode, date will be lost.
|
||||
User should implement a way to save date before entering in low power mode (an
|
||||
example is provided with firmware package based on backup registers)
|
||||
(+) Date is automatically updated each time a HAL_RTC_GetTime or HAL_RTC_GetDate is called.
|
||||
(+) Alarm detection is limited to 1 day. It will expire only 1 time (no alarm repetition, need
|
||||
to program a new alarm)
|
||||
|
||||
##### Backup Domain Operating Condition #####
|
||||
==============================================================================
|
||||
[..] The real-time clock (RTC) and the RTC backup registers can be powered
|
||||
from the VBAT voltage when the main VDD supply is powered off.
|
||||
To retain the content of the RTC backup registers and supply the RTC
|
||||
when VDD is turned off, VBAT pin can be connected to an optional
|
||||
standby voltage supplied by a battery or by another source.
|
||||
|
||||
[..] To allow the RTC operating even when the main digital supply (VDD) is turned
|
||||
off, the VBAT pin powers the following blocks:
|
||||
(#) The RTC
|
||||
(#) The LSE oscillator
|
||||
(#) The backup SRAM when the low power backup regulator is enabled
|
||||
(#) PC13 to PC15 I/Os, plus PI8 I/O (when available)
|
||||
|
||||
[..] When the backup domain is supplied by VDD (analog switch connected to VDD),
|
||||
the following pins are available:
|
||||
(+) PC13 can be used as a Tamper pin
|
||||
|
||||
[..] When the backup domain is supplied by VBAT (analog switch connected to VBAT
|
||||
because VDD is not present), the following pins are available:
|
||||
(+) PC13 can be used as the Tamper pin
|
||||
|
||||
##### Backup Domain Reset #####
|
||||
==================================================================
|
||||
[..] The backup domain reset sets all RTC registers and the RCC_BDCR register
|
||||
to their reset values.
|
||||
[..] A backup domain reset is generated when one of the following events occurs:
|
||||
(#) Software reset, triggered by setting the BDRST bit in the
|
||||
RCC Backup domain control register (RCC_BDCR).
|
||||
(#) VDD or VBAT power on, if both supplies have previously been powered off.
|
||||
(#) Tamper detection event resets all data backup registers.
|
||||
|
||||
##### Backup Domain Access #####
|
||||
==================================================================
|
||||
[..] After reset, the backup domain (RTC registers, RTC backup data
|
||||
registers and backup SRAM) is protected against possible unwanted write
|
||||
accesses.
|
||||
[..] To enable access to the RTC Domain and RTC registers, proceed as follows:
|
||||
(+) Call the function HAL_RCCEx_PeriphCLKConfig in using RCC_PERIPHCLK_RTC for
|
||||
PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSE)
|
||||
(+) Enable the BKP clock in using __HAL_RCC_BKP_CLK_ENABLE()
|
||||
|
||||
##### RTC and low power modes #####
|
||||
==================================================================
|
||||
[..] The MCU can be woken up from a low power mode by an RTC alternate
|
||||
function.
|
||||
[..] The RTC alternate functions are the RTC alarms (Alarm A),
|
||||
and RTC tamper event detection.
|
||||
These RTC alternate functions can wake up the system from the Stop and
|
||||
Standby low power modes.
|
||||
[..] The system can also wake up from low power modes without depending
|
||||
on an external interrupt (Auto-wakeup mode), by using the RTC alarm.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_RTC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Function HAL_RTC_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
[..]
|
||||
Function HAL_RTC_RegisterCallback() allows to register following callbacks:
|
||||
(+) AlarmAEventCallback : RTC Alarm A Event callback.
|
||||
(+) Tamper1EventCallback : RTC Tamper 1 Event callback.
|
||||
(+) MspInitCallback : RTC MspInit callback.
|
||||
(+) MspDeInitCallback : RTC MspDeInit callback.
|
||||
[..]
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_RTC_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) AlarmAEventCallback : RTC Alarm A Event callback.
|
||||
(+) Tamper1EventCallback : RTC Tamper 1 Event callback.
|
||||
(+) MspInitCallback : RTC MspInit callback.
|
||||
(+) MspDeInitCallback : RTC MspDeInit callback.
|
||||
[..]
|
||||
By default, after the HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET,
|
||||
all callbacks are set to the corresponding weak functions :
|
||||
example AlarmAEventCallback().
|
||||
Exception done for MspInit and MspDeInit callbacks that are reset to the legacy weak function
|
||||
in the HAL_RTC_Init()/HAL_RTC_DeInit() only when these callbacks are null
|
||||
(not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, HAL_RTC_Init()/HAL_RTC_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_RTC_STATE_READY or HAL_RTC_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_RTC_RegisterCallback() before calling HAL_RTC_DeInit()
|
||||
or HAL_RTC_Init() function.
|
||||
[..]
|
||||
When The compilation define USE_HAL_RTC_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 "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTC RTC
|
||||
* @brief RTC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Constants RTC Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define RTC_ALARM_RESETVALUE_REGISTER (uint16_t)0xFFFF
|
||||
#define RTC_ALARM_RESETVALUE 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Macros RTC Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Functions RTC Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter);
|
||||
static uint32_t RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter);
|
||||
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc);
|
||||
static uint8_t RTC_ByteToBcd2(uint8_t Value);
|
||||
static uint8_t RTC_Bcd2ToByte(uint8_t Value);
|
||||
static uint8_t RTC_IsLeapYear(uint16_t nYear);
|
||||
static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed);
|
||||
static uint8_t RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup RTC_Exported_Functions RTC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_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 initialize and configure the
|
||||
RTC Prescaler (Asynchronous), disable RTC registers Write protection,
|
||||
enter and exit the RTC initialization mode,
|
||||
RTC registers synchronization check and reference clock detection enable.
|
||||
(#) The RTC Prescaler should be programmed to generate the RTC 1Hz time base.
|
||||
(#) All RTC registers are Write protected. Writing to the RTC registers
|
||||
is enabled by setting the CNF bit in the RTC_CRL register.
|
||||
(#) To read the calendar after wakeup from low power modes (Standby or Stop)
|
||||
the software must first wait for the RSF bit (Register Synchronized Flag)
|
||||
in the RTC_CRL register to be set by hardware.
|
||||
The HAL_RTC_WaitForSynchro() function implements the above software
|
||||
sequence (RSF clear and RSF check).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC peripheral
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t prescaler = 0U;
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
|
||||
assert_param(IS_RTC_CALIB_OUTPUT(hrtc->Init.OutPut));
|
||||
assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
if (hrtc->State == HAL_RTC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hrtc->Lock = HAL_UNLOCKED;
|
||||
|
||||
hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
|
||||
hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
|
||||
|
||||
if (hrtc->MspInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
}
|
||||
/* Init the low level hardware */
|
||||
hrtc->MspInitCallback(hrtc);
|
||||
|
||||
if (hrtc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (hrtc->State == HAL_RTC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hrtc->Lock = HAL_UNLOCKED;
|
||||
|
||||
/* Initialize RTC MSP */
|
||||
HAL_RTC_MspInit(hrtc);
|
||||
}
|
||||
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Waiting for synchro */
|
||||
if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear Flags Bits */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_OW | RTC_FLAG_ALRAF | RTC_FLAG_SEC));
|
||||
|
||||
if (hrtc->Init.OutPut != RTC_OUTPUTSOURCE_NONE)
|
||||
{
|
||||
/* Disable the selected Tamper pin */
|
||||
CLEAR_BIT(BKP->CR, BKP_CR_TPE);
|
||||
}
|
||||
|
||||
/* Set the signal which will be routed to RTC Tamper pin*/
|
||||
MODIFY_REG(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE | BKP_RTCCR_ASOS), hrtc->Init.OutPut);
|
||||
|
||||
if (hrtc->Init.AsynchPrediv != RTC_AUTO_1_SECOND)
|
||||
{
|
||||
/* RTC Prescaler provided directly by end-user*/
|
||||
prescaler = hrtc->Init.AsynchPrediv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RTC Prescaler will be automatically calculated to get 1 second timebase */
|
||||
/* Get the RTCCLK frequency */
|
||||
prescaler = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC);
|
||||
|
||||
/* Check that RTC clock is enabled*/
|
||||
if (prescaler == 0U)
|
||||
{
|
||||
/* Should not happen. Frequency is not available*/
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RTC period = RTCCLK/(RTC_PR + 1) */
|
||||
prescaler = prescaler - 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the RTC_PRLH / RTC_PRLL */
|
||||
WRITE_REG(hrtc->Instance->PRLH, ((prescaler >> 16U) & RTC_PRLH_PRL));
|
||||
WRITE_REG(hrtc->Instance->PRLL, (prescaler & RTC_PRLL_PRL));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize date to 1st of January 2000 */
|
||||
hrtc->DateToUpdate.Year = 0x00U;
|
||||
hrtc->DateToUpdate.Month = RTC_MONTH_JANUARY;
|
||||
hrtc->DateToUpdate.Date = 0x01U;
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the RTC peripheral
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @note This function does not reset the RTC Backup Data registers.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_REG(hrtc->Instance->CNTL);
|
||||
CLEAR_REG(hrtc->Instance->CNTH);
|
||||
WRITE_REG(hrtc->Instance->PRLL, 0x00008000U);
|
||||
CLEAR_REG(hrtc->Instance->PRLH);
|
||||
|
||||
/* Reset All CRH/CRL bits */
|
||||
CLEAR_REG(hrtc->Instance->CRH);
|
||||
CLEAR_REG(hrtc->Instance->CRL);
|
||||
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for synchro*/
|
||||
HAL_RTC_WaitForSynchro(hrtc);
|
||||
|
||||
/* Clear RSF flag */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
if (hrtc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
hrtc->MspDeInitCallback(hrtc);
|
||||
|
||||
#else
|
||||
/* De-Initialize RTC MSP */
|
||||
HAL_RTC_MspDeInit(hrtc);
|
||||
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User RTC Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hrtc RTC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
|
||||
* @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
|
||||
* @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
|
||||
* @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
if (HAL_RTC_STATE_READY == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_ALARM_A_EVENT_CB_ID :
|
||||
hrtc->AlarmAEventCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_TAMPER1_EVENT_CB_ID :
|
||||
hrtc->Tamper1EventCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_RTC_STATE_RESET == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an RTC Callback
|
||||
* RTC callback is redirected to the weak predefined callback
|
||||
* @param hrtc RTC handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
|
||||
* @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
|
||||
* @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
|
||||
* @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
if (HAL_RTC_STATE_READY == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_ALARM_A_EVENT_CB_ID :
|
||||
hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
|
||||
break;
|
||||
|
||||
case HAL_RTC_TAMPER1_EVENT_CB_ID :
|
||||
hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_RTC_STATE_RESET == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC MSP.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the RTC MSP.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group2 Time and Date functions
|
||||
* @brief RTC Time and Date functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Time and Date functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Time and Date features
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets RTC current time.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTime: Pointer to Time structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTime == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sTime->Hours));
|
||||
assert_param(IS_RTC_MINUTES(sTime->Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sTime->Seconds));
|
||||
|
||||
counter_time = (uint32_t)(((uint32_t)sTime->Hours * 3600U) + \
|
||||
((uint32_t)sTime->Minutes * 60U) + \
|
||||
((uint32_t)sTime->Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
|
||||
|
||||
counter_time = (((uint32_t)(RTC_Bcd2ToByte(sTime->Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sTime->Minutes)) * 60U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sTime->Seconds))));
|
||||
}
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Read current Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Set again alarm to match with new time if enabled */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
|
||||
/* Write new Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets RTC current time.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTime: Pointer to Time structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U, days_elapsed = 0U, hours = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTime == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Check if counter overflow occurred */
|
||||
if (__HAL_RTC_OVERFLOW_GET_FLAG(hrtc, RTC_FLAG_OW))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Read the time counter*/
|
||||
counter_time = RTC_ReadTimeCounter(hrtc);
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
hours = counter_time / 3600U;
|
||||
sTime->Minutes = (uint8_t)((counter_time % 3600U) / 60U);
|
||||
sTime->Seconds = (uint8_t)((counter_time % 3600U) % 60U);
|
||||
|
||||
if (hours >= 24U)
|
||||
{
|
||||
/* Get number of days elapsed from last calculation */
|
||||
days_elapsed = (hours / 24U);
|
||||
|
||||
/* Set Hours in RTC_TimeTypeDef structure*/
|
||||
sTime->Hours = (hours % 24U);
|
||||
|
||||
/* Read Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Calculate remaining time to reach alarm (only if set and not yet expired)*/
|
||||
if ((counter_alarm != RTC_ALARM_RESETVALUE) && (counter_alarm > counter_time))
|
||||
{
|
||||
counter_alarm -= counter_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In case of counter_alarm < counter_time */
|
||||
/* Alarm expiration already occurred but alarm not deactivated */
|
||||
counter_alarm = RTC_ALARM_RESETVALUE;
|
||||
}
|
||||
|
||||
/* Set updated time in decreasing counter by number of days elapsed */
|
||||
counter_time -= (days_elapsed * 24U * 3600U);
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set updated alarm to be set */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
counter_alarm += counter_time;
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Alarm already occurred. Set it to reset values to avoid unexpected expiration */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update date */
|
||||
RTC_DateUpdate(hrtc, days_elapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
sTime->Hours = hours;
|
||||
}
|
||||
|
||||
/* Check the input parameters format */
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
/* Convert the time structure parameters to BCD format */
|
||||
sTime->Hours = (uint8_t)RTC_ByteToBcd2(sTime->Hours);
|
||||
sTime->Minutes = (uint8_t)RTC_ByteToBcd2(sTime->Minutes);
|
||||
sTime->Seconds = (uint8_t)RTC_ByteToBcd2(sTime->Seconds);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets RTC current date.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sDate: Pointer to date structure
|
||||
* @param Format: specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U, hours = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sDate == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_YEAR(sDate->Year));
|
||||
assert_param(IS_RTC_MONTH(sDate->Month));
|
||||
assert_param(IS_RTC_DATE(sDate->Date));
|
||||
|
||||
/* Change the current date */
|
||||
hrtc->DateToUpdate.Year = sDate->Year;
|
||||
hrtc->DateToUpdate.Month = sDate->Month;
|
||||
hrtc->DateToUpdate.Date = sDate->Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
|
||||
assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month)));
|
||||
assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date)));
|
||||
|
||||
/* Change the current date */
|
||||
hrtc->DateToUpdate.Year = RTC_Bcd2ToByte(sDate->Year);
|
||||
hrtc->DateToUpdate.Month = RTC_Bcd2ToByte(sDate->Month);
|
||||
hrtc->DateToUpdate.Date = RTC_Bcd2ToByte(sDate->Date);
|
||||
}
|
||||
|
||||
/* WeekDay set by user can be ignored because automatically calculated */
|
||||
hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(hrtc->DateToUpdate.Year, hrtc->DateToUpdate.Month, hrtc->DateToUpdate.Date);
|
||||
sDate->WeekDay = hrtc->DateToUpdate.WeekDay;
|
||||
|
||||
/* Reset time to be aligned on the same day */
|
||||
/* Read the time counter*/
|
||||
counter_time = RTC_ReadTimeCounter(hrtc);
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
hours = counter_time / 3600U;
|
||||
if (hours > 24U)
|
||||
{
|
||||
/* Set updated time in decreasing counter by number of days elapsed */
|
||||
counter_time -= ((hours / 24U) * 24U * 3600U);
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Read current Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Set again alarm to match with new time if enabled */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
|
||||
/* Write new Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY ;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets RTC current date.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sDate: Pointer to Date structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
|
||||
{
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sDate == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
sDate->WeekDay = hrtc->DateToUpdate.WeekDay;
|
||||
sDate->Year = hrtc->DateToUpdate.Year;
|
||||
sDate->Month = hrtc->DateToUpdate.Month;
|
||||
sDate->Date = hrtc->DateToUpdate.Date;
|
||||
|
||||
/* Check the input parameters format */
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
/* Convert the date structure parameters to BCD format */
|
||||
sDate->Year = (uint8_t)RTC_ByteToBcd2(sDate->Year);
|
||||
sDate->Month = (uint8_t)RTC_ByteToBcd2(sDate->Month);
|
||||
sDate->Date = (uint8_t)RTC_ByteToBcd2(sDate->Date);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group3 Alarm functions
|
||||
* @brief RTC Alarm functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Alarm functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Alarm feature
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets the specified RTC Alarm.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Alarm structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U, counter_time;
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(sAlarm->Alarm));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Convert time in seconds */
|
||||
counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
|
||||
((uint32_t)stime.Minutes * 60U) + \
|
||||
((uint32_t)stime.Seconds));
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
|
||||
assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
|
||||
|
||||
counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
|
||||
counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
|
||||
((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
}
|
||||
|
||||
/* Check that requested alarm should expire in the same day (otherwise add 1 day) */
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
}
|
||||
|
||||
/* Write Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the specified RTC Alarm with Interrupt
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Alarm structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U, counter_time;
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(sAlarm->Alarm));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Convert time in seconds */
|
||||
counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
|
||||
((uint32_t)stime.Minutes * 60U) + \
|
||||
((uint32_t)stime.Seconds));
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
|
||||
assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
|
||||
|
||||
counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
|
||||
counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
|
||||
((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
}
|
||||
|
||||
/* Check that requested alarm should expire in the same day (otherwise add 1 day) */
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
}
|
||||
|
||||
/* Write alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Configure the Alarm interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA);
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_IT();
|
||||
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the RTC Alarm value and masks.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Date structure
|
||||
* @param Alarm: Specifies the Alarm.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_ALARM_A: Alarm
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Alarm);
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(Alarm));
|
||||
|
||||
/* Read Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Fill the structure with the read parameters */
|
||||
/* Set hours in a day range (between 0 to 24)*/
|
||||
sAlarm->AlarmTime.Hours = (uint32_t)((counter_alarm / 3600U) % 24U);
|
||||
sAlarm->AlarmTime.Minutes = (uint32_t)((counter_alarm % 3600U) / 60U);
|
||||
sAlarm->AlarmTime.Seconds = (uint32_t)((counter_alarm % 3600U) % 60U);
|
||||
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
sAlarm->AlarmTime.Hours = RTC_ByteToBcd2(sAlarm->AlarmTime.Hours);
|
||||
sAlarm->AlarmTime.Minutes = RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes);
|
||||
sAlarm->AlarmTime.Seconds = RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivate the specified RTC Alarm
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Alarm: Specifies the Alarm.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_ALARM_A: AlarmA
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Alarm);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALARM(Alarm));
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* In case of interrupt mode is used, the interrupt source must disabled */
|
||||
__HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Set to default values ALRH & ALRL registers */
|
||||
WRITE_REG(hrtc->Instance->ALRH, RTC_ALARM_RESETVALUE_REGISTER);
|
||||
WRITE_REG(hrtc->Instance->ALRL, RTC_ALARM_RESETVALUE_REGISTER);
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: Disable EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_DISABLE_IT();
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Alarm interrupt request.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA))
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != (uint32_t)RESET)
|
||||
{
|
||||
/* AlarmA callback */
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
hrtc->AlarmAEventCallback(hrtc);
|
||||
#else
|
||||
HAL_RTC_AlarmAEventCallback(hrtc);
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Alarm interrupt pending bit */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the EXTI's line Flag for RTC Alarm */
|
||||
__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Alarm A callback.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_AlarmAEventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles AlarmA Polling request.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Timeout: Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_TIMEOUT;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the Alarm interrupt pending bit */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Get RTC state
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Returns the RTC state.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
return hrtc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group5 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Wait for RTC Time and Date Synchronization
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL)
|
||||
* are synchronized with RTC APB clock.
|
||||
* @note This function must be called before any read operation after an APB reset
|
||||
* or an APB clock stop.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear RSF flag */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait the registers to be synchronised */
|
||||
while ((hrtc->Instance->CRL & RTC_FLAG_RSF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the time counter available in RTC_CNT registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval Time counter
|
||||
*/
|
||||
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint16_t high1 = 0U, high2 = 0U, low = 0U;
|
||||
uint32_t timecounter = 0U;
|
||||
|
||||
high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
|
||||
low = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
|
||||
high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
|
||||
|
||||
if (high1 != high2)
|
||||
{
|
||||
/* In this case the counter roll over during reading of CNTL and CNTH registers,
|
||||
read again CNTL register then return the counter value */
|
||||
timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No counter roll over during reading of CNTL and CNTH registers, counter
|
||||
value is equal to first value of CNTL and CNTH */
|
||||
timecounter = (((uint32_t) high1 << 16U) | low);
|
||||
}
|
||||
|
||||
return timecounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the time counter in RTC_CNT registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param TimeCounter: Counter to write in RTC_CNT registers
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTH, (TimeCounter >> 16U));
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTL, (TimeCounter & RTC_CNTL_RTC_CNT));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the time counter available in RTC_ALR registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval Time counter
|
||||
*/
|
||||
static uint32_t RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint16_t high1 = 0U, low = 0U;
|
||||
|
||||
high1 = READ_REG(hrtc->Instance->ALRH & RTC_CNTH_RTC_CNT);
|
||||
low = READ_REG(hrtc->Instance->ALRL & RTC_CNTL_RTC_CNT);
|
||||
|
||||
return (((uint32_t) high1 << 16U) | low);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the time counter in RTC_ALR registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param AlarmCounter: Counter to write in RTC_ALR registers
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->ALRH, (AlarmCounter >> 16U));
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->ALRL, (AlarmCounter & RTC_ALRL_RTC_ALR));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters the RTC Initialization mode.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit the RTC Initialization mode.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a 2 digit decimal to BCD format.
|
||||
* @param Value: Byte to be converted
|
||||
* @retval Converted byte
|
||||
*/
|
||||
static uint8_t RTC_ByteToBcd2(uint8_t Value)
|
||||
{
|
||||
uint32_t bcdhigh = 0U;
|
||||
|
||||
while (Value >= 10U)
|
||||
{
|
||||
bcdhigh++;
|
||||
Value -= 10U;
|
||||
}
|
||||
|
||||
return ((uint8_t)(bcdhigh << 4U) | Value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts from 2 digit BCD to Binary.
|
||||
* @param Value: BCD value to be converted
|
||||
* @retval Converted word
|
||||
*/
|
||||
static uint8_t RTC_Bcd2ToByte(uint8_t Value)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10U;
|
||||
return (tmp + (Value & (uint8_t)0x0F));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates date when time is 23:59:59.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param DayElapsed: Number of days elapsed from last date update
|
||||
* @retval None
|
||||
*/
|
||||
static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed)
|
||||
{
|
||||
uint32_t year = 0U, month = 0U, day = 0U;
|
||||
uint32_t loop = 0U;
|
||||
|
||||
/* Get the current year*/
|
||||
year = hrtc->DateToUpdate.Year;
|
||||
|
||||
/* Get the current month and day */
|
||||
month = hrtc->DateToUpdate.Month;
|
||||
day = hrtc->DateToUpdate.Date;
|
||||
|
||||
for (loop = 0U; loop < DayElapsed; loop++)
|
||||
{
|
||||
if ((month == 1U) || (month == 3U) || (month == 5U) || (month == 7U) || \
|
||||
(month == 8U) || (month == 10U) || (month == 12U))
|
||||
{
|
||||
if (day < 31U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
/* Date structure member: day = 31 */
|
||||
else
|
||||
{
|
||||
if (month != 12U)
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
/* Date structure member: day = 31 & month =12 */
|
||||
else
|
||||
{
|
||||
month = 1U;
|
||||
day = 1U;
|
||||
year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((month == 4U) || (month == 6U) || (month == 9U) || (month == 11U))
|
||||
{
|
||||
if (day < 30U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
/* Date structure member: day = 30 */
|
||||
else
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
else if (month == 2U)
|
||||
{
|
||||
if (day < 28U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
else if (day == 28U)
|
||||
{
|
||||
/* Leap year */
|
||||
if (RTC_IsLeapYear(year))
|
||||
{
|
||||
day++;
|
||||
}
|
||||
else
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
else if (day == 29U)
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update year */
|
||||
hrtc->DateToUpdate.Year = year;
|
||||
|
||||
/* Update day and month */
|
||||
hrtc->DateToUpdate.Month = month;
|
||||
hrtc->DateToUpdate.Date = day;
|
||||
|
||||
/* Update day of the week */
|
||||
hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(year, month, day);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the passed year is Leap or not.
|
||||
* @param nYear year to check
|
||||
* @retval 1: leap year
|
||||
* 0: not leap year
|
||||
*/
|
||||
static uint8_t RTC_IsLeapYear(uint16_t nYear)
|
||||
{
|
||||
if ((nYear % 4U) != 0U)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if ((nYear % 100U) != 0U)
|
||||
{
|
||||
return 1U;
|
||||
}
|
||||
|
||||
if ((nYear % 400U) == 0U)
|
||||
{
|
||||
return 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines the week number, the day number and the week day number.
|
||||
* @param nYear year to check
|
||||
* @param nMonth Month to check
|
||||
* @param nDay Day to check
|
||||
* @note Day is calculated with hypothesis that year > 2000
|
||||
* @retval Value which can take one of the following parameters:
|
||||
* @arg RTC_WEEKDAY_MONDAY
|
||||
* @arg RTC_WEEKDAY_TUESDAY
|
||||
* @arg RTC_WEEKDAY_WEDNESDAY
|
||||
* @arg RTC_WEEKDAY_THURSDAY
|
||||
* @arg RTC_WEEKDAY_FRIDAY
|
||||
* @arg RTC_WEEKDAY_SATURDAY
|
||||
* @arg RTC_WEEKDAY_SUNDAY
|
||||
*/
|
||||
static uint8_t RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay)
|
||||
{
|
||||
uint32_t year = 0U, weekday = 0U;
|
||||
|
||||
year = 2000U + nYear;
|
||||
|
||||
if (nMonth < 3U)
|
||||
{
|
||||
/*D = { [(23 x month)/9] + day + 4 + year + [(year-1)/4] - [(year-1)/100] + [(year-1)/400] } mod 7*/
|
||||
weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + ((year - 1U) / 4U) - ((year - 1U) / 100U) + ((year - 1U) / 400U)) % 7U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*D = { [(23 x month)/9] + day + 4 + year + [year/4] - [year/100] + [year/400] - 2 } mod 7*/
|
||||
weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + (year / 4U) - (year / 100U) + (year / 400U) - 2U) % 7U;
|
||||
}
|
||||
|
||||
return (uint8_t)weekday;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rtc_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended RTC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Real Time Clock (RTC) Extension peripheral:
|
||||
* + RTC Tamper functions
|
||||
* + Extension Control functions
|
||||
* + Extension RTC features 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
|
||||
/** @defgroup RTCEx RTCEx
|
||||
* @brief RTC Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RTCEx_Private_Macros RTCEx Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group1 RTC Tamper functions
|
||||
* @brief RTC Tamper functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Tamper functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Tamper feature
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets Tamper
|
||||
* @note By calling this API we disable the tamper interrupt for all tampers.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTamper: Pointer to Tamper Structure.
|
||||
* @note Tamper can be enabled only if ASOE and CCO bit are reset
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTamper == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_TAMPER(sTamper->Tamper));
|
||||
assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (HAL_IS_BIT_SET(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE)))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
MODIFY_REG(BKP->CR, (BKP_CR_TPE | BKP_CR_TPAL), (sTamper->Tamper | (sTamper->Trigger)));
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets Tamper with interrupt.
|
||||
* @note By calling this API we force the tamper interrupt for all tampers.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTamper: Pointer to RTC Tamper.
|
||||
* @note Tamper can be enabled only if ASOE and CCO bit are reset
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTamper == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_TAMPER(sTamper->Tamper));
|
||||
assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (HAL_IS_BIT_SET(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE)))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
MODIFY_REG(BKP->CR, (BKP_CR_TPE | BKP_CR_TPAL), (sTamper->Tamper | (sTamper->Trigger)));
|
||||
|
||||
/* Configure the Tamper Interrupt in the BKP->CSR */
|
||||
__HAL_RTC_TAMPER_ENABLE_IT(hrtc, RTC_IT_TAMP1);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates Tamper.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Tamper: Selected tamper pin.
|
||||
* This parameter can be a value of @ref RTCEx_Tamper_Pins_Definitions
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Tamper);
|
||||
|
||||
assert_param(IS_RTC_TAMPER(Tamper));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Disable the selected Tamper pin */
|
||||
CLEAR_BIT(BKP->CR, BKP_CR_TPE);
|
||||
|
||||
/* Disable the Tamper Interrupt in the BKP->CSR */
|
||||
/* Configure the Tamper Interrupt in the BKP->CSR */
|
||||
__HAL_RTC_TAMPER_DISABLE_IT(hrtc, RTC_IT_TAMP1);
|
||||
|
||||
/* Clear the Tamper interrupt pending bit */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
SET_BIT(BKP->CSR, BKP_CSR_CTE);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Tamper interrupt request.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_TamperIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP1))
|
||||
{
|
||||
/* Get the TAMPER Interrupt enable bit and pending bit */
|
||||
if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != (uint32_t)RESET)
|
||||
{
|
||||
/* Tamper callback */
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
hrtc->Tamper1EventCallback(hrtc);
|
||||
#else
|
||||
HAL_RTCEx_Tamper1EventCallback(hrtc);
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Tamper interrupt pending bit */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
}
|
||||
}
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tamper 1 callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Tamper1 Polling.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Timeout: Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get the status of the Interrupt */
|
||||
while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) == RESET)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_TIMEOUT;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the Tamper Flag */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group2 RTC Second functions
|
||||
* @brief RTC Second functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Second functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions implementing second interrupt handlers
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets Interrupt for second
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetSecond_IT(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Enable Second interruption */
|
||||
__HAL_RTC_SECOND_ENABLE_IT(hrtc, RTC_IT_SEC);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates Second.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_DeactivateSecond(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Deactivate Second interruption*/
|
||||
__HAL_RTC_SECOND_DISABLE_IT(hrtc, RTC_IT_SEC);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles second interrupt request.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_RTCIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
if (__HAL_RTC_SECOND_GET_IT_SOURCE(hrtc, RTC_IT_SEC))
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_SEC))
|
||||
{
|
||||
/* Check if Overrun occurred */
|
||||
if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_OW))
|
||||
{
|
||||
/* Second error callback */
|
||||
HAL_RTCEx_RTCEventErrorCallback(hrtc);
|
||||
|
||||
/* Clear flag Second */
|
||||
__HAL_RTC_OVERFLOW_CLEAR_FLAG(hrtc, RTC_FLAG_OW);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second callback */
|
||||
HAL_RTCEx_RTCEventCallback(hrtc);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/* Clear flag Second */
|
||||
__HAL_RTC_SECOND_CLEAR_FLAG(hrtc, RTC_FLAG_SEC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second event callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_RTCEventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second event error callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_RTCEventErrorCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_RTCEventErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extension Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Writes a data in a specified RTC Backup data register
|
||||
(+) Read a data in a specified RTC Backup data register
|
||||
(+) Sets the Smooth calibration parameters.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Writes a data in a specified RTC Backup data register.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param BackupRegister: RTC Backup data Register number.
|
||||
* This parameter can be: RTC_BKP_DRx where x can be from 1 to 10 (or 42) to
|
||||
* specify the register (depending devices).
|
||||
* @param Data: Data to be written in the specified RTC Backup data register.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_BKP(BackupRegister));
|
||||
|
||||
tmp = (uint32_t)BKP_BASE;
|
||||
tmp += (BackupRegister * 4U);
|
||||
|
||||
*(__IO uint32_t *) tmp = (Data & BKP_DR1_D);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads data from the specified RTC Backup data Register.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param BackupRegister: RTC Backup data Register number.
|
||||
* This parameter can be: RTC_BKP_DRx where x can be from 1 to 10 (or 42) to
|
||||
* specify the register (depending devices).
|
||||
* @retval Read value
|
||||
*/
|
||||
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
|
||||
{
|
||||
uint32_t backupregister = 0U;
|
||||
uint32_t pvalue = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_BKP(BackupRegister));
|
||||
|
||||
backupregister = (uint32_t)BKP_BASE;
|
||||
backupregister += (BackupRegister * 4U);
|
||||
|
||||
pvalue = (*(__IO uint32_t *)(backupregister)) & BKP_DR1_D;
|
||||
|
||||
/* Read the specified register */
|
||||
return pvalue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the Smooth calibration parameters.
|
||||
* @param hrtc: RTC handle
|
||||
* @param SmoothCalibPeriod: Not used (only present for compatibility with another families)
|
||||
* @param SmoothCalibPlusPulses: Not used (only present for compatibility with another families)
|
||||
* @param SmouthCalibMinusPulsesValue: specifies the RTC Clock Calibration value.
|
||||
* This parameter must be a number between 0 and 0x7F.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmouthCalibMinusPulsesValue)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(SmoothCalibPeriod);
|
||||
UNUSED(SmoothCalibPlusPulses);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmouthCalibMinusPulsesValue));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Sets RTC Clock Calibration value.*/
|
||||
MODIFY_REG(BKP->RTCCR, BKP_RTCCR_CAL, SmouthCalibMinusPulsesValue);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
4025
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c
Normal file
4025
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c
Normal file
@@ -0,0 +1,4025 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_spi.c
|
||||
* @author MCD Application Team
|
||||
* @brief SPI HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Serial Peripheral Interface (SPI) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The SPI HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a SPI_HandleTypeDef handle structure, for example:
|
||||
SPI_HandleTypeDef hspi;
|
||||
|
||||
(#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
|
||||
(##) Enable the SPIx interface clock
|
||||
(##) SPI pins configuration
|
||||
(+++) Enable the clock for the SPI GPIOs
|
||||
(+++) Configure these SPI pins as alternate function push-pull
|
||||
(##) NVIC configuration if you need to use interrupt process
|
||||
(+++) Configure the SPIx interrupt priority
|
||||
(+++) Enable the NVIC SPI IRQ handle
|
||||
(##) DMA Configuration if you need to use DMA process
|
||||
(+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel
|
||||
(+++) Enable the DMAx clock
|
||||
(+++) Configure the DMA handle parameters
|
||||
(+++) Configure the DMA Tx or Rx Stream/Channel
|
||||
(+++) Associate the initialized hdma_tx(or _rx) handle to the hspi DMA Tx or Rx handle
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx
|
||||
or Rx Stream/Channel
|
||||
|
||||
(#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
|
||||
management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
|
||||
|
||||
(#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
|
||||
(++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_SPI_MspInit() API.
|
||||
[..]
|
||||
Circular mode restriction:
|
||||
(#) The DMA circular mode cannot be used when the SPI is configured in these modes:
|
||||
(##) Master 2Lines RxOnly
|
||||
(##) Master 1Line Rx
|
||||
(#) The CRC feature is not managed when the DMA circular mode is enabled
|
||||
(#) When the SPI DMA Pause/Stop features are used, we must use the following APIs
|
||||
the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks
|
||||
[..]
|
||||
Master Receive mode restriction:
|
||||
(#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or
|
||||
bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI
|
||||
does not initiate a new transfer the following procedure has to be respected:
|
||||
(##) HAL_SPI_DeInit()
|
||||
(##) HAL_SPI_Init()
|
||||
[..]
|
||||
Callback registration:
|
||||
|
||||
(#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function HAL_SPI_RegisterCallback() allows to register following callbacks:
|
||||
(++) TxCpltCallback : SPI Tx Completed callback
|
||||
(++) RxCpltCallback : SPI Rx Completed callback
|
||||
(++) TxRxCpltCallback : SPI TxRx Completed callback
|
||||
(++) TxHalfCpltCallback : SPI Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : SPI Rx Half Completed callback
|
||||
(++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
|
||||
(++) ErrorCallback : SPI Error callback
|
||||
(++) AbortCpltCallback : SPI Abort callback
|
||||
(++) MspInitCallback : SPI Msp Init callback
|
||||
(++) MspDeInitCallback : SPI Msp DeInit callback
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
|
||||
(#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default
|
||||
weak function.
|
||||
HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) TxCpltCallback : SPI Tx Completed callback
|
||||
(++) RxCpltCallback : SPI Rx Completed callback
|
||||
(++) TxRxCpltCallback : SPI TxRx Completed callback
|
||||
(++) TxHalfCpltCallback : SPI Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : SPI Rx Half Completed callback
|
||||
(++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
|
||||
(++) ErrorCallback : SPI Error callback
|
||||
(++) AbortCpltCallback : SPI Abort callback
|
||||
(++) MspInitCallback : SPI Msp Init callback
|
||||
(++) MspDeInitCallback : SPI Msp DeInit callback
|
||||
|
||||
[..]
|
||||
By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit functions that can be registered/unregistered
|
||||
in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
Then, the user first registers the MspInit/MspDeInit user callbacks
|
||||
using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit()
|
||||
or HAL_SPI_Init() function.
|
||||
|
||||
[..]
|
||||
When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
[..]
|
||||
Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes,
|
||||
the following table resume the max SPI frequency reached with data size 8bits/16bits,
|
||||
according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance.
|
||||
|
||||
@endverbatim
|
||||
|
||||
Additional table :
|
||||
|
||||
DataSize = SPI_DATASIZE_8BIT:
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
| | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
|
||||
| Process | Transfer mode |---------------------|----------------------|----------------------|
|
||||
| | | Master | Slave | Master | Slave | Master | Slave |
|
||||
|==============================================================================================|
|
||||
| T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| / | Interrupt | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA |
|
||||
| R |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| R | Interrupt | Fpclk/8 | Fpclk/8 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128|
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
|
||||
DataSize = SPI_DATASIZE_16BIT:
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
| | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
|
||||
| Process | Transfer mode |---------------------|----------------------|----------------------|
|
||||
| | | Master | Slave | Master | Slave | Master | Slave |
|
||||
|==============================================================================================|
|
||||
| T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| / | Interrupt | Fpclk/4 | Fpclk/4 | NA | NA | NA | NA |
|
||||
| R |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/32 | Fpclk/2 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| R | Interrupt | Fpclk/4 | Fpclk/4 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/32 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| T | Interrupt | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128|
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
@note The max SPI frequency depend on SPI data size (8bits, 16bits),
|
||||
SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA).
|
||||
@note
|
||||
(#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and
|
||||
HAL_SPI_TransmitReceive_DMA()
|
||||
(#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA()
|
||||
(#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA()
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SPI SPI
|
||||
* @brief SPI HAL module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#if (USE_SPI_CRC != 0U) && defined(SPI_CRC_ERROR_WORKAROUND_FEATURE)
|
||||
/* CRC WORKAROUND FEATURE: Variable used to determine if device is impacted by implementation
|
||||
* of workaround related to wrong CRC errors detection on SPI2. Conditions in which this workaround
|
||||
* has to be applied, are:
|
||||
* - STM32F101CDE/STM32F103CDE
|
||||
* - Revision ID : Z
|
||||
* - SPI2
|
||||
* - In receive only mode, with CRC calculation enabled, at the end of the CRC reception,
|
||||
* the software needs to check the CRCERR flag. If it is found set, read back the SPI_RXCRC:
|
||||
* + If the value is 0, the complete data transfer is successful.
|
||||
* + Otherwise, one or more errors have been detected during the data transfer by CPU or DMA.
|
||||
* If CRCERR is found reset, the complete data transfer is considered successful.
|
||||
*
|
||||
* Check RevisionID value for identifying if Device is Rev Z (0x0001) in order to enable workaround for
|
||||
* CRC errors wrongly detected
|
||||
*/
|
||||
/* Pb is that ES_STM32F10xxCDE also identify an issue in Debug registers access while not in Debug mode
|
||||
* Revision ID information is only available in Debug mode, so Workaround could not be implemented
|
||||
* to distinguish Rev Z devices (issue present) from more recent version (issue fixed).
|
||||
* So, in case of Revision Z F101 or F103 devices, below define should be assigned to 1.
|
||||
*/
|
||||
#define USE_SPI_CRC_ERROR_WORKAROUND 0U
|
||||
#endif /* USE_SPI_CRC */
|
||||
/** @defgroup SPI_Private_Constants SPI Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define SPI_DEFAULT_TIMEOUT 100U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup SPI_Private_Functions SPI Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout, uint32_t Tickstart);
|
||||
static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
#endif /* USE_SPI_CRC */
|
||||
static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
|
||||
static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup SPI_Exported_Functions SPI Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This subsection provides a set of functions allowing to initialize and
|
||||
de-initialize the SPIx peripheral:
|
||||
|
||||
(+) User must implement HAL_SPI_MspInit() function in which he configures
|
||||
all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
|
||||
|
||||
(+) Call the function HAL_SPI_Init() to configure the selected device with
|
||||
the selected configuration:
|
||||
(++) Mode
|
||||
(++) Direction
|
||||
(++) Data Size
|
||||
(++) Clock Polarity and Phase
|
||||
(++) NSS Management
|
||||
(++) BaudRate Prescaler
|
||||
(++) FirstBit
|
||||
(++) TIMode
|
||||
(++) CRC Calculation
|
||||
(++) CRC Polynomial if CRC enabled
|
||||
|
||||
(+) Call the function HAL_SPI_DeInit() to restore the default configuration
|
||||
of the selected SPIx peripheral.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI according to the specified parameters
|
||||
* in the SPI_InitTypeDef and initialize the associated handle.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Check the SPI handle allocation */
|
||||
if (hspi == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
|
||||
assert_param(IS_SPI_MODE(hspi->Init.Mode));
|
||||
assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
|
||||
assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
|
||||
assert_param(IS_SPI_NSS(hspi->Init.NSS));
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
|
||||
/* TI mode is not supported on this device.
|
||||
TIMode parameter is mandatory equal to SPI_TIMODE_DISABLE */
|
||||
assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
|
||||
if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
|
||||
{
|
||||
assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
|
||||
assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
|
||||
|
||||
if (hspi->Init.Mode == SPI_MODE_MASTER)
|
||||
{
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Baudrate prescaler not use in Motoraola Slave mode. force to default value */
|
||||
hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
|
||||
/* Force polarity and phase to TI protocaol requirements */
|
||||
hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
|
||||
}
|
||||
#else
|
||||
hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->State == HAL_SPI_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hspi->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
/* Init the SPI Callback settings */
|
||||
hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
|
||||
hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
|
||||
if (hspi->MspInitCallback == NULL)
|
||||
{
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
hspi->MspInitCallback(hspi);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_SPI_MspInit(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_BUSY;
|
||||
|
||||
/* Disable the selected SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
|
||||
/* Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management,
|
||||
Communication speed, First bit and CRC calculation state */
|
||||
WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) |
|
||||
(hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) |
|
||||
(hspi->Init.DataSize & SPI_CR1_DFF) |
|
||||
(hspi->Init.CLKPolarity & SPI_CR1_CPOL) |
|
||||
(hspi->Init.CLKPhase & SPI_CR1_CPHA) |
|
||||
(hspi->Init.NSS & SPI_CR1_SSM) |
|
||||
(hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) |
|
||||
(hspi->Init.FirstBit & SPI_CR1_LSBFIRST) |
|
||||
(hspi->Init.CRCCalculation & SPI_CR1_CRCEN)));
|
||||
|
||||
/* Configure : NSS management */
|
||||
WRITE_REG(hspi->Instance->CR2, ((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE));
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/*---------------------------- SPIx CRCPOLY Configuration ------------------*/
|
||||
/* Configure : CRC Polynomial */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk));
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
#if defined(SPI_I2SCFGR_I2SMOD)
|
||||
/* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
|
||||
CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
|
||||
#endif /* SPI_I2SCFGR_I2SMOD */
|
||||
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize the SPI peripheral.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Check the SPI handle allocation */
|
||||
if (hspi == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check SPI Instance parameter */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
|
||||
|
||||
hspi->State = HAL_SPI_STATE_BUSY;
|
||||
|
||||
/* Disable the SPI Peripheral Clock */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
if (hspi->MspDeInitCallback == NULL)
|
||||
{
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
hspi->MspDeInitCallback(hspi);
|
||||
#else
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
HAL_SPI_MspDeInit(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->State = HAL_SPI_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI MSP.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_MspInit should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize the SPI MSP.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_MspDeInit should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User SPI Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hspi Pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI.
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
|
||||
pSPI_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
if (HAL_SPI_STATE_READY == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_TX_COMPLETE_CB_ID :
|
||||
hspi->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_COMPLETE_CB_ID :
|
||||
hspi->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_COMPLETE_CB_ID :
|
||||
hspi->TxRxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxRxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_ERROR_CB_ID :
|
||||
hspi->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_ABORT_CB_ID :
|
||||
hspi->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SPI_STATE_RESET == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an SPI Callback
|
||||
* SPI callback is redirected to the weak predefined callback
|
||||
* @param hspi Pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI.
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
if (HAL_SPI_STATE_READY == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_TX_COMPLETE_CB_ID :
|
||||
hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_COMPLETE_CB_ID :
|
||||
hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_COMPLETE_CB_ID :
|
||||
hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_ERROR_CB_ID :
|
||||
hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_ABORT_CB_ID :
|
||||
hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SPI_STATE_RESET == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the SPI
|
||||
data transfers.
|
||||
|
||||
[..] The SPI supports master and slave mode :
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) No-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, These APIs return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
|
||||
|
||||
(#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
|
||||
exist for 1Line (simplex) and 2Lines (full duplex) modes.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
uint16_t initial_TxXferCount;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
initial_TxXferCount = Size;
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->RxISR = NULL;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Transmit data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
/* Transmit data in 16 Bit mode */
|
||||
while (hspi->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send data */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Transmit data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
while (hspi->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send data */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be received
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
uint32_t tickstart;
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
|
||||
}
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->pTxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
/* this is done to handle the CRCNEXT before the latest data */
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Configure communication direction: 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Receive data in 8 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_8BIT)
|
||||
{
|
||||
/* Transfer loop */
|
||||
while (hspi->RxXferCount > 0U)
|
||||
{
|
||||
/* Check the RXNE flag */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
|
||||
{
|
||||
/* read the received data */
|
||||
(* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint8_t);
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer loop */
|
||||
while (hspi->RxXferCount > 0U)
|
||||
{
|
||||
/* Check the RXNE flag */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Handle the CRC Transmission */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* freeze the CRC before the latest data */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Read the latest data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
/* the latest data has not been received */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Receive last data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
}
|
||||
/* Receive last data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
(*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
|
||||
}
|
||||
|
||||
/* Wait the CRC data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Read CRC to Flush DR and RXNE flag */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Unlock the process */
|
||||
__HAL_UNLOCK(hspi);
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @param Size amount of data to be sent and received
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint16_t initial_TxXferCount;
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Variable used to alternate Rx and Tx during transfer */
|
||||
uint32_t txallowed = 1U;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
initial_TxXferCount = Size;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) || \
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferCount = Size;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->TxXferSize = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Transmit and Receive data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
}
|
||||
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
|
||||
{
|
||||
/* Check TXE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
/* Next Data is a reception (Rx). Tx not allowed */
|
||||
txallowed = 0U;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/* Check RXNE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
/* Next Data is a Transmission (Tx). Tx is allowed */
|
||||
txallowed = 1U;
|
||||
}
|
||||
if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Transmit and Receive data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
|
||||
{
|
||||
/* Check TXE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
/* Next Data is a reception (Rx). Tx not allowed */
|
||||
txallowed = 0U;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/* Wait until RXNE flag is reset */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
|
||||
{
|
||||
(*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
/* Next Data is a Transmission (Tx). Tx is allowed */
|
||||
txallowed = 1U;
|
||||
}
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Read CRC from DR to close CRC calculation process */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait until TXE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
/* Error on the CRC reception */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
/* Read CRC */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Unlock the process */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->RxISR = NULL;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->TxISR = SPI_TxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->TxISR = SPI_TxISR_8BIT;
|
||||
}
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable TXE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size);
|
||||
}
|
||||
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pTxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_8BIT;
|
||||
}
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Note : The SPI must be enabled after unlocking current process
|
||||
to avoid the risk of SPI interrupt handle execution before current
|
||||
process unlock */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable RXNE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @param Size amount of data to be sent and received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) || \
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_16BIT;
|
||||
hspi->TxISR = SPI_2linesTxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_8BIT;
|
||||
hspi->TxISR = SPI_2linesTxISR_8BIT;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable TXE, RXNE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with DMA.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
/* Check tx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->RxISR = NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Set the SPI TxDMA Half transfer complete callback */
|
||||
hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
|
||||
|
||||
/* Set the SPI TxDMA transfer complete callback */
|
||||
hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmatx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
|
||||
hspi->TxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with DMA.
|
||||
* @note In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @note When the CRC feature is enabled the pData Length must be Size + 1.
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check rx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
|
||||
/* Check tx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size);
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Set the SPI RxDMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
|
||||
|
||||
/* Set the SPI Rx DMA transfer complete callback */
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmarx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
|
||||
hspi->RxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in non-blocking mode with DMA.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @note When the CRC feature is enabled the pRxData Length must be Size + 1
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
|
||||
/* Check rx & tx dma handles */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) ||
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
|
||||
if (hspi->State == HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
/* Set the SPI Rx DMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the SPI Tx/Rx DMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
|
||||
}
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmarx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
|
||||
hspi->RxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
|
||||
is performed in DMA reception complete callback */
|
||||
hspi->hdmatx->XferHalfCpltCallback = NULL;
|
||||
hspi->hdmatx->XferCpltCallback = NULL;
|
||||
hspi->hdmatx->XferErrorCallback = NULL;
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
|
||||
hspi->TxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (blocking mode).
|
||||
* @param hspi SPI handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
|
||||
* started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SPI Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode;
|
||||
__IO uint32_t count;
|
||||
__IO uint32_t resetcount;
|
||||
|
||||
/* Initialized local variable */
|
||||
errorcode = HAL_OK;
|
||||
resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
count = resetcount;
|
||||
|
||||
/* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
|
||||
|
||||
/* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
|
||||
{
|
||||
hspi->TxISR = SPI_AbortTx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
|
||||
{
|
||||
hspi->RxISR = SPI_AbortRx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Abort DMA Tx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN));
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Abort DMA Rx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
|
||||
/* Disable peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN));
|
||||
}
|
||||
}
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check error during Abort procedure */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* return HAL_Error in case of error during Abort procedure */
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->state to ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (Interrupt mode).
|
||||
* @param hspi SPI handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
|
||||
* started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SPI Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode;
|
||||
uint32_t abortcplt ;
|
||||
__IO uint32_t count;
|
||||
__IO uint32_t resetcount;
|
||||
|
||||
/* Initialized local variable */
|
||||
errorcode = HAL_OK;
|
||||
abortcplt = 1U;
|
||||
resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
count = resetcount;
|
||||
|
||||
/* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
|
||||
|
||||
/* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
|
||||
{
|
||||
hspi->TxISR = SPI_AbortTx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
|
||||
{
|
||||
hspi->RxISR = SPI_AbortRx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Tx Stream/Channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Abort DMA Tx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK)
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
abortcplt = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Disable the SPI DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Rx Stream/Channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Abort DMA Rx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK)
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
abortcplt = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (abortcplt == 1U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check error during Abort procedure */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* return HAL_Error in case of error during Abort procedure */
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pause the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Disable the SPI DMA Tx & Rx requests */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Enable the SPI DMA Tx & Rx requests */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode = HAL_OK;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
|
||||
HAL_SPI_TxRxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
|
||||
HAL_SPI_TxRxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Abort the SPI DMA tx Stream/Channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* Abort the SPI DMA rx Stream/Channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx & Rx requests */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle SPI interrupt request.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t itsource = hspi->Instance->CR2;
|
||||
uint32_t itflag = hspi->Instance->SR;
|
||||
|
||||
/* SPI in mode Receiver ----------------------------------------------------*/
|
||||
if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) &&
|
||||
(SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET))
|
||||
{
|
||||
hspi->RxISR(hspi);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SPI in mode Transmitter -------------------------------------------------*/
|
||||
if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET))
|
||||
{
|
||||
hspi->TxISR(hspi);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SPI in Error Treatment --------------------------------------------------*/
|
||||
if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET))
|
||||
&& (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET))
|
||||
{
|
||||
/* SPI Overrun error interrupt occurred ----------------------------------*/
|
||||
if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
|
||||
{
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_TX)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* SPI Mode Fault error interrupt occurred -------------------------------*/
|
||||
if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
|
||||
__HAL_SPI_CLEAR_MODFFLAG(hspi);
|
||||
}
|
||||
|
||||
/* SPI Frame error interrupt occurred ------------------------------------*/
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Disable all interrupts */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Disable the SPI DMA requests if enabled */
|
||||
if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN)))
|
||||
{
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN));
|
||||
|
||||
/* Abort the SPI DMA Rx channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
|
||||
hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError;
|
||||
if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
/* Abort the SPI DMA Tx channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
|
||||
hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError;
|
||||
if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_RxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx and Rx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxRxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx and Rx Half Transfer callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI error callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_ErrorCallback should be implemented in the user file
|
||||
*/
|
||||
/* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
|
||||
and user can use HAL_SPI_GetError() API to check the latest error occurred
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI Abort Complete callback.
|
||||
* @param hspi SPI handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief SPI control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SPI.
|
||||
(+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
|
||||
(+) HAL_SPI_GetError() check in run-time Errors occurring during communication
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the SPI handle state.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval SPI state
|
||||
*/
|
||||
HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Return SPI handle state */
|
||||
return hspi->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SPI error code.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval SPI error code in bitmap format
|
||||
*/
|
||||
uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Return SPI ErrorCode */
|
||||
return hspi->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_Private_Functions
|
||||
* @brief Private functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SPI transmit process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received data is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* CRC handling */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait until RXNE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
/* Error on the CRC reception */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
}
|
||||
/* Read CRC */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if we are in Master RX 2 line mode */
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
/* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal case */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI transmit receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* CRC handling */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait the CRC data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
}
|
||||
/* Read CRC to Flush DR and RXNE flag */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Disable Rx/Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user TxRx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half transmit process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user Tx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half receive process complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user Rx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half transmit receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user TxRx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI communication error callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Stop the disable DMA transfer on SPI side */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
__IO uint32_t count;
|
||||
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
if (hspi->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check no error during Abort procedure */
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Check Busy flag */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
if (hspi->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check no error during Abort procedure */
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Receive data in 8bit mode */
|
||||
*hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
|
||||
/* Check end of the reception */
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_8BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint8_t *ptmpreg8;
|
||||
__IO uint8_t tmpreg8 = 0;
|
||||
|
||||
/* Initialize the 8bit temporary pointer */
|
||||
ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
|
||||
/* Read 8bit CRC to flush Data Register */
|
||||
tmpreg8 = *ptmpreg8;
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg8);
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
|
||||
/* Check the end of the transmission */
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Set CRC Next Bit to send CRC */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Receive data in 16 Bit mode */
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_16BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable RXNE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
|
||||
/* Read 16bit CRC to flush Data Register */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
/* Disable RXNE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
|
||||
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Transmit data in 16 Bit mode */
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
/* Enable CRC Transmission */
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Set CRC Next Bit to send CRC */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 8-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint8_t *ptmpreg8;
|
||||
__IO uint8_t tmpreg8 = 0;
|
||||
|
||||
/* Initialize the 8bit temporary pointer */
|
||||
ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
|
||||
/* Read 8bit CRC to flush Data Register */
|
||||
tmpreg8 = *ptmpreg8;
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg8);
|
||||
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Manage the receive 8-bit in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_8BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 16-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
|
||||
/* Read 16bit CRC to flush Data Register */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Manage the 16-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_16BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the data 8-bit transmit in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Enable CRC Transmission */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the data 16-bit transmit in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Transmit data in 16 Bit mode */
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Enable CRC Transmission */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle SPI Communication Timeout.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param Flag SPI flag to check
|
||||
* @param State flag state to check
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
__IO uint32_t count;
|
||||
uint32_t tmp_timeout;
|
||||
uint32_t tmp_tickstart;
|
||||
|
||||
/* Adjust Timeout value in case of end of transfer */
|
||||
tmp_timeout = Timeout - (HAL_GetTick() - Tickstart);
|
||||
tmp_tickstart = HAL_GetTick();
|
||||
|
||||
/* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
|
||||
count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U);
|
||||
|
||||
while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
|
||||
{
|
||||
/* Disable the SPI and reset the CRC: the CRC value should be cleared
|
||||
on both master and slave sides in order to resynchronize the master
|
||||
and slave for their respective CRC calculation */
|
||||
|
||||
/* Disable TXE, RXNE and ERR interrupts for the interrupt process */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
|| (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
|
||||
{
|
||||
/* Disable SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
}
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
/* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
|
||||
if (count == 0U)
|
||||
{
|
||||
tmp_timeout = 0U;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the check of the RX transaction complete.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
|| (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
|
||||
{
|
||||
/* Disable SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
}
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))
|
||||
{
|
||||
/* Wait the RXNE reset */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Control the BSY flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the check of the RXTX or TX transaction complete.
|
||||
* @param hspi SPI handle
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
/* Wait until TXE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_TXE, SET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Control the BSY flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the RXTX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* USE_SPI_CRC */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
if (hspi->State == HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user TxRx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the RX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* USE_SPI_CRC */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the TX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle abort a Rx transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE));
|
||||
|
||||
/* Flush Data Register by a blank read */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_ABORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle abort a Tx or Rx/Tx transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Disable TXEIE interrupt */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE));
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_ABORT;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Checks if encountered CRC error could be corresponding to wrongly detected errors
|
||||
* according to SPI instance, Device type, and revision ID.
|
||||
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval CRC error validity (SPI_INVALID_CRC_ERROR or SPI_VALID_CRC_ERROR).
|
||||
*/
|
||||
uint8_t SPI_ISCRCErrorValid(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
#if defined(SPI_CRC_ERROR_WORKAROUND_FEATURE) && (USE_SPI_CRC_ERROR_WORKAROUND != 0U)
|
||||
/* Check how to handle this CRC error (workaround to be applied or not) */
|
||||
/* If CRC errors could be wrongly detected (issue 2.15.2 in STM32F10xxC/D/E silicon limitations ES
|
||||
(DocID14732 Rev 13)) */
|
||||
if (hspi->Instance == SPI2)
|
||||
{
|
||||
if (hspi->Instance->RXCRCR == 0U)
|
||||
{
|
||||
return (SPI_INVALID_CRC_ERROR);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC_ERROR_WORKAROUND */
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
return (SPI_VALID_CRC_ERROR);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user