From 9fc2f0b73bf21714da390e5c174d57f024b4629b Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Sun, 14 Jun 2026 21:32:29 +0200 Subject: [PATCH] Remove files that were misteriously duplicated... --- Core/Src/ThreadSafe/newlib_lock_glue.c | 435 --- .../Src/stm32f4xx_hal_dma_ex 2.c | 313 -- .../Src/stm32f4xx_hal_flash_ex 2.c | 1344 ------- .../Src/stm32f4xx_hal_sd 2.c | 3288 ----------------- .../Third_Party/FreeRTOS/Source/queue 2.c | 2945 --------------- 5 files changed, 8325 deletions(-) delete mode 100644 Core/Src/ThreadSafe/newlib_lock_glue.c delete mode 100644 Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex 2.c delete mode 100644 Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex 2.c delete mode 100644 Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd 2.c delete mode 100644 Middlewares/Third_Party/FreeRTOS/Source/queue 2.c diff --git a/Core/Src/ThreadSafe/newlib_lock_glue.c b/Core/Src/ThreadSafe/newlib_lock_glue.c deleted file mode 100644 index 744d87e..0000000 --- a/Core/Src/ThreadSafe/newlib_lock_glue.c +++ /dev/null @@ -1,435 +0,0 @@ -/** - ****************************************************************************** - * @file newlib_lock_glue.c - * @author STMicroelectronics - * @brief Implementation of newlib lock interface - * - * @details This file implements locking glue necessary to protect C library - * functions and initialization of local static objects in C++. - * Lock strategies are defined in stm32_lock.h that implements - * different level of thread-safety. - * - * For more information about which C functions need which of these - * low level functions, please consult the newlib libc manual, - * see https://sourceware.org/newlib/libc.html - * - * For more information about the one-time construction API for C++, - * see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor - * - ****************************************************************************** - * @attention - * - * Copyright (c) 2026 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 (__GNUC__) || defined (__CC_ARM) -#error "newlib_lock_glue.c" should be used with GNU Compilers only -#endif /* !defined (__GNUC__) || defined (__CC_ARM) */ - -/* Includes ------------------------------------------------------------------*/ -#include - -/* Private functions prototypes ----------------------------------------------*/ -__WEAK void Error_Handler(void); -/* Private functions ---------------------------------------------------------*/ - -/** - * @brief Global Error_Handler - */ -__WEAK void Error_Handler(void) -{ - /* Not used if it exists in project */ - while (1); -} - -#ifdef __SINGLE_THREAD__ -#warning C library is in single-threaded mode. Please take care when using C library functions in threaded contexts -#else - -/* Includes ------------------------------------------------------------------*/ -#include -#include -#include "stm32_lock.h" - -/** - * @defgroup _newlib_lock_functions newlib library locks - * @see https://sourceware.org/newlib/libc.html - * @{ - */ - -#if __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING) -#include -#include -#include - -/* Private macros ------------------------------------------------------------*/ -/** See struct __lock definition */ -#define STM32_LOCK_PARAMETER(lock) (&(lock)->lock_data) - -/* shared variables for bare metal allow lock ------------------------------------------------------*/ -#if defined(STM32_THREAD_SAFE_BAREMETAL_ALLOW_LOCKS) && (STM32_THREAD_SAFE_BAREMETAL_ALLOW_LOCKS != 0) -uint32_t gflag = 0; -uint32_t call_counter = 0; -#endif /* defined(STM32_THREAD_SAFE_BAREMETAL_ALLOW_LOCKS) && (STM32_THREAD_SAFE_BAREMETAL_ALLOW_LOCKS != 0) */ - -/* Private variables ---------------------------------------------------------*/ -struct __lock -{ - LockingData_t lock_data; /**< The STM32 lock instance */ -}; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___sinit_recursive_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___sfp_recursive_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___atexit_recursive_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___at_quick_exit_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___malloc_recursive_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___env_recursive_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___tz_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___dd_hash_mutex = { LOCKING_DATA_INIT }; - -/** Implementing mutex from newlib/libc/misc/lock.c */ -struct __lock __lock___arc4random_mutex = { LOCKING_DATA_INIT }; - -/* Private functions ---------------------------------------------------------*/ - -/** - * @brief Initialize lock - * @param lock The lock - */ -void __retarget_lock_init(_LOCK_T *lock) -{ - __retarget_lock_init_recursive(lock); -} - -/** - * @brief Initialize recursive lock - * @param lock The lock - */ -void __retarget_lock_init_recursive(_LOCK_T *lock) -{ - if (lock == NULL) - { - errno = EINVAL; - return; - } - - *lock = (_LOCK_T)malloc(sizeof(struct __lock)); - if (*lock != NULL) - { - stm32_lock_init(STM32_LOCK_PARAMETER(*lock)); - return; - } - - /* Unable to allocate memory */ - STM32_LOCK_BLOCK(); -} - -/** - * @brief Close lock - * @param lock The lock - */ -void __retarget_lock_close(_LOCK_T lock) -{ - __retarget_lock_close_recursive(lock); -} - -/** - * @brief Close recursive lock - * @param lock The lock - */ -void __retarget_lock_close_recursive(_LOCK_T lock) -{ - free(lock); -} - -/** - * @brief Acquire lock - * @param lock The lock - */ -void __retarget_lock_acquire(_LOCK_T lock) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); - stm32_lock_acquire(STM32_LOCK_PARAMETER(lock)); -} - -/** - * @brief Acquire recursive lock - * @param lock The lock - */ -void __retarget_lock_acquire_recursive(_LOCK_T lock) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); - stm32_lock_acquire(STM32_LOCK_PARAMETER(lock)); -} - -/** - * @brief Try acquire lock - * @param lock The lock - * @return 0 always - */ -int __retarget_lock_try_acquire(_LOCK_T lock) -{ - __retarget_lock_acquire(lock); - return 0; -} - -/** - * @brief Try acquire recursive lock - * @param lock The lock - * @return 0 always - */ -int __retarget_lock_try_acquire_recursive(_LOCK_T lock) -{ - __retarget_lock_acquire_recursive(lock); - return 0; -} - -/** - * @brief Release lock - * @param lock The lock - */ -void __retarget_lock_release(_LOCK_T lock) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); - stm32_lock_release(STM32_LOCK_PARAMETER(lock)); -} - -/** - * @brief Release recursive lock - * @param lock The lock - */ -void __retarget_lock_release_recursive(_LOCK_T lock) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(lock); - stm32_lock_release(STM32_LOCK_PARAMETER(lock)); -} - -#else -#warning This makes malloc, env, and TZ calls thread-safe, not the entire newlib - -/* Includes ------------------------------------------------------------------*/ -#include - -/* Private variables ---------------------------------------------------------*/ -/** Mutex used in __malloc_lock and __malloc_unlock */ -static LockingData_t __lock___malloc_recursive_mutex = LOCKING_DATA_INIT; - -/** Mutex used in __env_lock and __env_unlock */ -static LockingData_t __lock___env_recursive_mutex = LOCKING_DATA_INIT; - -/** Mutex used in __tz_lock and __tz_unlock */ -static LockingData_t __lock___tz_mutex = LOCKING_DATA_INIT; - -/* Private functions ---------------------------------------------------------*/ - -#if __STD_C - -/** - * @brief Acquire malloc lock - * @param reent The reentrance struct - */ -void __malloc_lock(struct _reent *reent) -{ - STM32_LOCK_UNUSED(reent); - stm32_lock_acquire(&__lock___malloc_recursive_mutex); -} - -/** - * @brief Release malloc lock - * @param reent The reentrance struct - */ -void __malloc_unlock(struct _reent *reent) -{ - STM32_LOCK_UNUSED(reent); - stm32_lock_release(&__lock___malloc_recursive_mutex); -} - -#else - -/** - * @brief Acquire malloc lock - */ -void __malloc_lock() -{ - stm32_lock_acquire(&__lock___malloc_recursive_mutex); -} - -/** - * @brief Release malloc lock - */ -void __malloc_unlock() -{ - stm32_lock_release(&__lock___malloc_recursive_mutex); -} -#endif /* __STD_C */ - -/** - * @brief Acquire env lock - * @param reent The reentrance struct - */ -void __env_lock(struct _reent *reent) -{ - STM32_LOCK_UNUSED(reent); - stm32_lock_acquire(&__lock___env_recursive_mutex); -} - -/** - * @brief Release env lock - * @param reent The reentrance struct - */ -void __env_unlock(struct _reent *reent) -{ - STM32_LOCK_UNUSED(reent); - stm32_lock_release(&__lock___env_recursive_mutex); -} - -/** - * @brief Acquire tz lock - */ -void __tz_lock() -{ - stm32_lock_acquire(&__lock___tz_mutex); -} - -/** - * @brief Release tz lock - */ -void __tz_unlock() -{ - stm32_lock_release(&__lock___tz_mutex); -} - -#endif /* __NEWLIB__ >= 3 && defined (_RETARGETABLE_LOCKING) */ - -/** - * @} - */ - - -/** - * @defgroup __cxa_guard_ GNU C++ one-time construction API - * @see https://itanium-cxx-abi.github.io/cxx-abi/abi.html#once-ctor - * - * When building for C++, please make sure that -fno-threadsafe-statics is not passed to the compiler - * @{ - */ - -/* Private typedef -----------------------------------------------------------*/ -/** The guard object is created by the C++ compiler and is 32 bit for ARM EABI. */ -typedef struct -{ - atomic_uchar initialized; /**< Indicate if object is initialized */ - uint8_t acquired; /**< Ensure non-recursive lock */ - uint16_t unused; /**< Padding */ -} __attribute__((packed)) CxaGuardObject_t; - -/* Private variables ---------------------------------------------------------*/ -/** Mutex used in __cxa_guard_acquire, __cxa_guard_release and __cxa_guard_abort */ -static LockingData_t __cxa_guard_mutex = LOCKING_DATA_INIT; - -/* Private functions prototype ---------------------------------------------------------*/ -int __cxa_guard_acquire(CxaGuardObject_t *guard_object); -void __cxa_guard_abort(CxaGuardObject_t *guard_object); -void __cxa_guard_release(CxaGuardObject_t *guard_object); -/* Private functions ---------------------------------------------------------*/ - -/** - * @brief Acquire __cxa_guard mutex - * @param guard_object Guard object - * @return 0 if object is initialized, else initialization of object required - */ -int __cxa_guard_acquire(CxaGuardObject_t *guard_object) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object); - - if (atomic_load(&guard_object->initialized) == 0) - { - /* Object needs initialization, lock threading context */ - stm32_lock_acquire(&__cxa_guard_mutex); - if (atomic_load(&guard_object->initialized) == 0) - { - /* Object needs initialization */ - if (guard_object->acquired) - { - /* Object initialization already in progress */ - STM32_LOCK_BLOCK(); - } - - /* Lock acquired */ - guard_object->acquired = 1; - return 1; - } - else - { - /* Object initialized in another thread */ - stm32_lock_release(&__cxa_guard_mutex); - } - } - - /* Object already initialized */ - return 0; -} - -/** - * @brief Abort __cxa_guard mutex - * @param guard_object Guard object - */ -void __cxa_guard_abort(CxaGuardObject_t *guard_object) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object); - - if (guard_object->acquired) - { - /* Release lock */ - guard_object->acquired = 0; - stm32_lock_release(&__cxa_guard_mutex); - } - else - { - /* Trying to release non-acquired lock */ - STM32_LOCK_BLOCK(); - } -} - -/** - * @brief Release __cxa_guard mutex - * @param guard_object Guard object - */ -void __cxa_guard_release(CxaGuardObject_t *guard_object) -{ - STM32_LOCK_BLOCK_IF_NULL_ARGUMENT(guard_object); - - /* Object initialized */ - atomic_store(&guard_object->initialized, 1); - - /* Release lock */ - __cxa_guard_abort(guard_object); -} - -/** - * @} - */ - -#endif /* __SINGLE_THREAD__ */ diff --git a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex 2.c b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex 2.c deleted file mode 100644 index 7167e77..0000000 --- a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_dma_ex 2.c +++ /dev/null @@ -1,313 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_dma_ex.c - * @author MCD Application Team - * @brief DMA Extension HAL module driver - * This file provides firmware functions to manage the following - * functionalities of the DMA Extension peripheral: - * + Extended features functions - * - @verbatim - ============================================================================== - ##### How to use this driver ##### - ============================================================================== - [..] - The DMA Extension HAL driver can be used as follows: - (#) Start a multi buffer transfer using the HAL_DMA_MultiBufferStart() function - for polling mode or HAL_DMA_MultiBufferStart_IT() for interrupt mode. - - -@- In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed. - -@- When Multi (Double) Buffer mode is enabled the, transfer is circular by default. - -@- In Multi (Double) buffer mode, it is possible to update the base address for - the AHB memory port on the fly (DMA_SxM0AR or DMA_SxM1AR) when the stream is enabled. - - @endverbatim - ****************************************************************************** - * @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 "stm32f4xx_hal.h" - -/** @addtogroup STM32F4xx_HAL_Driver - * @{ - */ - -/** @defgroup DMAEx DMAEx - * @brief DMA Extended HAL module driver - * @{ - */ - -#ifdef HAL_DMA_MODULE_ENABLED - -/* Private types -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/* Private Constants ---------------------------------------------------------*/ -/* Private macros ------------------------------------------------------------*/ -/* Private functions ---------------------------------------------------------*/ -/** @addtogroup DMAEx_Private_Functions - * @{ - */ -static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); -/** - * @} - */ - -/* Exported functions ---------------------------------------------------------*/ - -/** @addtogroup DMAEx_Exported_Functions - * @{ - */ - - -/** @addtogroup DMAEx_Exported_Functions_Group1 - * -@verbatim - =============================================================================== - ##### Extended features functions ##### - =============================================================================== - [..] This section provides functions allowing to: - (+) Configure the source, destination address and data length and - Start MultiBuffer DMA transfer - (+) Configure the source, destination address and data length and - Start MultiBuffer DMA transfer with interrupt - (+) Change on the fly the memory0 or memory1 address. - -@endverbatim - * @{ - */ - - -/** - * @brief Starts the multi_buffer DMA Transfer. - * @param hdma pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA Stream. - * @param SrcAddress The source memory Buffer address - * @param DstAddress The destination memory Buffer address - * @param SecondMemAddress The second memory Buffer address in case of multi buffer Transfer - * @param DataLength The length of data to be transferred from source to destination - * @retval HAL status - */ -HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_DMA_BUFFER_SIZE(DataLength)); - - /* Memory-to-memory transfer not supported in double buffering mode */ - if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) - { - hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; - status = HAL_ERROR; - } - else - { - /* Process Locked */ - __HAL_LOCK(hdma); - - if(HAL_DMA_STATE_READY == hdma->State) - { - /* Change DMA peripheral state */ - hdma->State = HAL_DMA_STATE_BUSY; - - /* Enable the double buffer mode */ - hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; - - /* Configure DMA Stream destination address */ - hdma->Instance->M1AR = SecondMemAddress; - - /* Configure the source, destination address and the data length */ - DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength); - - /* Enable the peripheral */ - __HAL_DMA_ENABLE(hdma); - } - else - { - /* Return error status */ - status = HAL_BUSY; - } - } - return status; -} - -/** - * @brief Starts the multi_buffer DMA Transfer with interrupt enabled. - * @param hdma pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA Stream. - * @param SrcAddress The source memory Buffer address - * @param DstAddress The destination memory Buffer address - * @param SecondMemAddress The second memory Buffer address in case of multi buffer Transfer - * @param DataLength The length of data to be transferred from source to destination - * @retval HAL status - */ -HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_DMA_BUFFER_SIZE(DataLength)); - - /* Memory-to-memory transfer not supported in double buffering mode */ - if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) - { - hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; - return HAL_ERROR; - } - - /* Check callback functions */ - if ((NULL == hdma->XferCpltCallback) || (NULL == hdma->XferM1CpltCallback) || (NULL == hdma->XferErrorCallback)) - { - hdma->ErrorCode = HAL_DMA_ERROR_PARAM; - return HAL_ERROR; - } - - /* Process locked */ - __HAL_LOCK(hdma); - - if(HAL_DMA_STATE_READY == hdma->State) - { - /* Change DMA peripheral state */ - hdma->State = HAL_DMA_STATE_BUSY; - - /* Initialize the error code */ - hdma->ErrorCode = HAL_DMA_ERROR_NONE; - - /* Enable the Double buffer mode */ - hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM; - - /* Configure DMA Stream destination address */ - hdma->Instance->M1AR = SecondMemAddress; - - /* Configure the source, destination address and the data length */ - DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength); - - /* Clear all flags */ - __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)); - __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)); - __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)); - __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)); - __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)); - - /* Enable Common interrupts*/ - hdma->Instance->CR |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME; - hdma->Instance->FCR |= DMA_IT_FE; - - if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL)) - { - hdma->Instance->CR |= DMA_IT_HT; - } - - /* Enable the peripheral */ - __HAL_DMA_ENABLE(hdma); - } - else - { - /* Process unlocked */ - __HAL_UNLOCK(hdma); - - /* Return error status */ - status = HAL_BUSY; - } - return status; -} - -/** - * @brief Change the memory0 or memory1 address on the fly. - * @param hdma pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA Stream. - * @param Address The new address - * @param memory the memory to be changed, This parameter can be one of - * the following values: - * MEMORY0 / - * MEMORY1 - * @note The MEMORY0 address can be changed only when the current transfer use - * MEMORY1 and the MEMORY1 address can be changed only when the current - * transfer use MEMORY0. - * @retval HAL status - */ -HAL_StatusTypeDef HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef *hdma, uint32_t Address, HAL_DMA_MemoryTypeDef memory) -{ - if(memory == MEMORY0) - { - /* change the memory0 address */ - hdma->Instance->M0AR = Address; - } - else - { - /* change the memory1 address */ - hdma->Instance->M1AR = Address; - } - - return HAL_OK; -} - -/** - * @} - */ - -/** - * @} - */ - -/** @addtogroup DMAEx_Private_Functions - * @{ - */ - -/** - * @brief Set the DMA Transfer parameter. - * @param hdma pointer to a DMA_HandleTypeDef structure that contains - * the configuration information for the specified DMA Stream. - * @param SrcAddress The source memory Buffer address - * @param DstAddress The destination memory Buffer address - * @param DataLength The length of data to be transferred from source to destination - * @retval HAL status - */ -static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) -{ - /* Configure DMA Stream data length */ - hdma->Instance->NDTR = DataLength; - - /* Peripheral to Memory */ - if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) - { - /* Configure DMA Stream destination address */ - hdma->Instance->PAR = DstAddress; - - /* Configure DMA Stream source address */ - hdma->Instance->M0AR = SrcAddress; - } - /* Memory to Peripheral */ - else - { - /* Configure DMA Stream source address */ - hdma->Instance->PAR = SrcAddress; - - /* Configure DMA Stream destination address */ - hdma->Instance->M0AR = DstAddress; - } -} - -/** - * @} - */ - -#endif /* HAL_DMA_MODULE_ENABLED */ -/** - * @} - */ - -/** - * @} - */ - diff --git a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex 2.c b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex 2.c deleted file mode 100644 index 839c91b..0000000 --- a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_flash_ex 2.c +++ /dev/null @@ -1,1344 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f4xx_hal_flash_ex.c - * @author MCD Application Team - * @brief Extended FLASH HAL module driver. - * This file provides firmware functions to manage the following - * functionalities of the FLASH extension peripheral: - * + Extended programming operations functions - * - @verbatim - ============================================================================== - ##### Flash Extension features ##### - ============================================================================== - - [..] Comparing to other previous devices, the FLASH interface for STM32F427xx/437xx and - STM32F429xx/439xx devices contains the following additional features - - (+) Capacity up to 2 Mbyte with dual bank architecture supporting read-while-write - capability (RWW) - (+) Dual bank memory organization - (+) PCROP protection for all banks - - ##### How to use this driver ##### - ============================================================================== - [..] This driver provides functions to configure and program the FLASH memory - of all STM32F427xx/437xx, STM32F429xx/439xx, STM32F469xx/479xx and STM32F446xx - devices. It includes - (#) FLASH Memory Erase functions: - (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and - HAL_FLASH_Lock() functions - (++) Erase function: Erase sector, erase all sectors - (++) There are two modes of erase : - (+++) Polling Mode using HAL_FLASHEx_Erase() - (+++) Interrupt Mode using HAL_FLASHEx_Erase_IT() - - (#) Option Bytes Programming functions: Use HAL_FLASHEx_OBProgram() to : - (++) Set/Reset the write protection - (++) Set the Read protection Level - (++) Set the BOR level - (++) Program the user Option Bytes - (#) Advanced Option Bytes Programming functions: Use HAL_FLASHEx_AdvOBProgram() to : - (++) Extended space (bank 2) erase function - (++) Full FLASH space (2 Mo) erase (bank 1 and bank 2) - (++) Dual Boot activation - (++) Write protection configuration for bank 2 - (++) PCROP protection configuration and control for both banks - - @endverbatim - ****************************************************************************** - * @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 "stm32f4xx_hal.h" - -/** @addtogroup STM32F4xx_HAL_Driver - * @{ - */ - -/** @defgroup FLASHEx FLASHEx - * @brief FLASH HAL Extension module driver - * @{ - */ - -#ifdef HAL_FLASH_MODULE_ENABLED - -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -/** @addtogroup FLASHEx_Private_Constants - * @{ - */ -#define FLASH_TIMEOUT_VALUE 50000U /* 50 s */ -/** - * @} - */ - -/* Private macro -------------------------------------------------------------*/ -/* Private variables ---------------------------------------------------------*/ -/** @addtogroup FLASHEx_Private_Variables - * @{ - */ -extern FLASH_ProcessTypeDef pFlash; -/** - * @} - */ - -/* Private function prototypes -----------------------------------------------*/ -/** @addtogroup FLASHEx_Private_Functions - * @{ - */ -/* Option bytes control */ -static void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks); -static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks); -static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks); -static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level); -static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby); -static HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level); -static uint8_t FLASH_OB_GetUser(void); -static uint16_t FLASH_OB_GetWRP(void); -static uint8_t FLASH_OB_GetRDP(void); -static uint8_t FLASH_OB_GetBOR(void); - -#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) || defined(STM32F411xE) ||\ - defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||\ - defined(STM32F423xx) -static HAL_StatusTypeDef FLASH_OB_EnablePCROP(uint32_t Sector); -static HAL_StatusTypeDef FLASH_OB_DisablePCROP(uint32_t Sector); -#endif /* STM32F401xC || STM32F401xE || STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx - STM32F413xx || STM32F423xx */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) -static HAL_StatusTypeDef FLASH_OB_EnablePCROP(uint32_t SectorBank1, uint32_t SectorBank2, uint32_t Banks); -static HAL_StatusTypeDef FLASH_OB_DisablePCROP(uint32_t SectorBank1, uint32_t SectorBank2, uint32_t Banks); -static HAL_StatusTypeDef FLASH_OB_BootConfig(uint8_t BootConfig); -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -extern HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout); -/** - * @} - */ - -/* Exported functions --------------------------------------------------------*/ -/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions - * @{ - */ - -/** @defgroup FLASHEx_Exported_Functions_Group1 Extended IO operation functions - * @brief Extended IO operation functions - * -@verbatim - =============================================================================== - ##### Extended programming operation functions ##### - =============================================================================== - [..] - This subsection provides a set of functions allowing to manage the Extension FLASH - programming operations. - -@endverbatim - * @{ - */ -/** - * @brief Perform a mass erase or erase the specified FLASH memory sectors - * @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that - * contains the configuration information for the erasing. - * - * @param[out] SectorError pointer to variable that - * contains the configuration information on faulty sector in case of error - * (0xFFFFFFFFU means that all the sectors have been correctly erased) - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *SectorError) -{ - HAL_StatusTypeDef status; - uint32_t index = 0U; - - /* Process Locked */ - __HAL_LOCK(&pFlash); - - /* Check the parameters */ - assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - /*Initialization of SectorError variable*/ - *SectorError = 0xFFFFFFFFU; - - if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) - { - /*Mass erase to be done*/ - FLASH_MassErase((uint8_t) pEraseInit->VoltageRange, pEraseInit->Banks); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - /* if the erase operation is completed, disable the MER Bit */ - FLASH->CR &= (~FLASH_MER_BIT); - } - else - { - /* Check the parameters */ - assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector)); - - /* Erase by sector by sector to be done*/ - for (index = pEraseInit->Sector; index < (pEraseInit->NbSectors + pEraseInit->Sector); index++) - { - FLASH_Erase_Sector(index, (uint8_t) pEraseInit->VoltageRange); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - /* If the erase operation is completed, disable the SER and SNB Bits */ - CLEAR_BIT(FLASH->CR, (FLASH_CR_SER | FLASH_CR_SNB)); - - if (status != HAL_OK) - { - /* In case of error, stop erase procedure and return the faulty sector*/ - *SectorError = index; - break; - } - } - } - /* Flush the caches to be sure of the data consistency */ - FLASH_FlushCaches(); - } - - /* Process Unlocked */ - __HAL_UNLOCK(&pFlash); - - return status; -} - -/** - * @brief Perform a mass erase or erase the specified FLASH memory sectors with interrupt enabled - * @param pEraseInit pointer to an FLASH_EraseInitTypeDef structure that - * contains the configuration information for the erasing. - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase)); - - /* Enable End of FLASH Operation interrupt */ - __HAL_FLASH_ENABLE_IT(FLASH_IT_EOP); - - /* Enable Error source interrupt */ - __HAL_FLASH_ENABLE_IT(FLASH_IT_ERR); - - /* Clear pending flags (if any) */ - __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | \ - FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); - - if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE) - { - /*Mass erase to be done*/ - pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE; - pFlash.Bank = pEraseInit->Banks; - FLASH_MassErase((uint8_t) pEraseInit->VoltageRange, pEraseInit->Banks); - } - else - { - /* Erase by sector to be done*/ - - /* Check the parameters */ - assert_param(IS_FLASH_NBSECTORS(pEraseInit->NbSectors + pEraseInit->Sector)); - - pFlash.ProcedureOnGoing = FLASH_PROC_SECTERASE; - pFlash.NbSectorsToErase = pEraseInit->NbSectors; - pFlash.Sector = pEraseInit->Sector; - pFlash.VoltageForErase = (uint8_t)pEraseInit->VoltageRange; - - /*Erase 1st sector and wait for IT*/ - FLASH_Erase_Sector(pEraseInit->Sector, pEraseInit->VoltageRange); - } - - return status; -} - -/** - * @brief Program option bytes - * @param pOBInit pointer to an FLASH_OBInitStruct structure that - * contains the configuration information for the programming. - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit) -{ - HAL_StatusTypeDef status = HAL_ERROR; - - /* Process Locked */ - __HAL_LOCK(&pFlash); - - /* Check the parameters */ - assert_param(IS_OPTIONBYTE(pOBInit->OptionType)); - - /*Write protection configuration*/ - if ((pOBInit->OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP) - { - assert_param(IS_WRPSTATE(pOBInit->WRPState)); - if (pOBInit->WRPState == OB_WRPSTATE_ENABLE) - { - /*Enable of Write protection on the selected Sector*/ - status = FLASH_OB_EnableWRP(pOBInit->WRPSector, pOBInit->Banks); - } - else - { - /*Disable of Write protection on the selected Sector*/ - status = FLASH_OB_DisableWRP(pOBInit->WRPSector, pOBInit->Banks); - } - } - - /*Read protection configuration*/ - if ((pOBInit->OptionType & OPTIONBYTE_RDP) == OPTIONBYTE_RDP) - { - status = FLASH_OB_RDP_LevelConfig(pOBInit->RDPLevel); - } - - /*USER configuration*/ - if ((pOBInit->OptionType & OPTIONBYTE_USER) == OPTIONBYTE_USER) - { - status = FLASH_OB_UserConfig(pOBInit->USERConfig & OB_IWDG_SW, - pOBInit->USERConfig & OB_STOP_NO_RST, - pOBInit->USERConfig & OB_STDBY_NO_RST); - } - - /*BOR Level configuration*/ - if ((pOBInit->OptionType & OPTIONBYTE_BOR) == OPTIONBYTE_BOR) - { - status = FLASH_OB_BOR_LevelConfig(pOBInit->BORLevel); - } - - /* Process Unlocked */ - __HAL_UNLOCK(&pFlash); - - return status; -} - -/** - * @brief Get the Option byte configuration - * @param pOBInit pointer to an FLASH_OBInitStruct structure that - * contains the configuration information for the programming. - * - * @retval None - */ -void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit) -{ - pOBInit->OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER | OPTIONBYTE_BOR; - - /*Get WRP*/ - pOBInit->WRPSector = (uint32_t)FLASH_OB_GetWRP(); - - /*Get RDP Level*/ - pOBInit->RDPLevel = (uint32_t)FLASH_OB_GetRDP(); - - /*Get USER*/ - pOBInit->USERConfig = (uint8_t)FLASH_OB_GetUser(); - - /*Get BOR Level*/ - pOBInit->BORLevel = (uint32_t)FLASH_OB_GetBOR(); -} - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) ||\ - defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F469xx) ||\ - defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||\ - defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) -/** - * @brief Program option bytes - * @param pAdvOBInit pointer to an FLASH_AdvOBProgramInitTypeDef structure that - * contains the configuration information for the programming. - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_AdvOBProgram(FLASH_AdvOBProgramInitTypeDef *pAdvOBInit) -{ - HAL_StatusTypeDef status = HAL_ERROR; - - /* Check the parameters */ - assert_param(IS_OBEX(pAdvOBInit->OptionType)); - - /*Program PCROP option byte*/ - if (((pAdvOBInit->OptionType) & OPTIONBYTE_PCROP) == OPTIONBYTE_PCROP) - { - /* Check the parameters */ - assert_param(IS_PCROPSTATE(pAdvOBInit->PCROPState)); - if ((pAdvOBInit->PCROPState) == OB_PCROP_STATE_ENABLE) - { - /*Enable of Write protection on the selected Sector*/ -#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ - defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||\ - defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) - status = FLASH_OB_EnablePCROP(pAdvOBInit->Sectors); -#else /* STM32F427xx || STM32F437xx || STM32F429xx|| STM32F439xx || STM32F469xx || STM32F479xx */ - status = FLASH_OB_EnablePCROP(pAdvOBInit->SectorsBank1, pAdvOBInit->SectorsBank2, pAdvOBInit->Banks); -#endif /* STM32F401xC || STM32F401xE || STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || - STM32F413xx || STM32F423xx */ - } - else - { - /*Disable of Write protection on the selected Sector*/ -#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ - defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||\ - defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) - status = FLASH_OB_DisablePCROP(pAdvOBInit->Sectors); -#else /* STM32F427xx || STM32F437xx || STM32F429xx|| STM32F439xx || STM32F469xx || STM32F479xx */ - status = FLASH_OB_DisablePCROP(pAdvOBInit->SectorsBank1, pAdvOBInit->SectorsBank2, pAdvOBInit->Banks); -#endif /* STM32F401xC || STM32F401xE || STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || - STM32F413xx || STM32F423xx */ - } - } - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) - /*Program BOOT config option byte*/ - if (((pAdvOBInit->OptionType) & OPTIONBYTE_BOOTCONFIG) == OPTIONBYTE_BOOTCONFIG) - { - status = FLASH_OB_BootConfig(pAdvOBInit->BootConfig); - } -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - - return status; -} - -/** - * @brief Get the OBEX byte configuration - * @param pAdvOBInit pointer to an FLASH_AdvOBProgramInitTypeDef structure that - * contains the configuration information for the programming. - * - * @retval None - */ -void HAL_FLASHEx_AdvOBGetConfig(FLASH_AdvOBProgramInitTypeDef *pAdvOBInit) -{ -#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ - defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||\ - defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) - /*Get Sector*/ - pAdvOBInit->Sectors = (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); -#else /* STM32F427xx || STM32F437xx || STM32F429xx|| STM32F439xx || STM32F469xx || STM32F479xx */ - /*Get Sector for Bank1*/ - pAdvOBInit->SectorsBank1 = (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); - - /*Get Sector for Bank2*/ - pAdvOBInit->SectorsBank2 = (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS)); - - /*Get Boot config OB*/ - pAdvOBInit->BootConfig = *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS; -#endif /* STM32F401xC || STM32F401xE || STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || - STM32F413xx || STM32F423xx */ -} - -/** - * @brief Select the Protection Mode - * - * @note After PCROP activated Option Byte modification NOT POSSIBLE! excepted - * Global Read Out Protection modification (from level1 to level0) - * @note Once SPRMOD bit is active unprotection of a protected sector is not possible - * @note Read a protected sector will set RDERR Flag and write a protected sector will set WRPERR Flag - * @note This function can be used only for STM32F42xxx/STM32F43xxx/STM32F401xx/STM32F411xx/STM32F446xx/ - * STM32F469xx/STM32F479xx/STM32F412xx/STM32F413xx devices. - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_OB_SelectPCROP(void) -{ - uint8_t optiontmp; - - /* Mask SPRMOD bit */ - optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE3_ADDRESS) & (uint8_t)0x7F); - - /* Update Option Byte */ - *(__IO uint8_t *)OPTCR_BYTE3_ADDRESS = (uint8_t)(OB_PCROP_SELECTED | optiontmp); - - return HAL_OK; -} - -/** - * @brief Deselect the Protection Mode - * - * @note After PCROP activated Option Byte modification NOT POSSIBLE! excepted - * Global Read Out Protection modification (from level1 to level0) - * @note Once SPRMOD bit is active unprotection of a protected sector is not possible - * @note Read a protected sector will set RDERR Flag and write a protected sector will set WRPERR Flag - * @note This function can be used only for STM32F42xxx/STM32F43xxx/STM32F401xx/STM32F411xx/STM32F446xx/ - * STM32F469xx/STM32F479xx/STM32F412xx/STM32F413xx devices. - * - * @retval HAL Status - */ -HAL_StatusTypeDef HAL_FLASHEx_OB_DeSelectPCROP(void) -{ - uint8_t optiontmp; - - /* Mask SPRMOD bit */ - optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE3_ADDRESS) & (uint8_t)0x7F); - - /* Update Option Byte */ - *(__IO uint8_t *)OPTCR_BYTE3_ADDRESS = (uint8_t)(OB_PCROP_DESELECTED | optiontmp); - - return HAL_OK; -} -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F401xC || STM32F401xE || STM32F410xx ||\ - STM32F411xE || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx || - STM32F413xx || STM32F423xx */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx)|| defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) -/** - * @brief Returns the FLASH Write Protection Option Bytes value for Bank 2 - * @note This function can be used only for STM32F42xxx/STM32F43xxx/STM32F469xx/STM32F479xx devices. - * @retval The FLASH Write Protection Option Bytes value - */ -uint16_t HAL_FLASHEx_OB_GetBank2WRP(void) -{ - /* Return the FLASH write protection Register value */ - return (*(__IO uint16_t *)(OPTCR1_BYTE2_ADDRESS)); -} -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -/** - * @} - */ - -#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || defined(STM32F469xx) || defined(STM32F479xx) -/** - * @brief Full erase of FLASH memory sectors - * @param VoltageRange The device voltage range which defines the erase parallelism. - * This parameter can be one of the following values: - * @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, - * the operation will be done by byte (8-bit) - * @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V, - * the operation will be done by half word (16-bit) - * @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V, - * the operation will be done by word (32-bit) - * @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, - * the operation will be done by double word (64-bit) - * - * @param Banks Banks to be erased - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: Bank1 to be erased - * @arg FLASH_BANK_2: Bank2 to be erased - * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased - * - * @retval HAL Status - */ -static void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks) -{ - /* Check the parameters */ - assert_param(IS_VOLTAGERANGE(VoltageRange)); - assert_param(IS_FLASH_BANK(Banks)); - - /* if the previous operation is completed, proceed to erase all sectors */ - CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); - - if (Banks == FLASH_BANK_BOTH) - { - /* bank1 & bank2 will be erased*/ - FLASH->CR |= FLASH_MER_BIT; - } - else if (Banks == FLASH_BANK_1) - { - /*Only bank1 will be erased*/ - FLASH->CR |= FLASH_CR_MER1; - } - else - { - /*Only bank2 will be erased*/ - FLASH->CR |= FLASH_CR_MER2; - } - FLASH->CR |= FLASH_CR_STRT | ((uint32_t)VoltageRange << 8U); -} - -/** - * @brief Erase the specified FLASH memory sector - * @param Sector FLASH sector to erase - * The value of this parameter depend on device used within the same series - * @param VoltageRange The device voltage range which defines the erase parallelism. - * This parameter can be one of the following values: - * @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, - * the operation will be done by byte (8-bit) - * @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V, - * the operation will be done by half word (16-bit) - * @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V, - * the operation will be done by word (32-bit) - * @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, - * the operation will be done by double word (64-bit) - * - * @retval None - */ -void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange) -{ - uint32_t tmp_psize = 0U; - - /* Check the parameters */ - assert_param(IS_FLASH_SECTOR(Sector)); - assert_param(IS_VOLTAGERANGE(VoltageRange)); - - if (VoltageRange == FLASH_VOLTAGE_RANGE_1) - { - tmp_psize = FLASH_PSIZE_BYTE; - } - else if (VoltageRange == FLASH_VOLTAGE_RANGE_2) - { - tmp_psize = FLASH_PSIZE_HALF_WORD; - } - else if (VoltageRange == FLASH_VOLTAGE_RANGE_3) - { - tmp_psize = FLASH_PSIZE_WORD; - } - else - { - tmp_psize = FLASH_PSIZE_DOUBLE_WORD; - } - - /* Need to add offset of 4 when sector higher than FLASH_SECTOR_11 */ - if (Sector > FLASH_SECTOR_11) - { - Sector += 4U; - } - /* If the previous operation is completed, proceed to erase the sector */ - CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); - FLASH->CR |= tmp_psize; - CLEAR_BIT(FLASH->CR, FLASH_CR_SNB); - FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos); - FLASH->CR |= FLASH_CR_STRT; -} - -/** - * @brief Enable the write protection of the desired bank1 or bank 2 sectors - * - * @note When the memory read protection level is selected (RDP level = 1), - * it is not possible to program or erase the flash sector i if CortexM4 - * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 - * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). - * - * @param WRPSector specifies the sector(s) to be write protected. - * This parameter can be one of the following values: - * @arg WRPSector: A value between OB_WRP_SECTOR_0 and OB_WRP_SECTOR_23 - * @arg OB_WRP_SECTOR_All - * @note BANK2 starts from OB_WRP_SECTOR_12 - * - * @param Banks Enable write protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: WRP on all sectors of bank1 - * @arg FLASH_BANK_2: WRP on all sectors of bank2 - * @arg FLASH_BANK_BOTH: WRP on all sectors of bank1 & bank2 - * - * @retval HAL FLASH State - */ -static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_WRP_SECTOR(WRPSector)); - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - if (((WRPSector == OB_WRP_SECTOR_All) && ((Banks == FLASH_BANK_1) || (Banks == FLASH_BANK_BOTH))) || - (WRPSector < OB_WRP_SECTOR_12)) - { - if (WRPSector == OB_WRP_SECTOR_All) - { - /*Write protection on all sector of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS &= (~(WRPSector >> 12)); - } - else - { - /*Write protection done on sectors of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS &= (~WRPSector); - } - } - else - { - /*Write protection done on sectors of BANK2*/ - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS &= (~(WRPSector >> 12)); - } - - /*Write protection on all sector of BANK2*/ - if ((WRPSector == OB_WRP_SECTOR_All) && (Banks == FLASH_BANK_BOTH)) - { - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS &= (~(WRPSector >> 12)); - } - } - - } - return status; -} - -/** - * @brief Disable the write protection of the desired bank1 or bank 2 sectors - * - * @note When the memory read protection level is selected (RDP level = 1), - * it is not possible to program or erase the flash sector i if CortexM4 - * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 - * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). - * - * @param WRPSector specifies the sector(s) to be write protected. - * This parameter can be one of the following values: - * @arg WRPSector: A value between OB_WRP_SECTOR_0 and OB_WRP_SECTOR_23 - * @arg OB_WRP_Sector_All - * @note BANK2 starts from OB_WRP_SECTOR_12 - * - * @param Banks Disable write protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: Bank1 to be erased - * @arg FLASH_BANK_2: Bank2 to be erased - * @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_WRP_SECTOR(WRPSector)); - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - if (((WRPSector == OB_WRP_SECTOR_All) && ((Banks == FLASH_BANK_1) || (Banks == FLASH_BANK_BOTH))) || - (WRPSector < OB_WRP_SECTOR_12)) - { - if (WRPSector == OB_WRP_SECTOR_All) - { - /*Write protection on all sector of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS |= (uint16_t)(WRPSector >> 12); - } - else - { - /*Write protection done on sectors of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS |= (uint16_t)WRPSector; - } - } - else - { - /*Write protection done on sectors of BANK2*/ - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS |= (uint16_t)(WRPSector >> 12); - } - - /*Write protection on all sector of BANK2*/ - if ((WRPSector == OB_WRP_SECTOR_All) && (Banks == FLASH_BANK_BOTH)) - { - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS |= (uint16_t)(WRPSector >> 12); - } - } - - } - - return status; -} - -/** - * @brief Configure the Dual Bank Boot. - * - * @note This function can be used only for STM32F42xxx/43xxx devices. - * - * @param BootConfig specifies the Dual Bank Boot Option byte. - * This parameter can be one of the following values: - * @arg OB_Dual_BootEnabled: Dual Bank Boot Enable - * @arg OB_Dual_BootDisabled: Dual Bank Boot Disabled - * @retval None - */ -static HAL_StatusTypeDef FLASH_OB_BootConfig(uint8_t BootConfig) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_BOOT(BootConfig)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - /* Set Dual Bank Boot */ - *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS &= (~FLASH_OPTCR_BFB2); - *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= BootConfig; - } - - return status; -} - -/** - * @brief Enable the read/write protection (PCROP) of the desired - * sectors of Bank 1 and/or Bank 2. - * @note This function can be used only for STM32F42xxx/43xxx devices. - * @param SectorBank1 Specifies the sector(s) to be read/write protected or unprotected for bank1. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_SECTOR_0 and OB_PCROP_SECTOR_11 - * @arg OB_PCROP_SECTOR__All - * @param SectorBank2 Specifies the sector(s) to be read/write protected or unprotected for bank2. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_SECTOR_12 and OB_PCROP_SECTOR_23 - * @arg OB_PCROP_SECTOR__All - * @param Banks Enable PCROP protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: WRP on all sectors of bank1 - * @arg FLASH_BANK_2: WRP on all sectors of bank2 - * @arg FLASH_BANK_BOTH: WRP on all sectors of bank1 & bank2 - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_EnablePCROP(uint32_t SectorBank1, uint32_t SectorBank2, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - if ((Banks == FLASH_BANK_1) || (Banks == FLASH_BANK_BOTH)) - { - assert_param(IS_OB_PCROP(SectorBank1)); - /*Write protection done on sectors of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS |= (uint16_t)SectorBank1; - } - else - { - assert_param(IS_OB_PCROP(SectorBank2)); - /*Write protection done on sectors of BANK2*/ - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS |= (uint16_t)SectorBank2; - } - - /*Write protection on all sector of BANK2*/ - if (Banks == FLASH_BANK_BOTH) - { - assert_param(IS_OB_PCROP(SectorBank2)); - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - /*Write protection done on sectors of BANK2*/ - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS |= (uint16_t)SectorBank2; - } - } - - } - - return status; -} - - -/** - * @brief Disable the read/write protection (PCROP) of the desired - * sectors of Bank 1 and/or Bank 2. - * @note This function can be used only for STM32F42xxx/43xxx devices. - * @param SectorBank1 specifies the sector(s) to be read/write protected or unprotected for bank1. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_SECTOR_0 and OB_PCROP_SECTOR_11 - * @arg OB_PCROP_SECTOR__All - * @param SectorBank2 Specifies the sector(s) to be read/write protected or unprotected for bank2. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_SECTOR_12 and OB_PCROP_SECTOR_23 - * @arg OB_PCROP_SECTOR__All - * @param Banks Disable PCROP protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: WRP on all sectors of bank1 - * @arg FLASH_BANK_2: WRP on all sectors of bank2 - * @arg FLASH_BANK_BOTH: WRP on all sectors of bank1 & bank2 - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_DisablePCROP(uint32_t SectorBank1, uint32_t SectorBank2, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - if ((Banks == FLASH_BANK_1) || (Banks == FLASH_BANK_BOTH)) - { - assert_param(IS_OB_PCROP(SectorBank1)); - /*Write protection done on sectors of BANK1*/ - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS &= (~SectorBank1); - } - else - { - /*Write protection done on sectors of BANK2*/ - assert_param(IS_OB_PCROP(SectorBank2)); - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS &= (~SectorBank2); - } - - /*Write protection on all sector of BANK2*/ - if (Banks == FLASH_BANK_BOTH) - { - assert_param(IS_OB_PCROP(SectorBank2)); - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - /*Write protection done on sectors of BANK2*/ - *(__IO uint16_t *)OPTCR1_BYTE2_ADDRESS &= (~SectorBank2); - } - } - - } - - return status; - -} - -#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */ - -#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) ||\ - defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) ||\ - defined(STM32F410Rx) || defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) ||\ - defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) ||\ - defined(STM32F423xx) -/** - * @brief Mass erase of FLASH memory - * @param VoltageRange The device voltage range which defines the erase parallelism. - * This parameter can be one of the following values: - * @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, - * the operation will be done by byte (8-bit) - * @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V, - * the operation will be done by half word (16-bit) - * @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V, - * the operation will be done by word (32-bit) - * @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, - * the operation will be done by double word (64-bit) - * - * @param Banks Banks to be erased - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: Bank1 to be erased - * - * @retval None - */ -static void FLASH_MassErase(uint8_t VoltageRange, uint32_t Banks) -{ - /* Check the parameters */ - assert_param(IS_VOLTAGERANGE(VoltageRange)); - assert_param(IS_FLASH_BANK(Banks)); - - /* If the previous operation is completed, proceed to erase all sectors */ - CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); - FLASH->CR |= FLASH_CR_MER; - FLASH->CR |= FLASH_CR_STRT | ((uint32_t)VoltageRange << 8U); -} - -/** - * @brief Erase the specified FLASH memory sector - * @param Sector FLASH sector to erase - * The value of this parameter depend on device used within the same series - * @param VoltageRange The device voltage range which defines the erase parallelism. - * This parameter can be one of the following values: - * @arg FLASH_VOLTAGE_RANGE_1: when the device voltage range is 1.8V to 2.1V, - * the operation will be done by byte (8-bit) - * @arg FLASH_VOLTAGE_RANGE_2: when the device voltage range is 2.1V to 2.7V, - * the operation will be done by half word (16-bit) - * @arg FLASH_VOLTAGE_RANGE_3: when the device voltage range is 2.7V to 3.6V, - * the operation will be done by word (32-bit) - * @arg FLASH_VOLTAGE_RANGE_4: when the device voltage range is 2.7V to 3.6V + External Vpp, - * the operation will be done by double word (64-bit) - * - * @retval None - */ -void FLASH_Erase_Sector(uint32_t Sector, uint8_t VoltageRange) -{ - uint32_t tmp_psize = 0U; - - /* Check the parameters */ - assert_param(IS_FLASH_SECTOR(Sector)); - assert_param(IS_VOLTAGERANGE(VoltageRange)); - - if (VoltageRange == FLASH_VOLTAGE_RANGE_1) - { - tmp_psize = FLASH_PSIZE_BYTE; - } - else if (VoltageRange == FLASH_VOLTAGE_RANGE_2) - { - tmp_psize = FLASH_PSIZE_HALF_WORD; - } - else if (VoltageRange == FLASH_VOLTAGE_RANGE_3) - { - tmp_psize = FLASH_PSIZE_WORD; - } - else - { - tmp_psize = FLASH_PSIZE_DOUBLE_WORD; - } - - /* If the previous operation is completed, proceed to erase the sector */ - CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE); - FLASH->CR |= tmp_psize; - CLEAR_BIT(FLASH->CR, FLASH_CR_SNB); - FLASH->CR |= FLASH_CR_SER | (Sector << FLASH_CR_SNB_Pos); - FLASH->CR |= FLASH_CR_STRT; -} - -/** - * @brief Enable the write protection of the desired bank 1 sectors - * - * @note When the memory read protection level is selected (RDP level = 1), - * it is not possible to program or erase the flash sector i if CortexM4 - * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 - * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). - * - * @param WRPSector specifies the sector(s) to be write protected. - * The value of this parameter depend on device used within the same series - * - * @param Banks Enable write protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: WRP on all sectors of bank1 - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WRPSector, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_WRP_SECTOR(WRPSector)); - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS &= (~WRPSector); - } - - return status; -} - -/** - * @brief Disable the write protection of the desired bank 1 sectors - * - * @note When the memory read protection level is selected (RDP level = 1), - * it is not possible to program or erase the flash sector i if CortexM4 - * debug features are connected or boot code is executed in RAM, even if nWRPi = 1 - * @note Active value of nWRPi bits is inverted when PCROP mode is active (SPRMOD =1). - * - * @param WRPSector specifies the sector(s) to be write protected. - * The value of this parameter depend on device used within the same series - * - * @param Banks Enable write protection on all the sectors for the specific bank - * This parameter can be one of the following values: - * @arg FLASH_BANK_1: WRP on all sectors of bank1 - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WRPSector, uint32_t Banks) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_WRP_SECTOR(WRPSector)); - assert_param(IS_FLASH_BANK(Banks)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS |= (uint16_t)WRPSector; - } - - return status; -} -#endif /* STM32F40xxx || STM32F41xxx || STM32F401xx || STM32F410xx || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx - STM32F413xx || STM32F423xx */ - -#if defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F410Tx) || defined(STM32F410Cx) || defined(STM32F410Rx) ||\ - defined(STM32F411xE) || defined(STM32F446xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) ||\ - defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) -/** - * @brief Enable the read/write protection (PCROP) of the desired sectors. - * @note This function can be used only for STM32F401xx devices. - * @param Sector specifies the sector(s) to be read/write protected or unprotected. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_Sector0 and OB_PCROP_Sector5 - * @arg OB_PCROP_Sector_All - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_EnablePCROP(uint32_t Sector) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_PCROP(Sector)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS |= (uint16_t)Sector; - } - - return status; -} - - -/** - * @brief Disable the read/write protection (PCROP) of the desired sectors. - * @note This function can be used only for STM32F401xx devices. - * @param Sector specifies the sector(s) to be read/write protected or unprotected. - * This parameter can be one of the following values: - * @arg OB_PCROP: A value between OB_PCROP_Sector0 and OB_PCROP_Sector5 - * @arg OB_PCROP_Sector_All - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_DisablePCROP(uint32_t Sector) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_PCROP(Sector)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint16_t *)OPTCR_BYTE2_ADDRESS &= (~Sector); - } - - return status; - -} -#endif /* STM32F401xC || STM32F401xE || STM32F411xE || STM32F446xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx - STM32F413xx || STM32F423xx */ - -/** - * @brief Set the read protection level. - * @param Level specifies the read protection level. - * This parameter can be one of the following values: - * @arg OB_RDP_LEVEL_0: No protection - * @arg OB_RDP_LEVEL_1: Read protection of the memory - * @arg OB_RDP_LEVEL_2: Full chip protection - * - * @note WARNING: When enabling OB_RDP level 2 it's no more possible to go back to level 1 or 0 - * - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t Level) -{ - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_RDP_LEVEL(Level)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - *(__IO uint8_t *)OPTCR_BYTE1_ADDRESS = Level; - } - - return status; -} - -/** - * @brief Program the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY. - * @param Iwdg Selects the IWDG mode - * This parameter can be one of the following values: - * @arg OB_IWDG_SW: Software IWDG selected - * @arg OB_IWDG_HW: Hardware IWDG selected - * @param Stop Reset event when entering STOP mode. - * This parameter can be one of the following values: - * @arg OB_STOP_NO_RST: No reset generated when entering in STOP - * @arg OB_STOP_RST: Reset generated when entering in STOP - * @param Stdby Reset event when entering Standby mode. - * This parameter can be one of the following values: - * @arg OB_STDBY_NO_RST: No reset generated when entering in STANDBY - * @arg OB_STDBY_RST: Reset generated when entering in STANDBY - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t Iwdg, uint8_t Stop, uint8_t Stdby) -{ - uint8_t optiontmp; - HAL_StatusTypeDef status = HAL_OK; - - /* Check the parameters */ - assert_param(IS_OB_IWDG_SOURCE(Iwdg)); - assert_param(IS_OB_STOP_SOURCE(Stop)); - assert_param(IS_OB_STDBY_SOURCE(Stdby)); - - /* Wait for last operation to be completed */ - status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE); - - if (status == HAL_OK) - { - /* Mask OPTLOCK, OPTSTRT, BOR_LEV and BFB2 bits */ - optiontmp = (uint8_t)((*(__IO uint8_t *)OPTCR_BYTE0_ADDRESS) & (uint8_t)0x1F); - - /* Update User Option Byte */ - *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS = Iwdg | (uint8_t)(Stdby | (uint8_t)(Stop | ((uint8_t)optiontmp))); - } - - return status; -} - -/** - * @brief Set the BOR Level. - * @param Level specifies the Option Bytes BOR Reset Level. - * This parameter can be one of the following values: - * @arg OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V - * @arg OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V - * @arg OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V - * @arg OB_BOR_OFF: Supply voltage ranges from 1.62 to 2.1 V - * @retval HAL Status - */ -static HAL_StatusTypeDef FLASH_OB_BOR_LevelConfig(uint8_t Level) -{ - /* Check the parameters */ - assert_param(IS_OB_BOR_LEVEL(Level)); - - /* Set the BOR Level */ - *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS &= (~FLASH_OPTCR_BOR_LEV); - *(__IO uint8_t *)OPTCR_BYTE0_ADDRESS |= Level; - - return HAL_OK; - -} - -/** - * @brief Return the FLASH User Option Byte value. - * @retval uint8_t FLASH User Option Bytes values: IWDG_SW(Bit0), RST_STOP(Bit1) - * and RST_STDBY(Bit2). - */ -static uint8_t FLASH_OB_GetUser(void) -{ - /* Return the User Option Byte */ - return ((uint8_t)(FLASH->OPTCR & 0xE0)); -} - -/** - * @brief Return the FLASH Write Protection Option Bytes value. - * @retval uint16_t FLASH Write Protection Option Bytes value - */ -static uint16_t FLASH_OB_GetWRP(void) -{ - /* Return the FLASH write protection Register value */ - return (*(__IO uint16_t *)(OPTCR_BYTE2_ADDRESS)); -} - -/** - * @brief Returns the FLASH Read Protection level. - * @retval FLASH ReadOut Protection Status: - * This parameter can be one of the following values: - * @arg OB_RDP_LEVEL_0: No protection - * @arg OB_RDP_LEVEL_1: Read protection of the memory - * @arg OB_RDP_LEVEL_2: Full chip protection - */ -static uint8_t FLASH_OB_GetRDP(void) -{ - uint8_t readstatus = OB_RDP_LEVEL_0; - - if (*(__IO uint8_t *)(OPTCR_BYTE1_ADDRESS) == (uint8_t)OB_RDP_LEVEL_2) - { - readstatus = OB_RDP_LEVEL_2; - } - else if (*(__IO uint8_t *)(OPTCR_BYTE1_ADDRESS) == (uint8_t)OB_RDP_LEVEL_0) - { - readstatus = OB_RDP_LEVEL_0; - } - else - { - readstatus = OB_RDP_LEVEL_1; - } - - return readstatus; -} - -/** - * @brief Returns the FLASH BOR level. - * @retval uint8_t The FLASH BOR level: - * - OB_BOR_LEVEL3: Supply voltage ranges from 2.7 to 3.6 V - * - OB_BOR_LEVEL2: Supply voltage ranges from 2.4 to 2.7 V - * - OB_BOR_LEVEL1: Supply voltage ranges from 2.1 to 2.4 V - * - OB_BOR_OFF : Supply voltage ranges from 1.62 to 2.1 V - */ -static uint8_t FLASH_OB_GetBOR(void) -{ - /* Return the FLASH BOR level */ - return (uint8_t)(*(__IO uint8_t *)(OPTCR_BYTE0_ADDRESS) & (uint8_t)0x0C); -} - -/** - * @brief Flush the instruction and data caches - * @retval None - */ -void FLASH_FlushCaches(void) -{ - /* Flush instruction cache */ - if (READ_BIT(FLASH->ACR, FLASH_ACR_ICEN) != RESET) - { - /* Disable instruction cache */ - __HAL_FLASH_INSTRUCTION_CACHE_DISABLE(); - /* Reset instruction cache */ - __HAL_FLASH_INSTRUCTION_CACHE_RESET(); - /* Enable instruction cache */ - __HAL_FLASH_INSTRUCTION_CACHE_ENABLE(); - } - - /* Flush data cache */ - if (READ_BIT(FLASH->ACR, FLASH_ACR_DCEN) != RESET) - { - /* Disable data cache */ - __HAL_FLASH_DATA_CACHE_DISABLE(); - /* Reset data cache */ - __HAL_FLASH_DATA_CACHE_RESET(); - /* Enable data cache */ - __HAL_FLASH_DATA_CACHE_ENABLE(); - } -} - -/** - * @} - */ - -#endif /* HAL_FLASH_MODULE_ENABLED */ - -/** - * @} - */ - -/** - * @} - */ - diff --git a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd 2.c b/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd 2.c deleted file mode 100644 index 8e27a52..0000000 --- a/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_sd 2.c +++ /dev/null @@ -1,3288 +0,0 @@ -/** - ****************************************************************************** - * @file stm32f4xx_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 "stm32f4xx_hal.h" - -#if defined(SDIO) - -/** @addtogroup STM32F4xx_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; -#if defined(SDIO_STA_STBITERR) - while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) -#else /* SDIO_STA_STBITERR not defined */ - while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) -#endif /* SDIO_STA_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 defined(SDIO_STA_STBITERR) - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR))) -#else /* SDIO_STA_STBITERR not defined */ - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) -#endif /* SDIO_STA_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; -#if defined(SDIO_STA_STBITERR) - while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR)) -#else /* SDIO_STA_STBITERR not defined */ - while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND)) -#endif /* SDIO_STA_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 defined(SDIO_STA_STBITERR) - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR))) -#else /* SDIO_STA_STBITERR not defined */ - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) -#endif /* SDIO_STA_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; - -#if defined(SDIO_STA_STBITERR) - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF | SDIO_IT_STBITERR)); -#else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF)); -#endif /* SDIO_STA_STBITERR */ - - 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 */ -#if defined(SDIO_STA_STBITERR) - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE | SDIO_IT_STBITERR)); -#else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE)); -#endif /* SDIO_STA_STBITERR */ - - 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; - -#if defined(SDIO_STA_STBITERR) - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR)); -#else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND)); -#endif /* SDIO_STA_STBITERR */ - - /* 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->CR, DMA_SxCR_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 */ -#if defined(SDIO_STA_STBITERR) - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); -#else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); -#endif /* SDIO_STA_STBITERR */ - - /* 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->CR, DMA_SxCR_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) - { -#if defined(SDIO_STA_STBITERR) - __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR)); -#else /* SDIO_STA_STBITERR not defined */ - __HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR)); -#endif /* SDIO_STA_STBITERR */ - __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); - -#if defined(SDIO_STA_STBITERR) - __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 | SDIO_IT_STBITERR); -#else /* SDIO_STA_STBITERR not defined */ - __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); -#endif /* SDIO_STA_STBITERR */ - - 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); - } - -#if defined(SDIO_STA_STBITERR) - else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR | SDIO_FLAG_STBITERR) != RESET) -#else /* SDIO_STA_STBITERR not defined */ - else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET) -#endif /* SDIO_STA_STBITERR */ - { - /* 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; - } -#if defined(SDIO_STA_STBITERR) - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR) != RESET) - { - hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT; - } -#endif /* SDIO_STA_STBITERR */ - -#if defined(SDIO_STA_STBITERR) - /* 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); -#else /* SDIO_STA_STBITERR not defined */ - /* Clear All flags */ - __HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS); - - /* Disable all interrupts */ - __HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\ - SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR); -#endif /* SDIO_STA_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; - - /* if DMA error is FIFO error ignore it */ - if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE) - { - 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 defined(SDIO_STA_STBITERR) - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR))) -#else /* SDIO_STA_STBITERR not defined */ - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) -#endif /* SDIO_STA_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 defined(SDIO_STA_STBITERR) - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR))) -#else /* SDIO_STA_STBITERR not defined */ - if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT)) -#endif /* SDIO_STA_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 */ diff --git a/Middlewares/Third_Party/FreeRTOS/Source/queue 2.c b/Middlewares/Third_Party/FreeRTOS/Source/queue 2.c deleted file mode 100644 index e35055f..0000000 --- a/Middlewares/Third_Party/FreeRTOS/Source/queue 2.c +++ /dev/null @@ -1,2945 +0,0 @@ -/* - * FreeRTOS Kernel V10.3.1 - * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER - * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - -#include -#include - -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining -all the API functions to use the MPU wrappers. That should only be done when -task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#include "FreeRTOS.h" -#include "task.h" -#include "queue.h" - -#if ( configUSE_CO_ROUTINES == 1 ) - #include "croutine.h" -#endif - -/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified -because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined -for the header files above, but not in this file, in order to generate the -correct privileged Vs unprivileged linkage and placement. */ -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750 !e9021. */ - - -/* Constants used with the cRxLock and cTxLock structure members. */ -#define queueUNLOCKED ( ( int8_t ) -1 ) -#define queueLOCKED_UNMODIFIED ( ( int8_t ) 0 ) - -/* When the Queue_t structure is used to represent a base queue its pcHead and -pcTail members are used as pointers into the queue storage area. When the -Queue_t structure is used to represent a mutex pcHead and pcTail pointers are -not necessary, and the pcHead pointer is set to NULL to indicate that the -structure instead holds a pointer to the mutex holder (if any). Map alternative -names to the pcHead and structure member to ensure the readability of the code -is maintained. The QueuePointers_t and SemaphoreData_t types are used to form -a union as their usage is mutually exclusive dependent on what the queue is -being used for. */ -#define uxQueueType pcHead -#define queueQUEUE_IS_MUTEX NULL - -typedef struct QueuePointers -{ - int8_t *pcTail; /*< Points to the byte at the end of the queue storage area. Once more byte is allocated than necessary to store the queue items, this is used as a marker. */ - int8_t *pcReadFrom; /*< Points to the last place that a queued item was read from when the structure is used as a queue. */ -} QueuePointers_t; - -typedef struct SemaphoreData -{ - TaskHandle_t xMutexHolder; /*< The handle of the task that holds the mutex. */ - UBaseType_t uxRecursiveCallCount;/*< Maintains a count of the number of times a recursive mutex has been recursively 'taken' when the structure is used as a mutex. */ -} SemaphoreData_t; - -/* Semaphores do not actually store or copy data, so have an item size of -zero. */ -#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) -#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) - -#if( configUSE_PREEMPTION == 0 ) - /* If the cooperative scheduler is being used then a yield should not be - performed just because a higher priority task has been woken. */ - #define queueYIELD_IF_USING_PREEMPTION() -#else - #define queueYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API() -#endif - -/* - * Definition of the queue used by the scheduler. - * Items are queued by copy, not reference. See the following link for the - * rationale: https://www.freertos.org/Embedded-RTOS-Queues.html - */ -typedef struct QueueDefinition /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -{ - int8_t *pcHead; /*< Points to the beginning of the queue storage area. */ - int8_t *pcWriteTo; /*< Points to the free next place in the storage area. */ - - union - { - QueuePointers_t xQueue; /*< Data required exclusively when this structure is used as a queue. */ - SemaphoreData_t xSemaphore; /*< Data required exclusively when this structure is used as a semaphore. */ - } u; - - List_t xTasksWaitingToSend; /*< List of tasks that are blocked waiting to post onto this queue. Stored in priority order. */ - List_t xTasksWaitingToReceive; /*< List of tasks that are blocked waiting to read from this queue. Stored in priority order. */ - - volatile UBaseType_t uxMessagesWaiting;/*< The number of items currently in the queue. */ - UBaseType_t uxLength; /*< The length of the queue defined as the number of items it will hold, not the number of bytes. */ - UBaseType_t uxItemSize; /*< The size of each items that the queue will hold. */ - - volatile int8_t cRxLock; /*< Stores the number of items received from the queue (removed from the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - volatile int8_t cTxLock; /*< Stores the number of items transmitted to the queue (added to the queue) while the queue was locked. Set to queueUNLOCKED when the queue is not locked. */ - - #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the memory used by the queue was statically allocated to ensure no attempt is made to free the memory. */ - #endif - - #if ( configUSE_QUEUE_SETS == 1 ) - struct QueueDefinition *pxQueueSetContainer; - #endif - - #if ( configUSE_TRACE_FACILITY == 1 ) - UBaseType_t uxQueueNumber; - uint8_t ucQueueType; - #endif - -} xQUEUE; - -/* The old xQUEUE name is maintained above then typedefed to the new Queue_t -name below to enable the use of older kernel aware debuggers. */ -typedef xQUEUE Queue_t; - -/*-----------------------------------------------------------*/ - -/* - * The queue registry is just a means for kernel aware debuggers to locate - * queue structures. It has no other purpose so is an optional component. - */ -#if ( configQUEUE_REGISTRY_SIZE > 0 ) - - /* The type stored within the queue registry array. This allows a name - to be assigned to each queue making kernel aware debugging a little - more user friendly. */ - typedef struct QUEUE_REGISTRY_ITEM - { - const char *pcQueueName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - QueueHandle_t xHandle; - } xQueueRegistryItem; - - /* The old xQueueRegistryItem name is maintained above then typedefed to the - new xQueueRegistryItem name below to enable the use of older kernel aware - debuggers. */ - typedef xQueueRegistryItem QueueRegistryItem_t; - - /* The queue registry is simply an array of QueueRegistryItem_t structures. - The pcQueueName member of a structure being NULL is indicative of the - array position being vacant. */ - PRIVILEGED_DATA QueueRegistryItem_t xQueueRegistry[ configQUEUE_REGISTRY_SIZE ]; - -#endif /* configQUEUE_REGISTRY_SIZE */ - -/* - * Unlocks a queue locked by a call to prvLockQueue. Locking a queue does not - * prevent an ISR from adding or removing items to the queue, but does prevent - * an ISR from removing tasks from the queue event lists. If an ISR finds a - * queue is locked it will instead increment the appropriate queue lock count - * to indicate that a task may require unblocking. When the queue in unlocked - * these lock counts are inspected, and the appropriate action taken. - */ -static void prvUnlockQueue( Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Uses a critical section to determine if there is any data in a queue. - * - * @return pdTRUE if the queue contains no items, otherwise pdFALSE. - */ -static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Uses a critical section to determine if there is any space in a queue. - * - * @return pdTRUE if there is no space, otherwise pdFALSE; - */ -static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) PRIVILEGED_FUNCTION; - -/* - * Copies an item into the queue, either at the front of the queue or the - * back of the queue. - */ -static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) PRIVILEGED_FUNCTION; - -/* - * Copies an item out of a queue. - */ -static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) PRIVILEGED_FUNCTION; - -#if ( configUSE_QUEUE_SETS == 1 ) - /* - * Checks to see if a queue is a member of a queue set, and if so, notifies - * the queue set that the queue contains data. - */ - static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; -#endif - -/* - * Called after a Queue_t structure has been allocated either statically or - * dynamically to fill in the structure's members. - */ -static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; - -/* - * Mutexes are a special type of queue. When a mutex is created, first the - * queue is created, then prvInitialiseMutex() is called to configure the queue - * as a mutex. - */ -#if( configUSE_MUTEXES == 1 ) - static void prvInitialiseMutex( Queue_t *pxNewQueue ) PRIVILEGED_FUNCTION; -#endif - -#if( configUSE_MUTEXES == 1 ) - /* - * If a task waiting for a mutex causes the mutex holder to inherit a - * priority, but the waiting task times out, then the holder should - * disinherit the priority - but only down to the highest priority of any - * other tasks that are waiting for the same mutex. This function returns - * that priority. - */ - static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) PRIVILEGED_FUNCTION; -#endif -/*-----------------------------------------------------------*/ - -/* - * Macro to mark a queue as locked. Locking a queue prevents an ISR from - * accessing the queue event lists. - */ -#define prvLockQueue( pxQueue ) \ - taskENTER_CRITICAL(); \ - { \ - if( ( pxQueue )->cRxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->cRxLock = queueLOCKED_UNMODIFIED; \ - } \ - if( ( pxQueue )->cTxLock == queueUNLOCKED ) \ - { \ - ( pxQueue )->cTxLock = queueLOCKED_UNMODIFIED; \ - } \ - } \ - taskEXIT_CRITICAL() -/*-----------------------------------------------------------*/ - -BaseType_t xQueueGenericReset( QueueHandle_t xQueue, BaseType_t xNewQueue ) -{ -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - - taskENTER_CRITICAL(); - { - pxQueue->u.xQueue.pcTail = pxQueue->pcHead + ( pxQueue->uxLength * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->uxMessagesWaiting = ( UBaseType_t ) 0U; - pxQueue->pcWriteTo = pxQueue->pcHead; - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead + ( ( pxQueue->uxLength - 1U ) * pxQueue->uxItemSize ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - pxQueue->cRxLock = queueUNLOCKED; - pxQueue->cTxLock = queueUNLOCKED; - - if( xNewQueue == pdFALSE ) - { - /* If there are tasks blocked waiting to read from the queue, then - the tasks will remain blocked as after this function exits the queue - will still be empty. If there are tasks blocked waiting to write to - the queue, then one should be unblocked as after this function exits - it will be possible to write to it. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Ensure the event queues start in the correct state. */ - vListInitialise( &( pxQueue->xTasksWaitingToSend ) ); - vListInitialise( &( pxQueue->xTasksWaitingToReceive ) ); - } - } - taskEXIT_CRITICAL(); - - /* A value is returned for calling semantic consistency with previous - versions. */ - return pdPASS; -} -/*-----------------------------------------------------------*/ - -#if( configSUPPORT_STATIC_ALLOCATION == 1 ) - - QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType ) - { - Queue_t *pxNewQueue; - - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); - - /* The StaticQueue_t structure and the queue storage area must be - supplied. */ - configASSERT( pxStaticQueue != NULL ); - - /* A queue storage area should be provided if the item size is not 0, and - should not be provided if the item size is 0. */ - configASSERT( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ); - configASSERT( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ); - - #if( configASSERT_DEFINED == 1 ) - { - /* Sanity check that the size of the structure used to declare a - variable of type StaticQueue_t or StaticSemaphore_t equals the size of - the real queue and semaphore structures. */ - volatile size_t xSize = sizeof( StaticQueue_t ); - configASSERT( xSize == sizeof( Queue_t ) ); - ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ - } - #endif /* configASSERT_DEFINED */ - - /* The address of a statically allocated queue was passed in, use it. - The address of a statically allocated storage area was also passed in - but is already set. */ - pxNewQueue = ( Queue_t * ) pxStaticQueue; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */ - - if( pxNewQueue != NULL ) - { - #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - { - /* Queues can be allocated wither statically or dynamically, so - note this queue was allocated statically in case the queue is - later deleted. */ - pxNewQueue->ucStaticallyAllocated = pdTRUE; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ - - prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); - } - else - { - traceQUEUE_CREATE_FAILED( ucQueueType ); - mtCOVERAGE_TEST_MARKER(); - } - - return pxNewQueue; - } - -#endif /* configSUPPORT_STATIC_ALLOCATION */ -/*-----------------------------------------------------------*/ - -#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) - - QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType ) - { - Queue_t *pxNewQueue; - size_t xQueueSizeInBytes; - uint8_t *pucQueueStorage; - - configASSERT( uxQueueLength > ( UBaseType_t ) 0 ); - - /* Allocate enough space to hold the maximum number of items that - can be in the queue at any time. It is valid for uxItemSize to be - zero in the case the queue is used as a semaphore. */ - xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ - - /* Allocate the queue and storage area. Justification for MISRA - deviation as follows: pvPortMalloc() always ensures returned memory - blocks are aligned per the requirements of the MCU stack. In this case - pvPortMalloc() must return a pointer that is guaranteed to meet the - alignment requirements of the Queue_t structure - which in this case - is an int8_t *. Therefore, whenever the stack alignment requirements - are greater than or equal to the pointer to char requirements the cast - is safe. In other cases alignment requirements are not strict (one or - two bytes). */ - pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes ); /*lint !e9087 !e9079 see comment above. */ - - if( pxNewQueue != NULL ) - { - /* Jump past the queue structure to find the location of the queue - storage area. */ - pucQueueStorage = ( uint8_t * ) pxNewQueue; - pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */ - - #if( configSUPPORT_STATIC_ALLOCATION == 1 ) - { - /* Queues can be created either statically or dynamically, so - note this task was created dynamically in case it is later - deleted. */ - pxNewQueue->ucStaticallyAllocated = pdFALSE; - } - #endif /* configSUPPORT_STATIC_ALLOCATION */ - - prvInitialiseNewQueue( uxQueueLength, uxItemSize, pucQueueStorage, ucQueueType, pxNewQueue ); - } - else - { - traceQUEUE_CREATE_FAILED( ucQueueType ); - mtCOVERAGE_TEST_MARKER(); - } - - return pxNewQueue; - } - -#endif /* configSUPPORT_STATIC_ALLOCATION */ -/*-----------------------------------------------------------*/ - -static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, const uint8_t ucQueueType, Queue_t *pxNewQueue ) -{ - /* Remove compiler warnings about unused parameters should - configUSE_TRACE_FACILITY not be set to 1. */ - ( void ) ucQueueType; - - if( uxItemSize == ( UBaseType_t ) 0 ) - { - /* No RAM was allocated for the queue storage area, but PC head cannot - be set to NULL because NULL is used as a key to say the queue is used as - a mutex. Therefore just set pcHead to point to the queue as a benign - value that is known to be within the memory map. */ - pxNewQueue->pcHead = ( int8_t * ) pxNewQueue; - } - else - { - /* Set the head to the start of the queue storage area. */ - pxNewQueue->pcHead = ( int8_t * ) pucQueueStorage; - } - - /* Initialise the queue members as described where the queue type is - defined. */ - pxNewQueue->uxLength = uxQueueLength; - pxNewQueue->uxItemSize = uxItemSize; - ( void ) xQueueGenericReset( pxNewQueue, pdTRUE ); - - #if ( configUSE_TRACE_FACILITY == 1 ) - { - pxNewQueue->ucQueueType = ucQueueType; - } - #endif /* configUSE_TRACE_FACILITY */ - - #if( configUSE_QUEUE_SETS == 1 ) - { - pxNewQueue->pxQueueSetContainer = NULL; - } - #endif /* configUSE_QUEUE_SETS */ - - traceQUEUE_CREATE( pxNewQueue ); -} -/*-----------------------------------------------------------*/ - -#if( configUSE_MUTEXES == 1 ) - - static void prvInitialiseMutex( Queue_t *pxNewQueue ) - { - if( pxNewQueue != NULL ) - { - /* The queue create function will set all the queue structure members - correctly for a generic queue, but this function is creating a - mutex. Overwrite those members that need to be set differently - - in particular the information required for priority inheritance. */ - pxNewQueue->u.xSemaphore.xMutexHolder = NULL; - pxNewQueue->uxQueueType = queueQUEUE_IS_MUTEX; - - /* In case this is a recursive mutex. */ - pxNewQueue->u.xSemaphore.uxRecursiveCallCount = 0; - - traceCREATE_MUTEX( pxNewQueue ); - - /* Start with the semaphore in the expected state. */ - ( void ) xQueueGenericSend( pxNewQueue, NULL, ( TickType_t ) 0U, queueSEND_TO_BACK ); - } - else - { - traceCREATE_MUTEX_FAILED(); - } - } - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - - QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) - { - QueueHandle_t xNewQueue; - const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; - - xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); - prvInitialiseMutex( ( Queue_t * ) xNewQueue ); - - return xNewQueue; - } - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - - QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue ) - { - QueueHandle_t xNewQueue; - const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; - - /* Prevent compiler warnings about unused parameters if - configUSE_TRACE_FACILITY does not equal 1. */ - ( void ) ucQueueType; - - xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); - prvInitialiseMutex( ( Queue_t * ) xNewQueue ); - - return xNewQueue; - } - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) - - TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) - { - TaskHandle_t pxReturn; - Queue_t * const pxSemaphore = ( Queue_t * ) xSemaphore; - - /* This function is called by xSemaphoreGetMutexHolder(), and should not - be called directly. Note: This is a good way of determining if the - calling task is the mutex holder, but not a good way of determining the - identity of the mutex holder, as the holder may change between the - following critical section exiting and the function returning. */ - taskENTER_CRITICAL(); - { - if( pxSemaphore->uxQueueType == queueQUEUE_IS_MUTEX ) - { - pxReturn = pxSemaphore->u.xSemaphore.xMutexHolder; - } - else - { - pxReturn = NULL; - } - } - taskEXIT_CRITICAL(); - - return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ - -#endif -/*-----------------------------------------------------------*/ - -#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) - - TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) - { - TaskHandle_t pxReturn; - - configASSERT( xSemaphore ); - - /* Mutexes cannot be used in interrupt service routines, so the mutex - holder should not change in an ISR, and therefore a critical section is - not required here. */ - if( ( ( Queue_t * ) xSemaphore )->uxQueueType == queueQUEUE_IS_MUTEX ) - { - pxReturn = ( ( Queue_t * ) xSemaphore )->u.xSemaphore.xMutexHolder; - } - else - { - pxReturn = NULL; - } - - return pxReturn; - } /*lint !e818 xSemaphore cannot be a pointer to const because it is a typedef. */ - -#endif -/*-----------------------------------------------------------*/ - -#if ( configUSE_RECURSIVE_MUTEXES == 1 ) - - BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) - { - BaseType_t xReturn; - Queue_t * const pxMutex = ( Queue_t * ) xMutex; - - configASSERT( pxMutex ); - - /* If this is the task that holds the mutex then xMutexHolder will not - change outside of this task. If this task does not hold the mutex then - pxMutexHolder can never coincidentally equal the tasks handle, and as - this is the only condition we are interested in it does not matter if - pxMutexHolder is accessed simultaneously by another task. Therefore no - mutual exclusion is required to test the pxMutexHolder variable. */ - if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) - { - traceGIVE_MUTEX_RECURSIVE( pxMutex ); - - /* uxRecursiveCallCount cannot be zero if xMutexHolder is equal to - the task handle, therefore no underflow check is required. Also, - uxRecursiveCallCount is only modified by the mutex holder, and as - there can only be one, no mutual exclusion is required to modify the - uxRecursiveCallCount member. */ - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )--; - - /* Has the recursive call count unwound to 0? */ - if( pxMutex->u.xSemaphore.uxRecursiveCallCount == ( UBaseType_t ) 0 ) - { - /* Return the mutex. This will automatically unblock any other - task that might be waiting to access the mutex. */ - ( void ) xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - xReturn = pdPASS; - } - else - { - /* The mutex cannot be given because the calling task is not the - holder. */ - xReturn = pdFAIL; - - traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } - - return xReturn; - } - -#endif /* configUSE_RECURSIVE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_RECURSIVE_MUTEXES == 1 ) - - BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxMutex = ( Queue_t * ) xMutex; - - configASSERT( pxMutex ); - - /* Comments regarding mutual exclusion as per those within - xQueueGiveMutexRecursive(). */ - - traceTAKE_MUTEX_RECURSIVE( pxMutex ); - - if( pxMutex->u.xSemaphore.xMutexHolder == xTaskGetCurrentTaskHandle() ) - { - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; - xReturn = pdPASS; - } - else - { - xReturn = xQueueSemaphoreTake( pxMutex, xTicksToWait ); - - /* pdPASS will only be returned if the mutex was successfully - obtained. The calling task may have entered the Blocked state - before reaching here. */ - if( xReturn != pdFAIL ) - { - ( pxMutex->u.xSemaphore.uxRecursiveCallCount )++; - } - else - { - traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); - } - } - - return xReturn; - } - -#endif /* configUSE_RECURSIVE_MUTEXES */ -/*-----------------------------------------------------------*/ - -#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - - QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue ) - { - QueueHandle_t xHandle; - - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); - - xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - - if( xHandle != NULL ) - { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; - - traceCREATE_COUNTING_SEMAPHORE(); - } - else - { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); - } - - return xHandle; - } - -#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ -/*-----------------------------------------------------------*/ - -#if( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - - QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount ) - { - QueueHandle_t xHandle; - - configASSERT( uxMaxCount != 0 ); - configASSERT( uxInitialCount <= uxMaxCount ); - - xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); - - if( xHandle != NULL ) - { - ( ( Queue_t * ) xHandle )->uxMessagesWaiting = uxInitialCount; - - traceCREATE_COUNTING_SEMAPHORE(); - } - else - { - traceCREATE_COUNTING_SEMAPHORE_FAILED(); - } - - return xHandle; - } - -#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ -/*-----------------------------------------------------------*/ - -BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void * const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) -{ -BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif - - - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL(); - { - /* Is there room on the queue now? The running task must be the - highest priority task wanting to access the queue. If the head item - in the queue is to be overwritten then it does not matter if the - queue is full. */ - if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) - { - traceQUEUE_SEND( pxQueue ); - - #if ( configUSE_QUEUE_SETS == 1 ) - { - const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; - - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) - { - /* Do not notify the queue set as an existing item - was overwritten in the queue so the number of items - in the queue has not changed. */ - mtCOVERAGE_TEST_MARKER(); - } - else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - to the queue set caused a higher priority task to - unblock. A context switch is required. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. Yes it is ok to - do this from within the critical section - the - kernel takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if( xYieldRequired != pdFALSE ) - { - /* This path is a special case that will only get - executed if the task was holding multiple mutexes - and the mutexes were given back in an order that is - different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - xYieldRequired = prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - /* If there was a task waiting for data to arrive on the - queue then unblock it now. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The unblocked task has a priority higher than - our own so yield immediately. Yes it is ok to do - this from within the critical section - the kernel - takes care of that. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else if( xYieldRequired != pdFALSE ) - { - /* This path is a special case that will only get - executed if the task was holding multiple mutexes and - the mutexes were given back in an order that is - different to that in which they were taken. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_QUEUE_SETS */ - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was full and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); - - /* Return to the original privilege level before exiting - the function. */ - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was full and a block time was specified so - configure the timeout structure. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_SEND( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait ); - - /* Unlocking the queue means queue events can effect the - event list. It is possible that interrupts occurring now - remove this task from the event list again - but as the - scheduler is suspended the task will go onto the pending - ready last instead of the actual ready list. */ - prvUnlockQueue( pxQueue ); - - /* Resuming the scheduler will move tasks from the pending - ready list into the ready list - so it is feasible that this - task is already in a ready list before it yields - in which - case the yield will not cause a context switch unless there - is also a higher priority task in the pending ready list. */ - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - } - else - { - /* Try again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - /* The timeout has expired. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - - traceQUEUE_SEND_FAILED( pxQueue ); - return errQUEUE_FULL; - } - } /*lint -restore */ -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) -{ -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) ); - - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - - /* Similar to xQueueGenericSend, except without blocking if there is no room - in the queue. Also don't directly wake a task that was blocked on a queue - read, instead return a flag to say whether a context switch is required or - not (i.e. has a task with a higher priority than us been woken by this - post). */ - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) ) - { - const int8_t cTxLock = pxQueue->cTxLock; - const UBaseType_t uxPreviousMessagesWaiting = pxQueue->uxMessagesWaiting; - - traceQUEUE_SEND_FROM_ISR( pxQueue ); - - /* Semaphores use xQueueGiveFromISR(), so pxQueue will not be a - semaphore or mutex. That means prvCopyDataToQueue() cannot result - in a task disinheriting a priority and prvCopyDataToQueue() can be - called here even though the disinherit function does not check if - the scheduler is suspended before accessing the ready lists. */ - ( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ); - - /* The event list is not altered if the queue is locked. This will - be done when the queue is unlocked later. */ - if( cTxLock == queueUNLOCKED ) - { - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( ( xCopyPosition == queueOVERWRITE ) && ( uxPreviousMessagesWaiting != ( UBaseType_t ) 0 ) ) - { - /* Do not notify the queue set as an existing item - was overwritten in the queue so the number of items - in the queue has not changed. */ - mtCOVERAGE_TEST_MARKER(); - } - else if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting - to the queue set caused a higher priority task to - unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - /* Not used in this path. */ - ( void ) uxPreviousMessagesWaiting; - } - #endif /* configUSE_QUEUE_SETS */ - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was posted while it was locked. */ - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } - - xReturn = pdPASS; - } - else - { - traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); - xReturn = errQUEUE_FULL; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) -{ -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; - - /* Similar to xQueueGenericSendFromISR() but used with semaphores where the - item size is 0. Don't directly wake a task that was blocked on a queue - read, instead return a flag to say whether a context switch is required or - not (i.e. has a task with a higher priority than us been woken by this - post). */ - - configASSERT( pxQueue ); - - /* xQueueGenericSendFromISR() should be used instead of xQueueGiveFromISR() - if the item size is not 0. */ - configASSERT( pxQueue->uxItemSize == 0 ); - - /* Normally a mutex would not be given from an interrupt, especially if - there is a mutex holder, as priority inheritance makes no sense for an - interrupts, only tasks. */ - configASSERT( !( ( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) && ( pxQueue->u.xSemaphore.xMutexHolder != NULL ) ) ); - - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - - /* When the queue is used to implement a semaphore no data is ever - moved through the queue but it is still valid to see if the queue 'has - space'. */ - if( uxMessagesWaiting < pxQueue->uxLength ) - { - const int8_t cTxLock = pxQueue->cTxLock; - - traceQUEUE_SEND_FROM_ISR( pxQueue ); - - /* A task can only have an inherited priority if it is a mutex - holder - and if there is a mutex holder then the mutex cannot be - given from an ISR. As this is the ISR version of the function it - can be assumed there is no mutex holder and no need to determine if - priority disinheritance is needed. Simply increase the count of - messages (semaphores) available. */ - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; - - /* The event list is not altered if the queue is locked. This will - be done when the queue is unlocked later. */ - if( cTxLock == queueUNLOCKED ) - { - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The semaphore is a member of a queue set, and - posting to the queue set caused a higher priority - task to unblock. A context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so - record that a context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_QUEUE_SETS */ - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was posted while it was locked. */ - pxQueue->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } - - xReturn = pdPASS; - } - else - { - traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ); - xReturn = errQUEUE_FULL; - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) -{ -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; - - /* Check the pointer is not NULL. */ - configASSERT( ( pxQueue ) ); - - /* The buffer into which data is received can only be NULL if the data size - is zero (so no data is copied into the buffer. */ - configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); - - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif - - - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL(); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Data available, remove one item. */ - prvCopyDataFromQueue( pxQueue, pvBuffer ); - traceQUEUE_RECEIVE( pxQueue ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; - - /* There is now space in the queue, were any tasks waiting to - post to the queue? If so, unblock the highest priority waiting - task. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was empty and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was empty and a block time was specified so - configure the timeout structure. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - /* The timeout has not expired. If the queue is still empty place - the task on the list of tasks waiting to receive from the queue. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* The queue contains data again. Loop back to try and read the - data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - /* Timed out. If there is no data in the queue exit, otherwise loop - back and attempt to read the data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) -{ -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -Queue_t * const pxQueue = xQueue; - -#if( configUSE_MUTEXES == 1 ) - BaseType_t xInheritanceOccurred = pdFALSE; -#endif - - /* Check the queue pointer is not NULL. */ - configASSERT( ( pxQueue ) ); - - /* Check this really is a semaphore, in which case the item size will be - 0. */ - configASSERT( pxQueue->uxItemSize == 0 ); - - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif - - - /*lint -save -e904 This function relaxes the coding standard somewhat to allow return - statements within the function itself. This is done in the interest - of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL(); - { - /* Semaphores are queues with an item size of 0, and where the - number of messages in the queue is the semaphore's count value. */ - const UBaseType_t uxSemaphoreCount = pxQueue->uxMessagesWaiting; - - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxSemaphoreCount > ( UBaseType_t ) 0 ) - { - traceQUEUE_RECEIVE( pxQueue ); - - /* Semaphores are queues with a data size of zero and where the - messages waiting is the semaphore's count. Reduce the count. */ - pxQueue->uxMessagesWaiting = uxSemaphoreCount - ( UBaseType_t ) 1; - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* Record the information required to implement - priority inheritance should it become necessary. */ - pxQueue->u.xSemaphore.xMutexHolder = pvTaskIncrementMutexHeldCount(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_MUTEXES */ - - /* Check to see if other tasks are blocked waiting to give the - semaphore, and if so, unblock the highest priority such task. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* For inheritance to have occurred there must have been an - initial timeout, and an adjusted timeout cannot become 0, as - if it were 0 the function would have exited. */ - #if( configUSE_MUTEXES == 1 ) - { - configASSERT( xInheritanceOccurred == pdFALSE ); - } - #endif /* configUSE_MUTEXES */ - - /* The semaphore count was 0 and no block time is specified - (or the block time has expired) so exit now. */ - taskEXIT_CRITICAL(); - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The semaphore count was 0 and a block time was specified - so configure the timeout structure ready to block. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can give to and take from the semaphore - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - /* A block time is specified and not expired. If the semaphore - count is 0 then enter the Blocked state to wait for a semaphore to - become available. As semaphores are implemented with queues the - queue being empty is equivalent to the semaphore count being 0. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ); - - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - taskENTER_CRITICAL(); - { - xInheritanceOccurred = xTaskPriorityInherit( pxQueue->u.xSemaphore.xMutexHolder ); - } - taskEXIT_CRITICAL(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif - - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* There was no timeout and the semaphore count was not 0, so - attempt to take the semaphore again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - /* Timed out. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - - /* If the semaphore count is 0 exit now as the timeout has - expired. Otherwise return to attempt to take the semaphore that is - known to be available. As semaphores are implemented by queues the - queue being empty is equivalent to the semaphore count being 0. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - #if ( configUSE_MUTEXES == 1 ) - { - /* xInheritanceOccurred could only have be set if - pxQueue->uxQueueType == queueQUEUE_IS_MUTEX so no need to - test the mutex type again to check it is actually a mutex. */ - if( xInheritanceOccurred != pdFALSE ) - { - taskENTER_CRITICAL(); - { - UBaseType_t uxHighestWaitingPriority; - - /* This task blocking on the mutex caused another - task to inherit this task's priority. Now this task - has timed out the priority should be disinherited - again, but only as low as the next highest priority - task that is waiting for the same mutex. */ - uxHighestWaitingPriority = prvGetDisinheritPriorityAfterTimeout( pxQueue ); - vTaskPriorityDisinheritAfterTimeout( pxQueue->u.xSemaphore.xMutexHolder, uxHighestWaitingPriority ); - } - taskEXIT_CRITICAL(); - } - } - #endif /* configUSE_MUTEXES */ - - traceQUEUE_RECEIVE_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueuePeek( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait ) -{ -BaseType_t xEntryTimeSet = pdFALSE; -TimeOut_t xTimeOut; -int8_t *pcOriginalReadPosition; -Queue_t * const pxQueue = xQueue; - - /* Check the pointer is not NULL. */ - configASSERT( ( pxQueue ) ); - - /* The buffer into which data is received can only be NULL if the data size - is zero (so no data is copied into the buffer. */ - configASSERT( !( ( ( pvBuffer ) == NULL ) && ( ( pxQueue )->uxItemSize != ( UBaseType_t ) 0U ) ) ); - - /* Cannot block if the scheduler is suspended. */ - #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) - { - configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); - } - #endif - - - /*lint -save -e904 This function relaxes the coding standard somewhat to - allow return statements within the function itself. This is done in the - interest of execution time efficiency. */ - for( ;; ) - { - taskENTER_CRITICAL(); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - - /* Is there data in the queue now? To be running the calling task - must be the highest priority task wanting to access the queue. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Remember the read position so it can be reset after the data - is read from the queue as this function is only peeking the - data, not removing it. */ - pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; - - prvCopyDataFromQueue( pxQueue, pvBuffer ); - traceQUEUE_PEEK( pxQueue ); - - /* The data is not being removed, so reset the read pointer. */ - pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; - - /* The data is being left in the queue, so see if there are - any other tasks waiting for the data. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than this task. */ - queueYIELD_IF_USING_PREEMPTION(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - taskEXIT_CRITICAL(); - return pdPASS; - } - else - { - if( xTicksToWait == ( TickType_t ) 0 ) - { - /* The queue was empty and no block time is specified (or - the block time has expired) so leave now. */ - taskEXIT_CRITICAL(); - traceQUEUE_PEEK_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else if( xEntryTimeSet == pdFALSE ) - { - /* The queue was empty and a block time was specified so - configure the timeout structure ready to enter the blocked - state. */ - vTaskInternalSetTimeOutState( &xTimeOut ); - xEntryTimeSet = pdTRUE; - } - else - { - /* Entry time was already set. */ - mtCOVERAGE_TEST_MARKER(); - } - } - } - taskEXIT_CRITICAL(); - - /* Interrupts and other tasks can send to and receive from the queue - now the critical section has been exited. */ - - vTaskSuspendAll(); - prvLockQueue( pxQueue ); - - /* Update the timeout state to see if it has expired yet. */ - if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE ) - { - /* Timeout has not expired yet, check to see if there is data in the - queue now, and if not enter the Blocked state to wait for data. */ - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceBLOCKING_ON_QUEUE_PEEK( pxQueue ); - vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait ); - prvUnlockQueue( pxQueue ); - if( xTaskResumeAll() == pdFALSE ) - { - portYIELD_WITHIN_API(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* There is data in the queue now, so don't enter the blocked - state, instead return to try and obtain the data. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - } - } - else - { - /* The timeout has expired. If there is still no data in the queue - exit, otherwise go back and try to read the data again. */ - prvUnlockQueue( pxQueue ); - ( void ) xTaskResumeAll(); - - if( prvIsQueueEmpty( pxQueue ) != pdFALSE ) - { - traceQUEUE_PEEK_FAILED( pxQueue ); - return errQUEUE_EMPTY; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } /*lint -restore */ -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken ) -{ -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting; - - /* Cannot block in an ISR, so check there is data available. */ - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - const int8_t cRxLock = pxQueue->cRxLock; - - traceQUEUE_RECEIVE_FROM_ISR( pxQueue ); - - prvCopyDataFromQueue( pxQueue, pvBuffer ); - pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1; - - /* If the queue is locked the event list will not be modified. - Instead update the lock count so the task that unlocks the queue - will know that an ISR has removed data while the queue was - locked. */ - if( cRxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - /* The task waiting has a higher priority than us so - force a context switch. */ - if( pxHigherPriorityTaskWoken != NULL ) - { - *pxHigherPriorityTaskWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Increment the lock count so the task that unlocks the queue - knows that data was removed while it was locked. */ - pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 ); - } - - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue, void * const pvBuffer ) -{ -BaseType_t xReturn; -UBaseType_t uxSavedInterruptStatus; -int8_t *pcOriginalReadPosition; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) ); - configASSERT( pxQueue->uxItemSize != 0 ); /* Can't peek a semaphore. */ - - /* RTOS ports that support interrupt nesting have the concept of a maximum - system call (or maximum API call) interrupt priority. Interrupts that are - above the maximum system call priority are kept permanently enabled, even - when the RTOS kernel is in a critical section, but cannot make any calls to - FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h - then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has been - assigned a priority above the configured maximum system call priority. - Only FreeRTOS functions that end in FromISR can be called from interrupts - that have been assigned a priority at or (logically) below the maximum - system call interrupt priority. FreeRTOS maintains a separate interrupt - safe API to ensure interrupt entry is as fast and as simple as possible. - More information (albeit Cortex-M specific) is provided on the following - link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */ - portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); - - uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR(); - { - /* Cannot block in an ISR, so check there is data available. */ - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - traceQUEUE_PEEK_FROM_ISR( pxQueue ); - - /* Remember the read position so it can be reset as nothing is - actually being removed from the queue. */ - pcOriginalReadPosition = pxQueue->u.xQueue.pcReadFrom; - prvCopyDataFromQueue( pxQueue, pvBuffer ); - pxQueue->u.xQueue.pcReadFrom = pcOriginalReadPosition; - - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ); - } - } - portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) -{ -UBaseType_t uxReturn; - - configASSERT( xQueue ); - - taskENTER_CRITICAL(); - { - uxReturn = ( ( Queue_t * ) xQueue )->uxMessagesWaiting; - } - taskEXIT_CRITICAL(); - - return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ -/*-----------------------------------------------------------*/ - -UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) -{ -UBaseType_t uxReturn; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - - taskENTER_CRITICAL(); - { - uxReturn = pxQueue->uxLength - pxQueue->uxMessagesWaiting; - } - taskEXIT_CRITICAL(); - - return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ -/*-----------------------------------------------------------*/ - -UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) -{ -UBaseType_t uxReturn; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - uxReturn = pxQueue->uxMessagesWaiting; - - return uxReturn; -} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */ -/*-----------------------------------------------------------*/ - -void vQueueDelete( QueueHandle_t xQueue ) -{ -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - traceQUEUE_DELETE( pxQueue ); - - #if ( configQUEUE_REGISTRY_SIZE > 0 ) - { - vQueueUnregisterQueue( pxQueue ); - } - #endif - - #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 0 ) ) - { - /* The queue can only have been allocated dynamically - free it - again. */ - vPortFree( pxQueue ); - } - #elif( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) - { - /* The queue could have been allocated statically or dynamically, so - check before attempting to free the memory. */ - if( pxQueue->ucStaticallyAllocated == ( uint8_t ) pdFALSE ) - { - vPortFree( pxQueue ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #else - { - /* The queue must have been statically allocated, so is not going to be - deleted. Avoid compiler warnings about the unused parameter. */ - ( void ) pxQueue; - } - #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ -} -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - UBaseType_t uxQueueGetQueueNumber( QueueHandle_t xQueue ) - { - return ( ( Queue_t * ) xQueue )->uxQueueNumber; - } - -#endif /* configUSE_TRACE_FACILITY */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - void vQueueSetQueueNumber( QueueHandle_t xQueue, UBaseType_t uxQueueNumber ) - { - ( ( Queue_t * ) xQueue )->uxQueueNumber = uxQueueNumber; - } - -#endif /* configUSE_TRACE_FACILITY */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TRACE_FACILITY == 1 ) - - uint8_t ucQueueGetQueueType( QueueHandle_t xQueue ) - { - return ( ( Queue_t * ) xQueue )->ucQueueType; - } - -#endif /* configUSE_TRACE_FACILITY */ -/*-----------------------------------------------------------*/ - -#if( configUSE_MUTEXES == 1 ) - - static UBaseType_t prvGetDisinheritPriorityAfterTimeout( const Queue_t * const pxQueue ) - { - UBaseType_t uxHighestPriorityOfWaitingTasks; - - /* If a task waiting for a mutex causes the mutex holder to inherit a - priority, but the waiting task times out, then the holder should - disinherit the priority - but only down to the highest priority of any - other tasks that are waiting for the same mutex. For this purpose, - return the priority of the highest priority task that is waiting for the - mutex. */ - if( listCURRENT_LIST_LENGTH( &( pxQueue->xTasksWaitingToReceive ) ) > 0U ) - { - uxHighestPriorityOfWaitingTasks = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) listGET_ITEM_VALUE_OF_HEAD_ENTRY( &( pxQueue->xTasksWaitingToReceive ) ); - } - else - { - uxHighestPriorityOfWaitingTasks = tskIDLE_PRIORITY; - } - - return uxHighestPriorityOfWaitingTasks; - } - -#endif /* configUSE_MUTEXES */ -/*-----------------------------------------------------------*/ - -static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition ) -{ -BaseType_t xReturn = pdFALSE; -UBaseType_t uxMessagesWaiting; - - /* This function is called from a critical section. */ - - uxMessagesWaiting = pxQueue->uxMessagesWaiting; - - if( pxQueue->uxItemSize == ( UBaseType_t ) 0 ) - { - #if ( configUSE_MUTEXES == 1 ) - { - if( pxQueue->uxQueueType == queueQUEUE_IS_MUTEX ) - { - /* The mutex is no longer being held. */ - xReturn = xTaskPriorityDisinherit( pxQueue->u.xSemaphore.xMutexHolder ); - pxQueue->u.xSemaphore.xMutexHolder = NULL; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - #endif /* configUSE_MUTEXES */ - } - else if( xPosition == queueSEND_TO_BACK ) - { - ( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ - pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ - if( pxQueue->pcWriteTo >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ - { - pxQueue->pcWriteTo = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - ( void ) memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e9087 !e418 MISRA exception as the casts are only redundant for some ports. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. Assert checks null pointer only used when length is 0. */ - pxQueue->u.xQueue.pcReadFrom -= pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom < pxQueue->pcHead ) /*lint !e946 MISRA exception justified as comparison of pointers is the cleanest solution. */ - { - pxQueue->u.xQueue.pcReadFrom = ( pxQueue->u.xQueue.pcTail - pxQueue->uxItemSize ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - if( xPosition == queueOVERWRITE ) - { - if( uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* An item is not being added but overwritten, so subtract - one from the recorded number of items in the queue so when - one is added again below the number of recorded items remains - correct. */ - --uxMessagesWaiting; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1; - - return xReturn; -} -/*-----------------------------------------------------------*/ - -static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer ) -{ - if( pxQueue->uxItemSize != ( UBaseType_t ) 0 ) - { - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */ - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */ - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */ - } -} -/*-----------------------------------------------------------*/ - -static void prvUnlockQueue( Queue_t * const pxQueue ) -{ - /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */ - - /* The lock counts contains the number of extra data items placed or - removed from the queue while the queue was locked. When a queue is - locked items can be added or removed, but the event lists cannot be - updated. */ - taskENTER_CRITICAL(); - { - int8_t cTxLock = pxQueue->cTxLock; - - /* See if data was added to the queue while it was locked. */ - while( cTxLock > queueLOCKED_UNMODIFIED ) - { - /* Data was posted while the queue was locked. Are any tasks - blocked waiting for data to become available? */ - #if ( configUSE_QUEUE_SETS == 1 ) - { - if( pxQueue->pxQueueSetContainer != NULL ) - { - if( prvNotifyQueueSetContainer( pxQueue ) != pdFALSE ) - { - /* The queue is a member of a queue set, and posting to - the queue set caused a higher priority task to unblock. - A context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - /* Tasks that are removed from the event list will get - added to the pending ready list as the scheduler is still - suspended. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that a - context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - break; - } - } - } - #else /* configUSE_QUEUE_SETS */ - { - /* Tasks that are removed from the event list will get added to - the pending ready list as the scheduler is still suspended. */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority so record that - a context switch is required. */ - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - break; - } - } - #endif /* configUSE_QUEUE_SETS */ - - --cTxLock; - } - - pxQueue->cTxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL(); - - /* Do the same for the Rx lock. */ - taskENTER_CRITICAL(); - { - int8_t cRxLock = pxQueue->cRxLock; - - while( cRxLock > queueLOCKED_UNMODIFIED ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - vTaskMissedYield(); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - --cRxLock; - } - else - { - break; - } - } - - pxQueue->cRxLock = queueUNLOCKED; - } - taskEXIT_CRITICAL(); -} -/*-----------------------------------------------------------*/ - -static BaseType_t prvIsQueueEmpty( const Queue_t *pxQueue ) -{ -BaseType_t xReturn; - - taskENTER_CRITICAL(); - { - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - taskEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) -{ -BaseType_t xReturn; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ -/*-----------------------------------------------------------*/ - -static BaseType_t prvIsQueueFull( const Queue_t *pxQueue ) -{ -BaseType_t xReturn; - - taskENTER_CRITICAL(); - { - if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - } - taskEXIT_CRITICAL(); - - return xReturn; -} -/*-----------------------------------------------------------*/ - -BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) -{ -BaseType_t xReturn; -Queue_t * const pxQueue = xQueue; - - configASSERT( pxQueue ); - if( pxQueue->uxMessagesWaiting == pxQueue->uxLength ) - { - xReturn = pdTRUE; - } - else - { - xReturn = pdFALSE; - } - - return xReturn; -} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_CO_ROUTINES == 1 ) - - BaseType_t xQueueCRSend( QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; - - /* If the queue is already full we may have to block. A critical section - is required to prevent an interrupt removing something from the queue - between the check to see if the queue is full and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( prvIsQueueFull( pxQueue ) != pdFALSE ) - { - /* The queue is full - do we want to block or just leave without - posting? */ - if( xTicksToWait > ( TickType_t ) 0 ) - { - /* As this is called from a coroutine we cannot block directly, but - return indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToSend ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - } - portENABLE_INTERRUPTS(); - - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - /* There is room in the queue, copy the data into the queue. */ - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - xReturn = pdPASS; - - /* Were any co-routines waiting for data to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The co-routine waiting has a higher priority so record - that a yield might be appropriate. */ - xReturn = errQUEUE_YIELD; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - xReturn = errQUEUE_FULL; - } - } - portENABLE_INTERRUPTS(); - - return xReturn; - } - -#endif /* configUSE_CO_ROUTINES */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_CO_ROUTINES == 1 ) - - BaseType_t xQueueCRReceive( QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; - - /* If the queue is already empty we may have to block. A critical section - is required to prevent an interrupt adding something to the queue - between the check to see if the queue is empty and blocking on the queue. */ - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0 ) - { - /* There are no messages in the queue, do we want to block or just - leave with nothing? */ - if( xTicksToWait > ( TickType_t ) 0 ) - { - /* As this is a co-routine we cannot block directly, but return - indicating that we need to block. */ - vCoRoutineAddToDelayedList( xTicksToWait, &( pxQueue->xTasksWaitingToReceive ) ); - portENABLE_INTERRUPTS(); - return errQUEUE_BLOCKED; - } - else - { - portENABLE_INTERRUPTS(); - return errQUEUE_FULL; - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - portENABLE_INTERRUPTS(); - - portDISABLE_INTERRUPTS(); - { - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Data is available from the queue. */ - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - --( pxQueue->uxMessagesWaiting ); - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - - xReturn = pdPASS; - - /* Were any co-routines waiting for space to become available? */ - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - /* In this instance the co-routine could be placed directly - into the ready list as we are within a critical section. - Instead the same pending ready list mechanism is used as if - the event were caused from within an interrupt. */ - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - xReturn = errQUEUE_YIELD; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - xReturn = pdFAIL; - } - } - portENABLE_INTERRUPTS(); - - return xReturn; - } - -#endif /* configUSE_CO_ROUTINES */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_CO_ROUTINES == 1 ) - - BaseType_t xQueueCRSendFromISR( QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken ) - { - Queue_t * const pxQueue = xQueue; - - /* Cannot block within an ISR so if there is no space on the queue then - exit without doing anything. */ - if( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) - { - prvCopyDataToQueue( pxQueue, pvItemToQueue, queueSEND_TO_BACK ); - - /* We only want to wake one co-routine per ISR, so check that a - co-routine has not already been woken. */ - if( xCoRoutinePreviouslyWoken == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE ) - { - return pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - return xCoRoutinePreviouslyWoken; - } - -#endif /* configUSE_CO_ROUTINES */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_CO_ROUTINES == 1 ) - - BaseType_t xQueueCRReceiveFromISR( QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxCoRoutineWoken ) - { - BaseType_t xReturn; - Queue_t * const pxQueue = xQueue; - - /* We cannot block from an ISR, so check there is data available. If - not then just leave without doing anything. */ - if( pxQueue->uxMessagesWaiting > ( UBaseType_t ) 0 ) - { - /* Copy the data from the queue. */ - pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; - if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) - { - pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - --( pxQueue->uxMessagesWaiting ); - ( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( unsigned ) pxQueue->uxItemSize ); - - if( ( *pxCoRoutineWoken ) == pdFALSE ) - { - if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE ) - { - if( xCoRoutineRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE ) - { - *pxCoRoutineWoken = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - xReturn = pdPASS; - } - else - { - xReturn = pdFAIL; - } - - return xReturn; - } - -#endif /* configUSE_CO_ROUTINES */ -/*-----------------------------------------------------------*/ - -#if ( configQUEUE_REGISTRY_SIZE > 0 ) - - void vQueueAddToRegistry( QueueHandle_t xQueue, const char *pcQueueName ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - UBaseType_t ux; - - /* See if there is an empty space in the registry. A NULL name denotes - a free slot. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].pcQueueName == NULL ) - { - /* Store the information on this queue. */ - xQueueRegistry[ ux ].pcQueueName = pcQueueName; - xQueueRegistry[ ux ].xHandle = xQueue; - - traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ); - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - } - -#endif /* configQUEUE_REGISTRY_SIZE */ -/*-----------------------------------------------------------*/ - -#if ( configQUEUE_REGISTRY_SIZE > 0 ) - - const char *pcQueueGetName( QueueHandle_t xQueue ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - { - UBaseType_t ux; - const char *pcReturn = NULL; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ - - /* Note there is nothing here to protect against another task adding or - removing entries from the registry while it is being searched. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].xHandle == xQueue ) - { - pcReturn = xQueueRegistry[ ux ].pcQueueName; - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - return pcReturn; - } /*lint !e818 xQueue cannot be a pointer to const because it is a typedef. */ - -#endif /* configQUEUE_REGISTRY_SIZE */ -/*-----------------------------------------------------------*/ - -#if ( configQUEUE_REGISTRY_SIZE > 0 ) - - void vQueueUnregisterQueue( QueueHandle_t xQueue ) - { - UBaseType_t ux; - - /* See if the handle of the queue being unregistered in actually in the - registry. */ - for( ux = ( UBaseType_t ) 0U; ux < ( UBaseType_t ) configQUEUE_REGISTRY_SIZE; ux++ ) - { - if( xQueueRegistry[ ux ].xHandle == xQueue ) - { - /* Set the name to NULL to show that this slot if free again. */ - xQueueRegistry[ ux ].pcQueueName = NULL; - - /* Set the handle to NULL to ensure the same queue handle cannot - appear in the registry twice if it is added, removed, then - added again. */ - xQueueRegistry[ ux ].xHandle = ( QueueHandle_t ) 0; - break; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - - } /*lint !e818 xQueue could not be pointer to const because it is a typedef. */ - -#endif /* configQUEUE_REGISTRY_SIZE */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_TIMERS == 1 ) - - void vQueueWaitForMessageRestricted( QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely ) - { - Queue_t * const pxQueue = xQueue; - - /* This function should not be called by application code hence the - 'Restricted' in its name. It is not part of the public API. It is - designed for use by kernel code, and has special calling requirements. - It can result in vListInsert() being called on a list that can only - possibly ever have one item in it, so the list will be fast, but even - so it should be called with the scheduler locked and not from a critical - section. */ - - /* Only do anything if there are no messages in the queue. This function - will not actually cause the task to block, just place it on a blocked - list. It will not block until the scheduler is unlocked - at which - time a yield will be performed. If an item is added to the queue while - the queue is locked, and the calling task blocks on the queue, then the - calling task will be immediately unblocked when the queue is unlocked. */ - prvLockQueue( pxQueue ); - if( pxQueue->uxMessagesWaiting == ( UBaseType_t ) 0U ) - { - /* There is nothing in the queue, block for the specified period. */ - vTaskPlaceOnEventListRestricted( &( pxQueue->xTasksWaitingToReceive ), xTicksToWait, xWaitIndefinitely ); - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - prvUnlockQueue( pxQueue ); - } - -#endif /* configUSE_TIMERS */ -/*-----------------------------------------------------------*/ - -#if( ( configUSE_QUEUE_SETS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) - - QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) - { - QueueSetHandle_t pxQueue; - - pxQueue = xQueueGenericCreate( uxEventQueueLength, ( UBaseType_t ) sizeof( Queue_t * ), queueQUEUE_TYPE_SET ); - - return pxQueue; - } - -#endif /* configUSE_QUEUE_SETS */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_QUEUE_SETS == 1 ) - - BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) - { - BaseType_t xReturn; - - taskENTER_CRITICAL(); - { - if( ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer != NULL ) - { - /* Cannot add a queue/semaphore to more than one queue set. */ - xReturn = pdFAIL; - } - else if( ( ( Queue_t * ) xQueueOrSemaphore )->uxMessagesWaiting != ( UBaseType_t ) 0 ) - { - /* Cannot add a queue/semaphore to a queue set if there are already - items in the queue/semaphore. */ - xReturn = pdFAIL; - } - else - { - ( ( Queue_t * ) xQueueOrSemaphore )->pxQueueSetContainer = xQueueSet; - xReturn = pdPASS; - } - } - taskEXIT_CRITICAL(); - - return xReturn; - } - -#endif /* configUSE_QUEUE_SETS */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_QUEUE_SETS == 1 ) - - BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet ) - { - BaseType_t xReturn; - Queue_t * const pxQueueOrSemaphore = ( Queue_t * ) xQueueOrSemaphore; - - if( pxQueueOrSemaphore->pxQueueSetContainer != xQueueSet ) - { - /* The queue was not a member of the set. */ - xReturn = pdFAIL; - } - else if( pxQueueOrSemaphore->uxMessagesWaiting != ( UBaseType_t ) 0 ) - { - /* It is dangerous to remove a queue from a set when the queue is - not empty because the queue set will still hold pending events for - the queue. */ - xReturn = pdFAIL; - } - else - { - taskENTER_CRITICAL(); - { - /* The queue is no longer contained in the set. */ - pxQueueOrSemaphore->pxQueueSetContainer = NULL; - } - taskEXIT_CRITICAL(); - xReturn = pdPASS; - } - - return xReturn; - } /*lint !e818 xQueueSet could not be declared as pointing to const as it is a typedef. */ - -#endif /* configUSE_QUEUE_SETS */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_QUEUE_SETS == 1 ) - - QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, TickType_t const xTicksToWait ) - { - QueueSetMemberHandle_t xReturn = NULL; - - ( void ) xQueueReceive( ( QueueHandle_t ) xQueueSet, &xReturn, xTicksToWait ); /*lint !e961 Casting from one typedef to another is not redundant. */ - return xReturn; - } - -#endif /* configUSE_QUEUE_SETS */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_QUEUE_SETS == 1 ) - - QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) - { - QueueSetMemberHandle_t xReturn = NULL; - - ( void ) xQueueReceiveFromISR( ( QueueHandle_t ) xQueueSet, &xReturn, NULL ); /*lint !e961 Casting from one typedef to another is not redundant. */ - return xReturn; - } - -#endif /* configUSE_QUEUE_SETS */ -/*-----------------------------------------------------------*/ - -#if ( configUSE_QUEUE_SETS == 1 ) - - static BaseType_t prvNotifyQueueSetContainer( const Queue_t * const pxQueue ) - { - Queue_t *pxQueueSetContainer = pxQueue->pxQueueSetContainer; - BaseType_t xReturn = pdFALSE; - - /* This function must be called form a critical section. */ - - configASSERT( pxQueueSetContainer ); - configASSERT( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ); - - if( pxQueueSetContainer->uxMessagesWaiting < pxQueueSetContainer->uxLength ) - { - const int8_t cTxLock = pxQueueSetContainer->cTxLock; - - traceQUEUE_SEND( pxQueueSetContainer ); - - /* The data copied is the handle of the queue that contains data. */ - xReturn = prvCopyDataToQueue( pxQueueSetContainer, &pxQueue, queueSEND_TO_BACK ); - - if( cTxLock == queueUNLOCKED ) - { - if( listLIST_IS_EMPTY( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) == pdFALSE ) - { - if( xTaskRemoveFromEventList( &( pxQueueSetContainer->xTasksWaitingToReceive ) ) != pdFALSE ) - { - /* The task waiting has a higher priority. */ - xReturn = pdTRUE; - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - } - else - { - pxQueueSetContainer->cTxLock = ( int8_t ) ( cTxLock + 1 ); - } - } - else - { - mtCOVERAGE_TEST_MARKER(); - } - - return xReturn; - } - -#endif /* configUSE_QUEUE_SETS */ - - - - - - - - - - - -