обмен перенес на usart2
на новой плате изолированный 485 передатчик на uart2 . на type-c сидит uart1
This commit is contained in:
1009
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cec.c
Normal file
1009
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cec.c
Normal file
@@ -0,0 +1,1009 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_cec.c
|
||||
* @author MCD Application Team
|
||||
* @brief CEC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the High Definition Multimedia Interface
|
||||
* Consumer Electronics Control Peripheral (CEC).
|
||||
* + Initialization and de-initialization function
|
||||
* + IO operation function
|
||||
* + Peripheral Control function
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 CEC HAL driver can be used as follow:
|
||||
|
||||
(#) Declare a CEC_HandleTypeDef handle structure.
|
||||
(#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API:
|
||||
(##) Enable the CEC interface clock.
|
||||
(##) CEC pins configuration:
|
||||
(+++) Enable the clock for the CEC GPIOs.
|
||||
(+++) Configure these CEC pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
|
||||
and HAL_CEC_Receive_IT() APIs):
|
||||
(+++) Configure the CEC interrupt priority.
|
||||
(+++) Enable the NVIC CEC IRQ handle.
|
||||
(+++) The specific CEC interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit
|
||||
and receive process.
|
||||
|
||||
(#) Program the Bit Timing Error Mode and the Bit Period Error Mode in the hcec Init structure.
|
||||
|
||||
(#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
|
||||
|
||||
[..]
|
||||
(@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customed HAL_CEC_MspInit() API.
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
|
||||
The compilation define USE_HAL_CEC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback()
|
||||
to register an interrupt callback.
|
||||
|
||||
Function HAL_CEC_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Transfer completed callback.
|
||||
(+) ErrorCallback : callback for error detection.
|
||||
(+) MspInitCallback : CEC MspInit.
|
||||
(+) MspDeInitCallback : CEC MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks
|
||||
HAL_CEC_RegisterRxCpltCallback().
|
||||
|
||||
Use function HAL_CEC_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Transfer completed callback.
|
||||
(+) ErrorCallback : callback for error detection.
|
||||
(+) MspInitCallback : CEC MspInit.
|
||||
(+) MspDeInitCallback : CEC MspDeInit.
|
||||
|
||||
For callback HAL_CEC_RxCpltCallback use dedicated unregister callback :
|
||||
HAL_CEC_UnRegisterRxCpltCallback().
|
||||
|
||||
By default, after the HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions :
|
||||
examples HAL_CEC_TxCpltCallback() , HAL_CEC_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak function in the HAL_CEC_Init()/ HAL_CEC_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
if not, MspInit or MspDeInit are not null, the HAL_CEC_Init() / HAL_CEC_DeInit()
|
||||
keep and use the user MspInit/MspDeInit functions (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in HAL_CEC_STATE_READY or HAL_CEC_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_CEC_RegisterCallback() before calling HAL_CEC_DeInit()
|
||||
or HAL_CEC_Init() function.
|
||||
|
||||
When the compilation define USE_HAL_CEC_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"
|
||||
|
||||
#ifdef HAL_CEC_MODULE_ENABLED
|
||||
|
||||
#if defined (CEC)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CEC CEC
|
||||
* @brief HAL CEC module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup CEC_Private_Constants CEC Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define CEC_CFGR_FIELDS (CEC_CFGR_BTEM | CEC_CFGR_BPEM )
|
||||
#define CEC_FLAG_TRANSMIT_MASK (CEC_FLAG_TSOM|CEC_FLAG_TEOM|CEC_FLAG_TBTRF)
|
||||
#define CEC_FLAG_RECEIVE_MASK (CEC_FLAG_RSOM|CEC_FLAG_REOM|CEC_FLAG_RBTF)
|
||||
#define CEC_ESR_ALL_ERROR (CEC_ESR_BTE|CEC_ESR_BPE|CEC_ESR_RBTFE|CEC_ESR_SBE|CEC_ESR_ACKE|CEC_ESR_LINE|CEC_ESR_TBTFE)
|
||||
#define CEC_RXXFERSIZE_INITIALIZE 0xFFFF /*!< Value used to initialise the RxXferSize of the handle */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup CEC_Private_Functions CEC Private Functions
|
||||
* @{
|
||||
*/
|
||||
static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec);
|
||||
static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup CEC_Exported_Functions CEC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the CEC
|
||||
(+) The following parameters need to be configured:
|
||||
(++) TimingErrorFree
|
||||
(++) PeriodErrorFree
|
||||
(++) InitiatorAddress
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the CEC mode according to the specified
|
||||
* parameters in the CEC_InitTypeDef and creates the associated handle .
|
||||
* @param hcec CEC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Check the CEC handle allocation */
|
||||
if ((hcec == NULL) || (hcec->Init.RxBuffer == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
|
||||
assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(hcec->Init.TimingErrorFree));
|
||||
assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(hcec->Init.PeriodErrorFree));
|
||||
assert_param(IS_CEC_ADDRESS(hcec->Init.OwnAddress));
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcec->Lock = HAL_UNLOCKED;
|
||||
|
||||
hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
|
||||
if (hcec->MspInitCallback == NULL)
|
||||
{
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hcec->MspInitCallback(hcec);
|
||||
}
|
||||
#else
|
||||
if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcec->Lock = HAL_UNLOCKED;
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_CEC_MspInit(hcec);
|
||||
}
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_CEC_DISABLE(hcec);
|
||||
|
||||
/* Write to CEC Control Register */
|
||||
MODIFY_REG(hcec->Instance->CFGR, CEC_CFGR_FIELDS, hcec->Init.TimingErrorFree | hcec->Init.PeriodErrorFree);
|
||||
|
||||
/* Write to CEC Own Address Register */
|
||||
MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
|
||||
|
||||
/* Configure the prescaler to generate the required 50 microseconds time base.*/
|
||||
MODIFY_REG(hcec->Instance->PRES, CEC_PRES_PRES, 50U * (HAL_RCC_GetPCLK1Freq() / 1000000U) - 1U);
|
||||
|
||||
/* Enable the following CEC Interrupt */
|
||||
__HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
|
||||
|
||||
/* Enable the CEC Peripheral */
|
||||
__HAL_CEC_ENABLE(hcec);
|
||||
|
||||
hcec->ErrorCode = HAL_CEC_ERROR_NONE;
|
||||
hcec->gState = HAL_CEC_STATE_READY;
|
||||
hcec->RxState = HAL_CEC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the CEC peripheral
|
||||
* @param hcec CEC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Check the CEC handle allocation */
|
||||
if (hcec == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
if (hcec->MspDeInitCallback == NULL)
|
||||
{
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hcec->MspDeInitCallback(hcec);
|
||||
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_CEC_MspDeInit(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_RCC_CEC_FORCE_RESET();
|
||||
__HAL_RCC_CEC_RELEASE_RESET();
|
||||
|
||||
hcec->ErrorCode = HAL_CEC_ERROR_NONE;
|
||||
hcec->gState = HAL_CEC_STATE_RESET;
|
||||
hcec->RxState = HAL_CEC_STATE_RESET;
|
||||
|
||||
/* Process Unlock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the Own Address of the CEC device
|
||||
* @param hcec CEC handle
|
||||
* @param CEC_OwnAddress The CEC own address.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress));
|
||||
|
||||
if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_CEC_DISABLE(hcec);
|
||||
|
||||
if (CEC_OwnAddress != CEC_OWN_ADDRESS_NONE)
|
||||
{
|
||||
MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcec->Instance->OAR, CEC_OAR_OA);
|
||||
}
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_READY;
|
||||
hcec->ErrorCode = HAL_CEC_ERROR_NONE;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_CEC_ENABLE(hcec);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CEC MSP Init
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcec);
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CEC_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CEC MSP DeInit
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcec);
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CEC_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User CEC Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
|
||||
* @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID,
|
||||
pCEC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (hcec->gState == HAL_CEC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_TX_CPLT_CB_ID :
|
||||
hcec->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_ERROR_CB_ID :
|
||||
hcec->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an CEC Callback
|
||||
* CEC callback is redirected to the weak predefined callback
|
||||
* @param hcec uart handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
|
||||
* @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (hcec->gState == HAL_CEC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_TX_CPLT_CB_ID :
|
||||
hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_CEC_ERROR_CB_ID :
|
||||
hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register CEC RX complete Callback
|
||||
* To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @param pCallback pointer to the Rx transfer compelete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (HAL_CEC_STATE_READY == hcec->RxState)
|
||||
{
|
||||
hcec->RxCpltCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UnRegister CEC RX complete Callback
|
||||
* CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (HAL_CEC_STATE_READY == hcec->RxState)
|
||||
{
|
||||
hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak CEC RxCpltCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief CEC Transmit/Receive functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
This subsection provides a set of functions allowing to manage the CEC data transfers.
|
||||
|
||||
(#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
|
||||
logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
|
||||
|
||||
(#) The communication is performed using Interrupts.
|
||||
These API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated CEC IRQ when using Interrupt mode.
|
||||
The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_CEC_ErrorCallback() user callback will be executed when a communication
|
||||
error is detected
|
||||
|
||||
(#) API's with Interrupt are :
|
||||
(+) HAL_CEC_Transmit_IT()
|
||||
(+) HAL_CEC_IRQHandler()
|
||||
|
||||
(#) A set of User Callbacks are provided:
|
||||
(+) HAL_CEC_TxCpltCallback()
|
||||
(+) HAL_CEC_RxCpltCallback()
|
||||
(+) HAL_CEC_ErrorCallback()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send data in interrupt mode
|
||||
* @param hcec CEC handle
|
||||
* @param InitiatorAddress Initiator address
|
||||
* @param DestinationAddress destination logical address
|
||||
* @param pData pointer to input byte data buffer
|
||||
* @param Size amount of data to be sent in bytes (without counting the header).
|
||||
* 0 means only the header is sent (ping operation).
|
||||
* Maximum TX size is 15 bytes (1 opcode and up to 14 operands).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress,
|
||||
const uint8_t *pData, uint32_t Size)
|
||||
{
|
||||
/* if the peripheral isn't already busy and if there is no previous transmission
|
||||
already pending due to arbitration lost */
|
||||
if (hcec->gState == HAL_CEC_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) && (Size > 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
assert_param(IS_CEC_ADDRESS(DestinationAddress));
|
||||
assert_param(IS_CEC_ADDRESS(InitiatorAddress));
|
||||
assert_param(IS_CEC_MSGSIZE(Size));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hcec);
|
||||
hcec->pTxBuffPtr = pData;
|
||||
hcec->gState = HAL_CEC_STATE_BUSY_TX;
|
||||
hcec->ErrorCode = HAL_CEC_ERROR_NONE;
|
||||
|
||||
/* initialize the number of bytes to send,
|
||||
* 0 means only one header is sent (ping operation) */
|
||||
hcec->TxXferCount = Size;
|
||||
|
||||
/* send header block */
|
||||
hcec->Instance->TXD = (uint8_t)((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
/* case no data to be sent, sender is only pinging the system */
|
||||
if (Size != 0)
|
||||
{
|
||||
/* Set TX Start of Message (TXSOM) bit */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TSOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send a ping command */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM | CEC_FLAG_TSOM);
|
||||
}
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get size of the received frame.
|
||||
* @param hcec CEC handle
|
||||
* @retval Frame size
|
||||
*/
|
||||
uint32_t HAL_CEC_GetLastReceivedFrameSize(const CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
return hcec->RxXferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change Rx Buffer.
|
||||
* @param hcec CEC handle
|
||||
* @param Rxbuffer Rx Buffer
|
||||
* @note This function can be called only inside the HAL_CEC_RxCpltCallback()
|
||||
* @retval Frame size
|
||||
*/
|
||||
void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer)
|
||||
{
|
||||
hcec->Init.RxBuffer = Rxbuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles CEC interrupt requests.
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
|
||||
/* save interrupts register for further error or interrupts handling purposes */
|
||||
uint32_t itflag;
|
||||
itflag = hcec->Instance->CSR;
|
||||
|
||||
/* Save error status register for further error handling purposes */
|
||||
hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
|
||||
|
||||
/* Transmit error */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TERR))
|
||||
{
|
||||
/* Acknowledgement of the error */
|
||||
__HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_READY;
|
||||
}
|
||||
|
||||
/* Receive error */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RERR))
|
||||
{
|
||||
/* Acknowledgement of the error */
|
||||
__HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
|
||||
hcec->Init.RxBuffer -= hcec->RxXferSize;
|
||||
hcec->RxXferSize = 0U;
|
||||
hcec->RxState = HAL_CEC_STATE_READY;
|
||||
}
|
||||
|
||||
if ((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0U)
|
||||
{
|
||||
/* Error Call Back */
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->ErrorCallback(hcec);
|
||||
#else
|
||||
HAL_CEC_ErrorCallback(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Transmit byte request or block transfer finished */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TBTRF))
|
||||
{
|
||||
CEC_Transmit_IT(hcec);
|
||||
}
|
||||
|
||||
/* Receive byte or block transfer finished */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RBTF))
|
||||
{
|
||||
if (hcec->RxXferSize == 0U)
|
||||
{
|
||||
/* reception is starting */
|
||||
hcec->RxState = HAL_CEC_STATE_BUSY_RX;
|
||||
}
|
||||
CEC_Receive_IT(hcec);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callback
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcec);
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CEC_TxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callback
|
||||
* @param hcec CEC handle
|
||||
* @param RxFrameSize Size of frame
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcec);
|
||||
UNUSED(RxFrameSize);
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CEC_RxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CEC error callbacks
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcec);
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CEC_ErrorCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CEC_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief CEC control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control function #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the CEC.
|
||||
(+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral.
|
||||
(+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief return the CEC state
|
||||
* @param hcec pointer to a CEC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CEC module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_CEC_StateTypeDef HAL_CEC_GetState(const CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
uint32_t temp1;
|
||||
uint32_t temp2;
|
||||
temp1 = hcec->gState;
|
||||
temp2 = hcec->RxState;
|
||||
|
||||
return (HAL_CEC_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the CEC error code
|
||||
* @param hcec pointer to a CEC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CEC.
|
||||
* @retval CEC Error Code
|
||||
*/
|
||||
uint32_t HAL_CEC_GetError(const CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
return hcec->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup CEC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send data in interrupt mode
|
||||
* @param hcec CEC handle.
|
||||
* Function called under interruption only, once
|
||||
* interruptions have been enabled by HAL_CEC_Transmit_IT()
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
/* if the peripheral is already busy or if there is a previous transmission
|
||||
already pending due to arbitration loss */
|
||||
if ((hcec->gState == HAL_CEC_STATE_BUSY_TX) || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET))
|
||||
{
|
||||
/* if all data have been sent */
|
||||
if (hcec->TxXferCount == 0U)
|
||||
{
|
||||
/* Acknowledge successful completion by writing 0x00 */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_READY;
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->TxCpltCallback(hcec);
|
||||
#else
|
||||
HAL_CEC_TxCpltCallback(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reduce the number of bytes to transfer by one */
|
||||
hcec->TxXferCount--;
|
||||
|
||||
/* Write data to TX buffer*/
|
||||
hcec->Instance->TXD = (uint8_t) * hcec->pTxBuffPtr++;
|
||||
|
||||
/* If this is the last byte of the ongoing transmission */
|
||||
if (hcec->TxXferCount == 0U)
|
||||
{
|
||||
/* Acknowledge byte request and signal end of message */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Acknowledge byte request by writing 0x00 */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive data in interrupt mode.
|
||||
* @param hcec CEC handle.
|
||||
* Function called under interruption only, once
|
||||
* interruptions have been enabled by HAL_CEC_Receive_IT()
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
static uint32_t temp;
|
||||
|
||||
if (hcec->RxState == HAL_CEC_STATE_BUSY_RX)
|
||||
{
|
||||
temp = hcec->Instance->CSR;
|
||||
|
||||
/* Store received data */
|
||||
hcec->RxXferSize++;
|
||||
*hcec->Init.RxBuffer++ = hcec->Instance->RXD;
|
||||
|
||||
/* Acknowledge received byte by writing 0x00 */
|
||||
MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK, 0x00U);
|
||||
|
||||
/* If the End Of Message is reached */
|
||||
if (HAL_IS_BIT_SET(temp, CEC_FLAG_REOM))
|
||||
{
|
||||
/* Interrupts are not disabled due to transmission still ongoing */
|
||||
hcec->RxState = HAL_CEC_STATE_READY;
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->RxCpltCallback(hcec, hcec->RxXferSize);
|
||||
#else
|
||||
HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* CEC */
|
||||
|
||||
#endif /* HAL_CEC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
328
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_crc.c
Normal file
328
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_crc.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_crc.c
|
||||
* @author MCD Application Team
|
||||
* @brief CRC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Cyclic Redundancy Check (CRC) peripheral:
|
||||
* + Initialization and de-initialization 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 CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE();
|
||||
(+) Initialize CRC calculator
|
||||
(++) specify generating polynomial (peripheral default or non-default one)
|
||||
(++) specify initialization value (peripheral default or non-default one)
|
||||
(++) specify input data format
|
||||
(++) specify input or output data inversion mode if any
|
||||
(+) Use HAL_CRC_Accumulate() function to compute the CRC value of the
|
||||
input data buffer starting with the previously computed CRC as
|
||||
initialization value
|
||||
(+) Use HAL_CRC_Calculate() function to compute the CRC value of the
|
||||
input data buffer starting with the defined initialization value
|
||||
(default or non-default) to initiate CRC calculation
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CRC CRC
|
||||
* @brief CRC HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions CRC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_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 the CRC according to the specified parameters
|
||||
in the CRC_InitTypeDef and create the associated handle
|
||||
(+) DeInitialize the CRC peripheral
|
||||
(+) Initialize the CRC MSP (MCU Specific Package)
|
||||
(+) DeInitialize the CRC MSP
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the CRC according to the specified
|
||||
* parameters in the CRC_InitTypeDef and create the associated handle.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Check the CRC handle allocation */
|
||||
if (hcrc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
|
||||
|
||||
if (hcrc->State == HAL_CRC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcrc->Lock = HAL_UNLOCKED;
|
||||
/* Init the low level hardware */
|
||||
HAL_CRC_MspInit(hcrc);
|
||||
}
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the CRC peripheral.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Check the CRC handle allocation */
|
||||
if (hcrc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
|
||||
|
||||
/* Check the CRC peripheral state */
|
||||
if (hcrc->State == HAL_CRC_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Reset CRC calculation unit */
|
||||
__HAL_CRC_DR_RESET(hcrc);
|
||||
|
||||
/* Reset IDR register content */
|
||||
__HAL_CRC_SET_IDR(hcrc, 0);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
HAL_CRC_MspDeInit(hcrc);
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_RESET;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hcrc);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the CRC MSP.
|
||||
* @param hcrc CRC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcrc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CRC_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the CRC MSP.
|
||||
* @param hcrc CRC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcrc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CRC_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief management functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) compute the 32-bit CRC value of a 32-bit data buffer
|
||||
using combination of the previous CRC value and the new one.
|
||||
|
||||
[..] or
|
||||
|
||||
(+) compute the 32-bit CRC value of a 32-bit data buffer
|
||||
independently of the previous CRC value.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Compute the 32-bit CRC value of a 32-bit data buffer
|
||||
* starting with the previously computed CRC as initialization value.
|
||||
* @param hcrc CRC handle
|
||||
* @param pBuffer pointer to the input data buffer.
|
||||
* @param BufferLength input data buffer length (number of uint32_t words).
|
||||
* @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*/
|
||||
uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
|
||||
{
|
||||
uint32_t index; /* CRC input data buffer index */
|
||||
uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Enter Data to the CRC calculator */
|
||||
for (index = 0U; index < BufferLength; index++)
|
||||
{
|
||||
hcrc->Instance->DR = pBuffer[index];
|
||||
}
|
||||
temp = hcrc->Instance->DR;
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return the CRC computed value */
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the 32-bit CRC value of a 32-bit data buffer
|
||||
* starting with hcrc->Instance->INIT as initialization value.
|
||||
* @param hcrc CRC handle
|
||||
* @param pBuffer pointer to the input data buffer.
|
||||
* @param BufferLength input data buffer length (number of uint32_t words).
|
||||
* @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*/
|
||||
uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
|
||||
{
|
||||
uint32_t index; /* CRC input data buffer index */
|
||||
uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Reset CRC Calculation Unit (hcrc->Instance->INIT is
|
||||
* written in hcrc->Instance->DR) */
|
||||
__HAL_CRC_DR_RESET(hcrc);
|
||||
|
||||
/* Enter 32-bit input data to the CRC calculator */
|
||||
for (index = 0U; index < BufferLength; index++)
|
||||
{
|
||||
hcrc->Instance->DR = pBuffer[index];
|
||||
}
|
||||
temp = hcrc->Instance->DR;
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return the CRC computed value */
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
|
||||
* @brief Peripheral State functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the CRC handle state.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_CRC_StateTypeDef HAL_CRC_GetState(const CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Return CRC handle state */
|
||||
return hcrc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
1418
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dac.c
Normal file
1418
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dac.c
Normal file
@@ -0,0 +1,1418 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_dac.c
|
||||
* @author MCD Application Team
|
||||
* @brief DAC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Digital to Analog Converter (DAC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors 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
|
||||
==============================================================================
|
||||
##### DAC Peripheral features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
*** DAC Channels ***
|
||||
====================
|
||||
[..]
|
||||
STM32F1 devices integrate two 12-bit Digital Analog Converters
|
||||
|
||||
The 2 converters (i.e. channel1 & channel2)
|
||||
can be used independently or simultaneously (dual mode):
|
||||
(#) DAC channel1 with DAC_OUT1 (PA4) as output or connected to on-chip
|
||||
peripherals (ex. timers).
|
||||
(#) DAC channel2 with DAC_OUT2 (PA5) as output or connected to on-chip
|
||||
peripherals (ex. timers).
|
||||
|
||||
*** DAC Triggers ***
|
||||
====================
|
||||
[..]
|
||||
Digital to Analog conversion can be non-triggered using DAC_TRIGGER_NONE
|
||||
and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register.
|
||||
[..]
|
||||
Digital to Analog conversion can be triggered by:
|
||||
(#) External event: EXTI Line 9 (any GPIOx_PIN_9) using DAC_TRIGGER_EXT_IT9.
|
||||
The used pin (GPIOx_PIN_9) must be configured in input mode.
|
||||
|
||||
(#) Timers TRGO: TIM2, TIM4, TIM6, TIM7
|
||||
For STM32F10x connectivity line devices and STM32F100x devices: TIM3
|
||||
For STM32F10x high-density and XL-density devices: TIM8
|
||||
For STM32F100x high-density value line devices: TIM15 as
|
||||
replacement of TIM5.
|
||||
(DAC_TRIGGER_T2_TRGO, DAC_TRIGGER_T4_TRGO...)
|
||||
|
||||
(#) Software using DAC_TRIGGER_SOFTWARE
|
||||
|
||||
*** DAC Buffer mode feature ***
|
||||
===============================
|
||||
[..]
|
||||
Each DAC channel integrates an output buffer that can be used to
|
||||
reduce the output impedance, and to drive external loads directly
|
||||
without having to add an external operational amplifier.
|
||||
To enable, the output buffer use
|
||||
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
|
||||
[..]
|
||||
(@) Refer to the device datasheet for more details about output
|
||||
impedance value with and without output buffer.
|
||||
|
||||
*** GPIO configurations guidelines ***
|
||||
=====================
|
||||
[..]
|
||||
When a DAC channel is used (ex channel1 on PA4) and the other is not
|
||||
(ex channel2 on PA5 is configured in Analog and disabled).
|
||||
Channel1 may disturb channel2 as coupling effect.
|
||||
Note that there is no coupling on channel2 as soon as channel2 is turned on.
|
||||
Coupling on adjacent channel could be avoided as follows:
|
||||
when unused PA5 is configured as INPUT PULL-UP or DOWN.
|
||||
PA5 is configured in ANALOG just before it is turned on.
|
||||
|
||||
*** DAC wave generation feature ***
|
||||
===================================
|
||||
[..]
|
||||
Both DAC channels can be used to generate
|
||||
(#) Noise wave
|
||||
(#) Triangle wave
|
||||
|
||||
*** DAC data format ***
|
||||
=======================
|
||||
[..]
|
||||
The DAC data format can be:
|
||||
(#) 8-bit right alignment using DAC_ALIGN_8B_R
|
||||
(#) 12-bit left alignment using DAC_ALIGN_12B_L
|
||||
(#) 12-bit right alignment using DAC_ALIGN_12B_R
|
||||
|
||||
*** DAC data value to voltage correspondence ***
|
||||
================================================
|
||||
[..]
|
||||
The analog output voltage on each DAC channel pin is determined
|
||||
by the following equation:
|
||||
[..]
|
||||
DAC_OUTx = VREF+ * DOR / 4095
|
||||
(+) with DOR is the Data Output Register
|
||||
[..]
|
||||
VREF+ is the input voltage reference (refer to the device datasheet)
|
||||
[..]
|
||||
e.g. To set DAC_OUT1 to 0.7V, use
|
||||
(+) Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
|
||||
|
||||
*** DMA requests ***
|
||||
=====================
|
||||
[..]
|
||||
A DMA request can be generated when an external trigger (but not a software trigger)
|
||||
occurs if DMA1 requests are enabled using HAL_DAC_Start_DMA().
|
||||
DMA1 requests are mapped as following:
|
||||
(#) DAC channel1 mapped on DMA1 channel3
|
||||
for STM32F100x low-density, medium-density, high-density with DAC
|
||||
DMA remap:
|
||||
(#) DAC channel2 mapped on DMA2 channel3
|
||||
for STM32F100x high-density without DAC DMA remap and other
|
||||
STM32F1 devices
|
||||
|
||||
[..]
|
||||
(@) For Dual mode and specific signal (Triangle and noise) generation please
|
||||
refer to Extended Features Driver description
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) DAC APB clock must be enabled to get write access to DAC
|
||||
registers using HAL_DAC_Init()
|
||||
(+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
|
||||
(+) Configure the DAC channel using HAL_DAC_ConfigChannel() function.
|
||||
(+) Enable the DAC channel using HAL_DAC_Start() or HAL_DAC_Start_DMA() functions.
|
||||
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Start the DAC peripheral using HAL_DAC_Start()
|
||||
(+) To read the DAC last data output value, use the HAL_DAC_GetValue() function.
|
||||
(+) Stop the DAC peripheral using HAL_DAC_Stop()
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Start the DAC peripheral using HAL_DAC_Start_DMA(), at this stage the user specify the length
|
||||
of data to be transferred at each end of conversion
|
||||
First issued trigger will start the conversion of the value previously set by HAL_DAC_SetValue().
|
||||
(+) At the middle of data transfer HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
(+) At The end of data transfer HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
(+) In case of transfer Error, HAL_DAC_ErrorCallbackCh1() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1
|
||||
(+) For STM32F100x devices with specific feature: DMA underrun.
|
||||
In case of DMA underrun, DAC interruption triggers and execute internal function HAL_DAC_IRQHandler.
|
||||
HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2() and
|
||||
add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1()
|
||||
(+) Stop the DAC peripheral using HAL_DAC_Stop_DMA()
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_DAC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_DAC_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
|
||||
(+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
|
||||
(+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
|
||||
(+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
|
||||
(+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
|
||||
(+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
|
||||
(+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
|
||||
(+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
|
||||
(+) MspInitCallback : DAC MspInit.
|
||||
(+) MspDeInitCallback : DAC MspdeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_DAC_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
|
||||
(+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
|
||||
(+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
|
||||
(+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
|
||||
(+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
|
||||
(+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
|
||||
(+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
|
||||
(+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
|
||||
(+) MspInitCallback : DAC MspInit.
|
||||
(+) MspDeInitCallback : DAC MspdeInit.
|
||||
(+) All Callbacks
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_DAC_Init and if the state is HAL_DAC_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_DAC_Init
|
||||
and HAL_DAC_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_DAC_Init and HAL_DAC_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_DAC_RegisterCallback before calling HAL_DAC_DeInit
|
||||
or HAL_DAC_Init function.
|
||||
|
||||
When The compilation define USE_HAL_DAC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
*** DAC HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in DAC HAL driver.
|
||||
|
||||
(+) __HAL_DAC_ENABLE : Enable the DAC peripheral (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_DISABLE : Disable the DAC peripheral (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_CLEAR_FLAG: Clear the DAC's pending flags (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_GET_FLAG: Get the selected DAC's flag status (For STM32F100x devices with specific feature: DMA underrun)
|
||||
|
||||
[..]
|
||||
(@) You can refer to the DAC HAL driver header file for more useful macros
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#if defined(DAC)
|
||||
|
||||
/** @defgroup DAC DAC
|
||||
* @brief DAC driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions -------------------------------------------------------*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions DAC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_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 DAC.
|
||||
(+) De-initialize the DAC.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the DAC peripheral according to the specified parameters
|
||||
* in the DAC_InitStruct and initialize the associated handle.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/* Init the DAC Callback settings */
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
|
||||
if (hdac->MspInitCallback == NULL)
|
||||
{
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
}
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Allocate lock resource and initialize it */
|
||||
hdac->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/* Init the low level hardware */
|
||||
hdac->MspInitCallback(hdac);
|
||||
#else
|
||||
/* Init the low level hardware */
|
||||
HAL_DAC_MspInit(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize the DAC state*/
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Set DAC error code to none */
|
||||
hdac->ErrorCode = HAL_DAC_ERROR_NONE;
|
||||
|
||||
/* Initialize the DAC state*/
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the DAC peripheral registers to their default reset values.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_DeInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
if (hdac->MspDeInitCallback == NULL)
|
||||
{
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hdac->MspDeInitCallback(hdac);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_DAC_MspDeInit(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Set DAC error code to none */
|
||||
hdac->ErrorCode = HAL_DAC_ERROR_NONE;
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the DAC MSP.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the DAC MSP.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_MspDeInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Start conversion.
|
||||
(+) Stop conversion.
|
||||
(+) Start conversion and enable DMA transfer.
|
||||
(+) Stop conversion and disable DMA transfer.
|
||||
(+) Get result of conversion.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, Channel);
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
|
||||
{
|
||||
/* Enable the selected DAC software conversion */
|
||||
SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG1);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (Channel & 0x10UL)))
|
||||
{
|
||||
/* Enable the selected DAC software conversion*/
|
||||
SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, Channel);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param pData The source Buffer address.
|
||||
* @param Length The length of data to be transferred from memory to DAC peripheral
|
||||
* @param Alignment Specifies the data alignment for DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, const uint32_t *pData, uint32_t Length,
|
||||
uint32_t Alignment)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
uint32_t tmpreg;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Set the DMA transfer complete callback for channel1 */
|
||||
hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
|
||||
|
||||
/* Set the DMA half transfer complete callback for channel1 */
|
||||
hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
|
||||
|
||||
/* Set the DMA error callback for channel1 */
|
||||
hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
|
||||
|
||||
/* Enable the selected DAC channel1 DMA request */
|
||||
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
|
||||
|
||||
/* Case of use of channel 1 */
|
||||
switch (Alignment)
|
||||
{
|
||||
case DAC_ALIGN_12B_R:
|
||||
/* Get DHR12R1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
|
||||
break;
|
||||
case DAC_ALIGN_12B_L:
|
||||
/* Get DHR12L1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
|
||||
break;
|
||||
default: /* case DAC_ALIGN_8B_R */
|
||||
/* Get DHR8R1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Set the DMA transfer complete callback for channel2 */
|
||||
hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
|
||||
|
||||
/* Set the DMA half transfer complete callback for channel2 */
|
||||
hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
|
||||
|
||||
/* Set the DMA error callback for channel2 */
|
||||
hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
|
||||
|
||||
/* Enable the selected DAC channel2 DMA request */
|
||||
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
|
||||
|
||||
/* Case of use of channel 2 */
|
||||
switch (Alignment)
|
||||
{
|
||||
case DAC_ALIGN_12B_R:
|
||||
/* Get DHR12R2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12R2;
|
||||
break;
|
||||
case DAC_ALIGN_12B_L:
|
||||
/* Get DHR12L2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12L2;
|
||||
break;
|
||||
default: /* case DAC_ALIGN_8B_R */
|
||||
/* Get DHR8R2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR8R2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
#if defined(DAC_CR_DMAUDRIE1)
|
||||
/* Enable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
|
||||
#endif /* DAC_CR_DMAUDRIE1 */
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
#if defined(DAC_CR_DMAUDRIE2)
|
||||
/* Enable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
|
||||
#endif /* DAC_CR_DMAUDRIE2 */
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
|
||||
}
|
||||
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Disable the selected DAC channel DMA request */
|
||||
hdac->Instance->CR &= ~(DAC_CR_DMAEN1 << (Channel & 0x10UL));
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, Channel);
|
||||
|
||||
/* Disable the DMA Stream */
|
||||
|
||||
/* Channel1 is used */
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Disable the DMA Stream */
|
||||
(void)HAL_DMA_Abort(hdac->DMA_Handle1);
|
||||
|
||||
#if defined(DAC_CR_DMAUDRIE1)
|
||||
/* Disable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
|
||||
#endif /* DAC_CR_DMAUDRIE1 */
|
||||
}
|
||||
|
||||
else /* Channel2 is used for */
|
||||
{
|
||||
/* Disable the DMA Stream */
|
||||
(void)HAL_DMA_Abort(hdac->DMA_Handle2);
|
||||
|
||||
#if defined(DAC_CR_DMAUDRIE2)
|
||||
/* Disable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
|
||||
#endif /* DAC_CR_DMAUDRIE2 */
|
||||
}
|
||||
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles DAC interrupt request
|
||||
* This function uses the interruption of DMA
|
||||
* underrun.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_DAC_IRQHandler(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
#if !defined(DAC_SR_DMAUDR1) && !defined(DAC_SR_DMAUDR2)
|
||||
UNUSED(hdac);
|
||||
#else
|
||||
uint32_t itsource = hdac->Instance->CR;
|
||||
uint32_t itflag = hdac->Instance->SR;
|
||||
#endif /* !DAC_SR_DMAUDR1 && !DAC_SR_DMAUDR2 */
|
||||
|
||||
#if defined(DAC_SR_DMAUDR1)
|
||||
if ((itsource & DAC_IT_DMAUDR1) == DAC_IT_DMAUDR1)
|
||||
{
|
||||
/* Check underrun flag of DAC channel 1 */
|
||||
if ((itflag & DAC_FLAG_DMAUDR1) == DAC_FLAG_DMAUDR1)
|
||||
{
|
||||
/* Change DAC state to error state */
|
||||
hdac->State = HAL_DAC_STATE_ERROR;
|
||||
|
||||
/* Set DAC error code to channel1 DMA underrun error */
|
||||
SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH1);
|
||||
|
||||
/* Clear the underrun flag */
|
||||
__HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR1);
|
||||
|
||||
/* Disable the selected DAC channel1 DMA request */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_CR_DMAEN1);
|
||||
|
||||
/* Error callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->DMAUnderrunCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_DMAUnderrunCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
#endif /* DAC_SR_DMAUDR1 */
|
||||
|
||||
#if defined(DAC_SR_DMAUDR2)
|
||||
if ((itsource & DAC_IT_DMAUDR2) == DAC_IT_DMAUDR2)
|
||||
{
|
||||
/* Check underrun flag of DAC channel 2 */
|
||||
if ((itflag & DAC_FLAG_DMAUDR2) == DAC_FLAG_DMAUDR2)
|
||||
{
|
||||
/* Change DAC state to error state */
|
||||
hdac->State = HAL_DAC_STATE_ERROR;
|
||||
|
||||
/* Set DAC error code to channel2 DMA underrun error */
|
||||
SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH2);
|
||||
|
||||
/* Clear the underrun flag */
|
||||
__HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR2);
|
||||
|
||||
/* Disable the selected DAC channel2 DMA request */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_CR_DMAEN2);
|
||||
|
||||
/* Error callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->DMAUnderrunCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_DMAUnderrunCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
#endif /* DAC_SR_DMAUDR2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the specified data holding register value for DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Alignment Specifies the data alignment.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @param Data Data to be loaded in the selected data holding register.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
|
||||
{
|
||||
__IO uint32_t tmp = 0UL;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
assert_param(IS_DAC_DATA(Data));
|
||||
|
||||
tmp = (uint32_t)hdac->Instance;
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
tmp += DAC_DHR12R1_ALIGNMENT(Alignment);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
tmp += DAC_DHR12R2_ALIGNMENT(Alignment);
|
||||
}
|
||||
|
||||
|
||||
/* Set the DAC channel selected data holding register */
|
||||
*(__IO uint32_t *) tmp = Data;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion complete callback in non-blocking mode for Channel1
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ConvCpltCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion half DMA transfer callback in non-blocking mode for Channel1
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ConvHalfCpltCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error DAC callback for Channel1.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ErrorCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA underrun DAC callback for channel1.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_DMAUnderrunCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_DMAUnderrunCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure channels.
|
||||
(+) Set the specified data holding register value for DAC channel.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the last data output value of the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval The selected DAC channel data output value.
|
||||
*/
|
||||
uint32_t HAL_DAC_GetValue(const DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
assert_param(hdac != NULL);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
result = hdac->Instance->DOR1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
result = hdac->Instance->DOR2;
|
||||
}
|
||||
|
||||
/* Returns the DAC channel data output register value */
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param sConfig DAC configuration structure.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac,
|
||||
const DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpreg1;
|
||||
uint32_t tmpreg2;
|
||||
|
||||
/* Check the DAC peripheral handle and channel configuration struct */
|
||||
if ((hdac == NULL) || (sConfig == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the DAC parameters */
|
||||
assert_param(IS_DAC_TRIGGER(sConfig->DAC_Trigger));
|
||||
assert_param(IS_DAC_OUTPUT_BUFFER_STATE(sConfig->DAC_OutputBuffer));
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Get the DAC CR value */
|
||||
tmpreg1 = hdac->Instance->CR;
|
||||
/* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
|
||||
tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1 | DAC_CR_BOFF1))
|
||||
<< (Channel & 0x10UL));
|
||||
/* Configure for the selected DAC channel: buffer output, trigger */
|
||||
/* Set TSELx and TENx bits according to DAC_Trigger value */
|
||||
/* Set BOFFx bit according to DAC_OutputBuffer value */
|
||||
tmpreg2 = (sConfig->DAC_Trigger | sConfig->DAC_OutputBuffer);
|
||||
/* Calculate CR register value depending on DAC_Channel */
|
||||
tmpreg1 |= tmpreg2 << (Channel & 0x10UL);
|
||||
/* Write to DAC CR */
|
||||
hdac->Instance->CR = tmpreg1;
|
||||
/* Disable wave generation */
|
||||
CLEAR_BIT(hdac->Instance->CR, (DAC_CR_WAVE1 << (Channel & 0x10UL)));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group4 Peripheral State and Errors functions
|
||||
* @brief Peripheral State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Check the DAC state.
|
||||
(+) Check the DAC Errors.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the DAC handle state
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_DAC_StateTypeDef HAL_DAC_GetState(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Return DAC handle state */
|
||||
return hdac->State;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the DAC error code
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval DAC Error Code
|
||||
*/
|
||||
uint32_t HAL_DAC_GetError(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
return hdac->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User DAC Callback
|
||||
* To be used instead of the weak (overridden) predefined callback
|
||||
* @note The HAL_DAC_RegisterCallback() may be called before HAL_DAC_Init() in HAL_DAC_STATE_RESET to register
|
||||
* callbacks for HAL_DAC_MSPINIT_CB_ID and HAL_DAC_MSPDEINIT_CB_ID
|
||||
* @param hdac DAC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_DAC_ERROR_INVALID_CALLBACK DAC Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
|
||||
* @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
|
||||
*
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID,
|
||||
pDAC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_CH1_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_ERROR_ID :
|
||||
hdac->ErrorCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh1 = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DAC_CH2_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_ERROR_ID :
|
||||
hdac->ErrorCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh2 = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User DAC Callback
|
||||
* DAC Callback is redirected to the weak (overridden) predefined callback
|
||||
* @note The HAL_DAC_UnRegisterCallback() may be called before HAL_DAC_Init() in HAL_DAC_STATE_RESET to un-register
|
||||
* callbacks for HAL_DAC_MSPINIT_CB_ID and HAL_DAC_MSPDEINIT_CB_ID
|
||||
* @param hdac DAC handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 transfer Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
|
||||
* @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
|
||||
* @arg @ref HAL_DAC_ALL_CB_ID DAC All callbacks
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_UnRegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_CH1_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_ERROR_ID :
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
break;
|
||||
|
||||
case HAL_DAC_CH2_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_ERROR_ID :
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
break;
|
||||
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
case HAL_DAC_ALL_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA conversion complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAConvCpltCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvCpltCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ConvCpltCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA half transfer complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAHalfConvCpltCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvHalfCpltCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ConvHalfCpltCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA error callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAErrorCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Set DAC error code to DMA error */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ErrorCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ErrorCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,515 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_dac_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended DAC HAL module driver.
|
||||
* This file provides firmware functions to manage the extended
|
||||
* functionalities of the DAC peripheral.
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
*** Signal generation operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
|
||||
(+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
|
||||
#if defined(DAC)
|
||||
|
||||
/** @defgroup DACEx DACEx
|
||||
* @brief DAC Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions DACEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Extended IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Extended features functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Start conversion.
|
||||
(+) Stop conversion.
|
||||
(+) Start conversion and enable DMA transfer.
|
||||
(+) Stop conversion and disable DMA transfer.
|
||||
(+) Get result of conversion.
|
||||
(+) Get result of dual mode conversion.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of both channels.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
uint32_t tmp_swtrig = 0UL;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
|
||||
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
|
||||
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
|
||||
{
|
||||
tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
|
||||
}
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (DAC_CHANNEL_2 & 0x10UL)))
|
||||
{
|
||||
tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
|
||||
}
|
||||
/* Enable the selected DAC software conversion*/
|
||||
SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of both channels.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
|
||||
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the selected DAC channel wave generation.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Amplitude Select max triangle amplitude.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the triangle wave generation for the selected DAC channel */
|
||||
MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
|
||||
(DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the selected DAC channel wave generation.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Amplitude Unmask DAC channel LFSR for noise wave generation.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the noise wave generation for the selected DAC channel */
|
||||
MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
|
||||
(DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the specified data holding register value for dual DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Alignment Specifies the data alignment for dual channel DAC.
|
||||
* This parameter can be one of the following values:
|
||||
* DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @param Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
|
||||
* @param Data2 Data for DAC Channel2 to be loaded in the selected data holding register.
|
||||
* @note In dual mode, a unique register access is required to write in both
|
||||
* DAC channels at the same time.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t tmp;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
assert_param(IS_DAC_DATA(Data1));
|
||||
assert_param(IS_DAC_DATA(Data2));
|
||||
|
||||
/* Calculate and set dual DAC data holding register value */
|
||||
if (Alignment == DAC_ALIGN_8B_R)
|
||||
{
|
||||
data = ((uint32_t)Data2 << 8U) | Data1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = ((uint32_t)Data2 << 16U) | Data1;
|
||||
}
|
||||
|
||||
tmp = (uint32_t)hdac->Instance;
|
||||
tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
|
||||
|
||||
/* Set the dual DAC selected data holding register */
|
||||
*(__IO uint32_t *)tmp = data;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion complete callback in non-blocking mode for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion half DMA transfer callback in non-blocking mode for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error DAC callback for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA underrun DAC callback for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Set the specified data holding register value for DAC channel.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the last data output value of the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval The selected DAC channel data output value.
|
||||
*/
|
||||
uint32_t HAL_DACEx_DualGetValue(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
uint32_t tmp = 0UL;
|
||||
|
||||
tmp |= hdac->Instance->DOR1;
|
||||
|
||||
tmp |= hdac->Instance->DOR2 << 16UL;
|
||||
|
||||
/* Returns the DAC channel data output register value */
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup DACEx_Private_Functions DACEx private functions
|
||||
* @brief Extended private functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief DMA conversion complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvCpltCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ConvCpltCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA half transfer complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvHalfCpltCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA error callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Set DAC error code to DMA error */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ErrorCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ErrorCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
2290
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_eth.c
Normal file
2290
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_eth.c
Normal file
@@ -0,0 +1,2290 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_eth.c
|
||||
* @author MCD Application Team
|
||||
* @brief ETH HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Ethernet (ETH) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#)Declare a ETH_HandleTypeDef handle structure, for example:
|
||||
ETH_HandleTypeDef heth;
|
||||
|
||||
(#)Fill parameters of Init structure in heth handle
|
||||
|
||||
(#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...)
|
||||
|
||||
(#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API:
|
||||
(##) Enable the Ethernet interface clock using
|
||||
(+++) __HAL_RCC_ETHMAC_CLK_ENABLE();
|
||||
(+++) __HAL_RCC_ETHMACTX_CLK_ENABLE();
|
||||
(+++) __HAL_RCC_ETHMACRX_CLK_ENABLE();
|
||||
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure Ethernet pin-out
|
||||
(##) Configure Ethernet NVIC interrupt (IT mode)
|
||||
|
||||
(#)Initialize Ethernet DMA Descriptors in chain mode and point to allocated buffers:
|
||||
(##) HAL_ETH_DMATxDescListInit(); for Transmission process
|
||||
(##) HAL_ETH_DMARxDescListInit(); for Reception process
|
||||
|
||||
(#)Enable MAC and DMA transmission and reception:
|
||||
(##) HAL_ETH_Start();
|
||||
|
||||
(#)Prepare ETH DMA TX Descriptors and give the hand to ETH DMA to transfer
|
||||
the frame to MAC TX FIFO:
|
||||
(##) HAL_ETH_TransmitFrame();
|
||||
|
||||
(#)Poll for a received frame in ETH RX DMA Descriptors and get received
|
||||
frame parameters
|
||||
(##) HAL_ETH_GetReceivedFrame(); (should be called into an infinite loop)
|
||||
|
||||
(#) Get a received frame when an ETH RX interrupt occurs:
|
||||
(##) HAL_ETH_GetReceivedFrame_IT(); (called in IT mode only)
|
||||
|
||||
(#) Communicate with external PHY device:
|
||||
(##) Read a specific register from the PHY
|
||||
HAL_ETH_ReadPHYRegister();
|
||||
(##) Write data to a specific RHY register:
|
||||
HAL_ETH_WritePHYRegister();
|
||||
|
||||
(#) Configure the Ethernet MAC after ETH peripheral initialization
|
||||
HAL_ETH_ConfigMAC(); all MAC parameters should be filled.
|
||||
|
||||
(#) Configure the Ethernet DMA after ETH peripheral initialization
|
||||
HAL_ETH_ConfigDMA(); all DMA parameters should be filled.
|
||||
|
||||
-@- The PTP protocol and the DMA descriptors ring mode are not supported
|
||||
in this driver
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
|
||||
The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Function @ref HAL_ETH_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function @ref HAL_ETH_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) DMAErrorCallback : DMA Error Callback.
|
||||
(+) MspInitCallback : MspInit Callback.
|
||||
(+) MspDeInitCallback: MspDeInit Callback.
|
||||
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function @ref HAL_ETH_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
@ref HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) DMAErrorCallback : DMA Error Callback.
|
||||
(+) MspInitCallback : MspInit Callback.
|
||||
(+) MspDeInitCallback: MspDeInit Callback.
|
||||
|
||||
By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples @ref HAL_ETH_TxCpltCallback(), @ref HAL_ETH_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak function in the HAL_ETH_Init/ @ref HAL_ETH_DeInit only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ @ref HAL_ETH_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using @ref HAL_ETH_RegisterCallback() before calling @ref HAL_ETH_DeInit
|
||||
or HAL_ETH_Init function.
|
||||
|
||||
When The compilation define USE_HAL_ETH_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 ETH ETH
|
||||
* @brief ETH HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_ETH_MODULE_ENABLED
|
||||
|
||||
#if defined (ETH)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup ETH_Private_Constants ETH Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define ETH_TIMEOUT_SWRESET 500U
|
||||
#define ETH_TIMEOUT_LINKED_STATE 5000U
|
||||
#define ETH_TIMEOUT_AUTONEGO_COMPLETED 5000U
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ETH_Private_Functions ETH Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err);
|
||||
static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr);
|
||||
static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth);
|
||||
static void ETH_Delay(uint32_t mdelay);
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions ETH Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_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 Ethernet peripheral
|
||||
(+) De-initialize the Ethernet peripheral
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the Ethernet MAC and DMA according to default
|
||||
* parameters.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U, phyreg = 0U;
|
||||
uint32_t hclk = 60000000U;
|
||||
uint32_t tickstart = 0U;
|
||||
uint32_t err = ETH_SUCCESS;
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_AUTONEGOTIATION(heth->Init.AutoNegotiation));
|
||||
assert_param(IS_ETH_RX_MODE(heth->Init.RxMode));
|
||||
assert_param(IS_ETH_CHECKSUM_MODE(heth->Init.ChecksumMode));
|
||||
assert_param(IS_ETH_MEDIA_INTERFACE(heth->Init.MediaInterface));
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
heth->Lock = HAL_UNLOCKED;
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
ETH_InitCallbacksToDefault(heth);
|
||||
|
||||
if (heth->MspInitCallback == NULL)
|
||||
{
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
}
|
||||
heth->MspInitCallback(heth);
|
||||
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
HAL_ETH_MspInit(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Select MII or RMII Mode*/
|
||||
AFIO->MAPR &= ~(AFIO_MAPR_MII_RMII_SEL);
|
||||
AFIO->MAPR |= (uint32_t)heth->Init.MediaInterface;
|
||||
|
||||
/* Ethernet Software reset */
|
||||
/* Set the SWR bit: resets all MAC subsystem internal registers and logic */
|
||||
/* After reset all the registers holds their respective reset values */
|
||||
(heth->Instance)->DMABMR |= ETH_DMABMR_SR;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for software reset */
|
||||
while (((heth->Instance)->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_SWRESET)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_TIMEOUT;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Note: The SWR is not performed if the ETH_RX_CLK or the ETH_TX_CLK are
|
||||
not available, please check your external PHY or the IO configuration */
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------- MAC Initialization ----------------------*/
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = (heth->Instance)->MACMIIAR;
|
||||
/* Clear CSR Clock Range CR[2:0] bits */
|
||||
tmpreg1 &= ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Get hclk frequency value */
|
||||
hclk = HAL_RCC_GetHCLKFreq();
|
||||
|
||||
/* Set CR bits depending on hclk value */
|
||||
if ((hclk >= 20000000U) && (hclk < 35000000U))
|
||||
{
|
||||
/* CSR Clock Range between 20-35 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV16;
|
||||
}
|
||||
else if ((hclk >= 35000000U) && (hclk < 60000000U))
|
||||
{
|
||||
/* CSR Clock Range between 35-60 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV26;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CSR Clock Range between 60-72 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV42;
|
||||
}
|
||||
|
||||
/* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */
|
||||
(heth->Instance)->MACMIIAR = (uint32_t)tmpreg1;
|
||||
|
||||
/*-------------------- PHY initialization and configuration ----------------*/
|
||||
/* Put the PHY in reset mode */
|
||||
if ((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_RESET)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Delay to assure PHY reset */
|
||||
HAL_Delay(PHY_RESET_DELAY);
|
||||
|
||||
if ((heth->Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* We wait for linked status */
|
||||
do
|
||||
{
|
||||
HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_LINKED_STATE)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));
|
||||
|
||||
|
||||
/* Enable Auto-Negotiation */
|
||||
if ((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_AUTONEGOTIATION)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until the auto-negotiation will be completed */
|
||||
do
|
||||
{
|
||||
HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_AUTONEGO_COMPLETED)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
}
|
||||
while (((phyreg & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
|
||||
|
||||
/* Read the result of the auto-negotiation */
|
||||
if ((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
|
||||
if ((phyreg & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
|
||||
{
|
||||
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
|
||||
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
|
||||
(heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
/* Configure the MAC with the speed fixed by the auto-negotiation process */
|
||||
if ((phyreg & PHY_SPEED_STATUS) == PHY_SPEED_STATUS)
|
||||
{
|
||||
/* Set Ethernet speed to 10M following the auto-negotiation */
|
||||
(heth->Init).Speed = ETH_SPEED_10M;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Ethernet speed to 100M following the auto-negotiation */
|
||||
(heth->Init).Speed = ETH_SPEED_100M;
|
||||
}
|
||||
}
|
||||
else /* AutoNegotiation Disable */
|
||||
{
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_SPEED(heth->Init.Speed));
|
||||
assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode));
|
||||
|
||||
/* Set MAC Speed and Duplex Mode */
|
||||
if (HAL_ETH_WritePHYRegister(heth, PHY_BCR, ((uint16_t)((heth->Init).DuplexMode >> 3U) |
|
||||
(uint16_t)((heth->Init).Speed >> 1U))) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Delay to assure PHY configuration */
|
||||
HAL_Delay(PHY_CONFIG_DELAY);
|
||||
}
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the ETH peripheral.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
if (heth->MspDeInitCallback == NULL)
|
||||
{
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
}
|
||||
/* De-Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
heth->MspDeInitCallback(heth);
|
||||
#else
|
||||
/* De-Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
HAL_ETH_MspDeInit(heth);
|
||||
#endif
|
||||
|
||||
/* Set ETH HAL state to Disabled */
|
||||
heth->State = HAL_ETH_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the DMA Tx descriptors in chain mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param DMATxDescTab: Pointer to the first Tx desc list
|
||||
* @param TxBuff: Pointer to the first TxBuffer list
|
||||
* @param TxBuffCount: Number of the used Tx desc in the list
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DMATxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMATxDescTab, uint8_t *TxBuff, uint32_t TxBuffCount)
|
||||
{
|
||||
uint32_t i = 0U;
|
||||
ETH_DMADescTypeDef *dmatxdesc;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */
|
||||
heth->TxDesc = DMATxDescTab;
|
||||
|
||||
/* Fill each DMATxDesc descriptor with the right values */
|
||||
for (i = 0U; i < TxBuffCount; i++)
|
||||
{
|
||||
/* Get the pointer on the ith member of the Tx Desc list */
|
||||
dmatxdesc = DMATxDescTab + i;
|
||||
|
||||
/* Set Second Address Chained bit */
|
||||
dmatxdesc->Status = ETH_DMATXDESC_TCH;
|
||||
|
||||
/* Set Buffer1 address pointer */
|
||||
dmatxdesc->Buffer1Addr = (uint32_t)(&TxBuff[i * ETH_TX_BUF_SIZE]);
|
||||
|
||||
if ((heth->Init).ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
|
||||
{
|
||||
/* Set the DMA Tx descriptors checksum insertion */
|
||||
dmatxdesc->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
|
||||
}
|
||||
|
||||
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
|
||||
if (i < (TxBuffCount - 1U))
|
||||
{
|
||||
/* Set next descriptor address register with next descriptor base address */
|
||||
dmatxdesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + i + 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
|
||||
dmatxdesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Transmit Descriptor List Address Register */
|
||||
(heth->Instance)->DMATDLAR = (uint32_t) DMATxDescTab;
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the DMA Rx descriptors in chain mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param DMARxDescTab: Pointer to the first Rx desc list
|
||||
* @param RxBuff: Pointer to the first RxBuffer list
|
||||
* @param RxBuffCount: Number of the used Rx desc in the list
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DMARxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount)
|
||||
{
|
||||
uint32_t i = 0U;
|
||||
ETH_DMADescTypeDef *DMARxDesc;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Set the Ethernet RxDesc pointer with the first one of the DMARxDescTab list */
|
||||
heth->RxDesc = DMARxDescTab;
|
||||
|
||||
/* Fill each DMARxDesc descriptor with the right values */
|
||||
for (i = 0U; i < RxBuffCount; i++)
|
||||
{
|
||||
/* Get the pointer on the ith member of the Rx Desc list */
|
||||
DMARxDesc = DMARxDescTab + i;
|
||||
|
||||
/* Set Own bit of the Rx descriptor Status */
|
||||
DMARxDesc->Status = ETH_DMARXDESC_OWN;
|
||||
|
||||
/* Set Buffer1 size and Second Address Chained bit */
|
||||
DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE;
|
||||
|
||||
/* Set Buffer1 address pointer */
|
||||
DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i * ETH_RX_BUF_SIZE]);
|
||||
|
||||
if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
|
||||
{
|
||||
/* Enable Ethernet DMA Rx Descriptor interrupt */
|
||||
DMARxDesc->ControlBufferSize &= ~ETH_DMARXDESC_DIC;
|
||||
}
|
||||
|
||||
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
|
||||
if (i < (RxBuffCount - 1U))
|
||||
{
|
||||
/* Set next descriptor address register with next descriptor base address */
|
||||
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + i + 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
|
||||
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Receive Descriptor List Address Register */
|
||||
(heth->Instance)->DMARDLAR = (uint32_t) DMARxDescTab;
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the ETH MSP.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes ETH MSP.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User ETH Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param heth eth handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
|
||||
* @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, pETH_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_TX_COMPLETE_CB_ID :
|
||||
heth->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_RX_COMPLETE_CB_ID :
|
||||
heth->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_DMA_ERROR_CB_ID :
|
||||
heth->DMAErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an ETH Callback
|
||||
* ETH callback is redirected to the weak predefined callback
|
||||
* @param heth eth handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
|
||||
* @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_TX_COMPLETE_CB_ID :
|
||||
heth->TxCpltCallback = HAL_ETH_TxCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_RX_COMPLETE_CB_ID :
|
||||
heth->RxCpltCallback = HAL_ETH_RxCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_DMA_ERROR_CB_ID :
|
||||
heth->DMAErrorCallback = HAL_ETH_ErrorCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Transmit a frame
|
||||
HAL_ETH_TransmitFrame();
|
||||
(+) Receive a frame
|
||||
HAL_ETH_GetReceivedFrame();
|
||||
HAL_ETH_GetReceivedFrame_IT();
|
||||
(+) Read from an External PHY register
|
||||
HAL_ETH_ReadPHYRegister();
|
||||
(+) Write to an External PHY register
|
||||
HAL_ETH_WritePHYRegister();
|
||||
|
||||
@endverbatim
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an Ethernet frame.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param FrameLength: Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength)
|
||||
{
|
||||
uint32_t bufcount = 0U, size = 0U, i = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
if (FrameLength == 0U)
|
||||
{
|
||||
/* Set ETH HAL state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if (((heth->TxDesc)->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
||||
{
|
||||
/* OWN bit set */
|
||||
heth->State = HAL_ETH_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get the number of needed Tx buffers for the current frame */
|
||||
if (FrameLength > ETH_TX_BUF_SIZE)
|
||||
{
|
||||
bufcount = FrameLength / ETH_TX_BUF_SIZE;
|
||||
if (FrameLength % ETH_TX_BUF_SIZE)
|
||||
{
|
||||
bufcount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufcount = 1U;
|
||||
}
|
||||
if (bufcount == 1U)
|
||||
{
|
||||
/* Set LAST and FIRST segment */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
|
||||
/* Set frame size */
|
||||
heth->TxDesc->ControlBufferSize = (FrameLength & ETH_DMATXDESC_TBS1);
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_OWN;
|
||||
/* Point to next descriptor */
|
||||
heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0U; i < bufcount; i++)
|
||||
{
|
||||
/* Clear FIRST and LAST segment bits */
|
||||
heth->TxDesc->Status &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS);
|
||||
|
||||
if (i == 0U)
|
||||
{
|
||||
/* Setting the first segment bit */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_FS;
|
||||
}
|
||||
|
||||
/* Program size */
|
||||
heth->TxDesc->ControlBufferSize = (ETH_TX_BUF_SIZE & ETH_DMATXDESC_TBS1);
|
||||
|
||||
if (i == (bufcount - 1U))
|
||||
{
|
||||
/* Setting the last segment bit */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_LS;
|
||||
size = FrameLength - (bufcount - 1U) * ETH_TX_BUF_SIZE;
|
||||
heth->TxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TBS1);
|
||||
}
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_OWN;
|
||||
/* point to next descriptor */
|
||||
heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
|
||||
if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)
|
||||
{
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
(heth->Instance)->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
(heth->Instance)->DMATPDR = 0U;
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for received frames.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_GetReceivedFrame(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t framelength = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Check the ETH state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Check if segment is not owned by DMA */
|
||||
/* (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET)) */
|
||||
if (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET))
|
||||
{
|
||||
/* Check if last segment */
|
||||
if (((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET))
|
||||
{
|
||||
/* increment segment count */
|
||||
(heth->RxFrameInfos).SegCount++;
|
||||
|
||||
/* Check if last segment is first segment: one segment contains the frame */
|
||||
if ((heth->RxFrameInfos).SegCount == 1U)
|
||||
{
|
||||
(heth->RxFrameInfos).FSRxDesc = heth->RxDesc;
|
||||
}
|
||||
|
||||
heth->RxFrameInfos.LSRxDesc = heth->RxDesc;
|
||||
|
||||
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
|
||||
framelength = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U;
|
||||
heth->RxFrameInfos.length = framelength;
|
||||
|
||||
/* Get the address of the buffer start address */
|
||||
heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr;
|
||||
/* point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)((heth->RxDesc)->Buffer2NextDescAddr);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
/* Check if first segment */
|
||||
else if ((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET)
|
||||
{
|
||||
(heth->RxFrameInfos).FSRxDesc = heth->RxDesc;
|
||||
(heth->RxFrameInfos).LSRxDesc = NULL;
|
||||
(heth->RxFrameInfos).SegCount = 1U;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Check if intermediate segment */
|
||||
else
|
||||
{
|
||||
(heth->RxFrameInfos).SegCount++;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the Received frame in interrupt mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_GetReceivedFrame_IT(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t descriptorscancounter = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set ETH HAL State to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Scan descriptors owned by CPU */
|
||||
while (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (descriptorscancounter < ETH_RXBUFNB))
|
||||
{
|
||||
/* Just for security */
|
||||
descriptorscancounter++;
|
||||
|
||||
/* Check if first segment in frame */
|
||||
/* ((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)) */
|
||||
if ((heth->RxDesc->Status & (ETH_DMARXDESC_FS | ETH_DMARXDESC_LS)) == (uint32_t)ETH_DMARXDESC_FS)
|
||||
{
|
||||
heth->RxFrameInfos.FSRxDesc = heth->RxDesc;
|
||||
heth->RxFrameInfos.SegCount = 1U;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Check if intermediate segment */
|
||||
/* ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)&& ((heth->RxDesc->Status & ETH_DMARXDESC_FS) == (uint32_t)RESET)) */
|
||||
else if ((heth->RxDesc->Status & (ETH_DMARXDESC_LS | ETH_DMARXDESC_FS)) == (uint32_t)RESET)
|
||||
{
|
||||
/* Increment segment count */
|
||||
(heth->RxFrameInfos.SegCount)++;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Should be last segment */
|
||||
else
|
||||
{
|
||||
/* Last segment */
|
||||
heth->RxFrameInfos.LSRxDesc = heth->RxDesc;
|
||||
|
||||
/* Increment segment count */
|
||||
(heth->RxFrameInfos.SegCount)++;
|
||||
|
||||
/* Check if last segment is first segment: one segment contains the frame */
|
||||
if ((heth->RxFrameInfos.SegCount) == 1U)
|
||||
{
|
||||
heth->RxFrameInfos.FSRxDesc = heth->RxDesc;
|
||||
}
|
||||
|
||||
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
|
||||
heth->RxFrameInfos.length = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U;
|
||||
|
||||
/* Get the address of the buffer start address */
|
||||
heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr;
|
||||
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles ETH interrupt request.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Frame received */
|
||||
if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_R))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Receive complete callback*/
|
||||
heth->RxCpltCallback(heth);
|
||||
#else
|
||||
/* Receive complete callback */
|
||||
HAL_ETH_RxCpltCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Eth DMA Rx IT pending bits */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_R);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
}
|
||||
/* Frame transmitted */
|
||||
else if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_T))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/* Call resgistered Transfer complete callback*/
|
||||
heth->TxCpltCallback(heth);
|
||||
#else
|
||||
/* Transfer complete callback */
|
||||
HAL_ETH_TxCpltCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Eth DMA Tx IT pending bits */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_T);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
}
|
||||
|
||||
/* Clear the interrupt flags */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_NIS);
|
||||
|
||||
/* ETH DMA Error */
|
||||
if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_AIS))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
heth->DMAErrorCallback(heth);
|
||||
#else
|
||||
/* Ethernet Error callback */
|
||||
HAL_ETH_ErrorCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the interrupt flags */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_FLAG_AIS);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ethernet transfer error callbacks
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a PHY register
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param PHYReg: PHY register address, is the index of one of the 32 PHY register.
|
||||
* This parameter can be one of the following values:
|
||||
* PHY_BCR: Transceiver Basic Control Register,
|
||||
* PHY_BSR: Transceiver Basic Status Register.
|
||||
* More PHY register could be read depending on the used PHY
|
||||
* @param RegValue: PHY register value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t *RegValue)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress));
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth->State == HAL_ETH_STATE_BUSY_RD)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
/* Set ETH HAL State to BUSY_RD */
|
||||
heth->State = HAL_ETH_STATE_BUSY_RD;
|
||||
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
|
||||
/* Keep only the CSR Clock Range CR[2:0] bits value */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Prepare the MII address register value */
|
||||
tmpreg1 |= (((uint32_t)heth->Init.PhyAddress << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */
|
||||
tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */
|
||||
tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
|
||||
|
||||
/* Write the result value into the MII Address register */
|
||||
heth->Instance->MACMIIAR = tmpreg1;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check for the Busy flag */
|
||||
while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > PHY_READ_TO)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
}
|
||||
|
||||
/* Get MACMIIDR value */
|
||||
*RegValue = (uint16_t)(heth->Instance->MACMIIDR);
|
||||
|
||||
/* Set ETH HAL State to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes to a PHY register.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param PHYReg: PHY register address, is the index of one of the 32 PHY register.
|
||||
* This parameter can be one of the following values:
|
||||
* PHY_BCR: Transceiver Control Register.
|
||||
* More PHY register could be written depending on the used PHY
|
||||
* @param RegValue: the value to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t RegValue)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress));
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth->State == HAL_ETH_STATE_BUSY_WR)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
/* Set ETH HAL State to BUSY_WR */
|
||||
heth->State = HAL_ETH_STATE_BUSY_WR;
|
||||
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
|
||||
/* Keep only the CSR Clock Range CR[2:0] bits value */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Prepare the MII register address value */
|
||||
tmpreg1 |= (((uint32_t)heth->Init.PhyAddress << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */
|
||||
tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */
|
||||
tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */
|
||||
tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
|
||||
|
||||
/* Give the value to the MII data register */
|
||||
heth->Instance->MACMIIDR = (uint16_t)RegValue;
|
||||
|
||||
/* Write the result value into the MII Address register */
|
||||
heth->Instance->MACMIIAR = tmpreg1;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check for the Busy flag */
|
||||
while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > PHY_WRITE_TO)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Enable MAC and DMA transmission and reception.
|
||||
HAL_ETH_Start();
|
||||
(+) Disable MAC and DMA transmission and reception.
|
||||
HAL_ETH_Stop();
|
||||
(+) Set the MAC configuration in runtime mode
|
||||
HAL_ETH_ConfigMAC();
|
||||
(+) Set the DMA configuration in runtime mode
|
||||
HAL_ETH_ConfigDMA();
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables Ethernet MAC and DMA reception/transmission
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Enable transmit state machine of the MAC for transmission on the MII */
|
||||
ETH_MACTransmissionEnable(heth);
|
||||
|
||||
/* Enable receive state machine of the MAC for reception from the MII */
|
||||
ETH_MACReceptionEnable(heth);
|
||||
|
||||
/* Flush Transmit FIFO */
|
||||
ETH_FlushTransmitFIFO(heth);
|
||||
|
||||
/* Start DMA transmission */
|
||||
ETH_DMATransmissionEnable(heth);
|
||||
|
||||
/* Start DMA reception */
|
||||
ETH_DMAReceptionEnable(heth);
|
||||
|
||||
/* Set the ETH state to READY*/
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop Ethernet MAC and DMA reception/transmission
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Stop DMA transmission */
|
||||
ETH_DMATransmissionDisable(heth);
|
||||
|
||||
/* Stop DMA reception */
|
||||
ETH_DMAReceptionDisable(heth);
|
||||
|
||||
/* Disable receive state machine of the MAC for reception from the MII */
|
||||
ETH_MACReceptionDisable(heth);
|
||||
|
||||
/* Flush Transmit FIFO */
|
||||
ETH_FlushTransmitFIFO(heth);
|
||||
|
||||
/* Disable transmit state machine of the MAC for transmission on the MII */
|
||||
ETH_MACTransmissionDisable(heth);
|
||||
|
||||
/* Set the ETH state*/
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ETH MAC Configuration.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param macconf: MAC Configuration structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef *macconf)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
assert_param(IS_ETH_SPEED(heth->Init.Speed));
|
||||
assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode));
|
||||
|
||||
if (macconf != NULL)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ETH_WATCHDOG(macconf->Watchdog));
|
||||
assert_param(IS_ETH_JABBER(macconf->Jabber));
|
||||
assert_param(IS_ETH_INTER_FRAME_GAP(macconf->InterFrameGap));
|
||||
assert_param(IS_ETH_CARRIER_SENSE(macconf->CarrierSense));
|
||||
assert_param(IS_ETH_RECEIVE_OWN(macconf->ReceiveOwn));
|
||||
assert_param(IS_ETH_LOOPBACK_MODE(macconf->LoopbackMode));
|
||||
assert_param(IS_ETH_CHECKSUM_OFFLOAD(macconf->ChecksumOffload));
|
||||
assert_param(IS_ETH_RETRY_TRANSMISSION(macconf->RetryTransmission));
|
||||
assert_param(IS_ETH_AUTOMATIC_PADCRC_STRIP(macconf->AutomaticPadCRCStrip));
|
||||
assert_param(IS_ETH_BACKOFF_LIMIT(macconf->BackOffLimit));
|
||||
assert_param(IS_ETH_DEFERRAL_CHECK(macconf->DeferralCheck));
|
||||
assert_param(IS_ETH_RECEIVE_ALL(macconf->ReceiveAll));
|
||||
assert_param(IS_ETH_SOURCE_ADDR_FILTER(macconf->SourceAddrFilter));
|
||||
assert_param(IS_ETH_CONTROL_FRAMES(macconf->PassControlFrames));
|
||||
assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(macconf->BroadcastFramesReception));
|
||||
assert_param(IS_ETH_DESTINATION_ADDR_FILTER(macconf->DestinationAddrFilter));
|
||||
assert_param(IS_ETH_PROMISCUOUS_MODE(macconf->PromiscuousMode));
|
||||
assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(macconf->MulticastFramesFilter));
|
||||
assert_param(IS_ETH_UNICAST_FRAMES_FILTER(macconf->UnicastFramesFilter));
|
||||
assert_param(IS_ETH_PAUSE_TIME(macconf->PauseTime));
|
||||
assert_param(IS_ETH_ZEROQUANTA_PAUSE(macconf->ZeroQuantaPause));
|
||||
assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(macconf->PauseLowThreshold));
|
||||
assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(macconf->UnicastPauseFrameDetect));
|
||||
assert_param(IS_ETH_RECEIVE_FLOWCONTROL(macconf->ReceiveFlowControl));
|
||||
assert_param(IS_ETH_TRANSMIT_FLOWCONTROL(macconf->TransmitFlowControl));
|
||||
assert_param(IS_ETH_VLAN_TAG_COMPARISON(macconf->VLANTagComparison));
|
||||
assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(macconf->VLANTagIdentifier));
|
||||
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
/* Clear WD, PCE, PS, TE and RE bits */
|
||||
tmpreg1 &= ETH_MACCR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)(macconf->Watchdog |
|
||||
macconf->Jabber |
|
||||
macconf->InterFrameGap |
|
||||
macconf->CarrierSense |
|
||||
(heth->Init).Speed |
|
||||
macconf->ReceiveOwn |
|
||||
macconf->LoopbackMode |
|
||||
(heth->Init).DuplexMode |
|
||||
macconf->ChecksumOffload |
|
||||
macconf->RetryTransmission |
|
||||
macconf->AutomaticPadCRCStrip |
|
||||
macconf->BackOffLimit |
|
||||
macconf->DeferralCheck);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACFFR Configuration --------------------*/
|
||||
/* Write to ETHERNET MACFFR */
|
||||
(heth->Instance)->MACFFR = (uint32_t)(macconf->ReceiveAll |
|
||||
macconf->SourceAddrFilter |
|
||||
macconf->PassControlFrames |
|
||||
macconf->BroadcastFramesReception |
|
||||
macconf->DestinationAddrFilter |
|
||||
macconf->PromiscuousMode |
|
||||
macconf->MulticastFramesFilter |
|
||||
macconf->UnicastFramesFilter);
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFFR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFFR = tmpreg1;
|
||||
|
||||
/*--------------- ETHERNET MACHTHR and MACHTLR Configuration ---------------*/
|
||||
/* Write to ETHERNET MACHTHR */
|
||||
(heth->Instance)->MACHTHR = (uint32_t)macconf->HashTableHigh;
|
||||
|
||||
/* Write to ETHERNET MACHTLR */
|
||||
(heth->Instance)->MACHTLR = (uint32_t)macconf->HashTableLow;
|
||||
/*----------------------- ETHERNET MACFCR Configuration --------------------*/
|
||||
|
||||
/* Get the ETHERNET MACFCR value */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_MACFCR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) |
|
||||
macconf->ZeroQuantaPause |
|
||||
macconf->PauseLowThreshold |
|
||||
macconf->UnicastPauseFrameDetect |
|
||||
macconf->ReceiveFlowControl |
|
||||
macconf->TransmitFlowControl);
|
||||
|
||||
/* Write to ETHERNET MACFCR */
|
||||
(heth->Instance)->MACFCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACVLANTR Configuration -----------------*/
|
||||
(heth->Instance)->MACVLANTR = (uint32_t)(macconf->VLANTagComparison |
|
||||
macconf->VLANTagIdentifier);
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACVLANTR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACVLANTR = tmpreg1;
|
||||
}
|
||||
else /* macconf == NULL : here we just configure Speed and Duplex mode */
|
||||
{
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
|
||||
/* Clear FES and DM bits */
|
||||
tmpreg1 &= ~(0x00004800U);
|
||||
|
||||
tmpreg1 |= (uint32_t)(heth->Init.Speed | heth->Init.DuplexMode);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/* Set the ETH state to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets ETH DMA Configuration.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param dmaconf: DMA Configuration structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef *dmaconf)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(dmaconf->DropTCPIPChecksumErrorFrame));
|
||||
assert_param(IS_ETH_RECEIVE_STORE_FORWARD(dmaconf->ReceiveStoreForward));
|
||||
assert_param(IS_ETH_FLUSH_RECEIVE_FRAME(dmaconf->FlushReceivedFrame));
|
||||
assert_param(IS_ETH_TRANSMIT_STORE_FORWARD(dmaconf->TransmitStoreForward));
|
||||
assert_param(IS_ETH_TRANSMIT_THRESHOLD_CONTROL(dmaconf->TransmitThresholdControl));
|
||||
assert_param(IS_ETH_FORWARD_ERROR_FRAMES(dmaconf->ForwardErrorFrames));
|
||||
assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(dmaconf->ForwardUndersizedGoodFrames));
|
||||
assert_param(IS_ETH_RECEIVE_THRESHOLD_CONTROL(dmaconf->ReceiveThresholdControl));
|
||||
assert_param(IS_ETH_SECOND_FRAME_OPERATE(dmaconf->SecondFrameOperate));
|
||||
assert_param(IS_ETH_ADDRESS_ALIGNED_BEATS(dmaconf->AddressAlignedBeats));
|
||||
assert_param(IS_ETH_FIXED_BURST(dmaconf->FixedBurst));
|
||||
assert_param(IS_ETH_RXDMA_BURST_LENGTH(dmaconf->RxDMABurstLength));
|
||||
assert_param(IS_ETH_TXDMA_BURST_LENGTH(dmaconf->TxDMABurstLength));
|
||||
assert_param(IS_ETH_DMA_DESC_SKIP_LENGTH(dmaconf->DescriptorSkipLength));
|
||||
assert_param(IS_ETH_DMA_ARBITRATION_ROUNDROBIN_RXTX(dmaconf->DMAArbitration));
|
||||
|
||||
/*----------------------- ETHERNET DMAOMR Configuration --------------------*/
|
||||
/* Get the ETHERNET DMAOMR value */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)(dmaconf->DropTCPIPChecksumErrorFrame |
|
||||
dmaconf->ReceiveStoreForward |
|
||||
dmaconf->FlushReceivedFrame |
|
||||
dmaconf->TransmitStoreForward |
|
||||
dmaconf->TransmitThresholdControl |
|
||||
dmaconf->ForwardErrorFrames |
|
||||
dmaconf->ForwardUndersizedGoodFrames |
|
||||
dmaconf->ReceiveThresholdControl |
|
||||
dmaconf->SecondFrameOperate);
|
||||
|
||||
/* Write to ETHERNET DMAOMR */
|
||||
(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET DMABMR Configuration --------------------*/
|
||||
(heth->Instance)->DMABMR = (uint32_t)(dmaconf->AddressAlignedBeats |
|
||||
dmaconf->FixedBurst |
|
||||
dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
|
||||
dmaconf->TxDMABurstLength |
|
||||
(dmaconf->DescriptorSkipLength << 2U) |
|
||||
dmaconf->DMAArbitration |
|
||||
ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMABMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMABMR = tmpreg1;
|
||||
|
||||
/* Set the ETH state to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
(+) Get the ETH handle state:
|
||||
HAL_ETH_GetState();
|
||||
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the ETH HAL state
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Return ETH state */
|
||||
return heth->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup ETH_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures Ethernet MAC and DMA with default parameters.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param err: Ethernet Init error
|
||||
* @retval HAL status
|
||||
*/
|
||||
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
|
||||
{
|
||||
ETH_MACInitTypeDef macinit;
|
||||
ETH_DMAInitTypeDef dmainit;
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
if (err != ETH_SUCCESS) /* Auto-negotiation failed */
|
||||
{
|
||||
/* Set Ethernet duplex mode to Full-duplex */
|
||||
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||
|
||||
/* Set Ethernet speed to 100M */
|
||||
(heth->Init).Speed = ETH_SPEED_100M;
|
||||
}
|
||||
|
||||
/* Ethernet MAC default initialization **************************************/
|
||||
macinit.Watchdog = ETH_WATCHDOG_ENABLE;
|
||||
macinit.Jabber = ETH_JABBER_ENABLE;
|
||||
macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;
|
||||
macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
|
||||
macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
|
||||
macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
|
||||
if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
|
||||
{
|
||||
macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
|
||||
}
|
||||
macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;
|
||||
macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
|
||||
macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
|
||||
macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
|
||||
macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE;
|
||||
macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;
|
||||
macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
|
||||
macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
|
||||
macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;
|
||||
macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
|
||||
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;
|
||||
macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
|
||||
macinit.HashTableHigh = 0x0U;
|
||||
macinit.HashTableLow = 0x0U;
|
||||
macinit.PauseTime = 0x0U;
|
||||
macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
|
||||
macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
|
||||
macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;
|
||||
macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;
|
||||
macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;
|
||||
macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
|
||||
macinit.VLANTagIdentifier = 0x0U;
|
||||
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
/* Clear WD, PCE, PS, TE and RE bits */
|
||||
tmpreg1 &= ETH_MACCR_CLEAR_MASK;
|
||||
/* Set the WD bit according to ETH Watchdog value */
|
||||
/* Set the JD: bit according to ETH Jabber value */
|
||||
/* Set the IFG bit according to ETH InterFrameGap value */
|
||||
/* Set the DCRS bit according to ETH CarrierSense value */
|
||||
/* Set the FES bit according to ETH Speed value */
|
||||
/* Set the DO bit according to ETH ReceiveOwn value */
|
||||
/* Set the LM bit according to ETH LoopbackMode value */
|
||||
/* Set the DM bit according to ETH Mode value */
|
||||
/* Set the IPCO bit according to ETH ChecksumOffload value */
|
||||
/* Set the DR bit according to ETH RetryTransmission value */
|
||||
/* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
|
||||
/* Set the BL bit according to ETH BackOffLimit value */
|
||||
/* Set the DC bit according to ETH DeferralCheck value */
|
||||
tmpreg1 |= (uint32_t)(macinit.Watchdog |
|
||||
macinit.Jabber |
|
||||
macinit.InterFrameGap |
|
||||
macinit.CarrierSense |
|
||||
(heth->Init).Speed |
|
||||
macinit.ReceiveOwn |
|
||||
macinit.LoopbackMode |
|
||||
(heth->Init).DuplexMode |
|
||||
macinit.ChecksumOffload |
|
||||
macinit.RetryTransmission |
|
||||
macinit.AutomaticPadCRCStrip |
|
||||
macinit.BackOffLimit |
|
||||
macinit.DeferralCheck);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACFFR Configuration --------------------*/
|
||||
/* Set the RA bit according to ETH ReceiveAll value */
|
||||
/* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */
|
||||
/* Set the PCF bit according to ETH PassControlFrames value */
|
||||
/* Set the DBF bit according to ETH BroadcastFramesReception value */
|
||||
/* Set the DAIF bit according to ETH DestinationAddrFilter value */
|
||||
/* Set the PR bit according to ETH PromiscuousMode value */
|
||||
/* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
|
||||
/* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */
|
||||
/* Write to ETHERNET MACFFR */
|
||||
(heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |
|
||||
macinit.SourceAddrFilter |
|
||||
macinit.PassControlFrames |
|
||||
macinit.BroadcastFramesReception |
|
||||
macinit.DestinationAddrFilter |
|
||||
macinit.PromiscuousMode |
|
||||
macinit.MulticastFramesFilter |
|
||||
macinit.UnicastFramesFilter);
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFFR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFFR = tmpreg1;
|
||||
|
||||
/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/
|
||||
/* Write to ETHERNET MACHTHR */
|
||||
(heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;
|
||||
|
||||
/* Write to ETHERNET MACHTLR */
|
||||
(heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;
|
||||
/*----------------------- ETHERNET MACFCR Configuration -------------------*/
|
||||
|
||||
/* Get the ETHERNET MACFCR value */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_MACFCR_CLEAR_MASK;
|
||||
|
||||
/* Set the PT bit according to ETH PauseTime value */
|
||||
/* Set the DZPQ bit according to ETH ZeroQuantaPause value */
|
||||
/* Set the PLT bit according to ETH PauseLowThreshold value */
|
||||
/* Set the UP bit according to ETH UnicastPauseFrameDetect value */
|
||||
/* Set the RFE bit according to ETH ReceiveFlowControl value */
|
||||
/* Set the TFE bit according to ETH TransmitFlowControl value */
|
||||
tmpreg1 |= (uint32_t)((macinit.PauseTime << 16U) |
|
||||
macinit.ZeroQuantaPause |
|
||||
macinit.PauseLowThreshold |
|
||||
macinit.UnicastPauseFrameDetect |
|
||||
macinit.ReceiveFlowControl |
|
||||
macinit.TransmitFlowControl);
|
||||
|
||||
/* Write to ETHERNET MACFCR */
|
||||
(heth->Instance)->MACFCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACVLANTR Configuration ----------------*/
|
||||
/* Set the ETV bit according to ETH VLANTagComparison value */
|
||||
/* Set the VL bit according to ETH VLANTagIdentifier value */
|
||||
(heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |
|
||||
macinit.VLANTagIdentifier);
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACVLANTR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACVLANTR = tmpreg1;
|
||||
|
||||
/* Ethernet DMA default initialization ************************************/
|
||||
dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
|
||||
dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
|
||||
dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;
|
||||
dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
|
||||
dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;
|
||||
dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
|
||||
dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
|
||||
dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;
|
||||
dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
|
||||
dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
|
||||
dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;
|
||||
dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
|
||||
dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
|
||||
dmainit.DescriptorSkipLength = 0x0U;
|
||||
dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;
|
||||
|
||||
/* Get the ETHERNET DMAOMR value */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;
|
||||
|
||||
/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */
|
||||
/* Set the RSF bit according to ETH ReceiveStoreForward value */
|
||||
/* Set the DFF bit according to ETH FlushReceivedFrame value */
|
||||
/* Set the TSF bit according to ETH TransmitStoreForward value */
|
||||
/* Set the TTC bit according to ETH TransmitThresholdControl value */
|
||||
/* Set the FEF bit according to ETH ForwardErrorFrames value */
|
||||
/* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */
|
||||
/* Set the RTC bit according to ETH ReceiveThresholdControl value */
|
||||
/* Set the OSF bit according to ETH SecondFrameOperate value */
|
||||
tmpreg1 |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |
|
||||
dmainit.ReceiveStoreForward |
|
||||
dmainit.FlushReceivedFrame |
|
||||
dmainit.TransmitStoreForward |
|
||||
dmainit.TransmitThresholdControl |
|
||||
dmainit.ForwardErrorFrames |
|
||||
dmainit.ForwardUndersizedGoodFrames |
|
||||
dmainit.ReceiveThresholdControl |
|
||||
dmainit.SecondFrameOperate);
|
||||
|
||||
/* Write to ETHERNET DMAOMR */
|
||||
(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET DMABMR Configuration ------------------*/
|
||||
/* Set the AAL bit according to ETH AddressAlignedBeats value */
|
||||
/* Set the FB bit according to ETH FixedBurst value */
|
||||
/* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */
|
||||
/* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */
|
||||
/* Set the DSL bit according to ETH DesciptorSkipLength value */
|
||||
/* Set the PR and DA bits according to ETH DMAArbitration value */
|
||||
(heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |
|
||||
dmainit.FixedBurst |
|
||||
dmainit.RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
|
||||
dmainit.TxDMABurstLength |
|
||||
(dmainit.DescriptorSkipLength << 2U) |
|
||||
dmainit.DMAArbitration |
|
||||
ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMABMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMABMR = tmpreg1;
|
||||
|
||||
if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
|
||||
{
|
||||
/* Enable the Ethernet Rx Interrupt */
|
||||
__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);
|
||||
}
|
||||
|
||||
/* Initialize MAC address in ethernet MAC */
|
||||
ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the selected MAC address.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param MacAddr: The MAC address to configure
|
||||
* This parameter can be one of the following values:
|
||||
* @arg ETH_MAC_Address0: MAC Address0
|
||||
* @arg ETH_MAC_Address1: MAC Address1
|
||||
* @arg ETH_MAC_Address2: MAC Address2
|
||||
* @arg ETH_MAC_Address3: MAC Address3
|
||||
* @param Addr: Pointer to MAC address buffer data (6 bytes)
|
||||
* @retval HAL status
|
||||
*/
|
||||
static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)
|
||||
{
|
||||
uint32_t tmpreg1;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ETH_MAC_ADDRESS0123(MacAddr));
|
||||
|
||||
/* Calculate the selected MAC address high register */
|
||||
tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U];
|
||||
/* Load the selected MAC address high register */
|
||||
(*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1;
|
||||
/* Calculate the selected MAC address low register */
|
||||
tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U];
|
||||
|
||||
/* Load the selected MAC address low register */
|
||||
(*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Enable the MAC transmission */
|
||||
(heth->Instance)->MACCR |= ETH_MACCR_TE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the MAC transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Disable the MAC transmission */
|
||||
(heth->Instance)->MACCR &= ~ETH_MACCR_TE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Enable the MAC reception */
|
||||
(heth->Instance)->MACCR |= ETH_MACCR_RE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the MAC reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Disable the MAC reception */
|
||||
(heth->Instance)->MACCR &= ~ETH_MACCR_RE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the DMA transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Enable the DMA transmission */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_ST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the DMA transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Disable the DMA transmission */
|
||||
(heth->Instance)->DMAOMR &= ~ETH_DMAOMR_ST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the DMA reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Enable the DMA reception */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_SR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the DMA reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Disable the DMA reception */
|
||||
(heth->Instance)->DMAOMR &= ~ETH_DMAOMR_SR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the ETHERNET transmit FIFO.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Set the Flush Transmit FIFO bit */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function provides delay (in milliseconds) based on CPU cycles method.
|
||||
* @param mdelay: specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_Delay(uint32_t mdelay)
|
||||
{
|
||||
__IO uint32_t Delay = mdelay * (SystemCoreClock / 8U / 1000U);
|
||||
do
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
while (Delay --);
|
||||
}
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Init the ETH Callback settings */
|
||||
heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
heth->DMAErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak DMAErrorCallback */
|
||||
}
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ETH */
|
||||
|
||||
#endif /* HAL_ETH_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
1738
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_hcd.c
Normal file
1738
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_hcd.c
Normal file
@@ -0,0 +1,1738 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_hcd.c
|
||||
* @author MCD Application Team
|
||||
* @brief HCD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#)Declare a HCD_HandleTypeDef handle structure, for example:
|
||||
HCD_HandleTypeDef hhcd;
|
||||
|
||||
(#)Fill parameters of Init structure in HCD handle
|
||||
|
||||
(#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
|
||||
|
||||
(#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
|
||||
(##) Enable the HCD/USB Low Level interface clock using the following macros
|
||||
(+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure HCD pin-out
|
||||
(##) Configure HCD NVIC interrupt
|
||||
|
||||
(#)Associate the Upper USB Host stack to the HAL HCD Driver:
|
||||
(##) hhcd.pData = phost;
|
||||
|
||||
(#)Enable HCD transmission and reception:
|
||||
(##) HAL_HCD_Start();
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#if defined (USB_OTG_FS)
|
||||
|
||||
/** @defgroup HCD HCD
|
||||
* @brief HCD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup HCD_Private_Functions HCD Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
||||
static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
||||
static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
|
||||
static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup HCD_Exported_Functions HCD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_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:
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Check the HCD handle allocation */
|
||||
if (hhcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hhcd->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->SOFCallback = HAL_HCD_SOF_Callback;
|
||||
hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
|
||||
hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
|
||||
hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
|
||||
hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
|
||||
hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
|
||||
|
||||
if (hhcd->MspInitCallback == NULL)
|
||||
{
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hhcd->MspInitCallback(hhcd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_HCD_MspInit(hhcd);
|
||||
#endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_BUSY;
|
||||
|
||||
/* Disable DMA mode for FS instance */
|
||||
hhcd->Init.dma_enable = 0U;
|
||||
|
||||
/* Disable the Interrupts */
|
||||
__HAL_HCD_DISABLE(hhcd);
|
||||
|
||||
/* Init the Core (common init.) */
|
||||
if (USB_CoreInit(hhcd->Instance, hhcd->Init) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Force Host Mode */
|
||||
if (USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Init Host */
|
||||
if (USB_HostInit(hhcd->Instance, hhcd->Init) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a host channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param epnum Endpoint number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param dev_address Current device address
|
||||
* This parameter can be a value from 0 to 255
|
||||
* @param speed Current device speed.
|
||||
* This parameter can be one of these values:
|
||||
* HCD_DEVICE_SPEED_FULL: Full speed mode,
|
||||
* HCD_DEVICE_SPEED_LOW: Low speed mode
|
||||
* @param ep_type Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* EP_TYPE_CTRL: Control type,
|
||||
* EP_TYPE_ISOC: Isochronous type,
|
||||
* EP_TYPE_BULK: Bulk type,
|
||||
* EP_TYPE_INTR: Interrupt type
|
||||
* @param mps Max Packet Size.
|
||||
* This parameter can be a value from 0 to32K
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
|
||||
uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
uint32_t HCcharMps = mps;
|
||||
|
||||
__HAL_LOCK(hhcd);
|
||||
hhcd->hc[ch_num].do_ping = 0U;
|
||||
hhcd->hc[ch_num].dev_addr = dev_address;
|
||||
hhcd->hc[ch_num].ch_num = ch_num;
|
||||
hhcd->hc[ch_num].ep_type = ep_type;
|
||||
hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
|
||||
|
||||
(void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
|
||||
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = 0U;
|
||||
}
|
||||
|
||||
hhcd->hc[ch_num].speed = speed;
|
||||
hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
|
||||
|
||||
status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
|
||||
dev_address, speed, ep_type, (uint16_t)HCcharMps);
|
||||
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Halt a host channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
__HAL_LOCK(hhcd);
|
||||
(void)USB_HC_Halt(hhcd->Instance, ch_num);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Check the HCD handle allocation */
|
||||
if (hhcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
if (hhcd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hhcd->MspDeInitCallback(hhcd);
|
||||
#else
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
HAL_HCD_MspDeInit(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_HCD_DISABLE(hhcd);
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the HCD MSP.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the HCD MSP.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief HCD IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This subsection provides a set of functions allowing to manage the USB Host Data
|
||||
Transfer
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Submit a new URB for processing.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param direction Channel number.
|
||||
* This parameter can be one of these values:
|
||||
* 0 : Output / 1 : Input
|
||||
* @param ep_type Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* EP_TYPE_CTRL: Control type/
|
||||
* EP_TYPE_ISOC: Isochronous type/
|
||||
* EP_TYPE_BULK: Bulk type/
|
||||
* EP_TYPE_INTR: Interrupt type/
|
||||
* @param token Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* 0: HC_PID_SETUP / 1: HC_PID_DATA1
|
||||
* @param pbuff pointer to URB data
|
||||
* @param length Length of URB data
|
||||
* @param do_ping activate do ping protocol (for high speed only).
|
||||
* This parameter can be one of these values:
|
||||
* 0 : do ping inactive / 1 : do ping active
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
|
||||
uint8_t ch_num,
|
||||
uint8_t direction,
|
||||
uint8_t ep_type,
|
||||
uint8_t token,
|
||||
uint8_t *pbuff,
|
||||
uint16_t length,
|
||||
uint8_t do_ping)
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = direction;
|
||||
hhcd->hc[ch_num].ep_type = ep_type;
|
||||
|
||||
if (token == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
|
||||
hhcd->hc[ch_num].do_ping = do_ping;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
|
||||
/* Manage Data Toggle */
|
||||
switch (ep_type)
|
||||
{
|
||||
case EP_TYPE_CTRL:
|
||||
if (token == 1U) /* send data */
|
||||
{
|
||||
if (direction == 0U)
|
||||
{
|
||||
if (length == 0U)
|
||||
{
|
||||
/* For Status OUT stage, Length == 0U, Status Out PID = 1 */
|
||||
hhcd->hc[ch_num].toggle_out = 1U;
|
||||
}
|
||||
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EP_TYPE_BULK:
|
||||
if (direction == 0U)
|
||||
{
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[ch_num].toggle_in == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EP_TYPE_INTR:
|
||||
if (direction == 0U)
|
||||
{
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[ch_num].toggle_in == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EP_TYPE_ISOC:
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
hhcd->hc[ch_num].xfer_buff = pbuff;
|
||||
hhcd->hc[ch_num].xfer_len = length;
|
||||
hhcd->hc[ch_num].urb_state = URB_IDLE;
|
||||
hhcd->hc[ch_num].xfer_count = 0U;
|
||||
hhcd->hc[ch_num].ch_num = ch_num;
|
||||
hhcd->hc[ch_num].state = HC_IDLE;
|
||||
|
||||
return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle HCD interrupt request.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t i;
|
||||
uint32_t interrupt;
|
||||
|
||||
/* Ensure that we are in device mode */
|
||||
if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
|
||||
{
|
||||
/* Avoid spurious interrupt */
|
||||
if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
|
||||
}
|
||||
|
||||
/* Handle Host Disconnect Interrupts */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
|
||||
{
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
|
||||
|
||||
if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
|
||||
{
|
||||
/* Flush USB Fifo */
|
||||
(void)USB_FlushTxFifo(USBx, 0x10U);
|
||||
(void)USB_FlushRxFifo(USBx);
|
||||
|
||||
if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
|
||||
{
|
||||
/* Restore FS Clock */
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
|
||||
}
|
||||
|
||||
/* Handle Host Port Disconnect Interrupt */
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->DisconnectCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_Disconnect_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Host Port Interrupts */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
|
||||
{
|
||||
HCD_Port_IRQHandler(hhcd);
|
||||
}
|
||||
|
||||
/* Handle Host SOF Interrupt */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->SOFCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_SOF_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
|
||||
}
|
||||
|
||||
/* Handle Host channel Interrupt */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
|
||||
{
|
||||
interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
|
||||
for (i = 0U; i < hhcd->Init.Host_channels; i++)
|
||||
{
|
||||
if ((interrupt & (1UL << (i & 0xFU))) != 0U)
|
||||
{
|
||||
if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
|
||||
{
|
||||
HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
|
||||
}
|
||||
else
|
||||
{
|
||||
HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
|
||||
}
|
||||
|
||||
/* Handle Rx Queue Level Interrupts */
|
||||
if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
|
||||
{
|
||||
USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
|
||||
HCD_RXQLVL_IRQHandler(hhcd);
|
||||
|
||||
USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles HCD Wakeup interrupt request.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
UNUSED(hhcd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief SOF callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_SOF_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connection Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Connect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnection Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port Enabled Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port Disabled Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify URB state change callback.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param urb_state:
|
||||
* This parameter can be one of these values:
|
||||
* URB_IDLE/
|
||||
* URB_DONE/
|
||||
* URB_NOTREADY/
|
||||
* URB_NYET/
|
||||
* URB_ERROR/
|
||||
* URB_STALL/
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
UNUSED(chnum);
|
||||
UNUSED(urb_state);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User USB HCD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hhcd USB HCD handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
|
||||
* @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
|
||||
* @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
|
||||
* @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
|
||||
* @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
|
||||
* @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
|
||||
HAL_HCD_CallbackIDTypeDef CallbackID,
|
||||
pHCD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_SOF_CB_ID :
|
||||
hhcd->SOFCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_CONNECT_CB_ID :
|
||||
hhcd->ConnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_DISCONNECT_CB_ID :
|
||||
hhcd->DisconnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_ENABLED_CB_ID :
|
||||
hhcd->PortEnabledCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_DISABLED_CB_ID :
|
||||
hhcd->PortDisabledCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USB HCD Callback
|
||||
* USB HCD callback is redirected to the weak predefined callback
|
||||
* @param hhcd USB HCD handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
|
||||
* @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
|
||||
* @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
|
||||
* @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
|
||||
* @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
|
||||
* @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
/* Setup Legacy weak Callbacks */
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_SOF_CB_ID :
|
||||
hhcd->SOFCallback = HAL_HCD_SOF_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_CONNECT_CB_ID :
|
||||
hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_DISCONNECT_CB_ID :
|
||||
hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_ENABLED_CB_ID :
|
||||
hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_DISABLED_CB_ID :
|
||||
hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB HCD Host Channel Notify URB Change Callback
|
||||
* To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
|
||||
* @param hhcd HCD handle
|
||||
* @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
|
||||
pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
hhcd->HC_NotifyURBChangeCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB HCD Host Channel Notify URB Change Callback
|
||||
* USB HCD Host Channel Notify URB Change Callback is redirected
|
||||
* to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the HCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
__HAL_LOCK(hhcd);
|
||||
/* Enable port power */
|
||||
(void)USB_DriveVbus(hhcd->Instance, 1U);
|
||||
|
||||
/* Enable global interrupt */
|
||||
__HAL_HCD_ENABLE(hhcd);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
|
||||
HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
__HAL_LOCK(hhcd);
|
||||
(void)USB_StopHost(hhcd->Instance);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the host port.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_ResetPort(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the HCD handle state.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
|
||||
{
|
||||
return hhcd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return URB state for a channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval URB state.
|
||||
* This parameter can be one of these values:
|
||||
* URB_IDLE/
|
||||
* URB_DONE/
|
||||
* URB_NOTREADY/
|
||||
* URB_NYET/
|
||||
* URB_ERROR/
|
||||
* URB_STALL
|
||||
*/
|
||||
HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].urb_state;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the last host transfer size.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval last transfer size in byte
|
||||
*/
|
||||
uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].xfer_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Host Channel state.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval Host channel state
|
||||
* This parameter can be one of these values:
|
||||
* HC_IDLE/
|
||||
* HC_XFRC/
|
||||
* HC_HALTED/
|
||||
* HC_NYET/
|
||||
* HC_NAK/
|
||||
* HC_STALL/
|
||||
* HC_XACTERR/
|
||||
* HC_BBLERR/
|
||||
* HC_DATATGLERR
|
||||
*/
|
||||
HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the current Host frame number.
|
||||
* @param hhcd HCD handle
|
||||
* @retval Current Host frame number
|
||||
*/
|
||||
uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_GetCurrentFrame(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Host enumeration speed.
|
||||
* @param hhcd HCD handle
|
||||
* @retval Enumeration speed
|
||||
*/
|
||||
uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_GetHostSpeed(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set host channel Hub information.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param addr Hub address
|
||||
* @param PortNbr Hub port number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
|
||||
uint8_t addr, uint8_t PortNbr)
|
||||
{
|
||||
hhcd->hc[ch_num].hub_addr = addr;
|
||||
hhcd->hc[ch_num].hub_port_nbr = PortNbr;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear host channel hub information.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
|
||||
{
|
||||
hhcd->hc[ch_num].hub_addr = 0U;
|
||||
hhcd->hc[ch_num].hub_port_nbr = 0U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup HCD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Handle Host Channel IN interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
|
||||
hhcd->hc[chnum].state = HC_BBLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
||||
hhcd->hc[chnum].state = HC_STALL;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
||||
hhcd->hc[chnum].state = HC_DATATGLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
|
||||
{
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_XFRC;
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
|
||||
{
|
||||
USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
if (hhcd->Init.dma_enable == 1U)
|
||||
{
|
||||
if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (hhcd->hc[chnum].state == HC_XFRC)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_STALL)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_STALL;
|
||||
}
|
||||
else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
|
||||
(hhcd->hc[chnum].state == HC_DATATGLERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
if (hhcd->hc[chnum].ErrCnt > 2U)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NYET)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_ACK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NAK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_BBLERR)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[chnum].state == HC_HALTED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
|
||||
hhcd->hc[chnum].state = HC_NYET;
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
|
||||
{
|
||||
if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Host Channel OUT interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
uint32_t num_packets;
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
||||
hhcd->hc[chnum].state = HC_XFRC;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
||||
hhcd->hc[chnum].state = HC_STALL;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_DATATGLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (hhcd->hc[chnum].state == HC_XFRC)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
|
||||
{
|
||||
if (hhcd->Init.dma_enable == 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_out ^= 1U;
|
||||
}
|
||||
|
||||
if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
|
||||
{
|
||||
num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
|
||||
|
||||
if ((num_packets & 1U) != 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_out ^= 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_ACK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NAK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_STALL)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_STALL;
|
||||
}
|
||||
else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
|
||||
(hhcd->hc[chnum].state == HC_DATATGLERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
if (hhcd->hc[chnum].ErrCnt > 2U)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Rx Queue Level interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t pktsts;
|
||||
uint32_t pktcnt;
|
||||
uint32_t GrxstspReg;
|
||||
uint32_t xferSizePktCnt;
|
||||
uint32_t tmpreg;
|
||||
uint32_t chnum;
|
||||
|
||||
GrxstspReg = hhcd->Instance->GRXSTSP;
|
||||
chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
|
||||
pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
|
||||
pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
|
||||
switch (pktsts)
|
||||
{
|
||||
case GRXSTS_PKTSTS_IN:
|
||||
/* Read the data into the host buffer. */
|
||||
if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
|
||||
{
|
||||
if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
|
||||
{
|
||||
(void)USB_ReadPacket(hhcd->Instance,
|
||||
hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
|
||||
|
||||
/* manage multiple Xfer */
|
||||
hhcd->hc[chnum].xfer_buff += pktcnt;
|
||||
hhcd->hc[chnum].xfer_count += pktcnt;
|
||||
|
||||
/* get transfer size packet count */
|
||||
xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
|
||||
|
||||
if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
|
||||
{
|
||||
/* re-activate the channel when more packets are expected */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
|
||||
break;
|
||||
|
||||
case GRXSTS_PKTSTS_IN_XFER_COMP:
|
||||
case GRXSTS_PKTSTS_CH_HALTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Host Port interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
__IO uint32_t hprt0;
|
||||
__IO uint32_t hprt0_dup;
|
||||
|
||||
/* Handle Host Port Interrupts */
|
||||
hprt0 = USBx_HPRT0;
|
||||
hprt0_dup = USBx_HPRT0;
|
||||
|
||||
hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
|
||||
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
|
||||
|
||||
/* Check whether Port Connect detected */
|
||||
if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
|
||||
{
|
||||
if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->ConnectCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_Connect_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
hprt0_dup |= USB_OTG_HPRT_PCDET;
|
||||
}
|
||||
|
||||
/* Check whether Port Enable Changed */
|
||||
if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
|
||||
{
|
||||
hprt0_dup |= USB_OTG_HPRT_PENCHNG;
|
||||
|
||||
if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
|
||||
{
|
||||
if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
|
||||
{
|
||||
if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
|
||||
{
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->Init.speed == HCD_SPEED_FULL)
|
||||
{
|
||||
USBx_HOST->HFIR = HFIR_60_MHZ;
|
||||
}
|
||||
}
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->PortEnabledCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_PortEnabled_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->PortDisabledCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_PortDisabled_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for an overcurrent */
|
||||
if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
|
||||
{
|
||||
hprt0_dup |= USB_OTG_HPRT_POCCHNG;
|
||||
}
|
||||
|
||||
/* Clear Port Interrupts */
|
||||
USBx_HPRT0 = hprt0_dup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
#endif /* HAL_HCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
1876
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2s.c
Normal file
1876
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2s.c
Normal file
@@ -0,0 +1,1876 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_i2s.c
|
||||
* @author MCD Application Team
|
||||
* @brief I2S HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Integrated Interchip Sound (I2S) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral State and Errors 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 I2S HAL driver can be used as follow:
|
||||
|
||||
(#) Declare a I2S_HandleTypeDef handle structure.
|
||||
(#) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API:
|
||||
(##) Enable the SPIx interface clock.
|
||||
(##) I2S pins configuration:
|
||||
(+++) Enable the clock for the I2S GPIOs.
|
||||
(+++) Configure these I2S pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT()
|
||||
and HAL_I2S_Receive_IT() APIs).
|
||||
(+++) Configure the I2Sx interrupt priority.
|
||||
(+++) Enable the NVIC I2S IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA()
|
||||
and HAL_I2S_Receive_DMA() APIs:
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx Stream/Channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx Stream/Channel.
|
||||
(+++) Associate the initialized DMA handle to the I2S DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
|
||||
DMA Tx/Rx Stream/Channel.
|
||||
|
||||
(#) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity
|
||||
using HAL_I2S_Init() function.
|
||||
|
||||
-@- The specific I2S interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_I2S_ENABLE_IT() and __HAL_I2S_DISABLE_IT() inside the transmit and receive process.
|
||||
-@- The I2SxCLK source is the system clock (provided by the HSI, the HSE or the PLL, and sourcing the AHB clock).
|
||||
For connectivity line devices, the I2SxCLK source can be either SYSCLK or the PLL3 VCO (2 x PLL3CLK) clock
|
||||
in order to achieve the maximum accuracy.
|
||||
-@- Make sure that either:
|
||||
(+@) External clock source is configured after setting correctly
|
||||
the define constant HSE_VALUE in the stm32f1xx_hal_conf.h file.
|
||||
|
||||
(#) Three mode of operations are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_I2S_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_I2S_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_I2S_Transmit_IT()
|
||||
(+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_I2S_Receive_IT()
|
||||
(+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_I2S_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_I2S_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_I2S_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_I2S_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_I2S_DMAStop()
|
||||
In Slave mode, if HAL_I2S_DMAStop is used to stop the communication, an error
|
||||
HAL_I2S_ERROR_BUSY_LINE_RX is raised as the master continue to transmit data.
|
||||
In this case __HAL_I2S_FLUSH_RX_DR macro must be used to flush the remaining data
|
||||
inside DR register and avoid using DeInit/Init process for the next transfer.
|
||||
|
||||
*** I2S HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of most used macros in I2S HAL driver.
|
||||
|
||||
(+) __HAL_I2S_ENABLE: Enable the specified SPI peripheral (in I2S mode)
|
||||
(+) __HAL_I2S_DISABLE: Disable the specified SPI peripheral (in I2S mode)
|
||||
(+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts
|
||||
(+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts
|
||||
(+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not
|
||||
(+) __HAL_I2S_FLUSH_RX_DR: Read DR Register to Flush RX Data
|
||||
|
||||
[..]
|
||||
(@) You can refer to the I2S HAL driver header file for more useful macros
|
||||
|
||||
*** I2S HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Callback registration:
|
||||
|
||||
(#) The compilation flag USE_HAL_I2S_REGISTER_CALLBACKS when set to 1U
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_I2S_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function HAL_I2S_RegisterCallback() allows to register following callbacks:
|
||||
(++) TxCpltCallback : I2S Tx Completed callback
|
||||
(++) RxCpltCallback : I2S Rx Completed callback
|
||||
(++) TxHalfCpltCallback : I2S Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : I2S Rx Half Completed callback
|
||||
(++) ErrorCallback : I2S Error callback
|
||||
(++) MspInitCallback : I2S Msp Init callback
|
||||
(++) MspDeInitCallback : I2S 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_I2S_UnRegisterCallback to reset a callback to the default
|
||||
weak function.
|
||||
HAL_I2S_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) TxCpltCallback : I2S Tx Completed callback
|
||||
(++) RxCpltCallback : I2S Rx Completed callback
|
||||
(++) TxHalfCpltCallback : I2S Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : I2S Rx Half Completed callback
|
||||
(++) ErrorCallback : I2S Error callback
|
||||
(++) MspInitCallback : I2S Msp Init callback
|
||||
(++) MspDeInitCallback : I2S Msp DeInit callback
|
||||
|
||||
[..]
|
||||
By default, after the HAL_I2S_Init() and when the state is HAL_I2S_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples HAL_I2S_MasterTxCpltCallback(), HAL_I2S_MasterRxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak functions in the HAL_I2S_Init()/ HAL_I2S_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
If MspInit or MspDeInit are not null, the HAL_I2S_Init()/ HAL_I2S_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_I2S_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit functions that can be registered/unregistered
|
||||
in HAL_I2S_STATE_READY or HAL_I2S_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_I2S_RegisterCallback() before calling HAL_I2S_DeInit()
|
||||
or HAL_I2S_Init() function.
|
||||
|
||||
[..]
|
||||
When the compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
*** I2S Workarounds linked to Silicon Limitation ***
|
||||
====================================================
|
||||
[..]
|
||||
(@) Only the 16-bit mode with no data extension can be used when the I2S
|
||||
is in Master and used the PCM long synchronization mode.
|
||||
|
||||
@endverbatim
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
|
||||
#if defined(SPI_I2S_SUPPORT)
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup I2S I2S
|
||||
* @brief I2S HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define I2S_TIMEOUT_FLAG 100U /*!< Timeout 100 ms */
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup I2S_Private_Functions I2S Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s);
|
||||
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s);
|
||||
static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions I2S Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_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 I2Sx peripheral in simplex mode:
|
||||
|
||||
(+) User must Implement HAL_I2S_MspInit() function in which he configures
|
||||
all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
|
||||
|
||||
(+) Call the function HAL_I2S_Init() to configure the selected device with
|
||||
the selected configuration:
|
||||
(++) Mode
|
||||
(++) Standard
|
||||
(++) Data Format
|
||||
(++) MCLK Output
|
||||
(++) Audio frequency
|
||||
(++) Polarity
|
||||
|
||||
(+) Call the function HAL_I2S_DeInit() to restore the default configuration
|
||||
of the selected I2Sx peripheral.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the I2S according to the specified parameters
|
||||
* in the I2S_InitTypeDef and create the associated handle.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
uint32_t i2sdiv;
|
||||
uint32_t i2sodd;
|
||||
uint32_t packetlength;
|
||||
uint32_t tmp;
|
||||
uint32_t i2sclk;
|
||||
|
||||
/* Check the I2S handle allocation */
|
||||
if (hi2s == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
|
||||
assert_param(IS_I2S_MODE(hi2s->Init.Mode));
|
||||
assert_param(IS_I2S_STANDARD(hi2s->Init.Standard));
|
||||
assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat));
|
||||
assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput));
|
||||
assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq));
|
||||
assert_param(IS_I2S_CPOL(hi2s->Init.CPOL));
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hi2s->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
/* Init the I2S Callback settings */
|
||||
hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
|
||||
if (hi2s->MspInitCallback == NULL)
|
||||
{
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
hi2s->MspInitCallback(hi2s);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_I2S_MspInit(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_BUSY;
|
||||
|
||||
/*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/
|
||||
/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||||
CLEAR_BIT(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \
|
||||
SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \
|
||||
SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD));
|
||||
hi2s->Instance->I2SPR = 0x0002U;
|
||||
|
||||
/*----------------------- I2SPR: I2SDIV and ODD Calculation -----------------*/
|
||||
/* If the requested audio frequency is not the default, compute the prescaler */
|
||||
if (hi2s->Init.AudioFreq != I2S_AUDIOFREQ_DEFAULT)
|
||||
{
|
||||
/* Check the frame length (For the Prescaler computing) ********************/
|
||||
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
|
||||
{
|
||||
/* Packet length is 16 bits */
|
||||
packetlength = 16U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Packet length is 32 bits */
|
||||
packetlength = 32U;
|
||||
}
|
||||
|
||||
/* I2S standard */
|
||||
if (hi2s->Init.Standard <= I2S_STANDARD_LSB)
|
||||
{
|
||||
/* In I2S standard packet length is multiplied by 2 */
|
||||
packetlength = packetlength * 2U;
|
||||
}
|
||||
|
||||
/* Get the source clock value **********************************************/
|
||||
if (hi2s->Instance == SPI2)
|
||||
{
|
||||
/* Get the source clock value: based on SPI2 Instance */
|
||||
i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S2);
|
||||
}
|
||||
else if (hi2s->Instance == SPI3)
|
||||
{
|
||||
/* Get the source clock value: based on SPI3 Instance */
|
||||
i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S3);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the source clock value: based on System Clock value */
|
||||
i2sclk = HAL_RCC_GetSysClockFreq();
|
||||
}
|
||||
/* Compute the Real divider depending on the MCLK output state, with a floating point */
|
||||
if (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE)
|
||||
{
|
||||
/* MCLK output is enabled */
|
||||
if (hi2s->Init.DataFormat != I2S_DATAFORMAT_16B)
|
||||
{
|
||||
tmp = (uint32_t)(((((i2sclk / (packetlength * 4U)) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (uint32_t)(((((i2sclk / (packetlength * 8U)) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MCLK output is disabled */
|
||||
tmp = (uint32_t)(((((i2sclk / packetlength) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
|
||||
/* Remove the flatting point */
|
||||
tmp = tmp / 10U;
|
||||
|
||||
/* Check the parity of the divider */
|
||||
i2sodd = (uint32_t)(tmp & (uint32_t)1U);
|
||||
|
||||
/* Compute the i2sdiv prescaler */
|
||||
i2sdiv = (uint32_t)((tmp - i2sodd) / 2U);
|
||||
|
||||
/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
|
||||
i2sodd = (uint32_t)(i2sodd << 8U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the default values */
|
||||
i2sdiv = 2U;
|
||||
i2sodd = 0U;
|
||||
}
|
||||
|
||||
/* Test if the divider is 1 or 0 or greater than 0xFF */
|
||||
if ((i2sdiv < 2U) || (i2sdiv > 0xFFU))
|
||||
{
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_PRESCALER);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/
|
||||
|
||||
/* Write to SPIx I2SPR register the computed value */
|
||||
hi2s->Instance->I2SPR = (uint32_t)((uint32_t)i2sdiv | (uint32_t)(i2sodd | (uint32_t)hi2s->Init.MCLKOutput));
|
||||
|
||||
/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||||
/* And configure the I2S with the I2S_InitStruct values */
|
||||
MODIFY_REG(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \
|
||||
SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \
|
||||
SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \
|
||||
SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD), \
|
||||
(SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode | \
|
||||
hi2s->Init.Standard | hi2s->Init.DataFormat | \
|
||||
hi2s->Init.CPOL));
|
||||
|
||||
#if defined(SPI_I2SCFGR_ASTRTEN)
|
||||
if ((hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) || ((hi2s->Init.Standard == I2S_STANDARD_PCM_LONG)))
|
||||
{
|
||||
/* Write to SPIx I2SCFGR */
|
||||
SET_BIT(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_ASTRTEN);
|
||||
}
|
||||
#endif /* SPI_I2SCFGR_ASTRTEN */
|
||||
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the I2S peripheral
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Check the I2S handle allocation */
|
||||
if (hi2s == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_BUSY;
|
||||
|
||||
/* Disable the I2S Peripheral Clock */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
if (hi2s->MspDeInitCallback == NULL)
|
||||
{
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
hi2s->MspDeInitCallback(hi2s);
|
||||
#else
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
HAL_I2S_MspDeInit(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->State = HAL_I2S_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S MSP Init
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S MSP DeInit
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User I2S Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified I2S.
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID,
|
||||
pI2S_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hi2s->ErrorCode |= HAL_I2S_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (HAL_I2S_STATE_READY == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_TX_COMPLETE_CB_ID :
|
||||
hi2s->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_COMPLETE_CB_ID :
|
||||
hi2s->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_ERROR_CB_ID :
|
||||
hi2s->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_I2S_STATE_RESET == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an I2S Callback
|
||||
* I2S callback is redirected to the weak predefined callback
|
||||
* @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified I2S.
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_UnRegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (HAL_I2S_STATE_READY == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_TX_COMPLETE_CB_ID :
|
||||
hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_COMPLETE_CB_ID :
|
||||
hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_ERROR_CB_ID :
|
||||
hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_I2S_STATE_RESET == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_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 I2S data
|
||||
transfers.
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode : The communication is performed in the polling mode.
|
||||
The 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 functions return the status of the transfer startup.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
|
||||
(#) Blocking mode functions are :
|
||||
(++) HAL_I2S_Transmit()
|
||||
(++) HAL_I2S_Receive()
|
||||
|
||||
(#) No-Blocking mode functions with Interrupt are :
|
||||
(++) HAL_I2S_Transmit_IT()
|
||||
(++) HAL_I2S_Receive_IT()
|
||||
|
||||
(#) No-Blocking mode functions with DMA are :
|
||||
(++) HAL_I2S_Transmit_DMA()
|
||||
(++) HAL_I2S_Receive_DMA()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_I2S_TxCpltCallback()
|
||||
(++) HAL_I2S_RxCpltCallback()
|
||||
(++) HAL_I2S_ErrorCallback()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in blocking mode
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @param Timeout Timeout duration
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR;
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
while (hi2s->TxXferCount > 0U)
|
||||
{
|
||||
hi2s->Instance->DR = (*hi2s->pTxBuffPtr);
|
||||
hi2s->pTxBuffPtr++;
|
||||
hi2s->TxXferCount--;
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if an underrun occurs */
|
||||
if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET)
|
||||
{
|
||||
/* Clear underrun flag */
|
||||
__HAL_I2S_CLEAR_UDRFLAG(hi2s);
|
||||
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if Slave mode is selected */
|
||||
if (((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX)
|
||||
|| ((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX))
|
||||
{
|
||||
/* Wait until Busy flag is reset */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @param Timeout Timeout duration
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate
|
||||
* in continuous way and as the I2S is not disabled at the end of the I2S transaction.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Check if Master Receiver mode is selected */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
|
||||
{
|
||||
/* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read
|
||||
access to the SPI_SR register. */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
}
|
||||
|
||||
/* Receive data */
|
||||
while (hi2s->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait until RXNE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
(*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR;
|
||||
hi2s->pRxBuffPtr++;
|
||||
hi2s->RxXferCount--;
|
||||
|
||||
/* Check if an overrun occurs */
|
||||
if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET)
|
||||
{
|
||||
/* Clear overrun flag */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Enable TXE and ERR interrupt */
|
||||
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Receive data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @note It is recommended to use DMA for the I2S receiver to avoid de-synchronization
|
||||
* between Master and Slave otherwise the I2S interrupt should be optimized.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Enable RXNE and ERR interrupt */
|
||||
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with DMA
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Transmit data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Set the I2S Tx DMA Half transfer complete callback */
|
||||
hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt;
|
||||
|
||||
/* Set the I2S Tx DMA transfer complete callback */
|
||||
hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hi2s->hdmatx->XferErrorCallback = I2S_DMAError;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx,
|
||||
(uint32_t)hi2s->pTxBuffPtr,
|
||||
(uint32_t)&hi2s->Instance->DR,
|
||||
hi2s->TxXferSize))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Check if the I2S Tx request is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with DMA
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Receive data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Set the I2S Rx DMA Half transfer complete callback */
|
||||
hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
|
||||
|
||||
/* Set the I2S Rx DMA transfer complete callback */
|
||||
hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hi2s->hdmarx->XferErrorCallback = I2S_DMAError;
|
||||
|
||||
/* Check if Master Receiver mode is selected */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
|
||||
{
|
||||
/* Clear the Overrun Flag by a read operation to the SPI_DR register followed by a read
|
||||
access to the SPI_SR register. */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
}
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, (uint32_t)hi2s->pRxBuffPtr,
|
||||
hi2s->RxXferSize))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Check if the I2S Rx request is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
|
||||
{
|
||||
/* Disable the I2S DMA Tx request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
else if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
|
||||
{
|
||||
/* Disable the I2S DMA Rx request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
|
||||
{
|
||||
/* Enable the I2S DMA Tx request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
else if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
|
||||
{
|
||||
/* Enable the I2S DMA Rx request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/* If the I2S peripheral is still not enabled, enable it */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
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_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
|
||||
when calling HAL_DMA_Abort() API the DMA TX or RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
|
||||
*/
|
||||
|
||||
if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX))
|
||||
{
|
||||
/* Abort the I2S DMA tx Stream/Channel */
|
||||
if (hi2s->hdmatx != NULL)
|
||||
{
|
||||
/* Disable the I2S DMA tx Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
|
||||
{
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, I2S_TIMEOUT_FLAG) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Wait until BSY flag is Reset */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, I2S_TIMEOUT_FLAG) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable I2S peripheral */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
/* Clear UDR flag */
|
||||
__HAL_I2S_CLEAR_UDRFLAG(hi2s);
|
||||
|
||||
/* Disable the I2S Tx DMA requests */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
}
|
||||
|
||||
else if ((hi2s->Init.Mode == I2S_MODE_MASTER_RX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_RX))
|
||||
{
|
||||
/* Abort the I2S DMA rx Stream/Channel */
|
||||
if (hi2s->hdmarx != NULL)
|
||||
{
|
||||
/* Disable the I2S DMA rx Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
|
||||
{
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable I2S peripheral */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
/* Clear OVR flag */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
|
||||
/* Disable the I2S Rx DMA request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
if (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_BUSY_LINE_RX);
|
||||
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read DR to Flush RX Data */
|
||||
READ_REG((hi2s->Instance)->DR);
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2S interrupt request.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
uint32_t itsource = hi2s->Instance->CR2;
|
||||
uint32_t itflag = hi2s->Instance->SR;
|
||||
|
||||
/* I2S in mode Receiver ------------------------------------------------*/
|
||||
if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) == RESET) &&
|
||||
(I2S_CHECK_FLAG(itflag, I2S_FLAG_RXNE) != RESET) && (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_RXNE) != RESET))
|
||||
{
|
||||
I2S_Receive_IT(hi2s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* I2S in mode Tramitter -----------------------------------------------*/
|
||||
if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_TXE) != RESET) && (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_TXE) != RESET))
|
||||
{
|
||||
I2S_Transmit_IT(hi2s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* I2S interrupt error -------------------------------------------------*/
|
||||
if (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_ERR) != RESET)
|
||||
{
|
||||
/* I2S Overrun error interrupt occurred ---------------------------------*/
|
||||
if (I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) != RESET)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
|
||||
}
|
||||
|
||||
/* I2S Underrun error interrupt occurred --------------------------------*/
|
||||
if (I2S_CHECK_FLAG(itflag, I2S_FLAG_UDR) != RESET)
|
||||
{
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
|
||||
}
|
||||
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->ErrorCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_ErrorCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer Half completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_TxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer half completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_RxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_RxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S error callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the I2S state
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
return hi2s->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the I2S error code
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval I2S Error Code
|
||||
*/
|
||||
uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
return hi2s->ErrorCode;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_Private_Functions I2S Private Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief DMA I2S 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 I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* if DMA is configured in DMA_NORMAL Mode */
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
hi2s->TxXferCount = 0U;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
}
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S transmit process half complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Call user Tx half complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxHalfCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxHalfCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S 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 I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* if DMA is configured in DMA_NORMAL Mode */
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
hi2s->RxXferCount = 0U;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
}
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S receive process half complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Call user Rx half complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxHalfCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxHalfCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S 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 I2S_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Disable Rx and Tx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN));
|
||||
hi2s->TxXferCount = 0U;
|
||||
hi2s->RxXferCount = 0U;
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->ErrorCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_ErrorCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Transmit data */
|
||||
hi2s->Instance->DR = (*hi2s->pTxBuffPtr);
|
||||
hi2s->pTxBuffPtr++;
|
||||
hi2s->TxXferCount--;
|
||||
|
||||
if (hi2s->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Receive data */
|
||||
(*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR;
|
||||
hi2s->pRxBuffPtr++;
|
||||
hi2s->RxXferCount--;
|
||||
|
||||
if (hi2s->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2S Communication Timeout.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param Flag Flag checked
|
||||
* @param State Value of the flag expected
|
||||
* @param Timeout Duration of the timeout
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until flag is set to status*/
|
||||
while (((__HAL_I2S_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
|
||||
#endif /* HAL_I2S_MODULE_ENABLED */
|
||||
|
||||
2666
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_irda.c
Normal file
2666
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_irda.c
Normal file
@@ -0,0 +1,2666 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_irda.c
|
||||
* @author MCD Application Team
|
||||
* @brief IRDA HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the IrDA SIR ENDEC block (IrDA):
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors 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 IRDA HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a IRDA_HandleTypeDef handle structure (eg. IRDA_HandleTypeDef hirda).
|
||||
(#) Initialize the IRDA low level resources by implementing the HAL_IRDA_MspInit() API:
|
||||
(##) Enable the USARTx interface clock.
|
||||
(##) IRDA pins configuration:
|
||||
(+++) Enable the clock for the IRDA GPIOs.
|
||||
(+++) Configure IRDA pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_IRDA_Transmit_IT()
|
||||
and HAL_IRDA_Receive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_IRDA_Transmit_DMA()
|
||||
and HAL_IRDA_Receive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the IRDA DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the IRDAx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length, Parity, IrDA Mode, Prescaler
|
||||
and Mode(Receiver/Transmitter) in the hirda Init structure.
|
||||
|
||||
(#) Initialize the IRDA registers by calling the HAL_IRDA_Init() API:
|
||||
(++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_IRDA_MspInit() API.
|
||||
|
||||
-@@- The specific IRDA interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_IRDA_ENABLE_IT() and __HAL_IRDA_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
(#) Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_IRDA_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_IRDA_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_IRDA_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_IRDA_Receive_IT()
|
||||
(+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
=============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_IRDA_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_IRDA_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_IRDA_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_IRDA_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_IRDA_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_IRDA_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_IRDA_DMAStop()
|
||||
|
||||
*** IRDA HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of most used macros in IRDA HAL driver.
|
||||
|
||||
(+) __HAL_IRDA_ENABLE: Enable the IRDA peripheral
|
||||
(+) __HAL_IRDA_DISABLE: Disable the IRDA peripheral
|
||||
(+) __HAL_IRDA_GET_FLAG : Check whether the specified IRDA flag is set or not
|
||||
(+) __HAL_IRDA_CLEAR_FLAG : Clear the specified IRDA pending flag
|
||||
(+) __HAL_IRDA_ENABLE_IT: Enable the specified IRDA interrupt
|
||||
(+) __HAL_IRDA_DISABLE_IT: Disable the specified IRDA interrupt
|
||||
(+) __HAL_IRDA_GET_IT_SOURCE: Check whether the specified IRDA interrupt has occurred or not
|
||||
|
||||
[..]
|
||||
(@) You can refer to the IRDA HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function HAL_IRDA_RegisterCallback() to register a user callback.
|
||||
Function HAL_IRDA_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : IRDA MspInit.
|
||||
(+) MspDeInitCallback : IRDA MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_IRDA_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
HAL_IRDA_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : IRDA MspInit.
|
||||
(+) MspDeInitCallback : IRDA MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxHalfCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_IRDA_Init()
|
||||
and HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_IRDA_Init() and HAL_IRDA_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_IRDA_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_IRDA_STATE_READY or HAL_IRDA_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_IRDA_RegisterCallback() before calling HAL_IRDA_DeInit()
|
||||
or HAL_IRDA_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
[..]
|
||||
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
the possible IRDA frame formats are as listed in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | IRDA frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 0 | 0 | | SB | 8 bit data | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 0 | 1 | | SB | 7 bit data | PB | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 0 | | SB | 9 bit data | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | 1 STB | |
|
||||
+-------------------------------------------------------------+
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA IRDA
|
||||
* @brief HAL IRDA module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup IRDA_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda);
|
||||
static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout);
|
||||
static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda);
|
||||
static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup IRDA_Exported_Functions IrDA Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group1 IrDA Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
|
||||
in asynchronous IrDA mode.
|
||||
(+) For the asynchronous mode only these parameters can be configured:
|
||||
(++) BaudRate
|
||||
(++) WordLength
|
||||
(++) Parity: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
please refer to Reference manual for possible IRDA frame formats.
|
||||
(++) Prescaler: A pulse of width less than two and greater than one PSC period(s) may or may
|
||||
not be rejected. The receiver set up time should be managed by software. The IrDA physical layer
|
||||
specification specifies a minimum of 10 ms delay between transmission and
|
||||
reception (IrDA is a half duplex protocol).
|
||||
(++) Mode: Receiver/transmitter modes
|
||||
(++) IrDAMode: the IrDA can operate in the Normal mode or in the Low power mode.
|
||||
[..]
|
||||
The HAL_IRDA_Init() API follows IRDA configuration procedures (details for the procedures
|
||||
are available in reference manual).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the IRDA mode according to the specified
|
||||
* parameters in the IRDA_InitTypeDef and create the associated handle.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Init(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Check the IRDA handle allocation */
|
||||
if (hirda == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the IRDA instance parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
/* Check the IRDA mode parameter in the IRDA handle */
|
||||
assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode));
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hirda->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
|
||||
IRDA_InitCallbacksToDefault(hirda);
|
||||
|
||||
if (hirda->MspInitCallback == NULL)
|
||||
{
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hirda->MspInitCallback(hirda);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_IRDA_MspInit(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY;
|
||||
|
||||
/* Disable the IRDA peripheral */
|
||||
__HAL_IRDA_DISABLE(hirda);
|
||||
|
||||
/* Set the IRDA communication parameters */
|
||||
IRDA_SetConfig(hirda);
|
||||
|
||||
/* In IrDA mode, the following bits must be kept cleared:
|
||||
- LINEN, STOP and CLKEN bits in the USART_CR2 register,
|
||||
- SCEN and HDSEL bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(hirda->Instance->CR2, (USART_CR2_LINEN | USART_CR2_STOP | USART_CR2_CLKEN));
|
||||
CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL));
|
||||
|
||||
/* Enable the IRDA peripheral */
|
||||
__HAL_IRDA_ENABLE(hirda);
|
||||
|
||||
/* Set the prescaler */
|
||||
MODIFY_REG(hirda->Instance->GTPR, USART_GTPR_PSC, hirda->Init.Prescaler);
|
||||
|
||||
/* Configure the IrDA mode */
|
||||
MODIFY_REG(hirda->Instance->CR3, USART_CR3_IRLP, hirda->Init.IrDAMode);
|
||||
|
||||
/* Enable the IrDA mode by setting the IREN bit in the CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_IREN);
|
||||
|
||||
/* Initialize the IRDA state*/
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the IRDA peripheral
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DeInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Check the IRDA handle allocation */
|
||||
if (hirda == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_IRDA_DISABLE(hirda);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
|
||||
if (hirda->MspDeInitCallback == NULL)
|
||||
{
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hirda->MspDeInitCallback(hirda);
|
||||
#else
|
||||
HAL_IRDA_MspDeInit(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_RESET;
|
||||
hirda->RxState = HAL_IRDA_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA MSP Init.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_MspInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA MSP DeInit.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_MspDeInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User IRDA Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_IRDA_RegisterCallback() may be called before HAL_IRDA_Init() in HAL_IRDA_STATE_RESET
|
||||
* to register callbacks for HAL_IRDA_MSPINIT_CB_ID and HAL_IRDA_MSPDEINIT_CB_ID
|
||||
* @param hirda irda handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_RegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID, pIRDA_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
|
||||
hirda->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_TX_COMPLETE_CB_ID :
|
||||
hirda->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
|
||||
hirda->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_COMPLETE_CB_ID :
|
||||
hirda->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ERROR_CB_ID :
|
||||
hirda->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_COMPLETE_CB_ID :
|
||||
hirda->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hirda->AbortTransmitCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hirda->AbortReceiveCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hirda->gState == HAL_IRDA_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an IRDA callback
|
||||
* IRDA callback is redirected to the weak predefined callback
|
||||
* @note The HAL_IRDA_UnRegisterCallback() may be called before HAL_IRDA_Init() in HAL_IRDA_STATE_RESET
|
||||
* to un-register callbacks for HAL_IRDA_MSPINIT_CB_ID and HAL_IRDA_MSPDEINIT_CB_ID
|
||||
* @param hirda irda handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_UnRegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (HAL_IRDA_STATE_READY == hirda->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
|
||||
hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_TX_COMPLETE_CB_ID :
|
||||
hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
|
||||
hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_COMPLETE_CB_ID :
|
||||
hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ERROR_CB_ID :
|
||||
hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_COMPLETE_CB_ID :
|
||||
hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_IRDA_STATE_RESET == hirda->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IRDA Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the IRDA data transfers.
|
||||
IrDA is a half duplex communication protocol. If the Transmitter is busy, any data
|
||||
on the IrDA receive line will be ignored by the IrDA decoder and if the Receiver
|
||||
is busy, data on the TX from the USART to IrDA will not be encoded by IrDA.
|
||||
While receiving data, transmission should be avoided as the data to be transmitted
|
||||
could be corrupted.
|
||||
|
||||
(#) 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.
|
||||
(++) Non-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, these API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated IRDA IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the Transmit or Receive process
|
||||
The HAL_IRDA_ErrorCallback() user callback will be executed when a communication error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_IRDA_Transmit()
|
||||
(++) HAL_IRDA_Receive()
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_IRDA_Transmit_IT()
|
||||
(++) HAL_IRDA_Receive_IT()
|
||||
(++) HAL_IRDA_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_IRDA_Transmit_DMA()
|
||||
(++) HAL_IRDA_Receive_DMA()
|
||||
(++) HAL_IRDA_DMAPause()
|
||||
(++) HAL_IRDA_DMAResume()
|
||||
(++) HAL_IRDA_DMAStop()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in Non Blocking mode:
|
||||
(++) HAL_IRDA_TxHalfCpltCallback()
|
||||
(++) HAL_IRDA_TxCpltCallback()
|
||||
(++) HAL_IRDA_RxHalfCpltCallback()
|
||||
(++) HAL_IRDA_RxCpltCallback()
|
||||
(++) HAL_IRDA_ErrorCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(+) HAL_IRDA_Abort()
|
||||
(+) HAL_IRDA_AbortTransmit()
|
||||
(+) HAL_IRDA_AbortReceive()
|
||||
(+) HAL_IRDA_Abort_IT()
|
||||
(+) HAL_IRDA_AbortTransmit_IT()
|
||||
(+) HAL_IRDA_AbortReceive_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_IRDA_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
|
||||
(+) HAL_IRDA_AbortCpltCallback()
|
||||
(+) HAL_IRDA_AbortTransmitCpltCallback()
|
||||
(+) HAL_IRDA_AbortReceiveCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_IRDA_ErrorCallback() user callback is executed. Transfer is kept ongoing on IRDA side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_IRDA_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @param Timeout Specify timeout value.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
while (hirda->TxXferCount > 0U)
|
||||
{
|
||||
hirda->TxXferCount--;
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
tmp = (const uint16_t *) pData;
|
||||
hirda->Instance->DR = (*tmp & (uint16_t)0x01FF);
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
pData += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
hirda->Instance->DR = (*pData++ & (uint8_t)0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* At end of Tx process, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @param Timeout Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint16_t *tmp;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hirda->RxXferSize = Size;
|
||||
hirda->RxXferCount = Size;
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while (hirda->RxXferCount > 0U)
|
||||
{
|
||||
hirda->RxXferCount--;
|
||||
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
tmp = (uint16_t *) pData ;
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x01FF);
|
||||
pData += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
*tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x00FF);
|
||||
pData += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pTxBuffPtr = pData;
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
/* Enable the IRDA Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pRxBuffPtr = pData;
|
||||
hirda->RxXferSize = Size;
|
||||
hirda->RxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
/* Enable the IRDA Parity Error and Data Register Not Empty Interrupts */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable the IRDA Data Register Not Empty Interrupts */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE);
|
||||
}
|
||||
|
||||
/* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pTxBuffPtr = pData;
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Set the IRDA DMA transfer complete callback */
|
||||
hirda->hdmatx->XferCpltCallback = IRDA_DMATransmitCplt;
|
||||
|
||||
/* Set the IRDA DMA half transfer complete callback */
|
||||
hirda->hdmatx->XferHalfCpltCallback = IRDA_DMATransmitHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hirda->hdmatx->XferErrorCallback = IRDA_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the IRDA transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(hirda->hdmatx, *(const uint32_t *)tmp, (uint32_t)&hirda->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_IRDA_CLEAR_FLAG(hirda, IRDA_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @note When the IRDA parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pRxBuffPtr = pData;
|
||||
hirda->RxXferSize = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Set the IRDA DMA transfer complete callback */
|
||||
hirda->hdmarx->XferCpltCallback = IRDA_DMAReceiveCplt;
|
||||
|
||||
/* Set the IRDA DMA half transfer complete callback */
|
||||
hirda->hdmarx->XferHalfCpltCallback = IRDA_DMAReceiveHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hirda->hdmarx->XferErrorCallback = IRDA_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
tmp = (uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(hirda->hdmarx, (uint32_t)&hirda->Instance->DR, *(uint32_t *)tmp, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
|
||||
__HAL_IRDA_CLEAR_OREFLAG(hirda);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
/* Enable the IRDA Parity Error Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
/* Disable the IRDA DMA Tx request */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
|
||||
{
|
||||
/* Enable the IRDA DMA Tx request */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
|
||||
{
|
||||
/* Clear the Overrun flag before resuming the Rx transfer */
|
||||
__HAL_IRDA_CLEAR_OREFLAG(hirda);
|
||||
|
||||
/* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the IRDA DMA Rx request */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL IRDA API under callbacks HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Stop IRDA DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
IRDA_EndTxTransfer(hirda);
|
||||
}
|
||||
|
||||
/* Stop IRDA DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_IRDA_Abort(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->RxState and hirda->gState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_IRDA_AbortTransmit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_IRDA_AbortReceive(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_IRDA_Abort_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to IRDA Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if IRDA DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = IRDA_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if IRDA DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at IRDA level */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* IRDA Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* IRDA Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if (AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable IRDA Interrupts (Tx)
|
||||
* - 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_IRDA_AbortTransmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = IRDA_DMATxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hirda->hdmatx->XferAbortCallback function in case of error */
|
||||
hirda->hdmatx->XferAbortCallback(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_IRDA_AbortReceive_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMARxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hirda->hdmarx->XferAbortCallback function in case of error */
|
||||
hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IRDA interrupt request.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_IRDA_IRQHandler(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(hirda->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(hirda->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(hirda->Instance->CR3);
|
||||
uint32_t errorflags = 0x00U;
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if (errorflags == RESET)
|
||||
{
|
||||
/* IRDA in mode Receiver -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
IRDA_Receive_IT(hirda);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some errors occur */
|
||||
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* IRDA parity error interrupt occurred -------------------------------*/
|
||||
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_PE;
|
||||
}
|
||||
|
||||
/* IRDA noise error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_NE;
|
||||
}
|
||||
|
||||
/* IRDA frame error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_FE;
|
||||
}
|
||||
|
||||
/* IRDA Over-Run interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_ORE;
|
||||
}
|
||||
/* Call IRDA Error Call back function if need be -----------------------*/
|
||||
if (hirda->ErrorCode != HAL_IRDA_ERROR_NONE)
|
||||
{
|
||||
/* IRDA in mode Receiver ---------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
IRDA_Receive_IT(hirda);
|
||||
}
|
||||
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if (((hirda->ErrorCode & HAL_IRDA_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the IRDA state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_ErrorCallback() at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMAAbortOnError;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non Blocking error : transfer could go on.
|
||||
Error is notified to user through user error callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* End if some error occurs */
|
||||
|
||||
/* IRDA in mode Transmitter ------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
IRDA_Transmit_IT(hirda);
|
||||
return;
|
||||
}
|
||||
|
||||
/* IRDA in mode Transmitter end --------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
IRDA_EndTransmit_IT(hirda);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_TxCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_TxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_TxHalfCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_RxCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_RxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_RxHalfCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA error callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_ErrorCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_ErrorCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Transmit Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortTransmitCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortTransmitCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Receive Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortReceiveCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortReceiveCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief IRDA State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to return the State of IrDA
|
||||
communication process and also return Peripheral Errors occurred during communication process
|
||||
(+) HAL_IRDA_GetState() API can be helpful to check in run-time the state of the IrDA peripheral.
|
||||
(+) HAL_IRDA_GetError() check in run-time errors that could be occurred during communication.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the IRDA state.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_IRDA_StateTypeDef HAL_IRDA_GetState(const IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t temp1 = 0x00U, temp2 = 0x00U;
|
||||
temp1 = hirda->gState;
|
||||
temp2 = hirda->RxState;
|
||||
|
||||
return (HAL_IRDA_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the IRDA error code
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @retval IRDA Error Code
|
||||
*/
|
||||
uint32_t HAL_IRDA_GetError(const IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
return hirda->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Private_Functions IRDA Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param hirda IRDA handle.
|
||||
* @retval none
|
||||
*/
|
||||
void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Init the IRDA Callback settings */
|
||||
hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
|
||||
}
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA transmit process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
hirda->TxXferCount = 0U;
|
||||
|
||||
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
|
||||
in the IRDA CR3 register */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the IRDA Transmit Complete Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
/* DMA Circular mode */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hirda->TxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Half complete callback */
|
||||
hirda->TxHalfCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxHalfCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
hirda->RxXferCount = 0U;
|
||||
|
||||
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by resetting the DMAR bit
|
||||
in the IRDA CR3 register */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hirda->RxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_IRDA_RxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process half complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Half complete callback*/
|
||||
hirda->RxHalfCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx Half complete callback */
|
||||
HAL_IRDA_RxHalfCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA communication error callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Stop IRDA DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
hirda->TxXferCount = 0U;
|
||||
IRDA_EndTxTransfer(hirda);
|
||||
}
|
||||
|
||||
/* Stop IRDA DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
hirda->RxXferCount = 0U;
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
}
|
||||
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IRDA Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @param Flag specifies the IRDA flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Tickstart Tick start value
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while ((__HAL_IRDA_GET_FLAG(hirda, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
|
||||
{
|
||||
/* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on IRDA peripheral (following error detection or Transmit completion).
|
||||
* @param hirda IRDA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* At end of Tx process, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on IRDA peripheral (following error detection or Reception completion).
|
||||
* @param hirda IRDA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA 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 IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA 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 IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
if (hirda->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA 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 IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
if (hirda->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Tx communication abort callback, when initiated by user by a call to
|
||||
* HAL_IRDA_AbortTransmit_IT API (Abort only Tx transfer)
|
||||
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
|
||||
* and leads to user Tx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Rx communication abort callback, when initiated by user by a call to
|
||||
* HAL_IRDA_AbortReceive_IT API (Abort only Rx transfer)
|
||||
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
|
||||
* and leads to user Rx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
|
||||
/* Check that a Tx process is ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
|
||||
{
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
tmp = (const uint16_t *) hirda->pTxBuffPtr;
|
||||
hirda->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
hirda->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->pTxBuffPtr += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->Instance->DR = (uint8_t)(*hirda->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
if (--hirda->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the IRDA Transmit Data Register Empty Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the IRDA Transmit Complete Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable the IRDA Transmit Complete Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Tx process is ended, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hirda->TxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint16_t *tmp;
|
||||
uint16_t uhdata;
|
||||
|
||||
/* Check that a Rx process is ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
|
||||
{
|
||||
uhdata = (uint16_t) READ_REG(hirda->Instance->DR);
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
tmp = (uint16_t *) hirda->pRxBuffPtr;
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*tmp = (uint16_t)(uhdata & (uint16_t)0x01FF);
|
||||
hirda->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
*tmp = (uint16_t)(uhdata & (uint16_t)0x00FF);
|
||||
hirda->pRxBuffPtr += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x007F);
|
||||
}
|
||||
}
|
||||
|
||||
if (--hirda->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the IRDA Data Register not empty Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the IRDA Parity Error Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Rx process is completed, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hirda->RxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_IRDA_RxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the IRDA peripheral.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
assert_param(IS_IRDA_BAUDRATE(hirda->Init.BaudRate));
|
||||
assert_param(IS_IRDA_WORD_LENGTH(hirda->Init.WordLength));
|
||||
assert_param(IS_IRDA_PARITY(hirda->Init.Parity));
|
||||
assert_param(IS_IRDA_MODE(hirda->Init.Mode));
|
||||
assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode));
|
||||
|
||||
/*-------------------------- USART CR2 Configuration ------------------------*/
|
||||
/* Clear STOP[13:12] bits */
|
||||
CLEAR_BIT(hirda->Instance->CR2, USART_CR2_STOP);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Configure the USART Word Length, Parity and mode:
|
||||
Set the M bits according to hirda->Init.WordLength value
|
||||
Set PCE and PS bits according to hirda->Init.Parity value
|
||||
Set TE and RE bits according to hirda->Init.Mode value */
|
||||
/* Write to USART CR1 */
|
||||
SET_BIT(hirda->Instance->CR1, (hirda->Init.WordLength | hirda->Init.Parity | hirda->Init.Mode));
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if(hirda->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate));
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_iwdg.c
|
||||
* @author MCD Application Team
|
||||
* @brief IWDG HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Independent Watchdog (IWDG) peripheral:
|
||||
* + Initialization and Start functions
|
||||
* + IO operation 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
|
||||
==============================================================================
|
||||
##### IWDG Generic features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) The IWDG can be started by either software or hardware (configurable
|
||||
through option byte).
|
||||
|
||||
(+) The IWDG is clocked by the Low-Speed Internal clock (LSI) and thus stays
|
||||
active even if the main clock fails.
|
||||
|
||||
(+) Once the IWDG is started, the LSI is forced ON and both cannot be
|
||||
disabled. The counter starts counting down from the reset value (0xFFF).
|
||||
When it reaches the end of count value (0x000) a reset signal is
|
||||
generated (IWDG reset).
|
||||
|
||||
(+) Whenever the key value 0x0000 AAAA is written in the IWDG_KR register,
|
||||
the IWDG_RLR value is reloaded into the counter and the watchdog reset
|
||||
is prevented.
|
||||
|
||||
(+) The IWDG is implemented in the VDD voltage domain that is still functional
|
||||
in STOP and STANDBY mode (IWDG reset can wake up the CPU from STANDBY).
|
||||
IWDGRST flag in RCC_CSR register can be used to inform when an IWDG
|
||||
reset occurs.
|
||||
|
||||
(+) Debug mode: When the microcontroller enters debug mode (core halted),
|
||||
the IWDG counter either continues to work normally or stops, depending
|
||||
on DBG_IWDG_STOP configuration bit in DBG module, accessible through
|
||||
__HAL_DBGMCU_FREEZE_IWDG() and __HAL_DBGMCU_UNFREEZE_IWDG() macros.
|
||||
|
||||
[..] Min-max timeout value @32KHz (LSI): ~125us / ~32.7s
|
||||
The IWDG timeout may vary due to LSI clock frequency dispersion.
|
||||
STM32F1xx devices provide the capability to measure the LSI clock
|
||||
frequency (LSI clock is internally connected to TIM5 CH4 input capture).
|
||||
The measured value can be used to have an IWDG timeout with an
|
||||
acceptable accuracy.
|
||||
|
||||
[..] Default timeout value (necessary for IWDG_SR status register update):
|
||||
Constant LSI_VALUE is defined based on the nominal LSI clock frequency.
|
||||
This frequency being subject to variations as mentioned above, the
|
||||
default timeout value (defined through constant HAL_IWDG_DEFAULT_TIMEOUT
|
||||
below) may become too short or too long.
|
||||
In such cases, this default timeout value can be tuned by redefining
|
||||
the constant LSI_VALUE at user-application level (based, for instance,
|
||||
on the measured LSI clock frequency as explained above).
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Use IWDG using HAL_IWDG_Init() function to :
|
||||
(++) Enable instance by writing Start keyword in IWDG_KEY register. LSI
|
||||
clock is forced ON and IWDG counter starts counting down.
|
||||
(++) Enable write access to configuration registers:
|
||||
IWDG_PR and IWDG_RLR.
|
||||
(++) Configure the IWDG prescaler and counter reload value. This reload
|
||||
value will be loaded in the IWDG counter each time the watchdog is
|
||||
reloaded, then the IWDG will start counting down from this value.
|
||||
(++) Wait for status flags to be reset.
|
||||
|
||||
(#) Then the application program must refresh the IWDG counter at regular
|
||||
intervals during normal operation to prevent an MCU reset, using
|
||||
HAL_IWDG_Refresh() function.
|
||||
|
||||
*** IWDG HAL driver macros list ***
|
||||
====================================
|
||||
[..]
|
||||
Below the list of most used macros in IWDG HAL driver:
|
||||
(+) __HAL_IWDG_START: Enable the IWDG peripheral
|
||||
(+) __HAL_IWDG_RELOAD_COUNTER: Reloads IWDG counter with value defined in
|
||||
the reload register
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
/** @addtogroup IWDG
|
||||
* @brief IWDG HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup IWDG_Private_Defines IWDG Private Defines
|
||||
* @{
|
||||
*/
|
||||
/* Status register needs up to 5 LSI clock periods divided by the clock
|
||||
prescaler to be updated. The number of LSI clock periods is upper-rounded to
|
||||
6 for the timeout value calculation.
|
||||
The timeout value is calculated using the highest prescaler (256) and
|
||||
the LSI_VALUE constant. The value of this constant can be changed by the user
|
||||
to take into account possible LSI clock period variations.
|
||||
The timeout value is multiplied by 1000 to be converted in milliseconds.
|
||||
LSI startup time is also considered here by adding LSI_STARTUP_TIME
|
||||
converted in milliseconds. */
|
||||
#define HAL_IWDG_DEFAULT_TIMEOUT (((6UL * 256UL * 1000UL) / (LSI_VALUE / 128U)) + \
|
||||
((LSI_STARTUP_TIME / 1000UL) + 1UL))
|
||||
#define IWDG_KERNEL_UPDATE_FLAGS (IWDG_SR_RVU | IWDG_SR_PVU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions_Group1
|
||||
* @brief Initialization and Start functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and Start functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Initialize the IWDG according to the specified parameters in the
|
||||
IWDG_InitTypeDef of associated handle.
|
||||
(+) Once initialization is performed in HAL_IWDG_Init function, Watchdog
|
||||
is reloaded in order to exit function with correct time base.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the IWDG according to the specified parameters in the
|
||||
* IWDG_InitTypeDef and start watchdog. Before exiting function,
|
||||
* watchdog is refreshed in order to have correct time base.
|
||||
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check the IWDG handle allocation */
|
||||
if (hiwdg == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
|
||||
assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));
|
||||
assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
|
||||
|
||||
/* Enable IWDG. LSI is turned on automatically */
|
||||
__HAL_IWDG_START(hiwdg);
|
||||
|
||||
/* Enable write access to IWDG_PR and IWDG_RLR registers by writing
|
||||
0x5555 in KR */
|
||||
IWDG_ENABLE_WRITE_ACCESS(hiwdg);
|
||||
|
||||
/* Write to IWDG registers the Prescaler & Reload values to work with */
|
||||
hiwdg->Instance->PR = hiwdg->Init.Prescaler;
|
||||
hiwdg->Instance->RLR = hiwdg->Init.Reload;
|
||||
|
||||
/* Check pending flag, if previous update not done, return timeout */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for register to be updated */
|
||||
while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)
|
||||
{
|
||||
if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reload IWDG counter with value defined in the reload register */
|
||||
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions_Group2
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Refresh the IWDG.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Refresh the IWDG.
|
||||
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
|
||||
{
|
||||
/* Reload IWDG counter with value defined in the reload register */
|
||||
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
3148
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_mmc.c
Normal file
3148
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_mmc.c
Normal file
@@ -0,0 +1,3148 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_mmc.c
|
||||
* @author MCD Application Team
|
||||
* @brief MMC card HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Secure Digital (MMC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + MMC card Control 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver implements a high level communication layer for read and write from/to
|
||||
this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
|
||||
the user in HAL_MMC_MspInit() function (MSP layer).
|
||||
Basically, the MSP layer configuration should be the same as we provide in the
|
||||
examples.
|
||||
You can easily tailor this configuration according to hardware resources.
|
||||
|
||||
[..]
|
||||
This driver is a generic layered driver for SDMMC memories which uses the HAL
|
||||
SDMMC driver functions to interface with MMC and eMMC cards devices.
|
||||
It is used as follows:
|
||||
|
||||
(#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
|
||||
(##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
|
||||
(##) SDMMC pins configuration for MMC card
|
||||
(+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
|
||||
(+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
|
||||
and according to your pin assignment;
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA()
|
||||
and HAL_MMC_WriteBlocks_DMA() APIs).
|
||||
(+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
|
||||
(+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
|
||||
(##) NVIC configuration if you need to use interrupt process when using DMA transfer.
|
||||
(+++) Configure the SDMMC and DMA interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
DMA priority is superior to SDMMC's priority
|
||||
(+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
|
||||
and __HAL_MMC_DISABLE_IT() inside the communication process.
|
||||
(+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
|
||||
and __HAL_MMC_CLEAR_IT()
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
|
||||
and HAL_MMC_WriteBlocks_IT() APIs).
|
||||
(+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
(+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
|
||||
and __HAL_MMC_DISABLE_IT() inside the communication process.
|
||||
(+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
|
||||
and __HAL_MMC_CLEAR_IT()
|
||||
(#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
|
||||
|
||||
|
||||
*** MMC Card Initialization and configuration ***
|
||||
================================================
|
||||
[..]
|
||||
To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
|
||||
SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
|
||||
This function provide the following operations:
|
||||
|
||||
(#) Initialize the SDMMC peripheral interface with default configuration.
|
||||
The initialization process is done at 400KHz. You can change or adapt
|
||||
this frequency by adjusting the "ClockDiv" field.
|
||||
The MMC Card frequency (SDMMC_CK) is computed as follows:
|
||||
|
||||
SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
|
||||
|
||||
In initialization mode and according to the MMC Card standard,
|
||||
make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
|
||||
|
||||
This phase of initialization is done through SDMMC_Init() and
|
||||
SDMMC_PowerState_ON() SDMMC low level APIs.
|
||||
|
||||
(#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
|
||||
This phase allows the card initialization and identification
|
||||
and check the MMC Card type (Standard Capacity or High Capacity)
|
||||
The initialization flow is compatible with MMC standard.
|
||||
|
||||
This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
|
||||
of plug-off plug-in.
|
||||
|
||||
(#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
|
||||
frequency is set to 24MHz. You can change or adapt this frequency by adjusting
|
||||
the "ClockDiv" field.
|
||||
In transfer mode and according to the MMC Card standard, make sure that the
|
||||
SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
|
||||
To be able to use a frequency higher than 24MHz, you should use the SDMMC
|
||||
peripheral in bypass mode. Refer to the corresponding reference manual
|
||||
for more details.
|
||||
|
||||
(#) Select the corresponding MMC Card according to the address read with the step 2.
|
||||
|
||||
(#) Configure the MMC Card in wide bus mode: 4-bits data.
|
||||
|
||||
*** MMC Card Read operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
|
||||
(+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the DMA transfer process through the MMC Rx interrupt event.
|
||||
|
||||
(+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
|
||||
This function allows the read of 512 bytes blocks.
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the IT transfer process through the MMC Rx interrupt event.
|
||||
|
||||
*** MMC Card Write operation ***
|
||||
===============================
|
||||
[..]
|
||||
(+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
|
||||
(+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 byte).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the DMA transfer process through the MMC Tx interrupt event.
|
||||
|
||||
(+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
|
||||
This function allows the read of 512 bytes blocks.
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the IT transfer process through the MMC Tx interrupt event.
|
||||
|
||||
*** MMC card information ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
|
||||
It returns useful information about the MMC card such as block size, card type,
|
||||
block number ...
|
||||
|
||||
*** MMC card CSD register ***
|
||||
============================
|
||||
[..]
|
||||
(+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** MMC card CID register ***
|
||||
============================
|
||||
[..]
|
||||
(+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
|
||||
Some of the CID parameters are useful for card initialization and identification.
|
||||
|
||||
*** MMC HAL driver macros list ***
|
||||
==================================
|
||||
[..]
|
||||
Below the list of most used macros in MMC HAL driver.
|
||||
|
||||
(+) __HAL_MMC_ENABLE : Enable the MMC device
|
||||
(+) __HAL_MMC_DISABLE : Disable the MMC device
|
||||
(+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
|
||||
(+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
|
||||
(+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
|
||||
(+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
|
||||
(+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
|
||||
(+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
|
||||
|
||||
[..]
|
||||
(@) You can refer to the MMC HAL driver header file for more useful macros
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_MMC_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : MMC MspInit.
|
||||
(+) MspDeInitCallback : MMC MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : MMC MspInit.
|
||||
(+) MspDeInitCallback : MMC MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_MMC_Init
|
||||
and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_MMC_RegisterCallback before calling HAL_MMC_DeInit
|
||||
or HAL_MMC_Init function.
|
||||
|
||||
When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup MMC MMC
|
||||
* @brief MMC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_MMC_MODULE_ENABLED
|
||||
|
||||
#if defined(SDIO)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
#if defined (VDD_VALUE) && (VDD_VALUE <= 1950U)
|
||||
#define MMC_VOLTAGE_RANGE EMMC_LOW_VOLTAGE_RANGE
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_INDEX 201
|
||||
#define MMC_EXT_CSD_PWR_CL_52_INDEX 200
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_POS 8
|
||||
#define MMC_EXT_CSD_PWR_CL_52_POS 0
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 16
|
||||
#else
|
||||
#define MMC_VOLTAGE_RANGE EMMC_HIGH_VOLTAGE_RANGE
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_INDEX 203
|
||||
#define MMC_EXT_CSD_PWR_CL_52_INDEX 202
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_POS 24
|
||||
#define MMC_EXT_CSD_PWR_CL_52_POS 16
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 24
|
||||
#endif
|
||||
|
||||
/* Frequencies used in the driver for clock divider calculation */
|
||||
#define MMC_INIT_FREQ 400000U /* Initialization phase : 400 kHz max */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup MMC_Private_Functions MMC Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
|
||||
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
|
||||
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
|
||||
static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout);
|
||||
static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_Write_IT(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_Read_IT(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
|
||||
static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group1
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize the MMC
|
||||
card device to be ready for use.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC according to the specified parameters in the
|
||||
MMC_HandleTypeDef and create the associated handle.
|
||||
* @param hmmc: Pointer to the MMC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Check the MMC handle allocation */
|
||||
if(hmmc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
|
||||
assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge));
|
||||
assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass));
|
||||
assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
|
||||
assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide));
|
||||
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
|
||||
assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv));
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hmmc->Lock = HAL_UNLOCKED;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
/* Reset Callback pointers in HAL_MMC_STATE_RESET only */
|
||||
hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
|
||||
hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
|
||||
hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
|
||||
hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
|
||||
|
||||
if(hmmc->MspInitCallback == NULL)
|
||||
{
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hmmc->MspInitCallback(hmmc);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_MMC_MspInit(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize the Card parameters */
|
||||
if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the error code */
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
/* Initialize the MMC operation */
|
||||
hmmc->Context = MMC_CONTEXT_NONE;
|
||||
|
||||
/* Initialize the MMC state */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
/* Configure bus width */
|
||||
if (hmmc->Init.BusWide != SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC Card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @note This function initializes the MMC card. It could be used when a card
|
||||
re-initialization is needed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
MMC_InitTypeDef Init;
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Default SDIO peripheral configuration for MMC card initialization */
|
||||
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
Init.ClockDiv = SDIO_INIT_CLK_DIV;
|
||||
|
||||
/* Initialize SDIO peripheral interface with default configuration */
|
||||
status = SDIO_Init(hmmc->Instance, Init);
|
||||
if(status == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable SDIO Clock */
|
||||
__HAL_MMC_DISABLE(hmmc);
|
||||
|
||||
/* Set Power State to ON */
|
||||
status = SDIO_PowerState_ON(hmmc->Instance);
|
||||
if(status == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable MMC Clock */
|
||||
__HAL_MMC_ENABLE(hmmc);
|
||||
|
||||
/* Required power up waiting time before starting the MMC initialization sequence */
|
||||
HAL_Delay(2);
|
||||
|
||||
/* Identify card operating voltage */
|
||||
errorstate = MMC_PowerON(hmmc);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Card initialization */
|
||||
errorstate = MMC_InitCard(hmmc);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the MMC card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Check the MMC handle allocation */
|
||||
if(hmmc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Set MMC power state to off */
|
||||
MMC_PowerOFF(hmmc);
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
if(hmmc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hmmc->MspDeInitCallback(hmmc);
|
||||
#else
|
||||
/* De-Initialize the MSP layer */
|
||||
HAL_MMC_MspDeInit(hmmc);
|
||||
#endif
|
||||
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC MSP.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_MMC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize MMC MSP.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_MMC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group2
|
||||
* @brief Data transfer functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the data
|
||||
transfer from/to MMC card.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of MMC blocks to read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read block(s) in polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDIO flags */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock read */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Empty FIFO if there is still any data */
|
||||
while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allows to write block(s) to a specified address in a card. The Data
|
||||
* transfer is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of MMC blocks to write
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Write block(s) in polling mode */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tempbuff);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 8U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 16U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 24U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hmmc->Instance, &data);
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock write */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the IT transfer process through the MMC Rx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
hmmc->pRxBuffPtr = pData;
|
||||
hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read Blocks in IT mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the IT transfer process through the MMC Tx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
hmmc->pTxBuffPtr = pData;
|
||||
hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
/* Enable transfer interrupts */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE));
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the MMC Rx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hmmc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Force DMA Direction */
|
||||
hmmc->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
MODIFY_REG(hmmc->hdmarx->Instance->CCR, DMA_CCR_DIR, hmmc->hdmarx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
|
||||
{
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_DMA;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable MMC DMA transfer */
|
||||
__HAL_MMC_DMA_ENABLE(hmmc);
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read Blocks in DMA mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
hmmc->ErrorCode = errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the MMC Tx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
/* Enable MMC Error interrupts */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hmmc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable SDIO DMA transfer */
|
||||
__HAL_MMC_DMA_ENABLE(hmmc);
|
||||
|
||||
/* Force DMA Direction */
|
||||
hmmc->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
MODIFY_REG(hmmc->hdmatx->Instance->CCR, DMA_CCR_DIR, hmmc->hdmatx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
|
||||
{
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases the specified memory area of the given MMC card.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param BlockStartAdd: Start Block address
|
||||
* @param BlockEndAdd: End Block address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t start_add = BlockStartAdd;
|
||||
uint32_t end_add = BlockEndAdd;
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if(end_add < start_add)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(end_add > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Check if the card command class supports erase command */
|
||||
if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
start_add *= 512U;
|
||||
end_add *= 512U;
|
||||
}
|
||||
|
||||
/* Send CMD35 MMC_ERASE_GRP_START with argument as addr */
|
||||
errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD36 MMC_ERASE_GRP_END with argument as addr */
|
||||
errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD38 ERASE */
|
||||
errorstate = SDMMC_CmdErase(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles MMC card interrupt request.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t context = hmmc->Context;
|
||||
|
||||
/* Check for SDIO interrupt flags */
|
||||
if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
|
||||
{
|
||||
MMC_Read_IT(hmmc);
|
||||
}
|
||||
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) != RESET)
|
||||
{
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND);
|
||||
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hmmc->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
|
||||
|
||||
if((context & MMC_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the MMC DCTRL register */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->TxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_TxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if((context & MMC_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Stop Transfer for Write Multi blocks or Read Multi blocks */
|
||||
if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->RxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_RxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->TxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_TxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
|
||||
{
|
||||
MMC_Write_IT(hmmc);
|
||||
}
|
||||
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
/* Set Error code */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
|
||||
}
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
|
||||
|
||||
/* Disable all interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
|
||||
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if((context & MMC_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Set the MMC state to ready to be able to start again the process */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if((context & MMC_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Abort the MMC DMA Streams */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the DMA Tx abort callback */
|
||||
hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
MMC_DMATxAbort(hmmc->hdmatx);
|
||||
}
|
||||
}
|
||||
else if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the DMA Rx abort callback */
|
||||
hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
MMC_DMARxAbort(hmmc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return the MMC state
|
||||
* @param hmmc: Pointer to mmc handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
return hmmc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the MMC error code
|
||||
* @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval MMC Error Code
|
||||
*/
|
||||
uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_TxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_RxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MMC error callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_ErrorCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MMC Abort callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_AbortCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User MMC Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hmmc : MMC handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
|
||||
* @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hmmc);
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_TX_CPLT_CB_ID :
|
||||
hmmc->TxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_RX_CPLT_CB_ID :
|
||||
hmmc->RxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_ERROR_CB_ID :
|
||||
hmmc->ErrorCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_ABORT_CB_ID :
|
||||
hmmc->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hmmc);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User MMC Callback
|
||||
* MMC Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hmmc : MMC handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
|
||||
* @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hmmc);
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_TX_CPLT_CB_ID :
|
||||
hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
|
||||
break;
|
||||
case HAL_MMC_RX_CPLT_CB_ID :
|
||||
hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
|
||||
break;
|
||||
case HAL_MMC_ERROR_CB_ID :
|
||||
hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
|
||||
break;
|
||||
case HAL_MMC_ABORT_CB_ID :
|
||||
hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hmmc);
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group3
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the MMC card
|
||||
operations and get the related information
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CID register.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCID: Pointer to a HAL_MMC_CIDTypedef structure that
|
||||
* contains all CID register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
|
||||
{
|
||||
pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
|
||||
|
||||
pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
|
||||
|
||||
pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
|
||||
|
||||
pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
|
||||
|
||||
pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
|
||||
|
||||
pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
|
||||
|
||||
pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCID->Reserved2 = 1U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CSD register.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
|
||||
* contains all CSD register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
|
||||
{
|
||||
uint32_t block_nbr = 0;
|
||||
|
||||
pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
|
||||
|
||||
pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
|
||||
|
||||
pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
|
||||
|
||||
pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
|
||||
|
||||
pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
|
||||
|
||||
pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
|
||||
|
||||
pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
|
||||
|
||||
pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
|
||||
|
||||
pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->Reserved2 = 0U; /*!< Reserved */
|
||||
|
||||
pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
|
||||
|
||||
pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
|
||||
|
||||
pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
|
||||
|
||||
pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
|
||||
|
||||
if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
|
||||
{
|
||||
hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
|
||||
hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
|
||||
hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
|
||||
hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
|
||||
hmmc->MmcCard.LogBlockSize = 512U;
|
||||
}
|
||||
else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
hmmc->MmcCard.BlockNbr = block_nbr;
|
||||
hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
|
||||
hmmc->MmcCard.BlockSize = 512U;
|
||||
hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
|
||||
|
||||
pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
|
||||
|
||||
pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
|
||||
|
||||
pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
|
||||
|
||||
pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
|
||||
|
||||
pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
|
||||
|
||||
pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
|
||||
|
||||
pCSD->Reserved3 = 0;
|
||||
|
||||
pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
|
||||
|
||||
pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
|
||||
|
||||
pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
|
||||
|
||||
pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCSD->Reserved4 = 1;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the MMC card info.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
|
||||
* will contain the MMC card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
|
||||
{
|
||||
pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType);
|
||||
pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class);
|
||||
pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd);
|
||||
pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr);
|
||||
pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize);
|
||||
pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
|
||||
pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the Extended CSD register.
|
||||
* @param hmmc Pointer to MMC handle
|
||||
* @param pExtCSD Pointer to a memory area (512 bytes) that contains all
|
||||
* Extended CSD register parameters
|
||||
* @param Timeout Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t *tmp_buf;
|
||||
|
||||
if(NULL == pExtCSD)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0;
|
||||
|
||||
/* Initiaize the destination pointer */
|
||||
tmp_buf = pExtCSD;
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 512;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Send ExtCSD Read command to Card */
|
||||
errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDMMC flags */
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
/* Read data from SDMMC Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
*tmp_buf = SDIO_ReadFIFO(hmmc->Instance);
|
||||
tmp_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables wide bus operation for the requested card if supported by
|
||||
* card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param WideMode: Specifies the MMC card wide bus mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
|
||||
{
|
||||
uint32_t count;
|
||||
SDIO_InitTypeDef Init;
|
||||
uint32_t errorstate;
|
||||
uint32_t response = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_BUS_WIDE(WideMode));
|
||||
|
||||
/* Change State */
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
errorstate = MMC_PwrClassUpdate(hmmc, WideMode);
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
if(WideMode == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_4B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* WideMode is not a valid argument*/
|
||||
errorstate = HAL_MMC_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Check for switch error and violation of the trial number of sending CMD 13 */
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
count = SDMMC_MAX_TRIAL;
|
||||
do
|
||||
{
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
count--;
|
||||
}while(((response & 0x100U) == 0U) && (count != 0U));
|
||||
|
||||
/* Check the status after the switch command execution */
|
||||
if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
|
||||
{
|
||||
/* Check the bit SWITCH_ERROR of the device status */
|
||||
if ((response & 0x80U) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SDIO peripheral */
|
||||
Init = hmmc->Init;
|
||||
Init.BusWide = WideMode;
|
||||
(void)SDIO_Init(hmmc->Instance, Init);
|
||||
}
|
||||
}
|
||||
else if (count == 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Change State */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current mmc card data state.
|
||||
* @param hmmc: pointer to MMC handle
|
||||
* @retval Card state
|
||||
*/
|
||||
HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t cardstate;
|
||||
uint32_t errorstate;
|
||||
uint32_t resp1 = 0U;
|
||||
|
||||
errorstate = MMC_SendStatus(hmmc, &resp1);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
cardstate = ((resp1 >> 9U) & 0x0FU);
|
||||
|
||||
return (HAL_MMC_CardStateTypeDef)cardstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the MMC.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information for MMC module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
|
||||
{
|
||||
/* Disable the MMC DMA request */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the MMC DMA Tx Stream */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
/* Abort the MMC DMA Rx Stream */
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
/* Initialize the MMC operation */
|
||||
hmmc->Context = MMC_CONTEXT_NONE;
|
||||
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the MMC (IT mode).
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information for MMC module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
|
||||
{
|
||||
/* Disable the MMC DMA request */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the MMC DMA Tx Stream */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hmmc->hdmatx = NULL;
|
||||
}
|
||||
}
|
||||
/* Abort the MMC DMA Rx Stream */
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hmmc->hdmarx = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No transfer ongoing on both DMA channels*/
|
||||
if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA MMC transmit process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
|
||||
/* Enable DATAEND Interrupt */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC receive process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send stop command in multiblock write */
|
||||
if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the MMC DCTRL register */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->RxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_RxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC communication error callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
uint32_t RxErrorCode, TxErrorCode;
|
||||
|
||||
RxErrorCode = hmmc->hdmarx->ErrorCode;
|
||||
TxErrorCode = hmmc->hdmatx->ErrorCode;
|
||||
if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC Tx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
hmmc->hdmatx = NULL;
|
||||
}
|
||||
|
||||
/* All DMA channels are aborted */
|
||||
if(hmmc->hdmarx == NULL)
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC Rx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
hmmc->hdmarx = NULL;
|
||||
}
|
||||
|
||||
/* All DMA channels are aborted */
|
||||
if(hmmc->hdmatx == NULL)
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the mmc card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval MMC Card error state
|
||||
*/
|
||||
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardCSDTypeDef CSD;
|
||||
uint32_t errorstate;
|
||||
uint16_t mmc_rca = 2U;
|
||||
MMC_InitTypeDef Init;
|
||||
|
||||
/* Check the power State */
|
||||
if(SDIO_GetPowerState(hmmc->Instance) == 0U)
|
||||
{
|
||||
/* Power off */
|
||||
return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
|
||||
/* Send CMD2 ALL_SEND_CID */
|
||||
errorstate = SDMMC_CmdSendCID(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card identification number data */
|
||||
hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
|
||||
hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
|
||||
hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
|
||||
}
|
||||
|
||||
/* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
|
||||
/* MMC Card publishes its RCA. */
|
||||
errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get the MMC card RCA */
|
||||
hmmc->MmcCard.RelCardAdd = mmc_rca;
|
||||
|
||||
/* Send CMD9 SEND_CSD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card Specific Data */
|
||||
hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
|
||||
hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
|
||||
hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
|
||||
}
|
||||
|
||||
/* Get the Card Class */
|
||||
hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
|
||||
|
||||
/* Select the Card */
|
||||
errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get CSD parameters */
|
||||
if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Get Extended CSD parameters */
|
||||
if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Configure the SDIO peripheral */
|
||||
Init = hmmc->Init;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
(void)SDIO_Init(hmmc->Instance, Init);
|
||||
|
||||
/* All cards are initialized */
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enquires cards about their operating voltage and configures clock
|
||||
* controls and stores MMC information that will be needed in future
|
||||
* in the MMC handle.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t response = 0U, validvoltage = 0U;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
while(validvoltage == 0U)
|
||||
{
|
||||
if(count++ == SDMMC_MAX_VOLT_TRIAL)
|
||||
{
|
||||
return HAL_MMC_ERROR_INVALID_VOLTRANGE;
|
||||
}
|
||||
|
||||
/* SEND CMD1 APP_CMD with voltage range as argument */
|
||||
errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
|
||||
/* Get operating voltage*/
|
||||
validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
|
||||
}
|
||||
|
||||
/* When power routine is finished and command returns valid voltage */
|
||||
if (((response & (0xFF000000U)) >> 24U) == 0xC0U)
|
||||
{
|
||||
hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
|
||||
}
|
||||
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turns the SDIO output signals off.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Set Power State to OFF */
|
||||
(void)SDIO_PowerState_OFF(hmmc->Instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current card's status.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCardStatus: pointer to the buffer that will contain the MMC card
|
||||
* status (Card Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
|
||||
if(pCardStatus == NULL)
|
||||
{
|
||||
return HAL_MMC_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Send Status command */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get MMC card status */
|
||||
*pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads extended CSD register to get the sectors number of the device
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pFieldData: Pointer to the read buffer
|
||||
* @param FieldIndex: Index of the field to be read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t i = 0;
|
||||
uint32_t tmp_data;
|
||||
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0;
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 512;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDMMC flags */
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
/* Read data from SDMMC Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
tmp_data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
/* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */
|
||||
/* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
|
||||
if ((i + count) == ((uint32_t)FieldIndex/4U))
|
||||
{
|
||||
*pFieldData = tmp_data;
|
||||
}
|
||||
}
|
||||
i += 8U;
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wrap up reading in non-blocking mode.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hmmc->pRxBuffPtr;
|
||||
dataremaining = hmmc->RxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tmp = (uint8_t)(data & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
}
|
||||
|
||||
hmmc->pRxBuffPtr = tmp;
|
||||
hmmc->RxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up writing in non-blocking mode.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hmmc->pTxBuffPtr;
|
||||
dataremaining = hmmc->TxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tmp);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 8U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 16U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 24U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hmmc->Instance, &data);
|
||||
}
|
||||
|
||||
hmmc->pTxBuffPtr = tmp;
|
||||
hmmc->TxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the power class of the device.
|
||||
* @param hmmc MMC handle
|
||||
* @param Wide Wide of MMC bus
|
||||
* @param Speed Speed of the MMC bus
|
||||
* @retval MMC Card error state
|
||||
*/
|
||||
static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide)
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t response = 0U;
|
||||
uint32_t errorstate = HAL_MMC_ERROR_NONE;
|
||||
uint32_t power_class, supported_pwr_class;
|
||||
|
||||
if((Wide == SDIO_BUS_WIDE_8B) || (Wide == SDIO_BUS_WIDE_4B))
|
||||
{
|
||||
power_class = 0U; /* Default value after power-on or software reset */
|
||||
|
||||
/* Read the PowerClass field of the Extended CSD register */
|
||||
if(MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */
|
||||
{
|
||||
errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
power_class = ((power_class >> 24U) & 0x000000FFU);
|
||||
}
|
||||
|
||||
/* Get the supported PowerClass field of the Extended CSD register */
|
||||
/* Field PWR_CL_26_xxx [201 or 203] */
|
||||
supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX/4)] >> MMC_EXT_CSD_PWR_CL_26_POS) & 0x000000FFU);
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
if(Wide == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
/* Bit [7:4] : power class for 8-bits bus configuration - Bit [3:0] : power class for 4-bits bus configuration */
|
||||
supported_pwr_class = (supported_pwr_class >> 4U);
|
||||
}
|
||||
|
||||
if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU))
|
||||
{
|
||||
/* Need to change current power class */
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U)));
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
count = SDMMC_MAX_TRIAL;
|
||||
do
|
||||
{
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
count--;
|
||||
}while(((response & 0x100U) == 0U) && (count != 0U));
|
||||
|
||||
/* Check the status after the switch command execution */
|
||||
if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
|
||||
{
|
||||
/* Check the bit SWITCH_ERROR of the device status */
|
||||
if ((response & 0x80U) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
}
|
||||
else if (count == 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SDIO */
|
||||
|
||||
#endif /* HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_msp_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL BSP module.
|
||||
* This file template is located in the HAL folder and should be copied
|
||||
* to the user folder.
|
||||
******************************************************************************
|
||||
* @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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_MSP HAL_MSP
|
||||
* @brief HAL MSP module.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup HAL_MSP_Exported_Functions HAL MSP Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the Global MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the Global MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MspDeInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the PPP MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PPP_MspInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the PPP MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PPP_MspDeInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
2315
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_nand.c
Normal file
2315
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_nand.c
Normal file
@@ -0,0 +1,2315 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_nand.c
|
||||
* @author MCD Application Team
|
||||
* @brief NAND HAL module driver.
|
||||
* This file provides a generic firmware to drive NAND memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control NAND flash memories. It uses the FSMC layer functions to interface
|
||||
with NAND devices. This driver is used as follows:
|
||||
|
||||
(+) NAND flash memory configuration sequence using the function HAL_NAND_Init()
|
||||
with control and timing parameters for both common and attribute spaces.
|
||||
|
||||
(+) Read NAND flash memory maker and device IDs using the function
|
||||
HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) Access NAND flash memory by read/write operations using the functions
|
||||
HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(),
|
||||
HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(),
|
||||
HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(),
|
||||
HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b()
|
||||
to read/write page(s)/spare area(s). These functions use specific device
|
||||
information (Block, page size..) predefined by the user in the NAND_DeviceConfigTypeDef
|
||||
structure. The read/write address information is contained by the Nand_Address_Typedef
|
||||
structure passed as parameter.
|
||||
|
||||
(+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().
|
||||
|
||||
(+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().
|
||||
The erase block address information is contained in the Nand_Address_Typedef
|
||||
structure passed as parameter.
|
||||
|
||||
(+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().
|
||||
|
||||
(+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/
|
||||
HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction
|
||||
feature or the function HAL_NAND_GetECC() to get the ECC correction code.
|
||||
|
||||
(+) You can monitor the NAND device HAL state by calling the function
|
||||
HAL_NAND_GetState()
|
||||
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard NAND flash operations.
|
||||
If a NAND flash device contains different operations and/or implementations,
|
||||
it should be implemented separately.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_NAND_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_NAND_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : NAND MspInit.
|
||||
(+) MspDeInitCallback : NAND MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_NAND_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : NAND MspInit.
|
||||
(+) MspDeInitCallback : NAND MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_NAND_Init
|
||||
and HAL_NAND_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_NAND_Init and HAL_NAND_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_NAND_RegisterCallback before calling HAL_NAND_DeInit
|
||||
or HAL_NAND_Init function.
|
||||
|
||||
When The compilation define USE_HAL_NAND_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
|
||||
/** @defgroup NAND NAND
|
||||
* @brief NAND HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private Constants ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions NAND Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the NAND memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform NAND memory Initialization sequence
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param ComSpace_Timing pointer to Common space timing structure
|
||||
* @param AttSpace_Timing pointer to Attribute space timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FSMC_NAND_PCC_TimingTypeDef *ComSpace_Timing,
|
||||
FSMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)
|
||||
{
|
||||
/* Check the NAND handle state */
|
||||
if (hnand == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hnand->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
if (hnand->MspInitCallback == NULL)
|
||||
{
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
}
|
||||
hnand->ItCallback = HAL_NAND_ITCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hnand->MspInitCallback(hnand);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NAND_MspInit(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
/* Initialize NAND control Interface */
|
||||
(void)FSMC_NAND_Init(hnand->Instance, &(hnand->Init));
|
||||
|
||||
/* Initialize NAND common space timing Interface */
|
||||
(void)FSMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);
|
||||
|
||||
/* Initialize NAND attribute space timing Interface */
|
||||
(void)FSMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);
|
||||
|
||||
/* Enable the NAND device */
|
||||
__FSMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform NAND memory De-Initialization sequence
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
if (hnand->MspDeInitCallback == NULL)
|
||||
{
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hnand->MspDeInitCallback(hnand);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NAND_MspDeInit(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Configure the NAND registers with their reset values */
|
||||
(void)FSMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Reset the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND MSP Init
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND MSP DeInit
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function handles NAND device interrupt request.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check NAND interrupt Rising edge flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Rising edge pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt Level flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Level pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt Falling edge flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Falling edge pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt FIFO empty flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt FIFO empty pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND interrupt feature callback
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_ITCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the NAND
|
||||
memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read the NAND memory electronic signature
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pNAND_ID NAND ID structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
|
||||
{
|
||||
__IO uint32_t data = 0;
|
||||
__IO uint32_t data1 = 0;
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Read ID command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
|
||||
__DSB();
|
||||
|
||||
/* Read the electronic signature from NAND flash */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
data = *(__IO uint32_t *)deviceaddress;
|
||||
|
||||
/* Return the data read */
|
||||
pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
|
||||
pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data);
|
||||
pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data);
|
||||
pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *(__IO uint32_t *)deviceaddress;
|
||||
data1 = *((__IO uint32_t *)deviceaddress + 4);
|
||||
|
||||
/* Return the data read */
|
||||
pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
|
||||
pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data);
|
||||
pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1);
|
||||
pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory reset
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send NAND reset command */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the device: Enter the physical parameters of the device
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, const NAND_DeviceConfigTypeDef *pDeviceConfig)
|
||||
{
|
||||
hnand->Config.PageSize = pDeviceConfig->PageSize;
|
||||
hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize;
|
||||
hnand->Config.BlockSize = pDeviceConfig->BlockSize;
|
||||
hnand->Config.BlockNbr = pDeviceConfig->BlockNbr;
|
||||
hnand->Config.PlaneSize = pDeviceConfig->PlaneSize;
|
||||
hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr;
|
||||
hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Page(s) from NAND memory block (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to destination read buffer
|
||||
* @param NumPageToRead number of pages to read from block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint8_t *pBuffer, uint32_t NumPageToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpagesread = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToRead;
|
||||
uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) read loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send read page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*buff = *(uint8_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read pages number */
|
||||
numpagesread++;
|
||||
|
||||
/* Decrement pages to read */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Page(s) from NAND memory block (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned
|
||||
* @param NumPageToRead number of pages to read from block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint16_t *pBuffer, uint32_t NumPageToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpagesread = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToRead;
|
||||
uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) read loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send read page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Calculate PageSize */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
hnand->Config.PageSize = hnand->Config.PageSize / 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing */
|
||||
/* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*buff = *(uint16_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read pages number */
|
||||
numpagesread++;
|
||||
|
||||
/* Decrement pages to read */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Page(s) to NAND memory block (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumPageToWrite number of pages to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint8_t *pBuffer, uint32_t NumPageToWrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpageswritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToWrite;
|
||||
const uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) write loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send write page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*(__IO uint8_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written pages number */
|
||||
numpageswritten++;
|
||||
|
||||
/* Decrement pages to write */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Page(s) to NAND memory block (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned
|
||||
* @param NumPageToWrite number of pages to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint16_t *pBuffer, uint32_t NumPageToWrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpageswritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToWrite;
|
||||
const uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) write loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send write page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate PageSize */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
hnand->Config.PageSize = hnand->Config.PageSize / 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing */
|
||||
/* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*(__IO uint16_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written pages number */
|
||||
numpageswritten++;
|
||||
|
||||
/* Decrement pages to write */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Spare area(s) from NAND memory (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumSpareAreaToRead Number of spare area to read
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numsparearearead = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaToRead;
|
||||
uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = COLUMN_ADDRESS(hnand);
|
||||
|
||||
/* Spare area(s) read loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*buff = *(uint8_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read spare areas number */
|
||||
numsparearearead++;
|
||||
|
||||
/* Decrement spare areas to read */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Spare area(s) from NAND memory (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
|
||||
* @param NumSpareAreaToRead Number of spare area to read
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint16_t *pBuffer, uint32_t NumSpareAreaToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numsparearearead = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaToRead;
|
||||
uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
|
||||
|
||||
/* Spare area(s) read loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*buff = *(uint16_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read spare areas number */
|
||||
numsparearearead++;
|
||||
|
||||
/* Decrement spare areas to read */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Spare area(s) to NAND memory (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumSpareAreaTowrite number of spare areas to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numspareareawritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaTowrite;
|
||||
const uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Page address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = COLUMN_ADDRESS(hnand);
|
||||
|
||||
/* Spare area(s) write loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*(__IO uint8_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written spare areas number */
|
||||
numspareareawritten++;
|
||||
|
||||
/* Decrement spare areas to write */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Spare area(s) to NAND memory (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
|
||||
* @param NumSpareAreaTowrite number of spare areas to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint16_t *pBuffer, uint32_t NumSpareAreaTowrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numspareareawritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaTowrite;
|
||||
const uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
|
||||
|
||||
/* Spare area(s) write loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*(__IO uint16_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written spare areas number */
|
||||
numspareareawritten++;
|
||||
|
||||
/* Decrement spare areas to write */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory Block erase
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Erase block command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1;
|
||||
__DSB();
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment the NAND memory address
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @retval The new status of the increment address operation. It can be:
|
||||
* - NAND_VALID_ADDRESS: When the new address is valid address
|
||||
* - NAND_INVALID_ADDRESS: When the new address is invalid address
|
||||
*/
|
||||
uint32_t HAL_NAND_Address_Inc(const NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
|
||||
{
|
||||
uint32_t status = NAND_VALID_ADDRESS;
|
||||
|
||||
/* Increment page address */
|
||||
pAddress->Page++;
|
||||
|
||||
/* Check NAND address is valid */
|
||||
if (pAddress->Page == hnand->Config.BlockSize)
|
||||
{
|
||||
pAddress->Page = 0;
|
||||
pAddress->Block++;
|
||||
|
||||
if (pAddress->Block == hnand->Config.PlaneSize)
|
||||
{
|
||||
pAddress->Block = 0;
|
||||
pAddress->Plane++;
|
||||
|
||||
if (pAddress->Plane == (hnand->Config.PlaneNbr))
|
||||
{
|
||||
status = NAND_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User NAND Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hnand : NAND handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
|
||||
* @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
|
||||
* @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId,
|
||||
pNAND_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_IT_CB_ID :
|
||||
hnand->ItCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User NAND Callback
|
||||
* NAND Callback is redirected to the weak predefined callback
|
||||
* @param hnand : NAND handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
|
||||
* @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
|
||||
* @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
break;
|
||||
case HAL_NAND_IT_CB_ID :
|
||||
hnand->ItCallback = HAL_NAND_ITCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the NAND interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Enable ECC feature */
|
||||
(void)FSMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Disable ECC feature */
|
||||
(void)FSMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param ECCval pointer to ECC value
|
||||
* @param Timeout maximum timeout to wait
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Get NAND ECC value */
|
||||
status = FSMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the NAND controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the NAND state
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_NAND_StateTypeDef HAL_NAND_GetState(const NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
return hnand->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory read status
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval NAND status
|
||||
*/
|
||||
uint32_t HAL_NAND_Read_Status(const NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t deviceaddress;
|
||||
UNUSED(hnand);
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Read status operation command */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
|
||||
|
||||
/* Read status register data */
|
||||
data = *(__IO uint8_t *)deviceaddress;
|
||||
|
||||
/* Return the status */
|
||||
if ((data & NAND_ERROR) == NAND_ERROR)
|
||||
{
|
||||
return NAND_ERROR;
|
||||
}
|
||||
else if ((data & NAND_READY) == NAND_READY)
|
||||
{
|
||||
return NAND_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NAND_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK3 */
|
||||
1641
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_nor.c
Normal file
1641
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_nor.c
Normal file
@@ -0,0 +1,1641 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_nor.c
|
||||
* @author MCD Application Team
|
||||
* @brief NOR HAL module driver.
|
||||
* This file provides a generic firmware to drive NOR memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control NOR flash memories. It uses the FSMC layer functions to interface
|
||||
with NOR devices. This driver is used as follows:
|
||||
|
||||
(+) NOR flash memory configuration sequence using the function HAL_NOR_Init()
|
||||
with control and timing parameters for both normal and extended mode.
|
||||
|
||||
(+) Read NOR flash memory manufacturer code and device IDs using the function
|
||||
HAL_NOR_Read_ID(). The read information is stored in the NOR_ID_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) Access NOR flash memory by read/write data unit operations using the functions
|
||||
HAL_NOR_Read(), HAL_NOR_Program().
|
||||
|
||||
(+) Perform NOR flash erase block/chip operations using the functions
|
||||
HAL_NOR_Erase_Block() and HAL_NOR_Erase_Chip().
|
||||
|
||||
(+) Read the NOR flash CFI (common flash interface) IDs using the function
|
||||
HAL_NOR_Read_CFI(). The read information is stored in the NOR_CFI_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) You can also control the NOR device by calling the control APIs HAL_NOR_WriteOperation_Enable()/
|
||||
HAL_NOR_WriteOperation_Disable() to respectively enable/disable the NOR write operation
|
||||
|
||||
(+) You can monitor the NOR device HAL state by calling the function
|
||||
HAL_NOR_GetState()
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard NOR flash operations.
|
||||
If a NOR flash device contains different operations and/or implementations,
|
||||
it should be implemented separately.
|
||||
|
||||
*** NOR HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in NOR HAL driver.
|
||||
|
||||
(+) NOR_WRITE : NOR memory write data to specified address
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_NOR_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_NOR_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : NOR MspInit.
|
||||
(+) MspDeInitCallback : NOR MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_NOR_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : NOR MspInit.
|
||||
(+) MspDeInitCallback : NOR MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_NOR_Init and if the state is HAL_NOR_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_NOR_Init
|
||||
and HAL_NOR_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_NOR_Init and HAL_NOR_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_NOR_RegisterCallback before calling HAL_NOR_DeInit
|
||||
or HAL_NOR_Init function.
|
||||
|
||||
When The compilation define USE_HAL_NOR_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
|
||||
/** @defgroup NOR NOR
|
||||
* @brief NOR driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup NOR_Private_Defines NOR Private Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Constants to define address to set to write a command */
|
||||
#define NOR_CMD_ADDRESS_FIRST_BYTE (uint16_t)0x0AAA
|
||||
#define NOR_CMD_ADDRESS_FIRST_CFI_BYTE (uint16_t)0x00AA
|
||||
#define NOR_CMD_ADDRESS_SECOND_BYTE (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_THIRD_BYTE (uint16_t)0x0AAA
|
||||
|
||||
#define NOR_CMD_ADDRESS_FIRST (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FIRST_CFI (uint16_t)0x0055
|
||||
#define NOR_CMD_ADDRESS_SECOND (uint16_t)0x02AA
|
||||
#define NOR_CMD_ADDRESS_THIRD (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FOURTH (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FIFTH (uint16_t)0x02AA
|
||||
#define NOR_CMD_ADDRESS_SIXTH (uint16_t)0x0555
|
||||
|
||||
/* Constants to define data to program a command */
|
||||
#define NOR_CMD_DATA_READ_RESET (uint16_t)0x00F0
|
||||
#define NOR_CMD_DATA_FIRST (uint16_t)0x00AA
|
||||
#define NOR_CMD_DATA_SECOND (uint16_t)0x0055
|
||||
#define NOR_CMD_DATA_AUTO_SELECT (uint16_t)0x0090
|
||||
#define NOR_CMD_DATA_PROGRAM (uint16_t)0x00A0
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD (uint16_t)0x0080
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH (uint16_t)0x00AA
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH (uint16_t)0x0055
|
||||
#define NOR_CMD_DATA_CHIP_ERASE (uint16_t)0x0010
|
||||
#define NOR_CMD_DATA_CFI (uint16_t)0x0098
|
||||
|
||||
#define NOR_CMD_DATA_BUFFER_AND_PROG (uint8_t)0x25
|
||||
#define NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM (uint8_t)0x29
|
||||
#define NOR_CMD_DATA_BLOCK_ERASE (uint8_t)0x30
|
||||
|
||||
#define NOR_CMD_READ_ARRAY (uint16_t)0x00FF
|
||||
#define NOR_CMD_WORD_PROGRAM (uint16_t)0x0040
|
||||
#define NOR_CMD_BUFFERED_PROGRAM (uint16_t)0x00E8
|
||||
#define NOR_CMD_CONFIRM (uint16_t)0x00D0
|
||||
#define NOR_CMD_BLOCK_ERASE (uint16_t)0x0020
|
||||
#define NOR_CMD_BLOCK_UNLOCK (uint16_t)0x0060
|
||||
#define NOR_CMD_READ_STATUS_REG (uint16_t)0x0070
|
||||
#define NOR_CMD_CLEAR_STATUS_REG (uint16_t)0x0050
|
||||
|
||||
/* Mask on NOR STATUS REGISTER */
|
||||
#define NOR_MASK_STATUS_DQ4 (uint16_t)0x0010
|
||||
#define NOR_MASK_STATUS_DQ5 (uint16_t)0x0020
|
||||
#define NOR_MASK_STATUS_DQ6 (uint16_t)0x0040
|
||||
#define NOR_MASK_STATUS_DQ7 (uint16_t)0x0080
|
||||
|
||||
/* Address of the primary command set */
|
||||
#define NOR_ADDRESS_COMMAND_SET (uint16_t)0x0013
|
||||
|
||||
/* Command set code assignment (defined in JEDEC JEP137B version may 2004) */
|
||||
#define NOR_INTEL_SHARP_EXT_COMMAND_SET (uint16_t)0x0001 /* Supported in this driver */
|
||||
#define NOR_AMD_FUJITSU_COMMAND_SET (uint16_t)0x0002 /* Supported in this driver */
|
||||
#define NOR_INTEL_STANDARD_COMMAND_SET (uint16_t)0x0003 /* Not Supported in this driver */
|
||||
#define NOR_AMD_FUJITSU_EXT_COMMAND_SET (uint16_t)0x0004 /* Not Supported in this driver */
|
||||
#define NOR_WINDBOND_STANDARD_COMMAND_SET (uint16_t)0x0006 /* Not Supported in this driver */
|
||||
#define NOR_MITSUBISHI_STANDARD_COMMAND_SET (uint16_t)0x0100 /* Not Supported in this driver */
|
||||
#define NOR_MITSUBISHI_EXT_COMMAND_SET (uint16_t)0x0101 /* Not Supported in this driver */
|
||||
#define NOR_PAGE_WRITE_COMMAND_SET (uint16_t)0x0102 /* Not Supported in this driver */
|
||||
#define NOR_INTEL_PERFORMANCE_COMMAND_SET (uint16_t)0x0200 /* Not Supported in this driver */
|
||||
#define NOR_INTEL_DATA_COMMAND_SET (uint16_t)0x0210 /* Not Supported in this driver */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup NOR_Private_Variables NOR Private Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
static uint32_t uwNORMemoryDataWidth = NOR_MEMORY_8B;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup NOR_Exported_Functions NOR Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the NOR memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform the NOR memory Initialization sequence
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Timing pointer to NOR control timing structure
|
||||
* @param ExtTiming pointer to NOR extended mode timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Init(NOR_HandleTypeDef *hnor, FSMC_NORSRAM_TimingTypeDef *Timing,
|
||||
FSMC_NORSRAM_TimingTypeDef *ExtTiming)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR handle parameter */
|
||||
if (hnor == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnor->State == HAL_NOR_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hnor->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
if (hnor->MspInitCallback == NULL)
|
||||
{
|
||||
hnor->MspInitCallback = HAL_NOR_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hnor->MspInitCallback(hnor);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NOR_MspInit(hnor);
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
/* Initialize NOR control Interface */
|
||||
(void)FSMC_NORSRAM_Init(hnor->Instance, &(hnor->Init));
|
||||
|
||||
/* Initialize NOR timing Interface */
|
||||
(void)FSMC_NORSRAM_Timing_Init(hnor->Instance, Timing, hnor->Init.NSBank);
|
||||
|
||||
/* Initialize NOR extended mode timing Interface */
|
||||
(void)FSMC_NORSRAM_Extended_Timing_Init(hnor->Extended, ExtTiming,
|
||||
hnor->Init.NSBank, hnor->Init.ExtendedMode);
|
||||
|
||||
/* Enable the NORSRAM device */
|
||||
__FSMC_NORSRAM_ENABLE(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Initialize NOR Memory Data Width*/
|
||||
if (hnor->Init.MemoryDataWidth == FSMC_NORSRAM_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
uwNORMemoryDataWidth = NOR_MEMORY_8B;
|
||||
}
|
||||
else
|
||||
{
|
||||
uwNORMemoryDataWidth = NOR_MEMORY_16B;
|
||||
}
|
||||
|
||||
/* Initialize the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
if (hnor->Init.WriteOperation == FSMC_WRITE_OPERATION_DISABLE)
|
||||
{
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_PROTECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the value of the command set */
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
|
||||
NOR_CMD_DATA_CFI);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
|
||||
}
|
||||
|
||||
hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
|
||||
|
||||
status = HAL_NOR_ReturnToReadMode(hnor);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform NOR memory De-Initialization sequence
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_DeInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
if (hnor->MspDeInitCallback == NULL)
|
||||
{
|
||||
hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hnor->MspDeInitCallback(hnor);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_NOR_MspDeInit(hnor);
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Configure the NOR registers with their reset values */
|
||||
(void)FSMC_NORSRAM_DeInit(hnor->Instance, hnor->Extended, hnor->Init.NSBank);
|
||||
|
||||
/* Reset the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hnor);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP Init
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP DeInit
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspDeInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP Wait for Ready/Busy signal
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Timeout Maximum timeout value
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspWait(NOR_HandleTypeDef *hnor, uint32_t Timeout)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
UNUSED(Timeout);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspWait could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the NOR memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read NOR flash IDs
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pNOR_ID pointer to NOR ID structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read_ID(NOR_HandleTypeDef *hnor, NOR_IDTypeDef *pNOR_ID)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read ID command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read the NOR IDs */
|
||||
pNOR_ID->Manufacturer_Code = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, MC_ADDRESS);
|
||||
pNOR_ID->Device_Code1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE1_ADDR);
|
||||
pNOR_ID->Device_Code2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE2_ADDR);
|
||||
pNOR_ID->Device_Code3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE3_ADDR);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the NOR memory to Read mode.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ReturnToReadMode(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pAddress pointer to Device address
|
||||
* @param pData pointer to read data
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(pAddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read the data */
|
||||
*pData = (uint16_t)(*(__IO uint32_t *)pAddress);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program data to NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pAddress Device address
|
||||
* @param pData pointer to the data to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send program data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_PROGRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_PROGRAM);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(pAddress, NOR_CMD_WORD_PROGRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Write the data */
|
||||
NOR_WRITE(pAddress, *pData);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a half-word buffer from the NOR memory.
|
||||
* @param hnor pointer to the NOR handle
|
||||
* @param uwAddress NOR memory internal address to read from.
|
||||
* @param pData pointer to the buffer that receives the data read from the
|
||||
* NOR memory.
|
||||
* @param uwBufferSize number of Half word to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ReadBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
|
||||
uint32_t uwBufferSize)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
uint32_t size = uwBufferSize;
|
||||
uint32_t address = uwAddress;
|
||||
uint16_t *data = pData;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read buffer */
|
||||
while (size > 0U)
|
||||
{
|
||||
*data = *(__IO uint16_t *)address;
|
||||
data++;
|
||||
address += 2U;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a half-word buffer to the NOR memory. This function must be used
|
||||
only with S29GL128P NOR memory.
|
||||
* @param hnor pointer to the NOR handle
|
||||
* @param uwAddress NOR memory internal start write address
|
||||
* @param pData pointer to source data buffer.
|
||||
* @param uwBufferSize Size of the buffer to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ProgramBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
|
||||
uint32_t uwBufferSize)
|
||||
{
|
||||
uint16_t *p_currentaddress;
|
||||
const uint16_t *p_endaddress;
|
||||
uint16_t *data = pData;
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Initialize variables */
|
||||
p_currentaddress = (uint16_t *)(deviceaddress + uwAddress);
|
||||
p_endaddress = (uint16_t *)(deviceaddress + uwAddress + (2U * (uwBufferSize - 1U)));
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
/* Issue unlock command sequence */
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Issue unlock command sequence */
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
}
|
||||
/* Write Buffer Load Command */
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG);
|
||||
NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
/* Write Buffer Load Command */
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_BUFFERED_PROGRAM);
|
||||
NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Load Data into NOR Buffer */
|
||||
while (p_currentaddress <= p_endaddress)
|
||||
{
|
||||
NOR_WRITE(p_currentaddress, *data);
|
||||
|
||||
data++;
|
||||
p_currentaddress ++;
|
||||
}
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM);
|
||||
}
|
||||
else /* => hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET */
|
||||
{
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the specified block of the NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param BlockAddress Block to erase address
|
||||
* @param Address Device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Erase_Block(NOR_HandleTypeDef *hnor, uint32_t BlockAddress, uint32_t Address)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send block erase command sequence */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
|
||||
}
|
||||
NOR_WRITE((uint32_t)(BlockAddress + Address), NOR_CMD_DATA_BLOCK_ERASE);
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_UNLOCK);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_ERASE);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR memory status and update the controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the entire NOR chip.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Address Device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Erase_Chip(NOR_HandleTypeDef *hnor, uint32_t Address)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
UNUSED(Address);
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send NOR chip erase command sequence */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SIXTH),
|
||||
NOR_CMD_DATA_CHIP_ERASE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR memory status and update the controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read NOR flash CFI IDs
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pNOR_CFI pointer to NOR CFI IDs structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read_CFI(NOR_HandleTypeDef *hnor, NOR_CFITypeDef *pNOR_CFI)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read CFI query command */
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
|
||||
NOR_CMD_DATA_CFI);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
|
||||
}
|
||||
/* read the NOR CFI information */
|
||||
pNOR_CFI->CFI_1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI1_ADDRESS);
|
||||
pNOR_CFI->CFI_2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI2_ADDRESS);
|
||||
pNOR_CFI->CFI_3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI3_ADDRESS);
|
||||
pNOR_CFI->CFI_4 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI4_ADDRESS);
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User NOR Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hnor : NOR handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
|
||||
* @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_RegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId,
|
||||
pNOR_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
state = hnor->State;
|
||||
if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NOR_MSP_INIT_CB_ID :
|
||||
hnor->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NOR_MSP_DEINIT_CB_ID :
|
||||
hnor->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User NOR Callback
|
||||
* NOR Callback is redirected to the weak predefined callback
|
||||
* @param hnor : NOR handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
|
||||
* @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_UnRegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
state = hnor->State;
|
||||
if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NOR_MSP_INIT_CB_ID :
|
||||
hnor->MspInitCallback = HAL_NOR_MspInit;
|
||||
break;
|
||||
case HAL_NOR_MSP_DEINIT_CB_ID :
|
||||
hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group3 NOR Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the NOR interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically NOR write operation.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_WriteOperation_Enable(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Enable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Enable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically NOR write operation.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_WriteOperation_Disable(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Disable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_PROTECTED;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group4 NOR State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the NOR controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the NOR controller state
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval NOR controller state
|
||||
*/
|
||||
HAL_NOR_StateTypeDef HAL_NOR_GetState(const NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
return hnor->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the NOR operation status.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Address Device address
|
||||
* @param Timeout NOR programming Timeout
|
||||
* @retval NOR_Status The returned value can be: HAL_NOR_STATUS_SUCCESS, HAL_NOR_STATUS_ERROR
|
||||
* or HAL_NOR_STATUS_TIMEOUT
|
||||
*/
|
||||
HAL_NOR_StatusTypeDef HAL_NOR_GetStatus(NOR_HandleTypeDef *hnor, uint32_t Address, uint32_t Timeout)
|
||||
{
|
||||
HAL_NOR_StatusTypeDef status = HAL_NOR_STATUS_ONGOING;
|
||||
uint16_t tmpsr1;
|
||||
uint16_t tmpsr2;
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Poll on NOR memory Ready/Busy signal ------------------------------------*/
|
||||
HAL_NOR_MspWait(hnor, Timeout);
|
||||
|
||||
/* Get the NOR memory operation status -------------------------------------*/
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
while ((status != HAL_NOR_STATUS_SUCCESS) && (status != HAL_NOR_STATUS_TIMEOUT))
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
status = HAL_NOR_STATUS_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read NOR status register (DQ6 and DQ5) */
|
||||
tmpsr1 = *(__IO uint16_t *)Address;
|
||||
tmpsr2 = *(__IO uint16_t *)Address;
|
||||
|
||||
/* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
|
||||
{
|
||||
return HAL_NOR_STATUS_SUCCESS ;
|
||||
}
|
||||
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
|
||||
{
|
||||
status = HAL_NOR_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
tmpsr1 = *(__IO uint16_t *)Address;
|
||||
tmpsr2 = *(__IO uint16_t *)Address;
|
||||
|
||||
/* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
|
||||
{
|
||||
return HAL_NOR_STATUS_SUCCESS;
|
||||
}
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
|
||||
{
|
||||
return HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
do
|
||||
{
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
tmpsr2 = *(__IO uint16_t *)(Address);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
return HAL_NOR_STATUS_TIMEOUT;
|
||||
}
|
||||
}
|
||||
} while ((tmpsr2 & NOR_MASK_STATUS_DQ7) == 0U);
|
||||
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
tmpsr1 = *(__IO uint16_t *)(Address);
|
||||
if ((tmpsr1 & (NOR_MASK_STATUS_DQ5 | NOR_MASK_STATUS_DQ4)) != 0U)
|
||||
{
|
||||
/* Clear the Status Register */
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
status = HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_NOR_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Return the operation status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK1 */
|
||||
@@ -0,0 +1,952 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pccard.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCCARD HAL module driver.
|
||||
* This file provides a generic firmware to drive PCCARD memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control PCCARD/compact flash memories. It uses the FSMC layer functions
|
||||
to interface with PCCARD devices. This driver is used for:
|
||||
|
||||
(+) PCCARD/Compact Flash memory configuration sequence using the function
|
||||
HAL_PCCARD_Init()/HAL_CF_Init() with control and timing parameters for
|
||||
both common and attribute spaces.
|
||||
|
||||
(+) Read PCCARD/Compact Flash memory maker and device IDs using the function
|
||||
HAL_PCCARD_Read_ID()/HAL_CF_Read_ID(). The read information is stored in
|
||||
the CompactFlash_ID structure declared by the function caller.
|
||||
|
||||
(+) Access PCCARD/Compact Flash memory by read/write operations using the functions
|
||||
HAL_PCCARD_Read_Sector()/ HAL_PCCARD_Write_Sector() -
|
||||
HAL_CF_Read_Sector()/HAL_CF_Write_Sector(), to read/write sector.
|
||||
|
||||
(+) Perform PCCARD/Compact Flash Reset chip operation using the function
|
||||
HAL_PCCARD_Reset()/HAL_CF_Reset.
|
||||
|
||||
(+) Perform PCCARD/Compact Flash erase sector operation using the function
|
||||
HAL_PCCARD_Erase_Sector()/HAL_CF_Erase_Sector.
|
||||
|
||||
(+) Read the PCCARD/Compact Flash status operation using the function
|
||||
HAL_PCCARD_ReadStatus()/HAL_CF_ReadStatus().
|
||||
|
||||
(+) You can monitor the PCCARD/Compact Flash device HAL state by calling
|
||||
the function HAL_PCCARD_GetState()/HAL_CF_GetState()
|
||||
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard PCCARD/compact flash
|
||||
operations. If a PCCARD/Compact Flash device contains different operations
|
||||
and/or implementations, it should be implemented separately.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_PCCARD_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : PCCARD MspInit.
|
||||
(+) MspDeInitCallback : PCCARD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_PCCARD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : PCCARD MspInit.
|
||||
(+) MspDeInitCallback : PCCARD MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_PCCARD_Init and if the state is HAL_PCCARD_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_PCCARD_Init
|
||||
and HAL_PCCARD_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_PCCARD_Init and HAL_PCCARD_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_PCCARD_RegisterCallback before calling HAL_PCCARD_DeInit
|
||||
or HAL_PCCARD_Init function.
|
||||
|
||||
When The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK4)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCCARD_MODULE_ENABLED
|
||||
|
||||
/** @defgroup PCCARD PCCARD
|
||||
* @brief PCCARD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup PCCARD_Private_Defines PCCARD Private Defines
|
||||
* @{
|
||||
*/
|
||||
#define PCCARD_TIMEOUT_READ_ID 0x0000FFFFU
|
||||
#define PCCARD_TIMEOUT_READ_WRITE_SECTOR 0x0000FFFFU
|
||||
#define PCCARD_TIMEOUT_ERASE_SECTOR 0x00000400U
|
||||
#define PCCARD_TIMEOUT_STATUS 0x01000000U
|
||||
|
||||
#define PCCARD_STATUS_OK (uint8_t)0x58
|
||||
#define PCCARD_STATUS_WRITE_OK (uint8_t)0x50
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup PCCARD_Exported_Functions PCCARD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the PCCARD memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform the PCCARD memory Initialization sequence
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param ComSpaceTiming Common space timing structure
|
||||
* @param AttSpaceTiming Attribute space timing structure
|
||||
* @param IOSpaceTiming IO space timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FSMC_NAND_PCC_TimingTypeDef *ComSpaceTiming,
|
||||
FSMC_NAND_PCC_TimingTypeDef *AttSpaceTiming,
|
||||
FSMC_NAND_PCC_TimingTypeDef *IOSpaceTiming)
|
||||
{
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hpccard->Lock = HAL_UNLOCKED;
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
if (hpccard->MspInitCallback == NULL)
|
||||
{
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
}
|
||||
hpccard->ItCallback = HAL_PCCARD_ITCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hpccard->MspInitCallback(hpccard);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_PCCARD_MspInit(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize the PCCARD state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD control Interface */
|
||||
FSMC_PCCARD_Init(hpccard->Instance, &(hpccard->Init));
|
||||
|
||||
/* Init PCCARD common space timing Interface */
|
||||
FSMC_PCCARD_CommonSpace_Timing_Init(hpccard->Instance, ComSpaceTiming);
|
||||
|
||||
/* Init PCCARD attribute space timing Interface */
|
||||
FSMC_PCCARD_AttributeSpace_Timing_Init(hpccard->Instance, AttSpaceTiming);
|
||||
|
||||
/* Init PCCARD IO space timing Interface */
|
||||
FSMC_PCCARD_IOSpace_Timing_Init(hpccard->Instance, IOSpaceTiming);
|
||||
|
||||
/* Enable the PCCARD device */
|
||||
__FSMC_PCCARD_ENABLE(hpccard->Instance);
|
||||
|
||||
/* Update the PCCARD state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the PCCARD memory De-initialization sequence
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
if (hpccard->MspDeInitCallback == NULL)
|
||||
{
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hpccard->MspDeInitCallback(hpccard);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_PCCARD_MspDeInit(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Configure the PCCARD registers with their reset values */
|
||||
FSMC_PCCARD_DeInit(hpccard->Instance);
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD MSP Init
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD MSP DeInit
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the PCCARD memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read Compact Flash's ID.
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param CompactFlash_ID Compact flash ID structure.
|
||||
* @param pStatus pointer to compact flash status
|
||||
* @retval HAL status
|
||||
*
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize the PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Send the Identify Command */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xECEC;
|
||||
|
||||
/* Read PCCARD IDs and timeout treatment */
|
||||
do
|
||||
{
|
||||
/* Read the PCCARD status */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read PCCARD ID bytes */
|
||||
for (index = 0U; index < 16U; index++)
|
||||
{
|
||||
CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read sector from PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param pBuffer pointer to destination read buffer
|
||||
* @param SectorAddress Sector address to read
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
|
||||
uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xE4A0;
|
||||
|
||||
do
|
||||
{
|
||||
/* wait till the Status = 0x80 */
|
||||
status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status == 0x80U) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
|
||||
|
||||
do
|
||||
{
|
||||
/* wait till the Status = PCCARD_STATUS_OK */
|
||||
status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Read bytes */
|
||||
for (; index < PCCARD_SECTOR_SIZE; index++)
|
||||
{
|
||||
*(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR);
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write sector to PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param pBuffer pointer to source write buffer
|
||||
* @param SectorAddress Sector address to write
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
|
||||
uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0x30A0;
|
||||
|
||||
do
|
||||
{
|
||||
/* Wait till the Status = PCCARD_STATUS_OK */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Write bytes */
|
||||
for (; index < PCCARD_SECTOR_SIZE; index++)
|
||||
{
|
||||
*(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Wait till the Status = PCCARD_STATUS_WRITE_OK */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_WRITE_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erase sector from PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param SectorAddress Sector address to erase
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW) = 0x00;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = 0x01;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD) = 0xA0;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = ATA_ERASE_SECTOR_CMD;
|
||||
|
||||
/* wait till the PCCARD is ready */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
while ((status != PCCARD_STATUS_WRITE_OK) && timeout)
|
||||
{
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Provide a SW reset and Read and verify the:
|
||||
- PCCard Configuration Option Register at address 0x98000200 --> 0x80
|
||||
- Card Configuration and Status Register at address 0x98000202 --> 0x00
|
||||
- Pin Replacement Register at address 0x98000204 --> 0x0C
|
||||
- Socket and Copy Register at address 0x98000206 --> 0x00
|
||||
*/
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
*(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles PCCARD device interrupt request.
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Check PCCARD interrupt Rising edge flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Rising edge pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt Level flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Level pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt Falling edge flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Falling edge pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt FIFO empty flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt FIFO empty pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD interrupt feature callback
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_ITCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User PCCARD Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hpccard : PCCARD handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID
|
||||
* @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID
|
||||
* @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId,
|
||||
pPCCARD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_IT_CB_ID :
|
||||
hpccard->ItCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User PCCARD Callback
|
||||
* PCCARD Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hpccard : PCCARD handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID
|
||||
* @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID
|
||||
* @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
break;
|
||||
case HAL_PCCARD_IT_CB_ID :
|
||||
hpccard->ItCallback = HAL_PCCARD_ITCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group3 State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the PCCARD controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the PCCARD controller state
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
return hpccard->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the compact flash memory status
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval New status of the PCCARD operation. This parameter can be:
|
||||
* - CompactFlash_TIMEOUT_ERROR: when the previous operation generate
|
||||
* a Timeout error
|
||||
* - CompactFlash_READY: when memory is ready for the next operation
|
||||
*/
|
||||
HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
uint32_t timeout = PCCARD_TIMEOUT_STATUS;
|
||||
uint32_t status_pccard = 0U;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_PCCARD_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
while ((status_pccard == PCCARD_BUSY) && timeout)
|
||||
{
|
||||
status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
status_pccard = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Return the operation status */
|
||||
return (HAL_PCCARD_StatusTypeDef) status_pccard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads the Compact Flash memory status using the Read status command
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval The status of the Compact Flash memory. This parameter can be:
|
||||
* - CompactFlash_BUSY: when memory is busy
|
||||
* - CompactFlash_READY: when memory is ready for the next operation
|
||||
* - CompactFlash_ERROR: when the previous operation generates error
|
||||
*/
|
||||
HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
uint8_t data = 0U;
|
||||
uint8_t status_pccard = PCCARD_BUSY;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_PCCARD_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
/* Read status operation */
|
||||
data = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR)
|
||||
{
|
||||
status_pccard = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
else if ((data & PCCARD_READY) == PCCARD_READY)
|
||||
{
|
||||
status_pccard = PCCARD_READY;
|
||||
}
|
||||
|
||||
return (HAL_PCCARD_StatusTypeDef) status_pccard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_PCCARD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK4 */
|
||||
2720
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.c
Normal file
2720
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.c
Normal file
@@ -0,0 +1,2720 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pcd.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + 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 PCD HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a PCD_HandleTypeDef handle structure, for example:
|
||||
PCD_HandleTypeDef hpcd;
|
||||
|
||||
(#) Fill parameters of Init structure in HCD handle
|
||||
|
||||
(#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
|
||||
|
||||
(#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
|
||||
(##) Enable the PCD/USB Low Level interface clock using
|
||||
(+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device FS peripheral
|
||||
(+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure PCD pin-out
|
||||
(##) Configure PCD NVIC interrupt
|
||||
|
||||
(#)Associate the Upper USB device stack to the HAL PCD Driver:
|
||||
(##) hpcd.pData = pdev;
|
||||
|
||||
(#)Enable PCD transmission and reception:
|
||||
(##) HAL_PCD_Start();
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCD PCD
|
||||
* @brief PCD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
|
||||
#if defined (USB) || defined (USB_OTG_FS)
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup PCD_Private_Macros PCD Private Macros
|
||||
* @{
|
||||
*/
|
||||
#define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions prototypes ----------------------------------------------*/
|
||||
/** @defgroup PCD_Private_Functions PCD Private Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
|
||||
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
#endif /* defined (USB) */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup PCD_Exported_Functions PCD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_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:
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the PCD according to the specified
|
||||
* parameters in the PCD_InitTypeDef and initialize the associated handle.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* Check the PCD handle allocation */
|
||||
if (hpcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hpcd->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback = HAL_PCD_SOFCallback;
|
||||
hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
|
||||
hpcd->ResetCallback = HAL_PCD_ResetCallback;
|
||||
hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
|
||||
hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
|
||||
hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
|
||||
hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
|
||||
hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
|
||||
hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
|
||||
hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
|
||||
hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
|
||||
|
||||
if (hpcd->MspInitCallback == NULL)
|
||||
{
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hpcd->MspInitCallback(hpcd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_PCD_MspInit(hpcd);
|
||||
#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_BUSY;
|
||||
|
||||
/* Disable DMA mode for FS instance */
|
||||
hpcd->Init.dma_enable = 0U;
|
||||
|
||||
/* Disable the Interrupts */
|
||||
__HAL_PCD_DISABLE(hpcd);
|
||||
|
||||
/*Init the Core (common init.) */
|
||||
if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Force Device Mode */
|
||||
if (USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Init endpoints structures */
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
/* Init ep structure */
|
||||
hpcd->IN_ep[i].is_in = 1U;
|
||||
hpcd->IN_ep[i].num = i;
|
||||
#if defined (USB_OTG_FS)
|
||||
hpcd->IN_ep[i].tx_fifo_num = i;
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
/* Control until ep is activated */
|
||||
hpcd->IN_ep[i].type = EP_TYPE_CTRL;
|
||||
hpcd->IN_ep[i].maxpacket = 0U;
|
||||
hpcd->IN_ep[i].xfer_buff = 0U;
|
||||
hpcd->IN_ep[i].xfer_len = 0U;
|
||||
}
|
||||
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
hpcd->OUT_ep[i].is_in = 0U;
|
||||
hpcd->OUT_ep[i].num = i;
|
||||
/* Control until ep is activated */
|
||||
hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
|
||||
hpcd->OUT_ep[i].maxpacket = 0U;
|
||||
hpcd->OUT_ep[i].xfer_buff = 0U;
|
||||
hpcd->OUT_ep[i].xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Init Device */
|
||||
if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hpcd->USB_Address = 0U;
|
||||
hpcd->State = HAL_PCD_STATE_READY;
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the PCD peripheral.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Check the PCD handle allocation */
|
||||
if (hpcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_BUSY;
|
||||
|
||||
/* Stop Device */
|
||||
if (USB_StopDevice(hpcd->Instance) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
if (hpcd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hpcd->MspDeInitCallback(hpcd);
|
||||
#else
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
HAL_PCD_MspDeInit(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the PCD MSP.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes PCD MSP.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User USB PCD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hpcd USB PCD handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
|
||||
* @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
|
||||
* @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
|
||||
* @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
|
||||
* @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
|
||||
* @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
|
||||
* @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
|
||||
* @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
|
||||
HAL_PCD_CallbackIDTypeDef CallbackID,
|
||||
pPCD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_SOF_CB_ID :
|
||||
hpcd->SOFCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SETUPSTAGE_CB_ID :
|
||||
hpcd->SetupStageCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESET_CB_ID :
|
||||
hpcd->ResetCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SUSPEND_CB_ID :
|
||||
hpcd->SuspendCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESUME_CB_ID :
|
||||
hpcd->ResumeCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_CONNECT_CB_ID :
|
||||
hpcd->ConnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_DISCONNECT_CB_ID :
|
||||
hpcd->DisconnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USB PCD Callback
|
||||
* USB PCD callback is redirected to the weak predefined callback
|
||||
* @param hpcd USB PCD handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
|
||||
* @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
|
||||
* @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
|
||||
* @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
|
||||
* @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
|
||||
* @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
|
||||
* @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
|
||||
* @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
/* Setup Legacy weak Callbacks */
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_SOF_CB_ID :
|
||||
hpcd->SOFCallback = HAL_PCD_SOFCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SETUPSTAGE_CB_ID :
|
||||
hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESET_CB_ID :
|
||||
hpcd->ResetCallback = HAL_PCD_ResetCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SUSPEND_CB_ID :
|
||||
hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESUME_CB_ID :
|
||||
hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_CONNECT_CB_ID :
|
||||
hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_DISCONNECT_CB_ID :
|
||||
hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Data OUT Stage Callback
|
||||
* To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Data OUT Stage Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_DataOutStageCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataOutStageCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Data OUT Stage Callback
|
||||
* USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Data IN Stage Callback
|
||||
* To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Data IN Stage Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_DataInStageCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataInStageCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Data IN Stage Callback
|
||||
* USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Iso OUT incomplete Callback
|
||||
* To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_IsoOutIncpltCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOOUTIncompleteCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Iso OUT incomplete Callback
|
||||
* USB PCD Iso OUT incomplete Callback is redirected
|
||||
* to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Iso IN incomplete Callback
|
||||
* To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_IsoInIncpltCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOINIncompleteCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Iso IN incomplete Callback
|
||||
* USB PCD Iso IN incomplete Callback is redirected
|
||||
* to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the PCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the USB device
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
__HAL_PCD_ENABLE(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 1U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevConnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the USB device.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
__HAL_PCD_DISABLE(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 0U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Handles PCD interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
USB_OTG_EPTypeDef *ep;
|
||||
uint32_t i;
|
||||
uint32_t ep_intr;
|
||||
uint32_t epint;
|
||||
uint32_t epnum;
|
||||
uint32_t fifoemptymsk;
|
||||
uint32_t RegVal;
|
||||
|
||||
/* ensure that we are in device mode */
|
||||
if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
|
||||
{
|
||||
/* avoid spurious interrupt */
|
||||
if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* store current frame number */
|
||||
hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
|
||||
{
|
||||
/* incorrect mode, acknowledge the interrupt */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
|
||||
}
|
||||
|
||||
/* Handle RxQLevel Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
|
||||
{
|
||||
USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
|
||||
RegVal = USBx->GRXSTSP;
|
||||
|
||||
ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];
|
||||
|
||||
if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
|
||||
{
|
||||
if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
|
||||
{
|
||||
(void)USB_ReadPacket(USBx, ep->xfer_buff,
|
||||
(uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
|
||||
|
||||
ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
}
|
||||
}
|
||||
else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
|
||||
{
|
||||
(void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
|
||||
ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
}
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
|
||||
{
|
||||
epnum = 0U;
|
||||
|
||||
/* Read in the device interrupt bits */
|
||||
ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
|
||||
|
||||
while (ep_intr != 0U)
|
||||
{
|
||||
if ((ep_intr & 0x1U) != 0U)
|
||||
{
|
||||
epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
|
||||
(void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
|
||||
}
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
|
||||
/* Class B setup phase done for previous decoded setup */
|
||||
(void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
|
||||
}
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
|
||||
}
|
||||
|
||||
/* Clear OUT Endpoint disable interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
|
||||
{
|
||||
if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
|
||||
{
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
|
||||
}
|
||||
|
||||
ep = &hpcd->OUT_ep[epnum];
|
||||
|
||||
if (ep->is_iso_incomplete == 1U)
|
||||
{
|
||||
ep->is_iso_incomplete = 0U;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
|
||||
}
|
||||
|
||||
/* Clear Status Phase Received interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
|
||||
}
|
||||
|
||||
/* Clear OUT NAK interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
|
||||
}
|
||||
}
|
||||
epnum++;
|
||||
ep_intr >>= 1U;
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
|
||||
{
|
||||
/* Read in the device interrupt bits */
|
||||
ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
|
||||
|
||||
epnum = 0U;
|
||||
|
||||
while (ep_intr != 0U)
|
||||
{
|
||||
if ((ep_intr & 0x1U) != 0U) /* In ITR */
|
||||
{
|
||||
epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
|
||||
|
||||
if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
|
||||
{
|
||||
fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
|
||||
USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
|
||||
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
|
||||
{
|
||||
(void)USB_FlushTxFifo(USBx, epnum);
|
||||
|
||||
ep = &hpcd->IN_ep[epnum];
|
||||
|
||||
if (ep->is_iso_incomplete == 1U)
|
||||
{
|
||||
ep->is_iso_incomplete = 0U;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
|
||||
{
|
||||
(void)PCD_WriteEmptyTxFifo(hpcd, epnum);
|
||||
}
|
||||
}
|
||||
epnum++;
|
||||
ep_intr >>= 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Resume Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
|
||||
{
|
||||
/* Clear the Remote Wake-up Signaling */
|
||||
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResumeCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResumeCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
|
||||
}
|
||||
|
||||
/* Handle Suspend Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
|
||||
{
|
||||
if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SuspendCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SuspendCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
|
||||
}
|
||||
/* Handle Reset Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
|
||||
{
|
||||
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
|
||||
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
USBx_INEP(i)->DIEPINT = 0xFB7FU;
|
||||
USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
|
||||
USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
|
||||
USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
|
||||
USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
|
||||
}
|
||||
USBx_DEVICE->DAINTMSK |= 0x10001U;
|
||||
|
||||
if (hpcd->Init.use_dedicated_ep1 != 0U)
|
||||
{
|
||||
USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
|
||||
USB_OTG_DOEPMSK_XFRCM |
|
||||
USB_OTG_DOEPMSK_EPDM;
|
||||
|
||||
USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
|
||||
USB_OTG_DIEPMSK_XFRCM |
|
||||
USB_OTG_DIEPMSK_EPDM;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
|
||||
USB_OTG_DOEPMSK_XFRCM |
|
||||
USB_OTG_DOEPMSK_EPDM |
|
||||
USB_OTG_DOEPMSK_OTEPSPRM |
|
||||
USB_OTG_DOEPMSK_NAKM;
|
||||
|
||||
USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
|
||||
USB_OTG_DIEPMSK_XFRCM |
|
||||
USB_OTG_DIEPMSK_EPDM;
|
||||
}
|
||||
|
||||
/* Set Default Address to 0 */
|
||||
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
|
||||
|
||||
/* setup EP0 to receive SETUP packets */
|
||||
(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
|
||||
}
|
||||
|
||||
/* Handle Enumeration done Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
|
||||
{
|
||||
(void)USB_ActivateSetup(hpcd->Instance);
|
||||
hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
|
||||
|
||||
/* Set USB Turnaround time */
|
||||
(void)USB_SetTurnaroundTime(hpcd->Instance,
|
||||
HAL_RCC_GetHCLKFreq(),
|
||||
(uint8_t)hpcd->Init.speed);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResetCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResetCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
|
||||
}
|
||||
|
||||
/* Handle SOF Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SOFCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
|
||||
}
|
||||
|
||||
/* Handle Global OUT NAK effective Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
|
||||
{
|
||||
USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
|
||||
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
|
||||
{
|
||||
/* Abort current transaction and disable the EP */
|
||||
(void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Incomplete ISO IN Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
|
||||
{
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
RegVal = USBx_INEP(epnum)->DIEPCTL;
|
||||
|
||||
if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
|
||||
((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
|
||||
{
|
||||
hpcd->IN_ep[epnum].is_iso_incomplete = 1U;
|
||||
|
||||
/* Abort current transaction and disable the EP */
|
||||
(void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
|
||||
}
|
||||
|
||||
/* Handle Incomplete ISO OUT Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
|
||||
{
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
RegVal = USBx_OUTEP(epnum)->DOEPCTL;
|
||||
|
||||
if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
|
||||
((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
|
||||
((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U)))
|
||||
{
|
||||
hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;
|
||||
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;
|
||||
|
||||
if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
|
||||
{
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
|
||||
}
|
||||
|
||||
/* Handle Connection event Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ConnectCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ConnectCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
|
||||
}
|
||||
|
||||
/* Handle Disconnection event Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
|
||||
{
|
||||
RegVal = hpcd->Instance->GOTGINT;
|
||||
|
||||
if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DisconnectCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_DisconnectCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
hpcd->Instance->GOTGINT |= RegVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles PCD Wakeup interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Clear EXTI pending Bit */
|
||||
__HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief This function handles PCD interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
uint32_t wIstr = USB_ReadInterrupts(hpcd->Instance);
|
||||
uint16_t store_ep[8];
|
||||
uint8_t i;
|
||||
|
||||
if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
|
||||
{
|
||||
/* servicing of the endpoint correct transfer interrupt */
|
||||
/* clear of the CTR flag into the sub */
|
||||
(void)PCD_EP_ISR_Handler(hpcd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_RESET) == USB_ISTR_RESET)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResetCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResetCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
(void)HAL_PCD_SetAddress(hpcd, 0U);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
|
||||
{
|
||||
hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
|
||||
hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResumeCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResumeCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
|
||||
{
|
||||
/* WA: To Clear Wakeup flag if raised with suspend signal */
|
||||
|
||||
/* Store Endpoint registers */
|
||||
for (i = 0U; i < 8U; i++)
|
||||
{
|
||||
store_ep[i] = PCD_GET_ENDPOINT(hpcd->Instance, i);
|
||||
}
|
||||
|
||||
/* FORCE RESET */
|
||||
hpcd->Instance->CNTR |= (uint16_t)(USB_CNTR_FRES);
|
||||
|
||||
/* CLEAR RESET */
|
||||
hpcd->Instance->CNTR &= (uint16_t)(~USB_CNTR_FRES);
|
||||
|
||||
/* wait for reset flag in ISTR */
|
||||
while ((hpcd->Instance->ISTR & USB_ISTR_RESET) == 0U)
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear Reset Flag */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
|
||||
|
||||
/* Restore Registre */
|
||||
for (i = 0U; i < 8U; i++)
|
||||
{
|
||||
PCD_SET_ENDPOINT(hpcd->Instance, i, store_ep[i]);
|
||||
}
|
||||
|
||||
/* Force low-power mode in the macrocell */
|
||||
hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
|
||||
|
||||
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
|
||||
|
||||
hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SuspendCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SuspendCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SOFCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_ESOF) == USB_ISTR_ESOF)
|
||||
{
|
||||
/* clear ESOF flag in ISTR */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles PCD Wakeup interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Clear EXTI pending Bit */
|
||||
__HAL_USB_WAKEUP_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @brief Data OUT stage callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DataOutStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data IN stage callback
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DataInStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* @brief Setup stage callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SetupStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB Start Of Frame callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SOFCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB Reset callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ResetCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SuspendCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ResumeCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Incomplete ISO OUT callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Incomplete ISO IN callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connection event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ConnectCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnection event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DisconnectCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the PCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Connect the USB device
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 1U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevConnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnect the USB device.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 0U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the USB Device address.
|
||||
* @param hpcd PCD handle
|
||||
* @param address new device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
hpcd->USB_Address = address;
|
||||
(void)USB_SetDevAddress(hpcd->Instance, address);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Open and configure an endpoint.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param ep_mps endpoint max packet size
|
||||
* @param ep_type endpoint type
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
|
||||
uint16_t ep_mps, uint8_t ep_type)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
ep->maxpacket = ep_mps;
|
||||
ep->type = ep_type;
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
/* Assign a Tx FIFO */
|
||||
ep->tx_fifo_num = ep->num;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
/* Set initial data PID. */
|
||||
if (ep_type == EP_TYPE_BULK)
|
||||
{
|
||||
ep->data_pid_start = 0U;
|
||||
}
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_ActivateEndpoint(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivate an endpoint.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_DeactivateEndpoint(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param pBuf pointer to the reception buffer
|
||||
* @param len amount of data to be received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
|
||||
/*setup and start the Xfer */
|
||||
ep->xfer_buff = pBuf;
|
||||
ep->xfer_len = len;
|
||||
ep->xfer_count = 0U;
|
||||
ep->is_in = 0U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Received Data Size
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval Data Size
|
||||
*/
|
||||
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
|
||||
}
|
||||
/**
|
||||
* @brief Send an amount of data
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param pBuf pointer to the transmission buffer
|
||||
* @param len amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
|
||||
/*setup and start the Xfer */
|
||||
ep->xfer_buff = pBuf;
|
||||
ep->xfer_len = len;
|
||||
#if defined (USB)
|
||||
ep->xfer_fill_db = 1U;
|
||||
ep->xfer_len_db = len;
|
||||
#endif /* defined (USB) */
|
||||
ep->xfer_count = 0U;
|
||||
ep->is_in = 1U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a STALL condition over an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->is_stall = 1U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
(void)USB_EPSetStall(hpcd->Instance, ep);
|
||||
|
||||
if ((ep_addr & EP_ADDR_MSK) == 0U)
|
||||
{
|
||||
(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a STALL condition over in an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->is_stall = 0U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_EPClearStall(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort an USB EP transaction.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
HAL_StatusTypeDef ret;
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
|
||||
/* Stop Xfer */
|
||||
ret = USB_EPStopXfer(hpcd->Instance, ep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flush an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_FlushRxFifo(hpcd->Instance);
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activate remote wakeup signalling
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
return (USB_ActivateRemoteWakeup(hpcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-activate remote wakeup signalling.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
return (USB_DeActivateRemoteWakeup(hpcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the PCD handle state.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
|
||||
{
|
||||
return hpcd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @addtogroup PCD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Check FIFO for the next packet to be loaded.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
USB_OTG_EPTypeDef *ep;
|
||||
uint32_t len;
|
||||
uint32_t len32b;
|
||||
uint32_t fifoemptymsk;
|
||||
|
||||
ep = &hpcd->IN_ep[epnum];
|
||||
|
||||
if (ep->xfer_count > ep->xfer_len)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
len = ep->xfer_len - ep->xfer_count;
|
||||
|
||||
if (len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
}
|
||||
|
||||
len32b = (len + 3U) / 4U;
|
||||
|
||||
while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
|
||||
(ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
|
||||
{
|
||||
/* Write the FIFO */
|
||||
len = ep->xfer_len - ep->xfer_count;
|
||||
|
||||
if (len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
}
|
||||
len32b = (len + 3U) / 4U;
|
||||
|
||||
(void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len);
|
||||
|
||||
ep->xfer_buff += len;
|
||||
ep->xfer_count += len;
|
||||
}
|
||||
|
||||
if (ep->xfer_len <= ep->xfer_count)
|
||||
{
|
||||
fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
|
||||
USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief process EP OUT transfer complete interrupt.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
|
||||
uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
|
||||
|
||||
if (gSNPSiD == USB_OTG_CORE_ID_310A)
|
||||
{
|
||||
/* StupPktRcvd = 1 this is a setup packet */
|
||||
if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief process EP OUT setup packet received interrupt.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
|
||||
uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
|
||||
|
||||
if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
|
||||
((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
|
||||
}
|
||||
|
||||
/* Inform the upper layer that a setup packet is available */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SetupStageCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SetupStageCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief This function handles PCD Endpoint interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
uint16_t count;
|
||||
uint16_t wIstr;
|
||||
uint16_t wEPVal;
|
||||
uint16_t TxPctSize;
|
||||
uint8_t epindex;
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER != 1U)
|
||||
count = 0U;
|
||||
#endif /* USE_USB_DOUBLE_BUFFER */
|
||||
|
||||
/* stay in loop while pending interrupts */
|
||||
while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
|
||||
{
|
||||
wIstr = hpcd->Instance->ISTR;
|
||||
|
||||
/* extract highest priority endpoint number */
|
||||
epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
|
||||
|
||||
if (epindex == 0U)
|
||||
{
|
||||
/* Decode and service control endpoint interrupt */
|
||||
|
||||
/* DIR bit = origin of the interrupt */
|
||||
if ((wIstr & USB_ISTR_DIR) == 0U)
|
||||
{
|
||||
/* DIR = 0 */
|
||||
|
||||
/* DIR = 0 => IN int */
|
||||
/* DIR = 0 implies that (EP_CTR_TX = 1) always */
|
||||
PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
ep = &hpcd->IN_ep[0];
|
||||
|
||||
ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
|
||||
ep->xfer_buff += ep->xfer_count;
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, 0U);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, 0U);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
|
||||
{
|
||||
hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
|
||||
hpcd->USB_Address = 0U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DIR = 1 */
|
||||
|
||||
/* DIR = 1 & CTR_RX => SETUP or OUT int */
|
||||
/* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
|
||||
ep = &hpcd->OUT_ep[0];
|
||||
wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
if ((wEPVal & USB_EP_SETUP) != 0U)
|
||||
{
|
||||
/* Get SETUP Packet */
|
||||
ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
|
||||
ep->pmaadress, (uint16_t)ep->xfer_count);
|
||||
|
||||
/* SETUP bit kept frozen while CTR_RX = 1 */
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
/* Process SETUP Packet*/
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SetupStageCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SetupStageCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if ((wEPVal & USB_EP_CTR_RX) != 0U)
|
||||
{
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
/* Get Control Data OUT Packet */
|
||||
ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
|
||||
ep->pmaadress, (uint16_t)ep->xfer_count);
|
||||
|
||||
ep->xfer_buff += ep->xfer_count;
|
||||
|
||||
/* Process Control Data OUT Packet */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, 0U);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, 0U);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
|
||||
{
|
||||
PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Decode and service non control endpoints interrupt */
|
||||
/* process related endpoint register */
|
||||
wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
|
||||
|
||||
if ((wEPVal & USB_EP_CTR_RX) != 0U)
|
||||
{
|
||||
/* clear int flag */
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
|
||||
ep = &hpcd->OUT_ep[epindex];
|
||||
|
||||
/* OUT Single Buffering */
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else
|
||||
{
|
||||
/* manage double buffer bulk out */
|
||||
if (ep->type == EP_TYPE_BULK)
|
||||
{
|
||||
count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
|
||||
}
|
||||
else /* manage double buffer iso out */
|
||||
{
|
||||
/* free EP OUT Buffer */
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
|
||||
if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
/* read from endpoint BUF0Addr buffer */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read from endpoint BUF1Addr buffer */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
/* multi-packet on the NON control OUT endpoint */
|
||||
ep->xfer_count += count;
|
||||
ep->xfer_buff += count;
|
||||
|
||||
if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
|
||||
{
|
||||
/* RX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
}
|
||||
}
|
||||
|
||||
if ((wEPVal & USB_EP_CTR_TX) != 0U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[epindex];
|
||||
|
||||
/* clear int flag */
|
||||
PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
|
||||
|
||||
if (ep->type == EP_TYPE_ISOC)
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
if (ep->doublebuffer != 0U)
|
||||
{
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
}
|
||||
else
|
||||
{
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Manage Single Buffer Transaction */
|
||||
if ((wEPVal & USB_EP_KIND) == 0U)
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len > TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Zero Length Packet? */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer is not yet Done */
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
|
||||
else
|
||||
{
|
||||
(void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/**
|
||||
* @brief Manage double buffer bulk out transaction from ISR
|
||||
* @param hpcd PCD handle
|
||||
* @param ep current endpoint handle
|
||||
* @param wEPVal Last snapshot of EPRx register value taken in ISR
|
||||
* @retval HAL status
|
||||
*/
|
||||
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
|
||||
PCD_EPTypeDef *ep, uint16_t wEPVal)
|
||||
{
|
||||
uint16_t count;
|
||||
|
||||
/* Manage Buffer0 OUT */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
/* Get count of received Data on buffer0 */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= count)
|
||||
{
|
||||
ep->xfer_len -= count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* set NAK to OUT endpoint since double buffer is enabled */
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
|
||||
/* Check if Buffer1 is in blocked state which requires to toggle */
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
}
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
|
||||
}
|
||||
}
|
||||
/* Manage Buffer 1 DTOG_RX=0 */
|
||||
else
|
||||
{
|
||||
/* Get count of received data */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= count)
|
||||
{
|
||||
ep->xfer_len -= count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* set NAK on the current endpoint */
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
|
||||
/*Need to FreeUser Buffer*/
|
||||
if ((wEPVal & USB_EP_DTOG_TX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
}
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manage double buffer bulk IN transaction from ISR
|
||||
* @param hpcd PCD handle
|
||||
* @param ep current endpoint handle
|
||||
* @param wEPVal Last snapshot of EPRx register value taken in ISR
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
|
||||
PCD_EPTypeDef *ep, uint16_t wEPVal)
|
||||
{
|
||||
uint32_t len;
|
||||
uint16_t TxPctSize;
|
||||
|
||||
/* Data Buffer0 ACK received */
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len > TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Transfer is completed */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
}
|
||||
else /* Transfer is not yet Done */
|
||||
{
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
|
||||
/* Still there is data to Fill in the next Buffer */
|
||||
if (ep->xfer_fill_db == 1U)
|
||||
{
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
|
||||
/* Calculate the len of the new buffer to fill */
|
||||
if (ep->xfer_len_db >= ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else if (ep->xfer_len_db == 0U)
|
||||
{
|
||||
len = TxPctSize;
|
||||
ep->xfer_fill_db = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_fill_db = 0U;
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
}
|
||||
|
||||
/* Write remaining Data to Buffer */
|
||||
/* Set the Double buffer counter for pma buffer1 */
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
|
||||
|
||||
/* Copy user buffer to USB PMA */
|
||||
USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Data Buffer1 ACK received */
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Transfer is completed */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
}
|
||||
else /* Transfer is not yet Done */
|
||||
{
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
|
||||
/* Still there is data to Fill in the next Buffer */
|
||||
if (ep->xfer_fill_db == 1U)
|
||||
{
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
|
||||
/* Calculate the len of the new buffer to fill */
|
||||
if (ep->xfer_len_db >= ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else if (ep->xfer_len_db == 0U)
|
||||
{
|
||||
len = TxPctSize;
|
||||
ep->xfer_fill_db = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
ep->xfer_fill_db = 0;
|
||||
}
|
||||
|
||||
/* Set the Double buffer counter for pmabuffer1 */
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
|
||||
|
||||
/* Copy the user buffer to USB PMA */
|
||||
USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*enable endpoint IN*/
|
||||
PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined (USB) || defined (USB_OTG_FS) */
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pcd_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCD Extended HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + Extended 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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCDEx PCDEx
|
||||
* @brief PCD Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
|
||||
#if defined (USB) || defined (USB_OTG_FS)
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
|
||||
* @brief PCDEx control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extended features functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Update FIFO configuration
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Set Tx FIFO
|
||||
* @param hpcd PCD handle
|
||||
* @param fifo The number of Tx fifo
|
||||
* @param size Fifo size
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t Tx_Offset;
|
||||
|
||||
/* TXn min size = 16 words. (n : Transmit FIFO index)
|
||||
When a TxFIFO is not used, the Configuration should be as follows:
|
||||
case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
--> Txm can use the space allocated for Txn.
|
||||
case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
--> Txn should be configured with the minimum space of 16 words
|
||||
The FIFO is used optimally when used TxFIFOs are allocated in the top
|
||||
of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
|
||||
When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
|
||||
|
||||
Tx_Offset = hpcd->Instance->GRXFSIZ;
|
||||
|
||||
if (fifo == 0U)
|
||||
{
|
||||
hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
|
||||
for (i = 0U; i < (fifo - 1U); i++)
|
||||
{
|
||||
Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
|
||||
}
|
||||
|
||||
/* Multiply Tx_Size by 2 to get higher performance */
|
||||
hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Rx FIFO
|
||||
* @param hpcd PCD handle
|
||||
* @param size Size of Rx fifo
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
|
||||
{
|
||||
hpcd->Instance->GRXFSIZ = size;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief Configure PMA for EP
|
||||
* @param hpcd Device instance
|
||||
* @param ep_addr endpoint address
|
||||
* @param ep_kind endpoint Kind
|
||||
* USB_SNG_BUF: Single Buffer used
|
||||
* USB_DBL_BUF: Double Buffer used
|
||||
* @param pmaadress: EP address in The PMA: In case of single buffer endpoint
|
||||
* this parameter is 16-bit value providing the address
|
||||
* in PMA allocated to endpoint.
|
||||
* In case of double buffer endpoint this parameter
|
||||
* is a 32-bit value providing the endpoint buffer 0 address
|
||||
* in the LSB part of 32-bit value and endpoint buffer 1 address
|
||||
* in the MSB part of 32-bit value.
|
||||
* @retval HAL status
|
||||
*/
|
||||
|
||||
HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, uint16_t ep_addr,
|
||||
uint16_t ep_kind, uint32_t pmaadress)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
/* initialize ep structure*/
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr];
|
||||
}
|
||||
|
||||
/* Here we check if the endpoint is single or double Buffer*/
|
||||
if (ep_kind == PCD_SNG_BUF)
|
||||
{
|
||||
/* Single Buffer */
|
||||
ep->doublebuffer = 0U;
|
||||
/* Configure the PMA */
|
||||
ep->pmaadress = (uint16_t)pmaadress;
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else /* USB_DBL_BUF */
|
||||
{
|
||||
/* Double Buffer Endpoint */
|
||||
ep->doublebuffer = 1U;
|
||||
/* Configure the PMA */
|
||||
ep->pmaaddr0 = (uint16_t)(pmaadress & 0xFFFFU);
|
||||
ep->pmaaddr1 = (uint16_t)((pmaadress & 0xFFFF0000U) >> 16);
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Software Device Connection,
|
||||
* this function is not required by USB OTG FS peripheral, it is used
|
||||
* only by USB Device FS peripheral.
|
||||
* @param hpcd PCD handle
|
||||
* @param state connection state (0 : disconnected / 1: connected)
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(state);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_SetConnectionState could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @brief Send LPM message to user layer callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param msg LPM message
|
||||
* @retval HAL status
|
||||
*/
|
||||
__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(msg);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_LPM_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send BatteryCharging message to user layer callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param msg LPM message
|
||||
* @retval HAL status
|
||||
*/
|
||||
__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(msg);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_BCD_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined (USB) || defined (USB_OTG_FS) */
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
3215
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_sd.c
Normal file
3215
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_sd.c
Normal file
@@ -0,0 +1,3215 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_sd.c
|
||||
* @author MCD Application Team
|
||||
* @brief SD card HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Secure Digital (SD) 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver implements a high level communication layer for read and write from/to
|
||||
this memory. The needed STM32 hardware resources (SDIO and GPIO) are performed by
|
||||
the user in HAL_SD_MspInit() function (MSP layer).
|
||||
Basically, the MSP layer configuration should be the same as we provide in the
|
||||
examples.
|
||||
You can easily tailor this configuration according to hardware resources.
|
||||
|
||||
[..]
|
||||
This driver is a generic layered driver for SDIO memories which uses the HAL
|
||||
SDIO driver functions to interface with SD and uSD cards devices.
|
||||
It is used as follows:
|
||||
|
||||
(#)Initialize the SDIO low level resources by implementing the HAL_SD_MspInit() API:
|
||||
(##) Enable the SDIO interface clock using __HAL_RCC_SDIO_CLK_ENABLE();
|
||||
(##) SDIO pins configuration for SD card
|
||||
(+++) Enable the clock for the SDIO GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
|
||||
(+++) Configure these SDIO pins as alternate function pull-up using HAL_GPIO_Init()
|
||||
and according to your pin assignment;
|
||||
(##) DMA configuration if you need to use DMA process (HAL_SD_ReadBlocks_DMA()
|
||||
and HAL_SD_WriteBlocks_DMA() APIs).
|
||||
(+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
|
||||
(+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
|
||||
(##) NVIC configuration if you need to use interrupt process when using DMA transfer.
|
||||
(+++) Configure the SDIO and DMA interrupt priorities using functions
|
||||
HAL_NVIC_SetPriority(); DMA priority is superior to SDIO's priority
|
||||
(+++) Enable the NVIC DMA and SDIO IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT()
|
||||
and __HAL_SD_DISABLE_IT() inside the communication process.
|
||||
(+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT()
|
||||
and __HAL_SD_CLEAR_IT()
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_SD_ReadBlocks_IT()
|
||||
and HAL_SD_WriteBlocks_IT() APIs).
|
||||
(+++) Configure the SDIO interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
(+++) Enable the NVIC SDIO IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT()
|
||||
and __HAL_SD_DISABLE_IT() inside the communication process.
|
||||
(+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT()
|
||||
and __HAL_SD_CLEAR_IT()
|
||||
(#) At this stage, you can perform SD read/write/erase operations after SD card initialization
|
||||
|
||||
|
||||
*** SD Card Initialization and configuration ***
|
||||
================================================
|
||||
[..]
|
||||
To initialize the SD Card, use the HAL_SD_Init() function. It Initializes
|
||||
SDIO Peripheral(STM32 side) and the SD Card, and put it into StandBy State (Ready for data transfer).
|
||||
This function provide the following operations:
|
||||
|
||||
(#) Apply the SD Card initialization process at 400KHz and check the SD Card
|
||||
type (Standard Capacity or High Capacity). You can change or adapt this
|
||||
frequency by adjusting the "ClockDiv" field.
|
||||
The SD Card frequency (SDIO_CK) is computed as follows:
|
||||
|
||||
SDIO_CK = SDIOCLK / (ClockDiv + 2)
|
||||
|
||||
In initialization mode and according to the SD Card standard,
|
||||
make sure that the SDIO_CK frequency doesn't exceed 400KHz.
|
||||
|
||||
This phase of initialization is done through SDIO_Init() and
|
||||
SDIO_PowerState_ON() SDIO low level APIs.
|
||||
|
||||
(#) Initialize the SD card. The API used is HAL_SD_InitCard().
|
||||
This phase allows the card initialization and identification
|
||||
and check the SD Card type (Standard Capacity or High Capacity)
|
||||
The initialization flow is compatible with SD standard.
|
||||
|
||||
This API (HAL_SD_InitCard()) could be used also to reinitialize the card in case
|
||||
of plug-off plug-in.
|
||||
|
||||
(#) Configure the SD Card Data transfer frequency. You can change or adapt this
|
||||
frequency by adjusting the "ClockDiv" field.
|
||||
In transfer mode and according to the SD Card standard, make sure that the
|
||||
SDIO_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
|
||||
To be able to use a frequency higher than 24MHz, you should use the SDIO
|
||||
peripheral in bypass mode. Refer to the corresponding reference manual
|
||||
for more details.
|
||||
|
||||
(#) Select the corresponding SD Card according to the address read with the step 2.
|
||||
|
||||
(#) Configure the SD Card in wide bus mode: 4-bits data.
|
||||
|
||||
*** SD Card Read operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
|
||||
(+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the DMA transfer process through the SD Rx interrupt event.
|
||||
|
||||
(+) You can read from SD card in Interrupt mode by using function HAL_SD_ReadBlocks_IT().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the IT transfer process through the SD Rx interrupt event.
|
||||
|
||||
*** SD Card Write operation ***
|
||||
===============================
|
||||
[..]
|
||||
(+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
|
||||
(+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the DMA transfer process through the SD Tx interrupt event.
|
||||
|
||||
(+) You can write to SD card in Interrupt mode by using function HAL_SD_WriteBlocks_IT().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the IT transfer process through the SD Tx interrupt event.
|
||||
|
||||
*** SD card status ***
|
||||
======================
|
||||
[..]
|
||||
(+) The SD Status contains status bits that are related to the SD Memory
|
||||
Card proprietary features. To get SD card status use the HAL_SD_GetCardStatus().
|
||||
|
||||
*** SD card information ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To get SD card information, you can use the function HAL_SD_GetCardInfo().
|
||||
It returns useful information about the SD card such as block size, card type,
|
||||
block number ...
|
||||
|
||||
*** SD card CSD register ***
|
||||
============================
|
||||
(+) The HAL_SD_GetCardCSD() API allows to get the parameters of the CSD register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** SD card CID register ***
|
||||
============================
|
||||
(+) The HAL_SD_GetCardCID() API allows to get the parameters of the CID register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** SD HAL driver macros list ***
|
||||
==================================
|
||||
[..]
|
||||
Below the list of most used macros in SD HAL driver.
|
||||
|
||||
(+) __HAL_SD_ENABLE : Enable the SD device
|
||||
(+) __HAL_SD_DISABLE : Disable the SD device
|
||||
(+) __HAL_SD_DMA_ENABLE: Enable the SDIO DMA transfer
|
||||
(+) __HAL_SD_DMA_DISABLE: Disable the SDIO DMA transfer
|
||||
(+) __HAL_SD_ENABLE_IT: Enable the SD device interrupt
|
||||
(+) __HAL_SD_DISABLE_IT: Disable the SD device interrupt
|
||||
(+) __HAL_SD_GET_FLAG:Check whether the specified SD flag is set or not
|
||||
(+) __HAL_SD_CLEAR_FLAG: Clear the SD's pending flags
|
||||
|
||||
(@) You can refer to the SD HAL driver header file for more useful macros
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_SD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_SD_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : SD MspInit.
|
||||
(+) MspDeInitCallback : SD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_SD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : SD MspInit.
|
||||
(+) MspDeInitCallback : SD MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_SD_Init and if the state is HAL_SD_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_SD_Init
|
||||
and HAL_SD_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SD_Init and HAL_SD_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_SD_RegisterCallback before calling HAL_SD_DeInit
|
||||
or HAL_SD_Init function.
|
||||
|
||||
When The compilation define USE_HAL_SD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(SDIO)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SD
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup SD_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup SD_Private_Functions SD Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t SD_InitCard(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_PowerON(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus);
|
||||
static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus);
|
||||
static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR);
|
||||
static void SD_PowerOFF(SD_HandleTypeDef *hsd);
|
||||
static void SD_Write_IT(SD_HandleTypeDef *hsd);
|
||||
static void SD_Read_IT(SD_HandleTypeDef *hsd);
|
||||
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMATxAbort(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMARxAbort(DMA_HandleTypeDef *hdma);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup SD_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group1
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize the SD
|
||||
card device to be ready for use.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD according to the specified parameters in the
|
||||
SD_HandleTypeDef and create the associated handle.
|
||||
* @param hsd: Pointer to the SD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Check the SD handle allocation */
|
||||
if(hsd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance));
|
||||
assert_param(IS_SDIO_CLOCK_EDGE(hsd->Init.ClockEdge));
|
||||
assert_param(IS_SDIO_CLOCK_BYPASS(hsd->Init.ClockBypass));
|
||||
assert_param(IS_SDIO_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
|
||||
assert_param(IS_SDIO_BUS_WIDE(hsd->Init.BusWide));
|
||||
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
|
||||
assert_param(IS_SDIO_CLKDIV(hsd->Init.ClockDiv));
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsd->Lock = HAL_UNLOCKED;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
/* Reset Callback pointers in HAL_SD_STATE_RESET only */
|
||||
hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
|
||||
hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
|
||||
hsd->ErrorCallback = HAL_SD_ErrorCallback;
|
||||
hsd->AbortCpltCallback = HAL_SD_AbortCallback;
|
||||
|
||||
if(hsd->MspInitCallback == NULL)
|
||||
{
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsd->MspInitCallback(hsd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_SD_MspInit(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize the Card parameters */
|
||||
if (HAL_SD_InitCard(hsd) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the error code */
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
/* Initialize the SD operation */
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
/* Initialize the SD state */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD Card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @note This function initializes the SD card. It could be used when a card
|
||||
re-initialization is needed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
SD_InitTypeDef Init;
|
||||
|
||||
/* Default SDIO peripheral configuration for SD card initialization */
|
||||
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
Init.ClockDiv = SDIO_INIT_CLK_DIV;
|
||||
|
||||
/* Initialize SDIO peripheral interface with default configuration */
|
||||
SDIO_Init(hsd->Instance, Init);
|
||||
|
||||
/* Disable SDIO Clock */
|
||||
__HAL_SD_DISABLE(hsd);
|
||||
|
||||
/* Set Power State to ON */
|
||||
(void)SDIO_PowerState_ON(hsd->Instance);
|
||||
|
||||
/* Enable SDIO Clock */
|
||||
__HAL_SD_ENABLE(hsd);
|
||||
|
||||
/* Required power up waiting time before starting the SD initialization sequence */
|
||||
HAL_Delay(2);
|
||||
|
||||
/* Identify card operating voltage */
|
||||
errorstate = SD_PowerON(hsd);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Card initialization */
|
||||
errorstate = SD_InitCard(hsd);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the SD card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Check the SD handle allocation */
|
||||
if(hsd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance));
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Set SD power state to off */
|
||||
SD_PowerOFF(hsd);
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
if(hsd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hsd->MspDeInitCallback(hsd);
|
||||
#else
|
||||
/* De-Initialize the MSP layer */
|
||||
HAL_SD_MspDeInit(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
hsd->State = HAL_SD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD MSP.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize SD MSP.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group2
|
||||
* @brief Data transfer functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the data
|
||||
transfer from/to SD card.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of SD blocks to read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read block(s) in polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDIO flags */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock read */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Empty FIFO if there is still any data */
|
||||
while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allows to write block(s) to a specified address in a card. The Data
|
||||
* transfer is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of SD blocks to write
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Write block(s) in polling mode */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tempbuff);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 8U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 16U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 24U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hsd->Instance, &data);
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock write */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the IT transfer process through the SD Rx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
hsd->pRxBuffPtr = pData;
|
||||
hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read Blocks in IT mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the IT transfer process through the SD Tx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
hsd->pTxBuffPtr = pData;
|
||||
hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
/* Enable transfer interrupts */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE));
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK| SD_CONTEXT_IT);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the SD Rx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hsd->hdmarx->XferCpltCallback = SD_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsd->hdmarx->XferErrorCallback = SD_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hsd->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Force DMA Direction */
|
||||
hsd->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
MODIFY_REG(hsd->hdmarx->Instance->CCR, DMA_CCR_DIR, hsd->hdmarx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hsd->hdmarx, (uint32_t)&hsd->Instance->FIFO, (uint32_t)pData, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK)
|
||||
{
|
||||
__HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable SD DMA transfer */
|
||||
__HAL_SD_DMA_ENABLE(hsd);
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read Blocks in DMA mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the SD Tx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
/* Enable SD Error interrupts */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsd->hdmatx->XferErrorCallback = SD_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hsd->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable SDIO DMA transfer */
|
||||
__HAL_SD_DMA_ENABLE(hsd);
|
||||
|
||||
/* Force DMA Direction */
|
||||
hsd->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
MODIFY_REG(hsd->hdmatx->Instance->CCR, DMA_CCR_DIR, hsd->hdmatx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK)
|
||||
{
|
||||
__HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases the specified memory area of the given SD card.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param BlockStartAdd: Start Block address
|
||||
* @param BlockEndAdd: End Block address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t start_add = BlockStartAdd;
|
||||
uint32_t end_add = BlockEndAdd;
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if(end_add < start_add)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(end_add > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Check if the card command class supports erase command */
|
||||
if(((hsd->SdCard.Class) & SDIO_CCCC_ERASE) == 0U)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get start and end block for high capacity cards */
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
start_add *= 512U;
|
||||
end_add *= 512U;
|
||||
}
|
||||
|
||||
/* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD32 SD_ERASE_GRP_START with argument as addr */
|
||||
errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD33 SD_ERASE_GRP_END with argument as addr */
|
||||
errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send CMD38 ERASE */
|
||||
errorstate = SDMMC_CmdErase(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SD card interrupt request.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* Check for SDIO interrupt flags */
|
||||
if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
|
||||
{
|
||||
SD_Read_IT(hsd);
|
||||
}
|
||||
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) != RESET)
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DATAEND);
|
||||
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_TXFIFOHE |\
|
||||
SDIO_IT_RXFIFOHF);
|
||||
|
||||
hsd->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
|
||||
|
||||
if((context & SD_CONTEXT_IT) != 0U)
|
||||
{
|
||||
if(((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->RxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_RxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->TxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_TxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else if((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the SD DCTRL register */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->TxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_TxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
|
||||
{
|
||||
SD_Write_IT(hsd);
|
||||
}
|
||||
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
/* Set Error code */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
|
||||
}
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
|
||||
|
||||
/* Disable all interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
|
||||
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
|
||||
if((context & SD_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Set the SD state to ready to be able to start again the process */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Abort the SD DMA channel */
|
||||
if(((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
/* Set the DMA Tx abort callback */
|
||||
hsd->hdmatx->XferAbortCallback = SD_DMATxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
SD_DMATxAbort(hsd->hdmatx);
|
||||
}
|
||||
}
|
||||
else if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
/* Set the DMA Rx abort callback */
|
||||
hsd->hdmarx->XferAbortCallback = SD_DMARxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
SD_DMARxAbort(hsd->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return the SD state
|
||||
* @param hsd: Pointer to sd handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SD_StateTypeDef HAL_SD_GetState(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
return hsd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SD error code
|
||||
* @param hsd : Pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval SD Error Code
|
||||
*/
|
||||
uint32_t HAL_SD_GetError(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
return hsd->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_TxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_RxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SD error callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_ErrorCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SD Abort callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_AbortCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User SD Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hsd : SD handle
|
||||
* @param CallbackID : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
|
||||
* @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
|
||||
* @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
|
||||
* @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
|
||||
* @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
|
||||
* @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_RegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID, pSD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsd);
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_TX_CPLT_CB_ID :
|
||||
hsd->TxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_RX_CPLT_CB_ID :
|
||||
hsd->RxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_ERROR_CB_ID :
|
||||
hsd->ErrorCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_ABORT_CB_ID :
|
||||
hsd->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User SD Callback
|
||||
* SD Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hsd : SD handle
|
||||
* @param CallbackID : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
|
||||
* @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
|
||||
* @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
|
||||
* @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
|
||||
* @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
|
||||
* @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_UnRegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsd);
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_TX_CPLT_CB_ID :
|
||||
hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
|
||||
break;
|
||||
case HAL_SD_RX_CPLT_CB_ID :
|
||||
hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
|
||||
break;
|
||||
case HAL_SD_ERROR_CB_ID :
|
||||
hsd->ErrorCallback = HAL_SD_ErrorCallback;
|
||||
break;
|
||||
case HAL_SD_ABORT_CB_ID :
|
||||
hsd->AbortCpltCallback = HAL_SD_AbortCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsd);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group3
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SD card
|
||||
operations and get the related information
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CID register.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCID: Pointer to a HAL_SD_CardCIDTypeDef structure that
|
||||
* contains all CID register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID)
|
||||
{
|
||||
pCID->ManufacturerID = (uint8_t)((hsd->CID[0] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->OEM_AppliID = (uint16_t)((hsd->CID[0] & 0x00FFFF00U) >> 8U);
|
||||
|
||||
pCID->ProdName1 = (((hsd->CID[0] & 0x000000FFU) << 24U) | ((hsd->CID[1] & 0xFFFFFF00U) >> 8U));
|
||||
|
||||
pCID->ProdName2 = (uint8_t)(hsd->CID[1] & 0x000000FFU);
|
||||
|
||||
pCID->ProdRev = (uint8_t)((hsd->CID[2] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->ProdSN = (((hsd->CID[2] & 0x00FFFFFFU) << 8U) | ((hsd->CID[3] & 0xFF000000U) >> 24U));
|
||||
|
||||
pCID->Reserved1 = (uint8_t)((hsd->CID[3] & 0x00F00000U) >> 20U);
|
||||
|
||||
pCID->ManufactDate = (uint16_t)((hsd->CID[3] & 0x000FFF00U) >> 8U);
|
||||
|
||||
pCID->CID_CRC = (uint8_t)((hsd->CID[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCID->Reserved2 = 1U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CSD register.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCSD: Pointer to a HAL_SD_CardCSDTypeDef structure that
|
||||
* contains all CSD register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD)
|
||||
{
|
||||
pCSD->CSDStruct = (uint8_t)((hsd->CSD[0] & 0xC0000000U) >> 30U);
|
||||
|
||||
pCSD->SysSpecVersion = (uint8_t)((hsd->CSD[0] & 0x3C000000U) >> 26U);
|
||||
|
||||
pCSD->Reserved1 = (uint8_t)((hsd->CSD[0] & 0x03000000U) >> 24U);
|
||||
|
||||
pCSD->TAAC = (uint8_t)((hsd->CSD[0] & 0x00FF0000U) >> 16U);
|
||||
|
||||
pCSD->NSAC = (uint8_t)((hsd->CSD[0] & 0x0000FF00U) >> 8U);
|
||||
|
||||
pCSD->MaxBusClkFrec = (uint8_t)(hsd->CSD[0] & 0x000000FFU);
|
||||
|
||||
pCSD->CardComdClasses = (uint16_t)((hsd->CSD[1] & 0xFFF00000U) >> 20U);
|
||||
|
||||
pCSD->RdBlockLen = (uint8_t)((hsd->CSD[1] & 0x000F0000U) >> 16U);
|
||||
|
||||
pCSD->PartBlockRead = (uint8_t)((hsd->CSD[1] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->WrBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->RdBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->DSRImpl = (uint8_t)((hsd->CSD[1] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->Reserved2 = 0U; /*!< Reserved */
|
||||
|
||||
if(hsd->SdCard.CardType == CARD_SDSC)
|
||||
{
|
||||
pCSD->DeviceSize = (((hsd->CSD[1] & 0x000003FFU) << 2U) | ((hsd->CSD[2] & 0xC0000000U) >> 30U));
|
||||
|
||||
pCSD->MaxRdCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x38000000U) >> 27U);
|
||||
|
||||
pCSD->MaxRdCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x07000000U) >> 24U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x00E00000U) >> 21U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x001C0000U) >> 18U);
|
||||
|
||||
pCSD->DeviceSizeMul = (uint8_t)((hsd->CSD[2] & 0x00038000U) >> 15U);
|
||||
|
||||
hsd->SdCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
|
||||
hsd->SdCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
|
||||
hsd->SdCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
|
||||
|
||||
hsd->SdCard.LogBlockNbr = (hsd->SdCard.BlockNbr) * ((hsd->SdCard.BlockSize) / 512U);
|
||||
hsd->SdCard.LogBlockSize = 512U;
|
||||
}
|
||||
else if(hsd->SdCard.CardType == CARD_SDHC_SDXC)
|
||||
{
|
||||
/* Byte 7 */
|
||||
pCSD->DeviceSize = (((hsd->CSD[1] & 0x0000003FU) << 16U) | ((hsd->CSD[2] & 0xFFFF0000U) >> 16U));
|
||||
|
||||
hsd->SdCard.BlockNbr = ((pCSD->DeviceSize + 1U) * 1024U);
|
||||
hsd->SdCard.LogBlockNbr = hsd->SdCard.BlockNbr;
|
||||
hsd->SdCard.BlockSize = 512U;
|
||||
hsd->SdCard.LogBlockSize = hsd->SdCard.BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
pCSD->EraseGrSize = (uint8_t)((hsd->CSD[2] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->EraseGrMul = (uint8_t)((hsd->CSD[2] & 0x00003F80U) >> 7U);
|
||||
|
||||
pCSD->WrProtectGrSize = (uint8_t)(hsd->CSD[2] & 0x0000007FU);
|
||||
|
||||
pCSD->WrProtectGrEnable = (uint8_t)((hsd->CSD[3] & 0x80000000U) >> 31U);
|
||||
|
||||
pCSD->ManDeflECC = (uint8_t)((hsd->CSD[3] & 0x60000000U) >> 29U);
|
||||
|
||||
pCSD->WrSpeedFact = (uint8_t)((hsd->CSD[3] & 0x1C000000U) >> 26U);
|
||||
|
||||
pCSD->MaxWrBlockLen= (uint8_t)((hsd->CSD[3] & 0x03C00000U) >> 22U);
|
||||
|
||||
pCSD->WriteBlockPaPartial = (uint8_t)((hsd->CSD[3] & 0x00200000U) >> 21U);
|
||||
|
||||
pCSD->Reserved3 = 0;
|
||||
|
||||
pCSD->ContentProtectAppli = (uint8_t)((hsd->CSD[3] & 0x00010000U) >> 16U);
|
||||
|
||||
pCSD->FileFormatGroup = (uint8_t)((hsd->CSD[3] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->CopyFlag = (uint8_t)((hsd->CSD[3] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->PermWrProtect = (uint8_t)((hsd->CSD[3] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->TempWrProtect = (uint8_t)((hsd->CSD[3] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->FileFormat = (uint8_t)((hsd->CSD[3] & 0x00000C00U) >> 10U);
|
||||
|
||||
pCSD->ECC= (uint8_t)((hsd->CSD[3] & 0x00000300U) >> 8U);
|
||||
|
||||
pCSD->CSD_CRC = (uint8_t)((hsd->CSD[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCSD->Reserved4 = 1;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the SD status info.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pStatus: Pointer to the HAL_SD_CardStatusTypeDef structure that
|
||||
* will contain the SD card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus)
|
||||
{
|
||||
uint32_t sd_status[16];
|
||||
uint32_t errorstate;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
errorstate = SD_SendSDStatus(hsd, sd_status);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
pStatus->DataBusWidth = (uint8_t)((sd_status[0] & 0xC0U) >> 6U);
|
||||
|
||||
pStatus->SecuredMode = (uint8_t)((sd_status[0] & 0x20U) >> 5U);
|
||||
|
||||
pStatus->CardType = (uint16_t)(((sd_status[0] & 0x00FF0000U) >> 8U) | ((sd_status[0] & 0xFF000000U) >> 24U));
|
||||
|
||||
pStatus->ProtectedAreaSize = (((sd_status[1] & 0xFFU) << 24U) | ((sd_status[1] & 0xFF00U) << 8U) |
|
||||
((sd_status[1] & 0xFF0000U) >> 8U) | ((sd_status[1] & 0xFF000000U) >> 24U));
|
||||
|
||||
pStatus->SpeedClass = (uint8_t)(sd_status[2] & 0xFFU);
|
||||
|
||||
pStatus->PerformanceMove = (uint8_t)((sd_status[2] & 0xFF00U) >> 8U);
|
||||
|
||||
pStatus->AllocationUnitSize = (uint8_t)((sd_status[2] & 0xF00000U) >> 20U);
|
||||
|
||||
pStatus->EraseSize = (uint16_t)(((sd_status[2] & 0xFF000000U) >> 16U) | (sd_status[3] & 0xFFU));
|
||||
|
||||
pStatus->EraseTimeout = (uint8_t)((sd_status[3] & 0xFC00U) >> 10U);
|
||||
|
||||
pStatus->EraseOffset = (uint8_t)((sd_status[3] & 0x0300U) >> 8U);
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode = errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the SD card info.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCardInfo: Pointer to the HAL_SD_CardInfoTypeDef structure that
|
||||
* will contain the SD card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo)
|
||||
{
|
||||
pCardInfo->CardType = (uint32_t)(hsd->SdCard.CardType);
|
||||
pCardInfo->CardVersion = (uint32_t)(hsd->SdCard.CardVersion);
|
||||
pCardInfo->Class = (uint32_t)(hsd->SdCard.Class);
|
||||
pCardInfo->RelCardAdd = (uint32_t)(hsd->SdCard.RelCardAdd);
|
||||
pCardInfo->BlockNbr = (uint32_t)(hsd->SdCard.BlockNbr);
|
||||
pCardInfo->BlockSize = (uint32_t)(hsd->SdCard.BlockSize);
|
||||
pCardInfo->LogBlockNbr = (uint32_t)(hsd->SdCard.LogBlockNbr);
|
||||
pCardInfo->LogBlockSize = (uint32_t)(hsd->SdCard.LogBlockSize);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables wide bus operation for the requested card if supported by
|
||||
* card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param WideMode: Specifies the SD card wide bus mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)
|
||||
{
|
||||
SDIO_InitTypeDef Init;
|
||||
uint32_t errorstate;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_BUS_WIDE(WideMode));
|
||||
|
||||
/* Change State */
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
if(WideMode == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_4B)
|
||||
{
|
||||
errorstate = SD_WideBus_Enable(hsd);
|
||||
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
errorstate = SD_WideBus_Disable(hsd);
|
||||
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* WideMode is not a valid argument*/
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MMC Card does not support this feature */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SDIO peripheral */
|
||||
Init.ClockEdge = hsd->Init.ClockEdge;
|
||||
Init.ClockBypass = hsd->Init.ClockBypass;
|
||||
Init.ClockPowerSave = hsd->Init.ClockPowerSave;
|
||||
Init.BusWide = WideMode;
|
||||
Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;
|
||||
Init.ClockDiv = hsd->Init.ClockDiv;
|
||||
(void)SDIO_Init(hsd->Instance, Init);
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Change State */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current sd card data state.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @retval Card state
|
||||
*/
|
||||
HAL_SD_CardStateTypeDef HAL_SD_GetCardState(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t cardstate;
|
||||
uint32_t errorstate;
|
||||
uint32_t resp1 = 0;
|
||||
|
||||
errorstate = SD_SendStatus(hsd, &resp1);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
cardstate = ((resp1 >> 9U) & 0x0FU);
|
||||
|
||||
return (HAL_SD_CardStateTypeDef)cardstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the SD.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information for SD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN);
|
||||
|
||||
if ((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Disable the SD DMA request */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the SD DMA Tx channel */
|
||||
if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
if(HAL_DMA_Abort(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
/* Abort the SD DMA Rx channel */
|
||||
else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
if(HAL_DMA_Abort(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
/* Initialize the SD operation */
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the SD (IT mode).
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information for SD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN);
|
||||
|
||||
if ((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Disable the SD DMA request */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the SD DMA Tx channel */
|
||||
if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
hsd->hdmatx->XferAbortCallback = SD_DMATxAbort;
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsd->hdmatx = NULL;
|
||||
}
|
||||
}
|
||||
/* Abort the SD DMA Rx channel */
|
||||
else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
hsd->hdmarx->XferAbortCallback = SD_DMARxAbort;
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsd->hdmarx = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
/* No transfer ongoing on both DMA channels*/
|
||||
else
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/** @addtogroup SD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SD transmit process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
|
||||
/* Enable DATAEND Interrupt */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD receive process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send stop command in multiblock write */
|
||||
if(hsd->Context == (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the SD DCTRL register */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->RxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_RxCpltCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD communication error callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t RxErrorCode, TxErrorCode;
|
||||
|
||||
RxErrorCode = hsd->hdmarx->ErrorCode;
|
||||
TxErrorCode = hsd->hdmatx->ErrorCode;
|
||||
if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
}
|
||||
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD Tx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMATxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode == HAL_SD_ERROR_NONE)
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD Rx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMARxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode == HAL_SD_ERROR_NONE)
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the sd card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
static uint32_t SD_InitCard(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardCSDTypeDef CSD;
|
||||
uint32_t errorstate;
|
||||
uint16_t sd_rca = 1U;
|
||||
|
||||
/* Check the power State */
|
||||
if(SDIO_GetPowerState(hsd->Instance) == 0U)
|
||||
{
|
||||
/* Power off */
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD2 ALL_SEND_CID */
|
||||
errorstate = SDMMC_CmdSendCID(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card identification number data */
|
||||
hsd->CID[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
hsd->CID[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2);
|
||||
hsd->CID[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3);
|
||||
hsd->CID[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4);
|
||||
}
|
||||
}
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD3 SET_REL_ADDR with argument 0 */
|
||||
/* SD Card publishes its RCA. */
|
||||
errorstate = SDMMC_CmdSetRelAdd(hsd->Instance, &sd_rca);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
}
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Get the SD card RCA */
|
||||
hsd->SdCard.RelCardAdd = sd_rca;
|
||||
|
||||
/* Send CMD9 SEND_CSD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdSendCSD(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card Specific Data */
|
||||
hsd->CSD[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
hsd->CSD[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2);
|
||||
hsd->CSD[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3);
|
||||
hsd->CSD[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the Card Class */
|
||||
hsd->SdCard.Class = (SDIO_GetResponse(hsd->Instance, SDIO_RESP2) >> 20U);
|
||||
|
||||
/* Get CSD parameters */
|
||||
if (HAL_SD_GetCardCSD(hsd, &CSD) != HAL_OK)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Select the Card */
|
||||
errorstate = SDMMC_CmdSelDesel(hsd->Instance, (uint32_t)(((uint32_t)hsd->SdCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Configure SDIO peripheral interface */
|
||||
(void)SDIO_Init(hsd->Instance, hsd->Init);
|
||||
|
||||
/* All cards are initialized */
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enquires cards about their operating voltage and configures clock
|
||||
* controls and stores SD information that will be needed in future
|
||||
* in the SD handle.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_PowerON(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t response = 0U, validvoltage = 0U;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
|
||||
errorstate = SDMMC_CmdOperCond(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->SdCard.CardVersion = CARD_V1_X;
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->SdCard.CardVersion = CARD_V2_X;
|
||||
}
|
||||
|
||||
if( hsd->SdCard.CardVersion == CARD_V2_X)
|
||||
{
|
||||
/* SEND CMD55 APP_CMD with RCA as 0 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
}
|
||||
/* SD CARD */
|
||||
/* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
|
||||
while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U))
|
||||
{
|
||||
/* SEND CMD55 APP_CMD with RCA as 0 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD41 */
|
||||
errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
|
||||
/* Get operating voltage*/
|
||||
validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if(count >= SDMMC_MAX_VOLT_TRIAL)
|
||||
{
|
||||
return HAL_SD_ERROR_INVALID_VOLTRANGE;
|
||||
}
|
||||
|
||||
if((response & SDMMC_HIGH_CAPACITY) == SDMMC_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */
|
||||
{
|
||||
hsd->SdCard.CardType = CARD_SDHC_SDXC;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->SdCard.CardType = CARD_SDSC;
|
||||
}
|
||||
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turns the SDIO output signals off.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_PowerOFF(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Set Power State to OFF */
|
||||
(void)SDIO_PowerState_OFF(hsd->Instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send Status info command.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @param pSDstatus: Pointer to the buffer that will contain the SD card status
|
||||
* SD Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t *pData = pSDstatus;
|
||||
|
||||
/* Check SD response */
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Set block size for card if it is not equal to current block size for card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD55 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 64U;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_64B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Send ACMD13 (SD_APP_STAUS) with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdStatusRegister(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get status data */
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
*pData = SDIO_ReadFIFO(hsd->Instance);
|
||||
pData++;
|
||||
}
|
||||
}
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
return HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
return HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
return HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)))
|
||||
{
|
||||
*pData = SDIO_ReadFIFO(hsd->Instance);
|
||||
pData++;
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static status flags*/
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current card's status.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCardStatus: pointer to the buffer that will contain the SD card
|
||||
* status (Card Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
|
||||
if(pCardStatus == NULL)
|
||||
{
|
||||
return HAL_SD_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Send Status command */
|
||||
errorstate = SDMMC_CmdSendStatus(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get SD card status */
|
||||
*pCardStatus = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the SDIO wide bus mode.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t scr[2U] = {0U, 0U};
|
||||
uint32_t errorstate;
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Get SCR Register */
|
||||
errorstate = SD_FindSCR(hsd, scr);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* If requested card supports wide bus operation */
|
||||
if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
|
||||
{
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA.*/
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
|
||||
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the SDIO wide bus mode.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t scr[2U] = {0U, 0U};
|
||||
uint32_t errorstate;
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Get SCR Register */
|
||||
errorstate = SD_FindSCR(hsd, scr);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* If requested card supports 1 bit mode operation */
|
||||
if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO)
|
||||
{
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
|
||||
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Finds the SD card SCR register value.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pSCR: pointer to the buffer that will contain the SCR value
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t index = 0U;
|
||||
uint32_t tempscr[2U] = {0U, 0U};
|
||||
uint32_t *scr = pSCR;
|
||||
|
||||
/* Set Block Size To 8 Bytes */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 8U;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_8B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
|
||||
errorstate = SDMMC_CmdSendSCR(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL))
|
||||
{
|
||||
*(tempscr + index) = SDIO_ReadFIFO(hsd->Instance);
|
||||
index++;
|
||||
}
|
||||
else if(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXACT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DTIMEOUT);
|
||||
|
||||
return HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DCRCFAIL);
|
||||
|
||||
return HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_RXOVERR);
|
||||
|
||||
return HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No error flag set */
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
*scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24) | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\
|
||||
((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24));
|
||||
scr++;
|
||||
*scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24) | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\
|
||||
((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24));
|
||||
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up reading in non-blocking mode.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_Read_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hsd->pRxBuffPtr;
|
||||
dataremaining = hsd->RxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tmp = (uint8_t)(data & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
}
|
||||
|
||||
hsd->pRxBuffPtr = tmp;
|
||||
hsd->RxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up writing in non-blocking mode.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_Write_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hsd->pTxBuffPtr;
|
||||
dataremaining = hsd->TxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tmp);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 8U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 16U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 24U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hsd->Instance, &data);
|
||||
}
|
||||
|
||||
hsd->pTxBuffPtr = tmp;
|
||||
hsd->TxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SDIO */
|
||||
@@ -0,0 +1,2348 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_smartcard.c
|
||||
* @author MCD Application Team
|
||||
* @brief SMARTCARD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the SMARTCARD peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The SMARTCARD HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a SMARTCARD_HandleTypeDef handle structure.
|
||||
(#) Initialize the SMARTCARD low level resources by implementing the HAL_SMARTCARD_MspInit() API:
|
||||
(##) Enable the interface clock of the USARTx associated to the SMARTCARD.
|
||||
(##) SMARTCARD pins configuration:
|
||||
(+++) Enable the clock for the SMARTCARD GPIOs.
|
||||
(+++) Configure SMARTCARD pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_SMARTCARD_Transmit_IT()
|
||||
and HAL_SMARTCARD_Receive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_SMARTCARD_Transmit_DMA()
|
||||
and HAL_SMARTCARD_Receive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the SMARTCARD DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length , Stop Bit, Parity, Hardware
|
||||
flow control and Mode(Receiver/Transmitter) in the SMARTCARD Init structure.
|
||||
|
||||
(#) Initialize the SMARTCARD registers by calling the HAL_SMARTCARD_Init() API:
|
||||
(++) These APIs configure also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_SMARTCARD_MspInit() API.
|
||||
[..]
|
||||
(@) The specific SMARTCARD interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_SMARTCARD_ENABLE_IT() and __HAL_SMARTCARD_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
[..]
|
||||
Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_SMARTCARD_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_SMARTCARD_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_SMARTCARD_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_SMARTCARD_Receive_IT()
|
||||
(+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Transmit_DMA()
|
||||
(+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Receive_DMA()
|
||||
(+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback
|
||||
|
||||
*** SMARTCARD HAL driver macros list ***
|
||||
========================================
|
||||
[..]
|
||||
Below the list of most used macros in SMARTCARD HAL driver.
|
||||
|
||||
(+) __HAL_SMARTCARD_ENABLE: Enable the SMARTCARD peripheral
|
||||
(+) __HAL_SMARTCARD_DISABLE: Disable the SMARTCARD peripheral
|
||||
(+) __HAL_SMARTCARD_GET_FLAG : Check whether the specified SMARTCARD flag is set or not
|
||||
(+) __HAL_SMARTCARD_CLEAR_FLAG : Clear the specified SMARTCARD pending flag
|
||||
(+) __HAL_SMARTCARD_ENABLE_IT: Enable the specified SMARTCARD interrupt
|
||||
(+) __HAL_SMARTCARD_DISABLE_IT: Disable the specified SMARTCARD interrupt
|
||||
|
||||
[..]
|
||||
(@) You can refer to the SMARTCARD HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function HAL_SMARTCARD_RegisterCallback() to register a user callback.
|
||||
Function HAL_SMARTCARD_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : SMARTCARD MspInit.
|
||||
(+) MspDeInitCallback : SMARTCARD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_SMARTCARD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
HAL_SMARTCARD_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : SMARTCARD MspInit.
|
||||
(+) MspDeInitCallback : SMARTCARD MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the HAL_SMARTCARD_Init() and when the state is HAL_SMARTCARD_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_SMARTCARD_Init()
|
||||
and HAL_SMARTCARD_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SMARTCARD_Init() and HAL_SMARTCARD_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_SMARTCARD_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_SMARTCARD_STATE_READY or HAL_SMARTCARD_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_SMARTCARD_RegisterCallback() before calling HAL_SMARTCARD_DeInit()
|
||||
or HAL_SMARTCARD_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD SMARTCARD
|
||||
* @brief HAL SMARTCARD module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup SMARTCARD_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup SMARTCARD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_SetConfig (SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup SMARTCARD_Exported_Functions SMARTCARD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group1 SmartCard Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USART
|
||||
in Smartcard mode.
|
||||
[..]
|
||||
The Smartcard interface is designed to support asynchronous protocol Smartcards as
|
||||
defined in the ISO 7816-3 standard.
|
||||
[..]
|
||||
The USART can provide a clock to the smartcard through the SCLK output.
|
||||
In smartcard mode, SCLK is not associated to the communication but is simply derived
|
||||
from the internal peripheral input clock through a 5-bit prescaler.
|
||||
[..]
|
||||
(+) For the Smartcard mode only these parameters can be configured:
|
||||
(++) Baud Rate
|
||||
(++) Word Length => Should be 9 bits (8 bits + parity)
|
||||
(++) Stop Bit
|
||||
(++) Parity: => Should be enabled
|
||||
(++) USART polarity
|
||||
(++) USART phase
|
||||
(++) USART LastBit
|
||||
(++) Receiver/transmitter modes
|
||||
(++) Prescaler
|
||||
(++) GuardTime
|
||||
(++) NACKState: The Smartcard NACK state
|
||||
|
||||
(+) Recommended SmartCard interface configuration to get the Answer to Reset from the Card:
|
||||
(++) Word Length = 9 Bits
|
||||
(++) 1.5 Stop Bit
|
||||
(++) Even parity
|
||||
(++) BaudRate = 12096 baud
|
||||
(++) Tx and Rx enabled
|
||||
[..]
|
||||
Please refer to the ISO 7816-3 specification for more details.
|
||||
|
||||
[..]
|
||||
(@) It is also possible to choose 0.5 stop bit for receiving but it is recommended
|
||||
to use 1.5 stop bits for both transmitting and receiving to avoid switching
|
||||
between the two configurations.
|
||||
[..]
|
||||
The HAL_SMARTCARD_Init() function follows the USART SmartCard configuration
|
||||
procedures (details for the procedures are available in reference manuals
|
||||
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
|
||||
|
||||
@endverbatim
|
||||
|
||||
The SMARTCARD frame format is given in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | SMARTCARD frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | STB | |
|
||||
+-------------------------------------------------------------+
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the SmartCard mode according to the specified
|
||||
* parameters in the SMARTCARD_InitTypeDef and create the associated handle.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Check the SMARTCARD handle allocation */
|
||||
if(hsc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState));
|
||||
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsc->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
|
||||
SMARTCARD_InitCallbacksToDefault(hsc);
|
||||
|
||||
if (hsc->MspInitCallback == NULL)
|
||||
{
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsc->MspInitCallback(hsc);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_SMARTCARD_MspInit(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY;
|
||||
|
||||
/* Set the Prescaler */
|
||||
MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_PSC, hsc->Init.Prescaler);
|
||||
|
||||
/* Set the Guard Time */
|
||||
MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_GT, ((hsc->Init.GuardTime)<<8U));
|
||||
|
||||
/* Set the Smartcard Communication parameters */
|
||||
SMARTCARD_SetConfig(hsc);
|
||||
|
||||
/* In SmartCard mode, the following bits must be kept cleared:
|
||||
- LINEN bit in the USART_CR2 register
|
||||
- HDSEL and IREN bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(hsc->Instance->CR2, USART_CR2_LINEN);
|
||||
CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_IREN | USART_CR3_HDSEL));
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Enable the SMARTCARD Framing Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_SMARTCARD_ENABLE(hsc);
|
||||
|
||||
/* Configure the Smartcard NACK state */
|
||||
MODIFY_REG(hsc->Instance->CR3, USART_CR3_NACK, hsc->Init.NACKState);
|
||||
|
||||
/* Enable the SC mode by setting the SCEN bit in the CR3 register */
|
||||
hsc->Instance->CR3 |= (USART_CR3_SCEN);
|
||||
|
||||
/* Initialize the SMARTCARD state*/
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState= HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState= HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the USART SmartCard peripheral
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_DeInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Check the SMARTCARD handle allocation */
|
||||
if(hsc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_SMARTCARD_DISABLE(hsc);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
|
||||
if (hsc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hsc->MspDeInitCallback(hsc);
|
||||
#else
|
||||
HAL_SMARTCARD_MspDeInit(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_RESET;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD MSP Init
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD MSP DeInit
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_MspDeInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User SMARTCARD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_SMARTCARD_RegisterCallback() may be called before HAL_SMARTCARD_Init()
|
||||
* in HAL_SMARTCARD_STATE_RESET to register callbacks for HAL_SMARTCARD_MSPINIT_CB_ID
|
||||
* and HAL_SMARTCARD_MSPDEINIT_CB_ID
|
||||
* @param hsc smartcard handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_RegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID, pSMARTCARD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
|
||||
case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
|
||||
hsc->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
|
||||
hsc->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ERROR_CB_ID :
|
||||
hsc->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
|
||||
hsc->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hsc->AbortTransmitCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hsc->AbortReceiveCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsc->gState == HAL_SMARTCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an SMARTCARD callback
|
||||
* SMARTCARD callback is redirected to the weak predefined callback
|
||||
* @note The HAL_SMARTCARD_UnRegisterCallback() may be called before HAL_SMARTCARD_Init()
|
||||
* in HAL_SMARTCARD_STATE_RESET to un-register callbacks for HAL_SMARTCARD_MSPINIT_CB_ID
|
||||
* and HAL_SMARTCARD_MSPDEINIT_CB_ID
|
||||
* @param hsc smartcard handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_UnRegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (HAL_SMARTCARD_STATE_READY == hsc->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
|
||||
hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
|
||||
hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ERROR_CB_ID :
|
||||
hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
|
||||
hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
break;
|
||||
|
||||
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SMARTCARD_STATE_RESET == hsc->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group2 IO operation functions
|
||||
* @brief SMARTCARD Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the SMARTCARD data transfers.
|
||||
|
||||
[..]
|
||||
(#) Smartcard is a single wire half duplex communication protocol.
|
||||
The Smartcard interface is designed to support asynchronous protocol Smartcards as
|
||||
defined in the ISO 7816-3 standard.
|
||||
(#) The USART should be configured as:
|
||||
(++) 8 bits plus parity: where M=1 and PCE=1 in the USART_CR1 register
|
||||
(++) 1.5 stop bits when transmitting and receiving: where STOP=11 in the USART_CR2 register.
|
||||
|
||||
(#) 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.
|
||||
(++) Non 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 SMARTCARD IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the Transmit or Receive process
|
||||
The HAL_SMARTCARD_ErrorCallback() user callback will be executed when a communication error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_SMARTCARD_Transmit()
|
||||
(++) HAL_SMARTCARD_Receive()
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_SMARTCARD_Transmit_IT()
|
||||
(++) HAL_SMARTCARD_Receive_IT()
|
||||
(++) HAL_SMARTCARD_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_SMARTCARD_Transmit_DMA()
|
||||
(++) HAL_SMARTCARD_Receive_DMA()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_SMARTCARD_TxCpltCallback()
|
||||
(++) HAL_SMARTCARD_RxCpltCallback()
|
||||
(++) HAL_SMARTCARD_ErrorCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(+) HAL_SMARTCARD_Abort()
|
||||
(+) HAL_SMARTCARD_AbortTransmit()
|
||||
(+) HAL_SMARTCARD_AbortReceive()
|
||||
(+) HAL_SMARTCARD_Abort_IT()
|
||||
(+) HAL_SMARTCARD_AbortTransmit_IT()
|
||||
(+) HAL_SMARTCARD_AbortReceive_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_SMARTCARD_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
|
||||
(+) HAL_SMARTCARD_AbortCpltCallback()
|
||||
(+) HAL_SMARTCARD_AbortTransmitCpltCallback()
|
||||
(+) HAL_SMARTCARD_AbortReceiveCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_SMARTCARD_ErrorCallback() user callback is executed. Transfer is kept ongoing on SMARTCARD side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Frame Error in Interrupt mode transmission, Overrun Error in Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_SMARTCARD_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD 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_SMARTCARD_Transmit(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint8_t *tmp = pData;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
while(hsc->TxXferCount > 0U)
|
||||
{
|
||||
hsc->TxXferCount--;
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
hsc->Instance->DR = (uint8_t)(*tmp & 0xFFU);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* At end of Tx process, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD 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_SMARTCARD_Receive(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *tmp = pData;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hsc->RxXferSize = Size;
|
||||
hsc->RxXferCount = Size;
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while(hsc->RxXferCount > 0U)
|
||||
{
|
||||
hsc->RxXferCount--;
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
*tmp = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pTxBuffPtr = pData;
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the SMARTCARD Transmit data register empty Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pRxBuffPtr = pData;
|
||||
hsc->RxXferSize = Size;
|
||||
hsc->RxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error and Data Register not empty Interrupts */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE| USART_CR1_RXNEIE);
|
||||
|
||||
/* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Transmit_DMA(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pTxBuffPtr = pData;
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Set the SMARTCARD DMA transfer complete callback */
|
||||
hsc->hdmatx->XferCpltCallback = SMARTCARD_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsc->hdmatx->XferErrorCallback = SMARTCARD_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the SMARTCARD transmit DMA channel */
|
||||
tmp = (const uint32_t*)&pData;
|
||||
HAL_DMA_Start_IT(hsc->hdmatx, *(const uint32_t*)tmp, (uint32_t)&hsc->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_SMARTCARD_CLEAR_FLAG(hsc, SMARTCARD_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the SMARTCARD CR3 register */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be received
|
||||
* @note When the SMARTCARD parity is enabled (PCE = 1) the data received contain the parity bit.s
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Receive_DMA(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pRxBuffPtr = pData;
|
||||
hsc->RxXferSize = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Set the SMARTCARD DMA transfer complete callback */
|
||||
hsc->hdmarx->XferCpltCallback = SMARTCARD_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsc->hdmarx->XferErrorCallback = SMARTCARD_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
tmp = (uint32_t*)&pData;
|
||||
HAL_DMA_Start_IT(hsc->hdmarx, (uint32_t)&hsc->Instance->DR, *(uint32_t*)tmp, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
|
||||
__HAL_SMARTCARD_CLEAR_OREFLAG(hsc);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the SMARTCARD CR3 register */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_SMARTCARD_Abort(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->RxState and hsc->gState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Tx)
|
||||
* - 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_SMARTCARD_AbortTransmit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_SMARTCARD_AbortReceive(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - 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_SMARTCARD_Abort_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to SMARTCARD Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if SMARTCARD DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if SMARTCARD DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at SMARTCARD level */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* SMARTCARD Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* SMARTCARD Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if(AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Tx)
|
||||
* - 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_SMARTCARD_AbortTransmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA TX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hsc->hdmatx->XferAbortCallback function in case of error */
|
||||
hsc->hdmatx->XferAbortCallback(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Rx)
|
||||
* - 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_SMARTCARD_AbortReceive_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hsc->hdmarx->XferAbortCallback function in case of error */
|
||||
hsc->hdmarx->XferAbortCallback(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SMARTCARD interrupt request.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SMARTCARD_IRQHandler(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(hsc->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(hsc->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(hsc->Instance->CR3);
|
||||
uint32_t dmarequest = 0x00U;
|
||||
uint32_t errorflags = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if(errorflags == RESET)
|
||||
{
|
||||
/* SMARTCARD in mode Receiver -------------------------------------------------*/
|
||||
if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Receive_IT(hsc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some errors occur */
|
||||
if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* SMARTCARD parity error interrupt occurred ---------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_PE;
|
||||
}
|
||||
|
||||
/* SMARTCARD frame error interrupt occurred ----------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_FE;
|
||||
}
|
||||
|
||||
/* SMARTCARD noise error interrupt occurred ----------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_NE;
|
||||
}
|
||||
|
||||
/* SMARTCARD Over-Run interrupt occurred -------------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_ORE;
|
||||
}
|
||||
/* Call the Error call Back in case of Errors --------------------------*/
|
||||
if(hsc->ErrorCode != HAL_SMARTCARD_ERROR_NONE)
|
||||
{
|
||||
/* SMARTCARD in mode Receiver ----------------------------------------*/
|
||||
if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Receive_IT(hsc);
|
||||
}
|
||||
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
if(((hsc->ErrorCode & HAL_SMARTCARD_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the SMARTCARD state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
SMARTCARD_EndRxTransfer(hsc);
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_ErrorCallback() at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMAAbortOnError;
|
||||
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
hsc->hdmarx->XferAbortCallback(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non Blocking error : transfer could go on.
|
||||
Error is notified to user through user error callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* End if some error occurs */
|
||||
|
||||
/* SMARTCARD in mode Transmitter ------------------------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Transmit_IT(hsc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SMARTCARD in mode Transmitter (transmission end) -----------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
SMARTCARD_EndTransmit_IT(hsc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_TxCpltCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_TxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callback
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_RxCpltCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_RxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD error callback
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_ErrorCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_ErrorCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Transmit Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortTransmitCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortTransmitCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Receive Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortReceiveCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortReceiveCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief SMARTCARD State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SmartCard.
|
||||
(+) HAL_SMARTCARD_GetState() API can be helpful to check in run-time the state of the SmartCard peripheral.
|
||||
(+) HAL_SMARTCARD_GetError() check in run-time errors that could be occurred during communication.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the SMARTCARD handle state
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SMARTCARD_StateTypeDef HAL_SMARTCARD_GetState(const SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t temp1= 0x00U, temp2 = 0x00U;
|
||||
temp1 = hsc->gState;
|
||||
temp2 = hsc->RxState;
|
||||
|
||||
return (HAL_SMARTCARD_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SMARTCARD error code
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SMARTCARD.
|
||||
* @retval SMARTCARD Error Code
|
||||
*/
|
||||
uint32_t HAL_SMARTCARD_GetError(const SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
return hsc->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Private_Functions SMARTCARD Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval none
|
||||
*/
|
||||
void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Init the SMARTCARD Callback settings */
|
||||
hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
|
||||
}
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->TxXferCount = 0U;
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the SMARTCARD Transmit Complete Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->RxXferCount = 0U;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hsc->RxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_SMARTCARD_RxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
hsc->RxXferCount = 0U;
|
||||
hsc->TxXferCount = 0U;
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
|
||||
|
||||
/* Stop SMARTCARD DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
if((hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
SMARTCARD_EndTxTransfer(hsc);
|
||||
}
|
||||
|
||||
/* Stop SMARTCARD DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
if((hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
SMARTCARD_EndRxTransfer(hsc);
|
||||
}
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SMARTCARD Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param Flag Specifies the SMARTCARD flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart Tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while((__HAL_SMARTCARD_GET_FLAG(hsc, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout))
|
||||
{
|
||||
/* Disable TXE and RXNE interrupts for the interrupt process */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
hsc->gState= HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState= HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on SMARTCARD peripheral (following error detection or Transmit completion).
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* At end of Tx process, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on SMARTCARD peripheral (following error detection or Reception completion).
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
|
||||
/* Check that a Tx process is ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX)
|
||||
{
|
||||
hsc->Instance->DR = (uint8_t)(*hsc->pTxBuffPtr & 0xFFU);
|
||||
hsc->pTxBuffPtr++;
|
||||
|
||||
if(--hsc->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the SMARTCARD Transmit data register empty Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the SMARTCARD Transmit Complete Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable the SMARTCARD Transmit Complete Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Tx process is ended, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hsc->TxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_SMARTCARD_TxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
|
||||
/* Check that a Rx process is ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX)
|
||||
{
|
||||
*hsc->pRxBuffPtr = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU);
|
||||
hsc->pRxBuffPtr++;
|
||||
|
||||
if(--hsc->RxXferCount == 0U)
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the SMARTCARD Parity Error Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Rx process is completed, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hsc->RxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_SMARTCARD_RxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = (SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
if(hsc->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD 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 SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
if(hsc->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Tx communication abort callback, when initiated by user by a call to
|
||||
* HAL_SMARTCARD_AbortTransmit_IT API (Abort only Tx transfer)
|
||||
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
|
||||
* and leads to user Tx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Rx communication abort callback, when initiated by user by a call to
|
||||
* HAL_SMARTCARD_AbortReceive_IT API (Abort only Rx transfer)
|
||||
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
|
||||
* and leads to user Rx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the SMARTCARD peripheral
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
assert_param(IS_SMARTCARD_POLARITY(hsc->Init.CLKPolarity));
|
||||
assert_param(IS_SMARTCARD_PHASE(hsc->Init.CLKPhase));
|
||||
assert_param(IS_SMARTCARD_LASTBIT(hsc->Init.CLKLastBit));
|
||||
assert_param(IS_SMARTCARD_BAUDRATE(hsc->Init.BaudRate));
|
||||
assert_param(IS_SMARTCARD_WORD_LENGTH(hsc->Init.WordLength));
|
||||
assert_param(IS_SMARTCARD_STOPBITS(hsc->Init.StopBits));
|
||||
assert_param(IS_SMARTCARD_PARITY(hsc->Init.Parity));
|
||||
assert_param(IS_SMARTCARD_MODE(hsc->Init.Mode));
|
||||
assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState));
|
||||
|
||||
/* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the
|
||||
receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/*---------------------------- USART CR2 Configuration ---------------------*/
|
||||
tmpreg = hsc->Instance->CR2;
|
||||
/* Clear CLKEN, CPOL, CPHA and LBCL bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL));
|
||||
/* Configure the SMARTCARD Clock, CPOL, CPHA and LastBit -----------------------*/
|
||||
/* Set CPOL bit according to hsc->Init.CLKPolarity value */
|
||||
/* Set CPHA bit according to hsc->Init.CLKPhase value */
|
||||
/* Set LBCL bit according to hsc->Init.CLKLastBit value */
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(USART_CR2_CLKEN | hsc->Init.CLKPolarity |
|
||||
hsc->Init.CLKPhase| hsc->Init.CLKLastBit | hsc->Init.StopBits);
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
tmpreg = hsc->Instance->CR2;
|
||||
|
||||
/* Clear STOP[13:12] bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)USART_CR2_STOP);
|
||||
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(hsc->Init.StopBits);
|
||||
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = hsc->Instance->CR1;
|
||||
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \
|
||||
USART_CR1_RE));
|
||||
|
||||
/* Configure the SMARTCARD Word Length, Parity and mode:
|
||||
Set the M bits according to hsc->Init.WordLength value
|
||||
Set PCE and PS bits according to hsc->Init.Parity value
|
||||
Set TE and RE bits according to hsc->Init.Mode value */
|
||||
tmpreg |= (uint32_t)hsc->Init.WordLength | hsc->Init.Parity | hsc->Init.Mode;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(hsc->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if(hsc->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
1117
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_sram.c
Normal file
1117
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_sram.c
Normal file
@@ -0,0 +1,1117 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_sram.c
|
||||
* @author MCD Application Team
|
||||
* @brief SRAM HAL module driver.
|
||||
* This file provides a generic firmware to drive SRAM memories
|
||||
* mounted as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control SRAM memories. It uses the FSMC layer functions to interface
|
||||
with SRAM devices.
|
||||
The following sequence should be followed to configure the FSMC to interface
|
||||
with SRAM/PSRAM memories:
|
||||
|
||||
(#) Declare a SRAM_HandleTypeDef handle structure, for example:
|
||||
SRAM_HandleTypeDef hsram; and:
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Init" field with the allowed
|
||||
values of the structure member.
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Instance" field with a predefined
|
||||
base register instance for NOR or SRAM device
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Extended" field with a predefined
|
||||
base register instance for NOR or SRAM extended mode
|
||||
|
||||
(#) Declare two FSMC_NORSRAM_TimingTypeDef structures, for both normal and extended
|
||||
mode timings; for example:
|
||||
FSMC_NORSRAM_TimingTypeDef Timing and FSMC_NORSRAM_TimingTypeDef ExTiming;
|
||||
and fill its fields with the allowed values of the structure member.
|
||||
|
||||
(#) Initialize the SRAM Controller by calling the function HAL_SRAM_Init(). This function
|
||||
performs the following sequence:
|
||||
|
||||
(##) MSP hardware layer configuration using the function HAL_SRAM_MspInit()
|
||||
(##) Control register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Init()
|
||||
(##) Timing register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Timing_Init()
|
||||
(##) Extended mode Timing register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Extended_Timing_Init()
|
||||
(##) Enable the SRAM device using the macro __FSMC_NORSRAM_ENABLE()
|
||||
|
||||
(#) At this stage you can perform read/write accesses from/to the memory connected
|
||||
to the NOR/SRAM Bank. You can perform either polling or DMA transfer using the
|
||||
following APIs:
|
||||
(++) HAL_SRAM_Read()/HAL_SRAM_Write() for polling read/write access
|
||||
(++) HAL_SRAM_Read_DMA()/HAL_SRAM_Write_DMA() for DMA read/write transfer
|
||||
|
||||
(#) You can also control the SRAM device by calling the control APIs HAL_SRAM_WriteOperation_Enable()/
|
||||
HAL_SRAM_WriteOperation_Disable() to respectively enable/disable the SRAM write operation
|
||||
|
||||
(#) You can continuously monitor the SRAM device HAL state by calling the function
|
||||
HAL_SRAM_GetState()
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_SRAM_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : SRAM MspInit.
|
||||
(+) MspDeInitCallback : SRAM MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_SRAM_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : SRAM MspInit.
|
||||
(+) MspDeInitCallback : SRAM MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_SRAM_Init and if the state is HAL_SRAM_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_SRAM_Init
|
||||
and HAL_SRAM_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SRAM_Init and HAL_SRAM_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or 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_SRAM_RegisterCallback before calling HAL_SRAM_DeInit
|
||||
or HAL_SRAM_Init function.
|
||||
|
||||
When The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
|
||||
/** @defgroup SRAM SRAM
|
||||
* @brief SRAM driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup SRAM_Private_Functions SRAM Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void SRAM_DMACplt(DMA_HandleTypeDef *hdma);
|
||||
static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma);
|
||||
static void SRAM_DMAError(DMA_HandleTypeDef *hdma);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions SRAM Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to initialize/de-initialize
|
||||
the SRAM memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Performs the SRAM device initialization sequence
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param Timing Pointer to SRAM control timing structure
|
||||
* @param ExtTiming Pointer to SRAM extended mode timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram, FSMC_NORSRAM_TimingTypeDef *Timing,
|
||||
FSMC_NORSRAM_TimingTypeDef *ExtTiming)
|
||||
{
|
||||
/* Check the SRAM handle parameter */
|
||||
if ((hsram == NULL) || (hsram->Init.BurstAccessMode == FSMC_BURST_ACCESS_MODE_ENABLE))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hsram->State == HAL_SRAM_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsram->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
if (hsram->MspInitCallback == NULL)
|
||||
{
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
}
|
||||
hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
|
||||
hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsram->MspInitCallback(hsram);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_SRAM_MspInit(hsram);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize SRAM control Interface */
|
||||
(void)FSMC_NORSRAM_Init(hsram->Instance, &(hsram->Init));
|
||||
|
||||
/* Initialize SRAM timing Interface */
|
||||
(void)FSMC_NORSRAM_Timing_Init(hsram->Instance, Timing, hsram->Init.NSBank);
|
||||
|
||||
/* Initialize SRAM extended mode timing Interface */
|
||||
(void)FSMC_NORSRAM_Extended_Timing_Init(hsram->Extended, ExtTiming, hsram->Init.NSBank,
|
||||
hsram->Init.ExtendedMode);
|
||||
|
||||
/* Enable the NORSRAM device */
|
||||
__FSMC_NORSRAM_ENABLE(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Initialize the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs the SRAM device De-initialization sequence.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_DeInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
if (hsram->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hsram->MspDeInitCallback(hsram);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_SRAM_MspDeInit(hsram);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
|
||||
/* Configure the SRAM registers with their reset values */
|
||||
(void)FSMC_NORSRAM_DeInit(hsram->Instance, hsram->Extended, hsram->Init.NSBank);
|
||||
|
||||
/* Reset the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsram);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SRAM MSP Init.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsram);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SRAM MSP DeInit.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsram);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA transfer complete callback.
|
||||
* @param hdma pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdma);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_DMA_XferCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA transfer complete error callback.
|
||||
* @param hdma pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdma);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_DMA_XferErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group2 Input Output and memory control functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the SRAM memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads 8-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint8_t *psramaddress = (uint8_t *)pAddress;
|
||||
uint8_t *pdestbuff = pDstBuffer;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*pdestbuff = *psramaddress;
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 8-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint8_t *psramaddress = (uint8_t *)pAddress;
|
||||
uint8_t *psrcbuff = pSrcBuffer;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*psramaddress = *psrcbuff;
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads 16-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint16_t *pdestbuff = pDstBuffer;
|
||||
uint8_t limit;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Check if the size is a 32-bits multiple */
|
||||
limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != limit; size -= 2U)
|
||||
{
|
||||
*pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
|
||||
pdestbuff++;
|
||||
*pdestbuff = (uint16_t)(((*psramaddress) & 0xFFFF0000U) >> 16U);
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Read last 16-bits if size is not 32-bits multiple */
|
||||
if (limit != 0U)
|
||||
{
|
||||
*pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 16-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint16_t *psrcbuff = pSrcBuffer;
|
||||
uint8_t limit;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Check if the size is a 32-bits multiple */
|
||||
limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != limit; size -= 2U)
|
||||
{
|
||||
*psramaddress = (uint32_t)(*psrcbuff);
|
||||
psrcbuff++;
|
||||
*psramaddress |= ((uint32_t)(*psrcbuff) << 16U);
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Write last 16-bits if size is not 32-bits multiple */
|
||||
if (limit != 0U)
|
||||
{
|
||||
*psramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psramaddress) & 0xFFFF0000U);
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads 32-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint32_t *pdestbuff = pDstBuffer;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*pdestbuff = *psramaddress;
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 32-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint32_t *psrcbuff = pSrcBuffer;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*psramaddress = *psrcbuff;
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a Words data from the SRAM memory using DMA transfer.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Configure DMA user callbacks */
|
||||
if (state == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACplt;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACpltProt;
|
||||
}
|
||||
hsram->hdma->XferErrorCallback = SRAM_DMAError;
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)BufferSize);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a Words data buffer to SRAM memory using DMA transfer.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Configure DMA user callbacks */
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACplt;
|
||||
hsram->hdma->XferErrorCallback = SRAM_DMAError;
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)BufferSize);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User SRAM Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
|
||||
* @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_RegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
|
||||
pSRAM_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_RESET) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User SRAM Callback
|
||||
* SRAM Callback is redirected to the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
|
||||
* @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_UnRegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
|
||||
hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_ERR_CB_ID :
|
||||
hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (state == HAL_SRAM_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a User SRAM Callback for DMA transfers
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_RegisterDmaCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
|
||||
pSRAM_DmaCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
|
||||
hsram->DmaXferCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_ERR_CB_ID :
|
||||
hsram->DmaXferErrorCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsram);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group3 Control functions
|
||||
* @brief Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the SRAM interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically SRAM write operation.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_WriteOperation_Enable(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_PROTECTED)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Enable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Enable(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically SRAM write operation.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_WriteOperation_Disable(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Disable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_PROTECTED;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the SRAM controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the SRAM controller state
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SRAM_StateTypeDef HAL_SRAM_GetState(const SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
return hsram->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SRAM_Private_Functions SRAM Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM process complete callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMACplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferCpltCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferCpltCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM process complete callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_PROTECTED;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferCpltCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferCpltCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM error callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_ERROR;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferErrorCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferErrorCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK1 */
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_timebase_rtc_alarm_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL time base based on the hardware RTC_ALARM.
|
||||
*
|
||||
* This file override the native HAL time base functions (defined as weak)
|
||||
* to use the RTC ALARM for time base generation:
|
||||
* + Intializes the RTC peripheral to increment the seconds registers each 1ms
|
||||
* + The alarm is configured to assert an interrupt when the RTC reaches 1ms
|
||||
* + HAL_IncTick is called at each Alarm event and the time is reset to 00:00:00
|
||||
* + HSE (default), LSE or LSI can be selected as RTC clock source
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This file must be copied to the application folder and modified as follows:
|
||||
(#) Rename it to 'stm32f1xx_hal_timebase_rtc_alarm.c'
|
||||
(#) Add this file and the RTC HAL drivers to your project and uncomment
|
||||
HAL_RTC_MODULE_ENABLED define in stm32f1xx_hal_conf.h
|
||||
|
||||
[..]
|
||||
(@) HAL RTC alarm and HAL RTC wakeup drivers can’t be used with low power modes:
|
||||
The wake up capability of the RTC may be intrusive in case of prior low power mode
|
||||
configuration requiring different wake up sources.
|
||||
Application/Example behavior is no more guaranteed
|
||||
(@) The stm32f1xx_hal_timebase_tim use is recommended for the Applications/Examples
|
||||
requiring low power modes
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_TimeBase_RTC_Alarm_Template HAL TimeBase RTC Alarm Template
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Uncomment the line below to select the appropriate RTC Clock source for your application:
|
||||
+ RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision.
|
||||
+ RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing
|
||||
precision.
|
||||
+ RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing
|
||||
precision.
|
||||
*/
|
||||
#define RTC_CLOCK_SOURCE_HSE
|
||||
/* #define RTC_CLOCK_SOURCE_LSE */
|
||||
/* #define RTC_CLOCK_SOURCE_LSI */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
RTC_HandleTypeDef hRTC_Handle;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void RTC_Alarm_IRQHandler(void);
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the RTC_ALARMA as a time base source.
|
||||
* The time source is configured to have 1ms time base with a dedicated
|
||||
* Tick interrupt priority.
|
||||
* @note This function is called automatically at the beginning of program after
|
||||
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
|
||||
* @param TickPriority Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
#ifdef RTC_CLOCK_SOURCE_LSE
|
||||
/* Configue LSE as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
|
||||
#elif defined (RTC_CLOCK_SOURCE_LSI)
|
||||
/* Configue LSI as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
|
||||
#elif defined (RTC_CLOCK_SOURCE_HSE)
|
||||
/* Configue HSE as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128;
|
||||
#else
|
||||
#error Please select the RTC Clock source
|
||||
#endif /* RTC_CLOCK_SOURCE_LSE */
|
||||
status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable RTC Clock */
|
||||
__HAL_RCC_RTC_ENABLE();
|
||||
|
||||
/* Configure RTC time base to 10Khz */
|
||||
hRTC_Handle.Instance = RTC;
|
||||
hRTC_Handle.Init.AsynchPrediv = (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC) / 10000) - 1;
|
||||
hRTC_Handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
|
||||
status = HAL_RTC_Init(&hRTC_Handle);
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
|
||||
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF);
|
||||
|
||||
counter = 0U;
|
||||
/* Wait till RTC ALRAF flag is set and if Time out is reached exit */
|
||||
while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF) != RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->ALRH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->ALRL = 0x09U;
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_IT();
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->CNTH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->CNTL = 0x00U;
|
||||
|
||||
/* Configure the Alarm interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
counter = 0U;
|
||||
while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the RTC global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
|
||||
|
||||
/* Configure the SysTick IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority ,0U);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling RTC ALARM interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable RTC ALARM update Interrupt */
|
||||
__HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling RTC ALARM interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->CNTH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->CNTL = 0x00U;
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW | RTC_FLAG_ALRAF));
|
||||
|
||||
/* Enable RTC ALARM Update interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ALARM A Event Callback in non blocking mode
|
||||
* @note This function is called when RTC_ALARM interrupt took place, inside
|
||||
* RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param hrtc RTC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
HAL_IncTick();
|
||||
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTH, 0x00U);
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTL, 0x00U);
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
|
||||
/* 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 (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles RTC ALARM interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void RTC_Alarm_IRQHandler(void)
|
||||
{
|
||||
HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_timebase_tim_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL time base based on the hardware TIM Template.
|
||||
*
|
||||
* This file overrides the native HAL time base functions (defined as weak)
|
||||
* the TIM time base:
|
||||
* + Initializes the TIM peripheral generate a Period elapsed Event each 1ms
|
||||
* + HAL_IncTick is called inside HAL_TIM_PeriodElapsedCallback ie each 1ms
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 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
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup HAL_TimeBase_TIM
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
TIM_HandleTypeDef TimHandle;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void TIM2_IRQHandler(void);
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the TIM2 as a time base source.
|
||||
* The time source is configured to have 1ms time base with a dedicated
|
||||
* Tick interrupt priority.
|
||||
* @note This function is called automatically at the beginning of program after
|
||||
* reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
|
||||
* @param TickPriority Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
RCC_ClkInitTypeDef clkconfig;
|
||||
uint32_t uwTimclock, uwAPB1Prescaler = 0U;
|
||||
uint32_t uwPrescalerValue = 0U;
|
||||
uint32_t pFLatency;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
|
||||
/* Enable TIM2 clock */
|
||||
__HAL_RCC_TIM2_CLK_ENABLE();
|
||||
|
||||
/* Get clock configuration */
|
||||
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
|
||||
|
||||
/* Get APB1 prescaler */
|
||||
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
|
||||
|
||||
/* Compute TIM2 clock */
|
||||
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
|
||||
{
|
||||
uwTimclock = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
uwTimclock = 2 * HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
/* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */
|
||||
uwPrescalerValue = (uint32_t)((uwTimclock / 1000000U) - 1U);
|
||||
|
||||
/* Initialize TIM2 */
|
||||
TimHandle.Instance = TIM2;
|
||||
|
||||
/* Initialize TIMx peripheral as follow:
|
||||
+ Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base.
|
||||
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
|
||||
+ ClockDivision = 0
|
||||
+ Counter direction = Up
|
||||
*/
|
||||
TimHandle.Init.Period = (1000000U / 1000U) - 1U;
|
||||
TimHandle.Init.Prescaler = uwPrescalerValue;
|
||||
TimHandle.Init.ClockDivision = 0U;
|
||||
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
status = HAL_TIM_Base_Init(&TimHandle);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Start the TIM time Base generation in interrupt mode */
|
||||
status = HAL_TIM_Base_Start_IT(&TimHandle);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM2 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
/*Configure the TIM2 IRQ priority */
|
||||
HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority ,0);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling TIM2 update interrupt.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable TIM2 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&TimHandle, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling TIM2 update interrupt.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
/* Enable TIM2 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM2 interrupt took place, inside
|
||||
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param htim TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
HAL_IncTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void TIM2_IRQHandler(void)
|
||||
{
|
||||
HAL_TIM_IRQHandler(&TimHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
2812
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_usart.c
Normal file
2812
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_usart.c
Normal file
@@ -0,0 +1,2812 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_usart.c
|
||||
* @author MCD Application Team
|
||||
* @brief USART HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Universal Synchronous/Asynchronous Receiver Transmitter
|
||||
* Peripheral (USART).
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control 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 USART HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a USART_HandleTypeDef handle structure (eg. USART_HandleTypeDef husart).
|
||||
(#) Initialize the USART low level resources by implementing the HAL_USART_MspInit() API:
|
||||
(##) Enable the USARTx interface clock.
|
||||
(##) USART pins configuration:
|
||||
(+++) Enable the clock for the USART GPIOs.
|
||||
(+++) Configure the USART pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_USART_Transmit_IT(),
|
||||
HAL_USART_Receive_IT() and HAL_USART_TransmitReceive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_USART_Transmit_DMA()
|
||||
HAL_USART_Receive_DMA() and HAL_USART_TransmitReceive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the USART DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
|
||||
flow control and Mode(Receiver/Transmitter) in the husart Init structure.
|
||||
|
||||
(#) Initialize the USART registers by calling the HAL_USART_Init() API:
|
||||
(++) These APIs configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_USART_MspInit(&husart) API.
|
||||
|
||||
-@@- The specific USART interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_USART_ENABLE_IT() and __HAL_USART_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
(#) Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_USART_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_USART_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_USART_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_USART_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_USART_Receive_IT()
|
||||
(+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_USART_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_USART_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_USART_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_USART_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_USART_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_USART_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_USART_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_USART_DMAStop()
|
||||
|
||||
*** USART HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in USART HAL driver.
|
||||
|
||||
(+) __HAL_USART_ENABLE: Enable the USART peripheral
|
||||
(+) __HAL_USART_DISABLE: Disable the USART peripheral
|
||||
(+) __HAL_USART_GET_FLAG : Check whether the specified USART flag is set or not
|
||||
(+) __HAL_USART_CLEAR_FLAG : Clear the specified USART pending flag
|
||||
(+) __HAL_USART_ENABLE_IT: Enable the specified USART interrupt
|
||||
(+) __HAL_USART_DISABLE_IT: Disable the specified USART interrupt
|
||||
|
||||
[..]
|
||||
(@) You can refer to the USART HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_USART_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function @ref HAL_USART_RegisterCallback() to register a user callback.
|
||||
Function @ref HAL_USART_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) TxRxCpltCallback : Tx Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) MspInitCallback : USART MspInit.
|
||||
(+) MspDeInitCallback : USART MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function @ref HAL_USART_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
@ref HAL_USART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) TxRxCpltCallback : Tx Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) MspInitCallback : USART MspInit.
|
||||
(+) MspDeInitCallback : USART MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the @ref HAL_USART_Init() and when the state is HAL_USART_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples @ref HAL_USART_TxCpltCallback(), @ref HAL_USART_RxHalfCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the @ref HAL_USART_Init()
|
||||
and @ref HAL_USART_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the @ref HAL_USART_Init() and @ref HAL_USART_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_USART_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_USART_STATE_READY or HAL_USART_STATE_RESET state, thus registered (user)
|
||||
MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using @ref HAL_USART_RegisterCallback() before calling @ref HAL_USART_DeInit()
|
||||
or @ref HAL_USART_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_USART_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
[..]
|
||||
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
the possible USART frame formats are as listed in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | USART frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 0 | 0 | | SB | 8 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 0 | 1 | | SB | 7 bit data | PB | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 0 | | SB | 9 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | STB | |
|
||||
+-------------------------------------------------------------+
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USART USART
|
||||
* @brief HAL USART Synchronous module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup USART_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
#define DUMMY_DATA 0xFFFFU
|
||||
#define USART_TIMEOUT_VALUE 22000U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @addtogroup USART_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
static void USART_EndTxTransfer(USART_HandleTypeDef *husart);
|
||||
static void USART_EndRxTransfer(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart);
|
||||
static void USART_SetConfig(USART_HandleTypeDef *husart);
|
||||
static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
|
||||
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup USART_Exported_Functions USART Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group1 USART Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USART
|
||||
in asynchronous and in synchronous modes.
|
||||
(+) For the asynchronous mode only these parameters can be configured:
|
||||
(++) Baud Rate
|
||||
(++) Word Length
|
||||
(++) Stop Bit
|
||||
(++) Parity: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
please refer to Reference manual for possible USART frame formats.
|
||||
(++) USART polarity
|
||||
(++) USART phase
|
||||
(++) USART LastBit
|
||||
(++) Receiver/transmitter modes
|
||||
|
||||
[..]
|
||||
The HAL_USART_Init() function follows the USART synchronous configuration
|
||||
procedures (details for the procedures are available in reference manuals
|
||||
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the USART mode according to the specified
|
||||
* parameters in the USART_InitTypeDef and initialize the associated handle.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Check the USART handle allocation */
|
||||
if (husart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
|
||||
if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
husart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
USART_InitCallbacksToDefault(husart);
|
||||
|
||||
if (husart->MspInitCallback == NULL)
|
||||
{
|
||||
husart->MspInitCallback = HAL_USART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
husart->MspInitCallback(husart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_USART_MspInit(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_BUSY;
|
||||
|
||||
/* Set the USART Communication parameters */
|
||||
USART_SetConfig(husart);
|
||||
|
||||
/* In USART mode, the following bits must be kept cleared:
|
||||
- LINEN bit in the USART_CR2 register
|
||||
- HDSEL, SCEN and IREN bits in the USART_CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR2, USART_CR2_LINEN);
|
||||
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_USART_ENABLE(husart);
|
||||
|
||||
/* Initialize the USART state */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the USART peripheral.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Check the USART handle allocation */
|
||||
if (husart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
|
||||
husart->State = HAL_USART_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_USART_DISABLE(husart);
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
if (husart->MspDeInitCallback == NULL)
|
||||
{
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
husart->MspDeInitCallback(husart);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_USART_MspDeInit(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART MSP Init.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_MspInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART MSP DeInit.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User USART Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_USART_RegisterCallback() may be called before HAL_USART_Init() in HAL_USART_STATE_RESET
|
||||
* to register callbacks for HAL_USART_MSPINIT_CB_ID and HAL_USART_MSPDEINIT_CB_ID
|
||||
* @param husart usart handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
+ */
|
||||
HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID,
|
||||
pUSART_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
|
||||
husart->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_COMPLETE_CB_ID :
|
||||
husart->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
|
||||
husart->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_COMPLETE_CB_ID :
|
||||
husart->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_RX_COMPLETE_CB_ID :
|
||||
husart->TxRxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_ERROR_CB_ID :
|
||||
husart->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_ABORT_COMPLETE_CB_ID :
|
||||
husart->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USART Callback
|
||||
* USART callaback is redirected to the weak predefined callback
|
||||
* @note The HAL_USART_UnRegisterCallback() may be called before HAL_USART_Init() in HAL_USART_STATE_RESET
|
||||
* to un-register callbacks for HAL_USART_MSPINIT_CB_ID and HAL_USART_MSPDEINIT_CB_ID
|
||||
* @param husart usart handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
|
||||
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_COMPLETE_CB_ID :
|
||||
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
|
||||
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_COMPLETE_CB_ID :
|
||||
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_RX_COMPLETE_CB_ID :
|
||||
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_ERROR_CB_ID :
|
||||
husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_ABORT_COMPLETE_CB_ID :
|
||||
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = HAL_USART_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = HAL_USART_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group2 IO operation functions
|
||||
* @brief USART Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the USART synchronous
|
||||
data transfers.
|
||||
|
||||
[..]
|
||||
The USART supports master mode only: it cannot receive or send data related to an input
|
||||
clock (SCLK is always an output).
|
||||
|
||||
(#) 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 API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated USART IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback()
|
||||
user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_USART_ErrorCallback() user callback will be executed when a communication
|
||||
error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_USART_Transmit() in simplex mode
|
||||
(++) HAL_USART_Receive() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive() in full duplex mode
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_USART_Transmit_IT()in simplex mode
|
||||
(++) HAL_USART_Receive_IT() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive_IT() in full duplex mode
|
||||
(++) HAL_USART_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_USART_Transmit_DMA()in simplex mode
|
||||
(++) HAL_USART_Receive_DMA() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive_DMA() in full duplex mode
|
||||
(++) HAL_USART_DMAPause()
|
||||
(++) HAL_USART_DMAResume()
|
||||
(++) HAL_USART_DMAStop()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_USART_TxHalfCpltCallback()
|
||||
(++) HAL_USART_TxCpltCallback()
|
||||
(++) HAL_USART_RxHalfCpltCallback()
|
||||
(++) HAL_USART_RxCpltCallback()
|
||||
(++) HAL_USART_ErrorCallback()
|
||||
(++) HAL_USART_TxRxCpltCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(++) HAL_USART_Abort()
|
||||
(++) HAL_USART_Abort_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_USART_Abort_IT), a Abort Complete Callbacks is provided:
|
||||
(++) HAL_USART_AbortCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_USART_ErrorCallback() user callback is executed. Transfer is kept ongoing on USART side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(++) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_USART_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in blocking mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint8_t *ptxdata8bits;
|
||||
const uint16_t *ptxdata16bits;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
ptxdata8bits = NULL;
|
||||
ptxdata16bits = (const uint16_t *) pTxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptxdata8bits = pTxData;
|
||||
ptxdata16bits = NULL;
|
||||
}
|
||||
|
||||
while (husart->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait for TXE flag in order to write data in DR */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (ptxdata8bits == NULL)
|
||||
{
|
||||
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
|
||||
ptxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
|
||||
ptxdata8bits++;
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
}
|
||||
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Receive an amount of data in blocking mode.
|
||||
* @note To receive synchronous data, dummy data are simultaneously transmitted.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *prxdata8bits;
|
||||
uint16_t *prxdata16bits;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
prxdata8bits = NULL;
|
||||
prxdata16bits = (uint16_t *) pRxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
prxdata8bits = pRxData;
|
||||
prxdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while (husart->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send dummy byte in order to generate the
|
||||
* clock for the slave to send data.
|
||||
* Whatever the frame length (7, 8 or 9-bit long), the same dummy value
|
||||
* can be written for all the cases. */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
|
||||
|
||||
/* Wait until RXNE flag is set to receive the byte */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
if (prxdata8bits == NULL)
|
||||
{
|
||||
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
prxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
|
||||
}
|
||||
prxdata8bits++;
|
||||
}
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (blocking mode).
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received).
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *prxdata8bits;
|
||||
uint16_t *prxdata16bits;
|
||||
const uint8_t *ptxdata8bits;
|
||||
const uint16_t *ptxdata16bits;
|
||||
uint16_t rxdatacount;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pTxData and pRxData buffers provided as input parameter
|
||||
should be aligned on a u16 frontier, as data to be filled into TDR/retrieved from RDR will be
|
||||
handled through a u16 cast. */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
if (((((uint32_t)pTxData) & 1U) != 0U) || ((((uint32_t)pRxData) & 1U) != 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->RxXferSize = Size;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
prxdata8bits = NULL;
|
||||
ptxdata8bits = NULL;
|
||||
ptxdata16bits = (const uint16_t *) pTxData;
|
||||
prxdata16bits = (uint16_t *) pRxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
prxdata8bits = pRxData;
|
||||
ptxdata8bits = pTxData;
|
||||
ptxdata16bits = NULL;
|
||||
prxdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Check the remain data to be received */
|
||||
/* rxdatacount is a temporary variable for MISRAC2012-Rule-13.5 */
|
||||
rxdatacount = husart->RxXferCount;
|
||||
while ((husart->TxXferCount > 0U) || (rxdatacount > 0U))
|
||||
{
|
||||
if (husart->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait for TXE flag in order to write data in DR */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
if (ptxdata8bits == NULL)
|
||||
{
|
||||
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
|
||||
ptxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
|
||||
ptxdata8bits++;
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
}
|
||||
|
||||
if (husart->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait for RXNE Flag */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (prxdata8bits == NULL)
|
||||
{
|
||||
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
prxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
|
||||
}
|
||||
|
||||
prxdata8bits++;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
rxdatacount = husart->RxXferCount;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in non-blocking mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
* @note The USART errors are not managed to avoid the overrun error.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* The USART Error Interrupts: (Frame error, Noise error, Overrun error)
|
||||
are not managed by the USART transmit process to avoid the overrun interrupt
|
||||
when the USART mode is configured for transmit and receive "USART_MODE_TX_RX"
|
||||
to benefit for the frame error and noise interrupts the USART mode should be
|
||||
configured only for transmit "USART_MODE_TX"
|
||||
The __HAL_USART_ENABLE_IT(husart, USART_IT_ERR) can be used to enable the Frame error,
|
||||
Noise error interrupt */
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the USART Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Receive an amount of data in non-blocking mode.
|
||||
* @note To receive synchronous data, dummy data are simultaneously transmitted.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error and Data Register not empty Interrupts */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable the USART Data Register not empty Interrupts */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Send dummy byte in order to generate the clock for the slave to send data */
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x01FF);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (non-blocking).
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the USART Data Register not empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the USART Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* Set the USART DMA transfer complete callback */
|
||||
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pTxData;
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Receive an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
* @note The USART DMA transmit channel must be configured in order to generate the clock for the slave.
|
||||
* @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->pTxBuffPtr = pRxData;
|
||||
husart->TxXferSize = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Set the USART DMA Rx transfer complete callback */
|
||||
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Rx transfer error callback */
|
||||
husart->hdmarx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Set the USART Tx DMA transfer complete callback as NULL because the communication closing
|
||||
is performed in DMA reception complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = NULL;
|
||||
husart->hdmatx->XferCpltCallback = NULL;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART receive DMA channel */
|
||||
tmp = (uint32_t *)&pRxData;
|
||||
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(uint32_t *)tmp, Size);
|
||||
|
||||
/* Enable the USART transmit DMA channel: the transmit channel is used in order
|
||||
to generate in the non-blocking mode the clock to the slave device,
|
||||
this mode isn't a simplex receive mode but a full-duplex receive one */
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: mandatory for the second transfer */
|
||||
__HAL_USART_CLEAR_OREFLAG(husart);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Transmit Receive an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received/sent.
|
||||
* @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX_RX;
|
||||
|
||||
/* Set the USART DMA Rx transfer complete callback */
|
||||
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Tx transfer complete callback */
|
||||
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Tx transfer error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the USART DMA Rx transfer error callback */
|
||||
husart->hdmarx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART receive DMA channel */
|
||||
tmp = (uint32_t *)&pRxData;
|
||||
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(const uint32_t *)tmp, Size);
|
||||
|
||||
/* Enable the USART transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pTxData;
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
|
||||
|
||||
/* Clear the Overrun flag: mandatory for the second transfer in circular mode */
|
||||
__HAL_USART_CLEAR_OREFLAG(husart);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
/* Disable the USART DMA Tx request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
/* Enable the USART DMA Tx request */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL USART API under callbacks HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Stop USART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
USART_EndTxTransfer(husart);
|
||||
|
||||
/* Abort the USART DMA Tx channel */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(husart->hdmatx);
|
||||
}
|
||||
|
||||
/* Disable the USART Tx DMA request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
/* Stop USART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
USART_EndRxTransfer(husart);
|
||||
|
||||
/* Abort the USART DMA Rx channel */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(husart->hdmarx);
|
||||
}
|
||||
|
||||
/* Disable the USART Rx DMA request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (blocking mode).
|
||||
* @param husart USART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx,
|
||||
* as described by TransferType parameter) started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP 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_USART_Abort(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the USART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the USART DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(husart->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(husart->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Reset Handle ErrorCode to No Error */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (Interrupt mode).
|
||||
* @param husart USART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx,
|
||||
* as described by TransferType parameter) started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP 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_USART_Abort_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to USART Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if USART DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if USART DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at USART level */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the USART DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* USART Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK)
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* USART Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if (AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USART interrupt request.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_USART_IRQHandler(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(husart->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(husart->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(husart->Instance->CR3);
|
||||
uint32_t errorflags = 0x00U;
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if (errorflags == RESET)
|
||||
{
|
||||
/* USART in mode Receiver -------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
USART_Receive_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* If some errors occur */
|
||||
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* USART parity error interrupt occurred ----------------------------------*/
|
||||
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_PE;
|
||||
}
|
||||
|
||||
/* USART noise error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_NE;
|
||||
}
|
||||
|
||||
/* USART frame error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_FE;
|
||||
}
|
||||
|
||||
/* USART Over-Run interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_ORE;
|
||||
}
|
||||
|
||||
if (husart->ErrorCode != HAL_USART_ERROR_NONE)
|
||||
{
|
||||
/* USART in mode Receiver -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
USART_Receive_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
}
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if (((husart->ErrorCode & HAL_USART_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Set the USART state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
USART_EndRxTransfer(husart);
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback :
|
||||
will lead to call HAL_USART_ErrorCallback() at end of DMA abort procedure */
|
||||
husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError;
|
||||
|
||||
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
husart->hdmarx->XferAbortCallback(husart->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* USART in mode Transmitter -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
USART_Transmit_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* USART in mode Transmitter (transmission end) ----------------------------*/
|
||||
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
USART_EndTransmit_IT(husart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_RxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_RxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx/Rx Transfers completed callback for the non-blocking process.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxRxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART error callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART Abort Complete callback.
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief USART State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to return the State of
|
||||
USART communication
|
||||
process, return Peripheral Errors occurred during communication process
|
||||
(+) HAL_USART_GetState() API can be helpful to check in run-time the state
|
||||
of the USART peripheral.
|
||||
(+) HAL_USART_GetError() check in run-time errors that could be occurred during
|
||||
communication.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the USART state.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_USART_StateTypeDef HAL_USART_GetState(const USART_HandleTypeDef *husart)
|
||||
{
|
||||
return husart->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the USART error code
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART.
|
||||
* @retval USART Error Code
|
||||
*/
|
||||
uint32_t HAL_USART_GetError(const USART_HandleTypeDef *husart)
|
||||
{
|
||||
return husart->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Private_Functions USART Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param husart USART handle.
|
||||
* @retval none
|
||||
*/
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Init the USART Callback settings */
|
||||
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
}
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
husart->TxXferCount = 0U;
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the USART Transmit Complete Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
}
|
||||
/* DMA Circular mode */
|
||||
else
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Complete Callback */
|
||||
husart->TxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Complete Callback */
|
||||
HAL_USART_TxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART transmit process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Half Complete Callback */
|
||||
husart->TxHalfCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Half Complete Callback */
|
||||
HAL_USART_TxHalfCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the Transmit/receiver request by clearing the DMAT/DMAR bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* The USART state is HAL_USART_STATE_BUSY_RX */
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
/* The USART state is HAL_USART_STATE_BUSY_TX_RX */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
/* DMA circular mode */
|
||||
else
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
/* The USART state is HAL_USART_STATE_BUSY_TX_RX */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART receive process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Half Complete Callback */
|
||||
husart->RxHalfCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Half Complete Callback */
|
||||
HAL_USART_RxHalfCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
husart->RxXferCount = 0x00U;
|
||||
husart->TxXferCount = 0x00U;
|
||||
|
||||
/* Stop USART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
USART_EndTxTransfer(husart);
|
||||
}
|
||||
|
||||
/* Stop USART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
USART_EndRxTransfer(husart);
|
||||
}
|
||||
|
||||
husart->ErrorCode |= HAL_USART_ERROR_DMA;
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USART Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param Flag specifies the USART flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Tickstart Tick start value.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
|
||||
{
|
||||
/* Disable the USART Transmit Complete Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on USART peripheral (following error detection or Transmit completion).
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_EndTxTransfer(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* At end of Tx process, restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on USART peripheral (following error detection or Reception completion).
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_EndRxTransfer(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* At end of Rx process, restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
husart->RxXferCount = 0x00U;
|
||||
husart->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
if (husart->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART 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 USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
if (husart->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in non-blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
* @note The USART errors are not managed to avoid the overrun error.
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
tmp = (const uint16_t *) husart->pTxBuffPtr;
|
||||
husart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
|
||||
husart->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
if (--husart->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART Transmit data register empty Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the USART Transmit Complete Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable the USART Transmit Complete Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Complete Callback */
|
||||
husart->TxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Complete Callback */
|
||||
HAL_USART_TxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Receive an amount of data in non-blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint8_t *pdata8bits;
|
||||
uint16_t *pdata16bits;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (uint16_t *) husart->pRxBuffPtr;
|
||||
*pdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
husart->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = (uint8_t *) husart->pRxBuffPtr;
|
||||
pdata16bits = NULL;
|
||||
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
|
||||
husart->pRxBuffPtr += 1U;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
|
||||
if (husart->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send dummy byte in order to generate the clock for the slave to send the next data.
|
||||
* Whatever the frame length (7, 8 or 9-bit long), the same dummy value
|
||||
* can be written for all the cases. */
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send receive an amount of data in full-duplex mode (non-blocking).
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
const uint16_t *pdatatx16bits;
|
||||
uint16_t *pdatarx16bits;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX_RX)
|
||||
{
|
||||
if (husart->TxXferCount != 0x00U)
|
||||
{
|
||||
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE) != RESET)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdatatx16bits = (const uint16_t *) husart->pTxBuffPtr;
|
||||
husart->Instance->DR = (uint16_t)(*pdatatx16bits & (uint16_t)0x01FF);
|
||||
husart->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
|
||||
/* Check the latest data transmitted */
|
||||
if (husart->TxXferCount == 0U)
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (husart->RxXferCount != 0x00U)
|
||||
{
|
||||
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXNE) != RESET)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdatarx16bits = (uint16_t *) husart->pRxBuffPtr;
|
||||
*pdatarx16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
husart->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
husart->pRxBuffPtr += 1U;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the latest data received */
|
||||
if (husart->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the USART peripheral.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_SetConfig(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity));
|
||||
assert_param(IS_USART_PHASE(husart->Init.CLKPhase));
|
||||
assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit));
|
||||
assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate));
|
||||
assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength));
|
||||
assert_param(IS_USART_STOPBITS(husart->Init.StopBits));
|
||||
assert_param(IS_USART_PARITY(husart->Init.Parity));
|
||||
assert_param(IS_USART_MODE(husart->Init.Mode));
|
||||
|
||||
/* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the
|
||||
receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/*---------------------------- USART CR2 Configuration ---------------------*/
|
||||
tmpreg = husart->Instance->CR2;
|
||||
/* Clear CLKEN, CPOL, CPHA and LBCL bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP));
|
||||
/* Configure the USART Clock, CPOL, CPHA and LastBit -----------------------*/
|
||||
/* Set CPOL bit according to husart->Init.CLKPolarity value */
|
||||
/* Set CPHA bit according to husart->Init.CLKPhase value */
|
||||
/* Set LBCL bit according to husart->Init.CLKLastBit value */
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to husart->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(USART_CLOCK_ENABLE | husart->Init.CLKPolarity |
|
||||
husart->Init.CLKPhase | husart->Init.CLKLastBit | husart->Init.StopBits);
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(husart->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = husart->Instance->CR1;
|
||||
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Configure the USART Word Length, Parity and mode:
|
||||
Set the M bits according to husart->Init.WordLength value
|
||||
Set PCE and PS bits according to husart->Init.Parity value
|
||||
Set TE and RE bits according to husart->Init.Mode value
|
||||
*/
|
||||
tmpreg |= (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(husart->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if (husart->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_wwdg.c
|
||||
* @author MCD Application Team
|
||||
* @brief WWDG HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Window Watchdog (WWDG) peripheral:
|
||||
* + Initialization and Configuration functions
|
||||
* + IO operation 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
|
||||
==============================================================================
|
||||
##### WWDG Specific features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
Once enabled the WWDG generates a system reset on expiry of a programmed
|
||||
time period, unless the program refreshes the counter (T[6;0] downcounter)
|
||||
before reaching 0x3F value (i.e. a reset is generated when the counter
|
||||
value rolls down from 0x40 to 0x3F).
|
||||
|
||||
(+) An MCU reset is also generated if the counter value is refreshed
|
||||
before the counter has reached the refresh window value. This
|
||||
implies that the counter must be refreshed in a limited window.
|
||||
(+) Once enabled the WWDG cannot be disabled except by a system reset.
|
||||
(+) If required by application, an Early Wakeup Interrupt can be triggered
|
||||
in order to be warned before WWDG expiration. The Early Wakeup Interrupt
|
||||
(EWI) can be used if specific safety operations or data logging must
|
||||
be performed before the actual reset is generated. When the downcounter
|
||||
reaches 0x40, interrupt occurs. This mechanism requires WWDG interrupt
|
||||
line to be enabled in NVIC. Once enabled, EWI interrupt cannot be
|
||||
disabled except by a system reset.
|
||||
(+) WWDGRST flag in RCC CSR register can be used to inform when a WWDG
|
||||
reset occurs.
|
||||
(+) The WWDG counter input clock is derived from the APB clock divided
|
||||
by a programmable prescaler.
|
||||
(+) WWDG clock (Hz) = PCLK1 / (4096 * Prescaler)
|
||||
(+) WWDG timeout (mS) = 1000 * (T[5;0] + 1) / WWDG clock (Hz)
|
||||
where T[5;0] are the lowest 6 bits of Counter.
|
||||
(+) WWDG Counter refresh is allowed between the following limits :
|
||||
(++) min time (mS) = 1000 * (Counter - Window) / WWDG clock
|
||||
(++) max time (mS) = 1000 * (Counter - 0x40) / WWDG clock
|
||||
(+) Typical values:
|
||||
(++) Counter min (T[5;0] = 0x00) at 36MHz (PCLK1) with zero prescaler:
|
||||
max timeout before reset: approximately 910us
|
||||
(++) Counter max (T[5;0] = 0x3F) at 36MHz (PCLK1) with prescaler
|
||||
dividing by 8:
|
||||
max timeout before reset: approximately 58.25ms
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
|
||||
*** Common driver usage ***
|
||||
===========================
|
||||
|
||||
[..]
|
||||
(+) Enable WWDG APB1 clock using __HAL_RCC_WWDG_CLK_ENABLE().
|
||||
(+) Configure the WWDG prescaler, refresh window value, counter value and early
|
||||
interrupt status using HAL_WWDG_Init() function. This will automatically
|
||||
enable WWDG and start its downcounter. Time reference can be taken from
|
||||
function exit. Care must be taken to provide a counter value
|
||||
greater than 0x40 to prevent generation of immediate reset.
|
||||
(+) If the Early Wakeup Interrupt (EWI) feature is enabled, an interrupt is
|
||||
generated when the counter reaches 0x40. When HAL_WWDG_IRQHandler is
|
||||
triggered by the interrupt service routine, flag will be automatically
|
||||
cleared and HAL_WWDG_WakeupCallback user callback will be executed. User
|
||||
can add his own code by customization of callback HAL_WWDG_WakeupCallback.
|
||||
(+) Then the application program must refresh the WWDG counter at regular
|
||||
intervals during normal operation to prevent an MCU reset, using
|
||||
HAL_WWDG_Refresh() function. This operation must occur only when
|
||||
the counter is lower than the refresh window value already programmed.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_WWDG_REGISTER_CALLBACKS when set to 1 allows
|
||||
the user to configure dynamically the driver callbacks. Use Functions
|
||||
HAL_WWDG_RegisterCallback() to register a user callback.
|
||||
|
||||
(+) Function HAL_WWDG_RegisterCallback() allows to register following
|
||||
callbacks:
|
||||
(++) EwiCallback : callback for Early WakeUp Interrupt.
|
||||
(++) MspInitCallback : WWDG MspInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
(+) Use function HAL_WWDG_UnRegisterCallback() to reset a callback to
|
||||
the default weak (surcharged) function. HAL_WWDG_UnRegisterCallback()
|
||||
takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) EwiCallback : callback for Early WakeUp Interrupt.
|
||||
(++) MspInitCallback : WWDG MspInit.
|
||||
|
||||
[..]
|
||||
When calling HAL_WWDG_Init function, callbacks are reset to the
|
||||
corresponding legacy weak (surcharged) functions:
|
||||
HAL_WWDG_EarlyWakeupCallback() and HAL_WWDG_MspInit() only if they have
|
||||
not been registered before.
|
||||
|
||||
[..]
|
||||
When compilation define USE_HAL_WWDG_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
*** WWDG HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of available macros in WWDG HAL driver.
|
||||
(+) __HAL_WWDG_ENABLE: Enable the WWDG peripheral
|
||||
(+) __HAL_WWDG_GET_FLAG: Get the selected WWDG's flag status
|
||||
(+) __HAL_WWDG_CLEAR_FLAG: Clear the WWDG's pending flags
|
||||
(+) __HAL_WWDG_ENABLE_IT: Enable the WWDG early wakeup interrupt
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
/** @defgroup WWDG WWDG
|
||||
* @brief WWDG HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions WWDG Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions_Group1 Initialization and Configuration functions
|
||||
* @brief Initialization and Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and start the WWDG according to the specified parameters
|
||||
in the WWDG_InitTypeDef of associated handle.
|
||||
(+) Initialize the WWDG MSP.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the WWDG according to the specified.
|
||||
* parameters in the WWDG_InitTypeDef of associated handle.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Check the WWDG handle allocation */
|
||||
if (hwwdg == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_WWDG_ALL_INSTANCE(hwwdg->Instance));
|
||||
assert_param(IS_WWDG_PRESCALER(hwwdg->Init.Prescaler));
|
||||
assert_param(IS_WWDG_WINDOW(hwwdg->Init.Window));
|
||||
assert_param(IS_WWDG_COUNTER(hwwdg->Init.Counter));
|
||||
assert_param(IS_WWDG_EWI_MODE(hwwdg->Init.EWIMode));
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/* Reset Callback pointers */
|
||||
if (hwwdg->EwiCallback == NULL)
|
||||
{
|
||||
hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
|
||||
}
|
||||
|
||||
if (hwwdg->MspInitCallback == NULL)
|
||||
{
|
||||
hwwdg->MspInitCallback = HAL_WWDG_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hwwdg->MspInitCallback(hwwdg);
|
||||
#else
|
||||
/* Init the low level hardware */
|
||||
HAL_WWDG_MspInit(hwwdg);
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
|
||||
/* Set WWDG Counter */
|
||||
WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
|
||||
|
||||
/* Set WWDG Prescaler and Window */
|
||||
WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window));
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize the WWDG MSP.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @note When rewriting this function in user file, mechanism may be added
|
||||
* to avoid multiple initialize when HAL_WWDG_Init function is called
|
||||
* again to change parameters.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hwwdg);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_WWDG_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User WWDG Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hwwdg WWDG handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
|
||||
* @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_RegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID,
|
||||
pWWDG_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_WWDG_EWI_CB_ID:
|
||||
hwwdg->EwiCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_WWDG_MSPINIT_CB_ID:
|
||||
hwwdg->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unregister a WWDG Callback
|
||||
* WWDG Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hwwdg WWDG handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
|
||||
* @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_UnRegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_WWDG_EWI_CB_ID:
|
||||
hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
|
||||
break;
|
||||
|
||||
case HAL_WWDG_MSPINIT_CB_ID:
|
||||
hwwdg->MspInitCallback = HAL_WWDG_MspInit;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Refresh the WWDG.
|
||||
(+) Handle WWDG interrupt request and associated function callback.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Refresh the WWDG.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Write to WWDG CR the WWDG Counter value to refresh with */
|
||||
WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle WWDG interrupt request.
|
||||
* @note The Early Wakeup Interrupt (EWI) can be used if specific safety operations
|
||||
* or data logging must be performed before the actual reset is generated.
|
||||
* The EWI interrupt is enabled by calling HAL_WWDG_Init function with
|
||||
* EWIMode set to WWDG_EWI_ENABLE.
|
||||
* When the downcounter reaches the value 0x40, and EWI interrupt is
|
||||
* generated and the corresponding Interrupt Service Routine (ISR) can
|
||||
* be used to trigger specific actions (such as communications or data
|
||||
* logging), before resetting the device.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Check if Early Wakeup Interrupt is enable */
|
||||
if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)
|
||||
{
|
||||
/* Check if WWDG Early Wakeup Interrupt occurred */
|
||||
if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)
|
||||
{
|
||||
/* Clear the WWDG Early Wakeup flag */
|
||||
__HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/* Early Wakeup registered callback */
|
||||
hwwdg->EwiCallback(hwwdg);
|
||||
#else
|
||||
/* Early Wakeup callback */
|
||||
HAL_WWDG_EarlyWakeupCallback(hwwdg);
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief WWDG Early Wakeup callback.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hwwdg);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_WWDG_EarlyWakeupCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
893
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_adc.c
Normal file
893
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_adc.c
Normal file
@@ -0,0 +1,893 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_adc.c
|
||||
* @author MCD Application Team
|
||||
* @brief ADC LL module driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_adc.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (ADC1) || defined (ADC2) || defined (ADC3)
|
||||
|
||||
/** @addtogroup ADC_LL ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup ADC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* common to several ADC instances. */
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC instance. */
|
||||
#define IS_LL_ADC_DATA_ALIGN(__DATA_ALIGN__) \
|
||||
( ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_RIGHT) \
|
||||
|| ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_LEFT) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_SCAN_SELECTION(__SCAN_SELECTION__) \
|
||||
( ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_DISABLE) \
|
||||
|| ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_ENABLE) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_SEQ_SCAN_MODE(__SEQ_SCAN_MODE__) \
|
||||
( ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_DISABLE) \
|
||||
|| ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_ENABLE) \
|
||||
)
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC group regular */
|
||||
#if defined(ADC3)
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__ADC_INSTANCE__, __REG_TRIG_SOURCE__) \
|
||||
((((__ADC_INSTANCE__) == ADC1) || ((__ADC_INSTANCE__) == ADC2)) \
|
||||
? ( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \
|
||||
) \
|
||||
: \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO_ADC3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH3) \
|
||||
) \
|
||||
)
|
||||
#else
|
||||
#if defined (STM32F101xE) || defined (STM32F105xC) || defined (STM32F107xC)
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \
|
||||
)
|
||||
#else
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
#define IS_LL_ADC_REG_CONTINUOUS_MODE(__REG_CONTINUOUS_MODE__) \
|
||||
( ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_SINGLE) \
|
||||
|| ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_CONTINUOUS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_DMA_TRANSFER(__REG_DMA_TRANSFER__) \
|
||||
( ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_NONE) \
|
||||
|| ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_SEQ_SCAN_LENGTH(__REG_SEQ_SCAN_LENGTH__) \
|
||||
( ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_DISABLE) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(__REG_SEQ_DISCONT_MODE__) \
|
||||
( ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_DISABLE) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_1RANK) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_2RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_3RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_4RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_5RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_6RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_7RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_8RANKS) \
|
||||
)
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC group injected */
|
||||
#if defined(ADC3)
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__ADC_INSTANCE__, __INJ_TRIG_SOURCE__) \
|
||||
((((__ADC_INSTANCE__) == ADC1) || ((__ADC_INSTANCE__) == ADC2)) \
|
||||
? ( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \
|
||||
) \
|
||||
: \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_CH3) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH2) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4_ADC3) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_CH4) \
|
||||
) \
|
||||
)
|
||||
#else
|
||||
#if defined (STM32F101xE) || defined (STM32F105xC) || defined (STM32F107xC)
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \
|
||||
)
|
||||
#else
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
#define IS_LL_ADC_INJ_TRIG_AUTO(__INJ_TRIG_AUTO__) \
|
||||
( ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_INDEPENDENT) \
|
||||
|| ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_FROM_GRP_REGULAR) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(__INJ_SEQ_SCAN_LENGTH__) \
|
||||
( ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_DISABLE) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(__INJ_SEQ_DISCONT_MODE__) \
|
||||
( ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_DISABLE) \
|
||||
|| ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_1RANK) \
|
||||
)
|
||||
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* multimode. */
|
||||
#define IS_LL_ADC_MULTI_MODE(__MULTI_MODE__) \
|
||||
( ((__MULTI_MODE__) == LL_ADC_MULTI_INDEPENDENT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIMULT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL_FAST) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL_SLOW) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_SIMULT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_ALTERN) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTFAST_INJ_SIM) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTSLOW_INJ_SIM) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_MULTI_MASTER_SLAVE(__MULTI_MASTER_SLAVE__) \
|
||||
( ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER) \
|
||||
|| ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_SLAVE) \
|
||||
|| ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER_SLAVE) \
|
||||
)
|
||||
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup ADC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of all ADC instances belonging to
|
||||
* the same ADC common instance to their default reset values.
|
||||
* @param ADCxy_COMMON ADC common instance
|
||||
* (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC common registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_ADC_CommonDeInit(ADC_Common_TypeDef *ADCxy_COMMON)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
|
||||
|
||||
/* Force reset of ADC clock (core clock) */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ADC1);
|
||||
|
||||
/* Release reset of ADC clock (core clock) */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ADC1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC common parameters
|
||||
* (all ADC instances belonging to the same ADC common instance)
|
||||
* and multimode (for devices with several ADC instances available).
|
||||
* @note The setting of ADC common parameters is conditioned to
|
||||
* ADC instances state:
|
||||
* All ADC instances belonging to the same ADC common instance
|
||||
* must be disabled.
|
||||
* @param ADCxy_COMMON ADC common instance
|
||||
* (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
|
||||
* @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC common registers are initialized
|
||||
* - ERROR: ADC common registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
assert_param(IS_LL_ADC_MULTI_MODE(ADC_CommonInitStruct->Multimode));
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
|
||||
/* Note: Hardware constraint (refer to description of functions */
|
||||
/* "LL_ADC_SetCommonXXX()" and "LL_ADC_SetMultiXXX()"): */
|
||||
/* On this STM32 series, setting of these features is conditioned to */
|
||||
/* ADC state: */
|
||||
/* All ADC instances of the ADC common group must be disabled. */
|
||||
if(__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(ADCxy_COMMON) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - common to several ADC */
|
||||
/* (all ADC instances belonging to the same ADC common instance) */
|
||||
/* - multimode (if several ADC instances available on the */
|
||||
/* selected device) */
|
||||
/* - Set ADC multimode configuration */
|
||||
/* - Set ADC multimode DMA transfer */
|
||||
/* - Set ADC multimode: delay between 2 sampling phases */
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
if(ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT)
|
||||
{
|
||||
MODIFY_REG(ADCxy_COMMON->CR1,
|
||||
ADC_CR1_DUALMOD,
|
||||
ADC_CommonInitStruct->Multimode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCxy_COMMON->CR1,
|
||||
ADC_CR1_DUALMOD,
|
||||
LL_ADC_MULTI_INDEPENDENT
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: One or several ADC instances belonging to */
|
||||
/* the same ADC common instance are not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_CommonInitTypeDef field to default value.
|
||||
* @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
|
||||
{
|
||||
/* Set ADC_CommonInitStruct fields to default values */
|
||||
/* Set fields of ADC common */
|
||||
/* (all ADC instances belonging to the same ADC common instance) */
|
||||
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
/* Set fields of ADC multimode */
|
||||
ADC_CommonInitStruct->Multimode = LL_ADC_MULTI_INDEPENDENT;
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of the selected ADC instance
|
||||
* to their default reset values.
|
||||
* @note To reset all ADC instances quickly (perform a hard reset),
|
||||
* use function @ref LL_ADC_CommonDeInit().
|
||||
* @param ADCx ADC instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are de-initialized
|
||||
* - ERROR: ADC registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
|
||||
/* Disable ADC instance if not already disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 1U)
|
||||
{
|
||||
/* Set ADC group regular trigger source to SW start to ensure to not */
|
||||
/* have an external trigger event occurring during the conversion stop */
|
||||
/* ADC disable process. */
|
||||
LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE);
|
||||
|
||||
/* Set ADC group injected trigger source to SW start to ensure to not */
|
||||
/* have an external trigger event occurring during the conversion stop */
|
||||
/* ADC disable process. */
|
||||
LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE);
|
||||
|
||||
/* Disable the ADC instance */
|
||||
LL_ADC_Disable(ADCx);
|
||||
}
|
||||
|
||||
/* Check whether ADC state is compliant with expected state */
|
||||
/* (hardware requirements of bits state to reset registers below) */
|
||||
if(READ_BIT(ADCx->CR2, ADC_CR2_ADON) == 0U)
|
||||
{
|
||||
/* ========== Reset ADC registers ========== */
|
||||
/* Reset register SR */
|
||||
CLEAR_BIT(ADCx->SR,
|
||||
( LL_ADC_FLAG_STRT
|
||||
| LL_ADC_FLAG_JSTRT
|
||||
| LL_ADC_FLAG_EOS
|
||||
| LL_ADC_FLAG_JEOS
|
||||
| LL_ADC_FLAG_AWD1 )
|
||||
);
|
||||
|
||||
/* Reset register CR1 */
|
||||
#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
|
||||
|
||||
CLEAR_BIT(ADCx->CR1,
|
||||
( ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DUALMOD
|
||||
| ADC_CR1_DISCNUM | ADC_CR1_JDISCEN | ADC_CR1_DISCEN
|
||||
| ADC_CR1_JAUTO | ADC_CR1_AWDSGL | ADC_CR1_SCAN
|
||||
| ADC_CR1_JEOCIE | ADC_CR1_AWDIE | ADC_CR1_EOCIE
|
||||
| ADC_CR1_AWDCH )
|
||||
);
|
||||
#else
|
||||
|
||||
CLEAR_BIT(ADCx->CR1,
|
||||
( ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DISCNUM
|
||||
| ADC_CR1_JDISCEN | ADC_CR1_DISCEN | ADC_CR1_JAUTO
|
||||
| ADC_CR1_AWDSGL | ADC_CR1_SCAN | ADC_CR1_JEOCIE
|
||||
| ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_AWDCH )
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Reset register CR2 */
|
||||
CLEAR_BIT(ADCx->CR2,
|
||||
( ADC_CR2_TSVREFE
|
||||
| ADC_CR2_SWSTART | ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL
|
||||
| ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG | ADC_CR2_JEXTSEL
|
||||
| ADC_CR2_ALIGN | ADC_CR2_DMA
|
||||
| ADC_CR2_RSTCAL | ADC_CR2_CAL
|
||||
| ADC_CR2_CONT | ADC_CR2_ADON )
|
||||
);
|
||||
|
||||
/* Reset register SMPR1 */
|
||||
CLEAR_BIT(ADCx->SMPR1,
|
||||
( ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16
|
||||
| ADC_SMPR1_SMP15 | ADC_SMPR1_SMP14 | ADC_SMPR1_SMP13
|
||||
| ADC_SMPR1_SMP12 | ADC_SMPR1_SMP11 | ADC_SMPR1_SMP10)
|
||||
);
|
||||
|
||||
/* Reset register SMPR2 */
|
||||
CLEAR_BIT(ADCx->SMPR2,
|
||||
( ADC_SMPR2_SMP9
|
||||
| ADC_SMPR2_SMP8 | ADC_SMPR2_SMP7 | ADC_SMPR2_SMP6
|
||||
| ADC_SMPR2_SMP5 | ADC_SMPR2_SMP4 | ADC_SMPR2_SMP3
|
||||
| ADC_SMPR2_SMP2 | ADC_SMPR2_SMP1 | ADC_SMPR2_SMP0)
|
||||
);
|
||||
|
||||
/* Reset register JOFR1 */
|
||||
CLEAR_BIT(ADCx->JOFR1, ADC_JOFR1_JOFFSET1);
|
||||
/* Reset register JOFR2 */
|
||||
CLEAR_BIT(ADCx->JOFR2, ADC_JOFR2_JOFFSET2);
|
||||
/* Reset register JOFR3 */
|
||||
CLEAR_BIT(ADCx->JOFR3, ADC_JOFR3_JOFFSET3);
|
||||
/* Reset register JOFR4 */
|
||||
CLEAR_BIT(ADCx->JOFR4, ADC_JOFR4_JOFFSET4);
|
||||
|
||||
/* Reset register HTR */
|
||||
SET_BIT(ADCx->HTR, ADC_HTR_HT);
|
||||
/* Reset register LTR */
|
||||
CLEAR_BIT(ADCx->LTR, ADC_LTR_LT);
|
||||
|
||||
/* Reset register SQR1 */
|
||||
CLEAR_BIT(ADCx->SQR1,
|
||||
( ADC_SQR1_L
|
||||
| ADC_SQR1_SQ16
|
||||
| ADC_SQR1_SQ15 | ADC_SQR1_SQ14 | ADC_SQR1_SQ13)
|
||||
);
|
||||
|
||||
/* Reset register SQR2 */
|
||||
CLEAR_BIT(ADCx->SQR2,
|
||||
( ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10
|
||||
| ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7)
|
||||
);
|
||||
|
||||
/* Reset register SQR3 */
|
||||
CLEAR_BIT(ADCx->SQR3,
|
||||
( ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4
|
||||
| ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1)
|
||||
);
|
||||
|
||||
/* Reset register JSQR */
|
||||
CLEAR_BIT(ADCx->JSQR,
|
||||
( ADC_JSQR_JL
|
||||
| ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3
|
||||
| ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 )
|
||||
);
|
||||
|
||||
/* Reset register DR */
|
||||
/* bits in access mode read only, no direct reset applicable */
|
||||
|
||||
/* Reset registers JDR1, JDR2, JDR3, JDR4 */
|
||||
/* bits in access mode read only, no direct reset applicable */
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC instance.
|
||||
* @note These parameters have an impact on ADC scope: ADC instance.
|
||||
* Affects both group regular and group injected (availability
|
||||
* of ADC group injected depends on STM32 families).
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Instance .
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, some other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group regular or group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_REG_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
|
||||
assert_param(IS_LL_ADC_DATA_ALIGN(ADC_InitStruct->DataAlignment));
|
||||
assert_param(IS_LL_ADC_SCAN_SELECTION(ADC_InitStruct->SequencersScanMode));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC instance */
|
||||
/* - Set ADC conversion data alignment */
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_SCAN
|
||||
,
|
||||
ADC_InitStruct->SequencersScanMode
|
||||
);
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_ALIGN
|
||||
,
|
||||
ADC_InitStruct->DataAlignment
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_InitTypeDef field to default value.
|
||||
* @param ADC_InitStruct Pointer to a @ref LL_ADC_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_StructInit(LL_ADC_InitTypeDef *ADC_InitStruct)
|
||||
{
|
||||
/* Set ADC_InitStruct fields to default values */
|
||||
/* Set fields of ADC instance */
|
||||
ADC_InitStruct->DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
|
||||
|
||||
/* Enable scan mode to have a generic behavior with ADC of other */
|
||||
/* STM32 families, without this setting available: */
|
||||
/* ADC group regular sequencer and ADC group injected sequencer depend */
|
||||
/* only of their own configuration. */
|
||||
ADC_InitStruct->SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC group regular.
|
||||
* @note These parameters have an impact on ADC scope: ADC group regular.
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Group_Regular
|
||||
* (functions with prefix "REG").
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group regular or group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_REG_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
#if defined(ADC3)
|
||||
assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADCx, ADC_REG_InitStruct->TriggerSource));
|
||||
#else
|
||||
assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource));
|
||||
#endif
|
||||
assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(ADC_REG_InitStruct->SequencerLength));
|
||||
if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont));
|
||||
}
|
||||
assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode));
|
||||
assert_param(IS_LL_ADC_REG_DMA_TRANSFER(ADC_REG_InitStruct->DMATransfer));
|
||||
|
||||
/* ADC group regular continuous mode and discontinuous mode */
|
||||
/* can not be enabled simultenaeously */
|
||||
assert_param((ADC_REG_InitStruct->ContinuousMode == LL_ADC_REG_CONV_SINGLE)
|
||||
|| (ADC_REG_InitStruct->SequencerDiscont == LL_ADC_REG_SEQ_DISCONT_DISABLE));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC group regular */
|
||||
/* - Set ADC group regular trigger source */
|
||||
/* - Set ADC group regular sequencer length */
|
||||
/* - Set ADC group regular sequencer discontinuous mode */
|
||||
/* - Set ADC group regular continuous mode */
|
||||
/* - Set ADC group regular conversion data transfer: no transfer or */
|
||||
/* transfer by DMA, and DMA requests mode */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */
|
||||
if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_DISCEN
|
||||
| ADC_CR1_DISCNUM
|
||||
,
|
||||
ADC_REG_InitStruct->SequencerLength
|
||||
| ADC_REG_InitStruct->SequencerDiscont
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_DISCEN
|
||||
| ADC_CR1_DISCNUM
|
||||
,
|
||||
ADC_REG_InitStruct->SequencerLength
|
||||
| LL_ADC_REG_SEQ_DISCONT_DISABLE
|
||||
);
|
||||
}
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_EXTSEL
|
||||
| ADC_CR2_CONT
|
||||
| ADC_CR2_DMA
|
||||
,
|
||||
ADC_REG_InitStruct->TriggerSource
|
||||
| ADC_REG_InitStruct->ContinuousMode
|
||||
| ADC_REG_InitStruct->DMATransfer
|
||||
);
|
||||
|
||||
/* Set ADC group regular sequencer length and scan direction */
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* Note: If ADC instance feature scan mode is disabled */
|
||||
/* (refer to ADC instance initialization structure */
|
||||
/* parameter @ref SequencersScanMode */
|
||||
/* or function @ref LL_ADC_SetSequencersScanMode() ), */
|
||||
/* this parameter is discarded. */
|
||||
LL_ADC_REG_SetSequencerLength(ADCx, ADC_REG_InitStruct->SequencerLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_REG_InitTypeDef field to default value.
|
||||
* @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
|
||||
{
|
||||
/* Set ADC_REG_InitStruct fields to default values */
|
||||
/* Set fields of ADC group regular */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */
|
||||
ADC_REG_InitStruct->TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
|
||||
ADC_REG_InitStruct->SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
|
||||
ADC_REG_InitStruct->SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
|
||||
ADC_REG_InitStruct->ContinuousMode = LL_ADC_REG_CONV_SINGLE;
|
||||
ADC_REG_InitStruct->DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC group injected.
|
||||
* @note These parameters have an impact on ADC scope: ADC group injected.
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Group_Regular
|
||||
* (functions with prefix "INJ").
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_INJ_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
#if defined(ADC3)
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADCx, ADC_INJ_InitStruct->TriggerSource));
|
||||
#else
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource));
|
||||
#endif
|
||||
assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength));
|
||||
if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont));
|
||||
}
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC group injected */
|
||||
/* - Set ADC group injected trigger source */
|
||||
/* - Set ADC group injected sequencer length */
|
||||
/* - Set ADC group injected sequencer discontinuous mode */
|
||||
/* - Set ADC group injected conversion trigger: independent or */
|
||||
/* from ADC group regular */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_INJ_StartConversionExtTrig(). */
|
||||
if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_JDISCEN
|
||||
| ADC_CR1_JAUTO
|
||||
,
|
||||
ADC_INJ_InitStruct->SequencerDiscont
|
||||
| ADC_INJ_InitStruct->TrigAuto
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_JDISCEN
|
||||
| ADC_CR1_JAUTO
|
||||
,
|
||||
LL_ADC_REG_SEQ_DISCONT_DISABLE
|
||||
| ADC_INJ_InitStruct->TrigAuto
|
||||
);
|
||||
}
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_JEXTSEL
|
||||
,
|
||||
ADC_INJ_InitStruct->TriggerSource
|
||||
);
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* Note: If ADC instance feature scan mode is disabled */
|
||||
/* (refer to ADC instance initialization structure */
|
||||
/* parameter @ref SequencersScanMode */
|
||||
/* or function @ref LL_ADC_SetSequencersScanMode() ), */
|
||||
/* this parameter is discarded. */
|
||||
LL_ADC_INJ_SetSequencerLength(ADCx, ADC_INJ_InitStruct->SequencerLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_INJ_InitTypeDef field to default value.
|
||||
* @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
|
||||
{
|
||||
/* Set ADC_INJ_InitStruct fields to default values */
|
||||
/* Set fields of ADC group injected */
|
||||
ADC_INJ_InitStruct->TriggerSource = LL_ADC_INJ_TRIG_SOFTWARE;
|
||||
ADC_INJ_InitStruct->SequencerLength = LL_ADC_INJ_SEQ_SCAN_DISABLE;
|
||||
ADC_INJ_InitStruct->SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE;
|
||||
ADC_INJ_InitStruct->TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ADC1 || ADC2 || ADC3 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
104
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_crc.c
Normal file
104
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_crc.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_crc.c
|
||||
* @author MCD Application Team
|
||||
* @brief CRC LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_crc.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (CRC)
|
||||
|
||||
/** @addtogroup CRC_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup CRC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize CRC registers (Registers restored to their default values).
|
||||
* @param CRCx CRC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: CRC registers are de-initialized
|
||||
* - ERROR: CRC registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(CRCx));
|
||||
|
||||
if (CRCx == CRC)
|
||||
{
|
||||
|
||||
/* Reset the CRC calculation unit */
|
||||
LL_CRC_ResetCRCCalculationUnit(CRCx);
|
||||
|
||||
/* Reset IDR register */
|
||||
LL_CRC_Write_IDR(CRCx, 0x00U);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (CRC) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
270
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_dac.c
Normal file
270
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_dac.c
Normal file
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_dac.c
|
||||
* @author MCD Application Team
|
||||
* @brief DAC LL module driver
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_dac.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(DAC)
|
||||
|
||||
/** @addtogroup DAC_LL DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup DAC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_DAC_CHANNEL(__DAC_CHANNEL__) \
|
||||
(((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \
|
||||
|| ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_2) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \
|
||||
(((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM15_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_WAVE_AUTO_GENER_MODE(__WAVE_AUTO_GENERATION_MODE__) \
|
||||
(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NONE) \
|
||||
|| ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
|
||||
|| ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(__WAVE_AUTO_GENERATION_MODE__, __WAVE_AUTO_GENERATION_CONFIG__) \
|
||||
( (((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
|
||||
&& (((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BIT0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS1_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS2_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS3_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS4_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS5_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS6_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS7_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS8_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS9_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS10_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS11_0)) \
|
||||
) \
|
||||
||(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
|
||||
&& (((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_3) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_7) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_15) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_31) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_63) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_127) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_255) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_511) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1023) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_2047) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_4095)) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_OUTPUT_BUFFER(__OUTPUT_BUFFER__) \
|
||||
(((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_ENABLE) \
|
||||
|| ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_DISABLE) \
|
||||
)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup DAC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of the selected DAC instance
|
||||
* to their default reset values.
|
||||
* @param DACx DAC instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DAC registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_DAC_DeInit(const DAC_TypeDef *DACx)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(DACx));
|
||||
|
||||
/* Force reset of DAC clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_DAC1);
|
||||
|
||||
/* Release reset of DAC clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_DAC1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of DAC channel.
|
||||
* @note @ref LL_DAC_Init() aims to ease basic configuration of a DAC channel.
|
||||
* Leaving it ready to be enabled and output:
|
||||
* a level by calling one of
|
||||
* @ref LL_DAC_ConvertData12RightAligned
|
||||
* @ref LL_DAC_ConvertData12LeftAligned
|
||||
* @ref LL_DAC_ConvertData8RightAligned
|
||||
* or one of the supported autogenerated wave.
|
||||
* @note This function allows configuration of:
|
||||
* - Output mode
|
||||
* - Trigger
|
||||
* - Wave generation
|
||||
* @note The setting of these parameters by function @ref LL_DAC_Init()
|
||||
* is conditioned to DAC state:
|
||||
* DAC channel must be disabled.
|
||||
* @param DACx DAC instance
|
||||
* @param DAC_Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DAC_CHANNEL_1
|
||||
* @arg @ref LL_DAC_CHANNEL_2
|
||||
* @param DAC_InitStruct Pointer to a @ref LL_DAC_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DAC registers are initialized
|
||||
* - ERROR: DAC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_DAC_Init(DAC_TypeDef *DACx, uint32_t DAC_Channel, const LL_DAC_InitTypeDef *DAC_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(DACx));
|
||||
assert_param(IS_LL_DAC_CHANNEL(DAC_Channel));
|
||||
assert_param(IS_LL_DAC_TRIGGER_SOURCE(DAC_InitStruct->TriggerSource));
|
||||
assert_param(IS_LL_DAC_OUTPUT_BUFFER(DAC_InitStruct->OutputBuffer));
|
||||
assert_param(IS_LL_DAC_WAVE_AUTO_GENER_MODE(DAC_InitStruct->WaveAutoGeneration));
|
||||
if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
|
||||
{
|
||||
assert_param(IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(DAC_InitStruct->WaveAutoGeneration,
|
||||
DAC_InitStruct->WaveAutoGenerationConfig));
|
||||
}
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function) */
|
||||
/* DAC instance must be disabled. */
|
||||
if (LL_DAC_IsEnabled(DACx, DAC_Channel) == 0UL)
|
||||
{
|
||||
/* Configuration of DAC channel: */
|
||||
/* - TriggerSource */
|
||||
/* - WaveAutoGeneration */
|
||||
/* - OutputBuffer */
|
||||
/* - OutputMode */
|
||||
if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
|
||||
{
|
||||
MODIFY_REG(DACx->CR,
|
||||
(DAC_CR_TSEL1
|
||||
| DAC_CR_WAVE1
|
||||
| DAC_CR_MAMP1
|
||||
| DAC_CR_BOFF1
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
,
|
||||
(DAC_InitStruct->TriggerSource
|
||||
| DAC_InitStruct->WaveAutoGeneration
|
||||
| DAC_InitStruct->WaveAutoGenerationConfig
|
||||
| DAC_InitStruct->OutputBuffer
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(DACx->CR,
|
||||
(DAC_CR_TSEL1
|
||||
| DAC_CR_WAVE1
|
||||
| DAC_CR_BOFF1
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
,
|
||||
(DAC_InitStruct->TriggerSource
|
||||
| LL_DAC_WAVE_AUTO_GENERATION_NONE
|
||||
| DAC_InitStruct->OutputBuffer
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: DAC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_DAC_InitTypeDef field to default value.
|
||||
* @param DAC_InitStruct pointer to a @ref LL_DAC_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_DAC_StructInit(LL_DAC_InitTypeDef *DAC_InitStruct)
|
||||
{
|
||||
/* Set DAC_InitStruct fields to default values */
|
||||
DAC_InitStruct->TriggerSource = LL_DAC_TRIG_SOFTWARE;
|
||||
DAC_InitStruct->WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
|
||||
/* Note: Parameter discarded if wave auto generation is disabled, */
|
||||
/* set anyway to its default value. */
|
||||
DAC_InitStruct->WaveAutoGenerationConfig = LL_DAC_NOISE_LFSR_UNMASK_BIT0;
|
||||
DAC_InitStruct->OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
312
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_dma.c
Normal file
312
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_dma.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_dma.c
|
||||
* @author MCD Application Team
|
||||
* @brief DMA LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_dma.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (DMA1) || defined (DMA2)
|
||||
|
||||
/** @defgroup DMA_LL DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup DMA_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_DMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
|
||||
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \
|
||||
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY))
|
||||
|
||||
#define IS_LL_DMA_MODE(__VALUE__) (((__VALUE__) == LL_DMA_MODE_NORMAL) || \
|
||||
((__VALUE__) == LL_DMA_MODE_CIRCULAR))
|
||||
|
||||
#define IS_LL_DMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \
|
||||
((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT))
|
||||
|
||||
#define IS_LL_DMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \
|
||||
((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT))
|
||||
|
||||
#define IS_LL_DMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE) || \
|
||||
((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD) || \
|
||||
((__VALUE__) == LL_DMA_PDATAALIGN_WORD))
|
||||
|
||||
#define IS_LL_DMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE) || \
|
||||
((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD) || \
|
||||
((__VALUE__) == LL_DMA_MDATAALIGN_WORD))
|
||||
|
||||
#define IS_LL_DMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
|
||||
|
||||
#define IS_LL_DMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_DMA_PRIORITY_LOW) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_HIGH) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH))
|
||||
|
||||
#if defined (DMA2)
|
||||
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_6) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_7))) || \
|
||||
(((INSTANCE) == DMA2) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5))))
|
||||
#else
|
||||
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_6) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_7))))
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup DMA_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DMA_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the DMA registers to their default reset values.
|
||||
* @param DMAx DMAx Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DMA_CHANNEL_1
|
||||
* @arg @ref LL_DMA_CHANNEL_2
|
||||
* @arg @ref LL_DMA_CHANNEL_3
|
||||
* @arg @ref LL_DMA_CHANNEL_4
|
||||
* @arg @ref LL_DMA_CHANNEL_5
|
||||
* @arg @ref LL_DMA_CHANNEL_6
|
||||
* @arg @ref LL_DMA_CHANNEL_7
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DMA registers are de-initialized
|
||||
* - ERROR: DMA registers are not de-initialized
|
||||
*/
|
||||
uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
|
||||
{
|
||||
DMA_Channel_TypeDef *tmp = (DMA_Channel_TypeDef *)DMA1_Channel1;
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the DMA Instance DMAx and Channel parameters*/
|
||||
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
/* Disable the selected DMAx_Channely */
|
||||
CLEAR_BIT(tmp->CCR, DMA_CCR_EN);
|
||||
|
||||
/* Reset DMAx_Channely control register */
|
||||
LL_DMA_WriteReg(tmp, CCR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely remaining bytes register */
|
||||
LL_DMA_WriteReg(tmp, CNDTR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely peripheral address register */
|
||||
LL_DMA_WriteReg(tmp, CPAR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely memory address register */
|
||||
LL_DMA_WriteReg(tmp, CMAR, 0U);
|
||||
|
||||
if (Channel == LL_DMA_CHANNEL_1)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel1 */
|
||||
LL_DMA_ClearFlag_GI1(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_2)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel2 */
|
||||
LL_DMA_ClearFlag_GI2(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_3)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel3 */
|
||||
LL_DMA_ClearFlag_GI3(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_4)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel4 */
|
||||
LL_DMA_ClearFlag_GI4(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_5)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel5 */
|
||||
LL_DMA_ClearFlag_GI5(DMAx);
|
||||
}
|
||||
|
||||
else if (Channel == LL_DMA_CHANNEL_6)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel6 */
|
||||
LL_DMA_ClearFlag_GI6(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_7)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel7 */
|
||||
LL_DMA_ClearFlag_GI7(DMAx);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
|
||||
* @note To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros :
|
||||
* @arg @ref __LL_DMA_GET_INSTANCE
|
||||
* @arg @ref __LL_DMA_GET_CHANNEL
|
||||
* @param DMAx DMAx Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DMA_CHANNEL_1
|
||||
* @arg @ref LL_DMA_CHANNEL_2
|
||||
* @arg @ref LL_DMA_CHANNEL_3
|
||||
* @arg @ref LL_DMA_CHANNEL_4
|
||||
* @arg @ref LL_DMA_CHANNEL_5
|
||||
* @arg @ref LL_DMA_CHANNEL_6
|
||||
* @arg @ref LL_DMA_CHANNEL_7
|
||||
* @param DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DMA registers are initialized
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
|
||||
{
|
||||
/* Check the DMA Instance DMAx and Channel parameters*/
|
||||
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
/* Check the DMA parameters from DMA_InitStruct */
|
||||
assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
|
||||
assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
|
||||
assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
|
||||
assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
|
||||
assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
|
||||
assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
|
||||
assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
|
||||
assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
|
||||
|
||||
/*---------------------------- DMAx CCR Configuration ------------------------
|
||||
* Configure DMAx_Channely: data transfer direction, data transfer mode,
|
||||
* peripheral and memory increment mode,
|
||||
* data size alignment and priority level with parameters :
|
||||
* - Direction: DMA_CCR_DIR and DMA_CCR_MEM2MEM bits
|
||||
* - Mode: DMA_CCR_CIRC bit
|
||||
* - PeriphOrM2MSrcIncMode: DMA_CCR_PINC bit
|
||||
* - MemoryOrM2MDstIncMode: DMA_CCR_MINC bit
|
||||
* - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits
|
||||
* - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits
|
||||
* - Priority: DMA_CCR_PL[1:0] bits
|
||||
*/
|
||||
LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction | \
|
||||
DMA_InitStruct->Mode | \
|
||||
DMA_InitStruct->PeriphOrM2MSrcIncMode | \
|
||||
DMA_InitStruct->MemoryOrM2MDstIncMode | \
|
||||
DMA_InitStruct->PeriphOrM2MSrcDataSize | \
|
||||
DMA_InitStruct->MemoryOrM2MDstDataSize | \
|
||||
DMA_InitStruct->Priority);
|
||||
|
||||
/*-------------------------- DMAx CMAR Configuration -------------------------
|
||||
* Configure the memory or destination base address with parameter :
|
||||
* - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits
|
||||
*/
|
||||
LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress);
|
||||
|
||||
/*-------------------------- DMAx CPAR Configuration -------------------------
|
||||
* Configure the peripheral or source base address with parameter :
|
||||
* - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits
|
||||
*/
|
||||
LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress);
|
||||
|
||||
/*--------------------------- DMAx CNDTR Configuration -----------------------
|
||||
* Configure the peripheral base address with parameter :
|
||||
* - NbData: DMA_CNDTR_NDT[15:0] bits
|
||||
*/
|
||||
LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_DMA_InitTypeDef field to default value.
|
||||
* @param DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
|
||||
{
|
||||
/* Set DMA_InitStruct fields to default values */
|
||||
DMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U;
|
||||
DMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U;
|
||||
DMA_InitStruct->Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||
DMA_InitStruct->Mode = LL_DMA_MODE_NORMAL;
|
||||
DMA_InitStruct->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
DMA_InitStruct->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT;
|
||||
DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
|
||||
DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
|
||||
DMA_InitStruct->NbData = 0x00000000U;
|
||||
DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DMA1 || DMA2 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
213
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_exti.c
Normal file
213
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_exti.c
Normal file
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_exti.c
|
||||
* @author MCD Application Team
|
||||
* @brief EXTI LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_exti.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (EXTI)
|
||||
|
||||
/** @defgroup EXTI_LL EXTI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup EXTI_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_EXTI_LINE_0_31(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_0_31) == 0x00000000U)
|
||||
|
||||
#define IS_LL_EXTI_MODE(__VALUE__) (((__VALUE__) == LL_EXTI_MODE_IT) \
|
||||
|| ((__VALUE__) == LL_EXTI_MODE_EVENT) \
|
||||
|| ((__VALUE__) == LL_EXTI_MODE_IT_EVENT))
|
||||
|
||||
|
||||
#define IS_LL_EXTI_TRIGGER(__VALUE__) (((__VALUE__) == LL_EXTI_TRIGGER_NONE) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_FALLING) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING_FALLING))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup EXTI_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup EXTI_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the EXTI registers to their default reset values.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: EXTI registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
uint32_t LL_EXTI_DeInit(void)
|
||||
{
|
||||
/* Interrupt mask register set to default reset values */
|
||||
LL_EXTI_WriteReg(IMR, 0x00000000U);
|
||||
/* Event mask register set to default reset values */
|
||||
LL_EXTI_WriteReg(EMR, 0x00000000U);
|
||||
/* Rising Trigger selection register set to default reset values */
|
||||
LL_EXTI_WriteReg(RTSR, 0x00000000U);
|
||||
/* Falling Trigger selection register set to default reset values */
|
||||
LL_EXTI_WriteReg(FTSR, 0x00000000U);
|
||||
/* Software interrupt event register set to default reset values */
|
||||
LL_EXTI_WriteReg(SWIER, 0x00000000U);
|
||||
/* Pending register clear */
|
||||
LL_EXTI_WriteReg(PR, 0x000FFFFFU);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the EXTI registers according to the specified parameters in EXTI_InitStruct.
|
||||
* @param EXTI_InitStruct pointer to a @ref LL_EXTI_InitTypeDef structure.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: EXTI registers are initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31));
|
||||
assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->LineCommand));
|
||||
assert_param(IS_LL_EXTI_MODE(EXTI_InitStruct->Mode));
|
||||
|
||||
/* ENABLE LineCommand */
|
||||
if (EXTI_InitStruct->LineCommand != DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_EXTI_TRIGGER(EXTI_InitStruct->Trigger));
|
||||
|
||||
/* Configure EXTI Lines in range from 0 to 31 */
|
||||
if (EXTI_InitStruct->Line_0_31 != LL_EXTI_LINE_NONE)
|
||||
{
|
||||
switch (EXTI_InitStruct->Mode)
|
||||
{
|
||||
case LL_EXTI_MODE_IT:
|
||||
/* First Disable Event on provided Lines */
|
||||
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable IT on provided Lines */
|
||||
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_MODE_EVENT:
|
||||
/* First Disable IT on provided Lines */
|
||||
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Event on provided Lines */
|
||||
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_MODE_IT_EVENT:
|
||||
/* Directly Enable IT & Event on provided Lines */
|
||||
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
}
|
||||
if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
|
||||
{
|
||||
switch (EXTI_InitStruct->Trigger)
|
||||
{
|
||||
case LL_EXTI_TRIGGER_RISING:
|
||||
/* First Disable Falling Trigger on provided Lines */
|
||||
LL_EXTI_DisableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Rising Trigger on provided Lines */
|
||||
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_TRIGGER_FALLING:
|
||||
/* First Disable Rising Trigger on provided Lines */
|
||||
LL_EXTI_DisableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Falling Trigger on provided Lines */
|
||||
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_TRIGGER_RISING_FALLING:
|
||||
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* DISABLE LineCommand */
|
||||
else
|
||||
{
|
||||
/* De-configure EXTI Lines in range from 0 to 31 */
|
||||
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_EXTI_InitTypeDef field to default value.
|
||||
* @param EXTI_InitStruct Pointer to a @ref LL_EXTI_InitTypeDef structure.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct)
|
||||
{
|
||||
EXTI_InitStruct->Line_0_31 = LL_EXTI_LINE_NONE;
|
||||
EXTI_InitStruct->LineCommand = DISABLE;
|
||||
EXTI_InitStruct->Mode = LL_EXTI_MODE_IT;
|
||||
EXTI_InitStruct->Trigger = LL_EXTI_TRIGGER_FALLING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (EXTI) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
1014
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_fsmc.c
Normal file
1014
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_fsmc.c
Normal file
@@ -0,0 +1,1014 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_fsmc.c
|
||||
* @author MCD Application Team
|
||||
* @brief FSMC Low Layer HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Flexible Memory Controller (FSMC) peripheral memories:
|
||||
* + Initialization/de-initialization 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
|
||||
==============================================================================
|
||||
##### FSMC peripheral features #####
|
||||
==============================================================================
|
||||
[..] The Flexible memory controller (FSMC) includes following memory controllers:
|
||||
(+) The NOR/PSRAM memory controller
|
||||
(+) The NAND/PC Card memory controller
|
||||
|
||||
[..] The FSMC functional block makes the interface with synchronous and asynchronous static
|
||||
memories and 16-bit PC memory cards. Its main purposes are:
|
||||
(+) to translate AHB transactions into the appropriate external device protocol
|
||||
(+) to meet the access time requirements of the external memory devices
|
||||
|
||||
[..] All external memories share the addresses, data and control signals with the controller.
|
||||
Each external device is accessed by means of a unique Chip Select. The FSMC performs
|
||||
only one access at a time to an external device.
|
||||
The main features of the FSMC controller are the following:
|
||||
(+) Interface with static-memory mapped devices including:
|
||||
(++) Static random access memory (SRAM)
|
||||
(++) Read-only memory (ROM)
|
||||
(++) NOR Flash memory/OneNAND Flash memory
|
||||
(++) PSRAM (4 memory banks)
|
||||
(++) 16-bit PC Card compatible devices
|
||||
(++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of
|
||||
data
|
||||
(+) Independent Chip Select control for each memory bank
|
||||
(+) Independent configuration for each memory bank
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
#if defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_NAND_MODULE_ENABLED) || defined(HAL_PCCARD_MODULE_ENABLED) \
|
||||
|| defined(HAL_SRAM_MODULE_ENABLED)
|
||||
|
||||
/** @defgroup FSMC_LL FSMC Low Layer
|
||||
* @brief FSMC driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup FSMC_LL_Private_Constants FSMC Low Layer Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* ----------------------- FSMC registers bit mask --------------------------- */
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
/* --- BCR Register ---*/
|
||||
/* BCR register clear mask */
|
||||
|
||||
/* --- BTR Register ---*/
|
||||
/* BTR register clear mask */
|
||||
#define BTR_CLEAR_MASK ((uint32_t)(FSMC_BTRx_ADDSET | FSMC_BTRx_ADDHLD |\
|
||||
FSMC_BTRx_DATAST | FSMC_BTRx_BUSTURN |\
|
||||
FSMC_BTRx_CLKDIV | FSMC_BTRx_DATLAT |\
|
||||
FSMC_BTRx_ACCMOD))
|
||||
|
||||
/* --- BWTR Register ---*/
|
||||
/* BWTR register clear mask */
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
#define BWTR_CLEAR_MASK ((uint32_t)(FSMC_BWTRx_ADDSET | FSMC_BWTRx_ADDHLD |\
|
||||
FSMC_BWTRx_DATAST | FSMC_BWTRx_BUSTURN |\
|
||||
FSMC_BWTRx_ACCMOD))
|
||||
#else
|
||||
#define BWTR_CLEAR_MASK ((uint32_t)(FSMC_BWTRx_ADDSET | FSMC_BWTRx_ADDHLD |\
|
||||
FSMC_BWTRx_DATAST | FSMC_BWTRx_ACCMOD |\
|
||||
FSMC_BWTRx_CLKDIV | FSMC_BWTRx_DATLAT))
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
#endif /* FSMC_BANK1 */
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/* --- PCR Register ---*/
|
||||
/* PCR register clear mask */
|
||||
#define PCR_CLEAR_MASK ((uint32_t)(FSMC_PCRx_PWAITEN | FSMC_PCRx_PBKEN | \
|
||||
FSMC_PCRx_PTYP | FSMC_PCRx_PWID | \
|
||||
FSMC_PCRx_ECCEN | FSMC_PCRx_TCLR | \
|
||||
FSMC_PCRx_TAR | FSMC_PCRx_ECCPS))
|
||||
/* --- PMEM Register ---*/
|
||||
/* PMEM register clear mask */
|
||||
#define PMEM_CLEAR_MASK ((uint32_t)(FSMC_PMEMx_MEMSETx | FSMC_PMEMx_MEMWAITx |\
|
||||
FSMC_PMEMx_MEMHOLDx | FSMC_PMEMx_MEMHIZx))
|
||||
|
||||
/* --- PATT Register ---*/
|
||||
/* PATT register clear mask */
|
||||
#define PATT_CLEAR_MASK ((uint32_t)(FSMC_PATTx_ATTSETx | FSMC_PATTx_ATTWAITx |\
|
||||
FSMC_PATTx_ATTHOLDx | FSMC_PATTx_ATTHIZx))
|
||||
|
||||
#endif /* FSMC_BANK3 */
|
||||
#if defined(FSMC_BANK4)
|
||||
/* --- PCR Register ---*/
|
||||
/* PCR register clear mask */
|
||||
#define PCR4_CLEAR_MASK ((uint32_t)(FSMC_PCR4_PWAITEN | FSMC_PCR4_PBKEN | \
|
||||
FSMC_PCR4_PTYP | FSMC_PCR4_PWID | \
|
||||
FSMC_PCR4_ECCEN | FSMC_PCR4_TCLR | \
|
||||
FSMC_PCR4_TAR | FSMC_PCR4_ECCPS))
|
||||
/* --- PMEM Register ---*/
|
||||
/* PMEM register clear mask */
|
||||
#define PMEM4_CLEAR_MASK ((uint32_t)(FSMC_PMEM4_MEMSET4 | FSMC_PMEM4_MEMWAIT4 |\
|
||||
FSMC_PMEM4_MEMHOLD4 | FSMC_PMEM4_MEMHIZ4))
|
||||
|
||||
/* --- PATT Register ---*/
|
||||
/* PATT register clear mask */
|
||||
#define PATT4_CLEAR_MASK ((uint32_t)(FSMC_PATT4_ATTSET4 | FSMC_PATT4_ATTWAIT4 |\
|
||||
FSMC_PATT4_ATTHOLD4 | FSMC_PATT4_ATTHIZ4))
|
||||
|
||||
/* --- PIO4 Register ---*/
|
||||
/* PIO4 register clear mask */
|
||||
#define PIO4_CLEAR_MASK ((uint32_t)(FSMC_PIO4_IOSET4 | FSMC_PIO4_IOWAIT4 | \
|
||||
FSMC_PIO4_IOHOLD4 | FSMC_PIO4_IOHIZ4))
|
||||
|
||||
#endif /* FSMC_BANK4 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions FSMC Low Layer Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions_NORSRAM FSMC Low Layer NOR SRAM Exported Functions
|
||||
* @brief NORSRAM Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use NORSRAM device driver #####
|
||||
==============================================================================
|
||||
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC NORSRAM banks in order
|
||||
to run the NORSRAM external devices.
|
||||
|
||||
(+) FSMC NORSRAM bank reset using the function FSMC_NORSRAM_DeInit()
|
||||
(+) FSMC NORSRAM bank control configuration using the function FSMC_NORSRAM_Init()
|
||||
(+) FSMC NORSRAM bank timing configuration using the function FSMC_NORSRAM_Timing_Init()
|
||||
(+) FSMC NORSRAM bank extended timing configuration using the function
|
||||
FSMC_NORSRAM_Extended_Timing_Init()
|
||||
(+) FSMC NORSRAM bank enable/disable write operation using the functions
|
||||
FSMC_NORSRAM_WriteOperation_Enable()/FSMC_NORSRAM_WriteOperation_Disable()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FSMC_LL_NORSRAM_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 FSMC NORSRAM interface
|
||||
(+) De-initialize the FSMC NORSRAM interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM device according to the specified
|
||||
* control parameters in the FSMC_NORSRAM_InitTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Init Pointer to NORSRAM Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Init(FSMC_NORSRAM_TypeDef *Device,
|
||||
const FSMC_NORSRAM_InitTypeDef *Init)
|
||||
{
|
||||
uint32_t flashaccess;
|
||||
uint32_t btcr_reg;
|
||||
uint32_t mask;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Init->NSBank));
|
||||
assert_param(IS_FSMC_MUX(Init->DataAddressMux));
|
||||
assert_param(IS_FSMC_MEMORY(Init->MemoryType));
|
||||
assert_param(IS_FSMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth));
|
||||
assert_param(IS_FSMC_BURSTMODE(Init->BurstAccessMode));
|
||||
assert_param(IS_FSMC_WAIT_POLARITY(Init->WaitSignalPolarity));
|
||||
assert_param(IS_FSMC_WRAP_MODE(Init->WrapMode));
|
||||
assert_param(IS_FSMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive));
|
||||
assert_param(IS_FSMC_WRITE_OPERATION(Init->WriteOperation));
|
||||
assert_param(IS_FSMC_WAITE_SIGNAL(Init->WaitSignal));
|
||||
assert_param(IS_FSMC_EXTENDED_MODE(Init->ExtendedMode));
|
||||
assert_param(IS_FSMC_ASYNWAIT(Init->AsynchronousWait));
|
||||
assert_param(IS_FSMC_WRITE_BURST(Init->WriteBurst));
|
||||
assert_param(IS_FSMC_PAGESIZE(Init->PageSize));
|
||||
|
||||
/* Disable NORSRAM Device */
|
||||
__FSMC_NORSRAM_DISABLE(Device, Init->NSBank);
|
||||
|
||||
/* Set NORSRAM device control parameters */
|
||||
if (Init->MemoryType == FSMC_MEMORY_TYPE_NOR)
|
||||
{
|
||||
flashaccess = FSMC_NORSRAM_FLASH_ACCESS_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
flashaccess = FSMC_NORSRAM_FLASH_ACCESS_DISABLE;
|
||||
}
|
||||
|
||||
btcr_reg = (flashaccess | \
|
||||
Init->DataAddressMux | \
|
||||
Init->MemoryType | \
|
||||
Init->MemoryDataWidth | \
|
||||
Init->BurstAccessMode | \
|
||||
Init->WaitSignalPolarity | \
|
||||
Init->WaitSignalActive | \
|
||||
Init->WriteOperation | \
|
||||
Init->WaitSignal | \
|
||||
Init->ExtendedMode | \
|
||||
Init->AsynchronousWait | \
|
||||
Init->WriteBurst);
|
||||
|
||||
btcr_reg |= Init->WrapMode;
|
||||
btcr_reg |= Init->PageSize;
|
||||
|
||||
mask = (FSMC_BCRx_MBKEN |
|
||||
FSMC_BCRx_MUXEN |
|
||||
FSMC_BCRx_MTYP |
|
||||
FSMC_BCRx_MWID |
|
||||
FSMC_BCRx_FACCEN |
|
||||
FSMC_BCRx_BURSTEN |
|
||||
FSMC_BCRx_WAITPOL |
|
||||
FSMC_BCRx_WAITCFG |
|
||||
FSMC_BCRx_WREN |
|
||||
FSMC_BCRx_WAITEN |
|
||||
FSMC_BCRx_EXTMOD |
|
||||
FSMC_BCRx_ASYNCWAIT |
|
||||
FSMC_BCRx_CBURSTRW);
|
||||
|
||||
mask |= FSMC_BCRx_WRAPMOD;
|
||||
mask |= 0x00070000U; /* CPSIZE to be defined in CMSIS file */
|
||||
|
||||
MODIFY_REG(Device->BTCR[Init->NSBank], mask, btcr_reg);
|
||||
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the FSMC_NORSRAM peripheral
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param ExDevice Pointer to NORSRAM extended mode device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_DeInit(FSMC_NORSRAM_TypeDef *Device,
|
||||
FSMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(ExDevice));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Disable the FSMC_NORSRAM device */
|
||||
__FSMC_NORSRAM_DISABLE(Device, Bank);
|
||||
|
||||
/* De-initialize the FSMC_NORSRAM device */
|
||||
/* FSMC_NORSRAM_BANK1 */
|
||||
if (Bank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
Device->BTCR[Bank] = 0x000030DBU;
|
||||
}
|
||||
/* FSMC_NORSRAM_BANK2, FSMC_NORSRAM_BANK3 or FSMC_NORSRAM_BANK4 */
|
||||
else
|
||||
{
|
||||
Device->BTCR[Bank] = 0x000030D2U;
|
||||
}
|
||||
|
||||
Device->BTCR[Bank + 1U] = 0x0FFFFFFFU;
|
||||
ExDevice->BWTR[Bank] = 0x0FFFFFFFU;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM Timing according to the specified
|
||||
* parameters in the FSMC_NORSRAM_TimingTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Timing Pointer to NORSRAM Timing structure
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Timing_Init(FSMC_NORSRAM_TypeDef *Device,
|
||||
const FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
|
||||
assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
|
||||
assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime));
|
||||
assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
|
||||
assert_param(IS_FSMC_CLK_DIV(Timing->CLKDivision));
|
||||
assert_param(IS_FSMC_DATA_LATENCY(Timing->DataLatency));
|
||||
assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NORSRAM device timing parameters */
|
||||
Device->BTCR[Bank + 1U] =
|
||||
(Timing->AddressSetupTime << FSMC_BTRx_ADDSET_Pos) |
|
||||
(Timing->AddressHoldTime << FSMC_BTRx_ADDHLD_Pos) |
|
||||
(Timing->DataSetupTime << FSMC_BTRx_DATAST_Pos) |
|
||||
(Timing->BusTurnAroundDuration << FSMC_BTRx_BUSTURN_Pos) |
|
||||
((Timing->CLKDivision - 1U) << FSMC_BTRx_CLKDIV_Pos) |
|
||||
((Timing->DataLatency - 2U) << FSMC_BTRx_DATLAT_Pos) |
|
||||
Timing->AccessMode;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM Extended mode Timing according to the specified
|
||||
* parameters in the FSMC_NORSRAM_TimingTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Timing Pointer to NORSRAM Timing structure
|
||||
* @param Bank NORSRAM bank number
|
||||
* @param ExtendedMode FSMC Extended Mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg FSMC_EXTENDED_MODE_DISABLE
|
||||
* @arg FSMC_EXTENDED_MODE_ENABLE
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Extended_Timing_Init(FSMC_NORSRAM_EXTENDED_TypeDef *Device,
|
||||
const FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank,
|
||||
uint32_t ExtendedMode)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_EXTENDED_MODE(ExtendedMode));
|
||||
|
||||
/* Set NORSRAM device timing register for write configuration, if extended mode is used */
|
||||
if (ExtendedMode == FSMC_EXTENDED_MODE_ENABLE)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(Device));
|
||||
assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
|
||||
assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
|
||||
assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime));
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
|
||||
#else
|
||||
assert_param(IS_FSMC_CLK_DIV(Timing->CLKDivision));
|
||||
assert_param(IS_FSMC_DATA_LATENCY(Timing->DataLatency));
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Set NORSRAM device timing register for write configuration, if extended mode is used */
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime |
|
||||
((Timing->AddressHoldTime) << FSMC_BWTRx_ADDHLD_Pos) |
|
||||
((Timing->DataSetupTime) << FSMC_BWTRx_DATAST_Pos) |
|
||||
Timing->AccessMode |
|
||||
((Timing->BusTurnAroundDuration) << FSMC_BWTRx_BUSTURN_Pos)));
|
||||
#else
|
||||
MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime |
|
||||
((Timing->AddressHoldTime) << FSMC_BWTRx_ADDHLD_Pos) |
|
||||
((Timing->DataSetupTime) << FSMC_BWTRx_DATAST_Pos) |
|
||||
Timing->AccessMode |
|
||||
(((Timing->CLKDivision) - 1U) << FSMC_BWTRx_CLKDIV_Pos) |
|
||||
(((Timing->DataLatency) - 2U) << FSMC_BWTRx_DATLAT_Pos)));
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->BWTR[Bank] = 0x0FFFFFFFU;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup FSMC_LL_NORSRAM_Private_Functions_Group2
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FSMC_NORSRAM Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the FSMC NORSRAM interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically FSMC_NORSRAM write operation.
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Enable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Enable write operation */
|
||||
SET_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NORSRAM write operation.
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Disable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Disable write operation */
|
||||
CLEAR_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK1 */
|
||||
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions_NAND FSMC Low Layer NAND Exported Functions
|
||||
* @brief NAND Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use NAND device driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC NAND banks in order
|
||||
to run the NAND external devices.
|
||||
|
||||
(+) FSMC NAND bank reset using the function FSMC_NAND_DeInit()
|
||||
(+) FSMC NAND bank control configuration using the function FSMC_NAND_Init()
|
||||
(+) FSMC NAND bank common space timing configuration using the function
|
||||
FSMC_NAND_CommonSpace_Timing_Init()
|
||||
(+) FSMC NAND bank attribute space timing configuration using the function
|
||||
FSMC_NAND_AttributeSpace_Timing_Init()
|
||||
(+) FSMC NAND bank enable/disable ECC correction feature using the functions
|
||||
FSMC_NAND_ECC_Enable()/FSMC_NAND_ECC_Disable()
|
||||
(+) FSMC NAND bank get ECC correction code using the function FSMC_NAND_GetECC()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FSMC_LL_NAND_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 FSMC NAND interface
|
||||
(+) De-initialize the FSMC NAND interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND device according to the specified
|
||||
* control parameters in the FSMC_NAND_HandleTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Init Pointer to NAND Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_Init(FSMC_NAND_TypeDef *Device, const FSMC_NAND_InitTypeDef *Init)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Init->NandBank));
|
||||
assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature));
|
||||
assert_param(IS_FSMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth));
|
||||
assert_param(IS_FSMC_ECC_STATE(Init->EccComputation));
|
||||
assert_param(IS_FSMC_ECCPAGE_SIZE(Init->ECCPageSize));
|
||||
assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime));
|
||||
assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime));
|
||||
|
||||
/* Set NAND device control parameters */
|
||||
if (Init->NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PCR2, PCR_CLEAR_MASK, (Init->Waitfeature |
|
||||
FSMC_PCR_MEMORY_TYPE_NAND |
|
||||
Init->MemoryDataWidth |
|
||||
Init->EccComputation |
|
||||
Init->ECCPageSize |
|
||||
((Init->TCLRSetupTime) << FSMC_PCRx_TCLR_Pos) |
|
||||
((Init->TARSetupTime) << FSMC_PCRx_TAR_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PCR3, PCR_CLEAR_MASK, (Init->Waitfeature |
|
||||
FSMC_PCR_MEMORY_TYPE_NAND |
|
||||
Init->MemoryDataWidth |
|
||||
Init->EccComputation |
|
||||
Init->ECCPageSize |
|
||||
((Init->TCLRSetupTime) << FSMC_PCRx_TCLR_Pos) |
|
||||
((Init->TARSetupTime) << FSMC_PCRx_TAR_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND Common space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Timing Pointer to NAND timing structure
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_CommonSpace_Timing_Init(FSMC_NAND_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NAND device timing parameters */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PMEM2, PMEM_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PMEM3, PMEM_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND Attribute space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Timing Pointer to NAND timing structure
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_AttributeSpace_Timing_Init(FSMC_NAND_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NAND device timing parameters */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PATT2, PATT_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PATT3, PATT_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the FSMC_NAND device
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_DeInit(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Disable the NAND Bank */
|
||||
__FSMC_NAND_DISABLE(Device, Bank);
|
||||
|
||||
/* De-initialize the NAND Bank */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* Set the FSMC_NAND_BANK2 registers to their reset values */
|
||||
WRITE_REG(Device->PCR2, 0x00000018U);
|
||||
WRITE_REG(Device->SR2, 0x00000040U);
|
||||
WRITE_REG(Device->PMEM2, 0xFCFCFCFCU);
|
||||
WRITE_REG(Device->PATT2, 0xFCFCFCFCU);
|
||||
}
|
||||
/* FSMC_Bank3_NAND */
|
||||
else
|
||||
{
|
||||
/* Set the FSMC_NAND_BANK3 registers to their reset values */
|
||||
WRITE_REG(Device->PCR3, 0x00000018U);
|
||||
WRITE_REG(Device->SR3, 0x00000040U);
|
||||
WRITE_REG(Device->PMEM3, 0xFCFCFCFCU);
|
||||
WRITE_REG(Device->PATT3, 0xFCFCFCFCU);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_FSMC_NAND_Group2 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FSMC_NAND Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the FSMC NAND interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_ECC_Enable(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Enable ECC feature */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
SET_BIT(Device->PCR2, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_BIT(Device->PCR3, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_ECC_Disable(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Disable ECC feature */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
CLEAR_BIT(Device->PCR2, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(Device->PCR3, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param ECCval Pointer to ECC value
|
||||
* @param Bank NAND bank number
|
||||
* @param Timeout Timeout wait value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_GetECC(const FSMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank,
|
||||
uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until FIFO is empty */
|
||||
while (__FSMC_NAND_GET_FLAG(Device, Bank, FSMC_FLAG_FEMPT) == RESET)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* Get the ECCR2 register value */
|
||||
*ECCval = (uint32_t)Device->ECCR2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the ECCR3 register value */
|
||||
*ECCval = (uint32_t)Device->ECCR3;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
#if defined(FSMC_BANK4)
|
||||
|
||||
/** @addtogroup FSMC_LL_PCCARD
|
||||
* @brief PCCARD Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use PCCARD device driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC PCCARD bank in order
|
||||
to run the PCCARD/compact flash external devices.
|
||||
|
||||
(+) FSMC PCCARD bank reset using the function FSMC_PCCARD_DeInit()
|
||||
(+) FSMC PCCARD bank control configuration using the function FSMC_PCCARD_Init()
|
||||
(+) FSMC PCCARD bank common space timing configuration using the function
|
||||
FSMC_PCCARD_CommonSpace_Timing_Init()
|
||||
(+) FSMC PCCARD bank attribute space timing configuration using the function
|
||||
FSMC_PCCARD_AttributeSpace_Timing_Init()
|
||||
(+) FSMC PCCARD bank IO space timing configuration using the function
|
||||
FSMC_PCCARD_IOSpace_Timing_Init()
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup FSMC_LL_PCCARD_Private_Functions_Group1
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and configure the FSMC PCCARD interface
|
||||
(+) De-initialize the FSMC PCCARD interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD device according to the specified
|
||||
* control parameters in the FSMC_PCCARD_HandleTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Init Pointer to PCCARD Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_Init(FSMC_PCCARD_TypeDef *Device, const FSMC_PCCARD_InitTypeDef *Init)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature));
|
||||
assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime));
|
||||
assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set FSMC_PCCARD device control parameters */
|
||||
MODIFY_REG(Device->PCR4,
|
||||
(FSMC_PCRx_PTYP |
|
||||
FSMC_PCRx_PWAITEN |
|
||||
FSMC_PCRx_PWID |
|
||||
FSMC_PCRx_TCLR |
|
||||
FSMC_PCRx_TAR),
|
||||
(FSMC_PCR_MEMORY_TYPE_PCCARD |
|
||||
Init->Waitfeature |
|
||||
FSMC_NAND_PCC_MEM_BUS_WIDTH_16 |
|
||||
(Init->TCLRSetupTime << FSMC_PCRx_TCLR_Pos) |
|
||||
(Init->TARSetupTime << FSMC_PCRx_TAR_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD Common space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_CommonSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set PCCARD timing parameters */
|
||||
MODIFY_REG(Device->PMEM4, PMEM_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD Attribute space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_AttributeSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set PCCARD timing parameters */
|
||||
MODIFY_REG(Device->PATT4, PATT_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD IO space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_IOSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set FSMC_PCCARD device timing parameters */
|
||||
MODIFY_REG(Device->PIO4, PIO4_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
(Timing->WaitSetupTime << FSMC_PIO4_IOWAIT4_Pos) |
|
||||
(Timing->HoldSetupTime << FSMC_PIO4_IOHOLD4_Pos) |
|
||||
(Timing->HiZSetupTime << FSMC_PIO4_IOHIZ4_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the FSMC_PCCARD device
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_DeInit(FSMC_PCCARD_TypeDef *Device)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
|
||||
/* Disable the FSMC_PCCARD device */
|
||||
__FSMC_PCCARD_DISABLE(Device);
|
||||
|
||||
/* De-initialize the FSMC_PCCARD device */
|
||||
Device->PCR4 = 0x00000018U;
|
||||
Device->SR4 = 0x00000040U;
|
||||
Device->PMEM4 = 0xFCFCFCFCU;
|
||||
Device->PATT4 = 0xFCFCFCFCU;
|
||||
Device->PIO4 = 0xFCFCFCFCU;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK4 */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
256
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c
Normal file
256
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_gpio.c
|
||||
* @author MCD Application Team
|
||||
* @brief GPIO LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_gpio.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG)
|
||||
|
||||
/** @addtogroup GPIO_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup GPIO_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_GPIO_PIN(__VALUE__) ((((__VALUE__) & LL_GPIO_PIN_ALL)!= 0u) &&\
|
||||
(((__VALUE__) & (~LL_GPIO_PIN_ALL))== 0u))
|
||||
|
||||
#define IS_LL_GPIO_MODE(__VALUE__) (((__VALUE__) == LL_GPIO_MODE_ANALOG) ||\
|
||||
((__VALUE__) == LL_GPIO_MODE_FLOATING) ||\
|
||||
((__VALUE__) == LL_GPIO_MODE_INPUT) ||\
|
||||
((__VALUE__) == LL_GPIO_MODE_OUTPUT) ||\
|
||||
((__VALUE__) == LL_GPIO_MODE_ALTERNATE))
|
||||
|
||||
#define IS_LL_GPIO_SPEED(__VALUE__) (((__VALUE__) == LL_GPIO_SPEED_FREQ_LOW) ||\
|
||||
((__VALUE__) == LL_GPIO_SPEED_FREQ_MEDIUM) ||\
|
||||
((__VALUE__) == LL_GPIO_SPEED_FREQ_HIGH))
|
||||
|
||||
#define IS_LL_GPIO_OUTPUT_TYPE(__VALUE__) (((__VALUE__) == LL_GPIO_OUTPUT_PUSHPULL) ||\
|
||||
((__VALUE__) == LL_GPIO_OUTPUT_OPENDRAIN))
|
||||
|
||||
#define IS_LL_GPIO_PULL(__VALUE__) (((__VALUE__) == LL_GPIO_PULL_DOWN) ||\
|
||||
((__VALUE__) == LL_GPIO_PULL_UP))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup GPIO_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup GPIO_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize GPIO registers (Registers restored to their default values).
|
||||
* @param GPIOx GPIO Port
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: GPIO registers are de-initialized
|
||||
* - ERROR: Wrong GPIO Port
|
||||
*/
|
||||
ErrorStatus LL_GPIO_DeInit(GPIO_TypeDef *GPIOx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||
|
||||
/* Force and Release reset on clock of GPIOx Port */
|
||||
if (GPIOx == GPIOA)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOA);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOA);
|
||||
}
|
||||
else if (GPIOx == GPIOB)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOB);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOB);
|
||||
}
|
||||
else if (GPIOx == GPIOC)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOC);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOC);
|
||||
}
|
||||
else if (GPIOx == GPIOD)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOD);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOD);
|
||||
}
|
||||
#if defined(GPIOE)
|
||||
else if (GPIOx == GPIOE)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOE);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOE);
|
||||
}
|
||||
#endif
|
||||
#if defined(GPIOF)
|
||||
else if (GPIOx == GPIOF)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOF);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOF);
|
||||
}
|
||||
#endif
|
||||
#if defined(GPIOG)
|
||||
else if (GPIOx == GPIOG)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_GPIOG);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_GPIOG);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize GPIO registers according to the specified parameters in GPIO_InitStruct.
|
||||
* @param GPIOx GPIO Port
|
||||
* @param GPIO_InitStruct: pointer to a @ref LL_GPIO_InitTypeDef structure
|
||||
* that contains the configuration information for the specified GPIO peripheral.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: GPIO registers are initialized according to GPIO_InitStruct content
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
ErrorStatus LL_GPIO_Init(GPIO_TypeDef *GPIOx, LL_GPIO_InitTypeDef *GPIO_InitStruct)
|
||||
{
|
||||
uint32_t pinmask;
|
||||
uint32_t pinpos;
|
||||
uint32_t currentpin;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||
assert_param(IS_LL_GPIO_PIN(GPIO_InitStruct->Pin));
|
||||
|
||||
/* ------------------------- Configure the port pins ---------------- */
|
||||
/* Initialize pinpos on first pin set */
|
||||
|
||||
pinmask = ((GPIO_InitStruct->Pin) << GPIO_PIN_MASK_POS) >> GPIO_PIN_NB;
|
||||
pinpos = POSITION_VAL(pinmask);
|
||||
|
||||
/* Configure the port pins */
|
||||
while ((pinmask >> pinpos) != 0u)
|
||||
{
|
||||
/* skip if bit is not set */
|
||||
if ((pinmask & (1u << pinpos)) != 0u)
|
||||
{
|
||||
/* Get current io position */
|
||||
if (pinpos < GPIO_PIN_MASK_POS)
|
||||
{
|
||||
currentpin = (0x00000101uL << pinpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
currentpin = ((0x00010001u << (pinpos - GPIO_PIN_MASK_POS)) | 0x04000000u);
|
||||
}
|
||||
|
||||
if (GPIO_InitStruct->Mode == LL_GPIO_MODE_INPUT)
|
||||
{
|
||||
/* Check The Pull parameter */
|
||||
assert_param(IS_LL_GPIO_PULL(GPIO_InitStruct->Pull));
|
||||
|
||||
/* Pull-up Pull-down resistor configuration*/
|
||||
LL_GPIO_SetPinPull(GPIOx, currentpin, GPIO_InitStruct->Pull);
|
||||
}
|
||||
|
||||
/* Check Pin Mode parameters */
|
||||
assert_param(IS_LL_GPIO_MODE(GPIO_InitStruct->Mode));
|
||||
|
||||
/* Pin Mode configuration */
|
||||
LL_GPIO_SetPinMode(GPIOx, currentpin, GPIO_InitStruct->Mode);
|
||||
|
||||
if ((GPIO_InitStruct->Mode == LL_GPIO_MODE_OUTPUT) || (GPIO_InitStruct->Mode == LL_GPIO_MODE_ALTERNATE))
|
||||
{
|
||||
/* Check speed and Output mode parameters */
|
||||
assert_param(IS_LL_GPIO_SPEED(GPIO_InitStruct->Speed));
|
||||
assert_param(IS_LL_GPIO_OUTPUT_TYPE(GPIO_InitStruct->OutputType));
|
||||
|
||||
/* Speed mode configuration */
|
||||
LL_GPIO_SetPinSpeed(GPIOx, currentpin, GPIO_InitStruct->Speed);
|
||||
|
||||
/* Output mode configuration*/
|
||||
LL_GPIO_SetPinOutputType(GPIOx, currentpin, GPIO_InitStruct->OutputType);
|
||||
}
|
||||
}
|
||||
pinpos++;
|
||||
}
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_GPIO_InitTypeDef field to default value.
|
||||
* @param GPIO_InitStruct: pointer to a @ref LL_GPIO_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void LL_GPIO_StructInit(LL_GPIO_InitTypeDef *GPIO_InitStruct)
|
||||
{
|
||||
/* Reset GPIO init structure parameters values */
|
||||
GPIO_InitStruct->Pin = LL_GPIO_PIN_ALL;
|
||||
GPIO_InitStruct->Mode = LL_GPIO_MODE_FLOATING;
|
||||
GPIO_InitStruct->Speed = LL_GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct->OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
|
||||
GPIO_InitStruct->Pull = LL_GPIO_PULL_DOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (GPIOA) || defined (GPIOB) || defined (GPIOC) || defined (GPIOD) || defined (GPIOE) || defined (GPIOF) || defined (GPIOG) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
219
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_i2c.c
Normal file
219
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_i2c.c
Normal file
@@ -0,0 +1,219 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_i2c.c
|
||||
* @author MCD Application Team
|
||||
* @brief I2C LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_i2c.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#include "stm32f1xx_ll_rcc.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (I2C1) || defined (I2C2)
|
||||
|
||||
/** @defgroup I2C_LL I2C
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup I2C_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_I2C_PERIPHERAL_MODE(__VALUE__) (((__VALUE__) == LL_I2C_MODE_I2C) || \
|
||||
((__VALUE__) == LL_I2C_MODE_SMBUS_HOST) || \
|
||||
((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE) || \
|
||||
((__VALUE__) == LL_I2C_MODE_SMBUS_DEVICE_ARP))
|
||||
|
||||
#define IS_LL_I2C_CLOCK_SPEED(__VALUE__) (((__VALUE__) > 0U) && ((__VALUE__) <= LL_I2C_MAX_SPEED_FAST))
|
||||
|
||||
#define IS_LL_I2C_DUTY_CYCLE(__VALUE__) (((__VALUE__) == LL_I2C_DUTYCYCLE_2) || \
|
||||
((__VALUE__) == LL_I2C_DUTYCYCLE_16_9))
|
||||
|
||||
#define IS_LL_I2C_OWN_ADDRESS1(__VALUE__) ((__VALUE__) <= 0x000003FFU)
|
||||
|
||||
#define IS_LL_I2C_TYPE_ACKNOWLEDGE(__VALUE__) (((__VALUE__) == LL_I2C_ACK) || \
|
||||
((__VALUE__) == LL_I2C_NACK))
|
||||
|
||||
#define IS_LL_I2C_OWN_ADDRSIZE(__VALUE__) (((__VALUE__) == LL_I2C_OWNADDRESS1_7BIT) || \
|
||||
((__VALUE__) == LL_I2C_OWNADDRESS1_10BIT))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup I2C_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2C_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the I2C registers to their default reset values.
|
||||
* @param I2Cx I2C Instance.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS I2C registers are de-initialized
|
||||
* - ERROR I2C registers are not de-initialized
|
||||
*/
|
||||
uint32_t LL_I2C_DeInit(I2C_TypeDef *I2Cx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the I2C Instance I2Cx */
|
||||
assert_param(IS_I2C_ALL_INSTANCE(I2Cx));
|
||||
|
||||
if (I2Cx == I2C1)
|
||||
{
|
||||
/* Force reset of I2C clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
|
||||
/* Release reset of I2C clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C1);
|
||||
}
|
||||
#if defined(I2C2)
|
||||
else if (I2Cx == I2C2)
|
||||
{
|
||||
/* Force reset of I2C clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_I2C2);
|
||||
|
||||
/* Release reset of I2C clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_I2C2);
|
||||
|
||||
}
|
||||
#endif /* I2C2 */
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the I2C registers according to the specified parameters in I2C_InitStruct.
|
||||
* @param I2Cx I2C Instance.
|
||||
* @param I2C_InitStruct pointer to a @ref LL_I2C_InitTypeDef structure.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS I2C registers are initialized
|
||||
* - ERROR Not applicable
|
||||
*/
|
||||
uint32_t LL_I2C_Init(I2C_TypeDef *I2Cx, LL_I2C_InitTypeDef *I2C_InitStruct)
|
||||
{
|
||||
LL_RCC_ClocksTypeDef rcc_clocks;
|
||||
|
||||
/* Check the I2C Instance I2Cx */
|
||||
assert_param(IS_I2C_ALL_INSTANCE(I2Cx));
|
||||
|
||||
/* Check the I2C parameters from I2C_InitStruct */
|
||||
assert_param(IS_LL_I2C_PERIPHERAL_MODE(I2C_InitStruct->PeripheralMode));
|
||||
assert_param(IS_LL_I2C_CLOCK_SPEED(I2C_InitStruct->ClockSpeed));
|
||||
assert_param(IS_LL_I2C_DUTY_CYCLE(I2C_InitStruct->DutyCycle));
|
||||
assert_param(IS_LL_I2C_OWN_ADDRESS1(I2C_InitStruct->OwnAddress1));
|
||||
assert_param(IS_LL_I2C_TYPE_ACKNOWLEDGE(I2C_InitStruct->TypeAcknowledge));
|
||||
assert_param(IS_LL_I2C_OWN_ADDRSIZE(I2C_InitStruct->OwnAddrSize));
|
||||
|
||||
/* Disable the selected I2Cx Peripheral */
|
||||
LL_I2C_Disable(I2Cx);
|
||||
|
||||
/* Retrieve Clock frequencies */
|
||||
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
|
||||
|
||||
/*---------------------------- I2Cx SCL Clock Speed Configuration ------------
|
||||
* Configure the SCL speed :
|
||||
* - ClockSpeed: I2C_CR2_FREQ[5:0], I2C_TRISE_TRISE[5:0], I2C_CCR_FS,
|
||||
* and I2C_CCR_CCR[11:0] bits
|
||||
* - DutyCycle: I2C_CCR_DUTY[7:0] bits
|
||||
*/
|
||||
LL_I2C_ConfigSpeed(I2Cx, rcc_clocks.PCLK1_Frequency, I2C_InitStruct->ClockSpeed, I2C_InitStruct->DutyCycle);
|
||||
|
||||
/*---------------------------- I2Cx OAR1 Configuration -----------------------
|
||||
* Disable, Configure and Enable I2Cx device own address 1 with parameters :
|
||||
* - OwnAddress1: I2C_OAR1_ADD[9:8], I2C_OAR1_ADD[7:1] and I2C_OAR1_ADD0 bits
|
||||
* - OwnAddrSize: I2C_OAR1_ADDMODE bit
|
||||
*/
|
||||
LL_I2C_SetOwnAddress1(I2Cx, I2C_InitStruct->OwnAddress1, I2C_InitStruct->OwnAddrSize);
|
||||
|
||||
/*---------------------------- I2Cx MODE Configuration -----------------------
|
||||
* Configure I2Cx peripheral mode with parameter :
|
||||
* - PeripheralMode: I2C_CR1_SMBUS, I2C_CR1_SMBTYPE and I2C_CR1_ENARP bits
|
||||
*/
|
||||
LL_I2C_SetMode(I2Cx, I2C_InitStruct->PeripheralMode);
|
||||
|
||||
/* Enable the selected I2Cx Peripheral */
|
||||
LL_I2C_Enable(I2Cx);
|
||||
|
||||
/*---------------------------- I2Cx CR2 Configuration ------------------------
|
||||
* Configure the ACKnowledge or Non ACKnowledge condition
|
||||
* after the address receive match code or next received byte with parameter :
|
||||
* - TypeAcknowledge: I2C_CR2_NACK bit
|
||||
*/
|
||||
LL_I2C_AcknowledgeNextData(I2Cx, I2C_InitStruct->TypeAcknowledge);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_I2C_InitTypeDef field to default value.
|
||||
* @param I2C_InitStruct Pointer to a @ref LL_I2C_InitTypeDef structure.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_I2C_StructInit(LL_I2C_InitTypeDef *I2C_InitStruct)
|
||||
{
|
||||
/* Set I2C_InitStruct fields to default values */
|
||||
I2C_InitStruct->PeripheralMode = LL_I2C_MODE_I2C;
|
||||
I2C_InitStruct->ClockSpeed = 5000U;
|
||||
I2C_InitStruct->DutyCycle = LL_I2C_DUTYCYCLE_2;
|
||||
I2C_InitStruct->OwnAddress1 = 0U;
|
||||
I2C_InitStruct->TypeAcknowledge = LL_I2C_NACK;
|
||||
I2C_InitStruct->OwnAddrSize = LL_I2C_OWNADDRESS1_7BIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* I2C1 || I2C2 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_pwr.c
|
||||
* @author MCD Application Team
|
||||
* @brief PWR LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_pwr.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(PWR)
|
||||
|
||||
/** @defgroup PWR_LL PWR
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup PWR_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup PWR_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the PWR registers to their default reset values.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: PWR registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_PWR_DeInit(void)
|
||||
{
|
||||
/* Force reset of PWR clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_PWR);
|
||||
|
||||
/* Release reset of PWR clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_PWR);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined(PWR) */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
471
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c
Normal file
471
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c
Normal file
@@ -0,0 +1,471 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_rcc.c
|
||||
* @author MCD Application Team
|
||||
* @brief RCC LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_rcc.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(RCC)
|
||||
|
||||
/** @defgroup RCC_LL RCC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup RCC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#if defined(RCC_PLLI2S_SUPPORT)
|
||||
#define IS_LL_RCC_I2S_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_I2S2_CLKSOURCE) \
|
||||
|| ((__VALUE__) == LL_RCC_I2S3_CLKSOURCE))
|
||||
#endif /* RCC_PLLI2S_SUPPORT */
|
||||
|
||||
#if defined(USB) || defined(USB_OTG_FS)
|
||||
#define IS_LL_RCC_USB_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_USB_CLKSOURCE))
|
||||
#endif /* USB */
|
||||
|
||||
#define IS_LL_RCC_ADC_CLKSOURCE(__VALUE__) (((__VALUE__) == LL_RCC_ADC_CLKSOURCE))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup RCC_LL_Private_Functions RCC Private functions
|
||||
* @{
|
||||
*/
|
||||
uint32_t RCC_GetSystemClockFreq(void);
|
||||
uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency);
|
||||
uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency);
|
||||
uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency);
|
||||
uint32_t RCC_PLL_GetFreqDomain_SYS(void);
|
||||
#if defined(RCC_PLLI2S_SUPPORT)
|
||||
uint32_t RCC_PLLI2S_GetFreqDomain_I2S(void);
|
||||
#endif /* RCC_PLLI2S_SUPPORT */
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
uint32_t RCC_PLL2_GetFreqClockFreq(void);
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup RCC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup RCC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reset the RCC clock configuration to the default reset state.
|
||||
* @note The default reset state of the clock configuration is given below:
|
||||
* - HSI ON and used as system clock source
|
||||
* - HSE PLL, PLL2 & PLL3 are OFF
|
||||
* - AHB, APB1 and APB2 prescaler set to 1.
|
||||
* - CSS, MCO OFF
|
||||
* - All interrupts disabled
|
||||
* @note This function doesn't modify the configuration of the
|
||||
* - Peripheral clocks
|
||||
* - LSI, LSE and RTC clocks
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RCC registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_RCC_DeInit(void)
|
||||
{
|
||||
/* Set HSION bit */
|
||||
LL_RCC_HSI_Enable();
|
||||
|
||||
/* Wait for HSI READY bit */
|
||||
while (LL_RCC_HSI_IsReady() != 1U)
|
||||
{}
|
||||
|
||||
/* Configure HSI as system clock source */
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSI);
|
||||
|
||||
/* Wait till clock switch is ready */
|
||||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI)
|
||||
{}
|
||||
|
||||
/* Reset PLLON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
|
||||
|
||||
/* Wait for PLL READY bit to be reset */
|
||||
while (LL_RCC_PLL_IsReady() != 0U)
|
||||
{}
|
||||
|
||||
/* Reset CFGR register */
|
||||
LL_RCC_WriteReg(CFGR, 0x00000000U);
|
||||
|
||||
/* Reset HSEON, HSEBYP & CSSON bits */
|
||||
CLEAR_BIT(RCC->CR, (RCC_CR_CSSON | RCC_CR_HSEON | RCC_CR_HSEBYP));
|
||||
|
||||
#if defined(RCC_CR_PLL2ON)
|
||||
/* Reset PLL2ON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLL2ON);
|
||||
#endif /* RCC_CR_PLL2ON */
|
||||
|
||||
#if defined(RCC_CR_PLL3ON)
|
||||
/* Reset PLL3ON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLL3ON);
|
||||
#endif /* RCC_CR_PLL3ON */
|
||||
|
||||
/* Set HSITRIM bits to the reset value */
|
||||
LL_RCC_HSI_SetCalibTrimming(0x10U);
|
||||
|
||||
#if defined(RCC_CFGR2_PREDIV1)
|
||||
/* Reset CFGR2 register */
|
||||
LL_RCC_WriteReg(CFGR2, 0x00000000U);
|
||||
#endif /* RCC_CFGR2_PREDIV1 */
|
||||
|
||||
/* Disable all interrupts */
|
||||
LL_RCC_WriteReg(CIR, 0x00000000U);
|
||||
|
||||
/* Clear reset flags */
|
||||
LL_RCC_ClearResetFlags();
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RCC_LL_EF_Get_Freq
|
||||
* @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
|
||||
* and different peripheral clocks available on the device.
|
||||
* @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(**)
|
||||
* @note If SYSCLK source is HSE, function returns values based on HSE_VALUE(***)
|
||||
* @note If SYSCLK source is PLL, function returns values based on
|
||||
* HSI_VALUE(**) or HSE_VALUE(***) multiplied/divided by the PLL factors.
|
||||
* @note (**) HSI_VALUE is a defined constant but the real value may vary
|
||||
* depending on the variations in voltage and temperature.
|
||||
* @note (***) HSE_VALUE is a defined constant, user has to ensure that
|
||||
* HSE_VALUE is same as the real frequency of the crystal used.
|
||||
* Otherwise, this function may have wrong result.
|
||||
* @note The result of this function could be incorrect when using fractional
|
||||
* value for HSE crystal.
|
||||
* @note This function can be used by the user application to compute the
|
||||
* baud-rate for the communication peripherals or configure other parameters.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the frequencies of different on chip clocks; System, AHB, APB1 and APB2 buses clocks
|
||||
* @note Each time SYSCLK, HCLK, PCLK1 and/or PCLK2 clock changes, this function
|
||||
* must be called to update structure fields. Otherwise, any
|
||||
* configuration based on this function will be incorrect.
|
||||
* @param RCC_Clocks pointer to a @ref LL_RCC_ClocksTypeDef structure which will hold the clocks frequencies
|
||||
* @retval None
|
||||
*/
|
||||
void LL_RCC_GetSystemClocksFreq(LL_RCC_ClocksTypeDef *RCC_Clocks)
|
||||
{
|
||||
/* Get SYSCLK frequency */
|
||||
RCC_Clocks->SYSCLK_Frequency = RCC_GetSystemClockFreq();
|
||||
|
||||
/* HCLK clock frequency */
|
||||
RCC_Clocks->HCLK_Frequency = RCC_GetHCLKClockFreq(RCC_Clocks->SYSCLK_Frequency);
|
||||
|
||||
/* PCLK1 clock frequency */
|
||||
RCC_Clocks->PCLK1_Frequency = RCC_GetPCLK1ClockFreq(RCC_Clocks->HCLK_Frequency);
|
||||
|
||||
/* PCLK2 clock frequency */
|
||||
RCC_Clocks->PCLK2_Frequency = RCC_GetPCLK2ClockFreq(RCC_Clocks->HCLK_Frequency);
|
||||
}
|
||||
|
||||
#if defined(RCC_CFGR2_I2S2SRC)
|
||||
/**
|
||||
* @brief Return I2Sx clock frequency
|
||||
* @param I2SxSource This parameter can be one of the following values:
|
||||
* @arg @ref LL_RCC_I2S2_CLKSOURCE
|
||||
* @arg @ref LL_RCC_I2S3_CLKSOURCE
|
||||
* @retval I2S clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t LL_RCC_GetI2SClockFreq(uint32_t I2SxSource)
|
||||
{
|
||||
uint32_t i2s_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
|
||||
|
||||
/* Check parameter */
|
||||
assert_param(IS_LL_RCC_I2S_CLKSOURCE(I2SxSource));
|
||||
|
||||
/* I2S1CLK clock frequency */
|
||||
switch (LL_RCC_GetI2SClockSource(I2SxSource))
|
||||
{
|
||||
case LL_RCC_I2S2_CLKSOURCE_SYSCLK: /*!< System clock selected as I2S clock source */
|
||||
case LL_RCC_I2S3_CLKSOURCE_SYSCLK:
|
||||
i2s_frequency = RCC_GetSystemClockFreq();
|
||||
break;
|
||||
|
||||
case LL_RCC_I2S2_CLKSOURCE_PLLI2S_VCO: /*!< PLLI2S oscillator clock selected as I2S clock source */
|
||||
case LL_RCC_I2S3_CLKSOURCE_PLLI2S_VCO:
|
||||
default:
|
||||
i2s_frequency = RCC_PLLI2S_GetFreqDomain_I2S() * 2U;
|
||||
break;
|
||||
}
|
||||
|
||||
return i2s_frequency;
|
||||
}
|
||||
#endif /* RCC_CFGR2_I2S2SRC */
|
||||
|
||||
#if defined(USB) || defined(USB_OTG_FS)
|
||||
/**
|
||||
* @brief Return USBx clock frequency
|
||||
* @param USBxSource This parameter can be one of the following values:
|
||||
* @arg @ref LL_RCC_USB_CLKSOURCE
|
||||
* @retval USB clock frequency (in Hz)
|
||||
* @arg @ref LL_RCC_PERIPH_FREQUENCY_NO indicates that oscillator (HSI), HSE or PLL is not ready
|
||||
*/
|
||||
uint32_t LL_RCC_GetUSBClockFreq(uint32_t USBxSource)
|
||||
{
|
||||
uint32_t usb_frequency = LL_RCC_PERIPH_FREQUENCY_NO;
|
||||
|
||||
/* Check parameter */
|
||||
assert_param(IS_LL_RCC_USB_CLKSOURCE(USBxSource));
|
||||
|
||||
/* USBCLK clock frequency */
|
||||
switch (LL_RCC_GetUSBClockSource(USBxSource))
|
||||
{
|
||||
#if defined(RCC_CFGR_USBPRE)
|
||||
case LL_RCC_USB_CLKSOURCE_PLL: /* PLL clock used as USB clock source */
|
||||
if (LL_RCC_PLL_IsReady())
|
||||
{
|
||||
usb_frequency = RCC_PLL_GetFreqDomain_SYS();
|
||||
}
|
||||
break;
|
||||
|
||||
case LL_RCC_USB_CLKSOURCE_PLL_DIV_1_5: /* PLL clock divided by 1.5 used as USB clock source */
|
||||
default:
|
||||
if (LL_RCC_PLL_IsReady())
|
||||
{
|
||||
usb_frequency = (RCC_PLL_GetFreqDomain_SYS() * 3U) / 2U;
|
||||
}
|
||||
break;
|
||||
#endif /* RCC_CFGR_USBPRE */
|
||||
#if defined(RCC_CFGR_OTGFSPRE)
|
||||
/* USBCLK = PLLVCO/2
|
||||
= (2 x PLLCLK) / 2
|
||||
= PLLCLK */
|
||||
case LL_RCC_USB_CLKSOURCE_PLL_DIV_2: /* PLL clock used as USB clock source */
|
||||
if (LL_RCC_PLL_IsReady())
|
||||
{
|
||||
usb_frequency = RCC_PLL_GetFreqDomain_SYS();
|
||||
}
|
||||
break;
|
||||
|
||||
/* USBCLK = PLLVCO/3
|
||||
= (2 x PLLCLK) / 3 */
|
||||
case LL_RCC_USB_CLKSOURCE_PLL_DIV_3: /* PLL clock divided by 3 used as USB clock source */
|
||||
default:
|
||||
if (LL_RCC_PLL_IsReady())
|
||||
{
|
||||
usb_frequency = (RCC_PLL_GetFreqDomain_SYS() * 2U) / 3U;
|
||||
}
|
||||
break;
|
||||
#endif /* RCC_CFGR_OTGFSPRE */
|
||||
}
|
||||
|
||||
return usb_frequency;
|
||||
}
|
||||
#endif /* USB */
|
||||
|
||||
/**
|
||||
* @brief Return ADCx clock frequency
|
||||
* @param ADCxSource This parameter can be one of the following values:
|
||||
* @arg @ref LL_RCC_ADC_CLKSOURCE
|
||||
* @retval ADC clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t LL_RCC_GetADCClockFreq(uint32_t ADCxSource)
|
||||
{
|
||||
uint32_t adc_prescaler = 0U;
|
||||
uint32_t adc_frequency = 0U;
|
||||
|
||||
/* Check parameter */
|
||||
assert_param(IS_LL_RCC_ADC_CLKSOURCE(ADCxSource));
|
||||
|
||||
/* Get ADC prescaler */
|
||||
adc_prescaler = LL_RCC_GetADCClockSource(ADCxSource);
|
||||
|
||||
/* ADC frequency = PCLK2 frequency / ADC prescaler (2, 4, 6 or 8) */
|
||||
adc_frequency = RCC_GetPCLK2ClockFreq(RCC_GetHCLKClockFreq(RCC_GetSystemClockFreq()))
|
||||
/ (((adc_prescaler >> POSITION_VAL(ADCxSource)) + 1U) * 2U);
|
||||
|
||||
return adc_frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RCC_LL_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return SYSTEM clock frequency
|
||||
* @retval SYSTEM clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_GetSystemClockFreq(void)
|
||||
{
|
||||
uint32_t frequency = 0U;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
switch (LL_RCC_GetSysClkSource())
|
||||
{
|
||||
case LL_RCC_SYS_CLKSOURCE_STATUS_HSI: /* HSI used as system clock source */
|
||||
frequency = HSI_VALUE;
|
||||
break;
|
||||
|
||||
case LL_RCC_SYS_CLKSOURCE_STATUS_HSE: /* HSE used as system clock source */
|
||||
frequency = HSE_VALUE;
|
||||
break;
|
||||
|
||||
case LL_RCC_SYS_CLKSOURCE_STATUS_PLL: /* PLL used as system clock source */
|
||||
frequency = RCC_PLL_GetFreqDomain_SYS();
|
||||
break;
|
||||
|
||||
default:
|
||||
frequency = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return frequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return HCLK clock frequency
|
||||
* @param SYSCLK_Frequency SYSCLK clock frequency
|
||||
* @retval HCLK clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_GetHCLKClockFreq(uint32_t SYSCLK_Frequency)
|
||||
{
|
||||
/* HCLK clock frequency */
|
||||
return __LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, LL_RCC_GetAHBPrescaler());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return PCLK1 clock frequency
|
||||
* @param HCLK_Frequency HCLK clock frequency
|
||||
* @retval PCLK1 clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_GetPCLK1ClockFreq(uint32_t HCLK_Frequency)
|
||||
{
|
||||
/* PCLK1 clock frequency */
|
||||
return __LL_RCC_CALC_PCLK1_FREQ(HCLK_Frequency, LL_RCC_GetAPB1Prescaler());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return PCLK2 clock frequency
|
||||
* @param HCLK_Frequency HCLK clock frequency
|
||||
* @retval PCLK2 clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_GetPCLK2ClockFreq(uint32_t HCLK_Frequency)
|
||||
{
|
||||
/* PCLK2 clock frequency */
|
||||
return __LL_RCC_CALC_PCLK2_FREQ(HCLK_Frequency, LL_RCC_GetAPB2Prescaler());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return PLL clock frequency used for system domain
|
||||
* @retval PLL clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_PLL_GetFreqDomain_SYS(void)
|
||||
{
|
||||
uint32_t pllinputfreq = 0U, pllsource = 0U;
|
||||
|
||||
/* PLL_VCO = (HSE_VALUE, HSI_VALUE or PLL2 / PLL Predivider) * PLL Multiplicator */
|
||||
|
||||
/* Get PLL source */
|
||||
pllsource = LL_RCC_PLL_GetMainSource();
|
||||
|
||||
switch (pllsource)
|
||||
{
|
||||
case LL_RCC_PLLSOURCE_HSI_DIV_2: /* HSI used as PLL clock source */
|
||||
pllinputfreq = HSI_VALUE / 2U;
|
||||
break;
|
||||
|
||||
case LL_RCC_PLLSOURCE_HSE: /* HSE used as PLL clock source */
|
||||
pllinputfreq = HSE_VALUE / (LL_RCC_PLL_GetPrediv() + 1U);
|
||||
break;
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
case LL_RCC_PLLSOURCE_PLL2: /* PLL2 used as PLL clock source */
|
||||
pllinputfreq = RCC_PLL2_GetFreqClockFreq() / (LL_RCC_PLL_GetPrediv() + 1U);
|
||||
break;
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
default:
|
||||
pllinputfreq = HSI_VALUE / 2U;
|
||||
break;
|
||||
}
|
||||
return __LL_RCC_CALC_PLLCLK_FREQ(pllinputfreq, LL_RCC_PLL_GetMultiplicator());
|
||||
}
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
/**
|
||||
* @brief Return PLL clock frequency used for system domain
|
||||
* @retval PLL clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_PLL2_GetFreqClockFreq(void)
|
||||
{
|
||||
return __LL_RCC_CALC_PLL2CLK_FREQ(HSE_VALUE, LL_RCC_PLL2_GetMultiplicator(), LL_RCC_HSE_GetPrediv2());
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
#if defined(RCC_PLLI2S_SUPPORT)
|
||||
/**
|
||||
* @brief Return PLL clock frequency used for system domain
|
||||
* @retval PLL clock frequency (in Hz)
|
||||
*/
|
||||
uint32_t RCC_PLLI2S_GetFreqDomain_I2S(void)
|
||||
{
|
||||
return __LL_RCC_CALC_PLLI2SCLK_FREQ(HSE_VALUE, LL_RCC_PLLI2S_GetMultiplicator(), LL_RCC_HSE_GetPrediv2());
|
||||
}
|
||||
#endif /* RCC_PLLI2S_SUPPORT */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined(RCC) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
541
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rtc.c
Normal file
541
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rtc.c
Normal file
@@ -0,0 +1,541 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_rtc.c
|
||||
* @author MCD Application Team
|
||||
* @brief RTC LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_rtc.h"
|
||||
#include "stm32f1xx_ll_cortex.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(RTC)
|
||||
|
||||
/** @addtogroup RTC_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @addtogroup RTC_LL_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
/* Default values used for prescaler */
|
||||
#define RTC_ASYNCH_PRESC_DEFAULT 0x00007FFFU
|
||||
|
||||
/* Values used for timeout */
|
||||
#define RTC_INITMODE_TIMEOUT 1000U /* 1s when tick set to 1ms */
|
||||
#define RTC_SYNCHRO_TIMEOUT 1000U /* 1s when tick set to 1ms */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup RTC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_RTC_ASYNCH_PREDIV(__VALUE__) ((__VALUE__) <= 0xFFFFFU)
|
||||
|
||||
#define IS_LL_RTC_FORMAT(__VALUE__) (((__VALUE__) == LL_RTC_FORMAT_BIN) \
|
||||
|| ((__VALUE__) == LL_RTC_FORMAT_BCD))
|
||||
|
||||
#define IS_LL_RTC_HOUR24(__HOUR__) ((__HOUR__) <= 23U)
|
||||
#define IS_LL_RTC_MINUTES(__MINUTES__) ((__MINUTES__) <= 59U)
|
||||
#define IS_LL_RTC_SECONDS(__SECONDS__) ((__SECONDS__) <= 59U)
|
||||
#define IS_LL_RTC_CALIB_OUTPUT(__OUTPUT__) (((__OUTPUT__) == LL_RTC_CALIB_OUTPUT_NONE) || \
|
||||
((__OUTPUT__) == LL_RTC_CALIB_OUTPUT_RTCCLOCK) || \
|
||||
((__OUTPUT__) == LL_RTC_CALIB_OUTPUT_ALARM) || \
|
||||
((__OUTPUT__) == LL_RTC_CALIB_OUTPUT_SECOND))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup RTC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup RTC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the RTC registers to their default reset values.
|
||||
* @note This function doesn't reset the RTC Clock source and RTC Backup Data
|
||||
* registers.
|
||||
* @param RTCx RTC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC registers are de-initialized
|
||||
* - ERROR: RTC registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_RTC_DeInit(RTC_TypeDef *RTCx)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
LL_RTC_DisableWriteProtection(RTCx);
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
LL_RTC_WriteReg(RTCx, CNTL, 0x0000);
|
||||
LL_RTC_WriteReg(RTCx, CNTH, 0x0000);
|
||||
LL_RTC_WriteReg(RTCx, PRLH, 0x0000);
|
||||
LL_RTC_WriteReg(RTCx, PRLL, 0x8000);
|
||||
LL_RTC_WriteReg(RTCx, CRH, 0x0000);
|
||||
LL_RTC_WriteReg(RTCx, CRL, 0x0020);
|
||||
|
||||
/* Reset Tamper and alternate functions configuration register */
|
||||
LL_RTC_WriteReg(BKP, RTCCR, 0x00000000U);
|
||||
LL_RTC_WriteReg(BKP, CR, 0x00000000U);
|
||||
LL_RTC_WriteReg(BKP, CSR, 0x00000000U);
|
||||
|
||||
/* Exit Initialization Mode */
|
||||
if (LL_RTC_ExitInitMode(RTCx) != ERROR)
|
||||
{
|
||||
/* Wait till the RTC RSF flag is set */
|
||||
status = LL_RTC_WaitForSynchro(RTCx);
|
||||
|
||||
/* Clear RSF Flag */
|
||||
LL_RTC_ClearFlag_RS(RTCx);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
LL_RTC_EnableWriteProtection(RTCx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable the write protection for RTC registers */
|
||||
LL_RTC_EnableWriteProtection(RTCx);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC registers according to the specified parameters
|
||||
* in RTC_InitStruct.
|
||||
* @param RTCx RTC Instance
|
||||
* @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure that contains
|
||||
* the configuration information for the RTC peripheral.
|
||||
* @note The RTC Prescaler register is write protected and can be written in
|
||||
* initialization mode only.
|
||||
* @note the user should call LL_RTC_StructInit() or the structure of Prescaler
|
||||
* need to be initialized before RTC init()
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC registers are initialized
|
||||
* - ERROR: RTC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_RTC_Init(RTC_TypeDef *RTCx, LL_RTC_InitTypeDef *RTC_InitStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
assert_param(IS_LL_RTC_ASYNCH_PREDIV(RTC_InitStruct->AsynchPrescaler));
|
||||
assert_param(IS_LL_RTC_CALIB_OUTPUT(RTC_InitStruct->OutPutSource));
|
||||
/* Waiting for synchro */
|
||||
if (LL_RTC_WaitForSynchro(RTCx) != ERROR)
|
||||
{
|
||||
/* Set Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
/* Clear Flag Bits */
|
||||
LL_RTC_ClearFlag_ALR(RTCx);
|
||||
LL_RTC_ClearFlag_OW(RTCx);
|
||||
LL_RTC_ClearFlag_SEC(RTCx);
|
||||
|
||||
if (RTC_InitStruct->OutPutSource != LL_RTC_CALIB_OUTPUT_NONE)
|
||||
{
|
||||
/* Disable the selected Tamper Pin */
|
||||
LL_RTC_TAMPER_Disable(BKP);
|
||||
}
|
||||
/* Set the signal which will be routed to RTC Tamper Pin */
|
||||
LL_RTC_SetOutputSource(BKP, RTC_InitStruct->OutPutSource);
|
||||
|
||||
/* Configure Synchronous and Asynchronous prescaler factor */
|
||||
LL_RTC_SetAsynchPrescaler(RTCx, RTC_InitStruct->AsynchPrescaler);
|
||||
|
||||
/* Exit Initialization Mode */
|
||||
LL_RTC_ExitInitMode(RTCx);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_RTC_InitTypeDef field to default value.
|
||||
* @param RTC_InitStruct pointer to a @ref LL_RTC_InitTypeDef structure which will be initialized.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_RTC_StructInit(LL_RTC_InitTypeDef *RTC_InitStruct)
|
||||
{
|
||||
/* Set RTC_InitStruct fields to default values */
|
||||
RTC_InitStruct->AsynchPrescaler = RTC_ASYNCH_PRESC_DEFAULT;
|
||||
RTC_InitStruct->OutPutSource = LL_RTC_CALIB_OUTPUT_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the RTC current time.
|
||||
* @param RTCx RTC Instance
|
||||
* @param RTC_Format This parameter can be one of the following values:
|
||||
* @arg @ref LL_RTC_FORMAT_BIN
|
||||
* @arg @ref LL_RTC_FORMAT_BCD
|
||||
* @param RTC_TimeStruct pointer to a RTC_TimeTypeDef structure that contains
|
||||
* the time configuration information for the RTC.
|
||||
* @note The user should call LL_RTC_TIME_StructInit() or the structure
|
||||
* of time need to be initialized before time init()
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC Time register is configured
|
||||
* - ERROR: RTC Time register is not configured
|
||||
*/
|
||||
ErrorStatus LL_RTC_TIME_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
uint32_t counter_time = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
assert_param(IS_LL_RTC_FORMAT(RTC_Format));
|
||||
|
||||
if (RTC_Format == LL_RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_LL_RTC_HOUR24(RTC_TimeStruct->Hours));
|
||||
assert_param(IS_LL_RTC_MINUTES(RTC_TimeStruct->Minutes));
|
||||
assert_param(IS_LL_RTC_SECONDS(RTC_TimeStruct->Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours)));
|
||||
assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Minutes)));
|
||||
assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Seconds)));
|
||||
}
|
||||
|
||||
/* Enter Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
/* Check the input parameters format */
|
||||
if (RTC_Format == LL_RTC_FORMAT_BIN)
|
||||
{
|
||||
counter_time = (uint32_t)(((uint32_t)RTC_TimeStruct->Hours * 3600U) + \
|
||||
((uint32_t)RTC_TimeStruct->Minutes * 60U) + \
|
||||
((uint32_t)RTC_TimeStruct->Seconds));
|
||||
LL_RTC_TIME_Set(RTCx, counter_time);
|
||||
}
|
||||
else
|
||||
{
|
||||
counter_time = (((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Hours)) * 3600U) + \
|
||||
((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Minutes)) * 60U) + \
|
||||
((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_TimeStruct->Seconds))));
|
||||
LL_RTC_TIME_Set(RTCx, counter_time);
|
||||
}
|
||||
status = SUCCESS;
|
||||
}
|
||||
/* Exit Initialization mode */
|
||||
LL_RTC_ExitInitMode(RTCx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_RTC_TimeTypeDef field to default value (Time = 00h:00min:00sec).
|
||||
* @param RTC_TimeStruct pointer to a @ref LL_RTC_TimeTypeDef structure which will be initialized.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_RTC_TIME_StructInit(LL_RTC_TimeTypeDef *RTC_TimeStruct)
|
||||
{
|
||||
/* Time = 00h:00min:00sec */
|
||||
RTC_TimeStruct->Hours = 0U;
|
||||
RTC_TimeStruct->Minutes = 0U;
|
||||
RTC_TimeStruct->Seconds = 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the RTC Alarm.
|
||||
* @param RTCx RTC Instance
|
||||
* @param RTC_Format This parameter can be one of the following values:
|
||||
* @arg @ref LL_RTC_FORMAT_BIN
|
||||
* @arg @ref LL_RTC_FORMAT_BCD
|
||||
* @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure that
|
||||
* contains the alarm configuration parameters.
|
||||
* @note the user should call LL_RTC_ALARM_StructInit() or the structure
|
||||
* of Alarm need to be initialized before Alarm init()
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ALARM registers are configured
|
||||
* - ERROR: ALARM registers are not configured
|
||||
*/
|
||||
ErrorStatus LL_RTC_ALARM_Init(RTC_TypeDef *RTCx, uint32_t RTC_Format, LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
uint32_t counter_alarm = 0U;
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
assert_param(IS_LL_RTC_FORMAT(RTC_Format));
|
||||
|
||||
if (RTC_Format == LL_RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_LL_RTC_HOUR24(RTC_AlarmStruct->AlarmTime.Hours));
|
||||
assert_param(IS_LL_RTC_MINUTES(RTC_AlarmStruct->AlarmTime.Minutes));
|
||||
assert_param(IS_LL_RTC_SECONDS(RTC_AlarmStruct->AlarmTime.Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_LL_RTC_HOUR24(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)));
|
||||
assert_param(IS_LL_RTC_MINUTES(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes)));
|
||||
assert_param(IS_LL_RTC_SECONDS(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds)));
|
||||
}
|
||||
|
||||
/* Enter Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
/* Check the input parameters format */
|
||||
if (RTC_Format == LL_RTC_FORMAT_BIN)
|
||||
{
|
||||
counter_alarm = (uint32_t)(((uint32_t)RTC_AlarmStruct->AlarmTime.Hours * 3600U) + \
|
||||
((uint32_t)RTC_AlarmStruct->AlarmTime.Minutes * 60U) + \
|
||||
((uint32_t)RTC_AlarmStruct->AlarmTime.Seconds));
|
||||
LL_RTC_ALARM_Set(RTCx, counter_alarm);
|
||||
}
|
||||
else
|
||||
{
|
||||
counter_alarm = (((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Hours)) * 3600U) + \
|
||||
((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Minutes)) * 60U) + \
|
||||
((uint32_t)(__LL_RTC_CONVERT_BCD2BIN(RTC_AlarmStruct->AlarmTime.Seconds))));
|
||||
LL_RTC_ALARM_Set(RTCx, counter_alarm);
|
||||
}
|
||||
status = SUCCESS;
|
||||
}
|
||||
/* Exit Initialization mode */
|
||||
LL_RTC_ExitInitMode(RTCx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_RTC_AlarmTypeDef of ALARM field to default value (Time = 00h:00mn:00sec /
|
||||
* Day = 1st day of the month/Mask = all fields are masked).
|
||||
* @param RTC_AlarmStruct pointer to a @ref LL_RTC_AlarmTypeDef structure which will be initialized.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_RTC_ALARM_StructInit(LL_RTC_AlarmTypeDef *RTC_AlarmStruct)
|
||||
{
|
||||
/* Alarm Time Settings : Time = 00h:00mn:00sec */
|
||||
RTC_AlarmStruct->AlarmTime.Hours = 0U;
|
||||
RTC_AlarmStruct->AlarmTime.Minutes = 0U;
|
||||
RTC_AlarmStruct->AlarmTime.Seconds = 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters the RTC Initialization mode.
|
||||
* @param RTCx RTC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC is in Init mode
|
||||
* - ERROR: RTC is not in Init mode
|
||||
*/
|
||||
ErrorStatus LL_RTC_EnterInitMode(RTC_TypeDef *RTCx)
|
||||
{
|
||||
__IO uint32_t timeout = RTC_INITMODE_TIMEOUT;
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
tmp = LL_RTC_IsActiveFlag_RTOF(RTCx);
|
||||
while ((timeout != 0U) && (tmp != 1U))
|
||||
{
|
||||
if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
|
||||
{
|
||||
timeout --;
|
||||
}
|
||||
tmp = LL_RTC_IsActiveFlag_RTOF(RTCx);
|
||||
if (timeout == 0U)
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
LL_RTC_DisableWriteProtection(RTCx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit the RTC Initialization mode.
|
||||
* @note When the initialization sequence is complete, the calendar restarts
|
||||
* counting after 4 RTCCLK cycles.
|
||||
* @param RTCx RTC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC exited from in Init mode
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
ErrorStatus LL_RTC_ExitInitMode(RTC_TypeDef *RTCx)
|
||||
{
|
||||
__IO uint32_t timeout = RTC_INITMODE_TIMEOUT;
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Disable initialization mode */
|
||||
LL_RTC_EnableWriteProtection(RTCx);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
tmp = LL_RTC_IsActiveFlag_RTOF(RTCx);
|
||||
while ((timeout != 0U) && (tmp != 1U))
|
||||
{
|
||||
if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
|
||||
{
|
||||
timeout --;
|
||||
}
|
||||
tmp = LL_RTC_IsActiveFlag_RTOF(RTCx);
|
||||
if (timeout == 0U)
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the Time Counter
|
||||
* @param RTCx RTC Instance
|
||||
* @param TimeCounter this value can be from 0 to 0xFFFFFFFF
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC Counter register configured
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
ErrorStatus LL_RTC_TIME_SetCounter(RTC_TypeDef *RTCx, uint32_t TimeCounter)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Enter Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
LL_RTC_TIME_Set(RTCx, TimeCounter);
|
||||
status = SUCCESS;
|
||||
}
|
||||
/* Exit Initialization mode */
|
||||
LL_RTC_ExitInitMode(RTCx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Alarm Counter.
|
||||
* @param RTCx RTC Instance
|
||||
* @param AlarmCounter this value can be from 0 to 0xFFFFFFFF
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC exited from in Init mode
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
ErrorStatus LL_RTC_ALARM_SetCounter(RTC_TypeDef *RTCx, uint32_t AlarmCounter)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Enter Initialization mode */
|
||||
if (LL_RTC_EnterInitMode(RTCx) != ERROR)
|
||||
{
|
||||
LL_RTC_ALARM_Set(RTCx, AlarmCounter);
|
||||
status = SUCCESS;
|
||||
}
|
||||
/* Exit Initialization mode */
|
||||
LL_RTC_ExitInitMode(RTCx);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits until the RTC registers are synchronized with RTC APB clock.
|
||||
* @note The RTC Resynchronization mode is write protected, use the
|
||||
* @ref LL_RTC_DisableWriteProtection before calling this function.
|
||||
* @param RTCx RTC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: RTC registers are synchronised
|
||||
* - ERROR: RTC registers are not synchronised
|
||||
*/
|
||||
ErrorStatus LL_RTC_WaitForSynchro(RTC_TypeDef *RTCx)
|
||||
{
|
||||
__IO uint32_t timeout = RTC_SYNCHRO_TIMEOUT;
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(RTCx));
|
||||
|
||||
/* Clear RSF flag */
|
||||
LL_RTC_ClearFlag_RS(RTCx);
|
||||
|
||||
/* Wait the registers to be synchronised */
|
||||
tmp = LL_RTC_IsActiveFlag_RS(RTCx);
|
||||
while ((timeout != 0U) && (tmp != 0U))
|
||||
{
|
||||
if (LL_SYSTICK_IsActiveCounterFlag() == 1U)
|
||||
{
|
||||
timeout--;
|
||||
}
|
||||
tmp = LL_RTC_IsActiveFlag_RS(RTCx);
|
||||
if (timeout == 0U)
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined(RTC) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
1578
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_sdmmc.c
Normal file
1578
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_sdmmc.c
Normal file
@@ -0,0 +1,1578 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_sdmmc.c
|
||||
* @author MCD Application Team
|
||||
* @brief SDMMC Low Layer HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the SDMMC peripheral:
|
||||
* + Initialization/de-initialization functions
|
||||
* + I/O 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
|
||||
==============================================================================
|
||||
##### SDMMC peripheral features #####
|
||||
==============================================================================
|
||||
[..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB
|
||||
peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
|
||||
devices.
|
||||
|
||||
[..] The SDMMC features include the following:
|
||||
(+) Full compliance with MultiMedia Card System Specification Version 4.2. Card support
|
||||
for three different databus modes: 1-bit (default), 4-bit and 8-bit
|
||||
(+) Full compatibility with previous versions of MultiMedia Cards (forward compatibility)
|
||||
(+) Full compliance with SD Memory Card Specifications Version 2.0
|
||||
(+) Full compliance with SD I/O Card Specification Version 2.0: card support for two
|
||||
different data bus modes: 1-bit (default) and 4-bit
|
||||
(+) Full support of the CE-ATA features (full compliance with CE-ATA digital protocol
|
||||
Rev1.1)
|
||||
(+) Data transfer up to 48 MHz for the 8 bit mode
|
||||
(+) Data and command output enable signals to control external bidirectional drivers
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a considered as a driver of service for external devices drivers
|
||||
that interfaces with the SDMMC peripheral.
|
||||
According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
|
||||
is used in the device's driver to perform SDMMC operations and functionalities.
|
||||
|
||||
This driver is almost transparent for the final user, it is only used to implement other
|
||||
functionalities of the external device.
|
||||
|
||||
[..]
|
||||
(+) The SDMMC clock (SDMMCCLK = 48 MHz) is coming from a specific output (MSI, PLLUSB1CLK,
|
||||
PLLUSB2CLK). Before start working with SDMMC peripheral make sure that the
|
||||
PLL is well configured.
|
||||
The SDMMC peripheral uses two clock signals:
|
||||
(++) SDMMC adapter clock (SDMMCCLK = 48 MHz)
|
||||
(++) APB2 bus clock (PCLK2)
|
||||
|
||||
-@@- PCLK2 and SDMMC_CK clock frequencies must respect the following condition:
|
||||
Frequency(PCLK2) >= (3 / 8 x Frequency(SDMMC_CK))
|
||||
|
||||
(+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
|
||||
peripheral.
|
||||
|
||||
(+) Enable the Power ON State using the SDIO_PowerState_ON()
|
||||
function and disable it using the function SDIO_PowerState_OFF().
|
||||
|
||||
(+) Enable/Disable the clock using the __SDIO_ENABLE()/__SDIO_DISABLE() macros.
|
||||
|
||||
(+) Enable/Disable the peripheral interrupts using the macros __SDIO_ENABLE_IT()
|
||||
and __SDIO_DISABLE_IT() if you need to use interrupt mode.
|
||||
|
||||
(+) When using the DMA mode
|
||||
(++) Configure the DMA in the MSP layer of the external device
|
||||
(++) Active the needed channel Request
|
||||
(++) Enable the DMA using __SDIO_DMA_ENABLE() macro or Disable it using the macro
|
||||
__SDIO_DMA_DISABLE().
|
||||
|
||||
(+) To control the CPSM (Command Path State Machine) and send
|
||||
commands to the card use the SDIO_SendCommand(),
|
||||
SDIO_GetCommandResponse() and SDIO_GetResponse() functions. First, user has
|
||||
to fill the command structure (pointer to SDIO_CmdInitTypeDef) according
|
||||
to the selected command to be sent.
|
||||
The parameters that should be filled are:
|
||||
(++) Command Argument
|
||||
(++) Command Index
|
||||
(++) Command Response type
|
||||
(++) Command Wait
|
||||
(++) CPSM Status (Enable or Disable).
|
||||
|
||||
-@@- To check if the command is well received, read the SDIO_CMDRESP
|
||||
register using the SDIO_GetCommandResponse().
|
||||
The SDMMC responses registers (SDIO_RESP1 to SDIO_RESP2), use the
|
||||
SDIO_GetResponse() function.
|
||||
|
||||
(+) To control the DPSM (Data Path State Machine) and send/receive
|
||||
data to/from the card use the SDIO_DataConfig(), SDIO_GetDataCounter(),
|
||||
SDIO_ReadFIFO(), SDIO_WriteFIFO() and SDIO_GetFIFOCount() functions.
|
||||
|
||||
*** Read Operations ***
|
||||
=======================
|
||||
[..]
|
||||
(#) First, user has to fill the data structure (pointer to
|
||||
SDIO_DataInitTypeDef) according to the selected data type to be received.
|
||||
The parameters that should be filled are:
|
||||
(++) Data TimeOut
|
||||
(++) Data Length
|
||||
(++) Data Block size
|
||||
(++) Data Transfer direction: should be from card (To SDMMC)
|
||||
(++) Data Transfer mode
|
||||
(++) DPSM Status (Enable or Disable)
|
||||
|
||||
(#) Configure the SDMMC resources to receive the data from the card
|
||||
according to selected transfer mode (Refer to Step 8, 9 and 10).
|
||||
|
||||
(#) Send the selected Read command (refer to step 11).
|
||||
|
||||
(#) Use the SDIO flags/interrupts to check the transfer status.
|
||||
|
||||
*** Write Operations ***
|
||||
========================
|
||||
[..]
|
||||
(#) First, user has to fill the data structure (pointer to
|
||||
SDIO_DataInitTypeDef) according to the selected data type to be received.
|
||||
The parameters that should be filled are:
|
||||
(++) Data TimeOut
|
||||
(++) Data Length
|
||||
(++) Data Block size
|
||||
(++) Data Transfer direction: should be to card (To CARD)
|
||||
(++) Data Transfer mode
|
||||
(++) DPSM Status (Enable or Disable)
|
||||
|
||||
(#) Configure the SDMMC resources to send the data to the card according to
|
||||
selected transfer mode.
|
||||
|
||||
(#) Send the selected Write command.
|
||||
|
||||
(#) Use the SDIO flags/interrupts to check the transfer status.
|
||||
|
||||
*** Command management operations ***
|
||||
=====================================
|
||||
[..]
|
||||
(#) The commands used for Read/Write/Erase operations are managed in
|
||||
separate functions.
|
||||
Each function allows to send the needed command with the related argument,
|
||||
then check the response.
|
||||
By the same approach, you could implement a command and check the response.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(SDIO)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SDMMC_LL SDMMC Low Layer
|
||||
* @brief Low layer module for SD
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_MMC_MODULE_ENABLED)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx);
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization/de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the SDMMC according to the specified
|
||||
* parameters in the SDMMC_InitTypeDef and create the associated handle.
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @param Init: SDMMC initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init)
|
||||
{
|
||||
uint32_t tmpreg = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(SDIOx));
|
||||
assert_param(IS_SDIO_CLOCK_EDGE(Init.ClockEdge));
|
||||
assert_param(IS_SDIO_CLOCK_BYPASS(Init.ClockBypass));
|
||||
assert_param(IS_SDIO_CLOCK_POWER_SAVE(Init.ClockPowerSave));
|
||||
assert_param(IS_SDIO_BUS_WIDE(Init.BusWide));
|
||||
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
|
||||
assert_param(IS_SDIO_CLKDIV(Init.ClockDiv));
|
||||
|
||||
/* Set SDMMC configuration parameters */
|
||||
tmpreg |= (Init.ClockEdge |\
|
||||
Init.ClockBypass |\
|
||||
Init.ClockPowerSave |\
|
||||
Init.BusWide |\
|
||||
Init.HardwareFlowControl |\
|
||||
Init.ClockDiv
|
||||
);
|
||||
|
||||
/* Write to SDMMC CLKCR */
|
||||
MODIFY_REG(SDIOx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### I/O operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the SDMMC data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read data (word) from Rx FIFO in blocking mode (polling)
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDIO_ReadFIFO(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
/* Read data from Rx FIFO */
|
||||
return (SDIOx->FIFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write data (word) to Tx FIFO in blocking mode (polling)
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @param pWriteData: pointer to data to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_WriteFIFO(SDIO_TypeDef *SDIOx, uint32_t *pWriteData)
|
||||
{
|
||||
/* Write data to FIFO */
|
||||
SDIOx->FIFO = *pWriteData;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SDMMC data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set SDMMC Power state to ON.
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_PowerState_ON(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
/* Set power state to ON */
|
||||
SDIOx->POWER = SDIO_POWER_PWRCTRL;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set SDMMC Power state to OFF.
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_PowerState_OFF(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
/* Set power state to OFF */
|
||||
SDIOx->POWER = (uint32_t)0x00000000;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get SDMMC Power state.
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @retval Power status of the controller. The returned value can be one of the
|
||||
* following values:
|
||||
* - 0x00: Power OFF
|
||||
* - 0x02: Power UP
|
||||
* - 0x03: Power ON
|
||||
*/
|
||||
uint32_t SDIO_GetPowerState(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
return (SDIOx->POWER & SDIO_POWER_PWRCTRL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the SDMMC command path according to the specified parameters in
|
||||
* SDIO_CmdInitTypeDef structure and send the command
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @param Command: pointer to a SDIO_CmdInitTypeDef structure that contains
|
||||
* the configuration information for the SDMMC command
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_SendCommand(SDIO_TypeDef *SDIOx, SDIO_CmdInitTypeDef *Command)
|
||||
{
|
||||
uint32_t tmpreg = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_CMD_INDEX(Command->CmdIndex));
|
||||
assert_param(IS_SDIO_RESPONSE(Command->Response));
|
||||
assert_param(IS_SDIO_WAIT(Command->WaitForInterrupt));
|
||||
assert_param(IS_SDIO_CPSM(Command->CPSM));
|
||||
|
||||
/* Set the SDMMC Argument value */
|
||||
SDIOx->ARG = Command->Argument;
|
||||
|
||||
/* Set SDMMC command parameters */
|
||||
tmpreg |= (uint32_t)(Command->CmdIndex |\
|
||||
Command->Response |\
|
||||
Command->WaitForInterrupt |\
|
||||
Command->CPSM);
|
||||
|
||||
/* Write to SDMMC CMD register */
|
||||
MODIFY_REG(SDIOx->CMD, CMD_CLEAR_MASK, tmpreg);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the command index of last command for which response received
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @retval Command index of the last command response received
|
||||
*/
|
||||
uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
return (uint8_t)(SDIOx->RESPCMD);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the response received from the card for the last command
|
||||
* @param SDIOx: Pointer to SDMMC register base
|
||||
* @param Response: Specifies the SDMMC response register.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SDIO_RESP1: Response Register 1
|
||||
* @arg SDIO_RESP2: Response Register 2
|
||||
* @arg SDIO_RESP3: Response Register 3
|
||||
* @arg SDIO_RESP4: Response Register 4
|
||||
* @retval The Corresponding response register value
|
||||
*/
|
||||
uint32_t SDIO_GetResponse(SDIO_TypeDef *SDIOx, uint32_t Response)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_RESP(Response));
|
||||
|
||||
/* Get the response */
|
||||
tmp = (uint32_t)(&(SDIOx->RESP1)) + Response;
|
||||
|
||||
return (*(__IO uint32_t *) tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the SDMMC data path according to the specified
|
||||
* parameters in the SDIO_DataInitTypeDef.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param Data : pointer to a SDIO_DataInitTypeDef structure
|
||||
* that contains the configuration information for the SDMMC data.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_ConfigData(SDIO_TypeDef *SDIOx, SDIO_DataInitTypeDef* Data)
|
||||
{
|
||||
uint32_t tmpreg = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_DATA_LENGTH(Data->DataLength));
|
||||
assert_param(IS_SDIO_BLOCK_SIZE(Data->DataBlockSize));
|
||||
assert_param(IS_SDIO_TRANSFER_DIR(Data->TransferDir));
|
||||
assert_param(IS_SDIO_TRANSFER_MODE(Data->TransferMode));
|
||||
assert_param(IS_SDIO_DPSM(Data->DPSM));
|
||||
|
||||
/* Set the SDMMC Data TimeOut value */
|
||||
SDIOx->DTIMER = Data->DataTimeOut;
|
||||
|
||||
/* Set the SDMMC DataLength value */
|
||||
SDIOx->DLEN = Data->DataLength;
|
||||
|
||||
/* Set the SDMMC data configuration parameters */
|
||||
tmpreg |= (uint32_t)(Data->DataBlockSize |\
|
||||
Data->TransferDir |\
|
||||
Data->TransferMode |\
|
||||
Data->DPSM);
|
||||
|
||||
/* Write to SDMMC DCTRL */
|
||||
MODIFY_REG(SDIOx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
|
||||
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns number of remaining data bytes to be transferred.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval Number of remaining data bytes to be transferred
|
||||
*/
|
||||
uint32_t SDIO_GetDataCounter(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
return (SDIOx->DCOUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the FIFO data
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval Data received
|
||||
*/
|
||||
uint32_t SDIO_GetFIFOCount(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
return (SDIOx->FIFO);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets one of the two options of inserting read wait interval.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param SDIO_ReadWaitMode: SDMMC Read Wait operation mode.
|
||||
* This parameter can be:
|
||||
* @arg SDIO_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
|
||||
* @arg SDIO_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode));
|
||||
|
||||
/* Set SDMMC read wait mode */
|
||||
MODIFY_REG(SDIOx->DCTRL, SDIO_DCTRL_RWMOD, SDIO_ReadWaitMode);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup HAL_SDMMC_LL_Group4 Command management functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Commands management functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the needed commands.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send the Data Block Length command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)BlockSize;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_BLOCKLEN;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_BLOCKLEN, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Read Single Block command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_SINGLE_BLOCK;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Read Multi Block command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)ReadAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_READ_MULT_BLOCK;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Write Single Block command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_SINGLE_BLOCK;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Write Multi Block command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)WriteAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_WRITE_MULT_BLOCK;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_MULT_BLOCK, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Start Address Erase command for SD and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_START;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the End Address Erase command for SD and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_ERASE_GRP_END;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Start Address Erase command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)StartAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_START;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the End Address Erase command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)EndAdd;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE_GRP_END;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Erase command and check the response
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdErase(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Set Block Size for Card */
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ERASE;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE, SDIO_MAXERASETIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Stop Transfer command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdStopTransfer(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD12 STOP_TRANSMISSION */
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_STOP_TRANSMISSION;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_STOP_TRANSMISSION, SDIO_STOPTRANSFERTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Select Deselect command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param addr: Address of the card to be selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSelDesel(SDIO_TypeDef *SDIOx, uint64_t Addr)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD7 SDMMC_SEL_DESEL_CARD */
|
||||
sdmmc_cmdinit.Argument = (uint32_t)Addr;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEL_DESEL_CARD;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEL_DESEL_CARD, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Go Idle State command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdGoIdleState(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_GO_IDLE_STATE;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_NO;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdError(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Operating Condition command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdOperCond(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD8 to verify SD card interface operating condition */
|
||||
/* Argument: - [31:12]: Reserved (shall be set to '0')
|
||||
- [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
|
||||
- [7:0]: Check Pattern (recommended 0xAA) */
|
||||
/* CMD Response: R7 */
|
||||
sdmmc_cmdinit.Argument = SDMMC_CHECK_PATTERN;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp7(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Application command to verify that that the next command
|
||||
* is an application specific com-mand rather than a standard command
|
||||
* and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param Argument: Command Argument
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdAppCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = (uint32_t)Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_CMD;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
/* If there is a HAL_ERROR, it is a MMC card, else
|
||||
it is a SD card: SD card 2.0 (voltage range mismatch)
|
||||
or SD card 1.x */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_CMD, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the command asking the accessed card to send its operating
|
||||
* condition register (OCR)
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param Argument: Command Argument
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdAppOperCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = SDMMC_VOLTAGE_WINDOW_SD | Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_OP_COND;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp3(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Bus Width command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param BusWidth: BusWidth
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdBusWidth(SDIO_TypeDef *SDIOx, uint32_t BusWidth)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = (uint32_t)BusWidth;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Send SCR command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD51 SD_APP_SEND_SCR */
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_SEND_SCR;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_SEND_SCR, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Send CID command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD2 ALL_SEND_CID */
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_ALL_SEND_CID;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp2(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Send CSD command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param Argument: Command Argument
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD9 SEND_CSD */
|
||||
sdmmc_cmdinit.Argument = Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_CSD;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_LONG;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp2(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Send CSD command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param pRCA: Card RCA
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD3 SD_CMD_SET_REL_ADDR */
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp6(SDIOx, SDMMC_CMD_SET_REL_ADDR, pRCA);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Set Relative Address command to MMC card (not SD card).
|
||||
* @param SDIOx Pointer to SDIO register base
|
||||
* @param RCA Card RCA
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD3 SD_CMD_SET_REL_ADDR */
|
||||
sdmmc_cmdinit.Argument = ((uint32_t)RCA << 16U);
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SET_REL_ADDR;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_REL_ADDR, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Status command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @param Argument: Command Argument
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_STATUS;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEND_STATUS, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Status register command and check the response.
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = 0U;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SD_APP_STATUS;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_STATUS, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends host capacity support information and activates the card's
|
||||
* initialization process. Send SDMMC_CMD_SEND_OP_COND command
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @parame Argument: Argument used for the command
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
sdmmc_cmdinit.Argument = Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_SEND_OP_COND;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp3(SDIOx);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
|
||||
* @param SDIOx: Pointer to SDIO register base
|
||||
* @parame Argument: Argument used for the command
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
|
||||
/* CMD Response: R1 */
|
||||
sdmmc_cmdinit.Argument = Argument; /* SDMMC_SDR25_SWITCH_PATTERN */
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SWITCH;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SWITCH, SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send the Send EXT_CSD command and check the response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @param Argument Command Argument
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
|
||||
{
|
||||
SDIO_CmdInitTypeDef sdmmc_cmdinit;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send CMD9 SEND_CSD */
|
||||
sdmmc_cmdinit.Argument = Argument;
|
||||
sdmmc_cmdinit.CmdIndex = SDMMC_CMD_HS_SEND_EXT_CSD;
|
||||
sdmmc_cmdinit.Response = SDIO_RESPONSE_SHORT;
|
||||
sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
|
||||
sdmmc_cmdinit.CPSM = SDIO_CPSM_ENABLE;
|
||||
(void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
|
||||
|
||||
/* Check for error conditions */
|
||||
errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT);
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
|
||||
* @brief Responses functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Responses management functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the needed responses.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Checks for error conditions for R1 response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @param SD_CMD: The sent command index
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
|
||||
{
|
||||
uint32_t response_r1;
|
||||
uint32_t sta_reg;
|
||||
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The Timeout is expressed in ms */
|
||||
uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
sta_reg = SDIOx->STA;
|
||||
}while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
||||
((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
||||
|
||||
if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
||||
|
||||
return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
||||
}
|
||||
else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
||||
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
||||
|
||||
/* Check response received is of desired command */
|
||||
if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
|
||||
{
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
|
||||
/* We have received response, retrieve it for analysis */
|
||||
response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
|
||||
|
||||
if((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
|
||||
{
|
||||
return SDMMC_ERROR_NONE;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
|
||||
{
|
||||
return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
|
||||
{
|
||||
return SDMMC_ERROR_ADDR_MISALIGNED;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
|
||||
{
|
||||
return SDMMC_ERROR_BLOCK_LEN_ERR;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
|
||||
{
|
||||
return SDMMC_ERROR_ERASE_SEQ_ERR;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
|
||||
{
|
||||
return SDMMC_ERROR_BAD_ERASE_PARAM;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
|
||||
{
|
||||
return SDMMC_ERROR_WRITE_PROT_VIOLATION;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
|
||||
{
|
||||
return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
|
||||
{
|
||||
return SDMMC_ERROR_COM_CRC_FAILED;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
|
||||
{
|
||||
return SDMMC_ERROR_ILLEGAL_CMD;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
|
||||
{
|
||||
return SDMMC_ERROR_CARD_ECC_FAILED;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
|
||||
{
|
||||
return SDMMC_ERROR_CC_ERR;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
|
||||
{
|
||||
return SDMMC_ERROR_STREAM_READ_UNDERRUN;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
|
||||
{
|
||||
return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
|
||||
{
|
||||
return SDMMC_ERROR_CID_CSD_OVERWRITE;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
|
||||
{
|
||||
return SDMMC_ERROR_WP_ERASE_SKIP;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
|
||||
{
|
||||
return SDMMC_ERROR_CARD_ECC_DISABLED;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
|
||||
{
|
||||
return SDMMC_ERROR_ERASE_RESET;
|
||||
}
|
||||
else if((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
|
||||
{
|
||||
return SDMMC_ERROR_AKE_SEQ_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for error conditions for R2 (CID or CSD) response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
uint32_t sta_reg;
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The SDIO_CMDTIMEOUT is expressed in ms */
|
||||
uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
sta_reg = SDIOx->STA;
|
||||
}while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
||||
((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
||||
|
||||
if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
||||
|
||||
return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
||||
}
|
||||
else if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
||||
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No error flag set */
|
||||
/* Clear all the static flags */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
||||
}
|
||||
|
||||
return SDMMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for error conditions for R3 (OCR) response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
uint32_t sta_reg;
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The SDIO_CMDTIMEOUT is expressed in ms */
|
||||
uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
sta_reg = SDIOx->STA;
|
||||
}while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
||||
((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
||||
|
||||
if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
||||
|
||||
return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
||||
}
|
||||
|
||||
return SDMMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for error conditions for R6 (RCA) response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @param SD_CMD: The sent command index
|
||||
* @param pRCA: Pointer to the variable that will contain the SD card relative
|
||||
* address RCA
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA)
|
||||
{
|
||||
uint32_t response_r1;
|
||||
uint32_t sta_reg;
|
||||
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The SDIO_CMDTIMEOUT is expressed in ms */
|
||||
uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
sta_reg = SDIOx->STA;
|
||||
}while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
||||
((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
||||
|
||||
if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
||||
|
||||
return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
||||
}
|
||||
else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
||||
{
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
||||
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Check response received is of desired command */
|
||||
if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
|
||||
{
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
||||
|
||||
/* We have received response, retrieve it. */
|
||||
response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
|
||||
|
||||
if((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD | SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
|
||||
{
|
||||
*pRCA = (uint16_t) (response_r1 >> 16);
|
||||
|
||||
return SDMMC_ERROR_NONE;
|
||||
}
|
||||
else if((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
|
||||
{
|
||||
return SDMMC_ERROR_ILLEGAL_CMD;
|
||||
}
|
||||
else if((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
|
||||
{
|
||||
return SDMMC_ERROR_COM_CRC_FAILED;
|
||||
}
|
||||
else
|
||||
{
|
||||
return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for error conditions for R7 response.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
uint32_t sta_reg;
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The SDIO_CMDTIMEOUT is expressed in ms */
|
||||
uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
sta_reg = SDIOx->STA;
|
||||
}while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
|
||||
((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
|
||||
|
||||
if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
|
||||
{
|
||||
/* Card is SD V2.0 compliant */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
|
||||
|
||||
return SDMMC_ERROR_CMD_RSP_TIMEOUT;
|
||||
}
|
||||
else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
|
||||
{
|
||||
/* Card is SD V2.0 compliant */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
|
||||
|
||||
return SDMMC_ERROR_CMD_CRC_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDREND))
|
||||
{
|
||||
/* Card is SD V2.0 compliant */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CMDREND);
|
||||
}
|
||||
|
||||
return SDMMC_ERROR_NONE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/** @addtogroup SD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Checks for error conditions for CMD0.
|
||||
* @param SDIOx Pointer to SDMMC register base
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx)
|
||||
{
|
||||
/* 8 is the number of required instructions cycles for the below loop statement.
|
||||
The SDIO_CMDTIMEOUT is expressed in ms */
|
||||
uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
|
||||
|
||||
do
|
||||
{
|
||||
if (count-- == 0U)
|
||||
{
|
||||
return SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
|
||||
}while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT));
|
||||
|
||||
/* Clear all the static flags */
|
||||
__SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
|
||||
|
||||
return SDMMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SDIO */
|
||||
529
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_spi.c
Normal file
529
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_spi.c
Normal file
@@ -0,0 +1,529 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_spi.c
|
||||
* @author MCD Application Team
|
||||
* @brief SPI LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_spi.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#include "stm32f1xx_ll_rcc.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (SPI1) || defined (SPI2) || defined (SPI3)
|
||||
|
||||
/** @addtogroup SPI_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @defgroup SPI_LL_Private_Constants SPI Private Constants
|
||||
* @{
|
||||
*/
|
||||
/* SPI registers Masks */
|
||||
#define SPI_CR1_CLEAR_MASK (SPI_CR1_CPHA | SPI_CR1_CPOL | SPI_CR1_MSTR | \
|
||||
SPI_CR1_BR | SPI_CR1_LSBFIRST | SPI_CR1_SSI | \
|
||||
SPI_CR1_SSM | SPI_CR1_RXONLY | SPI_CR1_DFF | \
|
||||
SPI_CR1_CRCNEXT | SPI_CR1_CRCEN | SPI_CR1_BIDIOE | \
|
||||
SPI_CR1_BIDIMODE)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup SPI_LL_Private_Macros SPI Private Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_SPI_TRANSFER_DIRECTION(__VALUE__) (((__VALUE__) == LL_SPI_FULL_DUPLEX) \
|
||||
|| ((__VALUE__) == LL_SPI_SIMPLEX_RX) \
|
||||
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_RX) \
|
||||
|| ((__VALUE__) == LL_SPI_HALF_DUPLEX_TX))
|
||||
|
||||
#define IS_LL_SPI_MODE(__VALUE__) (((__VALUE__) == LL_SPI_MODE_MASTER) \
|
||||
|| ((__VALUE__) == LL_SPI_MODE_SLAVE))
|
||||
|
||||
#define IS_LL_SPI_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_SPI_DATAWIDTH_8BIT) \
|
||||
|| ((__VALUE__) == LL_SPI_DATAWIDTH_16BIT))
|
||||
|
||||
#define IS_LL_SPI_POLARITY(__VALUE__) (((__VALUE__) == LL_SPI_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_SPI_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_SPI_PHASE(__VALUE__) (((__VALUE__) == LL_SPI_PHASE_1EDGE) \
|
||||
|| ((__VALUE__) == LL_SPI_PHASE_2EDGE))
|
||||
|
||||
#define IS_LL_SPI_NSS(__VALUE__) (((__VALUE__) == LL_SPI_NSS_SOFT) \
|
||||
|| ((__VALUE__) == LL_SPI_NSS_HARD_INPUT) \
|
||||
|| ((__VALUE__) == LL_SPI_NSS_HARD_OUTPUT))
|
||||
|
||||
#define IS_LL_SPI_BAUDRATE(__VALUE__) (((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV2) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV4) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV8) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV16) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV32) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV64) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV128) \
|
||||
|| ((__VALUE__) == LL_SPI_BAUDRATEPRESCALER_DIV256))
|
||||
|
||||
#define IS_LL_SPI_BITORDER(__VALUE__) (((__VALUE__) == LL_SPI_LSB_FIRST) \
|
||||
|| ((__VALUE__) == LL_SPI_MSB_FIRST))
|
||||
|
||||
#define IS_LL_SPI_CRCCALCULATION(__VALUE__) (((__VALUE__) == LL_SPI_CRCCALCULATION_ENABLE) \
|
||||
|| ((__VALUE__) == LL_SPI_CRCCALCULATION_DISABLE))
|
||||
|
||||
#define IS_LL_SPI_CRC_POLYNOMIAL(__VALUE__) ((__VALUE__) >= 0x1U)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup SPI_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the SPI registers to their default reset values.
|
||||
* @param SPIx SPI Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are de-initialized
|
||||
* - ERROR: SPI registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_SPI_DeInit(const SPI_TypeDef *SPIx)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
|
||||
|
||||
#if defined(SPI1)
|
||||
if (SPIx == SPI1)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_SPI1);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI1 */
|
||||
#if defined(SPI2)
|
||||
if (SPIx == SPI2)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI2);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI2 */
|
||||
#if defined(SPI3)
|
||||
if (SPIx == SPI3)
|
||||
{
|
||||
/* Force reset of SPI clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_SPI3);
|
||||
|
||||
/* Release reset of SPI clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_SPI3);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
#endif /* SPI3 */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI registers according to the specified parameters in SPI_InitStruct.
|
||||
* @note As some bits in SPI configuration registers can only be written when the
|
||||
* SPI is disabled (SPI_CR1_SPE bit = 0), SPI peripheral should be in disabled state prior
|
||||
* calling this function. Otherwise, ERROR result will be returned.
|
||||
* @param SPIx SPI Instance
|
||||
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value. (Return always SUCCESS)
|
||||
*/
|
||||
ErrorStatus LL_SPI_Init(SPI_TypeDef *SPIx, LL_SPI_InitTypeDef *SPI_InitStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the SPI Instance SPIx*/
|
||||
assert_param(IS_SPI_ALL_INSTANCE(SPIx));
|
||||
|
||||
/* Check the SPI parameters from SPI_InitStruct*/
|
||||
assert_param(IS_LL_SPI_TRANSFER_DIRECTION(SPI_InitStruct->TransferDirection));
|
||||
assert_param(IS_LL_SPI_MODE(SPI_InitStruct->Mode));
|
||||
assert_param(IS_LL_SPI_DATAWIDTH(SPI_InitStruct->DataWidth));
|
||||
assert_param(IS_LL_SPI_POLARITY(SPI_InitStruct->ClockPolarity));
|
||||
assert_param(IS_LL_SPI_PHASE(SPI_InitStruct->ClockPhase));
|
||||
assert_param(IS_LL_SPI_NSS(SPI_InitStruct->NSS));
|
||||
assert_param(IS_LL_SPI_BAUDRATE(SPI_InitStruct->BaudRate));
|
||||
assert_param(IS_LL_SPI_BITORDER(SPI_InitStruct->BitOrder));
|
||||
assert_param(IS_LL_SPI_CRCCALCULATION(SPI_InitStruct->CRCCalculation));
|
||||
|
||||
if (LL_SPI_IsEnabled(SPIx) == 0x00000000U)
|
||||
{
|
||||
/*---------------------------- SPIx CR1 Configuration ------------------------
|
||||
* Configure SPIx CR1 with parameters:
|
||||
* - TransferDirection: SPI_CR1_BIDIMODE, SPI_CR1_BIDIOE and SPI_CR1_RXONLY bits
|
||||
* - Master/Slave Mode: SPI_CR1_MSTR bit
|
||||
* - DataWidth: SPI_CR1_DFF bit
|
||||
* - ClockPolarity: SPI_CR1_CPOL bit
|
||||
* - ClockPhase: SPI_CR1_CPHA bit
|
||||
* - NSS management: SPI_CR1_SSM bit
|
||||
* - BaudRate prescaler: SPI_CR1_BR[2:0] bits
|
||||
* - BitOrder: SPI_CR1_LSBFIRST bit
|
||||
* - CRCCalculation: SPI_CR1_CRCEN bit
|
||||
*/
|
||||
MODIFY_REG(SPIx->CR1,
|
||||
SPI_CR1_CLEAR_MASK,
|
||||
SPI_InitStruct->TransferDirection | SPI_InitStruct->Mode | SPI_InitStruct->DataWidth |
|
||||
SPI_InitStruct->ClockPolarity | SPI_InitStruct->ClockPhase |
|
||||
SPI_InitStruct->NSS | SPI_InitStruct->BaudRate |
|
||||
SPI_InitStruct->BitOrder | SPI_InitStruct->CRCCalculation);
|
||||
|
||||
/*---------------------------- SPIx CR2 Configuration ------------------------
|
||||
* Configure SPIx CR2 with parameters:
|
||||
* - NSS management: SSOE bit
|
||||
*/
|
||||
MODIFY_REG(SPIx->CR2, SPI_CR2_SSOE, (SPI_InitStruct->NSS >> 16U));
|
||||
|
||||
/*---------------------------- SPIx CRCPR Configuration ----------------------
|
||||
* Configure SPIx CRCPR with parameters:
|
||||
* - CRCPoly: CRCPOLY[15:0] bits
|
||||
*/
|
||||
if (SPI_InitStruct->CRCCalculation == LL_SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
assert_param(IS_LL_SPI_CRC_POLYNOMIAL(SPI_InitStruct->CRCPoly));
|
||||
LL_SPI_SetCRCPolynomial(SPIx, SPI_InitStruct->CRCPoly);
|
||||
}
|
||||
status = SUCCESS;
|
||||
}
|
||||
|
||||
#if defined (SPI_I2S_SUPPORT)
|
||||
/* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
|
||||
CLEAR_BIT(SPIx->I2SCFGR, SPI_I2SCFGR_I2SMOD);
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_SPI_InitTypeDef field to default value.
|
||||
* @param SPI_InitStruct pointer to a @ref LL_SPI_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_SPI_StructInit(LL_SPI_InitTypeDef *SPI_InitStruct)
|
||||
{
|
||||
/* Set SPI_InitStruct fields to default values */
|
||||
SPI_InitStruct->TransferDirection = LL_SPI_FULL_DUPLEX;
|
||||
SPI_InitStruct->Mode = LL_SPI_MODE_SLAVE;
|
||||
SPI_InitStruct->DataWidth = LL_SPI_DATAWIDTH_8BIT;
|
||||
SPI_InitStruct->ClockPolarity = LL_SPI_POLARITY_LOW;
|
||||
SPI_InitStruct->ClockPhase = LL_SPI_PHASE_1EDGE;
|
||||
SPI_InitStruct->NSS = LL_SPI_NSS_HARD_INPUT;
|
||||
SPI_InitStruct->BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV2;
|
||||
SPI_InitStruct->BitOrder = LL_SPI_MSB_FIRST;
|
||||
SPI_InitStruct->CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
|
||||
SPI_InitStruct->CRCPoly = 7U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined(SPI_I2S_SUPPORT)
|
||||
/** @addtogroup I2S_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @defgroup I2S_LL_Private_Constants I2S Private Constants
|
||||
* @{
|
||||
*/
|
||||
/* I2S registers Masks */
|
||||
#define I2S_I2SCFGR_CLEAR_MASK (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \
|
||||
SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \
|
||||
SPI_I2SCFGR_I2SCFG | SPI_I2SCFGR_I2SMOD )
|
||||
|
||||
#define I2S_I2SPR_CLEAR_MASK 0x0002U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup I2S_LL_Private_Macros I2S Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_I2S_DATAFORMAT(__VALUE__) (((__VALUE__) == LL_I2S_DATAFORMAT_16B) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_16B_EXTENDED) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_24B) \
|
||||
|| ((__VALUE__) == LL_I2S_DATAFORMAT_32B))
|
||||
|
||||
#define IS_LL_I2S_CPOL(__VALUE__) (((__VALUE__) == LL_I2S_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_I2S_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_I2S_STANDARD(__VALUE__) (((__VALUE__) == LL_I2S_STANDARD_PHILIPS) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_MSB) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_LSB) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_PCM_SHORT) \
|
||||
|| ((__VALUE__) == LL_I2S_STANDARD_PCM_LONG))
|
||||
|
||||
#define IS_LL_I2S_MODE(__VALUE__) (((__VALUE__) == LL_I2S_MODE_SLAVE_TX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_SLAVE_RX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_MASTER_TX) \
|
||||
|| ((__VALUE__) == LL_I2S_MODE_MASTER_RX))
|
||||
|
||||
#define IS_LL_I2S_MCLK_OUTPUT(__VALUE__) (((__VALUE__) == LL_I2S_MCLK_OUTPUT_ENABLE) \
|
||||
|| ((__VALUE__) == LL_I2S_MCLK_OUTPUT_DISABLE))
|
||||
|
||||
#define IS_LL_I2S_AUDIO_FREQ(__VALUE__) ((((__VALUE__) >= LL_I2S_AUDIOFREQ_8K) \
|
||||
&& ((__VALUE__) <= LL_I2S_AUDIOFREQ_192K)) \
|
||||
|| ((__VALUE__) == LL_I2S_AUDIOFREQ_DEFAULT))
|
||||
|
||||
#define IS_LL_I2S_PRESCALER_LINEAR(__VALUE__) ((__VALUE__) >= 0x2U)
|
||||
|
||||
#define IS_LL_I2S_PRESCALER_PARITY(__VALUE__) (((__VALUE__) == LL_I2S_PRESCALER_PARITY_EVEN) \
|
||||
|| ((__VALUE__) == LL_I2S_PRESCALER_PARITY_ODD))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup I2S_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the SPI/I2S registers to their default reset values.
|
||||
* @param SPIx SPI Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are de-initialized
|
||||
* - ERROR: SPI registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_I2S_DeInit(const SPI_TypeDef *SPIx)
|
||||
{
|
||||
return LL_SPI_DeInit(SPIx);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the SPI/I2S registers according to the specified parameters in I2S_InitStruct.
|
||||
* @note As some bits in SPI configuration registers can only be written when the SPI is disabled (SPI_CR1_SPE bit =0),
|
||||
* SPI peripheral should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
|
||||
* @param SPIx SPI Instance
|
||||
* @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: SPI registers are Initialized
|
||||
* - ERROR: SPI registers are not Initialized
|
||||
*/
|
||||
ErrorStatus LL_I2S_Init(SPI_TypeDef *SPIx, LL_I2S_InitTypeDef *I2S_InitStruct)
|
||||
{
|
||||
uint32_t i2sdiv = 2U;
|
||||
uint32_t i2sodd = 0U;
|
||||
uint32_t packetlength = 1U;
|
||||
uint32_t tmp;
|
||||
LL_RCC_ClocksTypeDef rcc_clocks;
|
||||
uint32_t sourceclock;
|
||||
ErrorStatus status = ERROR;
|
||||
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(SPIx));
|
||||
assert_param(IS_LL_I2S_MODE(I2S_InitStruct->Mode));
|
||||
assert_param(IS_LL_I2S_STANDARD(I2S_InitStruct->Standard));
|
||||
assert_param(IS_LL_I2S_DATAFORMAT(I2S_InitStruct->DataFormat));
|
||||
assert_param(IS_LL_I2S_MCLK_OUTPUT(I2S_InitStruct->MCLKOutput));
|
||||
assert_param(IS_LL_I2S_AUDIO_FREQ(I2S_InitStruct->AudioFreq));
|
||||
assert_param(IS_LL_I2S_CPOL(I2S_InitStruct->ClockPolarity));
|
||||
|
||||
if (LL_I2S_IsEnabled(SPIx) == 0x00000000U)
|
||||
{
|
||||
/*---------------------------- SPIx I2SCFGR Configuration --------------------
|
||||
* Configure SPIx I2SCFGR with parameters:
|
||||
* - Mode: SPI_I2SCFGR_I2SCFG[1:0] bit
|
||||
* - Standard: SPI_I2SCFGR_I2SSTD[1:0] and SPI_I2SCFGR_PCMSYNC bits
|
||||
* - DataFormat: SPI_I2SCFGR_CHLEN and SPI_I2SCFGR_DATLEN bits
|
||||
* - ClockPolarity: SPI_I2SCFGR_CKPOL bit
|
||||
*/
|
||||
|
||||
/* Write to SPIx I2SCFGR */
|
||||
MODIFY_REG(SPIx->I2SCFGR,
|
||||
I2S_I2SCFGR_CLEAR_MASK,
|
||||
I2S_InitStruct->Mode | I2S_InitStruct->Standard |
|
||||
I2S_InitStruct->DataFormat | I2S_InitStruct->ClockPolarity |
|
||||
SPI_I2SCFGR_I2SMOD);
|
||||
|
||||
/*---------------------------- SPIx I2SPR Configuration ----------------------
|
||||
* Configure SPIx I2SPR with parameters:
|
||||
* - MCLKOutput: SPI_I2SPR_MCKOE bit
|
||||
* - AudioFreq: SPI_I2SPR_I2SDIV[7:0] and SPI_I2SPR_ODD bits
|
||||
*/
|
||||
|
||||
/* If the requested audio frequency is not the default, compute the prescaler (i2sodd, i2sdiv)
|
||||
* else, default values are used: i2sodd = 0U, i2sdiv = 2U.
|
||||
*/
|
||||
if (I2S_InitStruct->AudioFreq != LL_I2S_AUDIOFREQ_DEFAULT)
|
||||
{
|
||||
/* Check the frame length (For the Prescaler computing)
|
||||
* Default value: LL_I2S_DATAFORMAT_16B (packetlength = 1U).
|
||||
*/
|
||||
if (I2S_InitStruct->DataFormat != LL_I2S_DATAFORMAT_16B)
|
||||
{
|
||||
/* Packet length is 32 bits */
|
||||
packetlength = 2U;
|
||||
}
|
||||
|
||||
/* I2S Clock source is System clock: Get System Clock frequency */
|
||||
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
|
||||
|
||||
/* Get the source clock value: based on System Clock value */
|
||||
sourceclock = rcc_clocks.SYSCLK_Frequency;
|
||||
|
||||
/* Compute the Real divider depending on the MCLK output state with a floating point */
|
||||
if (I2S_InitStruct->MCLKOutput == LL_I2S_MCLK_OUTPUT_ENABLE)
|
||||
{
|
||||
/* MCLK output is enabled */
|
||||
tmp = (((((sourceclock / 256U) * 10U) / I2S_InitStruct->AudioFreq)) + 5U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MCLK output is disabled */
|
||||
tmp = (((((sourceclock / (32U * packetlength)) * 10U) / I2S_InitStruct->AudioFreq)) + 5U);
|
||||
}
|
||||
|
||||
/* Remove the floating point */
|
||||
tmp = tmp / 10U;
|
||||
|
||||
/* Check the parity of the divider */
|
||||
i2sodd = (tmp & (uint16_t)0x0001U);
|
||||
|
||||
/* Compute the i2sdiv prescaler */
|
||||
i2sdiv = ((tmp - i2sodd) / 2U);
|
||||
|
||||
/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
|
||||
i2sodd = (i2sodd << 8U);
|
||||
}
|
||||
|
||||
/* Test if the divider is 1 or 0 or greater than 0xFF */
|
||||
if ((i2sdiv < 2U) || (i2sdiv > 0xFFU))
|
||||
{
|
||||
/* Set the default values */
|
||||
i2sdiv = 2U;
|
||||
i2sodd = 0U;
|
||||
}
|
||||
|
||||
/* Write to SPIx I2SPR register the computed value */
|
||||
WRITE_REG(SPIx->I2SPR, i2sdiv | i2sodd | I2S_InitStruct->MCLKOutput);
|
||||
|
||||
status = SUCCESS;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_I2S_InitTypeDef field to default value.
|
||||
* @param I2S_InitStruct pointer to a @ref LL_I2S_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_I2S_StructInit(LL_I2S_InitTypeDef *I2S_InitStruct)
|
||||
{
|
||||
/*--------------- Reset I2S init structure parameters values -----------------*/
|
||||
I2S_InitStruct->Mode = LL_I2S_MODE_SLAVE_TX;
|
||||
I2S_InitStruct->Standard = LL_I2S_STANDARD_PHILIPS;
|
||||
I2S_InitStruct->DataFormat = LL_I2S_DATAFORMAT_16B;
|
||||
I2S_InitStruct->MCLKOutput = LL_I2S_MCLK_OUTPUT_DISABLE;
|
||||
I2S_InitStruct->AudioFreq = LL_I2S_AUDIOFREQ_DEFAULT;
|
||||
I2S_InitStruct->ClockPolarity = LL_I2S_POLARITY_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set linear and parity prescaler.
|
||||
* @note To calculate value of PrescalerLinear(I2SDIV[7:0] bits) and PrescalerParity(ODD bit)\n
|
||||
* Check Audio frequency table and formulas inside Reference Manual (SPI/I2S).
|
||||
* @param SPIx SPI Instance
|
||||
* @param PrescalerLinear value Min_Data=0x02 and Max_Data=0xFF.
|
||||
* @param PrescalerParity This parameter can be one of the following values:
|
||||
* @arg @ref LL_I2S_PRESCALER_PARITY_EVEN
|
||||
* @arg @ref LL_I2S_PRESCALER_PARITY_ODD
|
||||
* @retval None
|
||||
*/
|
||||
void LL_I2S_ConfigPrescaler(SPI_TypeDef *SPIx, uint32_t PrescalerLinear, uint32_t PrescalerParity)
|
||||
{
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(SPIx));
|
||||
assert_param(IS_LL_I2S_PRESCALER_LINEAR(PrescalerLinear));
|
||||
assert_param(IS_LL_I2S_PRESCALER_PARITY(PrescalerParity));
|
||||
|
||||
/* Write to SPIx I2SPR */
|
||||
MODIFY_REG(SPIx->I2SPR, SPI_I2SPR_I2SDIV | SPI_I2SPR_ODD, PrescalerLinear | (PrescalerParity << 8U));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
|
||||
#endif /* defined (SPI1) || defined (SPI2) || defined (SPI3) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
1202
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_tim.c
Normal file
1202
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_tim.c
Normal file
@@ -0,0 +1,1202 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_tim.c
|
||||
* @author MCD Application Team
|
||||
* @brief TIM LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_tim.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (TIM1) || defined (TIM2) || defined (TIM3) || defined (TIM4) || defined (TIM5) || defined (TIM6) || defined (TIM7) || defined (TIM8) || defined (TIM9) || defined (TIM10) || defined (TIM11) || defined (TIM12) || defined (TIM13) || defined (TIM14) || defined (TIM15) || defined (TIM16) || defined (TIM17)
|
||||
|
||||
/** @addtogroup TIM_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup TIM_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_TIM_COUNTERMODE(__VALUE__) (((__VALUE__) == LL_TIM_COUNTERMODE_UP) \
|
||||
|| ((__VALUE__) == LL_TIM_COUNTERMODE_DOWN) \
|
||||
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP) \
|
||||
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_DOWN) \
|
||||
|| ((__VALUE__) == LL_TIM_COUNTERMODE_CENTER_UP_DOWN))
|
||||
|
||||
#define IS_LL_TIM_CLOCKDIVISION(__VALUE__) (((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV1) \
|
||||
|| ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV2) \
|
||||
|| ((__VALUE__) == LL_TIM_CLOCKDIVISION_DIV4))
|
||||
|
||||
#define IS_LL_TIM_OCMODE(__VALUE__) (((__VALUE__) == LL_TIM_OCMODE_FROZEN) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_ACTIVE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_INACTIVE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_TOGGLE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_FORCED_INACTIVE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_FORCED_ACTIVE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_PWM1) \
|
||||
|| ((__VALUE__) == LL_TIM_OCMODE_PWM2))
|
||||
|
||||
#define IS_LL_TIM_OCSTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCSTATE_DISABLE) \
|
||||
|| ((__VALUE__) == LL_TIM_OCSTATE_ENABLE))
|
||||
|
||||
#define IS_LL_TIM_OCPOLARITY(__VALUE__) (((__VALUE__) == LL_TIM_OCPOLARITY_HIGH) \
|
||||
|| ((__VALUE__) == LL_TIM_OCPOLARITY_LOW))
|
||||
|
||||
#define IS_LL_TIM_OCIDLESTATE(__VALUE__) (((__VALUE__) == LL_TIM_OCIDLESTATE_LOW) \
|
||||
|| ((__VALUE__) == LL_TIM_OCIDLESTATE_HIGH))
|
||||
|
||||
#define IS_LL_TIM_ACTIVEINPUT(__VALUE__) (((__VALUE__) == LL_TIM_ACTIVEINPUT_DIRECTTI) \
|
||||
|| ((__VALUE__) == LL_TIM_ACTIVEINPUT_INDIRECTTI) \
|
||||
|| ((__VALUE__) == LL_TIM_ACTIVEINPUT_TRC))
|
||||
|
||||
#define IS_LL_TIM_ICPSC(__VALUE__) (((__VALUE__) == LL_TIM_ICPSC_DIV1) \
|
||||
|| ((__VALUE__) == LL_TIM_ICPSC_DIV2) \
|
||||
|| ((__VALUE__) == LL_TIM_ICPSC_DIV4) \
|
||||
|| ((__VALUE__) == LL_TIM_ICPSC_DIV8))
|
||||
|
||||
#define IS_LL_TIM_IC_FILTER(__VALUE__) (((__VALUE__) == LL_TIM_IC_FILTER_FDIV1) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N2) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N4) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV1_N8) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N6) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV2_N8) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N6) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV4_N8) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N6) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV8_N8) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N5) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N6) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV16_N8) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N5) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N6) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_FILTER_FDIV32_N8))
|
||||
|
||||
#define IS_LL_TIM_IC_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING))
|
||||
|
||||
#define IS_LL_TIM_ENCODERMODE(__VALUE__) (((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI1) \
|
||||
|| ((__VALUE__) == LL_TIM_ENCODERMODE_X2_TI2) \
|
||||
|| ((__VALUE__) == LL_TIM_ENCODERMODE_X4_TI12))
|
||||
|
||||
#define IS_LL_TIM_IC_POLARITY_ENCODER(__VALUE__) (((__VALUE__) == LL_TIM_IC_POLARITY_RISING) \
|
||||
|| ((__VALUE__) == LL_TIM_IC_POLARITY_FALLING))
|
||||
|
||||
#define IS_LL_TIM_OSSR_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSR_DISABLE) \
|
||||
|| ((__VALUE__) == LL_TIM_OSSR_ENABLE))
|
||||
|
||||
#define IS_LL_TIM_OSSI_STATE(__VALUE__) (((__VALUE__) == LL_TIM_OSSI_DISABLE) \
|
||||
|| ((__VALUE__) == LL_TIM_OSSI_ENABLE))
|
||||
|
||||
#define IS_LL_TIM_LOCK_LEVEL(__VALUE__) (((__VALUE__) == LL_TIM_LOCKLEVEL_OFF) \
|
||||
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_1) \
|
||||
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_2) \
|
||||
|| ((__VALUE__) == LL_TIM_LOCKLEVEL_3))
|
||||
|
||||
#define IS_LL_TIM_BREAK_STATE(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_DISABLE) \
|
||||
|| ((__VALUE__) == LL_TIM_BREAK_ENABLE))
|
||||
|
||||
#define IS_LL_TIM_BREAK_POLARITY(__VALUE__) (((__VALUE__) == LL_TIM_BREAK_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_TIM_BREAK_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(__VALUE__) (((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_DISABLE) \
|
||||
|| ((__VALUE__) == LL_TIM_AUTOMATICOUTPUT_ENABLE))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup TIM_LL_Private_Functions TIM Private Functions
|
||||
* @{
|
||||
*/
|
||||
static ErrorStatus OC1Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
|
||||
static ErrorStatus OC2Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
|
||||
static ErrorStatus OC3Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
|
||||
static ErrorStatus OC4Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct);
|
||||
static ErrorStatus IC1Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
|
||||
static ErrorStatus IC2Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
|
||||
static ErrorStatus IC3Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
|
||||
static ErrorStatus IC4Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup TIM_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup TIM_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set TIMx registers to their reset values.
|
||||
* @param TIMx Timer instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: invalid TIMx instance
|
||||
*/
|
||||
ErrorStatus LL_TIM_DeInit(const TIM_TypeDef *TIMx)
|
||||
{
|
||||
ErrorStatus result = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_INSTANCE(TIMx));
|
||||
|
||||
if (TIMx == TIM2)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM2);
|
||||
}
|
||||
#if defined(TIM1)
|
||||
else if (TIMx == TIM1)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM1);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM1);
|
||||
}
|
||||
#endif /* TIM1 */
|
||||
#if defined(TIM3)
|
||||
else if (TIMx == TIM3)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM3);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM3);
|
||||
}
|
||||
#endif /* TIM3 */
|
||||
#if defined(TIM4)
|
||||
else if (TIMx == TIM4)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM4);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM4);
|
||||
}
|
||||
#endif /* TIM4 */
|
||||
#if defined(TIM5)
|
||||
else if (TIMx == TIM5)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM5);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM5);
|
||||
}
|
||||
#endif /* TIM5 */
|
||||
#if defined(TIM6)
|
||||
else if (TIMx == TIM6)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM6);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM6);
|
||||
}
|
||||
#endif /* TIM6 */
|
||||
#if defined (TIM7)
|
||||
else if (TIMx == TIM7)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM7);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM7);
|
||||
}
|
||||
#endif /* TIM7 */
|
||||
#if defined(TIM8)
|
||||
else if (TIMx == TIM8)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM8);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM8);
|
||||
}
|
||||
#endif /* TIM8 */
|
||||
#if defined(TIM9)
|
||||
else if (TIMx == TIM9)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM9);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM9);
|
||||
}
|
||||
#endif /* TIM9 */
|
||||
#if defined(TIM10)
|
||||
else if (TIMx == TIM10)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM10);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM10);
|
||||
}
|
||||
#endif /* TIM10 */
|
||||
#if defined(TIM11)
|
||||
else if (TIMx == TIM11)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM11);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM11);
|
||||
}
|
||||
#endif /* TIM11 */
|
||||
#if defined(TIM12)
|
||||
else if (TIMx == TIM12)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM12);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM12);
|
||||
}
|
||||
#endif /* TIM12 */
|
||||
#if defined(TIM13)
|
||||
else if (TIMx == TIM13)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM13);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM13);
|
||||
}
|
||||
#endif /* TIM13 */
|
||||
#if defined(TIM14)
|
||||
else if (TIMx == TIM14)
|
||||
{
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_TIM14);
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_TIM14);
|
||||
}
|
||||
#endif /* TIM14 */
|
||||
#if defined(TIM15)
|
||||
else if (TIMx == TIM15)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM15);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM15);
|
||||
}
|
||||
#endif /* TIM15 */
|
||||
#if defined(TIM16)
|
||||
else if (TIMx == TIM16)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM16);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM16);
|
||||
}
|
||||
#endif /* TIM16 */
|
||||
#if defined(TIM17)
|
||||
else if (TIMx == TIM17)
|
||||
{
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_TIM17);
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_TIM17);
|
||||
}
|
||||
#endif /* TIM17 */
|
||||
else
|
||||
{
|
||||
result = ERROR;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fields of the time base unit configuration data structure
|
||||
* to their default values.
|
||||
* @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure (time base unit configuration data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_StructInit(LL_TIM_InitTypeDef *TIM_InitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_InitStruct->Prescaler = (uint16_t)0x0000;
|
||||
TIM_InitStruct->CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct->Autoreload = 0xFFFFFFFFU;
|
||||
TIM_InitStruct->ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
TIM_InitStruct->RepetitionCounter = 0x00000000U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx time base unit.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_InitStruct pointer to a @ref LL_TIM_InitTypeDef structure
|
||||
* (TIMx time base unit configuration data structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_TIM_Init(TIM_TypeDef *TIMx, const LL_TIM_InitTypeDef *TIM_InitStruct)
|
||||
{
|
||||
uint32_t tmpcr1;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_COUNTERMODE(TIM_InitStruct->CounterMode));
|
||||
assert_param(IS_LL_TIM_CLOCKDIVISION(TIM_InitStruct->ClockDivision));
|
||||
|
||||
tmpcr1 = LL_TIM_ReadReg(TIMx, CR1);
|
||||
|
||||
if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
|
||||
{
|
||||
/* Select the Counter Mode */
|
||||
MODIFY_REG(tmpcr1, (TIM_CR1_DIR | TIM_CR1_CMS), TIM_InitStruct->CounterMode);
|
||||
}
|
||||
|
||||
if (IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
|
||||
{
|
||||
/* Set the clock division */
|
||||
MODIFY_REG(tmpcr1, TIM_CR1_CKD, TIM_InitStruct->ClockDivision);
|
||||
}
|
||||
|
||||
/* Write to TIMx CR1 */
|
||||
LL_TIM_WriteReg(TIMx, CR1, tmpcr1);
|
||||
|
||||
/* Set the Autoreload value */
|
||||
LL_TIM_SetAutoReload(TIMx, TIM_InitStruct->Autoreload);
|
||||
|
||||
/* Set the Prescaler value */
|
||||
LL_TIM_SetPrescaler(TIMx, TIM_InitStruct->Prescaler);
|
||||
|
||||
if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
|
||||
{
|
||||
/* Set the Repetition Counter value */
|
||||
LL_TIM_SetRepetitionCounter(TIMx, TIM_InitStruct->RepetitionCounter);
|
||||
}
|
||||
|
||||
/* Generate an update event to reload the Prescaler
|
||||
and the repetition counter value (if applicable) immediately */
|
||||
LL_TIM_GenerateEvent_UPDATE(TIMx);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fields of the TIMx output channel configuration data
|
||||
* structure to their default values.
|
||||
* @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure
|
||||
* (the output channel configuration data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_OC_StructInit(LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_OC_InitStruct->OCMode = LL_TIM_OCMODE_FROZEN;
|
||||
TIM_OC_InitStruct->OCState = LL_TIM_OCSTATE_DISABLE;
|
||||
TIM_OC_InitStruct->OCNState = LL_TIM_OCSTATE_DISABLE;
|
||||
TIM_OC_InitStruct->CompareValue = 0x00000000U;
|
||||
TIM_OC_InitStruct->OCPolarity = LL_TIM_OCPOLARITY_HIGH;
|
||||
TIM_OC_InitStruct->OCNPolarity = LL_TIM_OCPOLARITY_HIGH;
|
||||
TIM_OC_InitStruct->OCIdleState = LL_TIM_OCIDLESTATE_LOW;
|
||||
TIM_OC_InitStruct->OCNIdleState = LL_TIM_OCIDLESTATE_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx output channel.
|
||||
* @param TIMx Timer Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_TIM_CHANNEL_CH1
|
||||
* @arg @ref LL_TIM_CHANNEL_CH2
|
||||
* @arg @ref LL_TIM_CHANNEL_CH3
|
||||
* @arg @ref LL_TIM_CHANNEL_CH4
|
||||
* @param TIM_OC_InitStruct pointer to a @ref LL_TIM_OC_InitTypeDef structure (TIMx output channel configuration
|
||||
* data structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx output channel is initialized
|
||||
* - ERROR: TIMx output channel is not initialized
|
||||
*/
|
||||
ErrorStatus LL_TIM_OC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_OC_InitTypeDef *TIM_OC_InitStruct)
|
||||
{
|
||||
ErrorStatus result = ERROR;
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case LL_TIM_CHANNEL_CH1:
|
||||
result = OC1Config(TIMx, TIM_OC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH2:
|
||||
result = OC2Config(TIMx, TIM_OC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH3:
|
||||
result = OC3Config(TIMx, TIM_OC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH4:
|
||||
result = OC4Config(TIMx, TIM_OC_InitStruct);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fields of the TIMx input channel configuration data
|
||||
* structure to their default values.
|
||||
* @param TIM_ICInitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (the input channel configuration
|
||||
* data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_IC_StructInit(LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_ICInitStruct->ICPolarity = LL_TIM_IC_POLARITY_RISING;
|
||||
TIM_ICInitStruct->ICActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
|
||||
TIM_ICInitStruct->ICPrescaler = LL_TIM_ICPSC_DIV1;
|
||||
TIM_ICInitStruct->ICFilter = LL_TIM_IC_FILTER_FDIV1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx input channel.
|
||||
* @param TIMx Timer Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_TIM_CHANNEL_CH1
|
||||
* @arg @ref LL_TIM_CHANNEL_CH2
|
||||
* @arg @ref LL_TIM_CHANNEL_CH3
|
||||
* @arg @ref LL_TIM_CHANNEL_CH4
|
||||
* @param TIM_IC_InitStruct pointer to a @ref LL_TIM_IC_InitTypeDef structure (TIMx input channel configuration data
|
||||
* structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx output channel is initialized
|
||||
* - ERROR: TIMx output channel is not initialized
|
||||
*/
|
||||
ErrorStatus LL_TIM_IC_Init(TIM_TypeDef *TIMx, uint32_t Channel, const LL_TIM_IC_InitTypeDef *TIM_IC_InitStruct)
|
||||
{
|
||||
ErrorStatus result = ERROR;
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case LL_TIM_CHANNEL_CH1:
|
||||
result = IC1Config(TIMx, TIM_IC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH2:
|
||||
result = IC2Config(TIMx, TIM_IC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH3:
|
||||
result = IC3Config(TIMx, TIM_IC_InitStruct);
|
||||
break;
|
||||
case LL_TIM_CHANNEL_CH4:
|
||||
result = IC4Config(TIMx, TIM_IC_InitStruct);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fills each TIM_EncoderInitStruct field with its default value
|
||||
* @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (encoder interface
|
||||
* configuration data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_ENCODER_StructInit(LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_EncoderInitStruct->EncoderMode = LL_TIM_ENCODERMODE_X2_TI1;
|
||||
TIM_EncoderInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
|
||||
TIM_EncoderInitStruct->IC1ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
|
||||
TIM_EncoderInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
|
||||
TIM_EncoderInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
|
||||
TIM_EncoderInitStruct->IC2Polarity = LL_TIM_IC_POLARITY_RISING;
|
||||
TIM_EncoderInitStruct->IC2ActiveInput = LL_TIM_ACTIVEINPUT_DIRECTTI;
|
||||
TIM_EncoderInitStruct->IC2Prescaler = LL_TIM_ICPSC_DIV1;
|
||||
TIM_EncoderInitStruct->IC2Filter = LL_TIM_IC_FILTER_FDIV1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the encoder interface of the timer instance.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_EncoderInitStruct pointer to a @ref LL_TIM_ENCODER_InitTypeDef structure (TIMx encoder interface
|
||||
* configuration data structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_TIM_ENCODER_Init(TIM_TypeDef *TIMx, const LL_TIM_ENCODER_InitTypeDef *TIM_EncoderInitStruct)
|
||||
{
|
||||
uint32_t tmpccmr1;
|
||||
uint32_t tmpccer;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_ENCODER_INTERFACE_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_ENCODERMODE(TIM_EncoderInitStruct->EncoderMode));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC1Polarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC1ActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC1Prescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC1Filter));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_EncoderInitStruct->IC2Polarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_EncoderInitStruct->IC2ActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_EncoderInitStruct->IC2Prescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_EncoderInitStruct->IC2Filter));
|
||||
|
||||
/* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
|
||||
TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
|
||||
|
||||
/* Get the TIMx CCMR1 register value */
|
||||
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Configure TI1 */
|
||||
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1ActiveInput >> 16U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Filter >> 16U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC1Prescaler >> 16U);
|
||||
|
||||
/* Configure TI2 */
|
||||
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2ActiveInput >> 8U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Filter >> 8U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_EncoderInitStruct->IC2Prescaler >> 8U);
|
||||
|
||||
/* Set TI1 and TI2 polarity and enable TI1 and TI2 */
|
||||
tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
|
||||
tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC1Polarity);
|
||||
tmpccer |= (uint32_t)(TIM_EncoderInitStruct->IC2Polarity << 4U);
|
||||
tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
|
||||
|
||||
/* Set encoder mode */
|
||||
LL_TIM_SetEncoderMode(TIMx, TIM_EncoderInitStruct->EncoderMode);
|
||||
|
||||
/* Write to TIMx CCMR1 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fields of the TIMx Hall sensor interface configuration data
|
||||
* structure to their default values.
|
||||
* @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (HALL sensor interface
|
||||
* configuration data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_HALLSENSOR_StructInit(LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_HallSensorInitStruct->IC1Polarity = LL_TIM_IC_POLARITY_RISING;
|
||||
TIM_HallSensorInitStruct->IC1Prescaler = LL_TIM_ICPSC_DIV1;
|
||||
TIM_HallSensorInitStruct->IC1Filter = LL_TIM_IC_FILTER_FDIV1;
|
||||
TIM_HallSensorInitStruct->CommutationDelay = 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the Hall sensor interface of the timer instance.
|
||||
* @note TIMx CH1, CH2 and CH3 inputs connected through a XOR
|
||||
* to the TI1 input channel
|
||||
* @note TIMx slave mode controller is configured in reset mode.
|
||||
Selected internal trigger is TI1F_ED.
|
||||
* @note Channel 1 is configured as input, IC1 is mapped on TRC.
|
||||
* @note Captured value stored in TIMx_CCR1 correspond to the time elapsed
|
||||
* between 2 changes on the inputs. It gives information about motor speed.
|
||||
* @note Channel 2 is configured in output PWM 2 mode.
|
||||
* @note Compare value stored in TIMx_CCR2 corresponds to the commutation delay.
|
||||
* @note OC2REF is selected as trigger output on TRGO.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_HallSensorInitStruct pointer to a @ref LL_TIM_HALLSENSOR_InitTypeDef structure (TIMx HALL sensor
|
||||
* interface configuration data structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_TIM_HALLSENSOR_Init(TIM_TypeDef *TIMx, const LL_TIM_HALLSENSOR_InitTypeDef *TIM_HallSensorInitStruct)
|
||||
{
|
||||
uint32_t tmpcr2;
|
||||
uint32_t tmpccmr1;
|
||||
uint32_t tmpccer;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY_ENCODER(TIM_HallSensorInitStruct->IC1Polarity));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_HallSensorInitStruct->IC1Prescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_HallSensorInitStruct->IC1Filter));
|
||||
|
||||
/* Disable the CC1 and CC2: Reset the CC1E and CC2E Bits */
|
||||
TIMx->CCER &= (uint32_t)~(TIM_CCER_CC1E | TIM_CCER_CC2E);
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
|
||||
|
||||
/* Get the TIMx CCMR1 register value */
|
||||
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Get the TIMx SMCR register value */
|
||||
tmpsmcr = LL_TIM_ReadReg(TIMx, SMCR);
|
||||
|
||||
/* Connect TIMx_CH1, CH2 and CH3 pins to the TI1 input */
|
||||
tmpcr2 |= TIM_CR2_TI1S;
|
||||
|
||||
/* OC2REF signal is used as trigger output (TRGO) */
|
||||
tmpcr2 |= LL_TIM_TRGO_OC2REF;
|
||||
|
||||
/* Configure the slave mode controller */
|
||||
tmpsmcr &= (uint32_t)~(TIM_SMCR_TS | TIM_SMCR_SMS);
|
||||
tmpsmcr |= LL_TIM_TS_TI1F_ED;
|
||||
tmpsmcr |= LL_TIM_SLAVEMODE_RESET;
|
||||
|
||||
/* Configure input channel 1 */
|
||||
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC);
|
||||
tmpccmr1 |= (uint32_t)(LL_TIM_ACTIVEINPUT_TRC >> 16U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Filter >> 16U);
|
||||
tmpccmr1 |= (uint32_t)(TIM_HallSensorInitStruct->IC1Prescaler >> 16U);
|
||||
|
||||
/* Configure input channel 2 */
|
||||
tmpccmr1 &= (uint32_t)~(TIM_CCMR1_OC2M | TIM_CCMR1_OC2FE | TIM_CCMR1_OC2PE | TIM_CCMR1_OC2CE);
|
||||
tmpccmr1 |= (uint32_t)(LL_TIM_OCMODE_PWM2 << 8U);
|
||||
|
||||
/* Set Channel 1 polarity and enable Channel 1 and Channel2 */
|
||||
tmpccer &= (uint32_t)~(TIM_CCER_CC1P | TIM_CCER_CC1NP | TIM_CCER_CC2P | TIM_CCER_CC2NP);
|
||||
tmpccer |= (uint32_t)(TIM_HallSensorInitStruct->IC1Polarity);
|
||||
tmpccer |= (uint32_t)(TIM_CCER_CC1E | TIM_CCER_CC2E);
|
||||
|
||||
/* Write to TIMx CR2 */
|
||||
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
|
||||
|
||||
/* Write to TIMx SMCR */
|
||||
LL_TIM_WriteReg(TIMx, SMCR, tmpsmcr);
|
||||
|
||||
/* Write to TIMx CCMR1 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
/* Write to TIMx CCR2 */
|
||||
LL_TIM_OC_SetCompareCH2(TIMx, TIM_HallSensorInitStruct->CommutationDelay);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the fields of the Break and Dead Time configuration data structure
|
||||
* to their default values.
|
||||
* @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration
|
||||
* data structure)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_TIM_BDTR_StructInit(LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
|
||||
{
|
||||
/* Set the default configuration */
|
||||
TIM_BDTRInitStruct->OSSRState = LL_TIM_OSSR_DISABLE;
|
||||
TIM_BDTRInitStruct->OSSIState = LL_TIM_OSSI_DISABLE;
|
||||
TIM_BDTRInitStruct->LockLevel = LL_TIM_LOCKLEVEL_OFF;
|
||||
TIM_BDTRInitStruct->DeadTime = (uint8_t)0x00;
|
||||
TIM_BDTRInitStruct->BreakState = LL_TIM_BREAK_DISABLE;
|
||||
TIM_BDTRInitStruct->BreakPolarity = LL_TIM_BREAK_POLARITY_LOW;
|
||||
TIM_BDTRInitStruct->AutomaticOutput = LL_TIM_AUTOMATICOUTPUT_DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the Break and Dead Time feature of the timer instance.
|
||||
* @note As the bits AOE, BKP, BKE, OSSR, OSSI and DTG[7:0] can be write-locked
|
||||
* depending on the LOCK configuration, it can be necessary to configure all of
|
||||
* them during the first write access to the TIMx_BDTR register.
|
||||
* @note Macro IS_TIM_BREAK_INSTANCE(TIMx) can be used to check whether or not
|
||||
* a timer instance provides a break input.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_BDTRInitStruct pointer to a @ref LL_TIM_BDTR_InitTypeDef structure (Break and Dead Time configuration
|
||||
* data structure)
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: Break and Dead Time is initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_TIM_BDTR_Init(TIM_TypeDef *TIMx, const LL_TIM_BDTR_InitTypeDef *TIM_BDTRInitStruct)
|
||||
{
|
||||
uint32_t tmpbdtr = 0;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_BREAK_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_OSSR_STATE(TIM_BDTRInitStruct->OSSRState));
|
||||
assert_param(IS_LL_TIM_OSSI_STATE(TIM_BDTRInitStruct->OSSIState));
|
||||
assert_param(IS_LL_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->LockLevel));
|
||||
assert_param(IS_LL_TIM_BREAK_STATE(TIM_BDTRInitStruct->BreakState));
|
||||
assert_param(IS_LL_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->BreakPolarity));
|
||||
assert_param(IS_LL_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->AutomaticOutput));
|
||||
|
||||
/* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
|
||||
the OSSI State, the dead time value and the Automatic Output Enable Bit */
|
||||
|
||||
/* Set the BDTR bits */
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, TIM_BDTRInitStruct->DeadTime);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, TIM_BDTRInitStruct->LockLevel);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, TIM_BDTRInitStruct->OSSIState);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, TIM_BDTRInitStruct->OSSRState);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, TIM_BDTRInitStruct->BreakState);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, TIM_BDTRInitStruct->BreakPolarity);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, TIM_BDTRInitStruct->AutomaticOutput);
|
||||
|
||||
/* Set TIMx_BDTR */
|
||||
LL_TIM_WriteReg(TIMx, BDTR, tmpbdtr);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup TIM_LL_Private_Functions TIM Private Functions
|
||||
* @brief Private functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Configure the TIMx output channel 1.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_OCInitStruct pointer to the the TIMx output channel 1 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus OC1Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
|
||||
{
|
||||
uint32_t tmpccmr1;
|
||||
uint32_t tmpccer;
|
||||
uint32_t tmpcr2;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC1_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
|
||||
|
||||
/* Disable the Channel 1: Reset the CC1E Bit */
|
||||
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC1E);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
|
||||
|
||||
/* Get the TIMx CCMR1 register value */
|
||||
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
|
||||
|
||||
/* Reset Capture/Compare selection Bits */
|
||||
CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC1S);
|
||||
|
||||
/* Set the Output Compare Mode */
|
||||
MODIFY_REG(tmpccmr1, TIM_CCMR1_OC1M, TIM_OCInitStruct->OCMode);
|
||||
|
||||
/* Set the Output Compare Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC1P, TIM_OCInitStruct->OCPolarity);
|
||||
|
||||
/* Set the Output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC1E, TIM_OCInitStruct->OCState);
|
||||
|
||||
if (IS_TIM_BREAK_INSTANCE(TIMx))
|
||||
{
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
|
||||
|
||||
/* Set the complementary output Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC1NP, TIM_OCInitStruct->OCNPolarity << 2U);
|
||||
|
||||
/* Set the complementary output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC1NE, TIM_OCInitStruct->OCNState << 2U);
|
||||
|
||||
/* Set the Output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS1, TIM_OCInitStruct->OCIdleState);
|
||||
|
||||
/* Set the complementary output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS1N, TIM_OCInitStruct->OCNIdleState << 1U);
|
||||
}
|
||||
|
||||
/* Write to TIMx CR2 */
|
||||
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
|
||||
|
||||
/* Write to TIMx CCMR1 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
|
||||
|
||||
/* Set the Capture Compare Register value */
|
||||
LL_TIM_OC_SetCompareCH1(TIMx, TIM_OCInitStruct->CompareValue);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx output channel 2.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_OCInitStruct pointer to the the TIMx output channel 2 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus OC2Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
|
||||
{
|
||||
uint32_t tmpccmr1;
|
||||
uint32_t tmpccer;
|
||||
uint32_t tmpcr2;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC2_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
|
||||
|
||||
/* Disable the Channel 2: Reset the CC2E Bit */
|
||||
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC2E);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
|
||||
|
||||
/* Get the TIMx CCMR1 register value */
|
||||
tmpccmr1 = LL_TIM_ReadReg(TIMx, CCMR1);
|
||||
|
||||
/* Reset Capture/Compare selection Bits */
|
||||
CLEAR_BIT(tmpccmr1, TIM_CCMR1_CC2S);
|
||||
|
||||
/* Select the Output Compare Mode */
|
||||
MODIFY_REG(tmpccmr1, TIM_CCMR1_OC2M, TIM_OCInitStruct->OCMode << 8U);
|
||||
|
||||
/* Set the Output Compare Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC2P, TIM_OCInitStruct->OCPolarity << 4U);
|
||||
|
||||
/* Set the Output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC2E, TIM_OCInitStruct->OCState << 4U);
|
||||
|
||||
if (IS_TIM_BREAK_INSTANCE(TIMx))
|
||||
{
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
|
||||
|
||||
/* Set the complementary output Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC2NP, TIM_OCInitStruct->OCNPolarity << 6U);
|
||||
|
||||
/* Set the complementary output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC2NE, TIM_OCInitStruct->OCNState << 6U);
|
||||
|
||||
/* Set the Output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS2, TIM_OCInitStruct->OCIdleState << 2U);
|
||||
|
||||
/* Set the complementary output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS2N, TIM_OCInitStruct->OCNIdleState << 3U);
|
||||
}
|
||||
|
||||
/* Write to TIMx CR2 */
|
||||
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
|
||||
|
||||
/* Write to TIMx CCMR1 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR1, tmpccmr1);
|
||||
|
||||
/* Set the Capture Compare Register value */
|
||||
LL_TIM_OC_SetCompareCH2(TIMx, TIM_OCInitStruct->CompareValue);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx output channel 3.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_OCInitStruct pointer to the the TIMx output channel 3 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus OC3Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
|
||||
{
|
||||
uint32_t tmpccmr2;
|
||||
uint32_t tmpccer;
|
||||
uint32_t tmpcr2;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC3_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
|
||||
|
||||
/* Disable the Channel 3: Reset the CC3E Bit */
|
||||
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC3E);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
|
||||
|
||||
/* Get the TIMx CCMR2 register value */
|
||||
tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
|
||||
|
||||
/* Reset Capture/Compare selection Bits */
|
||||
CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC3S);
|
||||
|
||||
/* Select the Output Compare Mode */
|
||||
MODIFY_REG(tmpccmr2, TIM_CCMR2_OC3M, TIM_OCInitStruct->OCMode);
|
||||
|
||||
/* Set the Output Compare Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC3P, TIM_OCInitStruct->OCPolarity << 8U);
|
||||
|
||||
/* Set the Output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC3E, TIM_OCInitStruct->OCState << 8U);
|
||||
|
||||
if (IS_TIM_BREAK_INSTANCE(TIMx))
|
||||
{
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCNState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCNPolarity));
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCNIdleState));
|
||||
|
||||
/* Set the complementary output Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC3NP, TIM_OCInitStruct->OCNPolarity << 10U);
|
||||
|
||||
/* Set the complementary output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC3NE, TIM_OCInitStruct->OCNState << 10U);
|
||||
|
||||
/* Set the Output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS3, TIM_OCInitStruct->OCIdleState << 4U);
|
||||
|
||||
/* Set the complementary output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS3N, TIM_OCInitStruct->OCNIdleState << 5U);
|
||||
}
|
||||
|
||||
/* Write to TIMx CR2 */
|
||||
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
|
||||
|
||||
/* Write to TIMx CCMR2 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
|
||||
|
||||
/* Set the Capture Compare Register value */
|
||||
LL_TIM_OC_SetCompareCH3(TIMx, TIM_OCInitStruct->CompareValue);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx output channel 4.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_OCInitStruct pointer to the the TIMx output channel 4 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus OC4Config(TIM_TypeDef *TIMx, const LL_TIM_OC_InitTypeDef *TIM_OCInitStruct)
|
||||
{
|
||||
uint32_t tmpccmr2;
|
||||
uint32_t tmpccer;
|
||||
uint32_t tmpcr2;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC4_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_OCMODE(TIM_OCInitStruct->OCMode));
|
||||
assert_param(IS_LL_TIM_OCSTATE(TIM_OCInitStruct->OCState));
|
||||
assert_param(IS_LL_TIM_OCPOLARITY(TIM_OCInitStruct->OCPolarity));
|
||||
|
||||
/* Disable the Channel 4: Reset the CC4E Bit */
|
||||
CLEAR_BIT(TIMx->CCER, TIM_CCER_CC4E);
|
||||
|
||||
/* Get the TIMx CCER register value */
|
||||
tmpccer = LL_TIM_ReadReg(TIMx, CCER);
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = LL_TIM_ReadReg(TIMx, CR2);
|
||||
|
||||
/* Get the TIMx CCMR2 register value */
|
||||
tmpccmr2 = LL_TIM_ReadReg(TIMx, CCMR2);
|
||||
|
||||
/* Reset Capture/Compare selection Bits */
|
||||
CLEAR_BIT(tmpccmr2, TIM_CCMR2_CC4S);
|
||||
|
||||
/* Select the Output Compare Mode */
|
||||
MODIFY_REG(tmpccmr2, TIM_CCMR2_OC4M, TIM_OCInitStruct->OCMode << 8U);
|
||||
|
||||
/* Set the Output Compare Polarity */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC4P, TIM_OCInitStruct->OCPolarity << 12U);
|
||||
|
||||
/* Set the Output State */
|
||||
MODIFY_REG(tmpccer, TIM_CCER_CC4E, TIM_OCInitStruct->OCState << 12U);
|
||||
|
||||
if (IS_TIM_BREAK_INSTANCE(TIMx))
|
||||
{
|
||||
assert_param(IS_LL_TIM_OCIDLESTATE(TIM_OCInitStruct->OCIdleState));
|
||||
|
||||
/* Set the Output Idle state */
|
||||
MODIFY_REG(tmpcr2, TIM_CR2_OIS4, TIM_OCInitStruct->OCIdleState << 6U);
|
||||
}
|
||||
|
||||
/* Write to TIMx CR2 */
|
||||
LL_TIM_WriteReg(TIMx, CR2, tmpcr2);
|
||||
|
||||
/* Write to TIMx CCMR2 */
|
||||
LL_TIM_WriteReg(TIMx, CCMR2, tmpccmr2);
|
||||
|
||||
/* Set the Capture Compare Register value */
|
||||
LL_TIM_OC_SetCompareCH4(TIMx, TIM_OCInitStruct->CompareValue);
|
||||
|
||||
/* Write to TIMx CCER */
|
||||
LL_TIM_WriteReg(TIMx, CCER, tmpccer);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx input channel 1.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_ICInitStruct pointer to the the TIMx input channel 1 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus IC1Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC1_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
|
||||
|
||||
/* Disable the Channel 1: Reset the CC1E Bit */
|
||||
TIMx->CCER &= (uint32_t)~TIM_CCER_CC1E;
|
||||
|
||||
/* Select the Input and set the filter and the prescaler value */
|
||||
MODIFY_REG(TIMx->CCMR1,
|
||||
(TIM_CCMR1_CC1S | TIM_CCMR1_IC1F | TIM_CCMR1_IC1PSC),
|
||||
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
|
||||
|
||||
/* Select the Polarity and set the CC1E Bit */
|
||||
MODIFY_REG(TIMx->CCER,
|
||||
(TIM_CCER_CC1P | TIM_CCER_CC1NP),
|
||||
(TIM_ICInitStruct->ICPolarity | TIM_CCER_CC1E));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx input channel 2.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_ICInitStruct pointer to the the TIMx input channel 2 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus IC2Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC2_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
|
||||
|
||||
/* Disable the Channel 2: Reset the CC2E Bit */
|
||||
TIMx->CCER &= (uint32_t)~TIM_CCER_CC2E;
|
||||
|
||||
/* Select the Input and set the filter and the prescaler value */
|
||||
MODIFY_REG(TIMx->CCMR1,
|
||||
(TIM_CCMR1_CC2S | TIM_CCMR1_IC2F | TIM_CCMR1_IC2PSC),
|
||||
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
|
||||
|
||||
/* Select the Polarity and set the CC2E Bit */
|
||||
MODIFY_REG(TIMx->CCER,
|
||||
(TIM_CCER_CC2P | TIM_CCER_CC2NP),
|
||||
((TIM_ICInitStruct->ICPolarity << 4U) | TIM_CCER_CC2E));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx input channel 3.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_ICInitStruct pointer to the the TIMx input channel 3 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus IC3Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC3_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
|
||||
|
||||
/* Disable the Channel 3: Reset the CC3E Bit */
|
||||
TIMx->CCER &= (uint32_t)~TIM_CCER_CC3E;
|
||||
|
||||
/* Select the Input and set the filter and the prescaler value */
|
||||
MODIFY_REG(TIMx->CCMR2,
|
||||
(TIM_CCMR2_CC3S | TIM_CCMR2_IC3F | TIM_CCMR2_IC3PSC),
|
||||
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 16U);
|
||||
|
||||
/* Select the Polarity and set the CC3E Bit */
|
||||
MODIFY_REG(TIMx->CCER,
|
||||
(TIM_CCER_CC3P | TIM_CCER_CC3NP),
|
||||
((TIM_ICInitStruct->ICPolarity << 8U) | TIM_CCER_CC3E));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIMx input channel 4.
|
||||
* @param TIMx Timer Instance
|
||||
* @param TIM_ICInitStruct pointer to the the TIMx input channel 4 configuration data structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: TIMx registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
static ErrorStatus IC4Config(TIM_TypeDef *TIMx, const LL_TIM_IC_InitTypeDef *TIM_ICInitStruct)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CC4_INSTANCE(TIMx));
|
||||
assert_param(IS_LL_TIM_IC_POLARITY(TIM_ICInitStruct->ICPolarity));
|
||||
assert_param(IS_LL_TIM_ACTIVEINPUT(TIM_ICInitStruct->ICActiveInput));
|
||||
assert_param(IS_LL_TIM_ICPSC(TIM_ICInitStruct->ICPrescaler));
|
||||
assert_param(IS_LL_TIM_IC_FILTER(TIM_ICInitStruct->ICFilter));
|
||||
|
||||
/* Disable the Channel 4: Reset the CC4E Bit */
|
||||
TIMx->CCER &= (uint32_t)~TIM_CCER_CC4E;
|
||||
|
||||
/* Select the Input and set the filter and the prescaler value */
|
||||
MODIFY_REG(TIMx->CCMR2,
|
||||
(TIM_CCMR2_CC4S | TIM_CCMR2_IC4F | TIM_CCMR2_IC4PSC),
|
||||
(TIM_ICInitStruct->ICActiveInput | TIM_ICInitStruct->ICFilter | TIM_ICInitStruct->ICPrescaler) >> 8U);
|
||||
|
||||
/* Select the Polarity and set the CC4E Bit */
|
||||
MODIFY_REG(TIMx->CCER,
|
||||
TIM_CCER_CC4P,
|
||||
((TIM_ICInitStruct->ICPolarity << 12U) | TIM_CCER_CC4E));
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* TIM1 || TIM2 || TIM3 || TIM4 || TIM5 || TIM6 || TIM7 || TIM8 || TIM9 || TIM10 || TIM11 || TIM12 || TIM13 || TIM14 || TIM15 || TIM16 || TIM17 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
@@ -0,0 +1,438 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_usart.c
|
||||
* @author MCD Application Team
|
||||
* @brief USART LL module driver.
|
||||
******************************************************************************
|
||||
* @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.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_usart.h"
|
||||
#include "stm32f1xx_ll_rcc.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (USART1) || defined (USART2) || defined (USART3) || defined (UART4) || defined (UART5)
|
||||
|
||||
/** @addtogroup USART_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @addtogroup USART_LL_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup USART_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* __BAUDRATE__ The maximum Baud Rate is derived from the maximum clock available
|
||||
* divided by the smallest oversampling used on the USART (i.e. 8) */
|
||||
#define IS_LL_USART_BAUDRATE(__BAUDRATE__) ((__BAUDRATE__) <= 4500000U)
|
||||
|
||||
/* __VALUE__ In case of oversampling by 16 and 8, BRR content must be greater than or equal to 16d. */
|
||||
#define IS_LL_USART_BRR_MIN(__VALUE__) ((__VALUE__) >= 16U)
|
||||
|
||||
#define IS_LL_USART_DIRECTION(__VALUE__) (((__VALUE__) == LL_USART_DIRECTION_NONE) \
|
||||
|| ((__VALUE__) == LL_USART_DIRECTION_RX) \
|
||||
|| ((__VALUE__) == LL_USART_DIRECTION_TX) \
|
||||
|| ((__VALUE__) == LL_USART_DIRECTION_TX_RX))
|
||||
|
||||
#define IS_LL_USART_PARITY(__VALUE__) (((__VALUE__) == LL_USART_PARITY_NONE) \
|
||||
|| ((__VALUE__) == LL_USART_PARITY_EVEN) \
|
||||
|| ((__VALUE__) == LL_USART_PARITY_ODD))
|
||||
|
||||
#define IS_LL_USART_DATAWIDTH(__VALUE__) (((__VALUE__) == LL_USART_DATAWIDTH_8B) \
|
||||
|| ((__VALUE__) == LL_USART_DATAWIDTH_9B))
|
||||
|
||||
#define IS_LL_USART_OVERSAMPLING(__VALUE__) (((__VALUE__) == LL_USART_OVERSAMPLING_16) \
|
||||
|| ((__VALUE__) == LL_USART_OVERSAMPLING_8))
|
||||
|
||||
#define IS_LL_USART_LASTBITCLKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_LASTCLKPULSE_NO_OUTPUT) \
|
||||
|| ((__VALUE__) == LL_USART_LASTCLKPULSE_OUTPUT))
|
||||
|
||||
#define IS_LL_USART_CLOCKPHASE(__VALUE__) (((__VALUE__) == LL_USART_PHASE_1EDGE) \
|
||||
|| ((__VALUE__) == LL_USART_PHASE_2EDGE))
|
||||
|
||||
#define IS_LL_USART_CLOCKPOLARITY(__VALUE__) (((__VALUE__) == LL_USART_POLARITY_LOW) \
|
||||
|| ((__VALUE__) == LL_USART_POLARITY_HIGH))
|
||||
|
||||
#define IS_LL_USART_CLOCKOUTPUT(__VALUE__) (((__VALUE__) == LL_USART_CLOCK_DISABLE) \
|
||||
|| ((__VALUE__) == LL_USART_CLOCK_ENABLE))
|
||||
|
||||
#define IS_LL_USART_STOPBITS(__VALUE__) (((__VALUE__) == LL_USART_STOPBITS_0_5) \
|
||||
|| ((__VALUE__) == LL_USART_STOPBITS_1) \
|
||||
|| ((__VALUE__) == LL_USART_STOPBITS_1_5) \
|
||||
|| ((__VALUE__) == LL_USART_STOPBITS_2))
|
||||
|
||||
#define IS_LL_USART_HWCONTROL(__VALUE__) (((__VALUE__) == LL_USART_HWCONTROL_NONE) \
|
||||
|| ((__VALUE__) == LL_USART_HWCONTROL_RTS) \
|
||||
|| ((__VALUE__) == LL_USART_HWCONTROL_CTS) \
|
||||
|| ((__VALUE__) == LL_USART_HWCONTROL_RTS_CTS))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup USART_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup USART_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize USART registers (Registers restored to their default values).
|
||||
* @param USARTx USART Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: USART registers are de-initialized
|
||||
* - ERROR: USART registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_USART_DeInit(const USART_TypeDef *USARTx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(USARTx));
|
||||
|
||||
if (USARTx == USART1)
|
||||
{
|
||||
/* Force reset of USART clock */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_USART1);
|
||||
|
||||
/* Release reset of USART clock */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_USART1);
|
||||
}
|
||||
else if (USARTx == USART2)
|
||||
{
|
||||
/* Force reset of USART clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART2);
|
||||
|
||||
/* Release reset of USART clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART2);
|
||||
}
|
||||
#if defined(USART3)
|
||||
else if (USARTx == USART3)
|
||||
{
|
||||
/* Force reset of USART clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_USART3);
|
||||
|
||||
/* Release reset of USART clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_USART3);
|
||||
}
|
||||
#endif /* USART3 */
|
||||
#if defined(UART4)
|
||||
else if (USARTx == UART4)
|
||||
{
|
||||
/* Force reset of UART clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART4);
|
||||
|
||||
/* Release reset of UART clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART4);
|
||||
}
|
||||
#endif /* UART4 */
|
||||
#if defined(UART5)
|
||||
else if (USARTx == UART5)
|
||||
{
|
||||
/* Force reset of UART clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_UART5);
|
||||
|
||||
/* Release reset of UART clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_UART5);
|
||||
}
|
||||
#endif /* UART5 */
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize USART registers according to the specified
|
||||
* parameters in USART_InitStruct.
|
||||
* @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0),
|
||||
* USART IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
|
||||
* @note Baud rate value stored in USART_InitStruct BaudRate field, should be valid (different from 0).
|
||||
* @param USARTx USART Instance
|
||||
* @param USART_InitStruct pointer to a LL_USART_InitTypeDef structure
|
||||
* that contains the configuration information for the specified USART peripheral.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: USART registers are initialized according to USART_InitStruct content
|
||||
* - ERROR: Problem occurred during USART Registers initialization
|
||||
*/
|
||||
ErrorStatus LL_USART_Init(USART_TypeDef *USARTx, const LL_USART_InitTypeDef *USART_InitStruct)
|
||||
{
|
||||
ErrorStatus status = ERROR;
|
||||
uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO;
|
||||
LL_RCC_ClocksTypeDef rcc_clocks;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(USARTx));
|
||||
assert_param(IS_LL_USART_BAUDRATE(USART_InitStruct->BaudRate));
|
||||
assert_param(IS_LL_USART_DATAWIDTH(USART_InitStruct->DataWidth));
|
||||
assert_param(IS_LL_USART_STOPBITS(USART_InitStruct->StopBits));
|
||||
assert_param(IS_LL_USART_PARITY(USART_InitStruct->Parity));
|
||||
assert_param(IS_LL_USART_DIRECTION(USART_InitStruct->TransferDirection));
|
||||
assert_param(IS_LL_USART_HWCONTROL(USART_InitStruct->HardwareFlowControl));
|
||||
#if defined(USART_CR1_OVER8)
|
||||
assert_param(IS_LL_USART_OVERSAMPLING(USART_InitStruct->OverSampling));
|
||||
#endif /* USART_OverSampling_Feature */
|
||||
|
||||
/* USART needs to be in disabled state, in order to be able to configure some bits in
|
||||
CRx registers */
|
||||
if (LL_USART_IsEnabled(USARTx) == 0U)
|
||||
{
|
||||
/*---------------------------- USART CR1 Configuration -----------------------
|
||||
* Configure USARTx CR1 (USART Word Length, Parity, Mode and Oversampling bits) with parameters:
|
||||
* - DataWidth: USART_CR1_M bits according to USART_InitStruct->DataWidth value
|
||||
* - Parity: USART_CR1_PCE, USART_CR1_PS bits according to USART_InitStruct->Parity value
|
||||
* - TransferDirection: USART_CR1_TE, USART_CR1_RE bits according to USART_InitStruct->TransferDirection value
|
||||
* - Oversampling: USART_CR1_OVER8 bit according to USART_InitStruct->OverSampling value.
|
||||
*/
|
||||
#if defined(USART_CR1_OVER8)
|
||||
MODIFY_REG(USARTx->CR1,
|
||||
(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS |
|
||||
USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
|
||||
(USART_InitStruct->DataWidth | USART_InitStruct->Parity |
|
||||
USART_InitStruct->TransferDirection | USART_InitStruct->OverSampling));
|
||||
#else
|
||||
MODIFY_REG(USARTx->CR1,
|
||||
(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS |
|
||||
USART_CR1_TE | USART_CR1_RE),
|
||||
(USART_InitStruct->DataWidth | USART_InitStruct->Parity |
|
||||
USART_InitStruct->TransferDirection));
|
||||
#endif /* USART_OverSampling_Feature */
|
||||
|
||||
/*---------------------------- USART CR2 Configuration -----------------------
|
||||
* Configure USARTx CR2 (Stop bits) with parameters:
|
||||
* - Stop Bits: USART_CR2_STOP bits according to USART_InitStruct->StopBits value.
|
||||
* - CLKEN, CPOL, CPHA and LBCL bits are to be configured using LL_USART_ClockInit().
|
||||
*/
|
||||
LL_USART_SetStopBitsLength(USARTx, USART_InitStruct->StopBits);
|
||||
|
||||
/*---------------------------- USART CR3 Configuration -----------------------
|
||||
* Configure USARTx CR3 (Hardware Flow Control) with parameters:
|
||||
* - HardwareFlowControl: USART_CR3_RTSE, USART_CR3_CTSE bits according to USART_InitStruct->HardwareFlowControl value.
|
||||
*/
|
||||
LL_USART_SetHWFlowCtrl(USARTx, USART_InitStruct->HardwareFlowControl);
|
||||
|
||||
/*---------------------------- USART BRR Configuration -----------------------
|
||||
* Retrieve Clock frequency used for USART Peripheral
|
||||
*/
|
||||
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
|
||||
if (USARTx == USART1)
|
||||
{
|
||||
periphclk = rcc_clocks.PCLK2_Frequency;
|
||||
}
|
||||
else if (USARTx == USART2)
|
||||
{
|
||||
periphclk = rcc_clocks.PCLK1_Frequency;
|
||||
}
|
||||
#if defined(USART3)
|
||||
else if (USARTx == USART3)
|
||||
{
|
||||
periphclk = rcc_clocks.PCLK1_Frequency;
|
||||
}
|
||||
#endif /* USART3 */
|
||||
#if defined(UART4)
|
||||
else if (USARTx == UART4)
|
||||
{
|
||||
periphclk = rcc_clocks.PCLK1_Frequency;
|
||||
}
|
||||
#endif /* UART4 */
|
||||
#if defined(UART5)
|
||||
else if (USARTx == UART5)
|
||||
{
|
||||
periphclk = rcc_clocks.PCLK1_Frequency;
|
||||
}
|
||||
#endif /* UART5 */
|
||||
else
|
||||
{
|
||||
/* Nothing to do, as error code is already assigned to ERROR value */
|
||||
}
|
||||
|
||||
/* Configure the USART Baud Rate :
|
||||
- valid baud rate value (different from 0) is required
|
||||
- Peripheral clock as returned by RCC service, should be valid (different from 0).
|
||||
*/
|
||||
if ((periphclk != LL_RCC_PERIPH_FREQUENCY_NO)
|
||||
&& (USART_InitStruct->BaudRate != 0U))
|
||||
{
|
||||
status = SUCCESS;
|
||||
#if defined(USART_CR1_OVER8)
|
||||
LL_USART_SetBaudRate(USARTx,
|
||||
periphclk,
|
||||
USART_InitStruct->OverSampling,
|
||||
USART_InitStruct->BaudRate);
|
||||
#else
|
||||
LL_USART_SetBaudRate(USARTx,
|
||||
periphclk,
|
||||
USART_InitStruct->BaudRate);
|
||||
#endif /* USART_OverSampling_Feature */
|
||||
|
||||
/* Check BRR is greater than or equal to 16d */
|
||||
assert_param(IS_LL_USART_BRR_MIN(USARTx->BRR));
|
||||
}
|
||||
}
|
||||
/* Endif (=> USART not in Disabled state => return ERROR) */
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_USART_InitTypeDef field to default value.
|
||||
* @param USART_InitStruct Pointer to a @ref LL_USART_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
|
||||
void LL_USART_StructInit(LL_USART_InitTypeDef *USART_InitStruct)
|
||||
{
|
||||
/* Set USART_InitStruct fields to default values */
|
||||
USART_InitStruct->BaudRate = 9600U;
|
||||
USART_InitStruct->DataWidth = LL_USART_DATAWIDTH_8B;
|
||||
USART_InitStruct->StopBits = LL_USART_STOPBITS_1;
|
||||
USART_InitStruct->Parity = LL_USART_PARITY_NONE ;
|
||||
USART_InitStruct->TransferDirection = LL_USART_DIRECTION_TX_RX;
|
||||
USART_InitStruct->HardwareFlowControl = LL_USART_HWCONTROL_NONE;
|
||||
#if defined(USART_CR1_OVER8)
|
||||
USART_InitStruct->OverSampling = LL_USART_OVERSAMPLING_16;
|
||||
#endif /* USART_OverSampling_Feature */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize USART Clock related settings according to the
|
||||
* specified parameters in the USART_ClockInitStruct.
|
||||
* @note As some bits in USART configuration registers can only be written when the USART is disabled (USART_CR1_UE bit =0),
|
||||
* USART IP should be in disabled state prior calling this function. Otherwise, ERROR result will be returned.
|
||||
* @param USARTx USART Instance
|
||||
* @param USART_ClockInitStruct Pointer to a @ref LL_USART_ClockInitTypeDef structure
|
||||
* that contains the Clock configuration information for the specified USART peripheral.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: USART registers related to Clock settings are initialized according to USART_ClockInitStruct content
|
||||
* - ERROR: Problem occurred during USART Registers initialization
|
||||
*/
|
||||
ErrorStatus LL_USART_ClockInit(USART_TypeDef *USARTx, const LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check USART Instance and Clock signal output parameters */
|
||||
assert_param(IS_UART_INSTANCE(USARTx));
|
||||
assert_param(IS_LL_USART_CLOCKOUTPUT(USART_ClockInitStruct->ClockOutput));
|
||||
|
||||
/* USART needs to be in disabled state, in order to be able to configure some bits in
|
||||
CRx registers */
|
||||
if (LL_USART_IsEnabled(USARTx) == 0U)
|
||||
{
|
||||
/*---------------------------- USART CR2 Configuration -----------------------*/
|
||||
/* If Clock signal has to be output */
|
||||
if (USART_ClockInitStruct->ClockOutput == LL_USART_CLOCK_DISABLE)
|
||||
{
|
||||
/* Deactivate Clock signal delivery :
|
||||
* - Disable Clock Output: USART_CR2_CLKEN cleared
|
||||
*/
|
||||
LL_USART_DisableSCLKOutput(USARTx);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ensure USART instance is USART capable */
|
||||
assert_param(IS_USART_INSTANCE(USARTx));
|
||||
|
||||
/* Check clock related parameters */
|
||||
assert_param(IS_LL_USART_CLOCKPOLARITY(USART_ClockInitStruct->ClockPolarity));
|
||||
assert_param(IS_LL_USART_CLOCKPHASE(USART_ClockInitStruct->ClockPhase));
|
||||
assert_param(IS_LL_USART_LASTBITCLKOUTPUT(USART_ClockInitStruct->LastBitClockPulse));
|
||||
|
||||
/*---------------------------- USART CR2 Configuration -----------------------
|
||||
* Configure USARTx CR2 (Clock signal related bits) with parameters:
|
||||
* - Enable Clock Output: USART_CR2_CLKEN set
|
||||
* - Clock Polarity: USART_CR2_CPOL bit according to USART_ClockInitStruct->ClockPolarity value
|
||||
* - Clock Phase: USART_CR2_CPHA bit according to USART_ClockInitStruct->ClockPhase value
|
||||
* - Last Bit Clock Pulse Output: USART_CR2_LBCL bit according to USART_ClockInitStruct->LastBitClockPulse value.
|
||||
*/
|
||||
MODIFY_REG(USARTx->CR2,
|
||||
USART_CR2_CLKEN | USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_LBCL,
|
||||
USART_CR2_CLKEN | USART_ClockInitStruct->ClockPolarity |
|
||||
USART_ClockInitStruct->ClockPhase | USART_ClockInitStruct->LastBitClockPulse);
|
||||
}
|
||||
}
|
||||
/* Else (USART not in Disabled state => return ERROR */
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each field of a @ref LL_USART_ClockInitTypeDef type structure to default value.
|
||||
* @param USART_ClockInitStruct Pointer to a @ref LL_USART_ClockInitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_USART_ClockStructInit(LL_USART_ClockInitTypeDef *USART_ClockInitStruct)
|
||||
{
|
||||
/* Set LL_USART_ClockInitStruct fields with default values */
|
||||
USART_ClockInitStruct->ClockOutput = LL_USART_CLOCK_DISABLE;
|
||||
USART_ClockInitStruct->ClockPolarity = LL_USART_POLARITY_LOW; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
|
||||
USART_ClockInitStruct->ClockPhase = LL_USART_PHASE_1EDGE; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
|
||||
USART_ClockInitStruct->LastBitClockPulse = LL_USART_LASTCLKPULSE_NO_OUTPUT; /* Not relevant when ClockOutput = LL_USART_CLOCK_DISABLE */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USART1 || USART2 || USART3 || UART4 || UART5 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
|
||||
2897
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.c
Normal file
2897
john103C6T6/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.c
Normal file
@@ -0,0 +1,2897 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_usb.c
|
||||
* @author MCD Application Team
|
||||
* @brief USB Low Layer HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + Initialization/de-initialization functions
|
||||
* + I/O 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 #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Fill parameters of Init structure in USB_CfgTypeDef structure.
|
||||
|
||||
(#) Call USB_CoreInit() API to initialize the USB Core peripheral.
|
||||
|
||||
(#) The upper HAL HCD/PCD driver will call the right routines for its internal processes.
|
||||
|
||||
@endverbatim
|
||||
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_USB_DRIVER
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED)
|
||||
#if defined (USB) || defined (USB_OTG_FS)
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
#if defined (USB_OTG_FS)
|
||||
static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx);
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup USB_LL_Exported_Functions USB Low Layer Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USB_LL_Exported_Functions_Group1 Initialization/de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization/de-initialization functions #####
|
||||
===============================================================================
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the USB Core
|
||||
* @param USBx USB Instance
|
||||
* @param cfg pointer to a USB_OTG_CfgTypeDef structure that contains
|
||||
* the configuration information for the specified USBx peripheral.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_CoreInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
|
||||
{
|
||||
HAL_StatusTypeDef ret;
|
||||
|
||||
/* Select FS Embedded PHY */
|
||||
USBx->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL;
|
||||
|
||||
/* Reset after a PHY select */
|
||||
ret = USB_CoreReset(USBx);
|
||||
|
||||
/* Activate the USB Transceiver */
|
||||
USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the USB turnaround time
|
||||
* @param USBx USB Instance
|
||||
* @param hclk: AHB clock frequency
|
||||
* @retval USB turnaround time In PHY Clocks number
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetTurnaroundTime(USB_OTG_GlobalTypeDef *USBx,
|
||||
uint32_t hclk, uint8_t speed)
|
||||
{
|
||||
uint32_t UsbTrd;
|
||||
|
||||
/* The USBTRD is configured according to the tables below, depending on AHB frequency
|
||||
used by application. In the low AHB frequency range it is used to stretch enough the USB response
|
||||
time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access
|
||||
latency to the Data FIFO */
|
||||
if (speed == USBD_FS_SPEED)
|
||||
{
|
||||
if ((hclk >= 14200000U) && (hclk < 15000000U))
|
||||
{
|
||||
/* hclk Clock Range between 14.2-15 MHz */
|
||||
UsbTrd = 0xFU;
|
||||
}
|
||||
else if ((hclk >= 15000000U) && (hclk < 16000000U))
|
||||
{
|
||||
/* hclk Clock Range between 15-16 MHz */
|
||||
UsbTrd = 0xEU;
|
||||
}
|
||||
else if ((hclk >= 16000000U) && (hclk < 17200000U))
|
||||
{
|
||||
/* hclk Clock Range between 16-17.2 MHz */
|
||||
UsbTrd = 0xDU;
|
||||
}
|
||||
else if ((hclk >= 17200000U) && (hclk < 18500000U))
|
||||
{
|
||||
/* hclk Clock Range between 17.2-18.5 MHz */
|
||||
UsbTrd = 0xCU;
|
||||
}
|
||||
else if ((hclk >= 18500000U) && (hclk < 20000000U))
|
||||
{
|
||||
/* hclk Clock Range between 18.5-20 MHz */
|
||||
UsbTrd = 0xBU;
|
||||
}
|
||||
else if ((hclk >= 20000000U) && (hclk < 21800000U))
|
||||
{
|
||||
/* hclk Clock Range between 20-21.8 MHz */
|
||||
UsbTrd = 0xAU;
|
||||
}
|
||||
else if ((hclk >= 21800000U) && (hclk < 24000000U))
|
||||
{
|
||||
/* hclk Clock Range between 21.8-24 MHz */
|
||||
UsbTrd = 0x9U;
|
||||
}
|
||||
else if ((hclk >= 24000000U) && (hclk < 27700000U))
|
||||
{
|
||||
/* hclk Clock Range between 24-27.7 MHz */
|
||||
UsbTrd = 0x8U;
|
||||
}
|
||||
else if ((hclk >= 27700000U) && (hclk < 32000000U))
|
||||
{
|
||||
/* hclk Clock Range between 27.7-32 MHz */
|
||||
UsbTrd = 0x7U;
|
||||
}
|
||||
else /* if(hclk >= 32000000) */
|
||||
{
|
||||
/* hclk Clock Range between 32-200 MHz */
|
||||
UsbTrd = 0x6U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UsbTrd = USBD_DEFAULT_TRDT_VALUE;
|
||||
}
|
||||
|
||||
USBx->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
|
||||
USBx->GUSBCFG |= (uint32_t)((UsbTrd << 10) & USB_OTG_GUSBCFG_TRDT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EnableGlobalInt
|
||||
* Enables the controller's Global Int in the AHB Config reg
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EnableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
USBx->GAHBCFG |= USB_OTG_GAHBCFG_GINT;
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DisableGlobalInt
|
||||
* Disable the controller's Global Int in the AHB Config reg
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DisableGlobalInt(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
USBx->GAHBCFG &= ~USB_OTG_GAHBCFG_GINT;
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_SetCurrentMode Set functional mode
|
||||
* @param USBx Selected device
|
||||
* @param mode current core mode
|
||||
* This parameter can be one of these values:
|
||||
* @arg USB_DEVICE_MODE Peripheral mode
|
||||
* @arg USB_HOST_MODE Host mode
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetCurrentMode(USB_OTG_GlobalTypeDef *USBx, USB_ModeTypeDef mode)
|
||||
{
|
||||
uint32_t ms = 0U;
|
||||
|
||||
USBx->GUSBCFG &= ~(USB_OTG_GUSBCFG_FHMOD | USB_OTG_GUSBCFG_FDMOD);
|
||||
|
||||
if (mode == USB_HOST_MODE)
|
||||
{
|
||||
USBx->GUSBCFG |= USB_OTG_GUSBCFG_FHMOD;
|
||||
|
||||
do
|
||||
{
|
||||
HAL_Delay(10U);
|
||||
ms += 10U;
|
||||
} while ((USB_GetMode(USBx) != (uint32_t)USB_HOST_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
|
||||
}
|
||||
else if (mode == USB_DEVICE_MODE)
|
||||
{
|
||||
USBx->GUSBCFG |= USB_OTG_GUSBCFG_FDMOD;
|
||||
|
||||
do
|
||||
{
|
||||
HAL_Delay(10U);
|
||||
ms += 10U;
|
||||
} while ((USB_GetMode(USBx) != (uint32_t)USB_DEVICE_MODE) && (ms < HAL_USB_CURRENT_MODE_MAX_DELAY_MS));
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (ms == HAL_USB_CURRENT_MODE_MAX_DELAY_MS)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevInit Initializes the USB_OTG controller registers
|
||||
* for device mode
|
||||
* @param USBx Selected device
|
||||
* @param cfg pointer to a USB_OTG_CfgTypeDef structure that contains
|
||||
* the configuration information for the specified USBx peripheral.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0U; i < 15U; i++)
|
||||
{
|
||||
USBx->DIEPTXF[i] = 0U;
|
||||
}
|
||||
|
||||
/* Enable HW VBUS sensing */
|
||||
USBx->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
|
||||
|
||||
/* Restart the Phy Clock */
|
||||
USBx_PCGCCTL = 0U;
|
||||
|
||||
/* Set Core speed to Full speed mode */
|
||||
(void)USB_SetDevSpeed(USBx, USB_OTG_SPEED_FULL);
|
||||
|
||||
/* Flush the FIFOs */
|
||||
if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (USB_FlushRxFifo(USBx) != HAL_OK)
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear all pending Device Interrupts */
|
||||
USBx_DEVICE->DIEPMSK = 0U;
|
||||
USBx_DEVICE->DOEPMSK = 0U;
|
||||
USBx_DEVICE->DAINTMSK = 0U;
|
||||
|
||||
for (i = 0U; i < cfg.dev_endpoints; i++)
|
||||
{
|
||||
if ((USBx_INEP(i)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
|
||||
{
|
||||
if (i == 0U)
|
||||
{
|
||||
USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_SNAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_INEP(i)->DIEPCTL = USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_INEP(i)->DIEPCTL = 0U;
|
||||
}
|
||||
|
||||
USBx_INEP(i)->DIEPTSIZ = 0U;
|
||||
USBx_INEP(i)->DIEPINT = 0xFB7FU;
|
||||
}
|
||||
|
||||
for (i = 0U; i < cfg.dev_endpoints; i++)
|
||||
{
|
||||
if ((USBx_OUTEP(i)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
|
||||
{
|
||||
if (i == 0U)
|
||||
{
|
||||
USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_SNAK;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_OUTEP(i)->DOEPCTL = USB_OTG_DOEPCTL_EPDIS | USB_OTG_DOEPCTL_SNAK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_OUTEP(i)->DOEPCTL = 0U;
|
||||
}
|
||||
|
||||
USBx_OUTEP(i)->DOEPTSIZ = 0U;
|
||||
USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
|
||||
}
|
||||
|
||||
USBx_DEVICE->DIEPMSK &= ~(USB_OTG_DIEPMSK_TXFURM);
|
||||
|
||||
/* Disable all interrupts. */
|
||||
USBx->GINTMSK = 0U;
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
USBx->GINTSTS = 0xBFFFFFFFU;
|
||||
|
||||
/* Enable the common interrupts */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||
|
||||
/* Enable interrupts matching to the Device mode ONLY */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_USBRST |
|
||||
USB_OTG_GINTMSK_ENUMDNEM | USB_OTG_GINTMSK_IEPINT |
|
||||
USB_OTG_GINTMSK_OEPINT | USB_OTG_GINTMSK_IISOIXFRM |
|
||||
USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM;
|
||||
|
||||
if (cfg.Sof_enable != 0U)
|
||||
{
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_SOFM;
|
||||
}
|
||||
|
||||
if (cfg.vbus_sensing_enable == 1U)
|
||||
{
|
||||
USBx->GINTMSK |= (USB_OTG_GINTMSK_SRQIM | USB_OTG_GINTMSK_OTGINT);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_FlushTxFifo Flush a Tx FIFO
|
||||
* @param USBx Selected device
|
||||
* @param num FIFO number
|
||||
* This parameter can be a value from 1 to 15
|
||||
15 means Flush all Tx FIFOs
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_FlushTxFifo(USB_OTG_GlobalTypeDef *USBx, uint32_t num)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
|
||||
/* Flush TX Fifo */
|
||||
count = 0U;
|
||||
USBx->GRSTCTL = (USB_OTG_GRSTCTL_TXFFLSH | (num << 6));
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_TXFFLSH) == USB_OTG_GRSTCTL_TXFFLSH);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_FlushRxFifo Flush Rx FIFO
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_FlushRxFifo(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
|
||||
/* Flush RX Fifo */
|
||||
count = 0U;
|
||||
USBx->GRSTCTL = USB_OTG_GRSTCTL_RXFFLSH;
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_RXFFLSH) == USB_OTG_GRSTCTL_RXFFLSH);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_SetDevSpeed Initializes the DevSpd field of DCFG register
|
||||
* depending the PHY type and the enumeration speed of the device.
|
||||
* @param USBx Selected device
|
||||
* @param speed device speed
|
||||
* This parameter can be one of these values:
|
||||
* @arg USB_OTG_SPEED_FULL: Full speed mode
|
||||
* @retval Hal status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetDevSpeed(const USB_OTG_GlobalTypeDef *USBx, uint8_t speed)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
USBx_DEVICE->DCFG |= speed;
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_GetDevSpeed Return the Dev Speed
|
||||
* @param USBx Selected device
|
||||
* @retval speed device speed
|
||||
* This parameter can be one of these values:
|
||||
* @arg USBD_FS_SPEED: Full speed mode
|
||||
*/
|
||||
uint8_t USB_GetDevSpeed(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint8_t speed;
|
||||
uint32_t DevEnumSpeed = USBx_DEVICE->DSTS & USB_OTG_DSTS_ENUMSPD;
|
||||
|
||||
if ((DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ) ||
|
||||
(DevEnumSpeed == DSTS_ENUMSPD_FS_PHY_48MHZ))
|
||||
{
|
||||
speed = USBD_FS_SPEED;
|
||||
}
|
||||
else
|
||||
{
|
||||
speed = 0xFU;
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activate and configure an endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
|
||||
|
||||
if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_USBAEP) == 0U)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)ep->type << 18) | (epnum << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_DEVICE->DAINTMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
|
||||
|
||||
if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)ep->type << 18) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DOEPCTL_USBAEP;
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activate and configure a dedicated endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
/* Read DEPCTLn register */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
if (((USBx_INEP(epnum)->DIEPCTL) & USB_OTG_DIEPCTL_USBAEP) == 0U)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= (ep->maxpacket & USB_OTG_DIEPCTL_MPSIZ) |
|
||||
((uint32_t)ep->type << 18) | (epnum << 22) |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_USBAEP;
|
||||
}
|
||||
|
||||
USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((USBx_OUTEP(epnum)->DOEPCTL) & USB_OTG_DOEPCTL_USBAEP) == 0U)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= (ep->maxpacket & USB_OTG_DOEPCTL_MPSIZ) |
|
||||
((uint32_t)ep->type << 18) | (epnum << 22) |
|
||||
USB_OTG_DOEPCTL_USBAEP;
|
||||
}
|
||||
|
||||
USBx_DEVICE->DEACHMSK |= USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-activate and de-initialize an endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DeactivateEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
/* Read DEPCTLn register */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
|
||||
}
|
||||
|
||||
USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
|
||||
USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
|
||||
USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_USBAEP |
|
||||
USB_OTG_DIEPCTL_MPSIZ |
|
||||
USB_OTG_DIEPCTL_TXFNUM |
|
||||
USB_OTG_DIEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DIEPCTL_EPTYP);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
|
||||
}
|
||||
|
||||
USBx_DEVICE->DEACHMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
|
||||
USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
|
||||
USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_USBAEP |
|
||||
USB_OTG_DOEPCTL_MPSIZ |
|
||||
USB_OTG_DOEPCTL_SD0PID_SEVNFRM |
|
||||
USB_OTG_DOEPCTL_EPTYP);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-activate and de-initialize a dedicated endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DeactivateDedicatedEndpoint(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
/* Read DEPCTLn register */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
if ((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_EPDIS;
|
||||
}
|
||||
|
||||
USBx_INEP(epnum)->DIEPCTL &= ~ USB_OTG_DIEPCTL_USBAEP;
|
||||
USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_IEPM & (uint32_t)(1UL << (ep->num & EP_ADDR_MSK)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_EPDIS;
|
||||
}
|
||||
|
||||
USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_USBAEP;
|
||||
USBx_DEVICE->DAINTMSK &= ~(USB_OTG_DAINTMSK_OEPM & ((uint32_t)(1UL << (ep->num & EP_ADDR_MSK)) << 16));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPStartXfer : setup and starts a transfer over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPStartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
uint16_t pktcnt;
|
||||
|
||||
/* IN endpoint */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
/* Zero Length Packet? */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
|
||||
USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
|
||||
USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Program the transfer size and packet count
|
||||
* as follows: xfersize = N * maxpacket +
|
||||
* short_packet pktcnt = N + (short_packet
|
||||
* exist ? 1 : 0)
|
||||
*/
|
||||
USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_XFRSIZ);
|
||||
USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_PKTCNT);
|
||||
|
||||
if (epnum == 0U)
|
||||
{
|
||||
if (ep->xfer_len > ep->maxpacket)
|
||||
{
|
||||
ep->xfer_len = ep->maxpacket;
|
||||
}
|
||||
|
||||
USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT & (1U << 19));
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_PKTCNT &
|
||||
(((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket) << 19));
|
||||
}
|
||||
|
||||
USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_XFRSIZ & ep->xfer_len);
|
||||
|
||||
if (ep->type == EP_TYPE_ISOC)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPTSIZ &= ~(USB_OTG_DIEPTSIZ_MULCNT);
|
||||
USBx_INEP(epnum)->DIEPTSIZ |= (USB_OTG_DIEPTSIZ_MULCNT & (1U << 29));
|
||||
}
|
||||
}
|
||||
/* EP enable, IN data in FIFO */
|
||||
USBx_INEP(epnum)->DIEPCTL |= (USB_OTG_DIEPCTL_CNAK | USB_OTG_DIEPCTL_EPENA);
|
||||
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Enable the Tx FIFO Empty Interrupt for this EP */
|
||||
if (ep->xfer_len > 0U)
|
||||
{
|
||||
USBx_DEVICE->DIEPEMPMSK |= 1UL << (ep->num & EP_ADDR_MSK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SODDFRM;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM;
|
||||
}
|
||||
|
||||
(void)USB_WritePacket(USBx, ep->xfer_buff, ep->num, (uint16_t)ep->xfer_len);
|
||||
}
|
||||
}
|
||||
else /* OUT endpoint */
|
||||
{
|
||||
/* Program the transfer size and packet count as follows:
|
||||
* pktcnt = N
|
||||
* xfersize = N * maxpacket
|
||||
*/
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_XFRSIZ);
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ &= ~(USB_OTG_DOEPTSIZ_PKTCNT);
|
||||
|
||||
if (epnum == 0U)
|
||||
{
|
||||
if (ep->xfer_len > 0U)
|
||||
{
|
||||
ep->xfer_len = ep->maxpacket;
|
||||
}
|
||||
|
||||
/* Store transfer size, for EP0 this is equal to endpoint max packet size */
|
||||
ep->xfer_size = ep->maxpacket;
|
||||
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size);
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_XFRSIZ & ep->maxpacket);
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
|
||||
}
|
||||
else
|
||||
{
|
||||
pktcnt = (uint16_t)((ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket);
|
||||
ep->xfer_size = ep->maxpacket * pktcnt;
|
||||
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_PKTCNT & ((uint32_t)pktcnt << 19);
|
||||
USBx_OUTEP(epnum)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_XFRSIZ & ep->xfer_size;
|
||||
}
|
||||
}
|
||||
|
||||
if (ep->type == EP_TYPE_ISOC)
|
||||
{
|
||||
if ((USBx_DEVICE->DSTS & (1U << 8)) == 0U)
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SODDFRM;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM;
|
||||
}
|
||||
}
|
||||
/* EP enable */
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= (USB_OTG_DOEPCTL_CNAK | USB_OTG_DOEPCTL_EPENA);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_EPStoptXfer Stop transfer on an EP
|
||||
* @param USBx usb device instance
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPStopXfer(const USB_OTG_GlobalTypeDef *USBx, USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
/* IN endpoint */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
/* EP enable, IN data in FIFO */
|
||||
if (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA)
|
||||
{
|
||||
USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_SNAK);
|
||||
USBx_INEP(ep->num)->DIEPCTL |= (USB_OTG_DIEPCTL_EPDIS);
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > 10000U)
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
} while (((USBx_INEP(ep->num)->DIEPCTL) & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA);
|
||||
}
|
||||
}
|
||||
else /* OUT endpoint */
|
||||
{
|
||||
if (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
|
||||
{
|
||||
USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_SNAK);
|
||||
USBx_OUTEP(ep->num)->DOEPCTL |= (USB_OTG_DOEPCTL_EPDIS);
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > 10000U)
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
} while (((USBx_OUTEP(ep->num)->DOEPCTL) & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_WritePacket : Writes a packet into the Tx FIFO associated
|
||||
* with the EP/channel
|
||||
* @param USBx Selected device
|
||||
* @param src pointer to source buffer
|
||||
* @param ch_ep_num endpoint or host channel number
|
||||
* @param len Number of bytes to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_WritePacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *src,
|
||||
uint8_t ch_ep_num, uint16_t len)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint8_t *pSrc = src;
|
||||
uint32_t count32b;
|
||||
uint32_t i;
|
||||
|
||||
count32b = ((uint32_t)len + 3U) / 4U;
|
||||
for (i = 0U; i < count32b; i++)
|
||||
{
|
||||
USBx_DFIFO((uint32_t)ch_ep_num) = __UNALIGNED_UINT32_READ(pSrc);
|
||||
pSrc++;
|
||||
pSrc++;
|
||||
pSrc++;
|
||||
pSrc++;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadPacket : read a packet from the RX FIFO
|
||||
* @param USBx Selected device
|
||||
* @param dest source pointer
|
||||
* @param len Number of bytes to read
|
||||
* @retval pointer to destination buffer
|
||||
*/
|
||||
void *USB_ReadPacket(const USB_OTG_GlobalTypeDef *USBx, uint8_t *dest, uint16_t len)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint8_t *pDest = dest;
|
||||
uint32_t pData;
|
||||
uint32_t i;
|
||||
uint32_t count32b = (uint32_t)len >> 2U;
|
||||
uint16_t remaining_bytes = len % 4U;
|
||||
|
||||
for (i = 0U; i < count32b; i++)
|
||||
{
|
||||
__UNALIGNED_UINT32_WRITE(pDest, USBx_DFIFO(0U));
|
||||
pDest++;
|
||||
pDest++;
|
||||
pDest++;
|
||||
pDest++;
|
||||
}
|
||||
|
||||
/* When Number of data is not word aligned, read the remaining byte */
|
||||
if (remaining_bytes != 0U)
|
||||
{
|
||||
i = 0U;
|
||||
__UNALIGNED_UINT32_WRITE(&pData, USBx_DFIFO(0U));
|
||||
|
||||
do
|
||||
{
|
||||
*(uint8_t *)pDest = (uint8_t)(pData >> (8U * (uint8_t)(i)));
|
||||
i++;
|
||||
pDest++;
|
||||
remaining_bytes--;
|
||||
} while (remaining_bytes != 0U);
|
||||
}
|
||||
|
||||
return ((void *)pDest);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPSetStall : set a stall condition over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPSetStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
if (((USBx_INEP(epnum)->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == 0U) && (epnum != 0U))
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL &= ~(USB_OTG_DIEPCTL_EPDIS);
|
||||
}
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_STALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((USBx_OUTEP(epnum)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == 0U) && (epnum != 0U))
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL &= ~(USB_OTG_DOEPCTL_EPDIS);
|
||||
}
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_STALL;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPClearStall : Clear a stall condition over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPClearStall(const USB_OTG_GlobalTypeDef *USBx, const USB_OTG_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t epnum = (uint32_t)ep->num;
|
||||
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
|
||||
if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
|
||||
{
|
||||
USBx_INEP(epnum)->DIEPCTL |= USB_OTG_DIEPCTL_SD0PID_SEVNFRM; /* DATA0 */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
|
||||
if ((ep->type == EP_TYPE_INTR) || (ep->type == EP_TYPE_BULK))
|
||||
{
|
||||
USBx_OUTEP(epnum)->DOEPCTL |= USB_OTG_DOEPCTL_SD0PID_SEVNFRM; /* DATA0 */
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_StopDevice : Stop the usb device mode
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_StopDevice(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
HAL_StatusTypeDef ret;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t i;
|
||||
|
||||
/* Clear Pending interrupt */
|
||||
for (i = 0U; i < 15U; i++)
|
||||
{
|
||||
USBx_INEP(i)->DIEPINT = 0xFB7FU;
|
||||
USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
|
||||
}
|
||||
|
||||
/* Clear interrupt masks */
|
||||
USBx_DEVICE->DIEPMSK = 0U;
|
||||
USBx_DEVICE->DOEPMSK = 0U;
|
||||
USBx_DEVICE->DAINTMSK = 0U;
|
||||
|
||||
/* Flush the FIFO */
|
||||
ret = USB_FlushRxFifo(USBx);
|
||||
if (ret != HAL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = USB_FlushTxFifo(USBx, 0x10U);
|
||||
if (ret != HAL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_SetDevAddress : Stop the usb device mode
|
||||
* @param USBx Selected device
|
||||
* @param address new device address to be assigned
|
||||
* This parameter can be a value from 0 to 255
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetDevAddress(const USB_OTG_GlobalTypeDef *USBx, uint8_t address)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
USBx_DEVICE->DCFG &= ~(USB_OTG_DCFG_DAD);
|
||||
USBx_DEVICE->DCFG |= ((uint32_t)address << 4) & USB_OTG_DCFG_DAD;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevConnect : Connect the USB device by enabling Rpu
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevConnect(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
/* In case phy is stopped, ensure to ungate and restore the phy CLK */
|
||||
USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
|
||||
|
||||
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_SDIS;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevDisconnect : Disconnect the USB device by disabling Rpu
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevDisconnect(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
/* In case phy is stopped, ensure to ungate and restore the phy CLK */
|
||||
USBx_PCGCCTL &= ~(USB_OTG_PCGCCTL_STOPCLK | USB_OTG_PCGCCTL_GATECLK);
|
||||
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_SDIS;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadInterrupts: return the global USB interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval USB Global Interrupt status
|
||||
*/
|
||||
uint32_t USB_ReadInterrupts(USB_OTG_GlobalTypeDef const *USBx)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx->GINTSTS;
|
||||
tmpreg &= USBx->GINTMSK;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadChInterrupts: return USB channel interrupt status
|
||||
* @param USBx Selected device
|
||||
* @param chnum Channel number
|
||||
* @retval USB Channel Interrupt status
|
||||
*/
|
||||
uint32_t USB_ReadChInterrupts(const USB_OTG_GlobalTypeDef *USBx, uint8_t chnum)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx_HC(chnum)->HCINT;
|
||||
tmpreg &= USBx_HC(chnum)->HCINTMSK;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadDevAllOutEpInterrupt: return the USB device OUT endpoints interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval USB Device OUT EP interrupt status
|
||||
*/
|
||||
uint32_t USB_ReadDevAllOutEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx_DEVICE->DAINT;
|
||||
tmpreg &= USBx_DEVICE->DAINTMSK;
|
||||
|
||||
return ((tmpreg & 0xffff0000U) >> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadDevAllInEpInterrupt: return the USB device IN endpoints interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval USB Device IN EP interrupt status
|
||||
*/
|
||||
uint32_t USB_ReadDevAllInEpInterrupt(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx_DEVICE->DAINT;
|
||||
tmpreg &= USBx_DEVICE->DAINTMSK;
|
||||
|
||||
return ((tmpreg & 0xFFFFU));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Device OUT EP Interrupt register
|
||||
* @param USBx Selected device
|
||||
* @param epnum endpoint number
|
||||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device OUT EP Interrupt register
|
||||
*/
|
||||
uint32_t USB_ReadDevOutEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx_OUTEP((uint32_t)epnum)->DOEPINT;
|
||||
tmpreg &= USBx_DEVICE->DOEPMSK;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Device IN EP Interrupt register
|
||||
* @param USBx Selected device
|
||||
* @param epnum endpoint number
|
||||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device IN EP Interrupt register
|
||||
*/
|
||||
uint32_t USB_ReadDevInEPInterrupt(const USB_OTG_GlobalTypeDef *USBx, uint8_t epnum)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
uint32_t msk;
|
||||
uint32_t emp;
|
||||
|
||||
msk = USBx_DEVICE->DIEPMSK;
|
||||
emp = USBx_DEVICE->DIEPEMPMSK;
|
||||
msk |= ((emp >> (epnum & EP_ADDR_MSK)) & 0x1U) << 7;
|
||||
tmpreg = USBx_INEP((uint32_t)epnum)->DIEPINT & msk;
|
||||
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ClearInterrupts: clear a USB interrupt
|
||||
* @param USBx Selected device
|
||||
* @param interrupt flag
|
||||
* @retval None
|
||||
*/
|
||||
void USB_ClearInterrupts(USB_OTG_GlobalTypeDef *USBx, uint32_t interrupt)
|
||||
{
|
||||
USBx->GINTSTS &= interrupt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns USB core mode
|
||||
* @param USBx Selected device
|
||||
* @retval return core mode : Host or Device
|
||||
* This parameter can be one of these values:
|
||||
* 0 : Host
|
||||
* 1 : Device
|
||||
*/
|
||||
uint32_t USB_GetMode(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
return ((USBx->GINTSTS) & 0x1U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activate EP0 for Setup transactions
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateSetup(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
/* Set the MPS of the IN EP0 to 64 bytes */
|
||||
USBx_INEP(0U)->DIEPCTL &= ~USB_OTG_DIEPCTL_MPSIZ;
|
||||
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGINAK;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the EP0 to start the first control setup
|
||||
* @param USBx Selected device
|
||||
* @param psetup pointer to setup packet
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EP0_OutStart(const USB_OTG_GlobalTypeDef *USBx, const uint8_t *psetup)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
|
||||
UNUSED(psetup);
|
||||
|
||||
if (gSNPSiD > USB_OTG_CORE_ID_300A)
|
||||
{
|
||||
if ((USBx_OUTEP(0U)->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA)
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
USBx_OUTEP(0U)->DOEPTSIZ = 0U;
|
||||
USBx_OUTEP(0U)->DOEPTSIZ |= (USB_OTG_DOEPTSIZ_PKTCNT & (1U << 19));
|
||||
USBx_OUTEP(0U)->DOEPTSIZ |= (3U * 8U);
|
||||
USBx_OUTEP(0U)->DOEPTSIZ |= USB_OTG_DOEPTSIZ_STUPCNT;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the USB Core (needed after USB clock settings change)
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USB_CoreReset(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
|
||||
/* Wait for AHB master IDLE state. */
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U);
|
||||
|
||||
/* Core Soft Reset */
|
||||
count = 0U;
|
||||
USBx->GRSTCTL |= USB_OTG_GRSTCTL_CSRST;
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > HAL_USB_TIMEOUT)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
} while ((USBx->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_HostInit : Initializes the USB OTG controller registers
|
||||
* for Host mode
|
||||
* @param USBx Selected device
|
||||
* @param cfg pointer to a USB_OTG_CfgTypeDef structure that contains
|
||||
* the configuration information for the specified USBx peripheral.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_HostInit(USB_OTG_GlobalTypeDef *USBx, USB_OTG_CfgTypeDef cfg)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t i;
|
||||
|
||||
/* Restart the Phy Clock */
|
||||
USBx_PCGCCTL = 0U;
|
||||
|
||||
/* Disable VBUS sensing */
|
||||
USBx->GCCFG &= ~(USB_OTG_GCCFG_VBUSASEN);
|
||||
USBx->GCCFG &= ~(USB_OTG_GCCFG_VBUSBSEN);
|
||||
/* Set default Max speed support */
|
||||
USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSS);
|
||||
|
||||
/* Make sure the FIFOs are flushed. */
|
||||
if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (USB_FlushRxFifo(USBx) != HAL_OK)
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear all pending HC Interrupts */
|
||||
for (i = 0U; i < cfg.Host_channels; i++)
|
||||
{
|
||||
USBx_HC(i)->HCINT = CLEAR_INTERRUPT_MASK;
|
||||
USBx_HC(i)->HCINTMSK = 0U;
|
||||
}
|
||||
|
||||
/* Disable all interrupts. */
|
||||
USBx->GINTMSK = 0U;
|
||||
|
||||
/* Clear any pending interrupts */
|
||||
USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
|
||||
|
||||
/* set Rx FIFO size */
|
||||
USBx->GRXFSIZ = 0x80U;
|
||||
USBx->DIEPTXF0_HNPTXFSIZ = (uint32_t)(((0x60U << 16) & USB_OTG_NPTXFD) | 0x80U);
|
||||
USBx->HPTXFSIZ = (uint32_t)(((0x40U << 16)& USB_OTG_HPTXFSIZ_PTXFD) | 0xE0U);
|
||||
/* Enable the common interrupts */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
|
||||
|
||||
/* Enable interrupts matching to the Host mode ONLY */
|
||||
USBx->GINTMSK |= (USB_OTG_GINTMSK_PRTIM | USB_OTG_GINTMSK_HCIM | \
|
||||
USB_OTG_GINTMSK_SOFM | USB_OTG_GINTSTS_DISCINT | \
|
||||
USB_OTG_GINTMSK_PXFRM_IISOOXFRM | USB_OTG_GINTMSK_WUIM);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_InitFSLSPClkSel : Initializes the FSLSPClkSel field of the
|
||||
* HCFG register on the PHY type and set the right frame interval
|
||||
* @param USBx Selected device
|
||||
* @param freq clock frequency
|
||||
* This parameter can be one of these values:
|
||||
* HCFG_48_MHZ : Full Speed 48 MHz Clock
|
||||
* HCFG_6_MHZ : Low Speed 6 MHz Clock
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_InitFSLSPClkSel(const USB_OTG_GlobalTypeDef *USBx, uint8_t freq)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
USBx_HOST->HCFG &= ~(USB_OTG_HCFG_FSLSPCS);
|
||||
USBx_HOST->HCFG |= (uint32_t)freq & USB_OTG_HCFG_FSLSPCS;
|
||||
|
||||
if (freq == HCFG_48_MHZ)
|
||||
{
|
||||
USBx_HOST->HFIR = HFIR_48_MHZ;
|
||||
}
|
||||
else if (freq == HCFG_6_MHZ)
|
||||
{
|
||||
USBx_HOST->HFIR = HFIR_6_MHZ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_OTG_ResetPort : Reset Host Port
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
* @note (1)The application must wait at least 10 ms
|
||||
* before clearing the reset bit.
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ResetPort(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
__IO uint32_t hprt0 = 0U;
|
||||
|
||||
hprt0 = USBx_HPRT0;
|
||||
|
||||
hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
|
||||
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
|
||||
|
||||
USBx_HPRT0 = (USB_OTG_HPRT_PRST | hprt0);
|
||||
HAL_Delay(100U); /* See Note #1 */
|
||||
USBx_HPRT0 = ((~USB_OTG_HPRT_PRST) & hprt0);
|
||||
HAL_Delay(10U);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DriveVbus : activate or de-activate vbus
|
||||
* @param state VBUS state
|
||||
* This parameter can be one of these values:
|
||||
* 0 : Deactivate VBUS
|
||||
* 1 : Activate VBUS
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DriveVbus(const USB_OTG_GlobalTypeDef *USBx, uint8_t state)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
__IO uint32_t hprt0 = 0U;
|
||||
|
||||
hprt0 = USBx_HPRT0;
|
||||
|
||||
hprt0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |
|
||||
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
|
||||
|
||||
if (((hprt0 & USB_OTG_HPRT_PPWR) == 0U) && (state == 1U))
|
||||
{
|
||||
USBx_HPRT0 = (USB_OTG_HPRT_PPWR | hprt0);
|
||||
}
|
||||
if (((hprt0 & USB_OTG_HPRT_PPWR) == USB_OTG_HPRT_PPWR) && (state == 0U))
|
||||
{
|
||||
USBx_HPRT0 = ((~USB_OTG_HPRT_PPWR) & hprt0);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return Host Core speed
|
||||
* @param USBx Selected device
|
||||
* @retval speed : Host speed
|
||||
* This parameter can be one of these values:
|
||||
* @arg HCD_SPEED_FULL: Full speed mode
|
||||
* @arg HCD_SPEED_LOW: Low speed mode
|
||||
*/
|
||||
uint32_t USB_GetHostSpeed(USB_OTG_GlobalTypeDef const *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
__IO uint32_t hprt0 = 0U;
|
||||
|
||||
hprt0 = USBx_HPRT0;
|
||||
return ((hprt0 & USB_OTG_HPRT_PSPD) >> 17);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return Host Current Frame number
|
||||
* @param USBx Selected device
|
||||
* @retval current frame number
|
||||
*/
|
||||
uint32_t USB_GetCurrentFrame(USB_OTG_GlobalTypeDef const *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
return (USBx_HOST->HFNUM & USB_OTG_HFNUM_FRNUM);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a host channel
|
||||
* @param USBx Selected device
|
||||
* @param ch_num Channel number
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param epnum Endpoint number
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param dev_address Current device address
|
||||
* This parameter can be a value from 0 to 255
|
||||
* @param speed Current device speed
|
||||
* This parameter can be one of these values:
|
||||
* @arg USB_OTG_SPEED_FULL: Full speed mode
|
||||
* @arg USB_OTG_SPEED_LOW: Low speed mode
|
||||
* @param ep_type Endpoint Type
|
||||
* This parameter can be one of these values:
|
||||
* @arg EP_TYPE_CTRL: Control type
|
||||
* @arg EP_TYPE_ISOC: Isochronous type
|
||||
* @arg EP_TYPE_BULK: Bulk type
|
||||
* @arg EP_TYPE_INTR: Interrupt type
|
||||
* @param mps Max Packet Size
|
||||
* This parameter can be a value from 0 to 32K
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_StatusTypeDef USB_HC_Init(USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num,
|
||||
uint8_t epnum, uint8_t dev_address, uint8_t speed,
|
||||
uint8_t ep_type, uint16_t mps)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t HCcharEpDir;
|
||||
uint32_t HCcharLowSpeed;
|
||||
uint32_t HostCoreSpeed;
|
||||
|
||||
/* Clear old interrupt conditions for this host channel. */
|
||||
USBx_HC((uint32_t)ch_num)->HCINT = CLEAR_INTERRUPT_MASK;
|
||||
|
||||
/* Enable channel interrupts required for this transfer. */
|
||||
switch (ep_type)
|
||||
{
|
||||
case EP_TYPE_CTRL:
|
||||
case EP_TYPE_BULK:
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |
|
||||
USB_OTG_HCINTMSK_STALLM |
|
||||
USB_OTG_HCINTMSK_TXERRM |
|
||||
USB_OTG_HCINTMSK_DTERRM |
|
||||
USB_OTG_HCINTMSK_AHBERR |
|
||||
USB_OTG_HCINTMSK_NAKM;
|
||||
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
|
||||
}
|
||||
break;
|
||||
|
||||
case EP_TYPE_INTR:
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |
|
||||
USB_OTG_HCINTMSK_STALLM |
|
||||
USB_OTG_HCINTMSK_TXERRM |
|
||||
USB_OTG_HCINTMSK_DTERRM |
|
||||
USB_OTG_HCINTMSK_NAKM |
|
||||
USB_OTG_HCINTMSK_AHBERR |
|
||||
USB_OTG_HCINTMSK_FRMORM;
|
||||
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_BBERRM;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case EP_TYPE_ISOC:
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK = USB_OTG_HCINTMSK_XFRCM |
|
||||
USB_OTG_HCINTMSK_ACKM |
|
||||
USB_OTG_HCINTMSK_AHBERR |
|
||||
USB_OTG_HCINTMSK_FRMORM;
|
||||
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK |= (USB_OTG_HCINTMSK_TXERRM | USB_OTG_HCINTMSK_BBERRM);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable host channel Halt interrupt */
|
||||
USBx_HC((uint32_t)ch_num)->HCINTMSK |= USB_OTG_HCINTMSK_CHHM;
|
||||
|
||||
/* Enable the top level host channel interrupt. */
|
||||
USBx_HOST->HAINTMSK |= 1UL << (ch_num & 0xFU);
|
||||
|
||||
/* Make sure host channel interrupts are enabled. */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_HCIM;
|
||||
|
||||
/* Program the HCCHAR register */
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
HCcharEpDir = (0x1U << 15) & USB_OTG_HCCHAR_EPDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
HCcharEpDir = 0U;
|
||||
}
|
||||
|
||||
HostCoreSpeed = USB_GetHostSpeed(USBx);
|
||||
|
||||
/* LS device plugged to HUB */
|
||||
if ((speed == HPRT0_PRTSPD_LOW_SPEED) && (HostCoreSpeed != HPRT0_PRTSPD_LOW_SPEED))
|
||||
{
|
||||
HCcharLowSpeed = (0x1U << 17) & USB_OTG_HCCHAR_LSDEV;
|
||||
}
|
||||
else
|
||||
{
|
||||
HCcharLowSpeed = 0U;
|
||||
}
|
||||
|
||||
USBx_HC((uint32_t)ch_num)->HCCHAR = (((uint32_t)dev_address << 22) & USB_OTG_HCCHAR_DAD) |
|
||||
((((uint32_t)epnum & 0x7FU) << 11) & USB_OTG_HCCHAR_EPNUM) |
|
||||
(((uint32_t)ep_type << 18) & USB_OTG_HCCHAR_EPTYP) |
|
||||
((uint32_t)mps & USB_OTG_HCCHAR_MPSIZ) |
|
||||
USB_OTG_HCCHAR_MC_0 | HCcharEpDir | HCcharLowSpeed;
|
||||
|
||||
if ((ep_type == EP_TYPE_INTR) || (ep_type == EP_TYPE_ISOC))
|
||||
{
|
||||
USBx_HC((uint32_t)ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a transfer over a host channel
|
||||
* @param USBx Selected device
|
||||
* @param hc pointer to host channel structure
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_StatusTypeDef USB_HC_StartXfer(USB_OTG_GlobalTypeDef *USBx, USB_OTG_HCTypeDef *hc)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t ch_num = (uint32_t)hc->ch_num;
|
||||
__IO uint32_t tmpreg;
|
||||
uint8_t is_oddframe;
|
||||
uint16_t len_words;
|
||||
uint16_t num_packets;
|
||||
uint16_t max_hc_pkt_count = HC_MAX_PKT_CNT;
|
||||
|
||||
/* Compute the expected number of packets associated to the transfer */
|
||||
if (hc->xfer_len > 0U)
|
||||
{
|
||||
num_packets = (uint16_t)((hc->xfer_len + hc->max_packet - 1U) / hc->max_packet);
|
||||
|
||||
if (num_packets > max_hc_pkt_count)
|
||||
{
|
||||
num_packets = max_hc_pkt_count;
|
||||
hc->XferSize = (uint32_t)num_packets * hc->max_packet;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
num_packets = 1U;
|
||||
}
|
||||
|
||||
/*
|
||||
* For IN channel HCTSIZ.XferSize is expected to be an integer multiple of
|
||||
* max_packet size.
|
||||
*/
|
||||
if (hc->ep_is_in != 0U)
|
||||
{
|
||||
hc->XferSize = (uint32_t)num_packets * hc->max_packet;
|
||||
}
|
||||
else
|
||||
{
|
||||
hc->XferSize = hc->xfer_len;
|
||||
}
|
||||
|
||||
/* Initialize the HCTSIZn register */
|
||||
USBx_HC(ch_num)->HCTSIZ = (hc->XferSize & USB_OTG_HCTSIZ_XFRSIZ) |
|
||||
(((uint32_t)num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
|
||||
(((uint32_t)hc->data_pid << 29) & USB_OTG_HCTSIZ_DPID);
|
||||
|
||||
is_oddframe = (((uint32_t)USBx_HOST->HFNUM & 0x01U) != 0U) ? 0U : 1U;
|
||||
USBx_HC(ch_num)->HCCHAR &= ~USB_OTG_HCCHAR_ODDFRM;
|
||||
USBx_HC(ch_num)->HCCHAR |= (uint32_t)is_oddframe << 29;
|
||||
|
||||
/* Set host channel enable */
|
||||
tmpreg = USBx_HC(ch_num)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
|
||||
/* make sure to set the correct ep direction */
|
||||
if (hc->ep_is_in != 0U)
|
||||
{
|
||||
tmpreg |= USB_OTG_HCCHAR_EPDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpreg &= ~USB_OTG_HCCHAR_EPDIR;
|
||||
}
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(ch_num)->HCCHAR = tmpreg;
|
||||
|
||||
if ((hc->ep_is_in == 0U) && (hc->xfer_len > 0U))
|
||||
{
|
||||
switch (hc->ep_type)
|
||||
{
|
||||
/* Non periodic transfer */
|
||||
case EP_TYPE_CTRL:
|
||||
case EP_TYPE_BULK:
|
||||
|
||||
len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
|
||||
|
||||
/* check if there is enough space in FIFO space */
|
||||
if (len_words > (USBx->HNPTXSTS & 0xFFFFU))
|
||||
{
|
||||
/* need to process data in nptxfempty interrupt */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_NPTXFEM;
|
||||
}
|
||||
break;
|
||||
|
||||
/* Periodic transfer */
|
||||
case EP_TYPE_INTR:
|
||||
case EP_TYPE_ISOC:
|
||||
len_words = (uint16_t)((hc->xfer_len + 3U) / 4U);
|
||||
/* check if there is enough space in FIFO space */
|
||||
if (len_words > (USBx_HOST->HPTXSTS & 0xFFFFU)) /* split the transfer */
|
||||
{
|
||||
/* need to process data in ptxfempty interrupt */
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_PTXFEM;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Write packet into the Tx FIFO. */
|
||||
(void)USB_WritePacket(USBx, hc->xfer_buff, hc->ch_num, (uint16_t)hc->xfer_len);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read all host channel interrupts status
|
||||
* @param USBx Selected device
|
||||
* @retval HAL state
|
||||
*/
|
||||
uint32_t USB_HC_ReadInterrupt(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
return ((USBx_HOST->HAINT) & 0xFFFFU);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Halt a host channel
|
||||
* @param USBx Selected device
|
||||
* @param hc_num Host Channel number
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_StatusTypeDef USB_HC_Halt(const USB_OTG_GlobalTypeDef *USBx, uint8_t hc_num)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t hcnum = (uint32_t)hc_num;
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t HcEpType = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_EPTYP) >> 18;
|
||||
uint32_t ChannelEna = (USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) >> 31;
|
||||
uint32_t SplitEna = (USBx_HC(hcnum)->HCSPLT & USB_OTG_HCSPLT_SPLITEN) >> 31;
|
||||
|
||||
/* In buffer DMA, Channel disable must not be programmed for non-split periodic channels.
|
||||
At the end of the next uframe/frame (in the worst case), the core generates a channel halted
|
||||
and disables the channel automatically. */
|
||||
|
||||
if ((((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == USB_OTG_GAHBCFG_DMAEN) && (SplitEna == 0U)) &&
|
||||
((ChannelEna == 0U) || (((HcEpType == HCCHAR_ISOC) || (HcEpType == HCCHAR_INTR)))))
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/* Check for space in the request queue to issue the halt. */
|
||||
if ((HcEpType == HCCHAR_CTRL) || (HcEpType == HCCHAR_BULK))
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
|
||||
|
||||
if ((USBx->GAHBCFG & USB_OTG_GAHBCFG_DMAEN) == 0U)
|
||||
{
|
||||
if ((USBx->HNPTXSTS & (0xFFU << 16)) == 0U)
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > 1000U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHDIS;
|
||||
|
||||
if ((USBx_HOST->HPTXSTS & (0xFFU << 16)) == 0U)
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > 1000U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while ((USBx_HC(hcnum)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_HC(hcnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiate Do Ping protocol
|
||||
* @param USBx Selected device
|
||||
* @param hc_num Host Channel number
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DoPing(const USB_OTG_GlobalTypeDef *USBx, uint8_t ch_num)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t chnum = (uint32_t)ch_num;
|
||||
uint32_t num_packets = 1U;
|
||||
uint32_t tmpreg;
|
||||
|
||||
USBx_HC(chnum)->HCTSIZ = ((num_packets << 19) & USB_OTG_HCTSIZ_PKTCNT) |
|
||||
USB_OTG_HCTSIZ_DOPING;
|
||||
|
||||
/* Set host channel enable */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop Host Core
|
||||
* @param USBx Selected device
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_StatusTypeDef USB_StopHost(USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t value;
|
||||
uint32_t i;
|
||||
|
||||
(void)USB_DisableGlobalInt(USBx);
|
||||
|
||||
/* Flush USB FIFO */
|
||||
if (USB_FlushTxFifo(USBx, 0x10U) != HAL_OK) /* all Tx FIFOs */
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (USB_FlushRxFifo(USBx) != HAL_OK)
|
||||
{
|
||||
ret = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Flush out any leftover queued requests. */
|
||||
for (i = 0U; i <= 15U; i++)
|
||||
{
|
||||
value = USBx_HC(i)->HCCHAR;
|
||||
value |= USB_OTG_HCCHAR_CHDIS;
|
||||
value &= ~USB_OTG_HCCHAR_CHENA;
|
||||
value &= ~USB_OTG_HCCHAR_EPDIR;
|
||||
USBx_HC(i)->HCCHAR = value;
|
||||
}
|
||||
|
||||
/* Halt all channels to put them into a known state. */
|
||||
for (i = 0U; i <= 15U; i++)
|
||||
{
|
||||
value = USBx_HC(i)->HCCHAR;
|
||||
value |= USB_OTG_HCCHAR_CHDIS;
|
||||
value |= USB_OTG_HCCHAR_CHENA;
|
||||
value &= ~USB_OTG_HCCHAR_EPDIR;
|
||||
USBx_HC(i)->HCCHAR = value;
|
||||
|
||||
do
|
||||
{
|
||||
count++;
|
||||
|
||||
if (count > 1000U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_CHENA) == USB_OTG_HCCHAR_CHENA);
|
||||
}
|
||||
|
||||
/* Clear any pending Host interrupts */
|
||||
USBx_HOST->HAINT = CLEAR_INTERRUPT_MASK;
|
||||
USBx->GINTSTS = CLEAR_INTERRUPT_MASK;
|
||||
|
||||
(void)USB_EnableGlobalInt(USBx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ActivateRemoteWakeup active remote wakeup signalling
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
|
||||
{
|
||||
/* active Remote wakeup signalling */
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_RWUSIG;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DeActivateRemoteWakeup(const USB_OTG_GlobalTypeDef *USBx)
|
||||
{
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
|
||||
/* active Remote wakeup signalling */
|
||||
USBx_DEVICE->DCTL &= ~(USB_OTG_DCTL_RWUSIG);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief Initializes the USB Core
|
||||
* @param USBx USB Instance
|
||||
* @param cfg pointer to a USB_CfgTypeDef structure that contains
|
||||
* the configuration information for the specified USBx peripheral.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_CoreInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(cfg);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EnableGlobalInt
|
||||
* Enables the controller's Global Int in the AHB Config reg
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EnableGlobalInt(USB_TypeDef *USBx)
|
||||
{
|
||||
uint32_t winterruptmask;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
USBx->ISTR = 0U;
|
||||
|
||||
/* Set winterruptmask variable */
|
||||
winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
|
||||
USB_CNTR_SUSPM | USB_CNTR_ERRM |
|
||||
USB_CNTR_SOFM | USB_CNTR_ESOFM |
|
||||
USB_CNTR_RESETM;
|
||||
|
||||
/* Set interrupt mask */
|
||||
USBx->CNTR = (uint16_t)winterruptmask;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DisableGlobalInt
|
||||
* Disable the controller's Global Int in the AHB Config reg
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DisableGlobalInt(USB_TypeDef *USBx)
|
||||
{
|
||||
uint32_t winterruptmask;
|
||||
|
||||
/* Set winterruptmask variable */
|
||||
winterruptmask = USB_CNTR_CTRM | USB_CNTR_WKUPM |
|
||||
USB_CNTR_SUSPM | USB_CNTR_ERRM |
|
||||
USB_CNTR_SOFM | USB_CNTR_ESOFM |
|
||||
USB_CNTR_RESETM;
|
||||
|
||||
/* Clear interrupt mask */
|
||||
USBx->CNTR &= (uint16_t)(~winterruptmask);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_SetCurrentMode Set functional mode
|
||||
* @param USBx Selected device
|
||||
* @param mode current core mode
|
||||
* This parameter can be one of the these values:
|
||||
* @arg USB_DEVICE_MODE Peripheral mode
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetCurrentMode(USB_TypeDef *USBx, USB_ModeTypeDef mode)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(mode);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevInit Initializes the USB controller registers
|
||||
* for device mode
|
||||
* @param USBx Selected device
|
||||
* @param cfg pointer to a USB_CfgTypeDef structure that contains
|
||||
* the configuration information for the specified USBx peripheral.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevInit(USB_TypeDef *USBx, USB_CfgTypeDef cfg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(cfg);
|
||||
|
||||
/* Init Device */
|
||||
/* CNTR_FRES = 1 */
|
||||
USBx->CNTR = (uint16_t)USB_CNTR_FRES;
|
||||
|
||||
/* CNTR_FRES = 0 */
|
||||
USBx->CNTR = 0U;
|
||||
|
||||
/* Clear pending interrupts */
|
||||
USBx->ISTR = 0U;
|
||||
|
||||
/*Set Btable Address*/
|
||||
USBx->BTABLE = BTABLE_ADDRESS;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_FlushTxFifo : Flush a Tx FIFO
|
||||
* @param USBx : Selected device
|
||||
* @param num : FIFO number
|
||||
* This parameter can be a value from 1 to 15
|
||||
15 means Flush all Tx FIFOs
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_FlushTxFifo(USB_TypeDef const *USBx, uint32_t num)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(num);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_FlushRxFifo : Flush Rx FIFO
|
||||
* @param USBx : Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_FlushRxFifo(USB_TypeDef const *USBx)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
#if defined (HAL_PCD_MODULE_ENABLED)
|
||||
/**
|
||||
* @brief Activate and configure an endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
uint16_t wEpRegVal;
|
||||
|
||||
wEpRegVal = PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_T_MASK;
|
||||
|
||||
/* initialize Endpoint */
|
||||
switch (ep->type)
|
||||
{
|
||||
case EP_TYPE_CTRL:
|
||||
wEpRegVal |= USB_EP_CONTROL;
|
||||
break;
|
||||
|
||||
case EP_TYPE_BULK:
|
||||
wEpRegVal |= USB_EP_BULK;
|
||||
break;
|
||||
|
||||
case EP_TYPE_INTR:
|
||||
wEpRegVal |= USB_EP_INTERRUPT;
|
||||
break;
|
||||
|
||||
case EP_TYPE_ISOC:
|
||||
wEpRegVal |= USB_EP_ISOCHRONOUS;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
PCD_SET_ENDPOINT(USBx, ep->num, (wEpRegVal | USB_EP_CTR_RX | USB_EP_CTR_TX));
|
||||
|
||||
PCD_SET_EP_ADDRESS(USBx, ep->num, ep->num);
|
||||
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
/*Set the endpoint Transmit buffer address */
|
||||
PCD_SET_EP_TX_ADDRESS(USBx, ep->num, ep->pmaadress);
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure TX Endpoint to disabled state */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the endpoint Receive buffer address */
|
||||
PCD_SET_EP_RX_ADDRESS(USBx, ep->num, ep->pmaadress);
|
||||
|
||||
/* Set the endpoint Receive buffer counter */
|
||||
PCD_SET_EP_RX_CNT(USBx, ep->num, ep->maxpacket);
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
|
||||
if (ep->num == 0U)
|
||||
{
|
||||
/* Configure VALID status for EP0 */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure NAK status for OUT Endpoint */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/* Double Buffer */
|
||||
else
|
||||
{
|
||||
if (ep->type == EP_TYPE_BULK)
|
||||
{
|
||||
/* Set bulk endpoint as double buffered */
|
||||
PCD_SET_BULK_EP_DBUF(USBx, ep->num);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the ISOC endpoint in double buffer mode */
|
||||
PCD_CLEAR_EP_KIND(USBx, ep->num);
|
||||
}
|
||||
|
||||
/* Set buffer address for double buffered mode */
|
||||
PCD_SET_EP_DBUF_ADDR(USBx, ep->num, ep->pmaaddr0, ep->pmaaddr1);
|
||||
|
||||
if (ep->is_in == 0U)
|
||||
{
|
||||
/* Clear the data toggle bits for the endpoint IN/OUT */
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the data toggle bits for the endpoint IN/OUT */
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure TX Endpoint to disabled state */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-activate and de-initialize an endpoint
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DeactivateEndpoint(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
/* Configure DISABLE status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
|
||||
/* Configure DISABLE status for the Endpoint */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/* Double Buffer */
|
||||
else
|
||||
{
|
||||
if (ep->is_in == 0U)
|
||||
{
|
||||
/* Clear the data toggle bits for the endpoint IN/OUT*/
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
/* Reset value of the data toggle bits for the endpoint out*/
|
||||
PCD_TX_DTOG(USBx, ep->num);
|
||||
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the data toggle bits for the endpoint IN/OUT*/
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
PCD_RX_DTOG(USBx, ep->num);
|
||||
|
||||
/* Configure DISABLE status for the Endpoint*/
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPStartXfer setup and starts a transfer over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPStartXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
uint32_t len;
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
uint16_t pmabuffer;
|
||||
uint16_t wEPVal;
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
/* IN endpoint */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
/*Multi packet transfer*/
|
||||
if (ep->xfer_len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len;
|
||||
}
|
||||
|
||||
/* configure and validate Tx endpoint */
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
USB_WritePMA(USBx, ep->xfer_buff, ep->pmaadress, (uint16_t)len);
|
||||
PCD_SET_EP_TX_CNT(USBx, ep->num, len);
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else
|
||||
{
|
||||
/* double buffer bulk management */
|
||||
if (ep->type == EP_TYPE_BULK)
|
||||
{
|
||||
if (ep->xfer_len_db > ep->maxpacket)
|
||||
{
|
||||
/* enable double buffer */
|
||||
PCD_SET_BULK_EP_DBUF(USBx, ep->num);
|
||||
|
||||
/* each Time to write in PMA xfer_len_db will */
|
||||
ep->xfer_len_db -= len;
|
||||
|
||||
/* Fill the two first buffer in the Buffer0 & Buffer1 */
|
||||
if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
/* Set the Double buffer counter for pmabuffer1 */
|
||||
PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr1;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
ep->xfer_buff += len;
|
||||
|
||||
if (ep->xfer_len_db > ep->maxpacket)
|
||||
{
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
}
|
||||
|
||||
/* Set the Double buffer counter for pmabuffer0 */
|
||||
PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr0;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the Double buffer counter for pmabuffer0 */
|
||||
PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr0;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
ep->xfer_buff += len;
|
||||
|
||||
if (ep->xfer_len_db > ep->maxpacket)
|
||||
{
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
}
|
||||
|
||||
/* Set the Double buffer counter for pmabuffer1 */
|
||||
PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr1;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
/* auto Switch to single buffer mode when transfer <Mps no need to manage in double buffer */
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len_db;
|
||||
|
||||
/* disable double buffer mode for Bulk endpoint */
|
||||
PCD_CLEAR_BULK_EP_DBUF(USBx, ep->num);
|
||||
|
||||
/* Set Tx count with nbre of byte to be transmitted */
|
||||
PCD_SET_EP_TX_CNT(USBx, ep->num, len);
|
||||
pmabuffer = ep->pmaaddr0;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
else /* manage isochronous double buffer IN mode */
|
||||
{
|
||||
/* each Time to write in PMA xfer_len_db will */
|
||||
ep->xfer_len_db -= len;
|
||||
|
||||
/* Fill the data buffer */
|
||||
if ((PCD_GET_ENDPOINT(USBx, ep->num) & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
/* Set the Double buffer counter for pmabuffer1 */
|
||||
PCD_SET_EP_DBUF1_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr1;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the Double buffer counter for pmabuffer0 */
|
||||
PCD_SET_EP_DBUF0_CNT(USBx, ep->num, ep->is_in, len);
|
||||
pmabuffer = ep->pmaaddr0;
|
||||
|
||||
/* Write the user buffer to USB PMA */
|
||||
USB_WritePMA(USBx, ep->xfer_buff, pmabuffer, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_VALID);
|
||||
}
|
||||
else /* OUT endpoint */
|
||||
{
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
/* Multi packet transfer */
|
||||
if (ep->xfer_len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len;
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
/* configure and validate Rx endpoint */
|
||||
PCD_SET_EP_RX_CNT(USBx, ep->num, len);
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else
|
||||
{
|
||||
/* First Transfer Coming From HAL_PCD_EP_Receive & From ISR */
|
||||
/* Set the Double buffer counter */
|
||||
if (ep->type == EP_TYPE_BULK)
|
||||
{
|
||||
PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, ep->maxpacket);
|
||||
|
||||
/* Coming from ISR */
|
||||
if (ep->xfer_count != 0U)
|
||||
{
|
||||
/* update last value to check if there is blocking state */
|
||||
wEPVal = PCD_GET_ENDPOINT(USBx, ep->num);
|
||||
|
||||
/*Blocking State */
|
||||
if ((((wEPVal & USB_EP_DTOG_RX) != 0U) && ((wEPVal & USB_EP_DTOG_TX) != 0U)) ||
|
||||
(((wEPVal & USB_EP_DTOG_RX) == 0U) && ((wEPVal & USB_EP_DTOG_TX) == 0U)))
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(USBx, ep->num, 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* iso out double */
|
||||
else if (ep->type == EP_TYPE_ISOC)
|
||||
{
|
||||
/* Multi packet transfer */
|
||||
if (ep->xfer_len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len;
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
PCD_SET_EP_DBUF_CNT(USBx, ep->num, ep->is_in, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief USB_EPSetStall set a stall condition over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPSetStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_STALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_STALL);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPClearStall Clear a stall condition over an EP
|
||||
* @param USBx Selected device
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPClearStall(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
PCD_CLEAR_TX_DTOG(USBx, ep->num);
|
||||
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PCD_CLEAR_RX_DTOG(USBx, ep->num);
|
||||
|
||||
/* Configure VALID status for the Endpoint */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_VALID);
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_EPStoptXfer Stop transfer on an EP
|
||||
* @param USBx usb device instance
|
||||
* @param ep pointer to endpoint structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EPStopXfer(USB_TypeDef *USBx, USB_EPTypeDef *ep)
|
||||
{
|
||||
/* IN endpoint */
|
||||
if (ep->is_in == 1U)
|
||||
{
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure TX Endpoint to disabled state */
|
||||
PCD_SET_EP_TX_STATUS(USBx, ep->num, USB_EP_TX_DIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* OUT endpoint */
|
||||
{
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
if (ep->type != EP_TYPE_ISOC)
|
||||
{
|
||||
/* Configure NAK status for the Endpoint */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure RX Endpoint to disabled state */
|
||||
PCD_SET_EP_RX_STATUS(USBx, ep->num, USB_EP_RX_DIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (HAL_PCD_MODULE_ENABLED) */
|
||||
|
||||
/**
|
||||
* @brief USB_StopDevice Stop the usb device mode
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_StopDevice(USB_TypeDef *USBx)
|
||||
{
|
||||
/* disable all interrupts and force USB reset */
|
||||
USBx->CNTR = (uint16_t)USB_CNTR_FRES;
|
||||
|
||||
/* clear interrupt status register */
|
||||
USBx->ISTR = 0U;
|
||||
|
||||
/* switch-off device */
|
||||
USBx->CNTR = (uint16_t)(USB_CNTR_FRES | USB_CNTR_PDWN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_SetDevAddress Stop the usb device mode
|
||||
* @param USBx Selected device
|
||||
* @param address new device address to be assigned
|
||||
* This parameter can be a value from 0 to 255
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_SetDevAddress(USB_TypeDef *USBx, uint8_t address)
|
||||
{
|
||||
if (address == 0U)
|
||||
{
|
||||
/* set device address and enable function */
|
||||
USBx->DADDR = (uint16_t)USB_DADDR_EF;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevConnect Connect the USB device by enabling the pull-up/pull-down
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevConnect(USB_TypeDef *USBx)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DevDisconnect Disconnect the USB device by disabling the pull-up/pull-down
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DevDisconnect(USB_TypeDef *USBx)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadInterrupts return the global USB interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval USB Global Interrupt status
|
||||
*/
|
||||
uint32_t USB_ReadInterrupts(USB_TypeDef const *USBx)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
|
||||
tmpreg = USBx->ISTR;
|
||||
return tmpreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadDevAllOutEpInterrupt return the USB device OUT endpoints interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t USB_ReadDevAllOutEpInterrupt(USB_TypeDef *USBx)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ReadDevAllInEpInterrupt return the USB device IN endpoints interrupt status
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
uint32_t USB_ReadDevAllInEpInterrupt(USB_TypeDef *USBx)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Device OUT EP Interrupt register
|
||||
* @param USBx Selected device
|
||||
* @param epnum endpoint number
|
||||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device OUT EP Interrupt register
|
||||
*/
|
||||
uint32_t USB_ReadDevOutEPInterrupt(USB_TypeDef *USBx, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(epnum);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns Device IN EP Interrupt register
|
||||
* @param USBx Selected device
|
||||
* @param epnum endpoint number
|
||||
* This parameter can be a value from 0 to 15
|
||||
* @retval Device IN EP Interrupt register
|
||||
*/
|
||||
uint32_t USB_ReadDevInEPInterrupt(USB_TypeDef *USBx, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(epnum);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ClearInterrupts: clear a USB interrupt
|
||||
* @param USBx Selected device
|
||||
* @param interrupt flag
|
||||
* @retval None
|
||||
*/
|
||||
void USB_ClearInterrupts(USB_TypeDef *USBx, uint32_t interrupt)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(interrupt);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepare the EP0 to start the first control setup
|
||||
* @param USBx Selected device
|
||||
* @param psetup pointer to setup packet
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_EP0_OutStart(USB_TypeDef *USBx, uint8_t *psetup)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(USBx);
|
||||
UNUSED(psetup);
|
||||
/* NOTE : - This function is not required by USB Device FS peripheral, it is used
|
||||
only by USB OTG FS peripheral.
|
||||
- This function is added to ensure compatibility across platforms.
|
||||
*/
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_ActivateRemoteWakeup : active remote wakeup signalling
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_ActivateRemoteWakeup(USB_TypeDef *USBx)
|
||||
{
|
||||
USBx->CNTR |= (uint16_t)USB_CNTR_RESUME;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB_DeActivateRemoteWakeup de-active remote wakeup signalling
|
||||
* @param USBx Selected device
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef USB_DeActivateRemoteWakeup(USB_TypeDef *USBx)
|
||||
{
|
||||
USBx->CNTR &= (uint16_t)(~USB_CNTR_RESUME);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy a buffer from user memory area to packet memory area (PMA)
|
||||
* @param USBx USB peripheral instance register address.
|
||||
* @param pbUsrBuf pointer to user memory area.
|
||||
* @param wPMABufAddr address into PMA.
|
||||
* @param wNBytes no. of bytes to be copied.
|
||||
* @retval None
|
||||
*/
|
||||
void USB_WritePMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
|
||||
{
|
||||
uint32_t n = ((uint32_t)wNBytes + 1U) >> 1;
|
||||
uint32_t BaseAddr = (uint32_t)USBx;
|
||||
uint32_t count;
|
||||
uint16_t WrVal;
|
||||
__IO uint16_t *pdwVal;
|
||||
uint8_t *pBuf = pbUsrBuf;
|
||||
|
||||
pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
|
||||
|
||||
for (count = n; count != 0U; count--)
|
||||
{
|
||||
WrVal = pBuf[0];
|
||||
WrVal |= (uint16_t)pBuf[1] << 8;
|
||||
*pdwVal = (WrVal & 0xFFFFU);
|
||||
pdwVal++;
|
||||
|
||||
#if PMA_ACCESS > 1U
|
||||
pdwVal++;
|
||||
#endif /* PMA_ACCESS */
|
||||
|
||||
pBuf++;
|
||||
pBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy data from packet memory area (PMA) to user memory buffer
|
||||
* @param USBx USB peripheral instance register address.
|
||||
* @param pbUsrBuf pointer to user memory area.
|
||||
* @param wPMABufAddr address into PMA.
|
||||
* @param wNBytes no. of bytes to be copied.
|
||||
* @retval None
|
||||
*/
|
||||
void USB_ReadPMA(USB_TypeDef const *USBx, uint8_t *pbUsrBuf, uint16_t wPMABufAddr, uint16_t wNBytes)
|
||||
{
|
||||
uint32_t n = (uint32_t)wNBytes >> 1;
|
||||
uint32_t BaseAddr = (uint32_t)USBx;
|
||||
uint32_t count;
|
||||
uint32_t RdVal;
|
||||
__IO uint16_t *pdwVal;
|
||||
uint8_t *pBuf = pbUsrBuf;
|
||||
|
||||
pdwVal = (__IO uint16_t *)(BaseAddr + 0x400U + ((uint32_t)wPMABufAddr * PMA_ACCESS));
|
||||
|
||||
for (count = n; count != 0U; count--)
|
||||
{
|
||||
RdVal = *(__IO uint16_t *)pdwVal;
|
||||
pdwVal++;
|
||||
*pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
|
||||
pBuf++;
|
||||
*pBuf = (uint8_t)((RdVal >> 8) & 0xFFU);
|
||||
pBuf++;
|
||||
|
||||
#if PMA_ACCESS > 1U
|
||||
pdwVal++;
|
||||
#endif /* PMA_ACCESS */
|
||||
}
|
||||
|
||||
if ((wNBytes % 2U) != 0U)
|
||||
{
|
||||
RdVal = *pdwVal;
|
||||
*pBuf = (uint8_t)((RdVal >> 0) & 0xFFU);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined (USB) */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined (USB) || defined (USB_OTG_FS) */
|
||||
#endif /* defined (HAL_PCD_MODULE_ENABLED) || defined (HAL_HCD_MODULE_ENABLED) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,767 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_utils.c
|
||||
* @author MCD Application Team
|
||||
* @brief UTILS LL module driver.
|
||||
******************************************************************************
|
||||
* @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_ll_rcc.h"
|
||||
#include "stm32f1xx_ll_utils.h"
|
||||
#include "stm32f1xx_ll_system.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup UTILS_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/** @addtogroup UTILS_LL_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Defines used for PLL range */
|
||||
#define UTILS_PLL_OUTPUT_MAX RCC_MAX_FREQUENCY /*!< Frequency max for PLL output, in Hz */
|
||||
#define UTILS_PLL2_OUTPUT_MAX RCC_MAX_FREQUENCY /*!< Frequency max for PLL2 output, in Hz */
|
||||
|
||||
/* Defines used for HSE range */
|
||||
#define UTILS_HSE_FREQUENCY_MIN RCC_HSE_MIN /*!< Frequency min for HSE frequency, in Hz */
|
||||
#define UTILS_HSE_FREQUENCY_MAX RCC_HSE_MAX /*!< Frequency max for HSE frequency, in Hz */
|
||||
|
||||
/* Defines used for FLASH latency according to HCLK Frequency */
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
#define UTILS_LATENCY1_FREQ 24000000U /*!< SYSCLK frequency to set FLASH latency 1 */
|
||||
#define UTILS_LATENCY2_FREQ 48000000U /*!< SYSCLK frequency to set FLASH latency 2 */
|
||||
#else
|
||||
/*!< No Latency Configuration in this device */
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup UTILS_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_UTILS_SYSCLK_DIV(__VALUE__) (((__VALUE__) == LL_RCC_SYSCLK_DIV_1) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_2) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_4) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_8) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_16) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_64) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_128) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_256) \
|
||||
|| ((__VALUE__) == LL_RCC_SYSCLK_DIV_512))
|
||||
|
||||
#define IS_LL_UTILS_APB1_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB1_DIV_1) \
|
||||
|| ((__VALUE__) == LL_RCC_APB1_DIV_2) \
|
||||
|| ((__VALUE__) == LL_RCC_APB1_DIV_4) \
|
||||
|| ((__VALUE__) == LL_RCC_APB1_DIV_8) \
|
||||
|| ((__VALUE__) == LL_RCC_APB1_DIV_16))
|
||||
|
||||
#define IS_LL_UTILS_APB2_DIV(__VALUE__) (((__VALUE__) == LL_RCC_APB2_DIV_1) \
|
||||
|| ((__VALUE__) == LL_RCC_APB2_DIV_2) \
|
||||
|| ((__VALUE__) == LL_RCC_APB2_DIV_4) \
|
||||
|| ((__VALUE__) == LL_RCC_APB2_DIV_8) \
|
||||
|| ((__VALUE__) == LL_RCC_APB2_DIV_16))
|
||||
|
||||
#if defined(RCC_CFGR_PLLMULL6_5)
|
||||
#define IS_LL_UTILS_PLLMUL_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLL_MUL_4) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_5) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_6) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_7) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_8) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_9) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_6_5))
|
||||
#else
|
||||
#define IS_LL_UTILS_PLLMUL_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLL_MUL_2) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_3) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_4) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_5) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_6) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_7) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_8) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_9) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_10) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_11) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_12) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_13) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_14) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_15) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL_MUL_16))
|
||||
#endif /* RCC_CFGR_PLLMULL6_5 */
|
||||
|
||||
#if defined(RCC_CFGR2_PREDIV1)
|
||||
#define IS_LL_UTILS_PREDIV_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PREDIV_DIV_1) || ((__VALUE__) == LL_RCC_PREDIV_DIV_2) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_3) || ((__VALUE__) == LL_RCC_PREDIV_DIV_4) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_5) || ((__VALUE__) == LL_RCC_PREDIV_DIV_6) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_7) || ((__VALUE__) == LL_RCC_PREDIV_DIV_8) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_9) || ((__VALUE__) == LL_RCC_PREDIV_DIV_10) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_11) || ((__VALUE__) == LL_RCC_PREDIV_DIV_12) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_13) || ((__VALUE__) == LL_RCC_PREDIV_DIV_14) || \
|
||||
((__VALUE__) == LL_RCC_PREDIV_DIV_15) || ((__VALUE__) == LL_RCC_PREDIV_DIV_16))
|
||||
#else
|
||||
#define IS_LL_UTILS_PREDIV_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PREDIV_DIV_1) || ((__VALUE__) == LL_RCC_PREDIV_DIV_2))
|
||||
#endif /*RCC_PREDIV1_DIV_2_16_SUPPORT*/
|
||||
|
||||
#define IS_LL_UTILS_PLL_FREQUENCY(__VALUE__) ((__VALUE__) <= UTILS_PLL_OUTPUT_MAX)
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
#define IS_LL_UTILS_PLL2MUL_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_PLL2_MUL_8) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_9) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_10) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_11) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_12) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_13) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_14) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_16) \
|
||||
|| ((__VALUE__) == LL_RCC_PLL2_MUL_20))
|
||||
|
||||
#define IS_LL_UTILS_PREDIV2_VALUE(__VALUE__) (((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_1) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_2) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_3) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_4) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_5) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_6) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_7) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_8) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_9) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_10) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_11) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_12) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_13) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_14) || \
|
||||
((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_15) || ((__VALUE__) == LL_RCC_HSE_PREDIV2_DIV_16))
|
||||
|
||||
#define IS_LL_UTILS_PLL2_FREQUENCY(__VALUE__) ((__VALUE__) <= UTILS_PLL2_OUTPUT_MAX)
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
#define IS_LL_UTILS_HSE_BYPASS(__STATE__) (((__STATE__) == LL_UTILS_HSEBYPASS_ON) \
|
||||
|| ((__STATE__) == LL_UTILS_HSEBYPASS_OFF))
|
||||
|
||||
#define IS_LL_UTILS_HSE_FREQUENCY(__FREQUENCY__) (((__FREQUENCY__) >= UTILS_HSE_FREQUENCY_MIN) && ((__FREQUENCY__) <= UTILS_HSE_FREQUENCY_MAX))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup UTILS_LL_Private_Functions UTILS Private functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct);
|
||||
static ErrorStatus UTILS_PLL_HSE_ConfigSystemClock(uint32_t PLL_InputFrequency, uint32_t HSEBypass,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
|
||||
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
static uint32_t UTILS_GetPLL2OutputFrequency(uint32_t PLL2_InputFrequency,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLL2InitStruct);
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct);
|
||||
static ErrorStatus UTILS_PLL_IsBusy(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup UTILS_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup UTILS_LL_EF_DELAY
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the Cortex-M SysTick source to have 1ms time base.
|
||||
* @note When a RTOS is used, it is recommended to avoid changing the Systick
|
||||
* configuration by calling this function, for a delay use rather osDelay RTOS service.
|
||||
* @param HCLKFrequency HCLK frequency in Hz
|
||||
* @note HCLK frequency can be calculated thanks to RCC helper macro or function @ref LL_RCC_GetSystemClocksFreq
|
||||
* @retval None
|
||||
*/
|
||||
void LL_Init1msTick(uint32_t HCLKFrequency)
|
||||
{
|
||||
/* Use frequency provided in argument */
|
||||
LL_InitTick(HCLKFrequency, 1000U);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function provides accurate delay (in milliseconds) based
|
||||
* on SysTick counter flag
|
||||
* @note When a RTOS is used, it is recommended to avoid using blocking delay
|
||||
* and use rather osDelay service.
|
||||
* @note To respect 1ms timebase, user should call @ref LL_Init1msTick function which
|
||||
* will configure Systick to 1ms
|
||||
* @param Delay specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_mDelay(uint32_t Delay)
|
||||
{
|
||||
__IO uint32_t tmp = SysTick->CTRL; /* Clear the COUNTFLAG first */
|
||||
/* Add this code to indicate that local variable is not used */
|
||||
((void)tmp);
|
||||
|
||||
/* Add a period to guaranty minimum wait */
|
||||
if (Delay < LL_MAX_DELAY)
|
||||
{
|
||||
Delay++;
|
||||
}
|
||||
|
||||
while (Delay)
|
||||
{
|
||||
if ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) != 0U)
|
||||
{
|
||||
Delay--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup UTILS_EF_SYSTEM
|
||||
* @brief System Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### System Configuration functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
System, AHB and APB buses clocks configuration
|
||||
|
||||
(+) The maximum frequency of the SYSCLK, HCLK, PCLK1 and PCLK2 is RCC_MAX_FREQUENCY Hz.
|
||||
@endverbatim
|
||||
@internal
|
||||
Depending on the SYSCLK frequency, the flash latency should be adapted accordingly:
|
||||
(++) +-----------------------------------------------+
|
||||
(++) | Latency | SYSCLK clock frequency (MHz) |
|
||||
(++) |---------------|-------------------------------|
|
||||
(++) |0WS(1CPU cycle)| 0 < SYSCLK <= 24 |
|
||||
(++) |---------------|-------------------------------|
|
||||
(++) |1WS(2CPU cycle)| 24 < SYSCLK <= 48 |
|
||||
(++) |---------------|-------------------------------|
|
||||
(++) |2WS(3CPU cycle)| 48 < SYSCLK <= 72 |
|
||||
(++) +-----------------------------------------------+
|
||||
@endinternal
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function sets directly SystemCoreClock CMSIS variable.
|
||||
* @note Variable can be calculated also through SystemCoreClockUpdate function.
|
||||
* @param HCLKFrequency HCLK frequency in Hz (can be calculated thanks to RCC helper macro)
|
||||
* @retval None
|
||||
*/
|
||||
void LL_SetSystemCoreClock(uint32_t HCLKFrequency)
|
||||
{
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock = HCLKFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update number of Flash wait states in line with new frequency and current
|
||||
voltage range.
|
||||
* @param Frequency SYSCLK frequency
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: Latency has been modified
|
||||
* - ERROR: Latency cannot be modified
|
||||
*/
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
ErrorStatus LL_SetFlashLatency(uint32_t Frequency)
|
||||
{
|
||||
uint32_t timeout;
|
||||
uint32_t getlatency;
|
||||
uint32_t latency = LL_FLASH_LATENCY_0; /* default value 0WS */
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Frequency cannot be equal to 0 */
|
||||
if (Frequency == 0U)
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Frequency > UTILS_LATENCY2_FREQ)
|
||||
{
|
||||
/* 48 < SYSCLK <= 72 => 2WS (3 CPU cycles) */
|
||||
latency = LL_FLASH_LATENCY_2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Frequency > UTILS_LATENCY1_FREQ)
|
||||
{
|
||||
/* 24 < SYSCLK <= 48 => 1WS (2 CPU cycles) */
|
||||
latency = LL_FLASH_LATENCY_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* else SYSCLK < 24MHz default LL_FLASH_LATENCY_0 0WS */
|
||||
latency = LL_FLASH_LATENCY_0;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != ERROR)
|
||||
{
|
||||
LL_FLASH_SetLatency(latency);
|
||||
|
||||
/* Check that the new number of wait states is taken into account to access the Flash
|
||||
memory by reading the FLASH_ACR register */
|
||||
timeout = 2;
|
||||
do
|
||||
{
|
||||
/* Wait for Flash latency to be updated */
|
||||
getlatency = LL_FLASH_GetLatency();
|
||||
timeout--;
|
||||
}
|
||||
while ((getlatency != latency) && (timeout > 0));
|
||||
|
||||
if (getlatency != latency)
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
/**
|
||||
* @brief This function configures system clock with HSI as clock source of the PLL
|
||||
* @note The application need to ensure that PLL is disabled.
|
||||
* @note Function is based on the following formula:
|
||||
* - PLL output frequency = ((HSI frequency / PREDIV) * PLLMUL)
|
||||
* - PREDIV: Set to 2 for few devices
|
||||
* - PLLMUL: The application software must set correctly the PLL multiplication factor to
|
||||
* not exceed 72MHz
|
||||
* @note FLASH latency can be modified through this function.
|
||||
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
|
||||
* the configuration information for the BUS prescalers.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: Max frequency configuration done
|
||||
* - ERROR: Max frequency configuration not done
|
||||
*/
|
||||
ErrorStatus LL_PLL_ConfigSystemClock_HSI(LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
|
||||
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t pllfreq = 0U;
|
||||
|
||||
/* Check if one of the PLL is enabled */
|
||||
if (UTILS_PLL_IsBusy() == SUCCESS)
|
||||
{
|
||||
#if defined(RCC_PLLSRC_PREDIV1_SUPPORT)
|
||||
/* Check PREDIV value */
|
||||
assert_param(IS_LL_UTILS_PREDIV_VALUE(UTILS_PLLInitStruct->PLLDiv));
|
||||
#else
|
||||
/* Force PREDIV value to 2 */
|
||||
UTILS_PLLInitStruct->Prediv = LL_RCC_PREDIV_DIV_2;
|
||||
#endif /*RCC_PLLSRC_PREDIV1_SUPPORT*/
|
||||
/* Calculate the new PLL output frequency */
|
||||
pllfreq = UTILS_GetPLLOutputFrequency(HSI_VALUE, UTILS_PLLInitStruct);
|
||||
|
||||
/* Enable HSI if not enabled */
|
||||
if (LL_RCC_HSI_IsReady() != 1U)
|
||||
{
|
||||
LL_RCC_HSI_Enable();
|
||||
while (LL_RCC_HSI_IsReady() != 1U)
|
||||
{
|
||||
/* Wait for HSI ready */
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure PLL */
|
||||
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI_DIV_2, UTILS_PLLInitStruct->PLLMul);
|
||||
|
||||
/* Enable PLL and switch system clock to PLL */
|
||||
status = UTILS_EnablePLLAndSwitchSystem(pllfreq, UTILS_ClkInitStruct);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Current PLL configuration cannot be modified */
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function configures system clock with HSE as clock source of the PLL
|
||||
* @note The application need to ensure that PLL is disabled.
|
||||
* @note Function is based on the following formula:
|
||||
* - PLL output frequency = ((HSI frequency / PREDIV) * PLLMUL)
|
||||
* - PREDIV: Set to 2 for few devices
|
||||
* - PLLMUL: The application software must set correctly the PLL multiplication factor to
|
||||
* not exceed @ref UTILS_PLL_OUTPUT_MAX
|
||||
* @note FLASH latency can be modified through this function.
|
||||
* @param HSEFrequency Value between Min_Data = RCC_HSE_MIN and Max_Data = RCC_HSE_MAX
|
||||
* @param HSEBypass This parameter can be one of the following values:
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_ON
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_OFF
|
||||
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
|
||||
* the configuration information for the BUS prescalers.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: Max frequency configuration done
|
||||
* - ERROR: Max frequency configuration not done
|
||||
*/
|
||||
ErrorStatus LL_PLL_ConfigSystemClock_HSE(uint32_t HSEFrequency, uint32_t HSEBypass,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t pllfrequency = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
|
||||
assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
|
||||
assert_param(IS_LL_UTILS_PREDIV_VALUE(UTILS_PLLInitStruct->Prediv));
|
||||
|
||||
/* Calculate the new PLL output frequency */
|
||||
pllfrequency = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct);
|
||||
|
||||
/* Enable HSE if not enabled */
|
||||
status = UTILS_PLL_HSE_ConfigSystemClock(HSEFrequency, HSEBypass, UTILS_PLLInitStruct, UTILS_ClkInitStruct);
|
||||
|
||||
/* Check if HSE is not enabled*/
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
/* Configure PLL */
|
||||
LL_RCC_PLL_ConfigDomain_SYS((LL_RCC_PLLSOURCE_HSE | UTILS_PLLInitStruct->Prediv), UTILS_PLLInitStruct->PLLMul);
|
||||
|
||||
/* Enable PLL and switch system clock to PLL */
|
||||
status = UTILS_EnablePLLAndSwitchSystem(pllfrequency, UTILS_ClkInitStruct);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
/**
|
||||
* @brief This function configures system clock with HSE as clock source of the PLL, via PLL2
|
||||
* @note The application need to ensure that PLL and PLL2 are disabled.
|
||||
* @note Function is based on the following formula:
|
||||
* - PLL output frequency = ((((HSE frequency / PREDIV2) * PLL2MUL) / PREDIV) * PLLMUL)
|
||||
* - PREDIV, PLLMUL, PREDIV2, PLL2MUL: The application software must set correctly the
|
||||
* PLL multiplication factor to not exceed @ref UTILS_PLL_OUTPUT_MAX
|
||||
* @note FLASH latency can be modified through this function.
|
||||
* @param HSEFrequency Value between Min_Data = RCC_HSE_MIN and Max_Data = RCC_HSE_MAX
|
||||
* @param HSEBypass This parameter can be one of the following values:
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_ON
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_OFF
|
||||
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @param UTILS_PLL2InitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL2.
|
||||
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
|
||||
* the configuration information for the BUS prescalers.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: Max frequency configuration done
|
||||
* - ERROR: Max frequency configuration not done
|
||||
*/
|
||||
ErrorStatus LL_PLL_ConfigSystemClock_PLL2(uint32_t HSEFrequency, uint32_t HSEBypass,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLL2InitStruct,
|
||||
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
uint32_t pllfrequency = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_UTILS_HSE_FREQUENCY(HSEFrequency));
|
||||
assert_param(IS_LL_UTILS_HSE_BYPASS(HSEBypass));
|
||||
assert_param(IS_LL_UTILS_PREDIV_VALUE(UTILS_PLLInitStruct->Prediv));
|
||||
assert_param(IS_LL_UTILS_PREDIV2_VALUE(UTILS_PLL2InitStruct->Prediv));
|
||||
|
||||
/* Calculate the new PLL output frequency */
|
||||
pllfrequency = UTILS_GetPLLOutputFrequency(HSEFrequency, UTILS_PLLInitStruct);
|
||||
|
||||
/* Enable HSE if not enabled */
|
||||
status = UTILS_PLL_HSE_ConfigSystemClock(HSEFrequency, HSEBypass, UTILS_PLLInitStruct, UTILS_ClkInitStruct);
|
||||
|
||||
/* Check if HSE is not enabled*/
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
/* Configure PLL */
|
||||
LL_RCC_PLL_ConfigDomain_PLL2(UTILS_PLL2InitStruct->Prediv, UTILS_PLL2InitStruct->PLLMul);
|
||||
LL_RCC_PLL_ConfigDomain_SYS((LL_RCC_PLLSOURCE_PLL2 | UTILS_PLLInitStruct->Prediv), UTILS_PLLInitStruct->PLLMul);
|
||||
|
||||
/* Calculate the new PLL output frequency */
|
||||
pllfrequency = UTILS_GetPLL2OutputFrequency(pllfrequency, UTILS_PLL2InitStruct);
|
||||
|
||||
/* Enable PLL and switch system clock to PLL */
|
||||
status = UTILS_EnablePLLAndSwitchSystem(pllfrequency, UTILS_ClkInitStruct);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup UTILS_LL_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Function to check that PLL can be modified
|
||||
* @param PLL_InputFrequency PLL input frequency (in Hz)
|
||||
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @retval PLL output frequency (in Hz)
|
||||
*/
|
||||
static uint32_t UTILS_GetPLLOutputFrequency(uint32_t PLL_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct)
|
||||
{
|
||||
uint32_t pllfreq = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_UTILS_PLLMUL_VALUE(UTILS_PLLInitStruct->PLLMul));
|
||||
|
||||
/* Check different PLL parameters according to RM */
|
||||
#if defined (RCC_CFGR2_PREDIV1)
|
||||
pllfreq = __LL_RCC_CALC_PLLCLK_FREQ(PLL_InputFrequency / (UTILS_PLLInitStruct->Prediv + 1U), UTILS_PLLInitStruct->PLLMul);
|
||||
#else
|
||||
pllfreq = __LL_RCC_CALC_PLLCLK_FREQ(PLL_InputFrequency / ((UTILS_PLLInitStruct->Prediv >> RCC_CFGR_PLLXTPRE_Pos) + 1U), UTILS_PLLInitStruct->PLLMul);
|
||||
#endif /*RCC_CFGR2_PREDIV1SRC*/
|
||||
assert_param(IS_LL_UTILS_PLL_FREQUENCY(pllfreq));
|
||||
|
||||
return pllfreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function enable the HSE when it is used by PLL or PLL2
|
||||
* @note The application need to ensure that PLL is disabled.
|
||||
* @param HSEFrequency Value between Min_Data = RCC_HSE_MIN and Max_Data = RCC_HSE_MAX
|
||||
* @param HSEBypass This parameter can be one of the following values:
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_ON
|
||||
* @arg @ref LL_UTILS_HSEBYPASS_OFF
|
||||
* @param UTILS_PLLInitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
|
||||
* the configuration information for the BUS prescalers.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: HSE configuration done
|
||||
* - ERROR: HSE configuration not done
|
||||
*/
|
||||
static ErrorStatus UTILS_PLL_HSE_ConfigSystemClock(uint32_t PLL_InputFrequency, uint32_t HSEBypass,
|
||||
LL_UTILS_PLLInitTypeDef *UTILS_PLLInitStruct,
|
||||
LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check if one of the PLL is enabled */
|
||||
if (UTILS_PLL_IsBusy() == SUCCESS)
|
||||
{
|
||||
/* Enable HSE if not enabled */
|
||||
if (LL_RCC_HSE_IsReady() != 1U)
|
||||
{
|
||||
/* Check if need to enable HSE bypass feature or not */
|
||||
if (HSEBypass == LL_UTILS_HSEBYPASS_ON)
|
||||
{
|
||||
LL_RCC_HSE_EnableBypass();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_RCC_HSE_DisableBypass();
|
||||
}
|
||||
|
||||
/* Enable HSE */
|
||||
LL_RCC_HSE_Enable();
|
||||
while (LL_RCC_HSE_IsReady() != 1U)
|
||||
{
|
||||
/* Wait for HSE ready */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Current PLL configuration cannot be modified */
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
/**
|
||||
* @brief Function to check that PLL2 can be modified
|
||||
* @param PLL2_InputFrequency PLL2 input frequency (in Hz)
|
||||
* @param UTILS_PLL2InitStruct pointer to a @ref LL_UTILS_PLLInitTypeDef structure that contains
|
||||
* the configuration information for the PLL.
|
||||
* @retval PLL2 output frequency (in Hz)
|
||||
*/
|
||||
static uint32_t UTILS_GetPLL2OutputFrequency(uint32_t PLL2_InputFrequency, LL_UTILS_PLLInitTypeDef *UTILS_PLL2InitStruct)
|
||||
{
|
||||
uint32_t pll2freq = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_UTILS_PLL2MUL_VALUE(UTILS_PLL2InitStruct->PLLMul));
|
||||
assert_param(IS_LL_UTILS_PREDIV2_VALUE(UTILS_PLL2InitStruct->Prediv));
|
||||
|
||||
/* Check different PLL2 parameters according to RM */
|
||||
pll2freq = __LL_RCC_CALC_PLL2CLK_FREQ(PLL2_InputFrequency, UTILS_PLL2InitStruct->PLLMul, UTILS_PLL2InitStruct->Prediv);
|
||||
assert_param(IS_LL_UTILS_PLL2_FREQUENCY(pll2freq));
|
||||
|
||||
return pll2freq;
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
/**
|
||||
* @brief Function to check that PLL can be modified
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: PLL modification can be done
|
||||
* - ERROR: PLL is busy
|
||||
*/
|
||||
static ErrorStatus UTILS_PLL_IsBusy(void)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check if PLL is busy*/
|
||||
if (LL_RCC_PLL_IsReady() != 0U)
|
||||
{
|
||||
/* PLL configuration cannot be modified */
|
||||
status = ERROR;
|
||||
}
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
/* Check if PLL2 is busy*/
|
||||
if (LL_RCC_PLL2_IsReady() != 0U)
|
||||
{
|
||||
/* PLL2 configuration cannot be modified */
|
||||
status = ERROR;
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
#if defined(RCC_PLLI2S_SUPPORT)
|
||||
/* Check if PLLI2S is busy*/
|
||||
if (LL_RCC_PLLI2S_IsReady() != 0U)
|
||||
{
|
||||
/* PLLI2S configuration cannot be modified */
|
||||
status = ERROR;
|
||||
}
|
||||
#endif /* RCC_PLLI2S_SUPPORT */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Function to enable PLL and switch system clock to PLL
|
||||
* @param SYSCLK_Frequency SYSCLK frequency
|
||||
* @param UTILS_ClkInitStruct pointer to a @ref LL_UTILS_ClkInitTypeDef structure that contains
|
||||
* the configuration information for the BUS prescalers.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: No problem to switch system to PLL
|
||||
* - ERROR: Problem to switch system to PLL
|
||||
*/
|
||||
static ErrorStatus UTILS_EnablePLLAndSwitchSystem(uint32_t SYSCLK_Frequency, LL_UTILS_ClkInitTypeDef *UTILS_ClkInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
uint32_t sysclk_frequency_current = 0U;
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
assert_param(IS_LL_UTILS_SYSCLK_DIV(UTILS_ClkInitStruct->AHBCLKDivider));
|
||||
assert_param(IS_LL_UTILS_APB1_DIV(UTILS_ClkInitStruct->APB1CLKDivider));
|
||||
assert_param(IS_LL_UTILS_APB2_DIV(UTILS_ClkInitStruct->APB2CLKDivider));
|
||||
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
/* Calculate current SYSCLK frequency */
|
||||
sysclk_frequency_current = (SystemCoreClock << AHBPrescTable[LL_RCC_GetAHBPrescaler() >> RCC_CFGR_HPRE_Pos]);
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
/* Increasing the number of wait states because of higher CPU frequency */
|
||||
#if defined (FLASH_ACR_LATENCY)
|
||||
if (sysclk_frequency_current < SYSCLK_Frequency)
|
||||
{
|
||||
/* Set FLASH latency to highest latency */
|
||||
status = LL_SetFlashLatency(SYSCLK_Frequency);
|
||||
}
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
/* Update system clock configuration */
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
if (LL_RCC_PLL_GetMainSource() != LL_RCC_PLLSOURCE_HSI_DIV_2)
|
||||
{
|
||||
/* Enable PLL2 */
|
||||
LL_RCC_PLL2_Enable();
|
||||
while (LL_RCC_PLL2_IsReady() != 1U)
|
||||
{
|
||||
/* Wait for PLL2 ready */
|
||||
}
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
/* Enable PLL */
|
||||
LL_RCC_PLL_Enable();
|
||||
while (LL_RCC_PLL_IsReady() != 1U)
|
||||
{
|
||||
/* Wait for PLL ready */
|
||||
}
|
||||
|
||||
/* Sysclk activation on the main PLL */
|
||||
LL_RCC_SetAHBPrescaler(UTILS_ClkInitStruct->AHBCLKDivider);
|
||||
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
|
||||
while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
|
||||
{
|
||||
/* Wait for system clock switch to PLL */
|
||||
}
|
||||
|
||||
/* Set APB1 & APB2 prescaler*/
|
||||
LL_RCC_SetAPB1Prescaler(UTILS_ClkInitStruct->APB1CLKDivider);
|
||||
LL_RCC_SetAPB2Prescaler(UTILS_ClkInitStruct->APB2CLKDivider);
|
||||
}
|
||||
|
||||
/* Decreasing the number of wait states because of lower CPU frequency */
|
||||
#if defined (FLASH_ACR_LATENCY)
|
||||
if (sysclk_frequency_current > SYSCLK_Frequency)
|
||||
{
|
||||
/* Set FLASH latency to lowest latency */
|
||||
status = LL_SetFlashLatency(SYSCLK_Frequency);
|
||||
}
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
/* Update SystemCoreClock variable */
|
||||
if (status == SUCCESS)
|
||||
{
|
||||
LL_SetSystemCoreClock(__LL_RCC_CALC_HCLK_FREQ(SYSCLK_Frequency, UTILS_ClkInitStruct->AHBCLKDivider));
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
Reference in New Issue
Block a user