From 33c060079a7bb35a25c6085f4844509152c03fef Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Fri, 9 Nov 2018 22:36:28 +0100 Subject: [PATCH 01/23] initial commit add SDIOBlockdevice implementation for STM32F4 --- SDIOBlockDevice.cpp | 378 ++++++ SDIOBlockDevice.h | 143 ++ TARGET_STM/TARGET_STM32F4/sdio_device.c | 538 ++++++++ TARGET_STM/TARGET_STM32F4/sdio_device.h | 126 ++ TESTS/blockdevice/basic/main.cpp | 119 ++ TESTS/filesystem/dirs/main.cpp | 500 +++++++ TESTS/filesystem/files/main.cpp | 337 +++++ TESTS/filesystem/fopen/fopen.cpp | 1621 +++++++++++++++++++++++ TESTS/filesystem/parallel/main.cpp | 209 +++ TESTS/filesystem/seek/main.cpp | 656 +++++++++ config/mbed_lib.json | 12 + 11 files changed, 4639 insertions(+) create mode 100644 SDIOBlockDevice.cpp create mode 100644 SDIOBlockDevice.h create mode 100644 TARGET_STM/TARGET_STM32F4/sdio_device.c create mode 100644 TARGET_STM/TARGET_STM32F4/sdio_device.h create mode 100644 TESTS/blockdevice/basic/main.cpp create mode 100644 TESTS/filesystem/dirs/main.cpp create mode 100644 TESTS/filesystem/files/main.cpp create mode 100644 TESTS/filesystem/fopen/fopen.cpp create mode 100644 TESTS/filesystem/parallel/main.cpp create mode 100644 TESTS/filesystem/seek/main.cpp create mode 100644 config/mbed_lib.json diff --git a/SDIOBlockDevice.cpp b/SDIOBlockDevice.cpp new file mode 100644 index 0000000..86572bb --- /dev/null +++ b/SDIOBlockDevice.cpp @@ -0,0 +1,378 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "platform/mbed_debug.h" +#include "platform/mbed_wait_api.h" +#include "SDIOBlockDevice.h" + +namespace mbed +{ + +/* + * defines + */ + +#define SD_DBG 0 /*!< 1 - Enable debugging */ +#define SD_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */ + +#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ +#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ +#define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ +#define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ +#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ +#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ +#define SD_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */ +#define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */ +#define SD_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */ +#define SD_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */ +#define SD_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */ +#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */ +#define SD_BLOCK_DEVICE_ERROR_READBLOCKS -5013 /*!< read data blocks from SD failed */ +#define SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS -5014 /*!< write data blocks to SD failed */ +#define SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS -5015 /*!< erase data blocks to SD failed */ + +#define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */ + +// Types +#define SDCARD_NONE 0 /**< No card is present */ +#define SDCARD_V1 1 /**< v1.x Standard Capacity */ +#define SDCARD_V2 2 /**< v2.x Standard capacity SD card */ +#define SDCARD_V2HC 3 /**< v2.x High capacity SD card */ +#define CARD_UNKNOWN 4 /**< Unknown or unsupported card */ + +#ifndef MBED_CONF_SD_TIMEOUT +#define MBED_CONF_SD_TIMEOUT (30 * 1000) /* ms */ +#endif + +SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect), + _is_initialized(0), + _sectors(0), + _init_ref_count(0) +{ + _card_type = SDCARD_NONE; + + // Only HC block size is supported. + _block_size = BLOCK_SIZE_HC; + _erase_size = BLOCK_SIZE_HC; +} + +SDIOBlockDevice::~SDIOBlockDevice() +{ + if (_is_initialized) + { + deinit(); + } +} + +int SDIOBlockDevice::init() +{ + debug_if(SD_DBG, "init Card...\r\n"); + + lock(); + + if (!_is_initialized) + { + _init_ref_count = 0; + } + + _init_ref_count++; + + if (_init_ref_count != 1) + { + unlock(); + return BD_ERROR_OK; + } + + if (isPresent() == false) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + } + + int status = SD_Init(); + if (BD_ERROR_OK != status) + { + unlock(); + return BD_ERROR_DEVICE_ERROR; + } + + SD_GetCardInfo(&_cardInfo); + _is_initialized = true; + debug_if(SD_DBG, "SD initialized: type: %d version: %d class: %d\n", + _cardInfo.CardType, _cardInfo.CardVersion, _cardInfo.Class); + debug_if(SD_DBG, "SD size: %d MB\n", + _cardInfo.LogBlockNbr / 2 / 1024); + + // get sectors count from cardinfo + _sectors = _cardInfo.LogBlockNbr; + if (BLOCK_SIZE_HC != _cardInfo.BlockSize) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE; + } + + unlock(); + return status; +} + +int SDIOBlockDevice::deinit() +{ + debug_if(SD_DBG, "deinit Card...\r\n"); + lock(); + + if (!_is_initialized) + { + _init_ref_count = 0; + unlock(); + return BD_ERROR_OK; + } + + _init_ref_count--; + + if (_init_ref_count) + { + unlock(); + return BD_ERROR_OK; + } + + int status = SD_DeInit(); + _is_initialized = false; + + _sectors = 0; + + unlock(); + return status; +} + +int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) +{ + //debug_if(SD_DBG, "read Card...\r\n"); + lock(); + if (isPresent() == false) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + } + if (!is_valid_read(addr, size)) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + if (!_is_initialized) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + uint32_t *buffer = static_cast(b); + + // ReadBlocks uses byte unit address + // SDHC and SDXC Cards different addressing is handled in ReadBlocks() + bd_addr_t blockCnt = size / _block_size; + addr = addr / _block_size; + + // make sure card is ready + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + wait_ms(1); + } + + // receive the data : one block/ multiple blocks is handled in ReadBlocks() + int status = SD_ReadBlocks_DMA(buffer, addr, blockCnt); + debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + + if (status == MSD_OK) + { + // wait until DMA finished + while (SD_DMA_ReadPending() != SD_TRANSFER_OK) + { + uint32_t tickstart = HAL_GetTick(); + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + } + } + // make sure card is ready + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + wait_ms(10); + } + } + else + { + debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode); + status = SD_BLOCK_DEVICE_ERROR_READBLOCKS; + } + + unlock(); + return status; +} + +int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) +{ + //debug_if(SD_DBG, "program Card...\r\n"); + lock(); + + if (isPresent() == false) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + } + if (!is_valid_program(addr, size)) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + if (!_is_initialized) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + //uint32_t *buffer = static_cast< uint32_t *>(b); + // HAL layer uses uint32_t for addr/size + uint32_t *buffer = (uint32_t *)(b); + + // Get block count + bd_size_t blockCnt = size / _block_size; + addr = addr / _block_size; + + // make sure card is ready + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + wait_ms(1); + } + + int status = SD_WriteBlocks_DMA(buffer, addr, blockCnt); + debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + + if (status == MSD_OK) + { + // wait until DMA finished + while (SD_DMA_WritePending() != SD_TRANSFER_OK) + { + uint32_t tickstart = HAL_GetTick(); + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + } + } + // make sure card is ready + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + wait_ms(1); + } + } + else + { + debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode); + status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + } + + unlock(); + return status; +} + +int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) +{ + debug_if(SD_DBG, "trim Card...\r\n"); + lock(); + if (isPresent() == false) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + } + if (!_is_valid_trim(addr, size)) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_PARAMETER; + } + + if (!_is_initialized) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_NO_INIT; + } + + bd_size_t blockCnt = size / _block_size; + addr = addr / _block_size; + + int status = SD_Erase(addr, blockCnt); + if (status != 0) + { + debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; + } + else + { + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + wait_ms(10); + } + } + + unlock(); + return status; +} + +bd_size_t SDIOBlockDevice::get_read_size() const +{ + return _block_size; +} + +bd_size_t SDIOBlockDevice::get_program_size() const +{ + return _block_size; +} + +bd_size_t SDIOBlockDevice::size() const +{ + return _block_size * _sectors; +} + +void SDIOBlockDevice::debug(bool dbg) +{ +} + +bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) +{ + return ( + addr % _erase_size == 0 && + size % _erase_size == 0 && + addr + size <= this->size()); +} + +bool SDIOBlockDevice::isPresent(void) +{ + if (_cardDetect.is_connected()) + return (_cardDetect.read() == 0); + else + return true; +} + +} // namespace mbed diff --git a/SDIOBlockDevice.h b/SDIOBlockDevice.h new file mode 100644 index 0000000..9840833 --- /dev/null +++ b/SDIOBlockDevice.h @@ -0,0 +1,143 @@ +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ + +#define MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ + +#include "features/storage/blockdevice/BlockDevice.h" +#include "drivers/DigitalIn.h" +#include "platform/PlatformMutex.h" +#include "sdio_device.h" + +namespace mbed +{ + +class SDIOBlockDevice : public BlockDevice +{ + public: + SDIOBlockDevice(PinName cardDetect = NC); + virtual ~SDIOBlockDevice(); + /** Initialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int init(); + + /** Deinitialize a block device + * + * @return 0 on success or a negative error code on failure + */ + virtual int deinit(); + + /** Read blocks from a block device + * + * @param buffer Buffer to write blocks to + * @param addr Address of block to begin reading from + * @param size Size to read in bytes, must be a multiple of read block size + * @return 0 on success, negative error code on failure + */ + virtual int read(void *buffer, bd_addr_t addr, bd_size_t size); + + /** Program blocks to a block device + * + * The blocks must have been erased prior to being programmed + * + * @param buffer Buffer of data to write to blocks + * @param addr Address of block to begin writing to + * @param size Size to write in bytes, must be a multiple of program block size + * @return 0 on success, negative error code on failure + */ + virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size); + + /** Mark blocks as no longer in use + * + * This function provides a hint to the underlying block device that a region of blocks + * is no longer in use and may be erased without side effects. Erase must still be called + * before programming, but trimming allows flash-translation-layers to schedule erases when + * the device is not busy. + * + * @param addr Address of block to mark as unused + * @param size Size to mark as unused in bytes, must be a multiple of erase block size + * @return 0 on success, negative error code on failure + */ + virtual int trim(bd_addr_t addr, bd_size_t size); + + /** Get the size of a readable block + * + * @return Size of a readable block in bytes + */ + virtual bd_size_t get_read_size() const; + + /** Get the size of a programable block + * + * @return Size of a programable block in bytes + * @note Must be a multiple of the read size + */ + virtual bd_size_t get_program_size() const; + + /** Get the total size of the underlying device + * + * @return Size of the underlying device in bytes + */ + virtual bd_size_t size() const; + + /** Enable or disable debugging + * + * @param dbg State of debugging + */ + virtual void debug(bool dbg); + + /** Set the transfer frequency + * + * @param freq Transfer frequency + * @note Max frequency supported is 25MHZ + */ + virtual int frequency(uint64_t freq) { return BD_ERROR_OK; }; + + /** check if SD is present + * + * @note check physical present switch. Maybe not support by hardware, then function will always return true. + */ + virtual bool isPresent(void); + + private: + DigitalIn _cardDetect; + bool _is_initialized; + bd_size_t _block_size; + bd_size_t _erase_size; + bd_size_t _sectors; + uint32_t _init_ref_count; + SD_Cardinfo_t _cardInfo; + uint32_t _card_type; + + PlatformMutex _mutex; + virtual void lock() + { + _mutex.lock(); + } + + virtual void unlock() + { + _mutex.unlock(); + } + + bool _is_valid_trim(bd_addr_t addr, bd_size_t size); +}; + +} // namespace mbed + +#endif /* MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ */ diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.c b/TARGET_STM/TARGET_STM32F4/sdio_device.c new file mode 100644 index 0000000..6979c71 --- /dev/null +++ b/TARGET_STM/TARGET_STM32F4/sdio_device.c @@ -0,0 +1,538 @@ +/** + * + * This sourcecode is derived from STMicroelectronics CubeMX generated code. + * It is modified to work with mbed RTOS. + * + ****************************************************************************** + * @file bsp_driver_sd.c for F4 (based on stm324x9i_eval_sd.c) + * @brief This file includes a generic uSD card driver. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include "sdio_device.h" +#include "platform/mbed_error.h" + +/* Extern variables ---------------------------------------------------------*/ + +SD_HandleTypeDef hsd; +DMA_HandleTypeDef hdma_sdio_rx; +DMA_HandleTypeDef hdma_sdio_tx; + +// simple flags for DMA pending signaling +volatile uint8_t SD_DMA_ReadPendingState = SD_TRANSFER_OK; +volatile uint8_t SD_DMA_WritePendingState = SD_TRANSFER_OK; + +/* DMA Handlers are global, there is only one SDIO interface */ + +/** +* @brief This function handles SDIO global interrupt. +*/ +void _SDIO_IRQHandler(void) +{ + HAL_SD_IRQHandler(&hsd); +} + +/** +* @brief This function handles DMAx stream_n global interrupt. DMA Rx +*/ +void _DMA_Stream_Rx_IRQHandler(void) +{ + HAL_DMA_IRQHandler(hsd.hdmarx); +} + +/** +* @brief This function handles DMAx stream_n global interrupt. DMA Tx +*/ +void _DMA_Stream_Tx_IRQHandler(void) +{ + HAL_DMA_IRQHandler(hsd.hdmatx); +} + +/** + * + * @param hsd: Handle for SD handle Structure definition + */ +void HAL_SD_MspInit(SD_HandleTypeDef *hsd) +{ + IRQn_Type IRQn; + GPIO_InitTypeDef GPIO_InitStruct; + + if (hsd->Instance == SDIO) + { + /* Peripheral clock enable */ + __HAL_RCC_SDIO_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* Enable GPIOs clock */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /**SDIO GPIO Configuration + PC12 ------> SDIO_CK + PC11 ------> SDIO_D3 + PC10 ------> SDIO_D2 + PD2 ------> SDIO_CMD + PC9 ------> SDIO_D1 + PC8 ------> SDIO_D0 + */ + GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* NVIC configuration for SDIO interrupts */ + IRQn = SDIO_IRQn; + HAL_NVIC_SetPriority(IRQn, 0x0E, 0); + NVIC_SetVector(IRQn, (uint32_t)&_SDIO_IRQHandler); + HAL_NVIC_EnableIRQ(IRQn); + + /* SDIO DMA Init */ + /* SDIO_RX Init */ + hdma_sdio_rx.Instance = DMA2_Stream3; + hdma_sdio_rx.Init.Channel = DMA_CHANNEL_4; + hdma_sdio_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_sdio_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdio_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdio_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdio_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdio_rx.Init.Mode = DMA_PFCTRL; + hdma_sdio_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_sdio_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sdio_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sdio_rx.Init.MemBurst = DMA_MBURST_INC4; + hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4; + if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK) + { + error("SDIO DMA Init error at %d in %s", __FILE__, __LINE__); + } + + __HAL_LINKDMA(hsd, hdmarx, hdma_sdio_rx); + + /* Deinitialize the stream for new transfer */ + HAL_DMA_DeInit(&hdma_sdio_rx); + + /* Configure the DMA stream */ + HAL_DMA_Init(&hdma_sdio_rx); + + /* SDIO_TX Init */ + hdma_sdio_tx.Instance = DMA2_Stream6; + hdma_sdio_tx.Init.Channel = DMA_CHANNEL_4; + hdma_sdio_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_sdio_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdio_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdio_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdio_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdio_tx.Init.Mode = DMA_PFCTRL; + hdma_sdio_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_sdio_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sdio_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sdio_tx.Init.MemBurst = DMA_MBURST_INC4; + hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4; + if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK) + { + error("SDIO DMA Init error at %d in %s", __FILE__, __LINE__); + } + + __HAL_LINKDMA(hsd, hdmatx, hdma_sdio_tx); + + /* Deinitialize the stream for new transfer */ + HAL_DMA_DeInit(&hdma_sdio_tx); + + /* Configure the DMA stream */ + HAL_DMA_Init(&hdma_sdio_tx); + + /* Enable NVIC for DMA transfer complete interrupts */ + IRQn = DMA2_Stream3_IRQn; + NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Rx_IRQHandler); + HAL_NVIC_SetPriority(IRQn, 0x0F, 0); + HAL_NVIC_EnableIRQ(IRQn); + + IRQn = DMA2_Stream6_IRQn; + NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Tx_IRQHandler); + HAL_NVIC_SetPriority(IRQn, 0x0F, 0); + HAL_NVIC_EnableIRQ(IRQn); + } +} + +/** + * + * @param hsd: Handle for SD handle Structure definition + */ +void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) +{ + + if (hsd->Instance == SDIO) + { + /* Peripheral clock disable */ + __HAL_RCC_SDIO_CLK_DISABLE(); + + /**SDIO GPIO Configuration + PC12 ------> SDIO_CK + PC11 ------> SDIO_D3 + PC10 ------> SDIO_D2 + PD2 ------> SDIO_CMD + PC9 ------> SDIO_D1 + PC8 ------> SDIO_D0 + */ + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8); + + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); + + /* SDIO DMA DeInit */ + HAL_DMA_DeInit(hsd->hdmarx); + HAL_DMA_DeInit(hsd->hdmatx); + } +} + +/** + * @brief DeInitializes the SD MSP. + * @param hsd: SD handle + * @param Params : pointer on additional configuration parameters, can be NULL. + */ +__weak void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params) +{ + static DMA_HandleTypeDef dma_rx_handle; + static DMA_HandleTypeDef dma_tx_handle; + + /* Disable NVIC for DMA transfer complete interrupts */ + HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn); + HAL_NVIC_DisableIRQ(DMA2_Stream6_IRQn); + + /* Deinitialize the stream for new transfer */ + dma_rx_handle.Instance = DMA2_Stream3; + HAL_DMA_DeInit(&dma_rx_handle); + + /* Deinitialize the stream for new transfer */ + dma_tx_handle.Instance = DMA2_Stream6; + HAL_DMA_DeInit(&dma_tx_handle); + + /* Disable NVIC for SDIO interrupts */ + HAL_NVIC_DisableIRQ(SDIO_IRQn); + + /* Disable SDIO clock */ + __HAL_RCC_SDIO_CLK_DISABLE(); +} + +/** + * @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 errorstate = HAL_SD_ERROR_NONE; + + if ((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + return HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + } + + /* Send CMD55 APP_CMD with argument as card's RCA.*/ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if (errorstate != HAL_OK) + { + return errorstate; + } + + /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ + errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U); + if (errorstate != HAL_OK) + { + return errorstate; + } + + hsd->Init.BusWide = SDIO_BUS_WIDE_4B; + SDIO_Init(hsd->Instance, hsd->Init); + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Initializes the SD card device. + * @retval SD status + */ +uint8_t SD_Init(void) +{ + uint8_t sd_state = MSD_OK; + + hsd.Instance = SDIO; + hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; + hsd.Init.BusWide = SDIO_BUS_WIDE_1B; + hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; + hsd.Init.ClockDiv = 0; + + /* HAL SD initialization */ + sd_state = HAL_SD_Init(&hsd); + /* Configure SD Bus width (4 bits mode selected) */ + if (sd_state == MSD_OK) + { + /* Enable wide operation */ + if (SD_WideBus_Enable(&hsd) != HAL_OK) + { + sd_state = MSD_ERROR; + } + } + + return sd_state; +} + +/** + * @brief DeInitializes the SD card device. + * @retval SD status + */ +uint8_t SD_DeInit(void) +{ + uint8_t sd_state = MSD_OK; + + hsd.Instance = SDIO; + + /* HAL SD deinitialization */ + if (HAL_SD_DeInit(&hsd) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + /* Msp SD deinitialization */ + hsd.Instance = SDIO; + SD_MspDeInit(&hsd, NULL); + + return sd_state; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @param Timeout: Timeout for read operation + * @retval SD status + */ +uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @param Timeout: Timeout for write operation + * @retval SD status + */ +uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @retval SD status + */ +uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; + + /* Read block(s) in DMA transfer mode */ + if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK) + { + sd_state = MSD_ERROR; + SD_DMA_ReadPendingState = SD_TRANSFER_OK; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @retval SD status + */ +uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + SD_DMA_WritePendingState = SD_TRANSFER_BUSY; + + /* Write block(s) in DMA transfer mode */ + if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK) + { + sd_state = MSD_ERROR; + SD_DMA_WritePendingState = SD_TRANSFER_OK; + } + + return sd_state; +} + +/** + * @brief Erases the specified memory area of the given SD card. + * @param StartAddr: Start byte address + * @param EndAddr: End byte address + * @retval SD status + */ +uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Gets the current SD card data status. + * @param None + * @retval Data transfer state. + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_GetCardState(void) +{ + return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); +} + +/** + * @brief Get SD information about specific SD card. + * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure + * @retval None + */ +void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) +{ + /* Get SD card Information, copy structure for portability */ + HAL_SD_CardInfoTypeDef HAL_CardInfo; + + HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo); + + if (CardInfo) + { + CardInfo->CardType = HAL_CardInfo.CardType; + CardInfo->CardVersion = HAL_CardInfo.CardVersion; + CardInfo->Class = HAL_CardInfo.Class; + CardInfo->RelCardAdd = HAL_CardInfo.RelCardAdd; + CardInfo->BlockNbr = HAL_CardInfo.BlockNbr; + CardInfo->BlockSize = HAL_CardInfo.BlockSize; + CardInfo->LogBlockNbr = HAL_CardInfo.LogBlockNbr; + CardInfo->LogBlockSize = HAL_CardInfo.LogBlockSize; + } +} + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_DMA_ReadPending(void) +{ + return SD_DMA_ReadPendingState; +} + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_DMA_WritePending(void) +{ + return SD_DMA_WritePendingState; +} + +/** + * @brief Rx Transfer completed callbacks + * @param hsd Pointer SD handle + * @retval None + */ +void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) +{ + SD_DMA_ReadPendingState = SD_TRANSFER_OK; +} + +/** + * @brief Tx Transfer completed callbacks + * @param hsd Pointer to SD handle + * @retval None + */ +void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) +{ + SD_DMA_WritePendingState = SD_TRANSFER_OK; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.h b/TARGET_STM/TARGET_STM32F4/sdio_device.h new file mode 100644 index 0000000..edd20ac --- /dev/null +++ b/TARGET_STM/TARGET_STM32F4/sdio_device.h @@ -0,0 +1,126 @@ +/** + * + * This sourcecode is derived from STMicroelectronics CubeMX generated code. + * It is modified to work with mbed RTOS. + * + ****************************************************************************** + * @file bsp_driver_sd.h for F4 (based on stm324x9i_eval_sd.h) + * @brief This file contains the common defines and functions prototypes for + * the bsp_driver_sd.c driver. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __STM32F4_SD_H +#define __STM32F4_SD_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "stm32f4xx_hal.h" + + /* Typedefs */ + + typedef struct + { + uint32_t CardType; /* Specifies the card Type */ + uint32_t CardVersion; /* Specifies the card version */ + uint32_t Class; /* Specifies the class of the card class */ + uint32_t RelCardAdd; /* Specifies the Relative Card Address */ + uint32_t BlockNbr; /* Specifies the Card Capacity in blocks */ + uint32_t BlockSize; /* Specifies one block size in bytes */ + uint32_t LogBlockNbr; /* Specifies the Card logical Capacity in blocks */ + uint32_t LogBlockSize; /* Specifies logical block size in bytes */ + } SD_Cardinfo_t; + + /* External Global var */ + + extern SD_HandleTypeDef hsd; + +/* Exported types */ +/** + * @brief SD Card information structure + */ +#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef + +/* Exported constants */ +/** + * @brief SD status structure definition + */ +#define MSD_OK ((uint8_t)0x00) +#define MSD_ERROR ((uint8_t)0x01) + +/** + * @brief SD transfer state definition + */ +#define SD_TRANSFER_OK ((uint8_t)0x00) +#define SD_TRANSFER_BUSY ((uint8_t)0x01) + + /* Exported functions */ + uint8_t SD_Init(void); + uint8_t SD_DeInit(void); + uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); + uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); + uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); + uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); + uint8_t SD_DMA_ReadPending(void); + uint8_t SD_DMA_WritePending(void); + uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr); + + uint8_t SD_GetCardState(void); + void SD_GetCardInfo(SD_Cardinfo_t *CardInfo); + + /* callback function for DMA Rx/Tx completete, called by HAL SDIO interrupt handler */ + void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd); + void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd); + +#ifdef __cplusplus +} +#endif + +#endif /* __STM32F4_SD_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/TESTS/blockdevice/basic/main.cpp b/TESTS/blockdevice/basic/main.cpp new file mode 100644 index 0000000..709c07b --- /dev/null +++ b/TESTS/blockdevice/basic/main.cpp @@ -0,0 +1,119 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include +#include + +using namespace utest::v1; + +// test configuration +#ifndef MBED_TEST_BLOCKDEVICE +#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice +#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; +#endif + +#ifndef MBED_TEST_BLOCKDEVICE_DECL +#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd +#endif + +#ifndef MBED_TEST_BUFFER +#define MBED_TEST_BUFFER 8192 +#endif + +#ifndef MBED_TEST_TIMEOUT +#define MBED_TEST_TIMEOUT 120 +#endif + + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_BLOCKDEVICE) + +MBED_TEST_BLOCKDEVICE_DECL; + +size_t size; +uint8_t buffer[MBED_TEST_BUFFER]; +uint8_t rbuffer[MBED_TEST_BUFFER]; +uint8_t wbuffer[MBED_TEST_BUFFER]; + + +// tests + +// test multiple init-deinit sequences +void test_init_deinit() +{ + for (int repeatCount=0; repeatCount < 10; repeatCount++) + { + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); + } +} + +void test_init_deinit_stacked() +{ + for (int repeatCount=0; repeatCount < 10; repeatCount++) + { + // multiple init + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + // same number of deinit + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); + } +} + + +// test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Init/Deinit test", test_init_deinit), + Case("Init/Deinit stacked test", test_init_deinit_stacked) +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/filesystem/dirs/main.cpp b/TESTS/filesystem/dirs/main.cpp new file mode 100644 index 0000000..fcb055a --- /dev/null +++ b/TESTS/filesystem/dirs/main.cpp @@ -0,0 +1,500 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include +#include + +using namespace utest::v1; + +// test configuration +#ifndef MBED_TEST_FILESYSTEM +#define MBED_TEST_FILESYSTEM FATFileSystem +#endif + +#ifndef MBED_TEST_FILESYSTEM_DECL +#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") +#endif + +#ifndef MBED_TEST_BLOCKDEVICE +#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice +#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; +#endif + +#ifndef MBED_TEST_BLOCKDEVICE_DECL +#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd +#endif + +#ifndef MBED_TEST_FILES +#define MBED_TEST_FILES 4 +#endif + +#ifndef MBED_TEST_DIRS +#define MBED_TEST_DIRS 4 +#endif + +#ifndef MBED_TEST_BUFFER +#define MBED_TEST_BUFFER 8192 +#endif + +#ifndef MBED_TEST_TIMEOUT +#define MBED_TEST_TIMEOUT 120 +#endif + + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_FILESYSTEM) +#include INCLUDE(MBED_TEST_BLOCKDEVICE) + +MBED_TEST_FILESYSTEM_DECL; +MBED_TEST_BLOCKDEVICE_DECL; + +Dir dir[MBED_TEST_DIRS]; +File file[MBED_TEST_FILES]; +DIR *dd[MBED_TEST_DIRS]; +FILE *fd[MBED_TEST_FILES]; +struct dirent ent; +struct dirent *ed; +size_t size; +uint8_t buffer[MBED_TEST_BUFFER]; +uint8_t rbuffer[MBED_TEST_BUFFER]; +uint8_t wbuffer[MBED_TEST_BUFFER]; + + +// tests + +void test_directory_tests() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = MBED_TEST_FILESYSTEM::format(&bd); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_root_directory() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "/"); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_directory_creation() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("potato", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_file_creation() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "burito", O_CREAT | O_WRONLY); + TEST_ASSERT_EQUAL(0, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void dir_file_check(char *list[], uint32_t elements) +{ + int res; + while (1) { + res = dir[0].read(&ent); + if (0 == res) { + break; + } + for (int i = 0; i < elements ; i++) { + res = strcmp(ent.d_name, list[i]); + if (0 == res) { + res = ent.d_type; + if ((DT_DIR != res) && (DT_REG != res)) { + TEST_ASSERT(1); + } + break; + } else if ( i == elements) { + TEST_ASSERT_EQUAL(0, res); + } + } + } +} + +void test_directory_iteration() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "/"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"potato", "burito", ".", ".."}; + + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_directory_failures() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("potato", 0777); + TEST_ASSERT_EQUAL(-EEXIST, res); + res = dir[0].open(&fs, "tomato"); + TEST_ASSERT_EQUAL(-ENOTDIR, res); + res = dir[0].open(&fs, "burito"); + TEST_ASSERT_NOT_EQUAL(0, res); + res = file[0].open(&fs, "tomato", O_RDONLY); + TEST_ASSERT_EQUAL(-ENOENT, res); + res = file[0].open(&fs, "potato", O_RDONLY); + TEST_ASSERT_NOT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_nested_directories() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("potato/baked", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("potato/sweet", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("potato/fried", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "/"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"potato", "baked", "sweet", "fried", ".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_multi_block_directory() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("cactus", 0777); + TEST_ASSERT_EQUAL(0, res); + for (int i = 0; i < 128; i++) { + sprintf((char *)buffer, "cactus/test%d", i); + res = fs.mkdir((char *)buffer, 0777); + TEST_ASSERT_EQUAL(0, res); + } + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "cactus"); + TEST_ASSERT_EQUAL(0, res); + +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + char *dir_list[] = {".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); +#endif + + for (int i = 0; i < 128; i++) { + sprintf((char *)buffer, "test%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + } + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_directory_remove() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("potato"); + TEST_ASSERT_NOT_EQUAL(0, res); + res = fs.remove("potato/sweet"); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("potato/baked"); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("potato/fried"); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "potato"); + TEST_ASSERT_EQUAL(0, res); + +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + char *dir_list[] = {".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); +#endif + + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("potato"); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "/"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"burito", "cactus", ".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_directory_rename() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("coldpotato", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("coldpotato/baked", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("coldpotato/sweet", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("coldpotato/fried", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("coldpotato", "hotpotato"); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "hotpotato"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("warmpotato", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("warmpotato/mushy", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("hotpotato", "warmpotato"); + TEST_ASSERT_NOT_EQUAL(0, res); + res = fs.remove("warmpotato/mushy"); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("warmpotato"); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("hotpotato", "warmpotato"); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "warmpotato"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("coldpotato", 0777); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("warmpotato/baked", "coldpotato/baked"); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("warmpotato/sweet", "coldpotato/sweet"); + TEST_ASSERT_EQUAL(0, res); + res = fs.rename("warmpotato/fried", "coldpotato/fried"); + TEST_ASSERT_EQUAL(0, res); + res = fs.remove("coldpotato"); + TEST_ASSERT_NOT_EQUAL(0, res); + res = fs.remove("warmpotato"); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "coldpotato"); + TEST_ASSERT_EQUAL(0, res); + char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; + dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + + + +// test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Directory tests", test_directory_tests), + Case("Root directory", test_root_directory), + Case("Directory creation", test_directory_creation), + Case("File creation", test_file_creation), + Case("Directory iteration", test_directory_iteration), + Case("Directory failures", test_directory_failures), + Case("Nested directories", test_nested_directories), + Case("Multi-block directory", test_multi_block_directory), + Case("Directory remove", test_directory_remove), + Case("Directory rename", test_directory_rename), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/filesystem/files/main.cpp b/TESTS/filesystem/files/main.cpp new file mode 100644 index 0000000..ed4d242 --- /dev/null +++ b/TESTS/filesystem/files/main.cpp @@ -0,0 +1,337 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include +#include + +using namespace utest::v1; + +// test configuration +#ifndef MBED_TEST_FILESYSTEM +#define MBED_TEST_FILESYSTEM FATFileSystem +#endif + +#ifndef MBED_TEST_FILESYSTEM_DECL +#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") +#endif + +#ifndef MBED_TEST_BLOCKDEVICE +#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice +#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; +#endif + +#ifndef MBED_TEST_BLOCKDEVICE_DECL +#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd +#endif + +#ifndef MBED_TEST_FILES +#define MBED_TEST_FILES 4 +#endif + +#ifndef MBED_TEST_DIRS +#define MBED_TEST_DIRS 4 +#endif + +#ifndef MBED_TEST_BUFFER +#define MBED_TEST_BUFFER 8192 +#endif + +#ifndef MBED_TEST_TIMEOUT +#define MBED_TEST_TIMEOUT 120 +#endif + + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_FILESYSTEM) +#include INCLUDE(MBED_TEST_BLOCKDEVICE) + +MBED_TEST_FILESYSTEM_DECL; +MBED_TEST_BLOCKDEVICE_DECL; + +Dir dir[MBED_TEST_DIRS]; +File file[MBED_TEST_FILES]; +DIR *dd[MBED_TEST_DIRS]; +FILE *fd[MBED_TEST_FILES]; +struct dirent ent; +struct dirent *ed; +size_t size; +uint8_t buffer[MBED_TEST_BUFFER]; +uint8_t rbuffer[MBED_TEST_BUFFER]; +uint8_t wbuffer[MBED_TEST_BUFFER]; + +static char file_counter = 0; +const char *filenames[] = {"smallavacado", "mediumavacado", "largeavacado", + "blockfile", "bigblockfile", "hello", ".", ".." + }; + +// tests + +void test_file_tests() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = MBED_TEST_FILESYSTEM::format(&bd); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_simple_file_test() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello", O_WRONLY | O_CREAT); + TEST_ASSERT_EQUAL(0, res); + size = strlen("Hello World!\n"); + memcpy(wbuffer, "Hello World!\n", size); + res = file[0].write(wbuffer, size); + TEST_ASSERT_EQUAL(size, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + size = strlen("Hello World!\n"); + res = file[0].read(rbuffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(rbuffer, wbuffer, size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +template +void test_write_file_test() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + size_t size = file_size; + size_t chunk = write_size; + srand(0); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, filenames[file_counter], O_WRONLY | O_CREAT); + TEST_ASSERT_EQUAL(0, res); + for (size_t i = 0; i < size; i += chunk) { + chunk = (chunk < size - i) ? chunk : size - i; + for (size_t b = 0; b < chunk; b++) { + buffer[b] = rand() & 0xff; + } + res = file[0].write(buffer, chunk); + TEST_ASSERT_EQUAL(chunk, res); + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + size_t size = file_size; + size_t chunk = read_size; + srand(0); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, filenames[file_counter], O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + for (size_t i = 0; i < size; i += chunk) { + chunk = (chunk < size - i) ? chunk : size - i; + res = file[0].read(buffer, chunk); + TEST_ASSERT_EQUAL(chunk, res); + for (size_t b = 0; b < chunk && i + b < size; b++) { + res = buffer[b]; + TEST_ASSERT_EQUAL(rand() & 0xff, res); + } + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + file_counter++; + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_non_overlap_check() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + size_t size = 32; + size_t chunk = 29; + srand(0); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "smallavacado", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + for (size_t i = 0; i < size; i += chunk) { + chunk = (chunk < size - i) ? chunk : size - i; + res = file[0].read(buffer, chunk); + TEST_ASSERT_EQUAL(chunk, res); + for (size_t b = 0; b < chunk && i + b < size; b++) { + res = buffer[b]; + TEST_ASSERT_EQUAL(rand() & 0xff, res); + } + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + size_t size = 8192; + size_t chunk = 29; + srand(0); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "mediumavacado", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + for (size_t i = 0; i < size; i += chunk) { + chunk = (chunk < size - i) ? chunk : size - i; + res = file[0].read(buffer, chunk); + TEST_ASSERT_EQUAL(chunk, res); + for (size_t b = 0; b < chunk && i + b < size; b++) { + res = buffer[b]; + TEST_ASSERT_EQUAL(rand() & 0xff, res); + } + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + { + size_t size = 262144; + size_t chunk = 29; + srand(0); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "largeavacado", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + for (size_t i = 0; i < size; i += chunk) { + chunk = (chunk < size - i) ? chunk : size - i; + res = file[0].read(buffer, chunk); + TEST_ASSERT_EQUAL(chunk, res); + for (size_t b = 0; b < chunk && i + b < size; b++) { + res = buffer[b]; + TEST_ASSERT_EQUAL(rand() & 0xff, res); + } + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_dir_check() +{ + + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "/"); + TEST_ASSERT_EQUAL(0, res); + int numFiles = sizeof(filenames) / sizeof(filenames[0]); + // Check the filenames in directory + while (1) { + res = dir[0].read(&ent); + if (0 == res) { + break; + } + for (int i = 0; i < numFiles ; i++) { + res = strcmp(ent.d_name, filenames[i]); + if (0 == res) { + res = ent.d_type; + if ((DT_REG != res) && (DT_DIR != res)) { + TEST_ASSERT(1); + } + break; + } else if ( i == numFiles) { + TEST_ASSERT_EQUAL(0, res); + } + } + } + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + + +// test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("File tests", test_file_tests), + Case("Simple file test", test_simple_file_test), + Case("Small file test", test_write_file_test<32, 31, 29>), + Case("Medium file test", test_write_file_test<8192, 31, 29>), + Case("Large file test", test_write_file_test<262144, 31, 29>), + Case("Block Size file test", test_write_file_test<9000, 512, 512>), + Case("Multiple block size file test", test_write_file_test<26215, MBED_TEST_BUFFER, MBED_TEST_BUFFER>), + Case("Non-overlap check", test_non_overlap_check), + Case("Dir check", test_dir_check), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/filesystem/fopen/fopen.cpp b/TESTS/filesystem/fopen/fopen.cpp new file mode 100644 index 0000000..03c6fda --- /dev/null +++ b/TESTS/filesystem/fopen/fopen.cpp @@ -0,0 +1,1621 @@ +/* + * mbed Microcontroller Library + * Copyright (c) 2006-2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** @file fopen.cpp Test cases to POSIX file fopen() interface. + * + * Please consult the documentation under the test-case functions for + * a description of the individual test case. + */ + +#include "mbed.h" +#include "mbed_config.h" +#include "SDIOBlockDevice.h" +#include "FATFileSystem.h" +#include "fsfat_debug.h" +#include "fsfat_test.h" +#include "utest/utest.h" +#include "unity/unity.h" +#include "greentea-client/test_env.h" + +#include +#include +#include /*rand()*/ +#include +#include +/* mbed_retarget.h is included after errno.h so symbols are mapped to + * consistent values for all toolchains */ +#include "platform/mbed_retarget.h" + +using namespace utest::v1; + +/// @cond FSFAT_DOXYGEN_DISABLE +#ifdef FSFAT_DEBUG +#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 3000 +#else +#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 1000 +#endif +/// @endcond + + +/* DEVICE_SPI + * This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support. + * + * MBED_CONF_APP_FSFAT_SDCARD_INSTALLED + * For testing purposes, an SDCard must be installed on the target for the test cases in this file to succeed. + * If the target has an SD card installed then the MBED_CONF_APP_FSFAT_SDCARD_INSTALLED will be generated + * from the mbed_app.json, which includes the line + * { + * "config": { + * "UART_RX": "D0", + * <<< lines removed >>> + * "DEVICE_SPI": 1, + * "FSFAT_SDCARD_INSTALLED": 1 + * }, + * <<< lines removed >>> + */ + +#if defined(DEVICE_SPI) && ( defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) || (MBED_CONF_SD_FSFAT_SDCARD_INSTALLED)) +static char fsfat_fopen_utest_msg_g[FSFAT_UTEST_MSG_BUF_SIZE]; +#define FSFAT_FOPEN_TEST_MOUNT_PT_NAME "sd" +#define FSFAT_FOPEN_TEST_MOUNT_PT_PATH "/" FSFAT_FOPEN_TEST_MOUNT_PT_NAME +#define FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1 64 +#define FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH 20 +static const char *sd_badfile_path = "/sd/badfile.txt"; +static const char *sd_testfile_path = "/sd/test.txt"; + +SDIOBlockDevice sd(); +FATFileSystem fs("sd", &sd); + +#define FSFAT_FOPEN_TEST_01 fsfat_fopen_test_01 +#define FSFAT_FOPEN_TEST_02 fsfat_fopen_test_02 +#define FSFAT_FOPEN_TEST_03 fsfat_fopen_test_03 +#define FSFAT_FOPEN_TEST_04 fsfat_fopen_test_04 +#define FSFAT_FOPEN_TEST_05 fsfat_fopen_test_05 +#define FSFAT_FOPEN_TEST_06 fsfat_fopen_test_06 +#define FSFAT_FOPEN_TEST_07 fsfat_fopen_test_07 +#define FSFAT_FOPEN_TEST_08 fsfat_fopen_test_08 +#define FSFAT_FOPEN_TEST_09 fsfat_fopen_test_09 +#define FSFAT_FOPEN_TEST_10 fsfat_fopen_test_10 +#define FSFAT_FOPEN_TEST_11 fsfat_fopen_test_11 +#define FSFAT_FOPEN_TEST_12 fsfat_fopen_test_12 +#define FSFAT_FOPEN_TEST_13 fsfat_fopen_test_13 +#define FSFAT_FOPEN_TEST_14 fsfat_fopen_test_14 +#define FSFAT_FOPEN_TEST_15 fsfat_fopen_test_15 +#define FSFAT_FOPEN_TEST_16 fsfat_fopen_test_16 +#define FSFAT_FOPEN_TEST_17 fsfat_fopen_test_17 +#define FSFAT_FOPEN_TEST_18 fsfat_fopen_test_18 +#define FSFAT_FOPEN_TEST_19 fsfat_fopen_test_19 +#define FSFAT_FOPEN_TEST_20 fsfat_fopen_test_20 +#define FSFAT_FOPEN_TEST_21 fsfat_fopen_test_21 +#define FSFAT_FOPEN_TEST_22 fsfat_fopen_test_22 +#define FSFAT_FOPEN_TEST_23 fsfat_fopen_test_23 +#define FSFAT_FOPEN_TEST_24 fsfat_fopen_test_24 +#define FSFAT_FOPEN_TEST_25 fsfat_fopen_test_25 +#define FSFAT_FOPEN_TEST_26 fsfat_fopen_test_26 +#define FSFAT_FOPEN_TEST_27 fsfat_fopen_test_27 +#define FSFAT_FOPEN_TEST_28 fsfat_fopen_test_28 +#define FSFAT_FOPEN_TEST_29 fsfat_fopen_test_29 +#define FSFAT_FOPEN_TEST_30 fsfat_fopen_test_30 + + +/* support functions */ + +/* + * open tests that focus on testing fopen() + * fsfat_handle_t fopen(const char* filename, char* data, size_t* len, fsfat_key_desc_t* kdesc) + */ + +/* file data for test_01 */ +static fsfat_kv_data_t fsfat_fopen_test_01_kv_data[] = { + { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"}, + { NULL, NULL}, +}; + + +/** @brief + * Split a file path into its component parts, setting '/' characters to '\0', and returning + * pointers to the file path components in the parts array. For example, if + * filepath = "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt" then + * *parts[0] = "sd" + * *parts[1] = "fopentst" + * *parts[2] = "hello" + * *parts[3] = "world" + * *parts[4] = "animal" + * *parts[5] = "wobbly" + * *parts[6] = "dog" + * *parts[7] = "foot" + * *parts[8] = "frontlft.txt" + * parts[9] = NULL + * + * ARGUMENTS + * @param filepath IN file path string to split into component parts. Expected to start with '/' + * @param parts IN OUT array to hold pointers to parts + * @param num IN number of components available in parts + * + * @return On success, this returns the number of components in the filepath Returns number of compoee + */ +static int32_t fsfat_filepath_split(char *filepath, char *parts[], uint32_t num) +{ + uint32_t i = 0; + int32_t ret = -1; + char *z = filepath; + + while (i < num && *z != '\0') { + if (*z == '/' ) { + *z = '\0'; + parts[i] = ++z; + i++; + } else { + z++; + } + } + if (*z == '\0' && i > 0) { + ret = (int32_t) i; + } + return ret; +} + + +/** @brief + * remove all directories and file in the given filepath + * + * ARGUMENTS + * @param filepath IN file path string to split into component parts. Expected to start with '/' + * + * @return On success, this returns 0, otherwise < 0 is returned; + */ +int32_t fsfat_filepath_remove_all(char *filepath) +{ + int32_t ret = -1; + int32_t len = 0; + char *fpathbuf = NULL; + char *pos = NULL; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + len = strlen(filepath); + fpathbuf = (char *) malloc(len + 1); + if (fpathbuf == NULL) { + FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); + return ret; + } + memset(fpathbuf, 0, len + 1); + memcpy(fpathbuf, filepath, len); + + /* delete the leaf node first, and then successively parent directories. */ + pos = fpathbuf + strlen(fpathbuf); + while (pos != fpathbuf) { + /* If the remaining file path is the mount point path then finish as the mount point cannot be removed */ + if (strlen(fpathbuf) == strlen(FSFAT_FOPEN_TEST_MOUNT_PT_PATH)) { + if ( strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) { + break; + } + } + ret = remove(fpathbuf); + pos = strrchr(fpathbuf, '/'); + *pos = '\0'; + } + if (fpathbuf) { + free(fpathbuf); + } + return ret; +} + + +/** @brief + * make all directories in the given filepath. Do not create the file if present at end of filepath + * + * ARGUMENTS + * @param filepath IN file path containing directories and file + * @param do_asserts IN set to true if function should assert on errors + * + * @return On success, this returns 0, otherwise < 0 is returned; + */ +static int32_t fsfat_filepath_make_dirs(char *filepath, bool do_asserts) +{ + int32_t i = 0; + int32_t num_parts = 0; + int32_t len = 0; + int32_t ret = -1; + char *fpathbuf = NULL; + char *buf = NULL; + int pos = 0; + char *parts[FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH]; + + FSFAT_DBGLOG("%s:entered\n", __func__); + /* find the dirs to create*/ + memset(parts, 0, sizeof(parts)); + len = strlen(filepath); + fpathbuf = (char *) malloc(len + 1); + if (fpathbuf == NULL) { + FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); + return ret; + } + memset(fpathbuf, 0, len + 1); + memcpy(fpathbuf, filepath, len); + num_parts = fsfat_filepath_split(fpathbuf, parts, FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to split filepath (filename=\"%s\", num_parts=%d)\n", __func__, filepath, (int) num_parts); + TEST_ASSERT_MESSAGE(num_parts > 0, fsfat_fopen_utest_msg_g); + + /* Now create the directories on the directory path. + * Skip creating dir for "/sd" which must be present */ + buf = (char *) malloc(strlen(filepath) + 1); + memset(buf, 0, strlen(filepath) + 1); + pos = sprintf(buf, "/%s", parts[0]); + for (i = 1; i < num_parts - 1; i++) { + pos += sprintf(buf + pos, "/%s", parts[i]); + FSFAT_DBGLOG("mkdir(%s)\n", buf); + ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (do_asserts == true) { + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create directory (filepath2=\"%s\", ret=%d, errno=%d)\n", __func__, buf, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + } + } + + if (buf) { + free(buf); + } + if (fpathbuf) { + free(fpathbuf); + } + return ret; +} + + +/* FIX ME: errno not set correctly when error occurs. This indicates a problem with the implementation. */ + +/** @brief + * Basic fopen test which does the following: + * - creates file and writes some data to the value blob. + * - closes the newly created file. + * - opens the file (r-only) + * - reads the file data and checks its the same as the previously created data. + * - closes the opened file + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +static control_t fsfat_fopen_test_01(const size_t call_count) +{ + char *read_buf; + int32_t ret = 0; + size_t len = 0; + fsfat_kv_data_t *node; + FILE *fp = NULL; + + FSFAT_DBGLOG("%s:entered\n", __func__); + (void) call_count; + node = fsfat_fopen_test_01_kv_data; + + /* remove file and directory from a previous failed test run, if present */ + fsfat_filepath_remove_all((char *) node->filename); + + /* create dirs */ + ret = fsfat_filepath_make_dirs((char *) node->filename, true); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + FSFAT_DBGLOG("%s:About to create new file (filename=\"%s\", data=\"%s\")\n", __func__, node->filename, node->value); + fp = fopen(node->filename, "w+"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (filename=\"%s\", data=\"%s\")(ret=%d, errno=%d)\n", __func__, node->filename, + node->value, (int) ret, errno); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + FSFAT_DBGLOG("%s:length of file=%d (filename=\"%s\", data=\"%s\")\n", __func__, (int) len, node->filename, node->value); + len = strlen(node->value); + ret = fwrite((const void *) node->value, len, 1, fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to write file (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, + (int) ret); + TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); + + FSFAT_DBGLOG("Created file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); + ret = fclose(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* now open the newly created key */ + fp = NULL; + fp = fopen(node->filename, "r"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file for reading (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, + node->value, (int) ret); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + len = strlen(node->value) + 1; + read_buf = (char *) malloc(len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to allocated read buffer \n", __func__); + TEST_ASSERT_MESSAGE(read_buf != NULL, fsfat_fopen_utest_msg_g); + + FSFAT_DBGLOG("Opened file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); + memset(read_buf, 0, len); + ret = fread((void *) read_buf, len, 1, fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to read file (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, node->filename, + node->value, read_buf, (int) ret); + /* FIX ME: fread should return the number of items read, not 0 when an item is read successfully. + * This indicates a problem with the implementation, as the correct data is read. The correct assert should be: + * TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); + * The following assert is curerntly used until the implementation is fixed + */ + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* check read data is as expected */ + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: read value data (%s) != expected value data (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", + __func__, read_buf, node->filename, node->value, read_buf, (int) ret); + TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, fsfat_fopen_utest_msg_g); + + if (read_buf) { + free(read_buf); + } + ret = fclose(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: fclose() call failed (ret=%d, errno=%d).\n", __func__, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + return CaseNext; +} + +static fsfat_kv_data_t fsfat_fopen_test_02_data[] = { + FSFAT_INIT_1_TABLE_MID_NODE, + { NULL, NULL}, +}; + +/** + * @brief test to fopen() a pre-existing key and try to write it, which should fail + * as by default pre-existing keys are opened read-only + * + * Basic open test which does the following: + * - creates file with default rw perms and writes some data to the value blob. + * - closes the newly created file. + * - opens the file with the default permissions (read-only) + * - tries to write the file data which should fail because file was not opened with write flag set. + * - closes the opened key + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_02(const size_t call_count) +{ + int32_t ret = -1; + size_t len = 0; + FILE *fp = NULL; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + len = strlen(fsfat_fopen_test_02_data[0].value); + ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + /* by default, owner of key opens with read-only permissions*/ + fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file (filename=\"%s\", ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + len = strlen(fsfat_fopen_test_02_data[0].value); + ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: call to fwrite() succeeded when should have failed for read-only file (filename=\"%s\")(ret=%d).\n", + __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); + TEST_ASSERT_MESSAGE(ret <= 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", + __func__); + TEST_ASSERT_MESSAGE(fclose(fp) == 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + + +/** + * @brief test to fopen() a pre-existing file and try to write it, which should succeed + * because the key was opened read-write permissions explicitly + * + * Basic open test which does the following: + * - creates file with default rw perms and writes some data to the value blob. + * - closes the newly created file. + * - opens the file with the rw permissions (non default) + * - tries to write the file data which should succeeds because file was opened with write flag set. + * - closes the opened key + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_03(const size_t call_count) +{ + int32_t ret = -1; + size_t len = 0; + FILE *fp = NULL; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + len = strlen(fsfat_fopen_test_02_data[0].value); + ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file in store (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + /* opens with read-write permissions*/ + fp = fopen(fsfat_fopen_test_02_data[0].filename, "w+"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file (filename=\"%s\")(ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + len = strlen(fsfat_fopen_test_02_data[0].value); + ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: call to fwrite() failed when should have succeeded (filename=\"%s\", ret=%d).\n", __func__, + fsfat_fopen_test_02_data[0].filename, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", + __func__); + TEST_ASSERT_MESSAGE(fclose(fp) >= 0, fsfat_fopen_utest_msg_g); + + /* clean-up */ + ret = remove(fsfat_fopen_test_02_data[0].filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unable to delete file (filename=%s, ret=%d) .\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + + +/** @brief test to call fopen() with a filename string that exceeds the maximum length + * - chanFS supports the exFAT format which should support 255 char filenames + * - check that filenames of this length can be created + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_04(const size_t call_count) +{ + char filename_good[FSFAT_FILENAME_MAX_LENGTH + 1]; + char filename_bad[FSFAT_FILENAME_MAX_LENGTH + 2]; + int32_t ret = -1; + size_t len = 0; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + memset(filename_good, 0, FSFAT_FILENAME_MAX_LENGTH + 1); + memset(filename_bad, 0, FSFAT_FILENAME_MAX_LENGTH + 2); + ret = fsfat_test_filename_gen(filename_good, FSFAT_FILENAME_MAX_LENGTH); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unable to generate filename_good.\n", __func__); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: filename_good is not the correct length (filename_good=%s, len=%d, expected=%d).\n", __func__, filename_good, + (int) strlen(filename_good), (int) FSFAT_FILENAME_MAX_LENGTH); + TEST_ASSERT_MESSAGE(strlen(filename_good) == FSFAT_FILENAME_MAX_LENGTH, fsfat_fopen_utest_msg_g); + + ret = fsfat_test_filename_gen(filename_bad, FSFAT_FILENAME_MAX_LENGTH + 1); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unable to generate filename_bad.\n", __func__); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), + (int) FSFAT_FILENAME_MAX_LENGTH + 1); + TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSFAT_FILENAME_MAX_LENGTH + 1, fsfat_fopen_utest_msg_g); + + len = strlen(filename_good); + ret = fsfat_test_create(filename_good, filename_good, len); + /* FIXME: + * The current implementation can create file with a filename with 9 chars (more than the 8 restriction of FAT32 Short File Names). + * However, the exFAT 255 char filesnames is not supported and hence the following is commented out. Find out what is + * the supported max filename length and change this testcase according. + * + * FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (filename=%s, ret=%d).\n", __func__, filename_good, (int) ret); + * TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + */ + + len = strlen(filename_bad); + ret = fsfat_test_create(filename_bad, filename_bad, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: created file in store for filename_bad when should have failed (filename=%s, ret=%d).\n", __func__, + filename_bad, (int) ret); + TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); + return CaseNext; +} + + +/// @cond FSFAT_DOXYGEN_DISABLE +typedef struct fsfat_fopen_kv_name_ascii_node { + uint32_t code; + uint32_t f_allowed : 1; +} fsfat_fopen_kv_name_ascii_node; +/// @endcond + +static const uint32_t fsfat_fopen_kv_name_ascii_table_code_sentinel_g = 256; + +/*@brief table recording ascii character codes permitted in kv names */ +static fsfat_fopen_kv_name_ascii_node fsfat_fopen_kv_name_ascii_table[] = { + {0, true}, /* code 0-33 allowed*/ + {34, false}, /* '"' not allowed */ + {35, true}, /* allowed */ + {42, false}, /* '*' not allowed */ + {43, true}, /* allowed */ + {47, false}, /* '/' not allowed */ + {48, true}, /* allowed */ + {58, false}, /* ':' not allowed */ + {59, true}, /* allowed */ + {60, false}, /* '<' not allowed */ + {61, true}, /* allowed */ + {62, false}, /* '?', '>' not allowed */ + {64, true}, /* allowed */ + {92, false}, /* '\' not allowed */ + {93, true}, /* allowed */ + {124, false}, /* '!' not allowed */ + {125, true}, /* allowed */ + {127, false}, /* DEL not allowed */ + {128, true}, /* allowed */ + {fsfat_fopen_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */ +}; + + +/// @cond FSFAT_DOXYGEN_DISABLE +enum fsfat_fopen_kv_name_pos { + fsfat_fopen_kv_name_pos_start = 0x0, + fsfat_fopen_kv_name_pos_mid, + fsfat_fopen_kv_name_pos_end, + fsfat_fopen_kv_name_pos_max +}; +/// @endcond + +/** @brief test to call fopen() with filename that in includes illegal characters + * - the character(s) can be at the beginning of the filename + * - the character(s) can be at the end of the filename + * - the character(s) can be somewhere within the filename string + * - a max-length string of random characters (legal and illegal) + * - a max-length string of random illegal characters only + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_05(const size_t call_count) +{ + bool f_allowed = false; + const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; + const char *basename = "goodfile"; + const char *extname = "txt"; + const size_t basename_len = strlen(basename); + const size_t filename_len = strlen(mnt_pt) + strlen(basename) + strlen(extname) + + 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ + char filename[FSFAT_BUF_MAX_LENGTH]; + size_t len = 0; + uint32_t j = 0; + int32_t ret = 0; + fsfat_fopen_kv_name_ascii_node *node = NULL; + uint32_t pos; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + +#ifdef FSFAT_DEBUG + /* symbol only used why debug is enabled */ + const char *pos_str = NULL; +#endif + + /* create bad keyname strings with invalid character code at start of keyname */ + node = fsfat_fopen_kv_name_ascii_table; + memset(filename, 0, FSFAT_BUF_MAX_LENGTH); + while (node->code != fsfat_fopen_kv_name_ascii_table_code_sentinel_g) { + /* loop over range */ + for (j = node->code; j < (node + 1)->code; j++) { + if ( (j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { + FSFAT_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j); + continue; + } + + /* set the start, mid, last character of the name to the test char code */ + for (pos = (uint32_t) fsfat_fopen_kv_name_pos_start; pos < (uint32_t) fsfat_fopen_kv_name_pos_max; pos++) { + len = snprintf(filename, filename_len + 1, "%s/%s.%s", mnt_pt, basename, extname); + /* overwrite a char at the pos start, mid, end of the filename with an ascii char code (both illegal and legal)*/ + switch (pos) { + case fsfat_fopen_kv_name_pos_start: + filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/ + break; + case fsfat_fopen_kv_name_pos_mid: + /* create bad keyname strings with invalid character code in the middle of keyname */ + filename[5 + basename_len / 2] = (char) j; + break; + case fsfat_fopen_kv_name_pos_end: + /* create bad keyname strings with invalid character code at end of keyname */ + filename[5 + basename_len - 1] = (char) j; + break; + default: + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + break; + } + +#ifdef FSFAT_DEBUG + /* processing only required when debug trace enabled */ + switch (pos) { + case fsfat_fopen_kv_name_pos_start: + pos_str = "start"; + break; + case fsfat_fopen_kv_name_pos_mid: + pos_str = "middle"; + break; + case fsfat_fopen_kv_name_pos_end: + pos_str = "end"; + break; + default: + break; + } +#endif + ret = fsfat_test_create(filename, (const char *) filename, len); + + /* special cases */ + switch (j) { + //case 0 : + //case 46 : + // switch(pos) + // { + // /* for code = 0 (null terminator). permitted at mid and end of string */ + // /* for code = 46 ('.'). permitted at mid and end of string but not at start */ + // case fsfat_fopen_kv_name_pos_start: + // f_allowed = false; + // break; + // case fsfat_fopen_kv_name_pos_mid: + // case fsfat_fopen_kv_name_pos_end: + // default: + // f_allowed = true; + // break; + // } + // break; + default: + f_allowed = node->f_allowed; + break; + } + if (f_allowed == true) { + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file in store when filename contains valid characters (code=%d, ret=%d).\n", __func__, + (int) j, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + /* revert FSFAT_LOG for more trace */ + FSFAT_DBGLOG("Successfully created a file with valid keyname containing ascii character code %d (%c) at the %s of the keyname.\n", + (int) j, (int) j, pos_str); + FSFAT_LOG("%c", '.'); + + ret = fsfat_test_delete(filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to delete file previously created (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + } else { + /*node->f_allowed == false => not allowed to create kv name with ascii code */ + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: created file in store when filename contains an invalid character (code=%d, ret=%d).\n", __func__, (int) j, + (int) ret); + TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); + /* revert FSFAT_LOG for more trace */ + FSFAT_DBGLOG("Successfully failed to create a file with an invalid keyname containing ascii character code %d at the %s of the keyname.\n", + (int) j, pos_str); + FSFAT_LOG("%c", '.'); + } + } + } + node++; + } + + FSFAT_LOG("%c", '\n'); + return CaseNext; +} + + +static const char fsfat_fopen_ascii_illegal_buf_g[] = "\"�'*+,./:;<=>?[\\]|"; + +/** @brief test to call fopen() with filename that in includes + * illegal characters + * - a max-length string of random illegal characters only + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_06(const size_t call_count) +{ + const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; + const char *extname = "txt"; + const size_t filename_len = strlen(mnt_pt) + FSFAT_MAX_FILE_BASENAME + strlen(extname) + + 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ + char filename[FSFAT_BUF_MAX_LENGTH]; + int32_t i = 0; + int32_t j = 0; + uint32_t pos = 0; + uint32_t len = 0; + int32_t ret = -1; + size_t buf_data_max = 0; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + memset(filename, 0, FSFAT_BUF_MAX_LENGTH); + /* create bad keyname strings with invalid character code at start of keyname */ + buf_data_max = strlen(fsfat_fopen_ascii_illegal_buf_g); + + /* generate a number of illegal filenames */ + for (j = 0; i < FSFAT_MAX_FILE_BASENAME; j++) { + /* generate a kv name of illegal chars*/ + len = snprintf(filename, filename_len + 1, "%s/", mnt_pt); + for (i = 0; i < FSFAT_MAX_FILE_BASENAME; i++) { + pos = rand() % (buf_data_max + 1); + len += snprintf(filename + len, filename_len + 1, "%c", fsfat_fopen_ascii_illegal_buf_g[pos]); + + } + len += snprintf(filename + len, filename_len + 1, ".%s", extname); + ret = fsfat_test_create(filename, filename, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: created file when filename contains invalid characters (filename=%s, ret=%d).\n", __func__, filename, + (int) ret); + TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); + } + return CaseNext; +} + + +/** @brief test for errno reporting on a failed fopen()call + * + * This test does the following: + * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. + * - checks that errno is not 0 as there is an error. + * - checks that ferror() returns 1 indicating an error exists. + * + * Note: see NOTE_1 below. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_07(const size_t call_count) +{ + FILE *f = NULL; + int ret = -1; + int errno_val = 0; + const char *filename = sd_badfile_path; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + errno = 0; + /* this is expect to fail as the file doesnt exist */ + f = fopen(filename, "r"); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: opened non-existent file for reading (filename=%s, f=%p).\n", __func__, filename, f); + TEST_ASSERT_MESSAGE(f == NULL, fsfat_fopen_utest_msg_g); + + /* check errno is set correctly */ +#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) + /* Store errno so the current value set is not changed by new function call */ + errno_val = errno; + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: errno has unexpected value (errno != 0 expected) (filename=%s, errno=%d).\n", __func__, filename, errno); + TEST_ASSERT_MESSAGE(errno_val != 0, fsfat_fopen_utest_msg_g); +#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ + return CaseNext; +} + + +/** @brief test for operation of clearerr() and ferror() + * + * The test does the following: + * - opens and then closes a file, but keeps a copy of the FILE pointer fp. + * - set errno to 0. + * - write to the close file with fwrite(fp) which should return 0 (no writes) and set the errno. + * - check the error condition is set with ferror(). + * - clear the error with clearerr(). + * - check the error condition is reset with ferror(). + * + * NOTE_1: GCC/ARMCC support for setting errno + * - Documentation (e.g. fwrite() man page) does not explicity say fwrite() sets errno + * (e.g. for an fwrite() on a read-only file). + * - GCC libc fwrite() appears to set errno as expected. + * - ARMCC & IAR libc fwrite() appears not to set errno. + * + * The following ARMCC documents are silent on whether fwrite() sets errno: + * - "ARM C and C++ Libraries and Floating-Point Support". + * - "RL-ARM User Guide fwrite() section". + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_08(const size_t call_count) +{ + FILE *fp = NULL; + int ret = -1; + int ret_ferror = -1; + const char *filename = sd_testfile_path; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + errno = 0; + fp = fopen(filename, "w+"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file (filename=%s, f=%p).\n", __func__, filename, fp); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + /* close the fp but then try to read or write it */ + ret = fclose(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* open file */ + errno = 0; + fp = fopen(filename, "r"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file for reading (filename=\"%s\", ret=%d)\n", __func__, filename, (int) ret); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + /* Perform fwrite() operation that will fail. */ + errno = 0; + ret = fwrite("42!", 4, 1, fp); + + ret_ferror = ferror(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: ferror() failed to report error (filename=%s, ret_ferror=%d).\n", __func__, filename, (int) ret_ferror); + TEST_ASSERT_MESSAGE(ret_ferror != 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: fwrite successfully wrote to read-only file (filename=%s, ret=%d).\n", __func__, filename, (int) ret); + /* the fwrite() should fail and return 0. */ + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + +#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) + /* check that errno is set. ARMCC appears not to set errno for fwrite() failure. */ + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unexpected zero value for errno (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(errno != 0, fsfat_fopen_utest_msg_g); + + /* check that errno is set to the expected value (this may change differ for different libc's) */ + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: errno != EBADF (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(errno == EBADF, fsfat_fopen_utest_msg_g); +#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ + + /* check clearerr() return clears the error */ + clearerr(fp); + ret = ferror(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: ferror() did not return zero value when error has been cleared (filename=%s, ret=%d).\n", __func__, filename, + (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + fclose(fp); + return CaseNext; +} + + +/** @brief test for operation of ftell() + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_09(const size_t call_count) +{ + FILE *fp = NULL; + int ret = -1; + int32_t len = 0; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + /* create a file of a certain length */ + len = strlen(fsfat_fopen_test_02_data[0].value); + ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); + + errno = 0; + /* Open the file for reading so the file is not truncated to 0 length. */ + fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to open file (filename=%s, fp=%p, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, fp, + errno); + TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); + + errno = 0; + ret = fseek(fp, 0, SEEK_END); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: fseek() failed to SEEK_END (filename=%s, ret=%d, errno=%d).\n", __func__, + fsfat_fopen_test_02_data[0].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + errno = 0; + ret = ftell(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: ftell() failed to report correct offset value (filename=%s, ret=%d, errno=%d).\n", __func__, + fsfat_fopen_test_02_data[0].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == len, fsfat_fopen_utest_msg_g); + + errno = 0; + ret = fclose(fp); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + + +/* file data for test_10 */ +static fsfat_kv_data_t fsfat_fopen_test_10_kv_data[] = { + { "/sd/test_10/testfile.txt", "test_data"}, + { NULL, NULL}, +}; + +/** @brief test for operation of remove() + * + * Performs the following tests: + * 1. test remove() on a file that exists. This should succeed. + * 2. test remove() on a dir that exists. This should succeed. + * 3. test remove() on a file that doesnt exist. This should fail. check errno set. + * 4. test remove() on a dir that doesnt exist. This should fail. check errno set. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_10(const size_t call_count) +{ + char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; + char *pos = NULL; + int32_t ret = -1; + size_t len = 0; + fsfat_kv_data_t *node = fsfat_fopen_test_10_kv_data; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + + /* start from a known state i.e. directory to be created in not present */ + fsfat_filepath_remove_all((char *) node->filename); + + /* (1) */ + errno = 0; + ret = fsfat_filepath_make_dirs((char *) node->filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + len = strlen(node->value); + ret = fsfat_test_create(node->filename, (char *) node->value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + ret = remove(node->filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: delete file operation failed (filename=%s, ret=%d) .\n", __func__, node->filename, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* (3) */ + ret = remove(node->filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: deleted a file that doesn't exist (filename=%s, ret=%d, errno=%d) .\n", __func__, node->filename, (int) ret, + errno); + TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); + + /* (2) */ + memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + memcpy(buf, node->filename, strlen(node->filename)); + pos = strrchr(buf, '/'); + *pos = '\0'; + ret = remove(buf); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: delete directory operation failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, + errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* (4) */ + ret = remove(buf); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: deleted a directory that doesn't exist (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, + errno); + TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + + +/* file data for test_11 */ +static fsfat_kv_data_t fsfat_fopen_test_11_kv_data[] = { + { "/sd/test_11/step0.txt", "test_data"}, + { "/sd/test_11/step1.txt", "test_data"}, + { "/sd/test_11/subdir/step3.txt", "test_data"}, + { NULL, NULL}, +}; + +/** @brief test for operation of rename() + * + * This test does the following: + * 1) test rename() on a file that exists to a new filename within the same directory. + * 2) test rename() on a file that exists to a new filename within a different directory. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_11(const size_t call_count) +{ + int32_t ret = -1; + size_t len = 0; + fsfat_kv_data_t *node = fsfat_fopen_test_11_kv_data; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + + /* start from a known state i.e. directory to be created in not present, files not present */ + while (node->filename != NULL) { + fsfat_filepath_remove_all((char *) node->filename); + node++; + } + + /* create file and directories ready for rename() tests */ + errno = 0; + node = fsfat_fopen_test_11_kv_data; + ret = fsfat_filepath_make_dirs((char *) node->filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + len = strlen(node->value); + ret = fsfat_test_create(node->filename, (char *) node->value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + errno = 0; + node = &fsfat_fopen_test_11_kv_data[2]; + ret = fsfat_filepath_make_dirs((char *) node->filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* (1) */ + ret = rename(fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, + fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* (2) */ + ret = rename(fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, + fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + + +/* file data for test_12 */ +static fsfat_kv_data_t fsfat_fopen_test_12_kv_data[] = { + { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"}, + { "/sd/test_12/testfil2.txt", "testfil2.txt"}, + { "/sd/test_12/testfil3.txt", "testfil3.txt"}, + { "/sd/test_12/testfil4.txt", "testfil4.txt"}, + { "/sd/test_12/testfil5.txt", "testfil5.txt"}, + { NULL, NULL}, +}; + +/** @brief test for operation of readdir(). + * + * Note, rewinddir(), telldir() and seekdir() dont appear to work reliably. + * opendir() not available on ARM/IAR toolchains. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_12(const size_t call_count) +{ + char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; + char *pos = NULL; + int32_t count = 0; + int32_t ret = -1; + size_t len = 0; + DIR *dir; + struct dirent *dp; + fsfat_kv_data_t *node = fsfat_fopen_test_12_kv_data; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + +#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) + + /* start from a known state i.e. directory to be created in not present */ + while (node->filename != NULL) { + fsfat_filepath_remove_all((char *) node->filename); + node++; + } + + /* create a file */ + node = fsfat_fopen_test_12_kv_data; + errno = 0; + ret = fsfat_filepath_make_dirs((char *) node->filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + node = fsfat_fopen_test_12_kv_data; + while (node->filename != NULL) { + len = strlen(node->value); + ret = fsfat_test_create(node->filename, (char *) node->value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + node++; + } + + node = fsfat_fopen_test_12_kv_data; + memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + memcpy(buf, node->filename, strlen(node->filename)); + pos = strrchr(buf, '/'); + *pos = '\0'; + dir = opendir(buf); + + while ((dp = readdir(dir)) != NULL) { + FSFAT_DBGLOG("%s: filename: \"%s\"\n", __func__, dp->d_name); + TEST_ASSERT_MESSAGE(dp != 0, "Error: readdir() failed\n"); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unexpected object name (name=%s, expected=%s).\n", __func__, dp->d_name, + fsfat_fopen_test_12_kv_data[count].value); + TEST_ASSERT_MESSAGE(strncmp(dp->d_name, fsfat_fopen_test_12_kv_data[count].value, + strlen(fsfat_fopen_test_12_kv_data[count].value)) == 0, fsfat_fopen_utest_msg_g); + count++; + } + closedir(dir); + + /* cleanup */ + node = fsfat_fopen_test_12_kv_data; + while (node->filename != NULL) { + fsfat_filepath_remove_all((char *) node->filename); + node++; + } +#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ + return CaseNext; +} + + +/* file data for test_13 */ +static fsfat_kv_data_t fsfat_fopen_test_13_kv_data[] = { + /* a file is included in the filepath even though its not created by the test, + * as the fsfat_filepath_make_dirs() works with it present. */ + { "/sd/test_13/dummy.txt", "testdir"}, + { NULL, NULL}, +}; +/** @brief test for operation of mkdir()/remove() + * + * This test checks that: + * - The mkdir() function successfully creates a directory that is not already present. + * - The mkdir() function returns EEXIST when trying to create a directory thats already present. + * - The remove() function successfully removes a directory that is present. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_13(const size_t call_count) +{ + int32_t ret = 0; + + FSFAT_DBGLOG("%s:entered\n", __func__); + (void) call_count; + + /* start from a known state i.e. directory to be created in not present */ + fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); + + errno = 0; + ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, + (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + /* check that get a suitable error when try to create it again.*/ + errno = 0; + ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: permitted to create directory when already exists (dirname=%s, ret=%d, errno=%d)\n", __func__, + fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); + + /* check errno is as expected */ + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: errno != EEXIST (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, + (int) ret, errno); + TEST_ASSERT_MESSAGE(errno == EEXIST, fsfat_fopen_utest_msg_g); + + ret = fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to remove directory (dirname=%s, ret=%d, errno=%d)\n", __func__, + fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + return CaseNext; +} + +/* file data for test_14 */ +static fsfat_kv_data_t fsfat_fopen_test_14_kv_data[] = { + /* a file is included in the filepath even though its not created by the test, + * as the fsfat_filepath_make_dirs() works with it present. */ + { "/sd/test_14/testfile.txt", "testdata"}, + { NULL, NULL}, +}; + +/** @brief test for operation of stat() + * + * stat() is currently no supported by ARMCC and IAR toolchains libc. + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_14(const size_t call_count) +{ +#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) + + char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; + char *pos = NULL; + int32_t ret = -1; + size_t len = 0; + struct stat file_stat; + fsfat_kv_data_t *node = fsfat_fopen_test_14_kv_data; + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + + TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + + /* start from a known state i.e. directory to be created in not present */ + fsfat_filepath_remove_all((char *) node->filename); + + /* Create file in a directory. */ + errno = 0; + ret = fsfat_filepath_make_dirs((char *) node->filename, false); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + len = strlen(node->value); + ret = fsfat_test_create(node->filename, (char *) node->value, len); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); + + /* Test stat() on the file returns the correct attribute set */ + memset(&file_stat, 0, sizeof(file_stat)); + ret = stat(node->filename, &file_stat); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: stat() operation on file failed (filename=%s, ret=%d, errno=%d).\n", __func__, node->filename, (int) ret, + errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: expected st_mode S_IFREG flag not set (filename=%s).\n", __func__, node->filename); + TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) == S_IFREG, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unexpected st_mode S_IFDIR flag set (filename=%s).\n", __func__, node->filename); + TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) != S_IFDIR, fsfat_fopen_utest_msg_g); + + /* Test stat() on the directory returns the correct attribute set */ + memset(&file_stat, 0, sizeof(file_stat)); + memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); + memcpy(buf, node->filename, strlen(node->filename)); + pos = strrchr(buf, '/'); + *pos = '\0'; + ret = stat(buf, &file_stat); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: stat() operation on directory failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, + errno); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: unexpected st_mode S_IFREG flag set (directory name=%s).\n", __func__, buf); + TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) != S_IFREG, fsfat_fopen_utest_msg_g); + + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: expected st_mode S_IFDIR flag not set (directory name=%s).\n", __func__, buf); + TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) == S_IFDIR, fsfat_fopen_utest_msg_g); + + /* clean up after successful test */ + fsfat_filepath_remove_all((char *) node->filename); + +#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ + return CaseNext; +} + +/** @brief test for operation of SDFileSystem::format() + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_15(const size_t call_count) +{ + + FSFAT_FENTRYLOG("%s:entered\n", __func__); + (void) call_count; + int32_t ret = -1; + + /* the allocation_unit of 0 means chanFS will use the default for the card (varies according to capacity). */ + fs.unmount(); + ret = fs.format(&sd); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to format sdcard (ret=%d)\n", __func__, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + fs.mount(&sd); + return CaseNext; +} + + +/* @brief test utility function to create a file of a given size. + * + * A reference data table is used of so that the data file can be later be + * checked with fsfat_test_check_data_file(). + * + * @param filename name of the file including path + * @param data data to store in file + * @param len number of bytes of data present in the data buffer. + */ +int32_t fsfat_test_create_data_file(const char *filename, size_t len) +{ + int32_t ret = -1; + FILE *fp = NULL; + size_t write_len = 0; + size_t written_len = 0; + int32_t exp = 0; + const int32_t exp_max = 8; /* so as not to exceed FSFAT_TEST_BYTE_DATA_TABLE_SIZE/2 */ + + FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); + TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); + fp = fopen(filename, "a"); + if (fp == NULL) { + return ret; + } + + while (written_len < len) { + /* write fsfat_test_byte_data_table or part thereof, in 9 writes of sizes + * 1, 2, 4, 8, 16, 32, 64, 128, 1, totalling 256 bytes len permitting. */ + for (exp = 0; (exp <= exp_max) && (written_len < len); exp++) { + write_len = 0x1 << (exp % exp_max); + write_len = len - written_len > write_len ? write_len : len - written_len; + ret = fwrite((const void *) &fsfat_test_byte_data_table[written_len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, + fp); + written_len += write_len; + if (ret != 1) { + FSFAT_DBGLOG("%s:Error: fwrite() failed (ret=%d)\n", __func__, (int) ret); + ret = -1; + goto out0; + } + } + } + if (written_len == len) { + ret = 0; + } else { + ret = -1; + } +out0: + fclose(fp); + return ret; +} + + +/* @brief test utility function to check the data in the specified file is correct. + * + * The data read from the file is check that it agrees with the data written by + * fsfat_test_create_data_file(). + * + * @param filename name of the file including path + * @param data data to store in file + * @param len number of bytes of data present in the data buffer. + */ +int32_t fsfat_test_check_data_file(const char *filename, size_t len) +{ + int32_t ret = -1; + FILE *fp = NULL; + size_t read_len = 0; + uint8_t buf[FSFAT_TEST_BYTE_DATA_TABLE_SIZE]; + + FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); + TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); + fp = fopen(filename, "r"); + if (fp == NULL) { + return ret; + } + + while (read_len < len) { + ret = fread((void *) buf, FSFAT_TEST_BYTE_DATA_TABLE_SIZE, 1, fp); + read_len += FSFAT_TEST_BYTE_DATA_TABLE_SIZE; + if (ret == 0) { + /* end of read*/ + FSFAT_DBGLOG("%s:unable to read data\n", __func__); + break; + } + if (memcmp(buf, fsfat_test_byte_data_table, FSFAT_TEST_BYTE_DATA_TABLE_SIZE) != 0) { + FSFAT_DBGLOG("%s:Error: read data not as expected (0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x\n", + __func__, + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], + buf[14], buf[15]); + ret = -1; + goto out0; + } + } + if (read_len == len) { + ret = 0; + } +out0: + fclose(fp); + return ret; +} + +/* file data for test_16 */ +static fsfat_kv_data_t fsfat_fopen_test_16_kv_data[] = { + { "/sd/tst16_0/testfil0.txt", "dummy_data"}, + { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"}, + { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"}, + { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"}, + { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"}, + { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"}, + { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"}, + { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"}, + { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"}, + { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"}, + { NULL, NULL}, +}; + + +/** @brief stress test to write data to fs + * + * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. + */ +control_t fsfat_fopen_test_16(const size_t call_count) +{ + int32_t ret = 0; + fsfat_kv_data_t *node = fsfat_fopen_test_16_kv_data; + const int32_t num_blocks = 100; /* each file ~25kB */ + + FSFAT_DBGLOG("%s:entered\n", __func__); + (void) call_count; + + /* remove file and directory from a previous failed test run, if present */ + while (node->filename != NULL) { + fsfat_filepath_remove_all((char *) node->filename); + node++; + } + + /* create dirs */ + node = fsfat_fopen_test_16_kv_data; + while (node->filename != NULL) { + ret = fsfat_filepath_make_dirs((char *) node->filename, true); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + node++; + } + + /* create the data files */ + node = fsfat_fopen_test_16_kv_data; + while (node->filename != NULL) { + ret = fsfat_test_create_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to create data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + node++; + } + + /* read the data back and check its as expected */ + node = fsfat_fopen_test_16_kv_data; + while (node->filename != NULL) { + ret = fsfat_test_check_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); + FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, + "%s:Error: failed to check data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); + TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); + node++; + } + + /* clean up */ + node = fsfat_fopen_test_16_kv_data; + while (node->filename != NULL) { + fsfat_filepath_remove_all((char *) node->filename); + node++; + } + return CaseNext; +} + + +#else + + +#define FSFAT_FOPEN_TEST_01 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_02 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_03 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_04 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_05 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_06 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_07 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_08 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_09 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_10 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_11 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_12 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_13 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_14 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_15 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_16 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_17 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_18 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_19 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_20 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_21 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_22 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_23 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_24 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_25 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_26 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_27 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_28 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_29 fsfat_fopen_test_dummy +#define FSFAT_FOPEN_TEST_30 fsfat_fopen_test_dummy + +/** @brief fsfat_fopen_test_dummy Dummy test case for testing when platform doesnt have an SDCard installed. + * + * @return success always + */ +static control_t fsfat_fopen_test_dummy() +{ + printf("Null test\n"); + return CaseNext; +} + +#endif + + +/// @cond FSFAT_DOXYGEN_DISABLE +utest::v1::status_t greentea_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(FSFAT_FOPEN_GREENTEA_TIMEOUT_S, "default_auto"); + return greentea_test_setup_handler(number_of_cases); +} + +Case cases[] = { + /* 1 2 3 4 5 6 7 */ + /* 1234567890123456789012345678901234567890123456789012345678901234567890 */ + Case("FSFAT_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSFAT_FOPEN_TEST_01), + Case("FSFAT_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSFAT_FOPEN_TEST_02), + Case("FSFAT_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSFAT_FOPEN_TEST_03), + Case("FSFAT_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSFAT_FOPEN_TEST_04), +#ifdef FOPEN_EXTENDED_TESTING + Case("FSFAT_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSFAT_FOPEN_TEST_05), +#endif + Case("FSFAT_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSFAT_FOPEN_TEST_06), + Case("FSFAT_FOPEN_TEST_07: fopen()/errno handling.", FSFAT_FOPEN_TEST_07), + Case("FSFAT_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSFAT_FOPEN_TEST_08), + Case("FSFAT_FOPEN_TEST_09: ftell() handling.", FSFAT_FOPEN_TEST_09), + Case("FSFAT_FOPEN_TEST_10: remove() test.", FSFAT_FOPEN_TEST_10), + Case("FSFAT_FOPEN_TEST_11: rename().", FSFAT_FOPEN_TEST_11), + Case("FSFAT_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSFAT_FOPEN_TEST_12), + Case("FSFAT_FOPEN_TEST_13: mkdir() test.", FSFAT_FOPEN_TEST_13), + Case("FSFAT_FOPEN_TEST_14: stat() test.", FSFAT_FOPEN_TEST_14), + Case("FSFAT_FOPEN_TEST_15: format() test.", FSFAT_FOPEN_TEST_15), + Case("FSFAT_FOPEN_TEST_16: write/check n x 25kB data files.", FSFAT_FOPEN_TEST_16), +}; + + +/* Declare your test specification with a custom setup handler */ +Specification specification(greentea_setup, cases); + +int main() +{ + return !Harness::run(specification); +} +/// @endcond diff --git a/TESTS/filesystem/parallel/main.cpp b/TESTS/filesystem/parallel/main.cpp new file mode 100644 index 0000000..2ae26ee --- /dev/null +++ b/TESTS/filesystem/parallel/main.cpp @@ -0,0 +1,209 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include +#include + +using namespace utest::v1; + +// test configuration +#ifndef MBED_TEST_FILESYSTEM +#define MBED_TEST_FILESYSTEM FATFileSystem +#endif + +#ifndef MBED_TEST_FILESYSTEM_DECL +#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") +#endif + +#ifndef MBED_TEST_BLOCKDEVICE +#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice +#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; +#endif + +#ifndef MBED_TEST_BLOCKDEVICE_DECL +#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd +#endif + +#ifndef MBED_TEST_FILES +#define MBED_TEST_FILES 4 +#endif + +#ifndef MBED_TEST_DIRS +#define MBED_TEST_DIRS 4 +#endif + +#ifndef MBED_TEST_BUFFER +#define MBED_TEST_BUFFER 512 +#endif + +#ifndef MBED_TEST_TIMEOUT +#define MBED_TEST_TIMEOUT 120 +#endif + +#ifndef MBED_THREAD_COUNT +#define MBED_THREAD_COUNT MBED_TEST_FILES +#endif + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_FILESYSTEM) +#include INCLUDE(MBED_TEST_BLOCKDEVICE) + +MBED_TEST_FILESYSTEM_DECL; +MBED_TEST_BLOCKDEVICE_DECL; + +Dir dir[MBED_TEST_DIRS]; +File file[MBED_TEST_FILES]; +DIR *dd[MBED_TEST_DIRS]; +FILE *fd[MBED_TEST_FILES]; +struct dirent ent; +struct dirent *ed; + +volatile bool count_done = 0; + +// tests + +void test_file_tests() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = MBED_TEST_FILESYSTEM::format(&bd); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void write_file_data (char count) +{ + + char filename[10]; + uint8_t wbuffer[MBED_TEST_BUFFER]; + int res; + + sprintf(filename, "%s%d", "data", count); + res = file[count].open(&fs, filename, O_WRONLY | O_CREAT); + TEST_ASSERT_EQUAL(0, res); + + char letter = 'A' + count; + for (uint32_t i = 0; i < MBED_TEST_BUFFER; i++) { + wbuffer[i] = letter++; + if ('z' == letter) { + letter = 'A' + count; + } + } + + for (uint32_t i = 0; i < 5; i++) { + res = file[count].write(wbuffer, MBED_TEST_BUFFER); + TEST_ASSERT_EQUAL(MBED_TEST_BUFFER, res); + } + + res = file[count].close(); + TEST_ASSERT_EQUAL(0, res); +} + +void read_file_data (char count) +{ + char filename[10]; + uint8_t rbuffer[MBED_TEST_BUFFER]; + int res; + + sprintf(filename, "%s%d", "data", count); + res = file[count].open(&fs, filename, O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + + for (uint32_t i = 0; i < 5; i++) { + res = file[count].read(rbuffer, MBED_TEST_BUFFER); + TEST_ASSERT_EQUAL(MBED_TEST_BUFFER, res); + char letter = 'A' + count; + for (uint32_t i = 0; i < MBED_TEST_BUFFER; i++) { + res = rbuffer[i]; + TEST_ASSERT_EQUAL(letter++, res); + if ('z' == letter) { + letter = 'A' + count; + } + } + } + + res = file[count].close(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_thread_access_test() +{ + char *dummy = new (std::nothrow) char[OS_STACK_SIZE * MBED_THREAD_COUNT]; + delete[] dummy; + TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test"); + + Thread *data[MBED_THREAD_COUNT]; + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + + // Write threads in parallel + for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { + data[thread_count] = new Thread(osPriorityNormal); + data[thread_count]->start(callback((void(*)(void *))write_file_data, (void *)thread_count)); + } + + // Wait for write thread to join before creating read thread + for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { + data[thread_count]->join(); + delete data[thread_count]; + data[thread_count] = new Thread(osPriorityNormal); + data[thread_count]->start(callback((void(*)(void *))read_file_data, (void *)thread_count)); + } + + // Wait for read threads to join + for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { + data[thread_count]->join(); + delete data[thread_count]; + } + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +// test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("File tests", test_file_tests), + Case("Filesystem access from multiple threads", test_thread_access_test), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/TESTS/filesystem/seek/main.cpp b/TESTS/filesystem/seek/main.cpp new file mode 100644 index 0000000..e2fd2bd --- /dev/null +++ b/TESTS/filesystem/seek/main.cpp @@ -0,0 +1,656 @@ +/* mbed Microcontroller Library + * Copyright (c) 2016 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "mbed.h" +#include "greentea-client/test_env.h" +#include "unity.h" +#include "utest.h" +#include +#include + +using namespace utest::v1; + +// test configuration +#ifndef MBED_TEST_FILESYSTEM +#define MBED_TEST_FILESYSTEM FATFileSystem +#endif + +#ifndef MBED_TEST_FILESYSTEM_DECL +#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") +#endif + +#ifndef MBED_TEST_BLOCKDEVICE +#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice +#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; +#endif + +#ifndef MBED_TEST_BLOCKDEVICE_DECL +#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd +#endif + +#ifndef MBED_TEST_FILES +#define MBED_TEST_FILES 4 +#endif + +#ifndef MBED_TEST_DIRS +#define MBED_TEST_DIRS 4 +#endif + +#ifndef MBED_TEST_BUFFER +#define MBED_TEST_BUFFER 8192 +#endif + +#ifndef MBED_TEST_TIMEOUT +#define MBED_TEST_TIMEOUT 120 +#endif + + +// declarations +#define STRINGIZE(x) STRINGIZE2(x) +#define STRINGIZE2(x) #x +#define INCLUDE(x) STRINGIZE(x.h) + +#include INCLUDE(MBED_TEST_FILESYSTEM) +#include INCLUDE(MBED_TEST_BLOCKDEVICE) + +MBED_TEST_FILESYSTEM_DECL; +MBED_TEST_BLOCKDEVICE_DECL; + +Dir dir[MBED_TEST_DIRS]; +File file[MBED_TEST_FILES]; +DIR *dd[MBED_TEST_DIRS]; +FILE *fd[MBED_TEST_FILES]; +struct dirent ent; +struct dirent *ed; +size_t size; +uint8_t buffer[MBED_TEST_BUFFER]; +uint8_t rbuffer[MBED_TEST_BUFFER]; +uint8_t wbuffer[MBED_TEST_BUFFER]; + + +// tests + +void test_seek_tests() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = MBED_TEST_FILESYSTEM::format(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = fs.mkdir("hello", 0777); + TEST_ASSERT_EQUAL(0, res); + for (int i = 0; i < 132; i++) { + sprintf((char *)buffer, "hello/kitty%d", i); + res = file[0].open(&fs, (char *)buffer, + O_WRONLY | O_CREAT | O_APPEND); + TEST_ASSERT_EQUAL(0, res); + + size = strlen("kittycatcat"); + memcpy(buffer, "kittycatcat", size); + for (int j = 0; j < 132; j++) { + file[0].write(buffer, size); + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + } + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_simple_dir_seek() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "hello"); + TEST_ASSERT_EQUAL(0, res); +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, "."); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, ".."); + TEST_ASSERT_EQUAL(0, res); +#endif + + off_t pos; + int i; + for (i = 0; i < 4; i++) { + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + pos = dir[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + + dir[0].seek(pos); + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + + dir[0].rewind(); + sprintf((char *)buffer, "kitty%d", 0); +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, "."); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, ".."); + TEST_ASSERT_EQUAL(0, res); +#endif + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + + dir[0].seek(pos); + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_large_dir_seek() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].open(&fs, "hello"); + TEST_ASSERT_EQUAL(0, res); +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, "."); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, ".."); + TEST_ASSERT_EQUAL(0, res); +#endif + + off_t pos; + int i; + for (i = 0; i < 128; i++) { + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + pos = dir[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + + dir[0].seek(pos); + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + + dir[0].rewind(); + sprintf((char *)buffer, "kitty%d", 0); +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, "."); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, ".."); + TEST_ASSERT_EQUAL(0, res); +#endif + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + + dir[0].seek(pos); + sprintf((char *)buffer, "kitty%d", i); + res = dir[0].read(&ent); + TEST_ASSERT_EQUAL(1, res); + res = strcmp(ent.d_name, (char *)buffer); + TEST_ASSERT_EQUAL(0, res); + res = dir[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_simple_file_seek() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + + off_t pos; + size = strlen("kittycatcat"); + for (int i = 0; i < 4; i++) { + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + pos = file[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + file[0].rewind(); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_CUR); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_END) >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + size_t size = file[0].size(); + res = file[0].seek(0, SEEK_CUR); + TEST_ASSERT_EQUAL(size, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_large_file_seek() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDONLY); + TEST_ASSERT_EQUAL(0, res); + + off_t pos; + size = strlen("kittycatcat"); + for (int i = 0; i < 128; i++) { + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + pos = file[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + file[0].rewind(); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_CUR); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_END) >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + size_t size = file[0].size(); + res = file[0].seek(0, SEEK_CUR); + TEST_ASSERT_EQUAL(size, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_simple_file_seek_and_write() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDWR); + TEST_ASSERT_EQUAL(0, res); + + off_t pos; + size = strlen("kittycatcat"); + for (int i = 0; i < 4; i++) { + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + pos = file[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + + memcpy(buffer, "doggodogdog", size); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].write(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "doggodogdog", size); + TEST_ASSERT_EQUAL(0, res); + + file[0].rewind(); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "doggodogdog", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_END) >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + size_t size = file[0].size(); + res = file[0].seek(0, SEEK_CUR); + TEST_ASSERT_EQUAL(size, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_large_file_seek_and_write() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDWR); + TEST_ASSERT_EQUAL(0, res); + + off_t pos; + size = strlen("kittycatcat"); + for (int i = 0; i < 128; i++) { + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + if (i != 4) { + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + } + pos = file[0].tell(); + } + res = pos >= 0; + TEST_ASSERT_EQUAL(1, res); + + memcpy(buffer, "doggodogdog", size); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].write(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "doggodogdog", size); + TEST_ASSERT_EQUAL(0, res); + + file[0].rewind(); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(pos, SEEK_SET); + TEST_ASSERT_EQUAL(pos, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "doggodogdog", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(-size, SEEK_END) >= 0; + TEST_ASSERT_EQUAL(1, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + + size_t size = file[0].size(); + res = file[0].seek(0, SEEK_CUR); + TEST_ASSERT_EQUAL(size, res); + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_boundary_seek_and_write() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDWR); + TEST_ASSERT_EQUAL(0, res); + + size = strlen("hedgehoghog"); + const off_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; + + for (int i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { + off_t off = offsets[i]; + memcpy(buffer, "hedgehoghog", size); + res = file[0].seek(off, SEEK_SET); + TEST_ASSERT_EQUAL(off, res); + res = file[0].write(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = file[0].seek(off, SEEK_SET); + TEST_ASSERT_EQUAL(off, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "hedgehoghog", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(0, SEEK_SET); + TEST_ASSERT_EQUAL(0, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "kittycatcat", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].sync(); + TEST_ASSERT_EQUAL(0, res); + } + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + +void test_out_of_bounds_seek() +{ + int res = bd.init(); + TEST_ASSERT_EQUAL(0, res); + + { + res = fs.mount(&bd); + TEST_ASSERT_EQUAL(0, res); + res = file[0].open(&fs, "hello/kitty42", O_RDWR); + TEST_ASSERT_EQUAL(0, res); + + size = strlen("kittycatcat"); + res = file[0].size(); + TEST_ASSERT_EQUAL(132 * size, res); + res = file[0].seek((132 + 4) * size, + SEEK_SET); + TEST_ASSERT_EQUAL((132 + 4)*size, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(0, res); + + memcpy(buffer, "porcupineee", size); + res = file[0].write(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = file[0].seek((132 + 4) * size, + SEEK_SET); + TEST_ASSERT_EQUAL((132 + 4)*size, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); + res = memcmp(buffer, "porcupineee", size); + TEST_ASSERT_EQUAL(0, res); + res = file[0].seek(132 * size, + SEEK_SET); + TEST_ASSERT_EQUAL(132 * size, res); + res = file[0].read(buffer, size); + TEST_ASSERT_EQUAL(size, res); +#if (MBED_TEST_FILESYSTEM != FATFileSystem) + // FatFs does not guarantee empty expanded buffer + res = memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size); + TEST_ASSERT_EQUAL(0, res); +#endif + res = file[0].close(); + TEST_ASSERT_EQUAL(0, res); + res = fs.unmount(); + TEST_ASSERT_EQUAL(0, res); + } + + res = bd.deinit(); + TEST_ASSERT_EQUAL(0, res); +} + + + +// test setup +utest::v1::status_t test_setup(const size_t number_of_cases) +{ + GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); + return verbose_test_setup_handler(number_of_cases); +} + +Case cases[] = { + Case("Seek tests", test_seek_tests), + Case("Simple dir seek", test_simple_dir_seek), + Case("Large dir seek", test_large_dir_seek), + Case("Simple file seek", test_simple_file_seek), + Case("Large file seek", test_large_file_seek), + Case("Simple file seek and write", test_simple_file_seek_and_write), + Case("Large file seek and write", test_large_file_seek_and_write), + Case("Boundary seek and write", test_boundary_seek_and_write), + Case("Out-of-bounds seek", test_out_of_bounds_seek), +}; + +Specification specification(test_setup, cases); + +int main() +{ + return !Harness::run(specification); +} diff --git a/config/mbed_lib.json b/config/mbed_lib.json new file mode 100644 index 0000000..30d5324 --- /dev/null +++ b/config/mbed_lib.json @@ -0,0 +1,12 @@ +{ + "name": "sdio", + "config": { + "FSFAT_SDCARD_INSTALLED": 1, + "CMD_TIMEOUT": 30000 + }, + "target_overrides": { + "DISCO_F469NI": { + "CMD_TIMEOUT": 30000 + } + } +} From 4773505c5db6855cd4ff034b4d1818d3a885e8bb Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Mon, 12 Nov 2018 17:51:23 +0100 Subject: [PATCH 02/23] add implementation for STM32F7 almost the same as for STM32F4, but in F7 SDIO device is renamed to SDMMC SDMMC1 is used for DISCO_F746NG updated readme.md for new target # Conflicts: # README.md --- TARGET_STM/TARGET_STM32F7/sdio_device.c | 538 ++++++++++++++++++++++++ TARGET_STM/TARGET_STM32F7/sdio_device.h | 126 ++++++ 2 files changed, 664 insertions(+) create mode 100644 TARGET_STM/TARGET_STM32F7/sdio_device.c create mode 100644 TARGET_STM/TARGET_STM32F7/sdio_device.h diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.c b/TARGET_STM/TARGET_STM32F7/sdio_device.c new file mode 100644 index 0000000..e9b3fae --- /dev/null +++ b/TARGET_STM/TARGET_STM32F7/sdio_device.c @@ -0,0 +1,538 @@ +/** + * + * This sourcecode is derived from STMicroelectronics CubeMX generated code. + * It is modified to work with mbed RTOS. + * + ****************************************************************************** + * @file bsp_driver_sd.c for F4 (based on stm324x9i_eval_sd.c) + * @brief This file includes a generic uSD card driver. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +#include "sdio_device.h" +#include "platform/mbed_error.h" + +/* Extern variables ---------------------------------------------------------*/ + +SD_HandleTypeDef hsd; +DMA_HandleTypeDef hdma_sdmmc_rx; +DMA_HandleTypeDef hdma_sdmmc_tx; + +// simple flags for DMA pending signaling +volatile uint8_t SD_DMA_ReadPendingState = SD_TRANSFER_OK; +volatile uint8_t SD_DMA_WritePendingState = SD_TRANSFER_OK; + +/* DMA Handlers are global, there is only one SDIO interface */ + +/** +* @brief This function handles SDMMC global interrupt. +*/ +void _SDMMC_IRQHandler(void) +{ + HAL_SD_IRQHandler(&hsd); +} + +/** +* @brief This function handles DMAx stream_n global interrupt. DMA Rx +*/ +void _DMA_Stream_Rx_IRQHandler(void) +{ + HAL_DMA_IRQHandler(hsd.hdmarx); +} + +/** +* @brief This function handles DMAx stream_n global interrupt. DMA Tx +*/ +void _DMA_Stream_Tx_IRQHandler(void) +{ + HAL_DMA_IRQHandler(hsd.hdmatx); +} + +/** + * + * @param hsd: Handle for SD handle Structure definition + */ +void HAL_SD_MspInit(SD_HandleTypeDef *hsd) +{ + IRQn_Type IRQn; + GPIO_InitTypeDef GPIO_InitStruct; + + if (hsd->Instance == SDMMC1) + { + /* Peripheral clock enable */ + __HAL_RCC_SDMMC1_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + + /* Enable GPIOs clock */ + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + /** SDMMC GPIO Configuration + PC12 ------> SDIO_CK + PC11 ------> SDIO_D3 + PC10 ------> SDIO_D2 + PD2 ------> SDIO_CMD + PC9 ------> SDIO_D1 + PC8 ------> SDIO_D0 + */ + GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1; + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + GPIO_InitStruct.Pin = GPIO_PIN_2; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_PULLUP; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF12_SDMMC1; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + /* NVIC configuration for SDMMC interrupts */ + IRQn = SDMMC1_IRQn; + HAL_NVIC_SetPriority(IRQn, 0x0E, 0); + NVIC_SetVector(IRQn, (uint32_t)&_SDMMC_IRQHandler); + HAL_NVIC_EnableIRQ(IRQn); + + /* SDMMC DMA Init */ + /* SDMMC_RX Init */ + hdma_sdmmc_rx.Instance = DMA2_Stream3; + hdma_sdmmc_rx.Init.Channel = DMA_CHANNEL_4; + hdma_sdmmc_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_sdmmc_rx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdmmc_rx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdmmc_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdmmc_rx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdmmc_rx.Init.Mode = DMA_PFCTRL; + hdma_sdmmc_rx.Init.Priority = DMA_PRIORITY_LOW; + hdma_sdmmc_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sdmmc_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sdmmc_rx.Init.MemBurst = DMA_MBURST_INC4; + hdma_sdmmc_rx.Init.PeriphBurst = DMA_PBURST_INC4; + if (HAL_DMA_Init(&hdma_sdmmc_rx) != HAL_OK) + { + error("SDMMC DMA Init error at %d in %s", __FILE__, __LINE__); + } + + __HAL_LINKDMA(hsd, hdmarx, hdma_sdmmc_rx); + + /* Deinitialize the stream for new transfer */ + HAL_DMA_DeInit(&hdma_sdmmc_rx); + + /* Configure the DMA stream */ + HAL_DMA_Init(&hdma_sdmmc_rx); + + /* SDMMC_TX Init */ + hdma_sdmmc_tx.Instance = DMA2_Stream6; + hdma_sdmmc_tx.Init.Channel = DMA_CHANNEL_4; + hdma_sdmmc_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_sdmmc_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdmmc_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdmmc_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdmmc_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdmmc_tx.Init.Mode = DMA_PFCTRL; + hdma_sdmmc_tx.Init.Priority = DMA_PRIORITY_LOW; + hdma_sdmmc_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sdmmc_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sdmmc_tx.Init.MemBurst = DMA_MBURST_INC4; + hdma_sdmmc_tx.Init.PeriphBurst = DMA_PBURST_INC4; + if (HAL_DMA_Init(&hdma_sdmmc_tx) != HAL_OK) + { + error("SDMMC DMA Init error at %d in %s", __FILE__, __LINE__); + } + + __HAL_LINKDMA(hsd, hdmatx, hdma_sdmmc_tx); + + /* Deinitialize the stream for new transfer */ + HAL_DMA_DeInit(&hdma_sdmmc_tx); + + /* Configure the DMA stream */ + HAL_DMA_Init(&hdma_sdmmc_tx); + + /* Enable NVIC for DMA transfer complete interrupts */ + IRQn = DMA2_Stream3_IRQn; + NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Rx_IRQHandler); + HAL_NVIC_SetPriority(IRQn, 0x0F, 0); + HAL_NVIC_EnableIRQ(IRQn); + + IRQn = DMA2_Stream6_IRQn; + NVIC_SetVector(IRQn, (uint32_t)&_DMA_Stream_Tx_IRQHandler); + HAL_NVIC_SetPriority(IRQn, 0x0F, 0); + HAL_NVIC_EnableIRQ(IRQn); + } +} + +/** + * + * @param hsd: Handle for SD handle Structure definition + */ +void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) +{ + + if (hsd->Instance == SDMMC1) + { + /* Peripheral clock disable */ + __HAL_RCC_SDMMC1_CLK_DISABLE(); + + /** SDSDMMC1 GPIO Configuration + PC12 ------> SDIO_CK + PC11 ------> SDIO_D3 + PC10 ------> SDIO_D2 + PD2 ------> SDIO_CMD + PC9 ------> SDIO_D1 + PC8 ------> SDIO_D0 + */ + HAL_GPIO_DeInit(GPIOC, GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_9 | GPIO_PIN_8); + + HAL_GPIO_DeInit(GPIOD, GPIO_PIN_2); + + /* SDMMC1 DMA DeInit */ + HAL_DMA_DeInit(hsd->hdmarx); + HAL_DMA_DeInit(hsd->hdmatx); + } +} + +/** + * @brief DeInitializes the SD MSP. + * @param hsd: SD handle + * @param Params : pointer on additional configuration parameters, can be NULL. + */ +__weak void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params) +{ + static DMA_HandleTypeDef dma_rx_handle; + static DMA_HandleTypeDef dma_tx_handle; + + /* Disable NVIC for DMA transfer complete interrupts */ + HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn); + HAL_NVIC_DisableIRQ(DMA2_Stream6_IRQn); + + /* Deinitialize the stream for new transfer */ + dma_rx_handle.Instance = DMA2_Stream3; + HAL_DMA_DeInit(&dma_rx_handle); + + /* Deinitialize the stream for new transfer */ + dma_tx_handle.Instance = DMA2_Stream6; + HAL_DMA_DeInit(&dma_tx_handle); + + /* Disable NVIC for SDMMC interrupts */ + HAL_NVIC_DisableIRQ(SDMMC1_IRQn); + + /* Disable SDMMC clock */ + __HAL_RCC_SDMMC1_CLK_DISABLE(); +} + +/** + * @brief Enables the SD wide bus mode. + * @param hsd pointer to SD handle + * @retval error state + */ +static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) +{ + uint32_t errorstate = HAL_SD_ERROR_NONE; + + if ((SDMMC_GetResponse(hsd->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) + { + return HAL_SD_ERROR_LOCK_UNLOCK_FAILED; + } + + /* Send CMD55 APP_CMD with argument as card's RCA.*/ + errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U)); + if (errorstate != HAL_OK) + { + return errorstate; + } + + /* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */ + errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U); + if (errorstate != HAL_OK) + { + return errorstate; + } + + hsd->Init.BusWide = SDMMC_BUS_WIDE_4B; + SDMMC_Init(hsd->Instance, hsd->Init); + + return HAL_SD_ERROR_NONE; +} + +/** + * @brief Initializes the SD card device. + * @retval SD status + */ +uint8_t SD_Init(void) +{ + uint8_t sd_state = MSD_OK; + + hsd.Instance = SDMMC1; + hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; + hsd.Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE; + hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; + hsd.Init.BusWide = SDMMC_BUS_WIDE_1B; + hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE; + hsd.Init.ClockDiv = 0; + + /* HAL SD initialization */ + sd_state = HAL_SD_Init(&hsd); + /* Configure SD Bus width (4 bits mode selected) */ + if (sd_state == MSD_OK) + { + /* Enable wide operation */ + if (SD_WideBus_Enable(&hsd) != HAL_OK) + { + sd_state = MSD_ERROR; + } + } + + return sd_state; +} + +/** + * @brief DeInitializes the SD card device. + * @retval SD status + */ +uint8_t SD_DeInit(void) +{ + uint8_t sd_state = MSD_OK; + + hsd.Instance = SDMMC1; + + /* HAL SD deinitialization */ + if (HAL_SD_DeInit(&hsd) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + /* Msp SD deinitialization */ + hsd.Instance = SDMMC1; + SD_MspDeInit(&hsd, NULL); + + return sd_state; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @param Timeout: Timeout for read operation + * @retval SD status + */ +uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @param Timeout: Timeout for write operation + * @retval SD status + */ +uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @retval SD status + */ +uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; + + /* Read block(s) in DMA transfer mode */ + if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK) + { + sd_state = MSD_ERROR; + SD_DMA_ReadPendingState = SD_TRANSFER_OK; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @retval SD status + */ +uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + SD_DMA_WritePendingState = SD_TRANSFER_BUSY; + + /* Write block(s) in DMA transfer mode */ + if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK) + { + sd_state = MSD_ERROR; + SD_DMA_WritePendingState = SD_TRANSFER_OK; + } + + return sd_state; +} + +/** + * @brief Erases the specified memory area of the given SD card. + * @param StartAddr: Start byte address + * @param EndAddr: End byte address + * @retval SD status + */ +uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) +{ + uint8_t sd_state = MSD_OK; + + if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Gets the current SD card data status. + * @param None + * @retval Data transfer state. + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_GetCardState(void) +{ + return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); +} + +/** + * @brief Get SD information about specific SD card. + * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure + * @retval None + */ +void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) +{ + /* Get SD card Information, copy structure for portability */ + HAL_SD_CardInfoTypeDef HAL_CardInfo; + + HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo); + + if (CardInfo) + { + CardInfo->CardType = HAL_CardInfo.CardType; + CardInfo->CardVersion = HAL_CardInfo.CardVersion; + CardInfo->Class = HAL_CardInfo.Class; + CardInfo->RelCardAdd = HAL_CardInfo.RelCardAdd; + CardInfo->BlockNbr = HAL_CardInfo.BlockNbr; + CardInfo->BlockSize = HAL_CardInfo.BlockSize; + CardInfo->LogBlockNbr = HAL_CardInfo.LogBlockNbr; + CardInfo->LogBlockSize = HAL_CardInfo.LogBlockSize; + } +} + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_DMA_ReadPending(void) +{ + return SD_DMA_ReadPendingState; +} + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ +uint8_t SD_DMA_WritePending(void) +{ + return SD_DMA_WritePendingState; +} + +/** + * @brief Rx Transfer completed callbacks + * @param hsd Pointer SD handle + * @retval None + */ +void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd) +{ + SD_DMA_ReadPendingState = SD_TRANSFER_OK; +} + +/** + * @brief Tx Transfer completed callbacks + * @param hsd Pointer to SD handle + * @retval None + */ +void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) +{ + SD_DMA_WritePendingState = SD_TRANSFER_OK; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.h b/TARGET_STM/TARGET_STM32F7/sdio_device.h new file mode 100644 index 0000000..f5af32b --- /dev/null +++ b/TARGET_STM/TARGET_STM32F7/sdio_device.h @@ -0,0 +1,126 @@ +/** + * + * This sourcecode is derived from STMicroelectronics CubeMX generated code. + * It is modified to work with mbed RTOS. + * + ****************************************************************************** + * @file bsp_driver_sd.h for F4 (based on stm324x9i_eval_sd.h) + * @brief This file contains the common defines and functions prototypes for + * the bsp_driver_sd.c driver. + ****************************************************************************** + * This notice applies to any and all portions of this file + * that are not between comment pairs USER CODE BEGIN and + * USER CODE END. Other portions of this file, whether + * inserted by the user or by software development tools + * are owned by their respective copyright owners. + * + * Copyright (c) 2018 STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __SDIO_DEVICE_H +#define __SDIO_DEVICE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "stm32f7xx_hal.h" + + /* Typedefs */ + + typedef struct + { + uint32_t CardType; /* Specifies the card Type */ + uint32_t CardVersion; /* Specifies the card version */ + uint32_t Class; /* Specifies the class of the card class */ + uint32_t RelCardAdd; /* Specifies the Relative Card Address */ + uint32_t BlockNbr; /* Specifies the Card Capacity in blocks */ + uint32_t BlockSize; /* Specifies one block size in bytes */ + uint32_t LogBlockNbr; /* Specifies the Card logical Capacity in blocks */ + uint32_t LogBlockSize; /* Specifies logical block size in bytes */ + } SD_Cardinfo_t; + + /* External Global var */ + + extern SD_HandleTypeDef hsd; + +/* Exported types */ +/** + * @brief SD Card information structure + */ +#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef + +/* Exported constants */ +/** + * @brief SD status structure definition + */ +#define MSD_OK ((uint8_t)0x00) +#define MSD_ERROR ((uint8_t)0x01) + +/** + * @brief SD transfer state definition + */ +#define SD_TRANSFER_OK ((uint8_t)0x00) +#define SD_TRANSFER_BUSY ((uint8_t)0x01) + + /* Exported functions */ + uint8_t SD_Init(void); + uint8_t SD_DeInit(void); + uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); + uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); + uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); + uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); + uint8_t SD_DMA_ReadPending(void); + uint8_t SD_DMA_WritePending(void); + uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr); + + uint8_t SD_GetCardState(void); + void SD_GetCardInfo(SD_Cardinfo_t *CardInfo); + + /* callback function for DMA Rx/Tx completete, called by HAL SDIO interrupt handler */ + void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd); + void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd); + +#ifdef __cplusplus +} +#endif + +#endif /* __SDIO_DEVICE_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 8d1f8330380c0001ad49d9eb203dd88442004a87 Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Mon, 12 Nov 2018 17:52:52 +0100 Subject: [PATCH 03/23] changed copyright notice to standard mBed --- TARGET_STM/TARGET_STM32F7/sdio_device.c | 61 +++++------------------ TARGET_STM/TARGET_STM32F7/sdio_device.h | 64 ++++++------------------- 2 files changed, 26 insertions(+), 99 deletions(-) diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.c b/TARGET_STM/TARGET_STM32F7/sdio_device.c index e9b3fae..29cfb01 100644 --- a/TARGET_STM/TARGET_STM32F7/sdio_device.c +++ b/TARGET_STM/TARGET_STM32F7/sdio_device.c @@ -1,55 +1,20 @@ -/** - * - * This sourcecode is derived from STMicroelectronics CubeMX generated code. - * It is modified to work with mbed RTOS. - * - ****************************************************************************** - * @file bsp_driver_sd.c for F4 (based on stm324x9i_eval_sd.c) - * @brief This file includes a generic uSD card driver. - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2018 STMicroelectronics International N.V. - * All rights reserved. +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + #include "sdio_device.h" #include "platform/mbed_error.h" @@ -534,5 +499,3 @@ void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) { SD_DMA_WritePendingState = SD_TRANSFER_OK; } - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.h b/TARGET_STM/TARGET_STM32F7/sdio_device.h index f5af32b..db20c95 100644 --- a/TARGET_STM/TARGET_STM32F7/sdio_device.h +++ b/TARGET_STM/TARGET_STM32F7/sdio_device.h @@ -1,55 +1,19 @@ -/** +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited * - * This sourcecode is derived from STMicroelectronics CubeMX generated code. - * It is modified to work with mbed RTOS. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - ****************************************************************************** - * @file bsp_driver_sd.h for F4 (based on stm324x9i_eval_sd.h) - * @brief This file contains the common defines and functions prototypes for - * the bsp_driver_sd.c driver. - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2018 STMicroelectronics International N.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + /* Define to prevent recursive inclusion -------------------------------------*/ #ifndef __SDIO_DEVICE_H From 088679c750881b74e7e444dcfc384f6471f18ef3 Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Mon, 12 Nov 2018 17:58:00 +0100 Subject: [PATCH 04/23] changed copyright to mBed standard --- TARGET_STM/TARGET_STM32F4/sdio_device.c | 61 +++++---------------- TARGET_STM/TARGET_STM32F4/sdio_device.h | 71 ++++++------------------- TARGET_STM/TARGET_STM32F7/sdio_device.h | 2 - 3 files changed, 28 insertions(+), 106 deletions(-) diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.c b/TARGET_STM/TARGET_STM32F4/sdio_device.c index 6979c71..0e6b9d1 100644 --- a/TARGET_STM/TARGET_STM32F4/sdio_device.c +++ b/TARGET_STM/TARGET_STM32F4/sdio_device.c @@ -1,55 +1,20 @@ -/** - * - * This sourcecode is derived from STMicroelectronics CubeMX generated code. - * It is modified to work with mbed RTOS. - * - ****************************************************************************** - * @file bsp_driver_sd.c for F4 (based on stm324x9i_eval_sd.c) - * @brief This file includes a generic uSD card driver. - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2018 STMicroelectronics International N.V. - * All rights reserved. +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ + #include "sdio_device.h" #include "platform/mbed_error.h" @@ -534,5 +499,3 @@ void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) { SD_DMA_WritePendingState = SD_TRANSFER_OK; } - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.h b/TARGET_STM/TARGET_STM32F4/sdio_device.h index edd20ac..02266d4 100644 --- a/TARGET_STM/TARGET_STM32F4/sdio_device.h +++ b/TARGET_STM/TARGET_STM32F4/sdio_device.h @@ -1,59 +1,22 @@ -/** +/* mbed Microcontroller Library + * Copyright (c) 2017 ARM Limited * - * This sourcecode is derived from STMicroelectronics CubeMX generated code. - * It is modified to work with mbed RTOS. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - ****************************************************************************** - * @file bsp_driver_sd.h for F4 (based on stm324x9i_eval_sd.h) - * @brief This file contains the common defines and functions prototypes for - * the bsp_driver_sd.c driver. - ****************************************************************************** - * This notice applies to any and all portions of this file - * that are not between comment pairs USER CODE BEGIN and - * USER CODE END. Other portions of this file, whether - * inserted by the user or by software development tools - * are owned by their respective copyright owners. - * - * Copyright (c) 2018 STMicroelectronics International N.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted, provided that the following conditions are met: - * - * 1. Redistribution of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of STMicroelectronics nor the names of other - * contributors to this software may be used to endorse or promote products - * derived from this software without specific written permission. - * 4. This software, including modifications and/or derivative works of this - * software, must execute solely and exclusively on microcontroller or - * microprocessor devices manufactured by or for STMicroelectronics. - * 5. Redistribution and use of this software other than as permitted under - * this license is void and will automatically terminate your rights under - * this license. - * - * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY - * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT - * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************** - */ + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ /* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __STM32F4_SD_H -#define __STM32F4_SD_H +#ifndef __SDIO_DEVICE_H +#define __SDIO_DEVICE_H #ifdef __cplusplus extern "C" @@ -121,6 +84,4 @@ extern "C" } #endif -#endif /* __STM32F4_SD_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +#endif /* __SDIO_DEVICE_H */ diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.h b/TARGET_STM/TARGET_STM32F7/sdio_device.h index db20c95..7deaa14 100644 --- a/TARGET_STM/TARGET_STM32F7/sdio_device.h +++ b/TARGET_STM/TARGET_STM32F7/sdio_device.h @@ -86,5 +86,3 @@ extern "C" #endif #endif /* __SDIO_DEVICE_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ From 124d0bd2b17ca5c0b0a962804297b66dfdb7b059 Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Fri, 7 Dec 2018 00:52:58 +0100 Subject: [PATCH 05/23] code cleanup - removed comments - renamed short variable names --- SDIOBlockDevice.cpp | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/SDIOBlockDevice.cpp b/SDIOBlockDevice.cpp index 86572bb..2270b42 100644 --- a/SDIOBlockDevice.cpp +++ b/SDIOBlockDevice.cpp @@ -158,9 +158,8 @@ int SDIOBlockDevice::deinit() return status; } -int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) +int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) { - //debug_if(SD_DBG, "read Card...\r\n"); lock(); if (isPresent() == false) { @@ -179,7 +178,7 @@ int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_NO_INIT; } - uint32_t *buffer = static_cast(b); + uint32_t *_buffer = static_cast(buffer); // ReadBlocks uses byte unit address // SDHC and SDXC Cards different addressing is handled in ReadBlocks() @@ -194,7 +193,7 @@ int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) } // receive the data : one block/ multiple blocks is handled in ReadBlocks() - int status = SD_ReadBlocks_DMA(buffer, addr, blockCnt); + int status = SD_ReadBlocks_DMA(_buffer, addr, blockCnt); debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); if (status == MSD_OK) @@ -227,9 +226,8 @@ int SDIOBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size) return status; } -int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) +int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) { - //debug_if(SD_DBG, "program Card...\r\n"); lock(); if (isPresent() == false) @@ -249,9 +247,8 @@ int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_NO_INIT; } - //uint32_t *buffer = static_cast< uint32_t *>(b); // HAL layer uses uint32_t for addr/size - uint32_t *buffer = (uint32_t *)(b); + uint32_t *_buffer = (uint32_t *)(buffer); // Get block count bd_size_t blockCnt = size / _block_size; @@ -264,7 +261,7 @@ int SDIOBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size) wait_ms(1); } - int status = SD_WriteBlocks_DMA(buffer, addr, blockCnt); + int status = SD_WriteBlocks_DMA(_buffer, addr, blockCnt); debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); if (status == MSD_OK) @@ -369,10 +366,12 @@ bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) bool SDIOBlockDevice::isPresent(void) { - if (_cardDetect.is_connected()) + if (_cardDetect.is_connected()) { return (_cardDetect.read() == 0); - else + } + else { return true; + } } } // namespace mbed From 26a4b7c2d06dc8c4e8d5fd240c567e60d00dc3a3 Mon Sep 17 00:00:00 2001 From: JojoS62 Date: Sun, 16 Dec 2018 14:58:07 +0100 Subject: [PATCH 06/23] fiixed timeout checking tickstart was inside checking loop removed wait_ms() calls added timeout checks for all while loops --- SDIOBlockDevice.cpp | 64 +++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 17 deletions(-) diff --git a/SDIOBlockDevice.cpp b/SDIOBlockDevice.cpp index 2270b42..99b89d8 100644 --- a/SDIOBlockDevice.cpp +++ b/SDIOBlockDevice.cpp @@ -186,10 +186,17 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) addr = addr / _block_size; // make sure card is ready - while (SD_GetCardState() != SD_TRANSFER_OK) { - // wait until SD ready - wait_ms(1); + uint32_t tickstart = HAL_GetTick(); + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + } + } } // receive the data : one block/ multiple blocks is handled in ReadBlocks() @@ -199,9 +206,9 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) if (status == MSD_OK) { // wait until DMA finished + uint32_t tickstart = HAL_GetTick(); while (SD_DMA_ReadPending() != SD_TRANSFER_OK) { - uint32_t tickstart = HAL_GetTick(); if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); @@ -209,17 +216,22 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) } } // make sure card is ready + tickstart = HAL_GetTick(); while (SD_GetCardState() != SD_TRANSFER_OK) { // wait until SD ready - wait_ms(10); + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + } } } else { debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); - debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode); - status = SD_BLOCK_DEVICE_ERROR_READBLOCKS; + unlock(); + return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } unlock(); @@ -255,10 +267,17 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) addr = addr / _block_size; // make sure card is ready - while (SD_GetCardState() != SD_TRANSFER_OK) { - // wait until SD ready - wait_ms(1); + uint32_t tickstart = HAL_GetTick(); + while (SD_GetCardState() != SD_TRANSFER_OK) + { + // wait until SD ready + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + } + } } int status = SD_WriteBlocks_DMA(_buffer, addr, blockCnt); @@ -267,27 +286,32 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) if (status == MSD_OK) { // wait until DMA finished + uint32_t tickstart = HAL_GetTick(); while (SD_DMA_WritePending() != SD_TRANSFER_OK) { - uint32_t tickstart = HAL_GetTick(); if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); - status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } } // make sure card is ready + tickstart = HAL_GetTick(); while (SD_GetCardState() != SD_TRANSFER_OK) { // wait until SD ready - wait_ms(1); + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + } } } else { debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); - debug_if(SD_DBG, " hsd.errorcode: %lu 0x%lx\n", hsd.ErrorCode, hsd.ErrorCode); - status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + unlock(); + return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } unlock(); @@ -322,14 +346,20 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) if (status != 0) { debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); - status = SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; + unlock(); + return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } else { + uint32_t tickstart = HAL_GetTick(); while (SD_GetCardState() != SD_TRANSFER_OK) { // wait until SD ready - wait_ms(10); + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) + { + unlock(); + return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; + } } } From c0bd5f92019761a16d1064a1ea457cac89960a79 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 26 Mar 2019 19:48:29 +0200 Subject: [PATCH 07/23] Restructure across the tree --- TARGET_STM/TARGET_STM32F4/sdio_device.h | 87 ------------------- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 0 .../COMPONENT_SDIO/SDIOBlockDevice.h | 0 .../blockdevice/COMPONENT_SDIO}/mbed_lib.json | 0 .../TARGET_STM32F7 => hal}/sdio_device.h | 0 .../TARGET_STM}/TARGET_STM32F4/sdio_device.c | 0 .../TARGET_STM}/TARGET_STM32F7/sdio_device.c | 0 7 files changed, 87 deletions(-) delete mode 100644 TARGET_STM/TARGET_STM32F4/sdio_device.h rename SDIOBlockDevice.cpp => components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp (100%) rename SDIOBlockDevice.h => components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h (100%) rename {config => components/storage/blockdevice/COMPONENT_SDIO}/mbed_lib.json (100%) rename {TARGET_STM/TARGET_STM32F7 => hal}/sdio_device.h (100%) rename {TARGET_STM => targets/TARGET_STM}/TARGET_STM32F4/sdio_device.c (100%) rename {TARGET_STM => targets/TARGET_STM}/TARGET_STM32F7/sdio_device.c (100%) diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.h b/TARGET_STM/TARGET_STM32F4/sdio_device.h deleted file mode 100644 index 02266d4..0000000 --- a/TARGET_STM/TARGET_STM32F4/sdio_device.h +++ /dev/null @@ -1,87 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __SDIO_DEVICE_H -#define __SDIO_DEVICE_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "stm32f4xx_hal.h" - - /* Typedefs */ - - typedef struct - { - uint32_t CardType; /* Specifies the card Type */ - uint32_t CardVersion; /* Specifies the card version */ - uint32_t Class; /* Specifies the class of the card class */ - uint32_t RelCardAdd; /* Specifies the Relative Card Address */ - uint32_t BlockNbr; /* Specifies the Card Capacity in blocks */ - uint32_t BlockSize; /* Specifies one block size in bytes */ - uint32_t LogBlockNbr; /* Specifies the Card logical Capacity in blocks */ - uint32_t LogBlockSize; /* Specifies logical block size in bytes */ - } SD_Cardinfo_t; - - /* External Global var */ - - extern SD_HandleTypeDef hsd; - -/* Exported types */ -/** - * @brief SD Card information structure - */ -#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef - -/* Exported constants */ -/** - * @brief SD status structure definition - */ -#define MSD_OK ((uint8_t)0x00) -#define MSD_ERROR ((uint8_t)0x01) - -/** - * @brief SD transfer state definition - */ -#define SD_TRANSFER_OK ((uint8_t)0x00) -#define SD_TRANSFER_BUSY ((uint8_t)0x01) - - /* Exported functions */ - uint8_t SD_Init(void); - uint8_t SD_DeInit(void); - uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); - uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); - uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); - uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); - uint8_t SD_DMA_ReadPending(void); - uint8_t SD_DMA_WritePending(void); - uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr); - - uint8_t SD_GetCardState(void); - void SD_GetCardInfo(SD_Cardinfo_t *CardInfo); - - /* callback function for DMA Rx/Tx completete, called by HAL SDIO interrupt handler */ - void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd); - void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd); - -#ifdef __cplusplus -} -#endif - -#endif /* __SDIO_DEVICE_H */ diff --git a/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp similarity index 100% rename from SDIOBlockDevice.cpp rename to components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp diff --git a/SDIOBlockDevice.h b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h similarity index 100% rename from SDIOBlockDevice.h rename to components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h diff --git a/config/mbed_lib.json b/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json similarity index 100% rename from config/mbed_lib.json rename to components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.h b/hal/sdio_device.h similarity index 100% rename from TARGET_STM/TARGET_STM32F7/sdio_device.h rename to hal/sdio_device.h diff --git a/TARGET_STM/TARGET_STM32F4/sdio_device.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_device.c similarity index 100% rename from TARGET_STM/TARGET_STM32F4/sdio_device.c rename to targets/TARGET_STM/TARGET_STM32F4/sdio_device.c diff --git a/TARGET_STM/TARGET_STM32F7/sdio_device.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_device.c similarity index 100% rename from TARGET_STM/TARGET_STM32F7/sdio_device.c rename to targets/TARGET_STM/TARGET_STM32F7/sdio_device.c From eb4cb06ff5e67f79c392c24397b402eccca3086a Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 26 Mar 2019 20:01:14 +0200 Subject: [PATCH 08/23] Rename sdio_device to sdio_api --- hal/{sdio_device.h => sdio_api.h} | 0 targets/TARGET_STM/TARGET_STM32F4/{sdio_device.c => sdio_api.c} | 0 targets/TARGET_STM/TARGET_STM32F7/{sdio_device.c => sdio_api.c} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename hal/{sdio_device.h => sdio_api.h} (100%) rename targets/TARGET_STM/TARGET_STM32F4/{sdio_device.c => sdio_api.c} (100%) rename targets/TARGET_STM/TARGET_STM32F7/{sdio_device.c => sdio_api.c} (100%) diff --git a/hal/sdio_device.h b/hal/sdio_api.h similarity index 100% rename from hal/sdio_device.h rename to hal/sdio_api.h diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_device.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c similarity index 100% rename from targets/TARGET_STM/TARGET_STM32F4/sdio_device.c rename to targets/TARGET_STM/TARGET_STM32F4/sdio_api.c diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_device.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c similarity index 100% rename from targets/TARGET_STM/TARGET_STM32F7/sdio_device.c rename to targets/TARGET_STM/TARGET_STM32F7/sdio_api.c From bb0d00a6769280e814fa4dee1b6905513f44faf2 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 26 Mar 2019 20:02:08 +0200 Subject: [PATCH 09/23] Remove tests --- TESTS/blockdevice/basic/main.cpp | 119 -- TESTS/filesystem/dirs/main.cpp | 500 --------- TESTS/filesystem/files/main.cpp | 337 ------ TESTS/filesystem/fopen/fopen.cpp | 1621 ---------------------------- TESTS/filesystem/parallel/main.cpp | 209 ---- TESTS/filesystem/seek/main.cpp | 656 ----------- 6 files changed, 3442 deletions(-) delete mode 100644 TESTS/blockdevice/basic/main.cpp delete mode 100644 TESTS/filesystem/dirs/main.cpp delete mode 100644 TESTS/filesystem/files/main.cpp delete mode 100644 TESTS/filesystem/fopen/fopen.cpp delete mode 100644 TESTS/filesystem/parallel/main.cpp delete mode 100644 TESTS/filesystem/seek/main.cpp diff --git a/TESTS/blockdevice/basic/main.cpp b/TESTS/blockdevice/basic/main.cpp deleted file mode 100644 index 709c07b..0000000 --- a/TESTS/blockdevice/basic/main.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include -#include - -using namespace utest::v1; - -// test configuration -#ifndef MBED_TEST_BLOCKDEVICE -#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice -#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; -#endif - -#ifndef MBED_TEST_BLOCKDEVICE_DECL -#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd -#endif - -#ifndef MBED_TEST_BUFFER -#define MBED_TEST_BUFFER 8192 -#endif - -#ifndef MBED_TEST_TIMEOUT -#define MBED_TEST_TIMEOUT 120 -#endif - - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_BLOCKDEVICE) - -MBED_TEST_BLOCKDEVICE_DECL; - -size_t size; -uint8_t buffer[MBED_TEST_BUFFER]; -uint8_t rbuffer[MBED_TEST_BUFFER]; -uint8_t wbuffer[MBED_TEST_BUFFER]; - - -// tests - -// test multiple init-deinit sequences -void test_init_deinit() -{ - for (int repeatCount=0; repeatCount < 10; repeatCount++) - { - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); - } -} - -void test_init_deinit_stacked() -{ - for (int repeatCount=0; repeatCount < 10; repeatCount++) - { - // multiple init - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - // same number of deinit - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); - } -} - - -// test setup -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Init/Deinit test", test_init_deinit), - Case("Init/Deinit stacked test", test_init_deinit_stacked) -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} diff --git a/TESTS/filesystem/dirs/main.cpp b/TESTS/filesystem/dirs/main.cpp deleted file mode 100644 index fcb055a..0000000 --- a/TESTS/filesystem/dirs/main.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include -#include - -using namespace utest::v1; - -// test configuration -#ifndef MBED_TEST_FILESYSTEM -#define MBED_TEST_FILESYSTEM FATFileSystem -#endif - -#ifndef MBED_TEST_FILESYSTEM_DECL -#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") -#endif - -#ifndef MBED_TEST_BLOCKDEVICE -#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice -#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; -#endif - -#ifndef MBED_TEST_BLOCKDEVICE_DECL -#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd -#endif - -#ifndef MBED_TEST_FILES -#define MBED_TEST_FILES 4 -#endif - -#ifndef MBED_TEST_DIRS -#define MBED_TEST_DIRS 4 -#endif - -#ifndef MBED_TEST_BUFFER -#define MBED_TEST_BUFFER 8192 -#endif - -#ifndef MBED_TEST_TIMEOUT -#define MBED_TEST_TIMEOUT 120 -#endif - - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_FILESYSTEM) -#include INCLUDE(MBED_TEST_BLOCKDEVICE) - -MBED_TEST_FILESYSTEM_DECL; -MBED_TEST_BLOCKDEVICE_DECL; - -Dir dir[MBED_TEST_DIRS]; -File file[MBED_TEST_FILES]; -DIR *dd[MBED_TEST_DIRS]; -FILE *fd[MBED_TEST_FILES]; -struct dirent ent; -struct dirent *ed; -size_t size; -uint8_t buffer[MBED_TEST_BUFFER]; -uint8_t rbuffer[MBED_TEST_BUFFER]; -uint8_t wbuffer[MBED_TEST_BUFFER]; - - -// tests - -void test_directory_tests() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = MBED_TEST_FILESYSTEM::format(&bd); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_root_directory() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "/"); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_directory_creation() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("potato", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_file_creation() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "burito", O_CREAT | O_WRONLY); - TEST_ASSERT_EQUAL(0, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void dir_file_check(char *list[], uint32_t elements) -{ - int res; - while (1) { - res = dir[0].read(&ent); - if (0 == res) { - break; - } - for (int i = 0; i < elements ; i++) { - res = strcmp(ent.d_name, list[i]); - if (0 == res) { - res = ent.d_type; - if ((DT_DIR != res) && (DT_REG != res)) { - TEST_ASSERT(1); - } - break; - } else if ( i == elements) { - TEST_ASSERT_EQUAL(0, res); - } - } - } -} - -void test_directory_iteration() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "/"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"potato", "burito", ".", ".."}; - - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_directory_failures() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("potato", 0777); - TEST_ASSERT_EQUAL(-EEXIST, res); - res = dir[0].open(&fs, "tomato"); - TEST_ASSERT_EQUAL(-ENOTDIR, res); - res = dir[0].open(&fs, "burito"); - TEST_ASSERT_NOT_EQUAL(0, res); - res = file[0].open(&fs, "tomato", O_RDONLY); - TEST_ASSERT_EQUAL(-ENOENT, res); - res = file[0].open(&fs, "potato", O_RDONLY); - TEST_ASSERT_NOT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_nested_directories() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("potato/baked", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("potato/sweet", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("potato/fried", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "/"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"potato", "baked", "sweet", "fried", ".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_multi_block_directory() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("cactus", 0777); - TEST_ASSERT_EQUAL(0, res); - for (int i = 0; i < 128; i++) { - sprintf((char *)buffer, "cactus/test%d", i); - res = fs.mkdir((char *)buffer, 0777); - TEST_ASSERT_EQUAL(0, res); - } - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "cactus"); - TEST_ASSERT_EQUAL(0, res); - -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - char *dir_list[] = {".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); -#endif - - for (int i = 0; i < 128; i++) { - sprintf((char *)buffer, "test%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - } - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_directory_remove() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("potato"); - TEST_ASSERT_NOT_EQUAL(0, res); - res = fs.remove("potato/sweet"); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("potato/baked"); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("potato/fried"); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "potato"); - TEST_ASSERT_EQUAL(0, res); - -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - char *dir_list[] = {".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); -#endif - - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("potato"); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "/"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"burito", "cactus", ".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_directory_rename() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("coldpotato", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("coldpotato/baked", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("coldpotato/sweet", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("coldpotato/fried", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("coldpotato", "hotpotato"); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "hotpotato"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("warmpotato", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("warmpotato/mushy", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("hotpotato", "warmpotato"); - TEST_ASSERT_NOT_EQUAL(0, res); - res = fs.remove("warmpotato/mushy"); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("warmpotato"); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("hotpotato", "warmpotato"); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "warmpotato"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("coldpotato", 0777); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("warmpotato/baked", "coldpotato/baked"); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("warmpotato/sweet", "coldpotato/sweet"); - TEST_ASSERT_EQUAL(0, res); - res = fs.rename("warmpotato/fried", "coldpotato/fried"); - TEST_ASSERT_EQUAL(0, res); - res = fs.remove("coldpotato"); - TEST_ASSERT_NOT_EQUAL(0, res); - res = fs.remove("warmpotato"); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "coldpotato"); - TEST_ASSERT_EQUAL(0, res); - char *dir_list[] = {"baked", "sweet", "fried", ".", ".."}; - dir_file_check(dir_list, (sizeof(dir_list) / sizeof(dir_list[0]))); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - - - -// test setup -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Directory tests", test_directory_tests), - Case("Root directory", test_root_directory), - Case("Directory creation", test_directory_creation), - Case("File creation", test_file_creation), - Case("Directory iteration", test_directory_iteration), - Case("Directory failures", test_directory_failures), - Case("Nested directories", test_nested_directories), - Case("Multi-block directory", test_multi_block_directory), - Case("Directory remove", test_directory_remove), - Case("Directory rename", test_directory_rename), -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} diff --git a/TESTS/filesystem/files/main.cpp b/TESTS/filesystem/files/main.cpp deleted file mode 100644 index ed4d242..0000000 --- a/TESTS/filesystem/files/main.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include -#include - -using namespace utest::v1; - -// test configuration -#ifndef MBED_TEST_FILESYSTEM -#define MBED_TEST_FILESYSTEM FATFileSystem -#endif - -#ifndef MBED_TEST_FILESYSTEM_DECL -#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") -#endif - -#ifndef MBED_TEST_BLOCKDEVICE -#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice -#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; -#endif - -#ifndef MBED_TEST_BLOCKDEVICE_DECL -#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd -#endif - -#ifndef MBED_TEST_FILES -#define MBED_TEST_FILES 4 -#endif - -#ifndef MBED_TEST_DIRS -#define MBED_TEST_DIRS 4 -#endif - -#ifndef MBED_TEST_BUFFER -#define MBED_TEST_BUFFER 8192 -#endif - -#ifndef MBED_TEST_TIMEOUT -#define MBED_TEST_TIMEOUT 120 -#endif - - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_FILESYSTEM) -#include INCLUDE(MBED_TEST_BLOCKDEVICE) - -MBED_TEST_FILESYSTEM_DECL; -MBED_TEST_BLOCKDEVICE_DECL; - -Dir dir[MBED_TEST_DIRS]; -File file[MBED_TEST_FILES]; -DIR *dd[MBED_TEST_DIRS]; -FILE *fd[MBED_TEST_FILES]; -struct dirent ent; -struct dirent *ed; -size_t size; -uint8_t buffer[MBED_TEST_BUFFER]; -uint8_t rbuffer[MBED_TEST_BUFFER]; -uint8_t wbuffer[MBED_TEST_BUFFER]; - -static char file_counter = 0; -const char *filenames[] = {"smallavacado", "mediumavacado", "largeavacado", - "blockfile", "bigblockfile", "hello", ".", ".." - }; - -// tests - -void test_file_tests() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = MBED_TEST_FILESYSTEM::format(&bd); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_simple_file_test() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello", O_WRONLY | O_CREAT); - TEST_ASSERT_EQUAL(0, res); - size = strlen("Hello World!\n"); - memcpy(wbuffer, "Hello World!\n", size); - res = file[0].write(wbuffer, size); - TEST_ASSERT_EQUAL(size, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - size = strlen("Hello World!\n"); - res = file[0].read(rbuffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(rbuffer, wbuffer, size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -template -void test_write_file_test() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - size_t size = file_size; - size_t chunk = write_size; - srand(0); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, filenames[file_counter], O_WRONLY | O_CREAT); - TEST_ASSERT_EQUAL(0, res); - for (size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - for (size_t b = 0; b < chunk; b++) { - buffer[b] = rand() & 0xff; - } - res = file[0].write(buffer, chunk); - TEST_ASSERT_EQUAL(chunk, res); - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - size_t size = file_size; - size_t chunk = read_size; - srand(0); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, filenames[file_counter], O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - for (size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - res = file[0].read(buffer, chunk); - TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i + b < size; b++) { - res = buffer[b]; - TEST_ASSERT_EQUAL(rand() & 0xff, res); - } - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - file_counter++; - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_non_overlap_check() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - size_t size = 32; - size_t chunk = 29; - srand(0); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "smallavacado", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - for (size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - res = file[0].read(buffer, chunk); - TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i + b < size; b++) { - res = buffer[b]; - TEST_ASSERT_EQUAL(rand() & 0xff, res); - } - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - size_t size = 8192; - size_t chunk = 29; - srand(0); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "mediumavacado", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - for (size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - res = file[0].read(buffer, chunk); - TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i + b < size; b++) { - res = buffer[b]; - TEST_ASSERT_EQUAL(rand() & 0xff, res); - } - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - { - size_t size = 262144; - size_t chunk = 29; - srand(0); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "largeavacado", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - for (size_t i = 0; i < size; i += chunk) { - chunk = (chunk < size - i) ? chunk : size - i; - res = file[0].read(buffer, chunk); - TEST_ASSERT_EQUAL(chunk, res); - for (size_t b = 0; b < chunk && i + b < size; b++) { - res = buffer[b]; - TEST_ASSERT_EQUAL(rand() & 0xff, res); - } - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_dir_check() -{ - - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "/"); - TEST_ASSERT_EQUAL(0, res); - int numFiles = sizeof(filenames) / sizeof(filenames[0]); - // Check the filenames in directory - while (1) { - res = dir[0].read(&ent); - if (0 == res) { - break; - } - for (int i = 0; i < numFiles ; i++) { - res = strcmp(ent.d_name, filenames[i]); - if (0 == res) { - res = ent.d_type; - if ((DT_REG != res) && (DT_DIR != res)) { - TEST_ASSERT(1); - } - break; - } else if ( i == numFiles) { - TEST_ASSERT_EQUAL(0, res); - } - } - } - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - - -// test setup -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("File tests", test_file_tests), - Case("Simple file test", test_simple_file_test), - Case("Small file test", test_write_file_test<32, 31, 29>), - Case("Medium file test", test_write_file_test<8192, 31, 29>), - Case("Large file test", test_write_file_test<262144, 31, 29>), - Case("Block Size file test", test_write_file_test<9000, 512, 512>), - Case("Multiple block size file test", test_write_file_test<26215, MBED_TEST_BUFFER, MBED_TEST_BUFFER>), - Case("Non-overlap check", test_non_overlap_check), - Case("Dir check", test_dir_check), -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} diff --git a/TESTS/filesystem/fopen/fopen.cpp b/TESTS/filesystem/fopen/fopen.cpp deleted file mode 100644 index 03c6fda..0000000 --- a/TESTS/filesystem/fopen/fopen.cpp +++ /dev/null @@ -1,1621 +0,0 @@ -/* - * mbed Microcontroller Library - * Copyright (c) 2006-2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** @file fopen.cpp Test cases to POSIX file fopen() interface. - * - * Please consult the documentation under the test-case functions for - * a description of the individual test case. - */ - -#include "mbed.h" -#include "mbed_config.h" -#include "SDIOBlockDevice.h" -#include "FATFileSystem.h" -#include "fsfat_debug.h" -#include "fsfat_test.h" -#include "utest/utest.h" -#include "unity/unity.h" -#include "greentea-client/test_env.h" - -#include -#include -#include /*rand()*/ -#include -#include -/* mbed_retarget.h is included after errno.h so symbols are mapped to - * consistent values for all toolchains */ -#include "platform/mbed_retarget.h" - -using namespace utest::v1; - -/// @cond FSFAT_DOXYGEN_DISABLE -#ifdef FSFAT_DEBUG -#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 3000 -#else -#define FSFAT_FOPEN_GREENTEA_TIMEOUT_S 1000 -#endif -/// @endcond - - -/* DEVICE_SPI - * This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support. - * - * MBED_CONF_APP_FSFAT_SDCARD_INSTALLED - * For testing purposes, an SDCard must be installed on the target for the test cases in this file to succeed. - * If the target has an SD card installed then the MBED_CONF_APP_FSFAT_SDCARD_INSTALLED will be generated - * from the mbed_app.json, which includes the line - * { - * "config": { - * "UART_RX": "D0", - * <<< lines removed >>> - * "DEVICE_SPI": 1, - * "FSFAT_SDCARD_INSTALLED": 1 - * }, - * <<< lines removed >>> - */ - -#if defined(DEVICE_SPI) && ( defined(MBED_CONF_APP_FSFAT_SDCARD_INSTALLED) || (MBED_CONF_SD_FSFAT_SDCARD_INSTALLED)) -static char fsfat_fopen_utest_msg_g[FSFAT_UTEST_MSG_BUF_SIZE]; -#define FSFAT_FOPEN_TEST_MOUNT_PT_NAME "sd" -#define FSFAT_FOPEN_TEST_MOUNT_PT_PATH "/" FSFAT_FOPEN_TEST_MOUNT_PT_NAME -#define FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1 64 -#define FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH 20 -static const char *sd_badfile_path = "/sd/badfile.txt"; -static const char *sd_testfile_path = "/sd/test.txt"; - -SDIOBlockDevice sd(); -FATFileSystem fs("sd", &sd); - -#define FSFAT_FOPEN_TEST_01 fsfat_fopen_test_01 -#define FSFAT_FOPEN_TEST_02 fsfat_fopen_test_02 -#define FSFAT_FOPEN_TEST_03 fsfat_fopen_test_03 -#define FSFAT_FOPEN_TEST_04 fsfat_fopen_test_04 -#define FSFAT_FOPEN_TEST_05 fsfat_fopen_test_05 -#define FSFAT_FOPEN_TEST_06 fsfat_fopen_test_06 -#define FSFAT_FOPEN_TEST_07 fsfat_fopen_test_07 -#define FSFAT_FOPEN_TEST_08 fsfat_fopen_test_08 -#define FSFAT_FOPEN_TEST_09 fsfat_fopen_test_09 -#define FSFAT_FOPEN_TEST_10 fsfat_fopen_test_10 -#define FSFAT_FOPEN_TEST_11 fsfat_fopen_test_11 -#define FSFAT_FOPEN_TEST_12 fsfat_fopen_test_12 -#define FSFAT_FOPEN_TEST_13 fsfat_fopen_test_13 -#define FSFAT_FOPEN_TEST_14 fsfat_fopen_test_14 -#define FSFAT_FOPEN_TEST_15 fsfat_fopen_test_15 -#define FSFAT_FOPEN_TEST_16 fsfat_fopen_test_16 -#define FSFAT_FOPEN_TEST_17 fsfat_fopen_test_17 -#define FSFAT_FOPEN_TEST_18 fsfat_fopen_test_18 -#define FSFAT_FOPEN_TEST_19 fsfat_fopen_test_19 -#define FSFAT_FOPEN_TEST_20 fsfat_fopen_test_20 -#define FSFAT_FOPEN_TEST_21 fsfat_fopen_test_21 -#define FSFAT_FOPEN_TEST_22 fsfat_fopen_test_22 -#define FSFAT_FOPEN_TEST_23 fsfat_fopen_test_23 -#define FSFAT_FOPEN_TEST_24 fsfat_fopen_test_24 -#define FSFAT_FOPEN_TEST_25 fsfat_fopen_test_25 -#define FSFAT_FOPEN_TEST_26 fsfat_fopen_test_26 -#define FSFAT_FOPEN_TEST_27 fsfat_fopen_test_27 -#define FSFAT_FOPEN_TEST_28 fsfat_fopen_test_28 -#define FSFAT_FOPEN_TEST_29 fsfat_fopen_test_29 -#define FSFAT_FOPEN_TEST_30 fsfat_fopen_test_30 - - -/* support functions */ - -/* - * open tests that focus on testing fopen() - * fsfat_handle_t fopen(const char* filename, char* data, size_t* len, fsfat_key_desc_t* kdesc) - */ - -/* file data for test_01 */ -static fsfat_kv_data_t fsfat_fopen_test_01_kv_data[] = { - { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt", "missing"}, - { NULL, NULL}, -}; - - -/** @brief - * Split a file path into its component parts, setting '/' characters to '\0', and returning - * pointers to the file path components in the parts array. For example, if - * filepath = "/sd/fopentst/hello/world/animal/wobbly/dog/foot/frontlft.txt" then - * *parts[0] = "sd" - * *parts[1] = "fopentst" - * *parts[2] = "hello" - * *parts[3] = "world" - * *parts[4] = "animal" - * *parts[5] = "wobbly" - * *parts[6] = "dog" - * *parts[7] = "foot" - * *parts[8] = "frontlft.txt" - * parts[9] = NULL - * - * ARGUMENTS - * @param filepath IN file path string to split into component parts. Expected to start with '/' - * @param parts IN OUT array to hold pointers to parts - * @param num IN number of components available in parts - * - * @return On success, this returns the number of components in the filepath Returns number of compoee - */ -static int32_t fsfat_filepath_split(char *filepath, char *parts[], uint32_t num) -{ - uint32_t i = 0; - int32_t ret = -1; - char *z = filepath; - - while (i < num && *z != '\0') { - if (*z == '/' ) { - *z = '\0'; - parts[i] = ++z; - i++; - } else { - z++; - } - } - if (*z == '\0' && i > 0) { - ret = (int32_t) i; - } - return ret; -} - - -/** @brief - * remove all directories and file in the given filepath - * - * ARGUMENTS - * @param filepath IN file path string to split into component parts. Expected to start with '/' - * - * @return On success, this returns 0, otherwise < 0 is returned; - */ -int32_t fsfat_filepath_remove_all(char *filepath) -{ - int32_t ret = -1; - int32_t len = 0; - char *fpathbuf = NULL; - char *pos = NULL; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - len = strlen(filepath); - fpathbuf = (char *) malloc(len + 1); - if (fpathbuf == NULL) { - FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); - return ret; - } - memset(fpathbuf, 0, len + 1); - memcpy(fpathbuf, filepath, len); - - /* delete the leaf node first, and then successively parent directories. */ - pos = fpathbuf + strlen(fpathbuf); - while (pos != fpathbuf) { - /* If the remaining file path is the mount point path then finish as the mount point cannot be removed */ - if (strlen(fpathbuf) == strlen(FSFAT_FOPEN_TEST_MOUNT_PT_PATH)) { - if ( strncmp(fpathbuf, FSFAT_FOPEN_TEST_MOUNT_PT_PATH, strlen(fpathbuf)) == 0) { - break; - } - } - ret = remove(fpathbuf); - pos = strrchr(fpathbuf, '/'); - *pos = '\0'; - } - if (fpathbuf) { - free(fpathbuf); - } - return ret; -} - - -/** @brief - * make all directories in the given filepath. Do not create the file if present at end of filepath - * - * ARGUMENTS - * @param filepath IN file path containing directories and file - * @param do_asserts IN set to true if function should assert on errors - * - * @return On success, this returns 0, otherwise < 0 is returned; - */ -static int32_t fsfat_filepath_make_dirs(char *filepath, bool do_asserts) -{ - int32_t i = 0; - int32_t num_parts = 0; - int32_t len = 0; - int32_t ret = -1; - char *fpathbuf = NULL; - char *buf = NULL; - int pos = 0; - char *parts[FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH]; - - FSFAT_DBGLOG("%s:entered\n", __func__); - /* find the dirs to create*/ - memset(parts, 0, sizeof(parts)); - len = strlen(filepath); - fpathbuf = (char *) malloc(len + 1); - if (fpathbuf == NULL) { - FSFAT_DBGLOG("%s: failed to duplicate string (out of memory)\n", __func__); - return ret; - } - memset(fpathbuf, 0, len + 1); - memcpy(fpathbuf, filepath, len); - num_parts = fsfat_filepath_split(fpathbuf, parts, FSFAT_FOPEN_TEST_FILEPATH_MAX_DEPTH); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to split filepath (filename=\"%s\", num_parts=%d)\n", __func__, filepath, (int) num_parts); - TEST_ASSERT_MESSAGE(num_parts > 0, fsfat_fopen_utest_msg_g); - - /* Now create the directories on the directory path. - * Skip creating dir for "/sd" which must be present */ - buf = (char *) malloc(strlen(filepath) + 1); - memset(buf, 0, strlen(filepath) + 1); - pos = sprintf(buf, "/%s", parts[0]); - for (i = 1; i < num_parts - 1; i++) { - pos += sprintf(buf + pos, "/%s", parts[i]); - FSFAT_DBGLOG("mkdir(%s)\n", buf); - ret = mkdir(buf, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (do_asserts == true) { - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create directory (filepath2=\"%s\", ret=%d, errno=%d)\n", __func__, buf, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - } - } - - if (buf) { - free(buf); - } - if (fpathbuf) { - free(fpathbuf); - } - return ret; -} - - -/* FIX ME: errno not set correctly when error occurs. This indicates a problem with the implementation. */ - -/** @brief - * Basic fopen test which does the following: - * - creates file and writes some data to the value blob. - * - closes the newly created file. - * - opens the file (r-only) - * - reads the file data and checks its the same as the previously created data. - * - closes the opened file - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -static control_t fsfat_fopen_test_01(const size_t call_count) -{ - char *read_buf; - int32_t ret = 0; - size_t len = 0; - fsfat_kv_data_t *node; - FILE *fp = NULL; - - FSFAT_DBGLOG("%s:entered\n", __func__); - (void) call_count; - node = fsfat_fopen_test_01_kv_data; - - /* remove file and directory from a previous failed test run, if present */ - fsfat_filepath_remove_all((char *) node->filename); - - /* create dirs */ - ret = fsfat_filepath_make_dirs((char *) node->filename, true); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - FSFAT_DBGLOG("%s:About to create new file (filename=\"%s\", data=\"%s\")\n", __func__, node->filename, node->value); - fp = fopen(node->filename, "w+"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (filename=\"%s\", data=\"%s\")(ret=%d, errno=%d)\n", __func__, node->filename, - node->value, (int) ret, errno); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - FSFAT_DBGLOG("%s:length of file=%d (filename=\"%s\", data=\"%s\")\n", __func__, (int) len, node->filename, node->value); - len = strlen(node->value); - ret = fwrite((const void *) node->value, len, 1, fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to write file (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, node->value, - (int) ret); - TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); - - FSFAT_DBGLOG("Created file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); - ret = fclose(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* now open the newly created key */ - fp = NULL; - fp = fopen(node->filename, "r"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file for reading (filename=\"%s\", data=\"%s\")(ret=%d)\n", __func__, node->filename, - node->value, (int) ret); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - len = strlen(node->value) + 1; - read_buf = (char *) malloc(len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to allocated read buffer \n", __func__); - TEST_ASSERT_MESSAGE(read_buf != NULL, fsfat_fopen_utest_msg_g); - - FSFAT_DBGLOG("Opened file successfully (filename=\"%s\", data=\"%s\")\n", node->filename, node->value); - memset(read_buf, 0, len); - ret = fread((void *) read_buf, len, 1, fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to read file (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", __func__, node->filename, - node->value, read_buf, (int) ret); - /* FIX ME: fread should return the number of items read, not 0 when an item is read successfully. - * This indicates a problem with the implementation, as the correct data is read. The correct assert should be: - * TEST_ASSERT_MESSAGE(ret == 1, fsfat_fopen_utest_msg_g); - * The following assert is curerntly used until the implementation is fixed - */ - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* check read data is as expected */ - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: read value data (%s) != expected value data (filename=\"%s\", data=\"%s\", read_buf=\"%s\", ret=%d)\n", - __func__, read_buf, node->filename, node->value, read_buf, (int) ret); - TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, fsfat_fopen_utest_msg_g); - - if (read_buf) { - free(read_buf); - } - ret = fclose(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: fclose() call failed (ret=%d, errno=%d).\n", __func__, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - return CaseNext; -} - -static fsfat_kv_data_t fsfat_fopen_test_02_data[] = { - FSFAT_INIT_1_TABLE_MID_NODE, - { NULL, NULL}, -}; - -/** - * @brief test to fopen() a pre-existing key and try to write it, which should fail - * as by default pre-existing keys are opened read-only - * - * Basic open test which does the following: - * - creates file with default rw perms and writes some data to the value blob. - * - closes the newly created file. - * - opens the file with the default permissions (read-only) - * - tries to write the file data which should fail because file was not opened with write flag set. - * - closes the opened key - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_02(const size_t call_count) -{ - int32_t ret = -1; - size_t len = 0; - FILE *fp = NULL; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - len = strlen(fsfat_fopen_test_02_data[0].value); - ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - /* by default, owner of key opens with read-only permissions*/ - fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file (filename=\"%s\", ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - len = strlen(fsfat_fopen_test_02_data[0].value); - ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: call to fwrite() succeeded when should have failed for read-only file (filename=\"%s\")(ret=%d).\n", - __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); - TEST_ASSERT_MESSAGE(ret <= 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", - __func__); - TEST_ASSERT_MESSAGE(fclose(fp) == 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - - -/** - * @brief test to fopen() a pre-existing file and try to write it, which should succeed - * because the key was opened read-write permissions explicitly - * - * Basic open test which does the following: - * - creates file with default rw perms and writes some data to the value blob. - * - closes the newly created file. - * - opens the file with the rw permissions (non default) - * - tries to write the file data which should succeeds because file was opened with write flag set. - * - closes the opened key - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_03(const size_t call_count) -{ - int32_t ret = -1; - size_t len = 0; - FILE *fp = NULL; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - len = strlen(fsfat_fopen_test_02_data[0].value); - ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file in store (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - /* opens with read-write permissions*/ - fp = fopen(fsfat_fopen_test_02_data[0].filename, "w+"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file (filename=\"%s\")(ret=%d)\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - len = strlen(fsfat_fopen_test_02_data[0].value); - ret = fwrite((const void *) fsfat_fopen_test_02_data[0].value, len, 1, fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: call to fwrite() failed when should have succeeded (filename=\"%s\", ret=%d).\n", __func__, - fsfat_fopen_test_02_data[0].filename, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: fclose() call failed.\n", - __func__); - TEST_ASSERT_MESSAGE(fclose(fp) >= 0, fsfat_fopen_utest_msg_g); - - /* clean-up */ - ret = remove(fsfat_fopen_test_02_data[0].filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unable to delete file (filename=%s, ret=%d) .\n", __func__, fsfat_fopen_test_02_data[0].filename, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - - -/** @brief test to call fopen() with a filename string that exceeds the maximum length - * - chanFS supports the exFAT format which should support 255 char filenames - * - check that filenames of this length can be created - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_04(const size_t call_count) -{ - char filename_good[FSFAT_FILENAME_MAX_LENGTH + 1]; - char filename_bad[FSFAT_FILENAME_MAX_LENGTH + 2]; - int32_t ret = -1; - size_t len = 0; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - memset(filename_good, 0, FSFAT_FILENAME_MAX_LENGTH + 1); - memset(filename_bad, 0, FSFAT_FILENAME_MAX_LENGTH + 2); - ret = fsfat_test_filename_gen(filename_good, FSFAT_FILENAME_MAX_LENGTH); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unable to generate filename_good.\n", __func__); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: filename_good is not the correct length (filename_good=%s, len=%d, expected=%d).\n", __func__, filename_good, - (int) strlen(filename_good), (int) FSFAT_FILENAME_MAX_LENGTH); - TEST_ASSERT_MESSAGE(strlen(filename_good) == FSFAT_FILENAME_MAX_LENGTH, fsfat_fopen_utest_msg_g); - - ret = fsfat_test_filename_gen(filename_bad, FSFAT_FILENAME_MAX_LENGTH + 1); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unable to generate filename_bad.\n", __func__); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: filename_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(filename_bad), - (int) FSFAT_FILENAME_MAX_LENGTH + 1); - TEST_ASSERT_MESSAGE(strlen(filename_bad) == FSFAT_FILENAME_MAX_LENGTH + 1, fsfat_fopen_utest_msg_g); - - len = strlen(filename_good); - ret = fsfat_test_create(filename_good, filename_good, len); - /* FIXME: - * The current implementation can create file with a filename with 9 chars (more than the 8 restriction of FAT32 Short File Names). - * However, the exFAT 255 char filesnames is not supported and hence the following is commented out. Find out what is - * the supported max filename length and change this testcase according. - * - * FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create file (filename=%s, ret=%d).\n", __func__, filename_good, (int) ret); - * TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - */ - - len = strlen(filename_bad); - ret = fsfat_test_create(filename_bad, filename_bad, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: created file in store for filename_bad when should have failed (filename=%s, ret=%d).\n", __func__, - filename_bad, (int) ret); - TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); - return CaseNext; -} - - -/// @cond FSFAT_DOXYGEN_DISABLE -typedef struct fsfat_fopen_kv_name_ascii_node { - uint32_t code; - uint32_t f_allowed : 1; -} fsfat_fopen_kv_name_ascii_node; -/// @endcond - -static const uint32_t fsfat_fopen_kv_name_ascii_table_code_sentinel_g = 256; - -/*@brief table recording ascii character codes permitted in kv names */ -static fsfat_fopen_kv_name_ascii_node fsfat_fopen_kv_name_ascii_table[] = { - {0, true}, /* code 0-33 allowed*/ - {34, false}, /* '"' not allowed */ - {35, true}, /* allowed */ - {42, false}, /* '*' not allowed */ - {43, true}, /* allowed */ - {47, false}, /* '/' not allowed */ - {48, true}, /* allowed */ - {58, false}, /* ':' not allowed */ - {59, true}, /* allowed */ - {60, false}, /* '<' not allowed */ - {61, true}, /* allowed */ - {62, false}, /* '?', '>' not allowed */ - {64, true}, /* allowed */ - {92, false}, /* '\' not allowed */ - {93, true}, /* allowed */ - {124, false}, /* '!' not allowed */ - {125, true}, /* allowed */ - {127, false}, /* DEL not allowed */ - {128, true}, /* allowed */ - {fsfat_fopen_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */ -}; - - -/// @cond FSFAT_DOXYGEN_DISABLE -enum fsfat_fopen_kv_name_pos { - fsfat_fopen_kv_name_pos_start = 0x0, - fsfat_fopen_kv_name_pos_mid, - fsfat_fopen_kv_name_pos_end, - fsfat_fopen_kv_name_pos_max -}; -/// @endcond - -/** @brief test to call fopen() with filename that in includes illegal characters - * - the character(s) can be at the beginning of the filename - * - the character(s) can be at the end of the filename - * - the character(s) can be somewhere within the filename string - * - a max-length string of random characters (legal and illegal) - * - a max-length string of random illegal characters only - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_05(const size_t call_count) -{ - bool f_allowed = false; - const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; - const char *basename = "goodfile"; - const char *extname = "txt"; - const size_t basename_len = strlen(basename); - const size_t filename_len = strlen(mnt_pt) + strlen(basename) + strlen(extname) + - 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ - char filename[FSFAT_BUF_MAX_LENGTH]; - size_t len = 0; - uint32_t j = 0; - int32_t ret = 0; - fsfat_fopen_kv_name_ascii_node *node = NULL; - uint32_t pos; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - -#ifdef FSFAT_DEBUG - /* symbol only used why debug is enabled */ - const char *pos_str = NULL; -#endif - - /* create bad keyname strings with invalid character code at start of keyname */ - node = fsfat_fopen_kv_name_ascii_table; - memset(filename, 0, FSFAT_BUF_MAX_LENGTH); - while (node->code != fsfat_fopen_kv_name_ascii_table_code_sentinel_g) { - /* loop over range */ - for (j = node->code; j < (node + 1)->code; j++) { - if ( (j >= 48 && j <= 57) || (j >= 65 && j <= 90) || (j >= 97 && j <= 122)) { - FSFAT_DBGLOG("%s: skipping alpha-numeric ascii character code %d (%c).\n", __func__, (int) j, (char) j); - continue; - } - - /* set the start, mid, last character of the name to the test char code */ - for (pos = (uint32_t) fsfat_fopen_kv_name_pos_start; pos < (uint32_t) fsfat_fopen_kv_name_pos_max; pos++) { - len = snprintf(filename, filename_len + 1, "%s/%s.%s", mnt_pt, basename, extname); - /* overwrite a char at the pos start, mid, end of the filename with an ascii char code (both illegal and legal)*/ - switch (pos) { - case fsfat_fopen_kv_name_pos_start: - filename[5] = (char) j; /* 5 so at to write the second basename char (bad chars as first char not accepted)*/ - break; - case fsfat_fopen_kv_name_pos_mid: - /* create bad keyname strings with invalid character code in the middle of keyname */ - filename[5 + basename_len / 2] = (char) j; - break; - case fsfat_fopen_kv_name_pos_end: - /* create bad keyname strings with invalid character code at end of keyname */ - filename[5 + basename_len - 1] = (char) j; - break; - default: - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - break; - } - -#ifdef FSFAT_DEBUG - /* processing only required when debug trace enabled */ - switch (pos) { - case fsfat_fopen_kv_name_pos_start: - pos_str = "start"; - break; - case fsfat_fopen_kv_name_pos_mid: - pos_str = "middle"; - break; - case fsfat_fopen_kv_name_pos_end: - pos_str = "end"; - break; - default: - break; - } -#endif - ret = fsfat_test_create(filename, (const char *) filename, len); - - /* special cases */ - switch (j) { - //case 0 : - //case 46 : - // switch(pos) - // { - // /* for code = 0 (null terminator). permitted at mid and end of string */ - // /* for code = 46 ('.'). permitted at mid and end of string but not at start */ - // case fsfat_fopen_kv_name_pos_start: - // f_allowed = false; - // break; - // case fsfat_fopen_kv_name_pos_mid: - // case fsfat_fopen_kv_name_pos_end: - // default: - // f_allowed = true; - // break; - // } - // break; - default: - f_allowed = node->f_allowed; - break; - } - if (f_allowed == true) { - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file in store when filename contains valid characters (code=%d, ret=%d).\n", __func__, - (int) j, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - /* revert FSFAT_LOG for more trace */ - FSFAT_DBGLOG("Successfully created a file with valid keyname containing ascii character code %d (%c) at the %s of the keyname.\n", - (int) j, (int) j, pos_str); - FSFAT_LOG("%c", '.'); - - ret = fsfat_test_delete(filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to delete file previously created (code=%d, ret=%d).\n", __func__, (int) j, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - } else { - /*node->f_allowed == false => not allowed to create kv name with ascii code */ - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: created file in store when filename contains an invalid character (code=%d, ret=%d).\n", __func__, (int) j, - (int) ret); - TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); - /* revert FSFAT_LOG for more trace */ - FSFAT_DBGLOG("Successfully failed to create a file with an invalid keyname containing ascii character code %d at the %s of the keyname.\n", - (int) j, pos_str); - FSFAT_LOG("%c", '.'); - } - } - } - node++; - } - - FSFAT_LOG("%c", '\n'); - return CaseNext; -} - - -static const char fsfat_fopen_ascii_illegal_buf_g[] = "\"�'*+,./:;<=>?[\\]|"; - -/** @brief test to call fopen() with filename that in includes - * illegal characters - * - a max-length string of random illegal characters only - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_06(const size_t call_count) -{ - const char *mnt_pt = FSFAT_FOPEN_TEST_MOUNT_PT_PATH; - const char *extname = "txt"; - const size_t filename_len = strlen(mnt_pt) + FSFAT_MAX_FILE_BASENAME + strlen(extname) + - 2; /* extra 2 chars for '/' and '.' in "/sd/goodfile.txt" */ - char filename[FSFAT_BUF_MAX_LENGTH]; - int32_t i = 0; - int32_t j = 0; - uint32_t pos = 0; - uint32_t len = 0; - int32_t ret = -1; - size_t buf_data_max = 0; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - memset(filename, 0, FSFAT_BUF_MAX_LENGTH); - /* create bad keyname strings with invalid character code at start of keyname */ - buf_data_max = strlen(fsfat_fopen_ascii_illegal_buf_g); - - /* generate a number of illegal filenames */ - for (j = 0; i < FSFAT_MAX_FILE_BASENAME; j++) { - /* generate a kv name of illegal chars*/ - len = snprintf(filename, filename_len + 1, "%s/", mnt_pt); - for (i = 0; i < FSFAT_MAX_FILE_BASENAME; i++) { - pos = rand() % (buf_data_max + 1); - len += snprintf(filename + len, filename_len + 1, "%c", fsfat_fopen_ascii_illegal_buf_g[pos]); - - } - len += snprintf(filename + len, filename_len + 1, ".%s", extname); - ret = fsfat_test_create(filename, filename, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: created file when filename contains invalid characters (filename=%s, ret=%d).\n", __func__, filename, - (int) ret); - TEST_ASSERT_MESSAGE(ret < 0, fsfat_fopen_utest_msg_g); - } - return CaseNext; -} - - -/** @brief test for errno reporting on a failed fopen()call - * - * This test does the following: - * - tries to open a file that does not exist for reading, and checks that a NULL pointer is returned. - * - checks that errno is not 0 as there is an error. - * - checks that ferror() returns 1 indicating an error exists. - * - * Note: see NOTE_1 below. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_07(const size_t call_count) -{ - FILE *f = NULL; - int ret = -1; - int errno_val = 0; - const char *filename = sd_badfile_path; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - errno = 0; - /* this is expect to fail as the file doesnt exist */ - f = fopen(filename, "r"); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: opened non-existent file for reading (filename=%s, f=%p).\n", __func__, filename, f); - TEST_ASSERT_MESSAGE(f == NULL, fsfat_fopen_utest_msg_g); - - /* check errno is set correctly */ -#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) - /* Store errno so the current value set is not changed by new function call */ - errno_val = errno; - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: errno has unexpected value (errno != 0 expected) (filename=%s, errno=%d).\n", __func__, filename, errno); - TEST_ASSERT_MESSAGE(errno_val != 0, fsfat_fopen_utest_msg_g); -#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ - return CaseNext; -} - - -/** @brief test for operation of clearerr() and ferror() - * - * The test does the following: - * - opens and then closes a file, but keeps a copy of the FILE pointer fp. - * - set errno to 0. - * - write to the close file with fwrite(fp) which should return 0 (no writes) and set the errno. - * - check the error condition is set with ferror(). - * - clear the error with clearerr(). - * - check the error condition is reset with ferror(). - * - * NOTE_1: GCC/ARMCC support for setting errno - * - Documentation (e.g. fwrite() man page) does not explicity say fwrite() sets errno - * (e.g. for an fwrite() on a read-only file). - * - GCC libc fwrite() appears to set errno as expected. - * - ARMCC & IAR libc fwrite() appears not to set errno. - * - * The following ARMCC documents are silent on whether fwrite() sets errno: - * - "ARM C and C++ Libraries and Floating-Point Support". - * - "RL-ARM User Guide fwrite() section". - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_08(const size_t call_count) -{ - FILE *fp = NULL; - int ret = -1; - int ret_ferror = -1; - const char *filename = sd_testfile_path; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - errno = 0; - fp = fopen(filename, "w+"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file (filename=%s, f=%p).\n", __func__, filename, fp); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - /* close the fp but then try to read or write it */ - ret = fclose(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* open file */ - errno = 0; - fp = fopen(filename, "r"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file for reading (filename=\"%s\", ret=%d)\n", __func__, filename, (int) ret); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - /* Perform fwrite() operation that will fail. */ - errno = 0; - ret = fwrite("42!", 4, 1, fp); - - ret_ferror = ferror(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: ferror() failed to report error (filename=%s, ret_ferror=%d).\n", __func__, filename, (int) ret_ferror); - TEST_ASSERT_MESSAGE(ret_ferror != 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: fwrite successfully wrote to read-only file (filename=%s, ret=%d).\n", __func__, filename, (int) ret); - /* the fwrite() should fail and return 0. */ - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - -#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) - /* check that errno is set. ARMCC appears not to set errno for fwrite() failure. */ - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unexpected zero value for errno (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(errno != 0, fsfat_fopen_utest_msg_g); - - /* check that errno is set to the expected value (this may change differ for different libc's) */ - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: errno != EBADF (filename=%s, ret=%d, errno=%d).\n", __func__, filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(errno == EBADF, fsfat_fopen_utest_msg_g); -#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ - - /* check clearerr() return clears the error */ - clearerr(fp); - ret = ferror(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: ferror() did not return zero value when error has been cleared (filename=%s, ret=%d).\n", __func__, filename, - (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - fclose(fp); - return CaseNext; -} - - -/** @brief test for operation of ftell() - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_09(const size_t call_count) -{ - FILE *fp = NULL; - int ret = -1; - int32_t len = 0; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - /* create a file of a certain length */ - len = strlen(fsfat_fopen_test_02_data[0].value); - ret = fsfat_test_create(fsfat_fopen_test_02_data[0].filename, (char *) fsfat_fopen_test_02_data[0].value, len); - - errno = 0; - /* Open the file for reading so the file is not truncated to 0 length. */ - fp = fopen(fsfat_fopen_test_02_data[0].filename, "r"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to open file (filename=%s, fp=%p, errno=%d).\n", __func__, fsfat_fopen_test_02_data[0].filename, fp, - errno); - TEST_ASSERT_MESSAGE(fp != NULL, fsfat_fopen_utest_msg_g); - - errno = 0; - ret = fseek(fp, 0, SEEK_END); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: fseek() failed to SEEK_END (filename=%s, ret=%d, errno=%d).\n", __func__, - fsfat_fopen_test_02_data[0].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - errno = 0; - ret = ftell(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: ftell() failed to report correct offset value (filename=%s, ret=%d, errno=%d).\n", __func__, - fsfat_fopen_test_02_data[0].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == len, fsfat_fopen_utest_msg_g); - - errno = 0; - ret = fclose(fp); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to close file (ret=%d, errno=%d)\n", __func__, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - - -/* file data for test_10 */ -static fsfat_kv_data_t fsfat_fopen_test_10_kv_data[] = { - { "/sd/test_10/testfile.txt", "test_data"}, - { NULL, NULL}, -}; - -/** @brief test for operation of remove() - * - * Performs the following tests: - * 1. test remove() on a file that exists. This should succeed. - * 2. test remove() on a dir that exists. This should succeed. - * 3. test remove() on a file that doesnt exist. This should fail. check errno set. - * 4. test remove() on a dir that doesnt exist. This should fail. check errno set. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_10(const size_t call_count) -{ - char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; - char *pos = NULL; - int32_t ret = -1; - size_t len = 0; - fsfat_kv_data_t *node = fsfat_fopen_test_10_kv_data; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - - /* start from a known state i.e. directory to be created in not present */ - fsfat_filepath_remove_all((char *) node->filename); - - /* (1) */ - errno = 0; - ret = fsfat_filepath_make_dirs((char *) node->filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - len = strlen(node->value); - ret = fsfat_test_create(node->filename, (char *) node->value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - ret = remove(node->filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: delete file operation failed (filename=%s, ret=%d) .\n", __func__, node->filename, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* (3) */ - ret = remove(node->filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: deleted a file that doesn't exist (filename=%s, ret=%d, errno=%d) .\n", __func__, node->filename, (int) ret, - errno); - TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); - - /* (2) */ - memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - memcpy(buf, node->filename, strlen(node->filename)); - pos = strrchr(buf, '/'); - *pos = '\0'; - ret = remove(buf); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: delete directory operation failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, - errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* (4) */ - ret = remove(buf); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: deleted a directory that doesn't exist (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, - errno); - TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - - -/* file data for test_11 */ -static fsfat_kv_data_t fsfat_fopen_test_11_kv_data[] = { - { "/sd/test_11/step0.txt", "test_data"}, - { "/sd/test_11/step1.txt", "test_data"}, - { "/sd/test_11/subdir/step3.txt", "test_data"}, - { NULL, NULL}, -}; - -/** @brief test for operation of rename() - * - * This test does the following: - * 1) test rename() on a file that exists to a new filename within the same directory. - * 2) test rename() on a file that exists to a new filename within a different directory. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_11(const size_t call_count) -{ - int32_t ret = -1; - size_t len = 0; - fsfat_kv_data_t *node = fsfat_fopen_test_11_kv_data; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - - /* start from a known state i.e. directory to be created in not present, files not present */ - while (node->filename != NULL) { - fsfat_filepath_remove_all((char *) node->filename); - node++; - } - - /* create file and directories ready for rename() tests */ - errno = 0; - node = fsfat_fopen_test_11_kv_data; - ret = fsfat_filepath_make_dirs((char *) node->filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - len = strlen(node->value); - ret = fsfat_test_create(node->filename, (char *) node->value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - errno = 0; - node = &fsfat_fopen_test_11_kv_data[2]; - ret = fsfat_filepath_make_dirs((char *) node->filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* (1) */ - ret = rename(fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, - fsfat_fopen_test_11_kv_data[0].filename, fsfat_fopen_test_11_kv_data[1].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* (2) */ - ret = rename(fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unable to rename file from (%s) to (%s) (ret=%d, errno=%d).\n", __func__, - fsfat_fopen_test_11_kv_data[1].filename, fsfat_fopen_test_11_kv_data[2].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - - -/* file data for test_12 */ -static fsfat_kv_data_t fsfat_fopen_test_12_kv_data[] = { - { "/sd/test_12/subdir/testfil1.txt", "testfil1.txt"}, - { "/sd/test_12/testfil2.txt", "testfil2.txt"}, - { "/sd/test_12/testfil3.txt", "testfil3.txt"}, - { "/sd/test_12/testfil4.txt", "testfil4.txt"}, - { "/sd/test_12/testfil5.txt", "testfil5.txt"}, - { NULL, NULL}, -}; - -/** @brief test for operation of readdir(). - * - * Note, rewinddir(), telldir() and seekdir() dont appear to work reliably. - * opendir() not available on ARM/IAR toolchains. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_12(const size_t call_count) -{ - char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; - char *pos = NULL; - int32_t count = 0; - int32_t ret = -1; - size_t len = 0; - DIR *dir; - struct dirent *dp; - fsfat_kv_data_t *node = fsfat_fopen_test_12_kv_data; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - -#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) - - /* start from a known state i.e. directory to be created in not present */ - while (node->filename != NULL) { - fsfat_filepath_remove_all((char *) node->filename); - node++; - } - - /* create a file */ - node = fsfat_fopen_test_12_kv_data; - errno = 0; - ret = fsfat_filepath_make_dirs((char *) node->filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - node = fsfat_fopen_test_12_kv_data; - while (node->filename != NULL) { - len = strlen(node->value); - ret = fsfat_test_create(node->filename, (char *) node->value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - node++; - } - - node = fsfat_fopen_test_12_kv_data; - memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - memcpy(buf, node->filename, strlen(node->filename)); - pos = strrchr(buf, '/'); - *pos = '\0'; - dir = opendir(buf); - - while ((dp = readdir(dir)) != NULL) { - FSFAT_DBGLOG("%s: filename: \"%s\"\n", __func__, dp->d_name); - TEST_ASSERT_MESSAGE(dp != 0, "Error: readdir() failed\n"); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unexpected object name (name=%s, expected=%s).\n", __func__, dp->d_name, - fsfat_fopen_test_12_kv_data[count].value); - TEST_ASSERT_MESSAGE(strncmp(dp->d_name, fsfat_fopen_test_12_kv_data[count].value, - strlen(fsfat_fopen_test_12_kv_data[count].value)) == 0, fsfat_fopen_utest_msg_g); - count++; - } - closedir(dir); - - /* cleanup */ - node = fsfat_fopen_test_12_kv_data; - while (node->filename != NULL) { - fsfat_filepath_remove_all((char *) node->filename); - node++; - } -#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ - return CaseNext; -} - - -/* file data for test_13 */ -static fsfat_kv_data_t fsfat_fopen_test_13_kv_data[] = { - /* a file is included in the filepath even though its not created by the test, - * as the fsfat_filepath_make_dirs() works with it present. */ - { "/sd/test_13/dummy.txt", "testdir"}, - { NULL, NULL}, -}; -/** @brief test for operation of mkdir()/remove() - * - * This test checks that: - * - The mkdir() function successfully creates a directory that is not already present. - * - The mkdir() function returns EEXIST when trying to create a directory thats already present. - * - The remove() function successfully removes a directory that is present. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_13(const size_t call_count) -{ - int32_t ret = 0; - - FSFAT_DBGLOG("%s:entered\n", __func__); - (void) call_count; - - /* start from a known state i.e. directory to be created in not present */ - fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); - - errno = 0; - ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, - (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - /* check that get a suitable error when try to create it again.*/ - errno = 0; - ret = fsfat_filepath_make_dirs((char *) fsfat_fopen_test_13_kv_data[0].filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: permitted to create directory when already exists (dirname=%s, ret=%d, errno=%d)\n", __func__, - fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret != 0, fsfat_fopen_utest_msg_g); - - /* check errno is as expected */ - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: errno != EEXIST (dirname=%s, ret=%d, errno=%d)\n", __func__, fsfat_fopen_test_13_kv_data[0].filename, - (int) ret, errno); - TEST_ASSERT_MESSAGE(errno == EEXIST, fsfat_fopen_utest_msg_g); - - ret = fsfat_filepath_remove_all((char *) fsfat_fopen_test_13_kv_data[0].filename); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to remove directory (dirname=%s, ret=%d, errno=%d)\n", __func__, - fsfat_fopen_test_13_kv_data[0].filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - return CaseNext; -} - -/* file data for test_14 */ -static fsfat_kv_data_t fsfat_fopen_test_14_kv_data[] = { - /* a file is included in the filepath even though its not created by the test, - * as the fsfat_filepath_make_dirs() works with it present. */ - { "/sd/test_14/testfile.txt", "testdata"}, - { NULL, NULL}, -}; - -/** @brief test for operation of stat() - * - * stat() is currently no supported by ARMCC and IAR toolchains libc. - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_14(const size_t call_count) -{ -#if ! defined(__ARMCC_VERSION) && defined(__GNUC__) - - char buf[FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1]; - char *pos = NULL; - int32_t ret = -1; - size_t len = 0; - struct stat file_stat; - fsfat_kv_data_t *node = fsfat_fopen_test_14_kv_data; - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - - TEST_ASSERT(strlen(node->filename) < FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - - /* start from a known state i.e. directory to be created in not present */ - fsfat_filepath_remove_all((char *) node->filename); - - /* Create file in a directory. */ - errno = 0; - ret = fsfat_filepath_make_dirs((char *) node->filename, false); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dir (dirname=%s, ret=%d, errno=%d)\n", __func__, node->filename, (int) ret, errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - len = strlen(node->value); - ret = fsfat_test_create(node->filename, (char *) node->value, len); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create file (ret=%d).\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret >= 0, fsfat_fopen_utest_msg_g); - - /* Test stat() on the file returns the correct attribute set */ - memset(&file_stat, 0, sizeof(file_stat)); - ret = stat(node->filename, &file_stat); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: stat() operation on file failed (filename=%s, ret=%d, errno=%d).\n", __func__, node->filename, (int) ret, - errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: expected st_mode S_IFREG flag not set (filename=%s).\n", __func__, node->filename); - TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) == S_IFREG, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unexpected st_mode S_IFDIR flag set (filename=%s).\n", __func__, node->filename); - TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) != S_IFDIR, fsfat_fopen_utest_msg_g); - - /* Test stat() on the directory returns the correct attribute set */ - memset(&file_stat, 0, sizeof(file_stat)); - memset(buf, 0, FSFAT_FOPEN_TEST_WORK_BUF_SIZE_1); - memcpy(buf, node->filename, strlen(node->filename)); - pos = strrchr(buf, '/'); - *pos = '\0'; - ret = stat(buf, &file_stat); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: stat() operation on directory failed (directory name=%s, ret=%d, errno=%d).\n", __func__, buf, (int) ret, - errno); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: unexpected st_mode S_IFREG flag set (directory name=%s).\n", __func__, buf); - TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFREG) != S_IFREG, fsfat_fopen_utest_msg_g); - - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: expected st_mode S_IFDIR flag not set (directory name=%s).\n", __func__, buf); - TEST_ASSERT_MESSAGE((file_stat.st_mode & S_IFDIR) == S_IFDIR, fsfat_fopen_utest_msg_g); - - /* clean up after successful test */ - fsfat_filepath_remove_all((char *) node->filename); - -#endif /* ! defined(__ARMCC_VERSION) && defined(__GNUC__) */ - return CaseNext; -} - -/** @brief test for operation of SDFileSystem::format() - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_15(const size_t call_count) -{ - - FSFAT_FENTRYLOG("%s:entered\n", __func__); - (void) call_count; - int32_t ret = -1; - - /* the allocation_unit of 0 means chanFS will use the default for the card (varies according to capacity). */ - fs.unmount(); - ret = fs.format(&sd); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to format sdcard (ret=%d)\n", __func__, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - fs.mount(&sd); - return CaseNext; -} - - -/* @brief test utility function to create a file of a given size. - * - * A reference data table is used of so that the data file can be later be - * checked with fsfat_test_check_data_file(). - * - * @param filename name of the file including path - * @param data data to store in file - * @param len number of bytes of data present in the data buffer. - */ -int32_t fsfat_test_create_data_file(const char *filename, size_t len) -{ - int32_t ret = -1; - FILE *fp = NULL; - size_t write_len = 0; - size_t written_len = 0; - int32_t exp = 0; - const int32_t exp_max = 8; /* so as not to exceed FSFAT_TEST_BYTE_DATA_TABLE_SIZE/2 */ - - FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); - TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); - fp = fopen(filename, "a"); - if (fp == NULL) { - return ret; - } - - while (written_len < len) { - /* write fsfat_test_byte_data_table or part thereof, in 9 writes of sizes - * 1, 2, 4, 8, 16, 32, 64, 128, 1, totalling 256 bytes len permitting. */ - for (exp = 0; (exp <= exp_max) && (written_len < len); exp++) { - write_len = 0x1 << (exp % exp_max); - write_len = len - written_len > write_len ? write_len : len - written_len; - ret = fwrite((const void *) &fsfat_test_byte_data_table[written_len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE], write_len, 1, - fp); - written_len += write_len; - if (ret != 1) { - FSFAT_DBGLOG("%s:Error: fwrite() failed (ret=%d)\n", __func__, (int) ret); - ret = -1; - goto out0; - } - } - } - if (written_len == len) { - ret = 0; - } else { - ret = -1; - } -out0: - fclose(fp); - return ret; -} - - -/* @brief test utility function to check the data in the specified file is correct. - * - * The data read from the file is check that it agrees with the data written by - * fsfat_test_create_data_file(). - * - * @param filename name of the file including path - * @param data data to store in file - * @param len number of bytes of data present in the data buffer. - */ -int32_t fsfat_test_check_data_file(const char *filename, size_t len) -{ - int32_t ret = -1; - FILE *fp = NULL; - size_t read_len = 0; - uint8_t buf[FSFAT_TEST_BYTE_DATA_TABLE_SIZE]; - - FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len); - TEST_ASSERT(len % FSFAT_TEST_BYTE_DATA_TABLE_SIZE == 0); - fp = fopen(filename, "r"); - if (fp == NULL) { - return ret; - } - - while (read_len < len) { - ret = fread((void *) buf, FSFAT_TEST_BYTE_DATA_TABLE_SIZE, 1, fp); - read_len += FSFAT_TEST_BYTE_DATA_TABLE_SIZE; - if (ret == 0) { - /* end of read*/ - FSFAT_DBGLOG("%s:unable to read data\n", __func__); - break; - } - if (memcmp(buf, fsfat_test_byte_data_table, FSFAT_TEST_BYTE_DATA_TABLE_SIZE) != 0) { - FSFAT_DBGLOG("%s:Error: read data not as expected (0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x, 0x%2x\n", - __func__, - buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], - buf[14], buf[15]); - ret = -1; - goto out0; - } - } - if (read_len == len) { - ret = 0; - } -out0: - fclose(fp); - return ret; -} - -/* file data for test_16 */ -static fsfat_kv_data_t fsfat_fopen_test_16_kv_data[] = { - { "/sd/tst16_0/testfil0.txt", "dummy_data"}, - { "/sd/tst16_1/subdir0/testfil0.txt", "dummy_data"}, - { "/sd/tst16_2/subdir0/subdir1/testfil0.txt", "dummy_data"}, - { "/sd/tst16_3/subdir0/subdir1/subdir2/subdir3/testfil0.txt", "dummy_data"}, - { "/sd/tst16_4/subdir0/subdir1/subdir2/subdir3/subdir4/testfil0.txt", "dummy_data"}, - { "/sd/tst16_5/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/testfil0.txt", "dummy_data"}, - { "/sd/tst16_6/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/testfil0.txt", "dummy_data"}, - { "/sd/tst16_7/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/testfil0.txt", "dummy_data"}, - { "/sd/tst16_8/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/testfil0.txt", "dummy_data"}, - { "/sd/tst16_9/subdir0/subdir1/subdir2/subdir3/subdir4/subdir5/subdir6/subdir7/subdir8/subdir9/testfil0.txt", "dummy_data"}, - { NULL, NULL}, -}; - - -/** @brief stress test to write data to fs - * - * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. - */ -control_t fsfat_fopen_test_16(const size_t call_count) -{ - int32_t ret = 0; - fsfat_kv_data_t *node = fsfat_fopen_test_16_kv_data; - const int32_t num_blocks = 100; /* each file ~25kB */ - - FSFAT_DBGLOG("%s:entered\n", __func__); - (void) call_count; - - /* remove file and directory from a previous failed test run, if present */ - while (node->filename != NULL) { - fsfat_filepath_remove_all((char *) node->filename); - node++; - } - - /* create dirs */ - node = fsfat_fopen_test_16_kv_data; - while (node->filename != NULL) { - ret = fsfat_filepath_make_dirs((char *) node->filename, true); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create dirs for filename (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - node++; - } - - /* create the data files */ - node = fsfat_fopen_test_16_kv_data; - while (node->filename != NULL) { - ret = fsfat_test_create_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to create data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - node++; - } - - /* read the data back and check its as expected */ - node = fsfat_fopen_test_16_kv_data; - while (node->filename != NULL) { - ret = fsfat_test_check_data_file(node->filename, num_blocks * FSFAT_TEST_BYTE_DATA_TABLE_SIZE); - FSFAT_TEST_UTEST_MESSAGE(fsfat_fopen_utest_msg_g, FSFAT_UTEST_MSG_BUF_SIZE, - "%s:Error: failed to check data file (filename=\"%s\")(ret=%d)\n", __func__, node->filename, (int) ret); - TEST_ASSERT_MESSAGE(ret == 0, fsfat_fopen_utest_msg_g); - node++; - } - - /* clean up */ - node = fsfat_fopen_test_16_kv_data; - while (node->filename != NULL) { - fsfat_filepath_remove_all((char *) node->filename); - node++; - } - return CaseNext; -} - - -#else - - -#define FSFAT_FOPEN_TEST_01 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_02 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_03 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_04 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_05 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_06 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_07 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_08 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_09 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_10 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_11 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_12 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_13 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_14 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_15 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_16 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_17 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_18 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_19 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_20 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_21 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_22 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_23 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_24 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_25 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_26 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_27 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_28 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_29 fsfat_fopen_test_dummy -#define FSFAT_FOPEN_TEST_30 fsfat_fopen_test_dummy - -/** @brief fsfat_fopen_test_dummy Dummy test case for testing when platform doesnt have an SDCard installed. - * - * @return success always - */ -static control_t fsfat_fopen_test_dummy() -{ - printf("Null test\n"); - return CaseNext; -} - -#endif - - -/// @cond FSFAT_DOXYGEN_DISABLE -utest::v1::status_t greentea_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(FSFAT_FOPEN_GREENTEA_TIMEOUT_S, "default_auto"); - return greentea_test_setup_handler(number_of_cases); -} - -Case cases[] = { - /* 1 2 3 4 5 6 7 */ - /* 1234567890123456789012345678901234567890123456789012345678901234567890 */ - Case("FSFAT_FOPEN_TEST_01: fopen()/fwrite()/fclose() directories/file in multi-dir filepath.", FSFAT_FOPEN_TEST_01), - Case("FSFAT_FOPEN_TEST_02: fopen(r) pre-existing file try to write it.", FSFAT_FOPEN_TEST_02), - Case("FSFAT_FOPEN_TEST_03: fopen(w+) pre-existing file try to write it.", FSFAT_FOPEN_TEST_03), - Case("FSFAT_FOPEN_TEST_04: fopen() with a filename exceeding the maximum length.", FSFAT_FOPEN_TEST_04), -#ifdef FOPEN_EXTENDED_TESTING - Case("FSFAT_FOPEN_TEST_05: fopen() with bad filenames (extended).", FSFAT_FOPEN_TEST_05), -#endif - Case("FSFAT_FOPEN_TEST_06: fopen() with bad filenames (minimal).", FSFAT_FOPEN_TEST_06), - Case("FSFAT_FOPEN_TEST_07: fopen()/errno handling.", FSFAT_FOPEN_TEST_07), - Case("FSFAT_FOPEN_TEST_08: ferror()/clearerr()/errno handling.", FSFAT_FOPEN_TEST_08), - Case("FSFAT_FOPEN_TEST_09: ftell() handling.", FSFAT_FOPEN_TEST_09), - Case("FSFAT_FOPEN_TEST_10: remove() test.", FSFAT_FOPEN_TEST_10), - Case("FSFAT_FOPEN_TEST_11: rename().", FSFAT_FOPEN_TEST_11), - Case("FSFAT_FOPEN_TEST_12: opendir(), readdir(), closedir() test.", FSFAT_FOPEN_TEST_12), - Case("FSFAT_FOPEN_TEST_13: mkdir() test.", FSFAT_FOPEN_TEST_13), - Case("FSFAT_FOPEN_TEST_14: stat() test.", FSFAT_FOPEN_TEST_14), - Case("FSFAT_FOPEN_TEST_15: format() test.", FSFAT_FOPEN_TEST_15), - Case("FSFAT_FOPEN_TEST_16: write/check n x 25kB data files.", FSFAT_FOPEN_TEST_16), -}; - - -/* Declare your test specification with a custom setup handler */ -Specification specification(greentea_setup, cases); - -int main() -{ - return !Harness::run(specification); -} -/// @endcond diff --git a/TESTS/filesystem/parallel/main.cpp b/TESTS/filesystem/parallel/main.cpp deleted file mode 100644 index 2ae26ee..0000000 --- a/TESTS/filesystem/parallel/main.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include -#include - -using namespace utest::v1; - -// test configuration -#ifndef MBED_TEST_FILESYSTEM -#define MBED_TEST_FILESYSTEM FATFileSystem -#endif - -#ifndef MBED_TEST_FILESYSTEM_DECL -#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") -#endif - -#ifndef MBED_TEST_BLOCKDEVICE -#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice -#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; -#endif - -#ifndef MBED_TEST_BLOCKDEVICE_DECL -#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd -#endif - -#ifndef MBED_TEST_FILES -#define MBED_TEST_FILES 4 -#endif - -#ifndef MBED_TEST_DIRS -#define MBED_TEST_DIRS 4 -#endif - -#ifndef MBED_TEST_BUFFER -#define MBED_TEST_BUFFER 512 -#endif - -#ifndef MBED_TEST_TIMEOUT -#define MBED_TEST_TIMEOUT 120 -#endif - -#ifndef MBED_THREAD_COUNT -#define MBED_THREAD_COUNT MBED_TEST_FILES -#endif - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_FILESYSTEM) -#include INCLUDE(MBED_TEST_BLOCKDEVICE) - -MBED_TEST_FILESYSTEM_DECL; -MBED_TEST_BLOCKDEVICE_DECL; - -Dir dir[MBED_TEST_DIRS]; -File file[MBED_TEST_FILES]; -DIR *dd[MBED_TEST_DIRS]; -FILE *fd[MBED_TEST_FILES]; -struct dirent ent; -struct dirent *ed; - -volatile bool count_done = 0; - -// tests - -void test_file_tests() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = MBED_TEST_FILESYSTEM::format(&bd); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void write_file_data (char count) -{ - - char filename[10]; - uint8_t wbuffer[MBED_TEST_BUFFER]; - int res; - - sprintf(filename, "%s%d", "data", count); - res = file[count].open(&fs, filename, O_WRONLY | O_CREAT); - TEST_ASSERT_EQUAL(0, res); - - char letter = 'A' + count; - for (uint32_t i = 0; i < MBED_TEST_BUFFER; i++) { - wbuffer[i] = letter++; - if ('z' == letter) { - letter = 'A' + count; - } - } - - for (uint32_t i = 0; i < 5; i++) { - res = file[count].write(wbuffer, MBED_TEST_BUFFER); - TEST_ASSERT_EQUAL(MBED_TEST_BUFFER, res); - } - - res = file[count].close(); - TEST_ASSERT_EQUAL(0, res); -} - -void read_file_data (char count) -{ - char filename[10]; - uint8_t rbuffer[MBED_TEST_BUFFER]; - int res; - - sprintf(filename, "%s%d", "data", count); - res = file[count].open(&fs, filename, O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - - for (uint32_t i = 0; i < 5; i++) { - res = file[count].read(rbuffer, MBED_TEST_BUFFER); - TEST_ASSERT_EQUAL(MBED_TEST_BUFFER, res); - char letter = 'A' + count; - for (uint32_t i = 0; i < MBED_TEST_BUFFER; i++) { - res = rbuffer[i]; - TEST_ASSERT_EQUAL(letter++, res); - if ('z' == letter) { - letter = 'A' + count; - } - } - } - - res = file[count].close(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_thread_access_test() -{ - char *dummy = new (std::nothrow) char[OS_STACK_SIZE * MBED_THREAD_COUNT]; - delete[] dummy; - TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough memory to run test"); - - Thread *data[MBED_THREAD_COUNT]; - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - - // Write threads in parallel - for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { - data[thread_count] = new Thread(osPriorityNormal); - data[thread_count]->start(callback((void(*)(void *))write_file_data, (void *)thread_count)); - } - - // Wait for write thread to join before creating read thread - for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { - data[thread_count]->join(); - delete data[thread_count]; - data[thread_count] = new Thread(osPriorityNormal); - data[thread_count]->start(callback((void(*)(void *))read_file_data, (void *)thread_count)); - } - - // Wait for read threads to join - for (char thread_count = 0; thread_count < MBED_THREAD_COUNT; thread_count++) { - data[thread_count]->join(); - delete data[thread_count]; - } - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -// test setup -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("File tests", test_file_tests), - Case("Filesystem access from multiple threads", test_thread_access_test), -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} diff --git a/TESTS/filesystem/seek/main.cpp b/TESTS/filesystem/seek/main.cpp deleted file mode 100644 index e2fd2bd..0000000 --- a/TESTS/filesystem/seek/main.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2016 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "mbed.h" -#include "greentea-client/test_env.h" -#include "unity.h" -#include "utest.h" -#include -#include - -using namespace utest::v1; - -// test configuration -#ifndef MBED_TEST_FILESYSTEM -#define MBED_TEST_FILESYSTEM FATFileSystem -#endif - -#ifndef MBED_TEST_FILESYSTEM_DECL -#define MBED_TEST_FILESYSTEM_DECL MBED_TEST_FILESYSTEM fs("fs") -#endif - -#ifndef MBED_TEST_BLOCKDEVICE -#define MBED_TEST_BLOCKDEVICE SDIOBlockDevice -#define MBED_TEST_BLOCKDEVICE_DECL SDIOBlockDevice bd; -#endif - -#ifndef MBED_TEST_BLOCKDEVICE_DECL -#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd -#endif - -#ifndef MBED_TEST_FILES -#define MBED_TEST_FILES 4 -#endif - -#ifndef MBED_TEST_DIRS -#define MBED_TEST_DIRS 4 -#endif - -#ifndef MBED_TEST_BUFFER -#define MBED_TEST_BUFFER 8192 -#endif - -#ifndef MBED_TEST_TIMEOUT -#define MBED_TEST_TIMEOUT 120 -#endif - - -// declarations -#define STRINGIZE(x) STRINGIZE2(x) -#define STRINGIZE2(x) #x -#define INCLUDE(x) STRINGIZE(x.h) - -#include INCLUDE(MBED_TEST_FILESYSTEM) -#include INCLUDE(MBED_TEST_BLOCKDEVICE) - -MBED_TEST_FILESYSTEM_DECL; -MBED_TEST_BLOCKDEVICE_DECL; - -Dir dir[MBED_TEST_DIRS]; -File file[MBED_TEST_FILES]; -DIR *dd[MBED_TEST_DIRS]; -FILE *fd[MBED_TEST_FILES]; -struct dirent ent; -struct dirent *ed; -size_t size; -uint8_t buffer[MBED_TEST_BUFFER]; -uint8_t rbuffer[MBED_TEST_BUFFER]; -uint8_t wbuffer[MBED_TEST_BUFFER]; - - -// tests - -void test_seek_tests() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = MBED_TEST_FILESYSTEM::format(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = fs.mkdir("hello", 0777); - TEST_ASSERT_EQUAL(0, res); - for (int i = 0; i < 132; i++) { - sprintf((char *)buffer, "hello/kitty%d", i); - res = file[0].open(&fs, (char *)buffer, - O_WRONLY | O_CREAT | O_APPEND); - TEST_ASSERT_EQUAL(0, res); - - size = strlen("kittycatcat"); - memcpy(buffer, "kittycatcat", size); - for (int j = 0; j < 132; j++) { - file[0].write(buffer, size); - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - } - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_simple_dir_seek() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "hello"); - TEST_ASSERT_EQUAL(0, res); -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, "."); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, ".."); - TEST_ASSERT_EQUAL(0, res); -#endif - - off_t pos; - int i; - for (i = 0; i < 4; i++) { - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - pos = dir[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - - dir[0].seek(pos); - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - - dir[0].rewind(); - sprintf((char *)buffer, "kitty%d", 0); -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, "."); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, ".."); - TEST_ASSERT_EQUAL(0, res); -#endif - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - - dir[0].seek(pos); - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_large_dir_seek() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].open(&fs, "hello"); - TEST_ASSERT_EQUAL(0, res); -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, "."); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, ".."); - TEST_ASSERT_EQUAL(0, res); -#endif - - off_t pos; - int i; - for (i = 0; i < 128; i++) { - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - pos = dir[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - - dir[0].seek(pos); - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - - dir[0].rewind(); - sprintf((char *)buffer, "kitty%d", 0); -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, "."); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, ".."); - TEST_ASSERT_EQUAL(0, res); -#endif - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - - dir[0].seek(pos); - sprintf((char *)buffer, "kitty%d", i); - res = dir[0].read(&ent); - TEST_ASSERT_EQUAL(1, res); - res = strcmp(ent.d_name, (char *)buffer); - TEST_ASSERT_EQUAL(0, res); - res = dir[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_simple_file_seek() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - - off_t pos; - size = strlen("kittycatcat"); - for (int i = 0; i < 4; i++) { - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - pos = file[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - file[0].rewind(); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_CUR); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_END) >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - size_t size = file[0].size(); - res = file[0].seek(0, SEEK_CUR); - TEST_ASSERT_EQUAL(size, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_large_file_seek() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDONLY); - TEST_ASSERT_EQUAL(0, res); - - off_t pos; - size = strlen("kittycatcat"); - for (int i = 0; i < 128; i++) { - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - pos = file[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - file[0].rewind(); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_CUR); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_END) >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - size_t size = file[0].size(); - res = file[0].seek(0, SEEK_CUR); - TEST_ASSERT_EQUAL(size, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_simple_file_seek_and_write() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDWR); - TEST_ASSERT_EQUAL(0, res); - - off_t pos; - size = strlen("kittycatcat"); - for (int i = 0; i < 4; i++) { - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - pos = file[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - - memcpy(buffer, "doggodogdog", size); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].write(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "doggodogdog", size); - TEST_ASSERT_EQUAL(0, res); - - file[0].rewind(); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "doggodogdog", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_END) >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - size_t size = file[0].size(); - res = file[0].seek(0, SEEK_CUR); - TEST_ASSERT_EQUAL(size, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_large_file_seek_and_write() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDWR); - TEST_ASSERT_EQUAL(0, res); - - off_t pos; - size = strlen("kittycatcat"); - for (int i = 0; i < 128; i++) { - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - if (i != 4) { - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - } - pos = file[0].tell(); - } - res = pos >= 0; - TEST_ASSERT_EQUAL(1, res); - - memcpy(buffer, "doggodogdog", size); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].write(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "doggodogdog", size); - TEST_ASSERT_EQUAL(0, res); - - file[0].rewind(); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(pos, SEEK_SET); - TEST_ASSERT_EQUAL(pos, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "doggodogdog", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(-size, SEEK_END) >= 0; - TEST_ASSERT_EQUAL(1, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - - size_t size = file[0].size(); - res = file[0].seek(0, SEEK_CUR); - TEST_ASSERT_EQUAL(size, res); - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_boundary_seek_and_write() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDWR); - TEST_ASSERT_EQUAL(0, res); - - size = strlen("hedgehoghog"); - const off_t offsets[] = {512, 1020, 513, 1021, 511, 1019}; - - for (int i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++) { - off_t off = offsets[i]; - memcpy(buffer, "hedgehoghog", size); - res = file[0].seek(off, SEEK_SET); - TEST_ASSERT_EQUAL(off, res); - res = file[0].write(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = file[0].seek(off, SEEK_SET); - TEST_ASSERT_EQUAL(off, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "hedgehoghog", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(0, SEEK_SET); - TEST_ASSERT_EQUAL(0, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "kittycatcat", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].sync(); - TEST_ASSERT_EQUAL(0, res); - } - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - -void test_out_of_bounds_seek() -{ - int res = bd.init(); - TEST_ASSERT_EQUAL(0, res); - - { - res = fs.mount(&bd); - TEST_ASSERT_EQUAL(0, res); - res = file[0].open(&fs, "hello/kitty42", O_RDWR); - TEST_ASSERT_EQUAL(0, res); - - size = strlen("kittycatcat"); - res = file[0].size(); - TEST_ASSERT_EQUAL(132 * size, res); - res = file[0].seek((132 + 4) * size, - SEEK_SET); - TEST_ASSERT_EQUAL((132 + 4)*size, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(0, res); - - memcpy(buffer, "porcupineee", size); - res = file[0].write(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = file[0].seek((132 + 4) * size, - SEEK_SET); - TEST_ASSERT_EQUAL((132 + 4)*size, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); - res = memcmp(buffer, "porcupineee", size); - TEST_ASSERT_EQUAL(0, res); - res = file[0].seek(132 * size, - SEEK_SET); - TEST_ASSERT_EQUAL(132 * size, res); - res = file[0].read(buffer, size); - TEST_ASSERT_EQUAL(size, res); -#if (MBED_TEST_FILESYSTEM != FATFileSystem) - // FatFs does not guarantee empty expanded buffer - res = memcmp(buffer, "\0\0\0\0\0\0\0\0\0\0\0", size); - TEST_ASSERT_EQUAL(0, res); -#endif - res = file[0].close(); - TEST_ASSERT_EQUAL(0, res); - res = fs.unmount(); - TEST_ASSERT_EQUAL(0, res); - } - - res = bd.deinit(); - TEST_ASSERT_EQUAL(0, res); -} - - - -// test setup -utest::v1::status_t test_setup(const size_t number_of_cases) -{ - GREENTEA_SETUP(MBED_TEST_TIMEOUT, "default_auto"); - return verbose_test_setup_handler(number_of_cases); -} - -Case cases[] = { - Case("Seek tests", test_seek_tests), - Case("Simple dir seek", test_simple_dir_seek), - Case("Large dir seek", test_large_dir_seek), - Case("Simple file seek", test_simple_file_seek), - Case("Large file seek", test_large_file_seek), - Case("Simple file seek and write", test_simple_file_seek_and_write), - Case("Large file seek and write", test_large_file_seek_and_write), - Case("Boundary seek and write", test_boundary_seek_and_write), - Case("Out-of-bounds seek", test_out_of_bounds_seek), -}; - -Specification specification(test_setup, cases); - -int main() -{ - return !Harness::run(specification); -} From 62eb597288ac5fa8c541355ff0738d825b1dbd60 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 26 Mar 2019 19:24:25 +0200 Subject: [PATCH 10/23] API renaming --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 176 ++++++++---------- .../COMPONENT_SDIO/SDIOBlockDevice.h | 36 ++-- hal/sdio_api.h | 103 ++++++---- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 34 ++-- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 28 +-- 5 files changed, 200 insertions(+), 177 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index 99b89d8..c1e9cec 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -1,5 +1,6 @@ /* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,13 +15,14 @@ * limitations under the License. */ -#include -#include "platform/mbed_debug.h" -#include "platform/mbed_wait_api.h" +#include "sdio_api.h" #include "SDIOBlockDevice.h" +#include "platform/mbed_debug.h" +#include "sdio_device.h" -namespace mbed -{ +using namespace mbed; + +#if DEVICE_SDIO /* * defines @@ -54,17 +56,11 @@ namespace mbed #define SDCARD_V2HC 3 /**< v2.x High capacity SD card */ #define CARD_UNKNOWN 4 /**< Unknown or unsupported card */ -#ifndef MBED_CONF_SD_TIMEOUT -#define MBED_CONF_SD_TIMEOUT (30 * 1000) /* ms */ -#endif - SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect), _is_initialized(0), _sectors(0), _init_ref_count(0) { - _card_type = SDCARD_NONE; - // Only HC block size is supported. _block_size = BLOCK_SIZE_HC; _erase_size = BLOCK_SIZE_HC; @@ -72,8 +68,7 @@ SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect), SDIOBlockDevice::~SDIOBlockDevice() { - if (_is_initialized) - { + if (_is_initialized) { deinit(); } } @@ -84,33 +79,29 @@ int SDIOBlockDevice::init() lock(); - if (!_is_initialized) - { + if (!_is_initialized) { _init_ref_count = 0; } _init_ref_count++; - if (_init_ref_count != 1) - { + if (_init_ref_count != 1) { unlock(); return BD_ERROR_OK; } - if (isPresent() == false) - { + if (isPresent() == false) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - int status = SD_Init(); - if (BD_ERROR_OK != status) - { + int status = sdio_init(); + if (BD_ERROR_OK != status) { unlock(); return BD_ERROR_DEVICE_ERROR; } - SD_GetCardInfo(&_cardInfo); + sdio_get_card_info(&_cardInfo); _is_initialized = true; debug_if(SD_DBG, "SD initialized: type: %d version: %d class: %d\n", _cardInfo.CardType, _cardInfo.CardVersion, _cardInfo.Class); @@ -134,8 +125,7 @@ int SDIOBlockDevice::deinit() debug_if(SD_DBG, "deinit Card...\r\n"); lock(); - if (!_is_initialized) - { + if (!_is_initialized) { _init_ref_count = 0; unlock(); return BD_ERROR_OK; @@ -143,13 +133,12 @@ int SDIOBlockDevice::deinit() _init_ref_count--; - if (_init_ref_count) - { + if (_init_ref_count) { unlock(); return BD_ERROR_OK; } - int status = SD_DeInit(); + int status = sdio_deinit(); _is_initialized = false; _sectors = 0; @@ -160,20 +149,19 @@ int SDIOBlockDevice::deinit() int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) { + int status = 0; lock(); - if (isPresent() == false) - { + if (isPresent() == false) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!is_valid_read(addr, size)) - { + + if (!is_valid_read(addr, size)) { unlock(); return SD_BLOCK_DEVICE_ERROR_PARAMETER; } - if (!_is_initialized) - { + if (!_is_initialized) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_INIT; } @@ -185,14 +173,13 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) bd_addr_t blockCnt = size / _block_size; addr = addr / _block_size; +#if DEVICE_SDIO_ASYNC // make sure card is ready { uint32_t tickstart = HAL_GetTick(); - while (SD_GetCardState() != SD_TRANSFER_OK) - { + while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -200,39 +187,41 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) } // receive the data : one block/ multiple blocks is handled in ReadBlocks() - int status = SD_ReadBlocks_DMA(_buffer, addr, blockCnt); + status = sdio_readblocks_async(_buffer, addr, blockCnt); debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); - if (status == MSD_OK) - { + if (status == MSD_OK) { // wait until DMA finished uint32_t tickstart = HAL_GetTick(); - while (SD_DMA_ReadPending() != SD_TRANSFER_OK) - { - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + while (sdio_read_pending() != SD_TRANSFER_OK) { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } } // make sure card is ready tickstart = HAL_GetTick(); - while (SD_GetCardState() != SD_TRANSFER_OK) - { + while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } } - } - else - { + } else { debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } +#else + status = sdio_readblocks(buffer, addr, blockCnt); + debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + + if (status != MSD_OK) { + debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = SD_BLOCK_DEVICE_ERROR_READBLOCKS; + } +#endif unlock(); return status; @@ -240,21 +229,20 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) { + int status = 0; lock(); - if (isPresent() == false) - { + if (isPresent() == false) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!is_valid_program(addr, size)) - { + + if (!is_valid_program(addr, size)) { unlock(); return SD_BLOCK_DEVICE_ERROR_PARAMETER; } - if (!_is_initialized) - { + if (!_is_initialized) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_INIT; } @@ -266,53 +254,56 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) bd_size_t blockCnt = size / _block_size; addr = addr / _block_size; +#if DEVICE_SDIO_ASYNC // make sure card is ready { uint32_t tickstart = HAL_GetTick(); - while (SD_GetCardState() != SD_TRANSFER_OK) - { + while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } } } - int status = SD_WriteBlocks_DMA(_buffer, addr, blockCnt); + status = sdio_writeblocks_async(_buffer, addr, blockCnt); debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); if (status == MSD_OK) { // wait until DMA finished uint32_t tickstart = HAL_GetTick(); - while (SD_DMA_WritePending() != SD_TRANSFER_OK) - { - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + while (sdio_write_pending() != SD_TRANSFER_OK) { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } } // make sure card is ready tickstart = HAL_GetTick(); - while (SD_GetCardState() != SD_TRANSFER_OK) - { + while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } } - } - else - { + } else { debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } +#else + status = SDIO_WriteBlocks(buffer, addr, blockCnt); + + debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + + if (status != MSD_OK) { + debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + } +#endif unlock(); return status; @@ -322,19 +313,17 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) { debug_if(SD_DBG, "trim Card...\r\n"); lock(); - if (isPresent() == false) - { + if (isPresent() == false) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!_is_valid_trim(addr, size)) - { + + if (!_is_valid_trim(addr, size)) { unlock(); return SD_BLOCK_DEVICE_ERROR_PARAMETER; } - if (!_is_initialized) - { + if (!_is_initialized) { unlock(); return SD_BLOCK_DEVICE_ERROR_NO_INIT; } @@ -342,21 +331,16 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) bd_size_t blockCnt = size / _block_size; addr = addr / _block_size; - int status = SD_Erase(addr, blockCnt); - if (status != 0) - { + int status = sdio_erase(addr, blockCnt); + if (status != 0) { debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; - } - else - { + } else { uint32_t tickstart = HAL_GetTick(); - while (SD_GetCardState() != SD_TRANSFER_OK) - { + while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) - { + if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } @@ -398,10 +382,14 @@ bool SDIOBlockDevice::isPresent(void) { if (_cardDetect.is_connected()) { return (_cardDetect.read() == 0); - } - else { + } else { return true; } } -} // namespace mbed +const char *SDIOBlockDevice::get_type() const +{ + return "SDIO"; +} + +#endif //DEVICE_SDIO diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h index 9840833..fb82612 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h @@ -1,5 +1,6 @@ /* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited + * Copyright (c) 2019 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,20 +15,17 @@ * limitations under the License. */ -#ifndef MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ +#ifndef MBED_OS_SDIO_BLOCK_DEVICE_H_ +#define MBED_OS_SDIO_BLOCK_DEVICE_H_ -#define MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ +#if DEVICE_SDIO -#include "features/storage/blockdevice/BlockDevice.h" -#include "drivers/DigitalIn.h" -#include "platform/PlatformMutex.h" -#include "sdio_device.h" +#include "BlockDevice.h" +#include "DigitalIn.h" +#include "PlatformMutex.h" +#include "sdio_api.h" -namespace mbed -{ - -class SDIOBlockDevice : public BlockDevice -{ +class SDIOBlockDevice : public mbed::BlockDevice { public: SDIOBlockDevice(PinName cardDetect = NC); virtual ~SDIOBlockDevice(); @@ -114,6 +112,12 @@ class SDIOBlockDevice : public BlockDevice */ virtual bool isPresent(void); + /** Get the BlockDevice class type. + * + * @return A string representation of the BlockDevice class type. + */ + virtual const char *get_type() const; + private: DigitalIn _cardDetect; bool _is_initialized; @@ -121,8 +125,7 @@ class SDIOBlockDevice : public BlockDevice bd_size_t _erase_size; bd_size_t _sectors; uint32_t _init_ref_count; - SD_Cardinfo_t _cardInfo; - uint32_t _card_type; + SDIO_Cardinfo_t _cardInfo; PlatformMutex _mutex; virtual void lock() @@ -138,6 +141,5 @@ class SDIOBlockDevice : public BlockDevice bool _is_valid_trim(bd_addr_t addr, bd_size_t size); }; -} // namespace mbed - -#endif /* MBED_OS_FEATURES_STORAGE_BLOCKDEVICE_SDIOBLOCKDEVICE_H_ */ +#endif // DEVICE_SDIO +#endif // MBED_OS_SDIO_BLOCK_DEVICE_H_ diff --git a/hal/sdio_api.h b/hal/sdio_api.h index 7deaa14..8a25b6e 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -1,5 +1,9 @@ + +/** \addtogroup hal */ +/** @{*/ /* mbed Microcontroller Library - * Copyright (c) 2017 ARM Limited + * Copyright (c) 2006-2013 ARM Limited + * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,23 +17,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef MBED_SDIO_API_H +#define MBED_SDIO_API_H +#include "device.h" +#include "pinmap.h" -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __SDIO_DEVICE_H -#define __SDIO_DEVICE_H +#if DEVICE_SDIO #ifdef __cplusplus extern "C" { #endif -#include "stm32f7xx_hal.h" - - /* Typedefs */ +/** + * \defgroup SDIO Configuration Functions + * @{ + */ - typedef struct - { +typedef struct +{ uint32_t CardType; /* Specifies the card Type */ uint32_t CardVersion; /* Specifies the card version */ uint32_t Class; /* Specifies the class of the card class */ @@ -38,51 +45,65 @@ extern "C" uint32_t BlockSize; /* Specifies one block size in bytes */ uint32_t LogBlockNbr; /* Specifies the Card logical Capacity in blocks */ uint32_t LogBlockSize; /* Specifies logical block size in bytes */ - } SD_Cardinfo_t; - - /* External Global var */ +} SDIO_Cardinfo_t; - extern SD_HandleTypeDef hsd; - -/* Exported types */ -/** - * @brief SD Card information structure - */ -#define BSP_SD_CardInfo HAL_SD_CardInfoTypeDef - -/* Exported constants */ /** - * @brief SD status structure definition + * @brief SD status structure definition */ #define MSD_OK ((uint8_t)0x00) #define MSD_ERROR ((uint8_t)0x01) -/** - * @brief SD transfer state definition +/** + * @brief SD transfer state definition */ #define SD_TRANSFER_OK ((uint8_t)0x00) #define SD_TRANSFER_BUSY ((uint8_t)0x01) - /* Exported functions */ - uint8_t SD_Init(void); - uint8_t SD_DeInit(void); - uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); - uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); - uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); - uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); - uint8_t SD_DMA_ReadPending(void); - uint8_t SD_DMA_WritePending(void); - uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr); - uint8_t SD_GetCardState(void); - void SD_GetCardInfo(SD_Cardinfo_t *CardInfo); +uint8_t sdio_init(void); +uint8_t sdio_deinit(void); +uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); +uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); + +#if DEVICE_SDIO_ASYNC - /* callback function for DMA Rx/Tx completete, called by HAL SDIO interrupt handler */ - void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd); - void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd); +uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +uint8_t sdio_read_pending(void); +uint8_t sdio_write_pending(void); + +#endif // DEVICE_SDIO_ASYNC + +uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr); +uint8_t sdio_get_card_state(void); +void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo); + +/**@}*/ #ifdef __cplusplus } -#endif +#endif // __cplusplus + +#endif // DEVICE_SDIO + +#endif // MBED_SDIO_API_H + + +// TODO: check if this could be usefull +/** @}*/ + +// #if DEVICE_SDIO_ASYNCH +// /** Asynch SPI HAL structure +// */ +// typedef struct { +// struct spi_s spi; /**< Target specific SPI structure */ +// struct buffer_s tx_buff; /**< Tx buffer */ +// struct buffer_s rx_buff; /**< Rx buffer */ +// } spi_t; + +// #else +// /** Non-asynch SPI HAL structure +// */ +// typedef struct spi_s spi_t; -#endif /* __SDIO_DEVICE_H */ +// #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index 0e6b9d1..5f0684b 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -15,9 +15,11 @@ */ -#include "sdio_device.h" +#include "sdio_api.h" #include "platform/mbed_error.h" + +#if DEVICE_SDIO /* Extern variables ---------------------------------------------------------*/ SD_HandleTypeDef hsd; @@ -204,7 +206,7 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) * @param hsd: SD handle * @param Params : pointer on additional configuration parameters, can be NULL. */ -__weak void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params) +void SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params) { static DMA_HandleTypeDef dma_rx_handle; static DMA_HandleTypeDef dma_tx_handle; @@ -266,7 +268,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) * @brief Initializes the SD card device. * @retval SD status */ -uint8_t SD_Init(void) +uint8_t sdio_init(void) { uint8_t sd_state = MSD_OK; @@ -297,7 +299,7 @@ uint8_t SD_Init(void) * @brief DeInitializes the SD card device. * @retval SD status */ -uint8_t SD_DeInit(void) +uint8_t sdio_deinit(void) { uint8_t sd_state = MSD_OK; @@ -324,7 +326,7 @@ uint8_t SD_DeInit(void) * @param Timeout: Timeout for read operation * @retval SD status */ -uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -344,7 +346,7 @@ uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, * @param Timeout: Timeout for write operation * @retval SD status */ -uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -356,6 +358,8 @@ uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks return sd_state; } +#if DEVICE_SDIO_ASYNC + /** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. * @param pData: Pointer to the buffer that will contain the data to transmit @@ -363,7 +367,7 @@ uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ -uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; @@ -385,7 +389,7 @@ uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ -uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; @@ -400,13 +404,15 @@ uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl return sd_state; } +#endif // DEVICE_SDIO_ASYNC + /** * @brief Erases the specified memory area of the given SD card. * @param StartAddr: Start byte address * @param EndAddr: End byte address * @retval SD status */ -uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) +uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { uint8_t sd_state = MSD_OK; @@ -426,7 +432,7 @@ uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_GetCardState(void) +uint8_t sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } @@ -436,7 +442,7 @@ uint8_t SD_GetCardState(void) * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure * @retval None */ -void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) +void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) { /* Get SD card Information, copy structure for portability */ HAL_SD_CardInfoTypeDef HAL_CardInfo; @@ -463,7 +469,7 @@ void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_DMA_ReadPending(void) +uint8_t sdio_read_pending(void) { return SD_DMA_ReadPendingState; } @@ -475,7 +481,7 @@ uint8_t SD_DMA_ReadPending(void) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_DMA_WritePending(void) +uint8_t sdio_write_pending(void) { return SD_DMA_WritePendingState; } @@ -499,3 +505,5 @@ void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) { SD_DMA_WritePendingState = SD_TRANSFER_OK; } + +#endif // DEVICE_SDIO diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index 29cfb01..ff31bb8 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -15,9 +15,11 @@ */ -#include "sdio_device.h" +#include "sdio_api.h" #include "platform/mbed_error.h" +#if DEVICE_SDIO + /* Extern variables ---------------------------------------------------------*/ SD_HandleTypeDef hsd; @@ -266,7 +268,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) * @brief Initializes the SD card device. * @retval SD status */ -uint8_t SD_Init(void) +uint8_t sdio_init(void) { uint8_t sd_state = MSD_OK; @@ -297,7 +299,7 @@ uint8_t SD_Init(void) * @brief DeInitializes the SD card device. * @retval SD status */ -uint8_t SD_DeInit(void) +uint8_t sdio_deinit(void) { uint8_t sd_state = MSD_OK; @@ -324,7 +326,7 @@ uint8_t SD_DeInit(void) * @param Timeout: Timeout for read operation * @retval SD status */ -uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -344,7 +346,7 @@ uint8_t SD_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, * @param Timeout: Timeout for write operation * @retval SD status */ -uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -363,7 +365,7 @@ uint8_t SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ -uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; @@ -385,7 +387,7 @@ uint8_t SD_ReadBlocks_DMA(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ -uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; @@ -406,7 +408,7 @@ uint8_t SD_WriteBlocks_DMA(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl * @param EndAddr: End byte address * @retval SD status */ -uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) +uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { uint8_t sd_state = MSD_OK; @@ -426,7 +428,7 @@ uint8_t SD_Erase(uint32_t StartAddr, uint32_t EndAddr) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_GetCardState(void) +uint8_t sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } @@ -436,7 +438,7 @@ uint8_t SD_GetCardState(void) * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure * @retval None */ -void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) +void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) { /* Get SD card Information, copy structure for portability */ HAL_SD_CardInfoTypeDef HAL_CardInfo; @@ -463,7 +465,7 @@ void SD_GetCardInfo(SD_Cardinfo_t *CardInfo) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_DMA_ReadPending(void) +uint8_t sdio_read_pending(void) { return SD_DMA_ReadPendingState; } @@ -475,7 +477,7 @@ uint8_t SD_DMA_ReadPending(void) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t SD_DMA_WritePending(void) +uint8_t sdio_write_pending(void) { return SD_DMA_WritePendingState; } @@ -499,3 +501,5 @@ void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd) { SD_DMA_WritePendingState = SD_TRANSFER_OK; } + +#endif // DEVICE_SDIO From 5d1d09b0594c970e6876f0093517aaa4a95cba29 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Tue, 26 Mar 2019 20:47:34 +0200 Subject: [PATCH 11/23] Astyle fixes --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 18 ++++++++---------- .../COMPONENT_SDIO/SDIOBlockDevice.h | 9 ++++++--- hal/sdio_api.h | 3 +-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index c1e9cec..fd4e9e2 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -57,9 +57,9 @@ using namespace mbed; #define CARD_UNKNOWN 4 /**< Unknown or unsupported card */ SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect), - _is_initialized(0), - _sectors(0), - _init_ref_count(0) + _is_initialized(0), + _sectors(0), + _init_ref_count(0) { // Only HC block size is supported. _block_size = BLOCK_SIZE_HC; @@ -110,8 +110,7 @@ int SDIOBlockDevice::init() // get sectors count from cardinfo _sectors = _cardInfo.LogBlockNbr; - if (BLOCK_SIZE_HC != _cardInfo.BlockSize) - { + if (BLOCK_SIZE_HC != _cardInfo.BlockSize) { unlock(); return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE; } @@ -270,8 +269,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) status = sdio_writeblocks_async(_buffer, addr, blockCnt); debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); - if (status == MSD_OK) - { + if (status == MSD_OK) { // wait until DMA finished uint32_t tickstart = HAL_GetTick(); while (sdio_write_pending() != SD_TRANSFER_OK) { @@ -373,9 +371,9 @@ void SDIOBlockDevice::debug(bool dbg) bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) { return ( - addr % _erase_size == 0 && - size % _erase_size == 0 && - addr + size <= this->size()); + addr % _erase_size == 0 && + size % _erase_size == 0 && + addr + size <= this->size()); } bool SDIOBlockDevice::isPresent(void) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h index fb82612..a590852 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h @@ -26,7 +26,7 @@ #include "sdio_api.h" class SDIOBlockDevice : public mbed::BlockDevice { - public: +public: SDIOBlockDevice(PinName cardDetect = NC); virtual ~SDIOBlockDevice(); /** Initialize a block device @@ -104,7 +104,10 @@ class SDIOBlockDevice : public mbed::BlockDevice { * @param freq Transfer frequency * @note Max frequency supported is 25MHZ */ - virtual int frequency(uint64_t freq) { return BD_ERROR_OK; }; + virtual int frequency(uint64_t freq) + { + return BD_ERROR_OK; + }; /** check if SD is present * @@ -118,7 +121,7 @@ class SDIOBlockDevice : public mbed::BlockDevice { */ virtual const char *get_type() const; - private: +private: DigitalIn _cardDetect; bool _is_initialized; bd_size_t _block_size; diff --git a/hal/sdio_api.h b/hal/sdio_api.h index 8a25b6e..53f74de 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -35,8 +35,7 @@ extern "C" * @{ */ -typedef struct -{ +typedef struct { uint32_t CardType; /* Specifies the card Type */ uint32_t CardVersion; /* Specifies the card version */ uint32_t Class; /* Specifies the class of the card class */ From e742718a39cb1218093ac5e3330eefd1b179e2ce Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 14:45:41 +0200 Subject: [PATCH 12/23] Change error type to int and use us_ticker_read --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 31 +++++++------- hal/sdio_api.h | 40 +++++-------------- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 20 +++++----- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 20 +++++----- 4 files changed, 46 insertions(+), 65 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index fd4e9e2..0cb682f 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -15,10 +15,11 @@ * limitations under the License. */ + #include "sdio_api.h" +#include "us_ticker_api.h" #include "SDIOBlockDevice.h" #include "platform/mbed_debug.h" -#include "sdio_device.h" using namespace mbed; @@ -175,10 +176,10 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) #if DEVICE_SDIO_ASYNC // make sure card is ready { - uint32_t tickstart = HAL_GetTick(); + uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -191,18 +192,18 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) if (status == MSD_OK) { // wait until DMA finished - uint32_t tickstart = HAL_GetTick(); + uint32_t tickstart = us_ticker_read(); while (sdio_read_pending() != SD_TRANSFER_OK) { - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } } // make sure card is ready - tickstart = HAL_GetTick(); + tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -256,10 +257,10 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) #if DEVICE_SDIO_ASYNC // make sure card is ready { - uint32_t tickstart = HAL_GetTick(); + uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } @@ -271,18 +272,18 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) if (status == MSD_OK) { // wait until DMA finished - uint32_t tickstart = HAL_GetTick(); + uint32_t tickstart = us_ticker_read(); while (sdio_write_pending() != SD_TRANSFER_OK) { - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } } // make sure card is ready - tickstart = HAL_GetTick(); + tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } @@ -335,10 +336,10 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } else { - uint32_t tickstart = HAL_GetTick(); + uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((HAL_GetTick() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } diff --git a/hal/sdio_api.h b/hal/sdio_api.h index 53f74de..b57575b 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -59,22 +59,22 @@ typedef struct { #define SD_TRANSFER_BUSY ((uint8_t)0x01) -uint8_t sdio_init(void); -uint8_t sdio_deinit(void); -uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); -uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); +int sdio_init(void); +int sdio_deinit(void); +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); #if DEVICE_SDIO_ASYNC -uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); -uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); -uint8_t sdio_read_pending(void); -uint8_t sdio_write_pending(void); +int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +int sdio_read_pending(void); +int sdio_write_pending(void); #endif // DEVICE_SDIO_ASYNC -uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr); -uint8_t sdio_get_card_state(void); +int sdio_erase(uint32_t StartAddr, uint32_t EndAddr); +int sdio_get_card_state(void); void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo); /**@}*/ @@ -86,23 +86,3 @@ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo); #endif // DEVICE_SDIO #endif // MBED_SDIO_API_H - - -// TODO: check if this could be usefull -/** @}*/ - -// #if DEVICE_SDIO_ASYNCH -// /** Asynch SPI HAL structure -// */ -// typedef struct { -// struct spi_s spi; /**< Target specific SPI structure */ -// struct buffer_s tx_buff; /**< Tx buffer */ -// struct buffer_s rx_buff; /**< Rx buffer */ -// } spi_t; - -// #else -// /** Non-asynch SPI HAL structure -// */ -// typedef struct spi_s spi_t; - -// #endif diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index 5f0684b..13bfe34 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -268,7 +268,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) * @brief Initializes the SD card device. * @retval SD status */ -uint8_t sdio_init(void) +int sdio_init(void) { uint8_t sd_state = MSD_OK; @@ -299,7 +299,7 @@ uint8_t sdio_init(void) * @brief DeInitializes the SD card device. * @retval SD status */ -uint8_t sdio_deinit(void) +int sdio_deinit(void) { uint8_t sd_state = MSD_OK; @@ -326,7 +326,7 @@ uint8_t sdio_deinit(void) * @param Timeout: Timeout for read operation * @retval SD status */ -uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -346,7 +346,7 @@ uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks * @param Timeout: Timeout for write operation * @retval SD status */ -uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -367,7 +367,7 @@ uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBloc * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ -uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; @@ -389,7 +389,7 @@ uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOf * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ -uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; @@ -412,7 +412,7 @@ uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t Num * @param EndAddr: End byte address * @retval SD status */ -uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) +int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { uint8_t sd_state = MSD_OK; @@ -432,7 +432,7 @@ uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_get_card_state(void) +int sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } @@ -469,7 +469,7 @@ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_read_pending(void) +int sdio_read_pending(void) { return SD_DMA_ReadPendingState; } @@ -481,7 +481,7 @@ uint8_t sdio_read_pending(void) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_write_pending(void) +int sdio_write_pending(void) { return SD_DMA_WritePendingState; } diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index ff31bb8..58733a3 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -268,7 +268,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) * @brief Initializes the SD card device. * @retval SD status */ -uint8_t sdio_init(void) +int sdio_init(void) { uint8_t sd_state = MSD_OK; @@ -299,7 +299,7 @@ uint8_t sdio_init(void) * @brief DeInitializes the SD card device. * @retval SD status */ -uint8_t sdio_deinit(void) +int sdio_deinit(void) { uint8_t sd_state = MSD_OK; @@ -326,7 +326,7 @@ uint8_t sdio_deinit(void) * @param Timeout: Timeout for read operation * @retval SD status */ -uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -346,7 +346,7 @@ uint8_t sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks * @param Timeout: Timeout for write operation * @retval SD status */ -uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) { uint8_t sd_state = MSD_OK; @@ -365,7 +365,7 @@ uint8_t sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBloc * @param NumOfBlocks: Number of SD blocks to read * @retval SD status */ -uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; @@ -387,7 +387,7 @@ uint8_t sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOf * @param NumOfBlocks: Number of SD blocks to write * @retval SD status */ -uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { uint8_t sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; @@ -408,7 +408,7 @@ uint8_t sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t Num * @param EndAddr: End byte address * @retval SD status */ -uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) +int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { uint8_t sd_state = MSD_OK; @@ -428,7 +428,7 @@ uint8_t sdio_erase(uint32_t StartAddr, uint32_t EndAddr) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_get_card_state(void) +int sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } @@ -465,7 +465,7 @@ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_read_pending(void) +int sdio_read_pending(void) { return SD_DMA_ReadPendingState; } @@ -477,7 +477,7 @@ uint8_t sdio_read_pending(void) * @arg SD_TRANSFER_OK: No data transfer is acting * @arg SD_TRANSFER_BUSY: Data transfer is acting */ -uint8_t sdio_write_pending(void) +int sdio_write_pending(void) { return SD_DMA_WritePendingState; } From 4295558f57f8244805cc3d5673b810176116aec6 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 15:01:42 +0200 Subject: [PATCH 13/23] Remove timeout parameter --- hal/sdio_api.h | 12 ++++---- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 29 +++++++++---------- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 30 +++++++++----------- 3 files changed, 34 insertions(+), 37 deletions(-) diff --git a/hal/sdio_api.h b/hal/sdio_api.h index b57575b..7836880 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -49,20 +49,20 @@ typedef struct { /** * @brief SD status structure definition */ -#define MSD_OK ((uint8_t)0x00) -#define MSD_ERROR ((uint8_t)0x01) +#define MSD_OK ((int)0x00) +#define MSD_ERROR ((int)0x01) /** * @brief SD transfer state definition */ -#define SD_TRANSFER_OK ((uint8_t)0x00) -#define SD_TRANSFER_BUSY ((uint8_t)0x01) +#define SD_TRANSFER_OK ((int)0x00) +#define SD_TRANSFER_BUSY ((int)0x01) int sdio_init(void); int sdio_deinit(void); -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout); -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout); +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); #if DEVICE_SDIO_ASYNC diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index 13bfe34..7ffa6ec 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -20,6 +20,7 @@ #if DEVICE_SDIO +#define CMD_TIMEOUT 30000 /* Extern variables ---------------------------------------------------------*/ SD_HandleTypeDef hsd; @@ -27,8 +28,8 @@ DMA_HandleTypeDef hdma_sdio_rx; DMA_HandleTypeDef hdma_sdio_tx; // simple flags for DMA pending signaling -volatile uint8_t SD_DMA_ReadPendingState = SD_TRANSFER_OK; -volatile uint8_t SD_DMA_WritePendingState = SD_TRANSFER_OK; +volatile int SD_DMA_ReadPendingState = SD_TRANSFER_OK; +volatile int SD_DMA_WritePendingState = SD_TRANSFER_OK; /* DMA Handlers are global, there is only one SDIO interface */ @@ -270,7 +271,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) */ int sdio_init(void) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; hsd.Instance = SDIO; hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; @@ -301,7 +302,7 @@ int sdio_init(void) */ int sdio_deinit(void) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; hsd.Instance = SDIO; @@ -323,14 +324,13 @@ int sdio_deinit(void) * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param NumOfBlocks: Number of SD blocks to read - * @param Timeout: Timeout for read operation * @retval SD status */ -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; - if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK) + if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -343,14 +343,13 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, ui * @param pData: Pointer to the buffer that will contain the data to transmit * @param WriteAddr: Address from where data is to be written * @param NumOfBlocks: Number of SD blocks to write - * @param Timeout: Timeout for write operation * @retval SD status */ -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; - if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK) + if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -369,7 +368,7 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, */ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; /* Read block(s) in DMA transfer mode */ @@ -391,7 +390,7 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc */ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; /* Write block(s) in DMA transfer mode */ @@ -414,7 +413,7 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl */ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) { diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index 58733a3..1fb4ff1 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -19,7 +19,7 @@ #include "platform/mbed_error.h" #if DEVICE_SDIO - +#define CMD_TIMEOUT 30000 /* Extern variables ---------------------------------------------------------*/ SD_HandleTypeDef hsd; @@ -27,8 +27,8 @@ DMA_HandleTypeDef hdma_sdmmc_rx; DMA_HandleTypeDef hdma_sdmmc_tx; // simple flags for DMA pending signaling -volatile uint8_t SD_DMA_ReadPendingState = SD_TRANSFER_OK; -volatile uint8_t SD_DMA_WritePendingState = SD_TRANSFER_OK; +volatile int SD_DMA_ReadPendingState = SD_TRANSFER_OK; +volatile int SD_DMA_WritePendingState = SD_TRANSFER_OK; /* DMA Handlers are global, there is only one SDIO interface */ @@ -270,7 +270,7 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) */ int sdio_init(void) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; hsd.Instance = SDMMC1; hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; @@ -301,7 +301,7 @@ int sdio_init(void) */ int sdio_deinit(void) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; hsd.Instance = SDMMC1; @@ -323,14 +323,13 @@ int sdio_deinit(void) * @param pData: Pointer to the buffer that will contain the data to transmit * @param ReadAddr: Address from where data is to be read * @param NumOfBlocks: Number of SD blocks to read - * @param Timeout: Timeout for read operation * @retval SD status */ -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; - if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, Timeout) != HAL_OK) + if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -343,14 +342,13 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks, ui * @param pData: Pointer to the buffer that will contain the data to transmit * @param WriteAddr: Address from where data is to be written * @param NumOfBlocks: Number of SD blocks to write - * @param Timeout: Timeout for write operation * @retval SD status */ -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout) +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; - if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) != HAL_OK) + if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -367,7 +365,7 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, */ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; /* Read block(s) in DMA transfer mode */ @@ -389,7 +387,7 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc */ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; /* Write block(s) in DMA transfer mode */ @@ -410,7 +408,7 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl */ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) { From d5b6a08fc967eedc5235f9a520f07c193893178b Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 15:07:22 +0200 Subject: [PATCH 14/23] Move documentation to sdio_api.h --- hal/sdio_api.h | 78 +++++++++++++++++++- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 69 ----------------- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 69 ----------------- 3 files changed, 77 insertions(+), 139 deletions(-) diff --git a/hal/sdio_api.h b/hal/sdio_api.h index 7836880..5fb49e7 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -58,23 +58,99 @@ typedef struct { #define SD_TRANSFER_OK ((int)0x00) #define SD_TRANSFER_BUSY ((int)0x01) - +/** + * @brief Initializes the SD card device. + * @retval SD status + */ int sdio_init(void); + +/** + * @brief DeInitializes the SD card device. + * @retval SD status + */ int sdio_deinit(void); + +/** + * @brief Reads block(s) from a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @retval SD status + */ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); + +/** + * @brief Writes block(s) to a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @retval SD status + */ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); #if DEVICE_SDIO_ASYNC +/** + * @brief Reads block(s) from a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @retval SD status + */ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); + +/** + * @brief Writes block(s) to a specified address in an SD card, in DMA mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @retval SD status + */ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ int sdio_read_pending(void); + +/** + * @brief Check if a DMA operation is pending + * @retval DMA operation is pending + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ int sdio_write_pending(void); #endif // DEVICE_SDIO_ASYNC +/** + * @brief Erases the specified memory area of the given SD card. + * @param StartAddr: Start byte address + * @param EndAddr: End byte address + * @retval SD status + */ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr); + +/** + * @brief Gets the current SD card data status. + * @param None + * @retval Data transfer state. + * This value can be one of the following values: + * @arg SD_TRANSFER_OK: No data transfer is acting + * @arg SD_TRANSFER_BUSY: Data transfer is acting + */ int sdio_get_card_state(void); + +/** + * @brief Get SD information about specific SD card. + * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure + * @retval None + */ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo); /**@}*/ diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index 7ffa6ec..17aa05a 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -265,10 +265,6 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) return HAL_SD_ERROR_NONE; } -/** - * @brief Initializes the SD card device. - * @retval SD status - */ int sdio_init(void) { int sd_state = MSD_OK; @@ -296,10 +292,6 @@ int sdio_init(void) return sd_state; } -/** - * @brief DeInitializes the SD card device. - * @retval SD status - */ int sdio_deinit(void) { int sd_state = MSD_OK; @@ -319,13 +311,6 @@ int sdio_deinit(void) return sd_state; } -/** - * @brief Reads block(s) from a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read - * @retval SD status - */ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -338,13 +323,6 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) return sd_state; } -/** - * @brief Writes block(s) to a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write - * @retval SD status - */ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -359,13 +337,6 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) #if DEVICE_SDIO_ASYNC -/** - * @brief Reads block(s) from a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read - * @retval SD status - */ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -381,13 +352,6 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc return sd_state; } -/** - * @brief Writes block(s) to a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write - * @retval SD status - */ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -405,12 +369,6 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl #endif // DEVICE_SDIO_ASYNC -/** - * @brief Erases the specified memory area of the given SD card. - * @param StartAddr: Start byte address - * @param EndAddr: End byte address - * @retval SD status - */ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { int sd_state = MSD_OK; @@ -423,24 +381,11 @@ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) return sd_state; } -/** - * @brief Gets the current SD card data status. - * @param None - * @retval Data transfer state. - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } -/** - * @brief Get SD information about specific SD card. - * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure - * @retval None - */ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) { /* Get SD card Information, copy structure for portability */ @@ -461,25 +406,11 @@ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) } } -/** - * @brief Check if a DMA operation is pending - * @retval DMA operation is pending - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_read_pending(void) { return SD_DMA_ReadPendingState; } -/** - * @brief Check if a DMA operation is pending - * @retval DMA operation is pending - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_write_pending(void) { return SD_DMA_WritePendingState; diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index 1fb4ff1..c344de3 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -264,10 +264,6 @@ static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd) return HAL_SD_ERROR_NONE; } -/** - * @brief Initializes the SD card device. - * @retval SD status - */ int sdio_init(void) { int sd_state = MSD_OK; @@ -295,10 +291,6 @@ int sdio_init(void) return sd_state; } -/** - * @brief DeInitializes the SD card device. - * @retval SD status - */ int sdio_deinit(void) { int sd_state = MSD_OK; @@ -318,13 +310,6 @@ int sdio_deinit(void) return sd_state; } -/** - * @brief Reads block(s) from a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read - * @retval SD status - */ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -337,13 +322,6 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) return sd_state; } -/** - * @brief Writes block(s) to a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write - * @retval SD status - */ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -356,13 +334,6 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) return sd_state; } -/** - * @brief Reads block(s) from a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read - * @retval SD status - */ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -378,13 +349,6 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc return sd_state; } -/** - * @brief Writes block(s) to a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write - * @retval SD status - */ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { int sd_state = MSD_OK; @@ -400,12 +364,6 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl return sd_state; } -/** - * @brief Erases the specified memory area of the given SD card. - * @param StartAddr: Start byte address - * @param EndAddr: End byte address - * @retval SD status - */ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { int sd_state = MSD_OK; @@ -418,24 +376,11 @@ int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) return sd_state; } -/** - * @brief Gets the current SD card data status. - * @param None - * @retval Data transfer state. - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_get_card_state(void) { return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } -/** - * @brief Get SD information about specific SD card. - * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure - * @retval None - */ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) { /* Get SD card Information, copy structure for portability */ @@ -456,25 +401,11 @@ void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) } } -/** - * @brief Check if a DMA operation is pending - * @retval DMA operation is pending - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_read_pending(void) { return SD_DMA_ReadPendingState; } -/** - * @brief Check if a DMA operation is pending - * @retval DMA operation is pending - * This value can be one of the following values: - * @arg SD_TRANSFER_OK: No data transfer is acting - * @arg SD_TRANSFER_BUSY: Data transfer is acting - */ int sdio_write_pending(void) { return SD_DMA_WritePendingState; From 7ae99b12762b64221c94bcdb76c948987fa2f167 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 15:46:27 +0200 Subject: [PATCH 15/23] Compilation fix --- .../blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp | 14 +++++++------- .../blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h | 2 +- .../blockdevice/COMPONENT_SDIO/mbed_lib.json | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index 0cb682f..2a402de 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -179,7 +179,7 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -194,7 +194,7 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) // wait until DMA finished uint32_t tickstart = us_ticker_read(); while (sdio_read_pending() != SD_TRANSFER_OK) { - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -203,7 +203,7 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } @@ -260,7 +260,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } @@ -274,7 +274,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) // wait until DMA finished uint32_t tickstart = us_ticker_read(); while (sdio_write_pending() != SD_TRANSFER_OK) { - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } @@ -283,7 +283,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } @@ -339,7 +339,7 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { // wait until SD ready - if ((us_ticker_read() - tickstart) >= MBED_CONF_SD_TIMEOUT) { + if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h index a590852..a3a1fe8 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h @@ -122,7 +122,7 @@ class SDIOBlockDevice : public mbed::BlockDevice { virtual const char *get_type() const; private: - DigitalIn _cardDetect; + mbed::DigitalIn _cardDetect; bool _is_initialized; bd_size_t _block_size; bd_size_t _erase_size; diff --git a/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json b/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json index 30d5324..03a7de6 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json +++ b/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json @@ -1,8 +1,8 @@ { "name": "sdio", "config": { - "FSFAT_SDCARD_INSTALLED": 1, - "CMD_TIMEOUT": 30000 + "CMD_TIMEOUT": 30000, + "CD": "NC" }, "target_overrides": { "DISCO_F469NI": { From b840f321dd0df1b712cb2af7f273478ace210c45 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 16:50:22 +0200 Subject: [PATCH 16/23] Minor fixes --- .../storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index 2a402de..79da3b0 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -214,7 +214,7 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_READBLOCKS; } #else - status = sdio_readblocks(buffer, addr, blockCnt); + status = sdio_readblocks(_buffer, addr, blockCnt); debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); if (status != MSD_OK) { @@ -294,7 +294,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; } #else - status = SDIO_WriteBlocks(buffer, addr, blockCnt); + status = sdio_writeblocks(_buffer, addr, blockCnt); debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); From 11daa9f32bce9ff7d8c4ac2078991cafd5272cd7 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 17:50:26 +0200 Subject: [PATCH 17/23] Check if initialized before calling is_valid --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index 79da3b0..7b4d709 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -156,14 +156,14 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!is_valid_read(addr, size)) { + if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SD_BLOCK_DEVICE_ERROR_NO_INIT; } - if (!_is_initialized) { + if (!is_valid_read(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SD_BLOCK_DEVICE_ERROR_PARAMETER; } uint32_t *_buffer = static_cast(buffer); @@ -237,14 +237,14 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!is_valid_program(addr, size)) { + if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SD_BLOCK_DEVICE_ERROR_NO_INIT; } - if (!_is_initialized) { + if (!is_valid_program(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SD_BLOCK_DEVICE_ERROR_PARAMETER; } // HAL layer uses uint32_t for addr/size @@ -317,14 +317,14 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; } - if (!_is_valid_trim(addr, size)) { + if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SD_BLOCK_DEVICE_ERROR_NO_INIT; } - if (!_is_initialized) { + if (!_is_valid_trim(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SD_BLOCK_DEVICE_ERROR_PARAMETER; } bd_size_t blockCnt = size / _block_size; From f27d137f02cfe4ef9949e0094c909d1e06681b6f Mon Sep 17 00:00:00 2001 From: Mahesh Mahadevan Date: Mon, 18 Feb 2019 13:16:03 -0600 Subject: [PATCH 18/23] Add SDIO support for NXP LPC55S69 Tested this with the block device test inside features-storage-tests-blockdevice-general_block_device --- target/TARGET_NXP/board.h | 41 + target/TARGET_NXP/fsl_sd.c | 1967 ++++++++++++++++++++++++++ target/TARGET_NXP/fsl_sd.h | 322 +++++ target/TARGET_NXP/fsl_sdmmc_common.c | 298 ++++ target/TARGET_NXP/fsl_sdmmc_common.h | 236 +++ target/TARGET_NXP/fsl_sdmmc_host.c | 245 ++++ target/TARGET_NXP/fsl_sdmmc_host.h | 736 ++++++++++ target/TARGET_NXP/fsl_sdmmc_spec.h | 1164 +++++++++++++++ target/TARGET_NXP/sdio_device.c | 180 +++ target/TARGET_NXP/sdio_device.h | 52 + 10 files changed, 5241 insertions(+) create mode 100644 target/TARGET_NXP/board.h create mode 100644 target/TARGET_NXP/fsl_sd.c create mode 100644 target/TARGET_NXP/fsl_sd.h create mode 100644 target/TARGET_NXP/fsl_sdmmc_common.c create mode 100644 target/TARGET_NXP/fsl_sdmmc_common.h create mode 100644 target/TARGET_NXP/fsl_sdmmc_host.c create mode 100644 target/TARGET_NXP/fsl_sdmmc_host.h create mode 100644 target/TARGET_NXP/fsl_sdmmc_spec.h create mode 100644 target/TARGET_NXP/sdio_device.c create mode 100644 target/TARGET_NXP/sdio_device.h diff --git a/target/TARGET_NXP/board.h b/target/TARGET_NXP/board.h new file mode 100644 index 0000000..560a1fc --- /dev/null +++ b/target/TARGET_NXP/board.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +#include "fsl_common.h" +#include "fsl_gpio.h" +#include "fsl_iocon.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +#define BOARD_SDIF_BASEADDR SDIF +#define BOARD_SDIF_CLKSRC kCLOCK_SDio +#define BOARD_SDIF_CLK_FREQ CLOCK_GetFreq(kCLOCK_SDio) +#define BOARD_SDIF_CLK_ATTACH kMAIN_CLK_to_SDIO_CLK +#define BOARD_SDIF_IRQ SDIO_IRQn +#define BOARD_MMC_VCC_SUPPLY kMMC_VoltageWindows270to360 +#define BOARD_SD_CARD_DETECT_PIN 17 +#define BOARD_SD_CARD_DETECT_PORT 0 +#define BOARD_SD_CARD_DETECT_GPIO GPIO +#define BOARD_SD_DETECT_TYPE kSDMMCHOST_DetectCardByHostCD + +#define BOARD_SDIF_CD_GPIO_INIT() \ + { \ + CLOCK_EnableClock(kCLOCK_Gpio2); \ + GPIO_PinInit(BOARD_SD_CARD_DETECT_GPIO, BOARD_SD_CARD_DETECT_PORT, BOARD_SD_CARD_DETECT_PIN, \ + &(gpio_pin_config_t){kGPIO_DigitalInput, 0U}); \ + } +#define BOARD_SDIF_CD_STATUS() \ + GPIO_PinRead(BOARD_SD_CARD_DETECT_GPIO, BOARD_SD_CARD_DETECT_PORT, BOARD_SD_CARD_DETECT_PIN) + +#define BOARD_SDIF_CLK_ATTACH kMAIN_CLK_to_SDIO_CLK + +#endif /* _BOARD_H_ */ diff --git a/target/TARGET_NXP/fsl_sd.c b/target/TARGET_NXP/fsl_sd.c new file mode 100644 index 0000000..0cbb8b7 --- /dev/null +++ b/target/TARGET_NXP/fsl_sd.c @@ -0,0 +1,1967 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include "fsl_sd.h" + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief Wait write process complete. + * + * @param card Card descriptor. + * @retval kStatus_Timeout Send command timeout. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_WaitWriteComplete(sd_card_t *card); + +/*! + * @brief send write success blocks. + * + * @param card Card descriptor. + * @param blocks blocks number wirte successed + * @retval kStatus_SDMMC_TransferFailed Send command failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendWriteSuccessBlocks(sd_card_t *card, uint32_t *blocks); + +/*! + * @brief Send SEND_APPLICATION_COMMAND command. + * + * @param card Card descriptor. + * @param relativeaddress + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress); + +/*! + * @brief Send GO_IDLE command to set the card to be idle state. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_GoIdle(sd_card_t *card); + +/*! + * @brief Send STOP_TRANSMISSION command after multiple blocks read/write. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_StopTransmission(sd_card_t *card); + +/*! + * @brief Send SET_BLOCK_SIZE command. + * + * @param card Card descriptor. + * @param blockSize Block size. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize); + +/*! + * @brief Send GET_RCA command to get card relative address. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendRca(sd_card_t *card); + +/*! + * @brief Send SWITCH_FUNCTION command to switch the card function group. + * + * @param card Card descriptor. + * @param mode 0 to check function group. 1 to switch function group + * @param group Function group + * @param number Function number in the function group. + * @param status Switch function status. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SwitchFunction(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number, uint32_t *status); + +/*! + * @brief Decode raw SCR register content in the data blocks. + * + * @param card Card descriptor. + * @param rawScr Raw SCR register content. + */ +static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr); + +/*! + * @brief Send GET_SCR command. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_NotSupportYet Not support yet. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendScr(sd_card_t *card); + +/*! + * @brief Switch the card to be high speed mode. + * + * @param card Card descriptor. + * @param group Group number. + * @param functio Function number. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_SwitchFailed Switch failed. + * @retval kStatus_SDMMC_NotSupportYet Not support yet. + * @retval kStatus_Fail Switch failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SelectFunction(sd_card_t *card, uint32_t group, uint32_t function); + +/*! + * @brief Send SET_DATA_WIDTH command to set SD bus width. + * + * @param card Card descriptor. + * @param width Data bus width. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SetDataBusWidth(sd_card_t *card, sd_data_bus_width_t width); + +/*! + * @brief Decode raw CSD register content in the data blocks. + * + * @param card Card descriptor. + * @param rawCsd Raw CSD register content. + */ +static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd); + +/*! + * @brief Send SEND_CSD command to get CSD register content from Card. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendCsd(sd_card_t *card); + +/*! + * @brief Decode raw CID register content in the data blocks. + * + * @param rawCid raw CID register content. + * @param card Card descriptor. + */ +static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid); + +/*! + * @brief Send GET_CID command to get CID from card. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_AllSendCid(sd_card_t *card); + +/*! + * @brief Send SEND_OPERATION_CONDITION command. + * + * This function sends host capacity support information and asks the accessed card to send its operating condition + * register content. + * + * @param card Card descriptor. + * @param argument The argument of the send operation condition ncomamnd. + * @retval kStatus_SDMMC_SendApplicationCommandFailed Send application command failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Timeout Timeout. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument); + +/*! + * @brief Send GET_INTERFACE_CONDITION command to get card interface condition. + * + * This function checks card interface condition, which includes host supply voltage information and asks the card + * whether card supports the specified host voltage. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_SendInterfaceCondition(sd_card_t *card); + +/*! + * @brief Send switch voltage command + * switch card voltage to 1.8v + * + * @param card Card descriptor. + */ +static status_t SD_SwitchVoltage(sd_card_t *card); + +/*! + * @brief select bus timing + * select card timing + * @param card Card descriptor. + */ +static status_t SD_SelectBusTiming(sd_card_t *card); + +/*! + * @brief Decode sd 512 bit status + * @param card Card descriptor. + * @param 512 bits satus raw data. + */ +static void SD_DecodeStatus(sd_card_t *card, uint32_t *src); + +/*! + * @brief Read data from specific SD card. + * + * @param card Card descriptor. + * @param buffer Buffer to save data blocks read. + * @param startBlock Card start block number to be read. + * @param blockSize Block size. + * @param blockCount Block count. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Wait write complete failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Read(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockSize, uint32_t blockCount); + +/*! + * @brief Write data to specific card + * + * @param card Card descriptor. + * @param buffer Buffer to be sent. + * @param startBlock Card start block number to be written. + * @param blockSize Block size. + * @param blockCount Block count. + * @param blockWritten successfully write blocks + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Write(sd_card_t *card, + const uint8_t *buffer, + uint32_t startBlock, + uint32_t blockSize, + uint32_t blockCount, + uint32_t *blockWritten); + +/*! + * @brief Erase data for the given block range. + * + * @param card Card descriptor. + * @param startBlock Card start block number to be erased. + * @param blockCount The block count to be erased. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +static status_t SD_Erase(sd_card_t *card, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief card transfer function. + * + * @param card Card descriptor. + * @param content Transfer content. + * @param retry Retry times + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + * @retval kStatus_SDMMC_TuningFail tuning fail + */ +static status_t SD_Transfer(sd_card_t *card, SDMMCHOST_TRANSFER *content, uint32_t retry); + +/*! + * @brief card execute tuning function. + * + * @param card Card descriptor. + * @retval kStatus_Success Operate successfully. + * @retval kStatus_SDMMC_TuningFail tuning fail. + * @retval kStatus_SDMMC_TransferFailed transfer fail + */ +static status_t inline SD_ExecuteTuning(sd_card_t *card); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/* g_sdmmc statement */ +extern uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)]; +static uint32_t s_sdAuSizeMap[] = {0, + 16 * 1024, + 32 * 1024, + 64 * 1024, + 128 * 1024, + 256 * 1024, + 512 * 1024, + 1024 * 1024, + 2 * 1024 * 1024, + 4 * 1024 * 1024, + 8 * 1024 * 1024, + 12 * 1024 * 1024, + 16 * 1024 * 1024, + 24 * 1024 * 1024, + 32 * 1024 * 1024, + 64 * 1024 * 1024}; +/******************************************************************************* + * Code + ******************************************************************************/ +static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress) +{ + assert(card); + + return SDMMC_SendApplicationCommand(card->host.base, card->host.transfer, relativeAddress); +} + +static status_t inline SD_GoIdle(sd_card_t *card) +{ + assert(card); + + return SDMMC_GoIdle(card->host.base, card->host.transfer); +} + +static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize) +{ + assert(card); + + return SDMMC_SetBlockSize(card->host.base, card->host.transfer, blockSize); +} + +static status_t inline SD_ExecuteTuning(sd_card_t *card) +{ + assert(card); + + return SDMMC_ExecuteTuning(card->host.base, card->host.transfer, kSD_SendTuningBlock, 64U); +} + +static status_t SD_SwitchVoltage(sd_card_t *card) +{ + assert(card); + + return SDMMC_SwitchVoltage(card->host.base, card->host.transfer); +} + +static status_t SD_StopTransmission(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_StopTransmission; + command.argument = 0U; + command.type = kCARD_CommandTypeAbort; + command.responseType = kCARD_ResponseTypeR1b; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = 0U; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD12 failed with host error %d, reponse %x\r\n", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +static status_t SD_Transfer(sd_card_t *card, SDMMCHOST_TRANSFER *content, uint32_t retry) +{ + assert(card->host.transfer); + assert(content); + status_t error; + + do + { + error = card->host.transfer(card->host.base, content); +#if SDMMC_ENABLE_SOFTWARE_TUNING + if (((error == SDMMCHOST_RETUNING_REQUEST) || (error == SDMMCHOST_TUNING_ERROR)) && + (card->currentTiming == kSD_TimingSDR104Mode)) + { + /* tuning error need reset tuning circuit */ + if (error == SDMMCHOST_TUNING_ERROR) + { + SDMMCHOST_RESET_TUNING(card->host.base, 100U); + } + + /* execute re-tuning */ + if (SD_ExecuteTuning(card) != kStatus_Success) + { + error = kStatus_SDMMC_TuningFail; + break; + } + else + { + continue; + } + } + else +#endif + if (error != kStatus_Success) + { + /* if transfer data failed, send cmd12 to abort current transfer */ + if (content->data) + { + SD_StopTransmission(card); + } + } + + if (retry != 0U) + { + retry--; + } + else + { + break; + } + + } while (error != kStatus_Success); + + return error; +} + +static status_t SD_WaitWriteComplete(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_SendStatus; + command.argument = card->relativeAddress << 16U; + command.responseType = kCARD_ResponseTypeR1; + + do + { + content.command = &command; + content.data = 0U; + error = SD_Transfer(card, &content, 2U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD13 failed with host error %d, response %x", error, command.response[0U]); + break; + } + + if ((command.response[0U] & SDMMC_MASK(kSDMMC_R1ReadyForDataFlag)) && + (SDMMC_R1_CURRENT_STATE(command.response[0U]) != kSDMMC_R1StateProgram)) + { + break; + } + } while (true); + + return error; +} + +static status_t SD_SendWriteSuccessBlocks(sd_card_t *card, uint32_t *blocks) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + /* Wait for the card write process complete because of that card read process and write process use one buffer. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSendNumberWriteBlocks; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 4U; + data.blockCount = 1U; + data.rxData = &g_sdmmc[0]; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD13 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + *blocks = SWAP_WORD_BYTE_SEQUENCE(g_sdmmc[0]); + } + + return error; +} + +static status_t SD_SendRca(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSD_SendRelativeAddress; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR6; + + content.command = &command; + content.data = NULL; + + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success == error) + { + card->relativeAddress = (command.response[0U] >> 16U); + } + else + { + SDMMC_LOG("\r\nError: send CMD3 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static status_t SD_SwitchFunction(sd_card_t *card, uint32_t mode, uint32_t group, uint32_t number, uint32_t *status) +{ + assert(card); + assert(status); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + command.index = kSD_Switch; + command.argument = (mode << 31U | 0x00FFFFFFU); + command.argument &= ~((uint32_t)(0xFU) << (group * 4U)); + command.argument |= (number << (group * 4U)); + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 64U; + data.blockCount = 1U; + data.rxData = status; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\n\r\nError: send CMD6 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeScr(sd_card_t *card, uint32_t *rawScr) +{ + assert(card); + assert(rawScr); + + sd_scr_t *scr; + + scr = &(card->scr); + scr->scrStructure = (uint8_t)((rawScr[0U] & 0xF0000000U) >> 28U); + scr->sdSpecification = (uint8_t)((rawScr[0U] & 0xF000000U) >> 24U); + if ((uint8_t)((rawScr[0U] & 0x800000U) >> 23U)) + { + scr->flags |= kSD_ScrDataStatusAfterErase; + } + scr->sdSecurity = (uint8_t)((rawScr[0U] & 0x700000U) >> 20U); + scr->sdBusWidths = (uint8_t)((rawScr[0U] & 0xF0000U) >> 16U); + if ((uint8_t)((rawScr[0U] & 0x8000U) >> 15U)) + { + scr->flags |= kSD_ScrSdSpecification3; + } + scr->extendedSecurity = (uint8_t)((rawScr[0U] & 0x7800U) >> 10U); + scr->commandSupport = (uint8_t)(rawScr[0U] & 0x3U); + scr->reservedForManufacturer = rawScr[1U]; + /* Get specification version. */ + switch (scr->sdSpecification) + { + case 0U: + card->version = kSD_SpecificationVersion1_0; + break; + case 1U: + card->version = kSD_SpecificationVersion1_1; + break; + case 2U: + card->version = kSD_SpecificationVersion2_0; + if (card->scr.flags & kSD_ScrSdSpecification3) + { + card->version = kSD_SpecificationVersion3_0; + } + break; + default: + break; + } + if (card->scr.sdBusWidths & 0x4U) + { + card->flags |= kSD_Support4BitWidthFlag; + } + /* speed class control cmd */ + if (card->scr.commandSupport & 0x01U) + { + card->flags |= kSD_SupportSpeedClassControlCmd; + } + /* set block count cmd */ + if (card->scr.commandSupport & 0x02U) + { + card->flags |= kSD_SupportSetBlockCountCmd; + } +} + +static status_t SD_SendScr(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + uint32_t *rawScr = g_sdmmc; + status_t error = kStatus_Success; + + /* memset the global buffer */ + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSendScr; + command.responseType = kCARD_ResponseTypeR1; + command.argument = 0U; + + data.blockSize = 8U; + data.blockCount = 1U; + data.rxData = rawScr; + + content.data = &data; + content.command = &command; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD51 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + /* SCR register data byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in a + word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + rawScr[0U] = SWAP_WORD_BYTE_SEQUENCE(rawScr[0U]); + rawScr[1U] = SWAP_WORD_BYTE_SEQUENCE(rawScr[1U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + rawScr[0U] = SWAP_HALF_WROD_BYTE_SEQUENCE(rawScr[0U]); + rawScr[1U] = SWAP_HALF_WROD_BYTE_SEQUENCE(rawScr[1U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + memcpy(card->rawScr, rawScr, sizeof(card->rawScr)); + /* decode scr */ + SD_DecodeScr(card, rawScr); + } + + return error; +} + +static status_t SD_SelectFunction(sd_card_t *card, uint32_t group, uint32_t function) +{ + assert(card); + + uint32_t *functionStatus = g_sdmmc; + uint16_t functionGroupInfo[6U] = {0}; + uint32_t currentFunctionStatus = 0U; + + /* memset the global buffer */ + memset(g_sdmmc, 0, sizeof(g_sdmmc)); + + /* check if card support CMD6 */ + if ((card->version <= kSD_SpecificationVersion1_0) || (!(card->csd.cardCommandClass & kSDMMC_CommandClassSwitch))) + { + SDMMC_LOG("\r\nError: current card not support CMD6"); + return kStatus_SDMMC_NotSupportYet; + } + + /* Check if card support high speed mode. */ + if (kStatus_Success != SD_SwitchFunction(card, kSD_SwitchCheck, group, function, functionStatus)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Switch function status byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in + a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + functionStatus[0U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[0U]); + functionStatus[1U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[1U]); + functionStatus[2U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[2U]); + functionStatus[3U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[4U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + functionStatus[0U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[0U]); + functionStatus[1U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[1U]); + functionStatus[2U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[2U]); + functionStatus[3U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[4U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + /* -functionStatus[0U]---bit511~bit480; + -functionStatus[1U]---bit479~bit448; + -functionStatus[2U]---bit447~bit416; + -functionStatus[3U]---bit415~bit384; + -functionStatus[4U]---bit383~bit352; + According to the "switch function status[bits 511~0]" return by switch command in mode "check function": + -Check if function 1(high speed) in function group 1 is supported by checking if bit 401 is set; + -check if function 1 is ready and can be switched by checking if bits 379~376 equal value 1; + */ + functionGroupInfo[5U] = (uint16_t)functionStatus[0U]; + functionGroupInfo[4U] = (uint16_t)(functionStatus[1U] >> 16U); + functionGroupInfo[3U] = (uint16_t)(functionStatus[1U]); + functionGroupInfo[2U] = (uint16_t)(functionStatus[2U] >> 16U); + functionGroupInfo[1U] = (uint16_t)(functionStatus[2U]); + functionGroupInfo[0U] = (uint16_t)(functionStatus[3U] >> 16U); + currentFunctionStatus = ((functionStatus[3U] & 0xFFU) << 8U) | (functionStatus[4U] >> 24U); + + /* check if function is support */ + if (((functionGroupInfo[group] & (1 << function)) == 0U) || + ((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) + { + SDMMC_LOG("\r\nError: current card not support function %d", function); + return kStatus_SDMMC_NotSupportYet; + } + + /* Switch to high speed mode. */ + if (kStatus_Success != SD_SwitchFunction(card, kSD_SwitchSet, group, function, functionStatus)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Switch function status byte sequence from card is big endian(MSB first). */ + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode is little endian, SD bus byte transferred first is the byte stored in lowest byte + position in a word which will cause 4 byte's sequence in a word is not consistent with their original + sequence from card. So the sequence of 4 bytes received in a word should be converted. */ + functionStatus[3U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_WORD_BYTE_SEQUENCE(functionStatus[4U]); + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + functionStatus[3U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[3U]); + functionStatus[4U] = SWAP_HALF_WROD_BYTE_SEQUENCE(functionStatus[4U]); + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + /* According to the "switch function status[bits 511~0]" return by switch command in mode "set function": + -check if group 1 is successfully changed to function 1 by checking if bits 379~376 equal value 1; + */ + currentFunctionStatus = ((functionStatus[3U] & 0xFFU) << 8U) | (functionStatus[4U] >> 24U); + + if (((currentFunctionStatus >> (group * 4U)) & 0xFU) != function) + { + SDMMC_LOG("\r\nError: switch to function %d failed", function); + return kStatus_SDMMC_SwitchFailed; + } + + return kStatus_Success; +} + +static status_t SD_SetDataBusWidth(sd_card_t *card, sd_data_bus_width_t width) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSD_ApplicationSetBusWdith; + command.responseType = kCARD_ResponseTypeR1; + switch (width) + { + case kSD_DataBusWidth1Bit: + command.argument = 0U; + break; + case kSD_DataBusWidth4Bit: + command.argument = 2U; + break; + default: + return kStatus_InvalidArgument; + } + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD6 failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeCsd(sd_card_t *card, uint32_t *rawCsd) +{ + assert(card); + assert(rawCsd); + + sd_csd_t *csd; + + csd = &(card->csd); + csd->csdStructure = (uint8_t)((rawCsd[3U] & 0xC0000000U) >> 30U); + csd->dataReadAccessTime1 = (uint8_t)((rawCsd[3U] & 0xFF0000U) >> 16U); + csd->dataReadAccessTime2 = (uint8_t)((rawCsd[3U] & 0xFF00U) >> 8U); + csd->transferSpeed = (uint8_t)(rawCsd[3U] & 0xFFU); + csd->cardCommandClass = (uint16_t)((rawCsd[2U] & 0xFFF00000U) >> 20U); + csd->readBlockLength = (uint8_t)((rawCsd[2U] & 0xF0000U) >> 16U); + if (rawCsd[2U] & 0x8000U) + { + csd->flags |= kSD_CsdReadBlockPartialFlag; + } + if (rawCsd[2U] & 0x4000U) + { + csd->flags |= kSD_CsdReadBlockPartialFlag; + } + if (rawCsd[2U] & 0x2000U) + { + csd->flags |= kSD_CsdReadBlockMisalignFlag; + } + if (rawCsd[2U] & 0x1000U) + { + csd->flags |= kSD_CsdDsrImplementedFlag; + } + switch (csd->csdStructure) + { + case 0: + csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3FFU) << 2U); + csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xC0000000U) >> 30U); + csd->readCurrentVddMin = (uint8_t)((rawCsd[1U] & 0x38000000U) >> 27U); + csd->readCurrentVddMax = (uint8_t)((rawCsd[1U] & 0x7000000U) >> 24U); + csd->writeCurrentVddMin = (uint8_t)((rawCsd[1U] & 0xE00000U) >> 20U); + csd->writeCurrentVddMax = (uint8_t)((rawCsd[1U] & 0x1C0000U) >> 18U); + csd->deviceSizeMultiplier = (uint8_t)((rawCsd[1U] & 0x38000U) >> 15U); + + /* Get card total block count and block size. */ + card->blockCount = ((csd->deviceSize + 1U) << (csd->deviceSizeMultiplier + 2U)); + card->blockSize = (1U << (csd->readBlockLength)); + if (card->blockSize != FSL_SDMMC_DEFAULT_BLOCK_SIZE) + { + card->blockCount = (card->blockCount * card->blockSize); + card->blockSize = FSL_SDMMC_DEFAULT_BLOCK_SIZE; + card->blockCount = (card->blockCount / card->blockSize); + } + break; + case 1: + card->blockSize = FSL_SDMMC_DEFAULT_BLOCK_SIZE; + + csd->deviceSize = (uint32_t)((rawCsd[2U] & 0x3FU) << 16U); + csd->deviceSize |= (uint32_t)((rawCsd[1U] & 0xFFFF0000U) >> 16U); + if (csd->deviceSize >= 0xFFFFU) + { + card->flags |= kSD_SupportSdxcFlag; + } + + card->blockCount = ((csd->deviceSize + 1U) * 1024U); + break; + default: + break; + } + if ((uint8_t)((rawCsd[1U] & 0x4000U) >> 14U)) + { + csd->flags |= kSD_CsdEraseBlockEnabledFlag; + } + csd->eraseSectorSize = (uint8_t)((rawCsd[1U] & 0x3F80U) >> 7U); + csd->writeProtectGroupSize = (uint8_t)(rawCsd[1U] & 0x7FU); + if ((uint8_t)(rawCsd[0U] & 0x80000000U)) + { + csd->flags |= kSD_CsdWriteProtectGroupEnabledFlag; + } + csd->writeSpeedFactor = (uint8_t)((rawCsd[0U] & 0x1C000000U) >> 26U); + csd->writeBlockLength = (uint8_t)((rawCsd[0U] & 0x3C00000U) >> 22U); + if ((uint8_t)((rawCsd[0U] & 0x200000U) >> 21U)) + { + csd->flags |= kSD_CsdWriteBlockPartialFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x8000U) >> 15U)) + { + csd->flags |= kSD_CsdFileFormatGroupFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x4000U) >> 14U)) + { + csd->flags |= kSD_CsdCopyFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x2000U) >> 13U)) + { + csd->flags |= kSD_CsdPermanentWriteProtectFlag; + } + if ((uint8_t)((rawCsd[0U] & 0x1000U) >> 12U)) + { + csd->flags |= kSD_CsdTemporaryWriteProtectFlag; + } + csd->fileFormat = (uint8_t)((rawCsd[0U] & 0xC00U) >> 10U); +} + +static status_t SD_SendCsd(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSDMMC_SendCsd; + command.argument = (card->relativeAddress << 16U); + command.responseType = kCARD_ResponseTypeR2; + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success == error) + { + memcpy(card->rawCsd, command.response, sizeof(card->rawCsd)); + /* The response is from bit 127:8 in R2, corrisponding to command.response[3U]:command.response[0U][31U:8]. */ + SD_DecodeCsd(card, command.response); + } + else + { + error = kStatus_SDMMC_TransferFailed; + SDMMC_LOG("\r\nError: send CMD9(get csd) failed with host error %d, response %x", error, command.response[0U]); + } + + return error; +} + +static void SD_DecodeCid(sd_card_t *card, uint32_t *rawCid) +{ + assert(card); + assert(rawCid); + + sd_cid_t *cid; + + cid = &(card->cid); + cid->manufacturerID = (uint8_t)((rawCid[3U] & 0xFF000000U) >> 24U); + cid->applicationID = (uint16_t)((rawCid[3U] & 0xFFFF00U) >> 8U); + + cid->productName[0U] = (uint8_t)((rawCid[3U] & 0xFFU)); + cid->productName[1U] = (uint8_t)((rawCid[2U] & 0xFF000000U) >> 24U); + cid->productName[2U] = (uint8_t)((rawCid[2U] & 0xFF0000U) >> 16U); + cid->productName[3U] = (uint8_t)((rawCid[2U] & 0xFF00U) >> 8U); + cid->productName[4U] = (uint8_t)((rawCid[2U] & 0xFFU)); + + cid->productVersion = (uint8_t)((rawCid[1U] & 0xFF000000U) >> 24U); + + cid->productSerialNumber = (uint32_t)((rawCid[1U] & 0xFFFFFFU) << 8U); + cid->productSerialNumber |= (uint32_t)((rawCid[0U] & 0xFF000000U) >> 24U); + + cid->manufacturerData = (uint16_t)((rawCid[0U] & 0xFFF00U) >> 8U); +} + +static status_t SD_AllSendCid(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_AllSendCid; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR2; + + content.command = &command; + content.data = NULL; + if (kStatus_Success == card->host.transfer(card->host.base, &content)) + { + memcpy(card->rawCid, command.response, sizeof(card->rawCid)); + SD_DecodeCid(card, command.response); + + return kStatus_Success; + } + + return kStatus_SDMMC_TransferFailed; +} + +static status_t SD_ApplicationSendOperationCondition(sd_card_t *card, uint32_t argument) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Fail; + uint32_t i = FSL_SDMMC_MAX_VOLTAGE_RETRIES; + + command.index = kSD_ApplicationSendOperationCondition; + command.argument = argument; + command.responseType = kCARD_ResponseTypeR3; + + while (i--) + { + if (kStatus_Success != SD_SendApplicationCmd(card, 0U)) + { + continue; + } + + content.command = &command; + content.data = NULL; + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send ACMD41 failed with host error %d, response %x", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Wait until card exit busy state. */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrPowerUpBusyFlag)) + { + /* high capacity check */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrCardCapacitySupportFlag)) + { + card->flags |= kSD_SupportHighCapacityFlag; + } + /* 1.8V support */ + if (command.response[0U] & SDMMC_MASK(kSD_OcrSwitch18AcceptFlag)) + { + card->flags |= kSD_SupportVoltage180v; + } + card->ocr = command.response[0U]; + + return kStatus_Success; + } + } + + SDMMC_LOG("\r\nError: send ACMD41 timeout"); + + return error; +} + +static status_t SD_SendInterfaceCondition(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + uint32_t i = FSL_SDMMC_MAX_CMD_RETRIES; + status_t error = kStatus_Success; + + command.index = kSD_SendInterfaceCondition; + command.argument = 0x1AAU; + command.responseType = kCARD_ResponseTypeR7; + + content.command = &command; + content.data = NULL; + do + { + error = card->host.transfer(card->host.base, &content); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD8 failed with host error %d, response %x", error, command.response[0U]); + } + else + { + if ((command.response[0U] & 0xFFU) != 0xAAU) + { + error = kStatus_SDMMC_CardNotSupport; + SDMMC_LOG("\r\nError: card not support CMD8"); + } + else + { + error = kStatus_Success; + } + } + } while (--i && (error != kStatus_Success)); + + return error; +} + +static status_t SD_SelectBusTiming(sd_card_t *card) +{ + assert(card); + + status_t error = kStatus_SDMMC_SwitchBusTimingFailed; + + if (card->operationVoltage != kCARD_OperationVoltage180V) + { + /* Switch the card to high speed mode */ + if (card->host.capability.flags & kSDMMCHOST_SupportHighSpeed) + { + /* group 1, function 1 ->high speed mode*/ + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR25HighSpeed); + /* If the result isn't "switching to high speed mode(50MHZ) successfully or card doesn't support high speed + * mode". Return failed status. */ + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR25HighSpeedMode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + } + else if (error == kStatus_SDMMC_NotSupportYet) + { + /* if not support high speed, keep the card work at default mode */ + SDMMC_LOG("\r\nNote: High speed mode is not supported by card"); + return kStatus_Success; + } + } + else + { + /* if not support high speed, keep the card work at default mode */ + return kStatus_Success; + } + } + /* card is in UHS_I mode */ + else if ((kSDMMCHOST_SupportSDR104 != SDMMCHOST_NOT_SUPPORT) || + (kSDMMCHOST_SupportSDR50 != SDMMCHOST_NOT_SUPPORT) || (kSDMMCHOST_SupportDDR50 != SDMMCHOST_NOT_SUPPORT)) + { + switch (card->currentTiming) + { + /* if not select timing mode, sdmmc will handle it automatically*/ + case kSD_TimingSDR12DefaultMode: + case kSD_TimingSDR104Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR104); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR104Mode; + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, + SDMMCHOST_SUPPORT_SDR104_FREQ); + break; + } + SDMMC_LOG("\r\nNote: SDR104 mode is not supported by card"); + + case kSD_TimingDDR50Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionDDR50); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingDDR50Mode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + SDMMCHOST_ENABLE_DDR_MODE(card->host.base, true, 0U); + break; + } + SDMMC_LOG("\r\nNote: DDR50 mode is not supported by card"); + + case kSD_TimingSDR50Mode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR50); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR50Mode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_100MHZ); + break; + } + SDMMC_LOG("\r\nNote: SDR50 mode is not supported by card"); + + case kSD_TimingSDR25HighSpeedMode: + error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR25HighSpeed); + if (error == kStatus_Success) + { + card->currentTiming = kSD_TimingSDR25HighSpeedMode; + card->busClock_Hz = + SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_50MHZ); + } + break; + + default: + SDMMC_LOG("\r\nWarning: unknown timing mode"); + break; + } + } + else + { + } + + if (error == kStatus_Success) + { + /* SDR50 and SDR104 mode need tuning */ + if ((card->currentTiming == kSD_TimingSDR50Mode) || (card->currentTiming == kSD_TimingSDR104Mode)) + { + /* config IO strength in IOMUX*/ + if (card->currentTiming == kSD_TimingSDR50Mode) + { + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_100MHZ1, CARD_BUS_STRENGTH_7); + } + else + { + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_200MHZ, CARD_BUS_STRENGTH_7); + } + /* execute tuning */ + if (SD_ExecuteTuning(card) != kStatus_Success) + { + SDMMC_LOG("\r\nError: tuning failed for mode %d", card->currentTiming); + return kStatus_SDMMC_TuningFail; + } + } + else + { + /* set default IO strength to 4 to cover card adapter driver strength difference */ + SDMMCHOST_CONFIG_SD_IO(CARD_BUS_FREQ_100MHZ1, CARD_BUS_STRENGTH_4); + } + } + + return error; +} + +static void SD_DecodeStatus(sd_card_t *card, uint32_t *src) +{ + assert(card); + assert(src); + + card->stat.busWidth = (uint8_t)((src[0U] & 0xC0000000U) >> 30U); /* 511-510 */ + card->stat.secureMode = (uint8_t)((src[0U] & 0x20000000U) >> 29U); /* 509 */ + card->stat.cardType = (uint16_t)((src[0U] & 0x0000FFFFU)); /* 495-480 */ + card->stat.protectedSize = src[1U]; /* 479-448 */ + card->stat.speedClass = (uint8_t)((src[2U] & 0xFF000000U) >> 24U); /* 447-440 */ + card->stat.performanceMove = (uint8_t)((src[2U] & 0x00FF0000U) >> 16U); /* 439-432 */ + card->stat.auSize = (uint8_t)((src[2U] & 0x0000F000U) >> 12U); /* 431-428 */ + card->stat.eraseSize = (uint16_t)(((src[2U] & 0x000000FFU) << 8U) | ((src[3U] & 0xFF000000U) >> 24U)); /* 423-408 */ + card->stat.eraseTimeout = (((uint8_t)((src[3U] & 0x00FF0000U) >> 16U)) & 0xFCU) >> 2U; /* 407-402 */ + card->stat.eraseOffset = ((uint8_t)((src[3U] & 0x00FF0000U) >> 16U)) & 0x3U; /* 401-400 */ + card->stat.uhsSpeedGrade = (((uint8_t)((src[3U] & 0x0000FF00U) >> 8U)) & 0xF0U) >> 4U; /* 399-396 */ + card->stat.uhsAuSize = ((uint8_t)((src[3U] & 0x0000FF00U) >> 8U)) & 0xFU; /* 395-392 */ +} + +status_t SD_ReadStatus(sd_card_t *card) +{ + assert(card); + + uint32_t i = 0U; + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error = kStatus_Success; + + memset(g_sdmmc, 0U, sizeof(g_sdmmc)); + + /* wait card status ready. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + if (kStatus_Success != SD_SendApplicationCmd(card, card->relativeAddress)) + { + return kStatus_SDMMC_SendApplicationCommandFailed; + } + + command.index = kSDMMC_SendStatus; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = 64U; + data.blockCount = 1U; + data.rxData = &g_sdmmc[0]; + + content.command = &command; + content.data = &data; + error = card->host.transfer(card->host.base, &content); + if ((kStatus_Success != error) || ((command.response[0U]) & SDMMC_R1_ALL_ERROR_FLAG)) + { + SDMMC_LOG("\r\nError: send ACMD13 failed with host error %d, response %x", error, command.response[0U]); + + return kStatus_SDMMC_TransferFailed; + } + + switch (card->host.config.endianMode) + { + case kSDMMCHOST_EndianModeLittle: + /* In little endian mode, SD bus byte transferred first is the byte stored in lowest byte position in + a word which will cause 4 byte's sequence in a word is not consistent with their original sequence from + card. So the sequence of 4 bytes received in a word should be converted. */ + for (i = 0U; i < 16; i++) + { + g_sdmmc[i] = SWAP_WORD_BYTE_SEQUENCE(g_sdmmc[i]); + } + break; + case kSDMMCHOST_EndianModeBig: + break; /* Doesn't need to switch byte sequence when decodes bytes as big endian sequence. */ + case kSDMMCHOST_EndianModeHalfWordBig: + for (i = 0U; i < 16; i++) + { + g_sdmmc[i] = SWAP_HALF_WROD_BYTE_SEQUENCE(g_sdmmc[i]); + } + break; + default: + return kStatus_SDMMC_NotSupportYet; + } + + SD_DecodeStatus(card, g_sdmmc); + + return kStatus_Success; +} + +status_t SD_SelectCard(sd_card_t *card, bool isSelected) +{ + assert(card); + + return SDMMC_SelectCard(card->host.base, card->host.transfer, card->relativeAddress, isSelected); +} + +status_t SD_SetDriverStrength(sd_card_t *card, sd_driver_strength_t driverStrength) +{ + assert(card); + + status_t error; + uint32_t strength = driverStrength; + + error = SD_SelectFunction(card, kSD_GroupDriverStrength, strength); + + return error; +} + +status_t SD_SetMaxCurrent(sd_card_t *card, sd_max_current_t maxCurrent) +{ + assert(card); + + status_t error; + uint32_t current = maxCurrent; + + error = SD_SelectFunction(card, kSD_GroupCurrentLimit, current); + + return error; +} + +static status_t SD_Read(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockSize, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert(blockSize == FSL_SDMMC_DEFAULT_BLOCK_SIZE); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + + if (((card->flags & kSD_SupportHighCapacityFlag) && (blockSize != 512U)) || (blockSize > card->blockSize) || + (blockSize > card->host.capability.maxBlockLength) || (blockSize % 4)) + { + SDMMC_LOG("\r\nError: read with parameter, block size %d is not support", blockSize); + return kStatus_SDMMC_CardNotSupport; + } + + /* Wait for the card write process complete because of that card read process and write process use one buffer. */ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + data.blockSize = blockSize; + data.blockCount = blockCount; + data.rxData = (uint32_t *)buffer; + data.enableAutoCommand12 = true; + + command.index = (blockCount == 1U) ? kSDMMC_ReadSingleBlock : kSDMMC_ReadMultipleBlock; + command.argument = startBlock; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + command.argument *= data.blockSize; + } + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = &data; + + return SD_Transfer(card, &content, 1U); +} + +static status_t SD_Write(sd_card_t *card, + const uint8_t *buffer, + uint32_t startBlock, + uint32_t blockSize, + uint32_t blockCount, + uint32_t *writtenBlocks) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert(blockSize == FSL_SDMMC_DEFAULT_BLOCK_SIZE); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + SDMMCHOST_DATA data = {0}; + status_t error; + + if (((card->flags & kSD_SupportHighCapacityFlag) && (blockSize != 512U)) || (blockSize > card->blockSize) || + (blockSize > card->host.capability.maxBlockLength) || (blockSize % 4U)) + { + SDMMC_LOG("\r\nError: write with parameter, block size %d is not support", blockSize); + return kStatus_SDMMC_CardNotSupport; + } + + /* Wait for the card write process complete because of that card read process and write process use one buffer.*/ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + + /* Wait for the card's buffer to be not full to write to improve the write performance. */ + while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) + { + } + + data.enableAutoCommand12 = true; + data.blockSize = blockSize; + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + command.index = (blockCount == 1U) ? kSDMMC_WriteSingleBlock : kSDMMC_WriteMultipleBlock; + command.argument = startBlock; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + command.argument *= data.blockSize; + } + + *writtenBlocks = blockCount; + data.blockCount = blockCount; + data.txData = (const uint32_t *)(buffer); + + content.command = &command; + content.data = &data; + + error = SD_Transfer(card, &content, 0U); + if (error != kStatus_Success) + { + /* check the successfully written block */ + if ((SD_SendWriteSuccessBlocks(card, writtenBlocks) == kStatus_Success)) + { + if (*writtenBlocks) + { + /* written success, but not all the blocks are written */ + error = kStatus_Success; + } + } + SDMMC_LOG("\r\nWarning: write failed with block count %d, successed %d", blockCount, *writtenBlocks); + } + + return error; +} + +static status_t SD_Erase(sd_card_t *card, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(blockCount); + + uint32_t eraseBlockStart; + uint32_t eraseBlockEnd; + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + /* Wait for the card write process complete because of that card read process and write process use one buffer.*/ + if (kStatus_Success != SD_WaitWriteComplete(card)) + { + return kStatus_SDMMC_WaitWriteCompleteFailed; + } + /* Wait for the card's buffer to be not full to write to improve the write performance. */ + while ((GET_SDMMCHOST_STATUS(card->host.base) & CARD_DATA0_STATUS_MASK) != CARD_DATA0_NOT_BUSY) + { + } + + eraseBlockStart = startBlock; + eraseBlockEnd = eraseBlockStart + blockCount - 1U; + if (!(card->flags & kSD_SupportHighCapacityFlag)) + { + eraseBlockStart = eraseBlockStart * FSL_SDMMC_DEFAULT_BLOCK_SIZE; + eraseBlockEnd = eraseBlockEnd * FSL_SDMMC_DEFAULT_BLOCK_SIZE; + } + + /* Send ERASE_WRITE_BLOCK_START command to set the start block number to erase. */ + command.index = kSD_EraseWriteBlockStart; + command.argument = eraseBlockStart; + command.responseType = kCARD_ResponseTypeR1; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 1U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD32(erase start) failed with host error %d, response %x", error, + command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Send ERASE_WRITE_BLOCK_END command to set the end block number to erase. */ + command.index = kSD_EraseWriteBlockEnd; + command.argument = eraseBlockEnd; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 0U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD33(erase end) failed with host error %d, response %x", error, + command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + /* Send ERASE command to start erase process. */ + command.index = kSDMMC_Erase; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1b; + command.responseErrorFlags = SDMMC_R1_ALL_ERROR_FLAG; + + content.command = &command; + content.data = NULL; + error = SD_Transfer(card, &content, 0U); + if (kStatus_Success != error) + { + SDMMC_LOG("\r\nError: send CMD38(erase) failed with host error %d, response %x", error, command.response[0U]); + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +bool SD_CheckReadOnly(sd_card_t *card) +{ + assert(card); + + return ((card->csd.flags & kSD_CsdPermanentWriteProtectFlag) || + (card->csd.flags & kSD_CsdTemporaryWriteProtectFlag)); +} + +status_t SD_ReadBlocks(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime; + uint32_t blockLeft; + uint32_t blockDone = 0U; + uint8_t *nextBuffer = buffer; + bool dataAddrAlign = true; + + blockLeft = blockCount; + + while (blockLeft) + { + nextBuffer = (buffer + blockDone * FSL_SDMMC_DEFAULT_BLOCK_SIZE); + if (!card->noInteralAlign && (!dataAddrAlign || (((uint32_t)nextBuffer) & (sizeof(uint32_t) - 1U)))) + { + blockLeft--; + blockCountOneTime = 1U; + memset(g_sdmmc, 0U, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + dataAddrAlign = false; + } + else + { + if (blockLeft > card->host.capability.maxBlockCount) + { + blockLeft = (blockLeft - card->host.capability.maxBlockCount); + blockCountOneTime = card->host.capability.maxBlockCount; + } + else + { + blockCountOneTime = blockLeft; + blockLeft = 0U; + } + } + + if (kStatus_Success != SD_Read(card, dataAddrAlign ? nextBuffer : (uint8_t *)g_sdmmc, (startBlock + blockDone), + FSL_SDMMC_DEFAULT_BLOCK_SIZE, blockCountOneTime)) + { + return kStatus_SDMMC_TransferFailed; + } + + blockDone += blockCountOneTime; + + if (!card->noInteralAlign && (!dataAddrAlign)) + { + memcpy(nextBuffer, (uint8_t *)&g_sdmmc, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + } + } + + return kStatus_Success; +} + +status_t SD_WriteBlocks(sd_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(buffer); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime = 0U; /* The block count can be wrote in one time sending WRITE_BLOCKS command. */ + uint32_t blockWrittenOneTime = 0U; + uint32_t blockLeft = 0U; /* Left block count to be wrote. */ + const uint8_t *nextBuffer; + bool dataAddrAlign = true; + + blockLeft = blockCount; + while (blockLeft) + { + nextBuffer = (buffer + (blockCount - blockLeft) * FSL_SDMMC_DEFAULT_BLOCK_SIZE); + if (!card->noInteralAlign && (!dataAddrAlign || (((uint32_t)nextBuffer) & (sizeof(uint32_t) - 1U)))) + { + blockCountOneTime = 1U; + memcpy((uint8_t *)&g_sdmmc, nextBuffer, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + dataAddrAlign = false; + } + else + { + if (blockLeft > card->host.capability.maxBlockCount) + { + blockCountOneTime = card->host.capability.maxBlockCount; + } + else + { + blockCountOneTime = blockLeft; + } + } + + if (kStatus_Success != SD_Write(card, dataAddrAlign ? nextBuffer : (uint8_t *)g_sdmmc, + (startBlock + blockCount - blockLeft), FSL_SDMMC_DEFAULT_BLOCK_SIZE, + blockCountOneTime, &blockWrittenOneTime)) + { + return kStatus_SDMMC_TransferFailed; + } + + blockLeft -= blockWrittenOneTime; + + if ((!card->noInteralAlign) && !dataAddrAlign) + { + memset(g_sdmmc, 0U, FSL_SDMMC_DEFAULT_BLOCK_SIZE); + } + } + + return kStatus_Success; +} + +status_t SD_EraseBlocks(sd_card_t *card, uint32_t startBlock, uint32_t blockCount) +{ + assert(card); + assert(blockCount); + assert((blockCount + startBlock) <= card->blockCount); + + uint32_t blockCountOneTime; /* The block count can be erased in one time sending ERASE_BLOCKS command. */ + uint32_t blockDone = 0U; /* The block count has been erased. */ + uint32_t blockLeft; /* Left block count to be erase. */ + status_t error; + uint32_t onetimeMaxEraseBlocks = 0U; + + /* sdsc card erasable sector is determined by CSD register */ + if (card->csd.csdStructure == 0U) + { + onetimeMaxEraseBlocks = card->csd.eraseSectorSize + 1U; + } + else + { + /* limit one time maximum erase size to 1 AU */ + if (card->stat.auSize >= SD_AU_START_VALUE) + { + onetimeMaxEraseBlocks = s_sdAuSizeMap[card->stat.auSize] / FSL_SDMMC_DEFAULT_BLOCK_SIZE; + } + } + + if (onetimeMaxEraseBlocks == 0U) + { + SDMMC_LOG( + "Warning: AU size in sd descriptor is not set properly, please check if SD_ReadStatus is called before\ + SD_EraseBlocks"); + return kStatus_SDMMC_AuSizeNotSetProperly; + } + + blockLeft = blockCount; + while (blockLeft) + { + if (blockLeft > onetimeMaxEraseBlocks) + { + blockCountOneTime = onetimeMaxEraseBlocks; + blockLeft = blockLeft - blockCountOneTime; + } + else + { + blockCountOneTime = blockLeft; + blockLeft = 0U; + } + + error = SD_Erase(card, (startBlock + blockDone), blockCountOneTime); + if (error != kStatus_Success) + { + return error; + } + + blockDone += blockCountOneTime; + } + + return kStatus_Success; +} + +status_t SD_ProbeBusVoltage(sd_card_t *card) +{ + assert(card); + + uint32_t applicationCommand41Argument = 0U; + status_t error = kStatus_Success; + + /* 3.3V voltage should be supported as default */ + applicationCommand41Argument |= + SDMMC_MASK(kSD_OcrVdd29_30Flag) | SDMMC_MASK(kSD_OcrVdd32_33Flag) | SDMMC_MASK(kSD_OcrVdd33_34Flag); + card->operationVoltage = kCARD_OperationVoltage330V; + + /* allow user select the work voltage, if not select, sdmmc will handle it automatically */ + if (kSDMMCHOST_SupportV180 != SDMMCHOST_NOT_SUPPORT) + { + applicationCommand41Argument |= SDMMC_MASK(kSD_OcrSwitch18RequestFlag); + } + + do + { + /* card go idle */ + if (kStatus_Success != SD_GoIdle(card)) + { + error = kStatus_SDMMC_GoIdleFailed; + break; + } + + /* Check card's supported interface condition. */ + if (kStatus_Success == SD_SendInterfaceCondition(card)) + { + /* SDHC or SDXC card */ + applicationCommand41Argument |= SDMMC_MASK(kSD_OcrHostCapacitySupportFlag); + card->flags |= kSD_SupportSdhcFlag; + } + else + { + /* SDSC card */ + if (kStatus_Success != SD_GoIdle(card)) + { + error = kStatus_SDMMC_GoIdleFailed; + break; + } + } + /* Set card interface condition according to SDHC capability and card's supported interface condition. */ + if (kStatus_Success != SD_ApplicationSendOperationCondition(card, applicationCommand41Argument)) + { + error = kStatus_SDMMC_HandShakeOperationConditionFailed; + break; + } + + /* check if card support 1.8V */ + if ((card->flags & kSD_SupportVoltage180v)) + { + error = SD_SwitchVoltage(card); + if (kStatus_SDMMC_SwitchVoltageFail == error) + { + break; + } + + if (error == kStatus_SDMMC_SwitchVoltage18VFail33VSuccess) + { + applicationCommand41Argument &= ~SDMMC_MASK(kSD_OcrSwitch18RequestFlag); + card->flags &= ~kSD_SupportVoltage180v; + continue; + } + else + { + card->operationVoltage = kCARD_OperationVoltage180V; + break; + } + } + + break; + } while (1U); + + return error; +} + +status_t SD_CardInit(sd_card_t *card) +{ + assert(card); + assert(card->isHostReady == true); + + /* reset variables */ + card->flags = 0U; + /* set DATA bus width */ + SDMMCHOST_SET_CARD_BUS_WIDTH(card->host.base, kSDMMCHOST_DATABUSWIDTH1BIT); + /*set card freq to 400KHZ*/ + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SDMMC_CLOCK_400KHZ); + /* send card active */ + SDMMCHOST_SEND_CARD_ACTIVE(card->host.base, 100U); + /* Get host capability. */ + GET_SDMMCHOST_CAPABILITY(card->host.base, &(card->host.capability)); + + /* probe bus voltage*/ + if (SD_ProbeBusVoltage(card) == kStatus_SDMMC_SwitchVoltageFail) + { + return kStatus_SDMMC_SwitchVoltageFail; + } + + /* Initialize card if the card is SD card. */ + if (kStatus_Success != SD_AllSendCid(card)) + { + return kStatus_SDMMC_AllSendCidFailed; + } + if (kStatus_Success != SD_SendRca(card)) + { + return kStatus_SDMMC_SendRelativeAddressFailed; + } + if (kStatus_Success != SD_SendCsd(card)) + { + return kStatus_SDMMC_SendCsdFailed; + } + if (kStatus_Success != SD_SelectCard(card, true)) + { + return kStatus_SDMMC_SelectCardFailed; + } + + /* Set to max frequency in non-high speed mode. */ + card->busClock_Hz = SDMMCHOST_SET_CARD_CLOCK(card->host.base, card->host.sourceClock_Hz, SD_CLOCK_25MHZ); + + if (kStatus_Success != SD_SendScr(card)) + { + return kStatus_SDMMC_SendScrFailed; + } + /* Set to 4-bit data bus mode. */ + if (((card->host.capability.flags) & kSDMMCHOST_Support4BitBusWidth) && (card->flags & kSD_Support4BitWidthFlag)) + { + if (kStatus_Success != SD_SetDataBusWidth(card, kSD_DataBusWidth4Bit)) + { + return kStatus_SDMMC_SetDataBusWidthFailed; + } + SDMMCHOST_SET_CARD_BUS_WIDTH(card->host.base, kSDMMCHOST_DATABUSWIDTH4BIT); + } + + /* set block size */ + if (SD_SetBlockSize(card, FSL_SDMMC_DEFAULT_BLOCK_SIZE)) + { + return kStatus_SDMMC_SetCardBlockSizeFailed; + } + + /* select bus timing */ + if (kStatus_Success != SD_SelectBusTiming(card)) + { + return kStatus_SDMMC_SwitchBusTimingFailed; + } + + /* try to get card current status */ + SD_ReadStatus(card); + + return kStatus_Success; +} + +void SD_CardDeinit(sd_card_t *card) +{ + assert(card); + + SD_SelectCard(card, false); +} + +status_t SD_HostInit(sd_card_t *card) +{ + assert(card); + + if ((!card->isHostReady) && SDMMCHOST_Init(&(card->host), (void *)(card->usrParam.cd)) != kStatus_Success) + { + return kStatus_Fail; + } + + /* set the host status flag, after the card re-plug in, don't need init host again */ + card->isHostReady = true; + + return kStatus_Success; +} + +void SD_HostDeinit(sd_card_t *card) +{ + assert(card); + + SDMMCHOST_Deinit(&(card->host)); + /* should re-init host */ + card->isHostReady = false; +} + +void SD_HostReset(SDMMCHOST_CONFIG *host) +{ + SDMMCHOST_Reset(host->base); +} + +void SD_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + SDMMCHOST_PowerOnCard(base, pwr); +} + +void SD_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + SDMMCHOST_PowerOffCard(base, pwr); +} + +status_t SD_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, const sdmmchost_detect_card_t *cd, bool waitCardStatus) +{ + return SDMMCHOST_WaitCardDetectStatus(hostBase, cd, waitCardStatus); +} + +bool SD_IsCardPresent(sd_card_t *card) +{ + return SDMMCHOST_IsCardPresent(); +} + +status_t SD_Init(sd_card_t *card) +{ + assert(card); + + if (!card->isHostReady) + { + if (SD_HostInit(card) != kStatus_Success) + { + return kStatus_SDMMC_HostNotReady; + } + } + else + { + SD_HostReset(&(card->host)); + } + SD_PowerOffCard(card->host.base, card->usrParam.pwr); + + if (SD_WaitCardDetectStatus(card->host.base, card->usrParam.cd, true) != kStatus_Success) + { + return kStatus_SDMMC_CardDetectFailed; + } + SD_PowerOnCard(card->host.base, card->usrParam.pwr); + + return SD_CardInit(card); +} + +void SD_Deinit(sd_card_t *card) +{ + /* card deinitialize */ + SD_CardDeinit(card); + /* host deinitialize */ + SD_HostDeinit(card); +} diff --git a/target/TARGET_NXP/fsl_sd.h b/target/TARGET_NXP/fsl_sd.h new file mode 100644 index 0000000..128f935 --- /dev/null +++ b/target/TARGET_NXP/fsl_sd.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SD_H_ +#define _FSL_SD_H_ + +#include "fsl_sdmmc_common.h" +/*! + * @addtogroup SDCARD + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief SD card flags */ +enum _sd_card_flag +{ + kSD_SupportHighCapacityFlag = (1U << 1U), /*!< Support high capacity */ + kSD_Support4BitWidthFlag = (1U << 2U), /*!< Support 4-bit data width */ + kSD_SupportSdhcFlag = (1U << 3U), /*!< Card is SDHC */ + kSD_SupportSdxcFlag = (1U << 4U), /*!< Card is SDXC */ + kSD_SupportVoltage180v = (1U << 5U), /*!< card support 1.8v voltage*/ + kSD_SupportSetBlockCountCmd = (1U << 6U), /*!< card support cmd23 flag*/ + kSD_SupportSpeedClassControlCmd = (1U << 7U), /*!< card support speed class control flag */ +}; + +/*! @brief card user parameter, user can define the parameter according the board, card capability */ +typedef struct _sdcard_usr_param +{ + const sdmmchost_detect_card_t *cd; /*!< card detect type */ + const sdmmchost_pwr_card_t *pwr; /*!< power control configuration */ +} sdcard_usr_param_t; + +/*! + * @brief SD card state + * + * Define the card structure including the necessary fields to identify and describe the card. + */ +typedef struct _sd_card +{ + SDMMCHOST_CONFIG host; /*!< Host information */ + + sdcard_usr_param_t usrParam; /*!< user parameter */ + bool isHostReady; /*!< use this flag to indicate if need host re-init or not*/ + bool noInteralAlign; /*!< use this flag to disable sdmmc align. If disable, sdmmc will not make sure the + data buffer address is word align, otherwise all the transfer are align to low level driver */ + uint32_t busClock_Hz; /*!< SD bus clock frequency united in Hz */ + uint32_t relativeAddress; /*!< Relative address of the card */ + uint32_t version; /*!< Card version */ + uint32_t flags; /*!< Flags in _sd_card_flag */ + uint32_t rawCid[4U]; /*!< Raw CID content */ + uint32_t rawCsd[4U]; /*!< Raw CSD content */ + uint32_t rawScr[2U]; /*!< Raw CSD content */ + uint32_t ocr; /*!< Raw OCR content */ + sd_cid_t cid; /*!< CID */ + sd_csd_t csd; /*!< CSD */ + sd_scr_t scr; /*!< SCR */ + sd_status_t stat; /*!< sd 512 bit status */ + uint32_t blockCount; /*!< Card total block number */ + uint32_t blockSize; /*!< Card block size */ + sd_timing_mode_t currentTiming; /*!< current timing mode */ + sd_driver_strength_t driverStrength; /*!< driver strength */ + sd_max_current_t maxCurrent; /*!< card current limit */ + sdmmc_operation_voltage_t operationVoltage; /*!< card operation voltage */ +} sd_card_t; + +/************************************************************************************************* + * API + ************************************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name SDCARD Function + * @{ + */ + +/*! + * @brief Initializes the card on a specific host controller. + * @deprecated Do not use this function. It has been superceded by @ref SD_HostInit,SD_CardInit. + + * This function initializes the card on a specific host controller, it is consist of + * host init, card detect, card init function, however user can ignore this high level function, + * instead of use the low level function, such as SD_CardInit, SD_HostInit, SD_CardDetect. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_HostNotReady host is not ready. + * @retval kStatus_SDMMC_GoIdleFailed Go idle failed. + * @retval kStatus_SDMMC_NotSupportYet Card not support. + * @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed. + * @retval kStatus_SDMMC_AllSendCidFailed Send CID failed. + * @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed. + * @retval kStatus_SDMMC_SendCsdFailed Send CSD failed. + * @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed. + * @retval kStatus_SDMMC_SendScrFailed Send SCR failed. + * @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed. + * @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_Init(sd_card_t *card); + +/*! + * @brief Deinitializes the card. + * @deprecated Do not use this function. It has been superceded by @ref SD_HostDeinit,SD_CardDeinit. + * This function deinitializes the specific card and host. + * + * @param card Card descriptor. + */ +void SD_Deinit(sd_card_t *card); + +/*! + * @brief Initializes the card. + * + * This function initializes the card only, make sure the host is ready when call this function, + * otherwise it will return kStatus_SDMMC_HostNotReady. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_HostNotReady host is not ready. + * @retval kStatus_SDMMC_GoIdleFailed Go idle failed. + * @retval kStatus_SDMMC_NotSupportYet Card not support. + * @retval kStatus_SDMMC_SendOperationConditionFailed Send operation condition failed. + * @retval kStatus_SDMMC_AllSendCidFailed Send CID failed. + * @retval kStatus_SDMMC_SendRelativeAddressFailed Send relative address failed. + * @retval kStatus_SDMMC_SendCsdFailed Send CSD failed. + * @retval kStatus_SDMMC_SelectCardFailed Send SELECT_CARD command failed. + * @retval kStatus_SDMMC_SendScrFailed Send SCR failed. + * @retval kStatus_SDMMC_SetBusWidthFailed Set bus width failed. + * @retval kStatus_SDMMC_SwitchHighSpeedFailed Switch high speed failed. + * @retval kStatus_SDMMC_SetCardBlockSizeFailed Set card block size failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_CardInit(sd_card_t *card); + +/*! + * @brief Deinitializes the card. + * + * This function deinitializes the specific card. + * + * @param card Card descriptor. + */ +void SD_CardDeinit(sd_card_t *card); + +/*! + * @brief initialize the host. + * + * This function deinitializes the specific host. + * + * @param card Card descriptor. + */ +status_t SD_HostInit(sd_card_t *card); + +/*! + * @brief Deinitializes the host. + * + * This function deinitializes the host. + * + * @param card Card descriptor. + */ +void SD_HostDeinit(sd_card_t *card); + +/*! + * @brief reset the host. + * + * This function reset the specific host. + * + * @param host host descriptor. + */ +void SD_HostReset(SDMMCHOST_CONFIG *host); + +/*! + * @brief power on card. + * + * The power on operation depend on host or the user define power on function. + * @param base host base address. + * @param pwr user define power control configuration + */ +void SD_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief power off card. + * + * The power off operation depend on host or the user define power on function. + * @param base host base address. + * @param pwr user define power control configuration + */ +void SD_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief sd wait card detect function. + * + * Detect card through GPIO, CD, DATA3. + * + * @param card card descriptor. + * @param card detect configuration + * @param waitCardStatus wait card detect status + */ +status_t SD_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, const sdmmchost_detect_card_t *cd, bool waitCardStatus); + +/*! + * @brief sd card present check function. + * + * @param card card descriptor. + */ +bool SD_IsCardPresent(sd_card_t *card); + +/*! + * @brief Checks whether the card is write-protected. + * + * This function checks if the card is write-protected via the CSD register. + * + * @param card The specific card. + * @retval true Card is read only. + * @retval false Card isn't read only. + */ +bool SD_CheckReadOnly(sd_card_t *card); + +/*! + * @brief Send SELECT_CARD command to set the card to be transfer state or not. + * + * @param card Card descriptor. + * @param isSelected True to set the card into transfer state, false to disselect. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_SelectCard(sd_card_t *card, bool isSelected); + +/*! + * @brief Send ACMD13 to get the card current status. + * + * @param card Card descriptor. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_SendApplicationCommandFailed send application command failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_ReadStatus(sd_card_t *card); + +/*! + * @brief Reads blocks from the specific card. + * + * This function reads blocks from the specific card with default block size defined by the + * SDHC_CARD_DEFAULT_BLOCK_SIZE. + * + * @param card Card descriptor. + * @param buffer The buffer to save the data read from card. + * @param startBlock The start block index. + * @param blockCount The number of blocks to read. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_NotSupportYet Not support now. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_ReadBlocks(sd_card_t *card, uint8_t *buffer, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief Writes blocks of data to the specific card. + * + * This function writes blocks to the specific card with default block size 512 bytes. + * + * @param card Card descriptor. + * @param buffer The buffer holding the data to be written to the card. + * @param startBlock The start block index. + * @param blockCount The number of blocks to write. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_NotSupportYet Not support now. + * @retval kStatus_SDMMC_CardNotSupport Card not support. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_StopTransmissionFailed Stop transmission failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_WriteBlocks(sd_card_t *card, const uint8_t *buffer, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief Erases blocks of the specific card. + * + * This function erases blocks of the specific card with default block size 512 bytes. + * + * @param card Card descriptor. + * @param startBlock The start block index. + * @param blockCount The number of blocks to erase. + * @retval kStatus_InvalidArgument Invalid argument. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_WaitWriteCompleteFailed Send status failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SD_EraseBlocks(sd_card_t *card, uint32_t startBlock, uint32_t blockCount); + +/*! + * @brief select card driver strength + * select card driver strength + * @param card Card descriptor. + * @param driverStrength Driver strength + */ +status_t SD_SetDriverStrength(sd_card_t *card, sd_driver_strength_t driverStrength); + +/*! + * @brief select max current + * select max operation current + * @param card Card descriptor. + * @param maxCurrent Max current + */ +status_t SD_SetMaxCurrent(sd_card_t *card, sd_max_current_t maxCurrent); + +/* @} */ + +#if defined(__cplusplus) +} +#endif +/*! @} */ +#endif /* _FSL_SD_H_*/ diff --git a/target/TARGET_NXP/fsl_sdmmc_common.c b/target/TARGET_NXP/fsl_sdmmc_common.c new file mode 100644 index 0000000..030f5e6 --- /dev/null +++ b/target/TARGET_NXP/fsl_sdmmc_common.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_sdmmc_common.h" +/******************************************************************************* + * Variables + ******************************************************************************/ +SDK_ALIGN(uint32_t g_sdmmc[SDK_SIZEALIGN(SDMMC_GLOBAL_BUFFER_SIZE, SDMMC_DATA_BUFFER_ALIGN_CACHE)], + MAX(SDMMC_DATA_BUFFER_ALIGN_CACHE, SDMMCHOST_DMA_BUFFER_ADDR_ALIGN)); +/******************************************************************************* + * Code + ******************************************************************************/ +status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress, + bool isSelected) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SelectCard; + if (isSelected) + { + command.argument = relativeAddress << 16U; + command.responseType = kCARD_ResponseTypeR1; + } + else + { + command.argument = 0U; + command.responseType = kCARD_ResponseTypeNone; + } + + content.command = &command; + content.data = NULL; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + /* Wait until card to transfer state */ + return kStatus_Success; +} + +status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_ApplicationCommand; + command.argument = (relativeAddress << 16U); + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + if (!(command.response[0U] & SDMMC_MASK(kSDMMC_R1ApplicationCommandFlag))) + { + return kStatus_SDMMC_CardNotSupport; + } + + return kStatus_Success; +} + +status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SetBlockCount; + command.argument = blockCount; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_GoIdleState; + + content.command = &command; + content.data = 0U; + if (kStatus_Success != transfer(base, &content)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_SetBlockLength; + command.argument = blockSize; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content)) || (command.response[0U] & SDMMC_R1_ALL_ERROR_FLAG)) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + + command.index = kSDMMC_GoInactiveState; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeNone; + + content.command = &command; + content.data = 0U; + if ((kStatus_Success != transfer(base, &content))) + { + return kStatus_SDMMC_TransferFailed; + } + + return kStatus_Success; +} + +status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer) +{ + assert(transfer); + + SDMMCHOST_TRANSFER content = {0}; + SDMMCHOST_COMMAND command = {0}; + status_t error = kStatus_Success; + + command.index = kSD_VoltageSwitch; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1; + + content.command = &command; + content.data = NULL; + if (kStatus_Success != transfer(base, &content)) + { + return kStatus_SDMMC_TransferFailed; + } + /* disable card clock */ + SDMMCHOST_ENABLE_CARD_CLOCK(base, false); + + /* check data line and cmd line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) != 0U) + { + return kStatus_SDMMC_SwitchVoltageFail; + } + + /* host switch to 1.8V */ + SDMMCHOST_SWITCH_VOLTAGE180V(base, true); + + SDMMCHOST_Delay(100U); + + /*enable sd clock*/ + SDMMCHOST_ENABLE_CARD_CLOCK(base, true); + /*enable force clock on*/ + SDMMCHOST_FORCE_SDCLOCK_ON(base, true); + /* dealy 1ms,not exactly correct when use while */ + SDMMCHOST_Delay(10U); + /*disable force clock on*/ + SDMMCHOST_FORCE_SDCLOCK_ON(base, false); + + /* check data line and cmd line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY)) == 0U) + { + error = kStatus_SDMMC_SwitchVoltageFail; + /* power reset the card */ + SDMMCHOST_ENABLE_SD_POWER(false); + SDMMCHOST_Delay(10U); + SDMMCHOST_ENABLE_SD_POWER(true); + SDMMCHOST_Delay(10U); + /* re-check the data line status */ + if ((GET_SDMMCHOST_STATUS(base) & + (CARD_DATA1_STATUS_MASK | CARD_DATA2_STATUS_MASK | CARD_DATA3_STATUS_MASK | CARD_DATA0_NOT_BUSY))) + { + error = kStatus_SDMMC_SwitchVoltage18VFail33VSuccess; + SDMMC_LOG("\r\nNote: Current card support 1.8V, but board don't support, so sdmmc switch back to 3.3V."); + } + else + { + SDMMC_LOG( + "\r\nError: Current card support 1.8V, but board don't support, sdmmc tried to switch back\ + to 3.3V, but failed, please check board setting."); + } + } + + return error; +} + +status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t tuningCmd, + uint32_t blockSize) +{ + SDMMCHOST_TRANSFER content = {0U}; + SDMMCHOST_COMMAND command = {0U}; + SDMMCHOST_DATA data = {0U}; + uint32_t buffer[32U] = {0U}; + bool tuningError = true; + + command.index = tuningCmd; + command.argument = 0U; + command.responseType = kCARD_ResponseTypeR1; + + data.blockSize = blockSize; + data.blockCount = 1U; + data.rxData = buffer; + /* add this macro for adpter to different driver */ + SDMMCHOST_ENABLE_TUNING_FLAG(data); + + content.command = &command; + content.data = &data; + + /* enable the standard tuning */ + SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true); + + while (true) + { + /* send tuning block */ + if ((kStatus_Success != transfer(base, &content))) + { + return kStatus_SDMMC_TransferFailed; + } + SDMMCHOST_Delay(1U); + + /*wait excute tuning bit clear*/ + if ((SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) != 0U)) + { + continue; + } + + /* if tuning error , re-tuning again */ + if ((SDMMCHOST_CHECK_TUNING_ERROR(base) != 0U) && tuningError) + { + tuningError = false; + /* enable the standard tuning */ + SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, true); + SDMMCHOST_ADJUST_TUNING_DELAY(base, SDMMCHOST_STANDARD_TUNING_START); + } + else + { + break; + } + } + + /* check tuning result*/ + if (SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) == 0U) + { + return kStatus_SDMMC_TuningFail; + } + +#if !SDMMC_ENABLE_SOFTWARE_TUNING + SDMMCHOST_AUTO_TUNING_ENABLE(base, true); +#endif + + return kStatus_Success; +} diff --git a/target/TARGET_NXP/fsl_sdmmc_common.h b/target/TARGET_NXP/fsl_sdmmc_common.h new file mode 100644 index 0000000..78ec1d0 --- /dev/null +++ b/target/TARGET_NXP/fsl_sdmmc_common.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_COMMON_H_ +#define _FSL_SDMMC_COMMON_H_ + +#include "fsl_common.h" +#include "fsl_sdmmc_host.h" +#include "fsl_sdmmc_spec.h" +#include "stdlib.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief Middleware version. */ +#define FSL_SDMMC_DRIVER_VERSION (MAKE_VERSION(2U, 2U, 6U)) /*2.2.6*/ + +/*! @brief Reverse byte sequence in uint32_t */ +#define SWAP_WORD_BYTE_SEQUENCE(x) (__REV(x)) +/*! @brief Reverse byte sequence for each half word in uint32_t */ +#define SWAP_HALF_WROD_BYTE_SEQUENCE(x) (__REV16(x)) +/*! @brief Maximum loop count to check the card operation voltage range */ +#define FSL_SDMMC_MAX_VOLTAGE_RETRIES (1000U) +/*! @brief Maximum loop count to send the cmd */ +#define FSL_SDMMC_MAX_CMD_RETRIES (10U) +/*! @brief Default block size */ +#define FSL_SDMMC_DEFAULT_BLOCK_SIZE (512U) +#ifndef SDMMC_GLOBAL_BUFFER_SIZE +/*! @brief SDMMC global data buffer size, word unit*/ +#define SDMMC_GLOBAL_BUFFER_SIZE (128U) +#endif +/*! @brief SDMMC enable software tuning */ +#define SDMMC_ENABLE_SOFTWARE_TUNING (0U) +/* Common definition for cache line size align */ +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL +#if defined(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE) +#if defined(FSL_FEATURE_L2DCACHE_LINESIZE_BYTE) +#define SDMMC_DATA_BUFFER_ALIGN_CACHE MAX(FSL_FEATURE_L1DCACHE_LINESIZE_BYTE, FSL_FEATURE_L2DCACHE_LINESIZE_BYTE) +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE FSL_FEATURE_L1DCACHE_LINESIZE_BYTE +#endif +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1 +#endif +#else +#define SDMMC_DATA_BUFFER_ALIGN_CACHE 1 +#endif + +/*! @brief SD/MMC error log. */ +#if defined SDMMC_ENABLE_LOG_PRINT +#include "fsl_debug_console.h" +#define SDMMC_LOG(...) PRINTF(__VA_ARGS__) +#else +#define SDMMC_LOG(format, ...) +#endif + +/*! @brief SD/MMC card API's running status. */ +enum _sdmmc_status +{ + kStatus_SDMMC_NotSupportYet = MAKE_STATUS(kStatusGroup_SDMMC, 0U), /*!< Haven't supported */ + kStatus_SDMMC_TransferFailed = MAKE_STATUS(kStatusGroup_SDMMC, 1U), /*!< Send command failed */ + kStatus_SDMMC_SetCardBlockSizeFailed = MAKE_STATUS(kStatusGroup_SDMMC, 2U), /*!< Set block size failed */ + kStatus_SDMMC_HostNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 3U), /*!< Host doesn't support */ + kStatus_SDMMC_CardNotSupport = MAKE_STATUS(kStatusGroup_SDMMC, 4U), /*!< Card doesn't support */ + kStatus_SDMMC_AllSendCidFailed = MAKE_STATUS(kStatusGroup_SDMMC, 5U), /*!< Send CID failed */ + kStatus_SDMMC_SendRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 6U), /*!< Send relative address failed */ + kStatus_SDMMC_SendCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 7U), /*!< Send CSD failed */ + kStatus_SDMMC_SelectCardFailed = MAKE_STATUS(kStatusGroup_SDMMC, 8U), /*!< Select card failed */ + kStatus_SDMMC_SendScrFailed = MAKE_STATUS(kStatusGroup_SDMMC, 9U), /*!< Send SCR failed */ + kStatus_SDMMC_SetDataBusWidthFailed = MAKE_STATUS(kStatusGroup_SDMMC, 10U), /*!< Set bus width failed */ + kStatus_SDMMC_GoIdleFailed = MAKE_STATUS(kStatusGroup_SDMMC, 11U), /*!< Go idle failed */ + kStatus_SDMMC_HandShakeOperationConditionFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 12U), /*!< Send Operation Condition failed */ + kStatus_SDMMC_SendApplicationCommandFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 13U), /*!< Send application command failed */ + kStatus_SDMMC_SwitchFailed = MAKE_STATUS(kStatusGroup_SDMMC, 14U), /*!< Switch command failed */ + kStatus_SDMMC_StopTransmissionFailed = MAKE_STATUS(kStatusGroup_SDMMC, 15U), /*!< Stop transmission failed */ + kStatus_SDMMC_WaitWriteCompleteFailed = MAKE_STATUS(kStatusGroup_SDMMC, 16U), /*!< Wait write complete failed */ + kStatus_SDMMC_SetBlockCountFailed = MAKE_STATUS(kStatusGroup_SDMMC, 17U), /*!< Set block count failed */ + kStatus_SDMMC_SetRelativeAddressFailed = MAKE_STATUS(kStatusGroup_SDMMC, 18U), /*!< Set relative address failed */ + kStatus_SDMMC_SwitchBusTimingFailed = MAKE_STATUS(kStatusGroup_SDMMC, 19U), /*!< Switch high speed failed */ + kStatus_SDMMC_SendExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 20U), /*!< Send EXT_CSD failed */ + kStatus_SDMMC_ConfigureBootFailed = MAKE_STATUS(kStatusGroup_SDMMC, 21U), /*!< Configure boot failed */ + kStatus_SDMMC_ConfigureExtendedCsdFailed = MAKE_STATUS(kStatusGroup_SDMMC, 22U), /*!< Configure EXT_CSD failed */ + kStatus_SDMMC_EnableHighCapacityEraseFailed = + MAKE_STATUS(kStatusGroup_SDMMC, 23U), /*!< Enable high capacity erase failed */ + kStatus_SDMMC_SendTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 24U), /*!< Send test pattern failed */ + kStatus_SDMMC_ReceiveTestPatternFailed = MAKE_STATUS(kStatusGroup_SDMMC, 25U), /*!< Receive test pattern failed */ + kStatus_SDMMC_SDIO_ResponseError = MAKE_STATUS(kStatusGroup_SDMMC, 26U), /*!< sdio response error */ + kStatus_SDMMC_SDIO_InvalidArgument = + MAKE_STATUS(kStatusGroup_SDMMC, 27U), /*!< sdio invalid argument response error */ + kStatus_SDMMC_SDIO_SendOperationConditionFail = + MAKE_STATUS(kStatusGroup_SDMMC, 28U), /*!< sdio send operation condition fail */ + kStatus_SDMMC_InvalidVoltage = MAKE_STATUS(kStatusGroup_SDMMC, 29U), /*!< invaild voltage */ + kStatus_SDMMC_SDIO_SwitchHighSpeedFail = MAKE_STATUS(kStatusGroup_SDMMC, 30U), /*!< switch to high speed fail */ + kStatus_SDMMC_SDIO_ReadCISFail = MAKE_STATUS(kStatusGroup_SDMMC, 31U), /*!< read CIS fail */ + kStatus_SDMMC_SDIO_InvalidCard = MAKE_STATUS(kStatusGroup_SDMMC, 32U), /*!< invaild SDIO card */ + kStatus_SDMMC_TuningFail = MAKE_STATUS(kStatusGroup_SDMMC, 33U), /*!< tuning fail */ + + kStatus_SDMMC_SwitchVoltageFail = MAKE_STATUS(kStatusGroup_SDMMC, 34U), /*!< switch voltage fail*/ + kStatus_SDMMC_SwitchVoltage18VFail33VSuccess = MAKE_STATUS(kStatusGroup_SDMMC, 35U), /*!< switch voltage fail*/ + + kStatus_SDMMC_ReTuningRequest = MAKE_STATUS(kStatusGroup_SDMMC, 36U), /*!< retuning request */ + kStatus_SDMMC_SetDriverStrengthFail = MAKE_STATUS(kStatusGroup_SDMMC, 37U), /*!< set driver strength fail */ + kStatus_SDMMC_SetPowerClassFail = MAKE_STATUS(kStatusGroup_SDMMC, 38U), /*!< set power class fail */ + kStatus_SDMMC_HostNotReady = MAKE_STATUS(kStatusGroup_SDMMC, 39U), /*!< host controller not ready */ + kStatus_SDMMC_CardDetectFailed = MAKE_STATUS(kStatusGroup_SDMMC, 40U), /*!< card detect failed */ + kStatus_SDMMC_AuSizeNotSetProperly = MAKE_STATUS(kStatusGroup_SDMMC, 41U), /*!< AU size not set properly */ + +}; + +/*! @brief card operation voltage */ +typedef enum _sdmmc_operation_voltage +{ + kCARD_OperationVoltageNone = 0U, /*!< indicate current voltage setting is not setting bu suser*/ + kCARD_OperationVoltage330V = 1U, /*!< card operation voltage around 3.3v */ + kCARD_OperationVoltage300V = 2U, /*!< card operation voltage around 3.0v */ + kCARD_OperationVoltage180V = 3U, /*!< card operation voltage around 31.8v */ +} sdmmc_operation_voltage_t; + +/************************************************************************************************* + * API + ************************************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @brief Selects the card to put it into transfer state. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param relativeAddress Relative address. + * @param isSelected True to put card into transfer state. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SelectCard(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress, + bool isSelected); + +/*! + * @brief Sends an application command. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param relativeAddress Card relative address. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SendApplicationCommand(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t relativeAddress); + +/*! + * @brief Sets the block count. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param blockCount Block count. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetBlockCount(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockCount); + +/*! + * @brief Sets the card to be idle state. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_GoIdle(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief Sets data block size. + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @param blockSize Block size. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetBlockSize(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer, uint32_t blockSize); + +/*! + * @brief Sets card to inactive status + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + * @retval kStatus_SDMMC_TransferFailed Transfer failed. + * @retval kStatus_Success Operate successfully. + */ +status_t SDMMC_SetCardInactive(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief provide a simple delay function for sdmmc + * + * @param num Delay num*10000. + */ +void SDMMC_Delay(uint32_t num); + +/*! + * @brief provide a voltage switch function for SD/SDIO card + * + * @param base SDMMCHOST peripheral base address. + * @param transfer SDMMCHOST transfer function. + */ +status_t SDMMC_SwitchVoltage(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER_FUNCTION transfer); + +/*! + * @brief excute tuning + * + * @param base SDMMCHOST peripheral base address. + * @param transfer Host transfer function + * @param tuningCmd Tuning cmd + * @param blockSize Tuning block size + */ +status_t SDMMC_ExecuteTuning(SDMMCHOST_TYPE *base, + SDMMCHOST_TRANSFER_FUNCTION transfer, + uint32_t tuningCmd, + uint32_t blockSize); + +#if defined(__cplusplus) +} +#endif + +#endif /* _FSL_SDMMC_COMMON_H_ */ diff --git a/target/TARGET_NXP/fsl_sdmmc_host.c b/target/TARGET_NXP/fsl_sdmmc_host.c new file mode 100644 index 0000000..7d3ba77 --- /dev/null +++ b/target/TARGET_NXP/fsl_sdmmc_host.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "fsl_sdmmc_host.h" +#include "mbed_wait_api.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ +/*! + * @brief SDMMCHOST detect card insert status by host controller. + * @param base host base address. + * @param data3 flag indicate use data3 to detect card or not. + */ +static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, bool data3); + +/*! + * @brief SDMMCHOST detect card status by GPIO. + */ +static bool SDMMCHOST_DetectCardByGpio(void); + +/*! + * @brief SDMMCHOST transfer function. + * @param base host base address. + * @param content transfer configurations. + */ +static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content); + +/*! + * @brief card detect deinit function. + */ +static void SDMMCHOST_CardDetectDeinit(void); + +/*! + * @brief card detect deinit function. + * @param host base address. + * @param host detect card configuration. + */ +static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd); + +/******************************************************************************* + * Variables + ******************************************************************************/ +/*! @brief Card detect flag. */ +static volatile bool s_sdInsertedFlag = false; +/*! @brief DMA descriptor table. */ +static uint32_t s_sdifDmaTable[SDIF_DMA_TABLE_WORDS]; +/******************************************************************************* + * Code + ******************************************************************************/ +static bool SDMMCHOST_DetectCardByGpio(void) +{ + if (SDMMCHOST_CARD_DETECT_STATUS() != SDMMCHOST_CARD_INSERT_CD_LEVEL) + { + s_sdInsertedFlag = false; + } + else + { + s_sdInsertedFlag = true; + } + + return s_sdInsertedFlag; +} + +static void SDMMCHOST_DetectCardInsertByHost(SDMMCHOST_TYPE *base, bool data3) +{ + if (SDMMCHOST_CARD_DETECT_INSERT_STATUS(base, data3)) + { + s_sdInsertedFlag = true; + } +} + +/* User defined transfer function. */ +static status_t SDMMCHOST_TransferFunction(SDMMCHOST_TYPE *base, SDMMCHOST_TRANSFER *content) +{ + status_t error = kStatus_Success; + + sdif_dma_config_t dmaConfig; + + memset(s_sdifDmaTable, 0, sizeof(s_sdifDmaTable)); + memset(&dmaConfig, 0, sizeof(dmaConfig)); + + if (content->data != NULL) + { + dmaConfig.enableFixBurstLen = true; + dmaConfig.mode = kSDIF_ChainDMAMode; + dmaConfig.dmaDesBufferStartAddr = s_sdifDmaTable; + dmaConfig.dmaDesBufferLen = SDIF_DMA_TABLE_WORDS; + } + + if (kStatus_Success != SDIF_TransferBlocking(base, &dmaConfig, content)) + { + error = kStatus_Fail; + } + + return error; +} + +static status_t SDMMCHOST_CardDetectInit(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd) +{ + sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD; + + if (cd != NULL) + { + cdType = cd->cdType; + } + + if (cdType == kSDMMCHOST_DetectCardByGpioCD) + { + SDMMCHOST_CARD_DETECT_INIT(); + SDMMCHOST_DetectCardByGpio(); + } + else + { + /* enable card detect status */ + SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base); + } + + return kStatus_Success; +} + +static void SDMMCHOST_CardDetectDeinit(void) +{ + s_sdInsertedFlag = false; +} + +void SDMMCHOST_Delay(uint32_t milliseconds) +{ + wait_ms(milliseconds); +} + +status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *base, const sdmmchost_detect_card_t *cd, bool waitCardStatus) +{ + sdmmchost_detect_card_type_t cdType = kSDMMCHOST_DetectCardByGpioCD; + + if (cd != NULL) + { + cdType = cd->cdType; + } + + if (waitCardStatus != s_sdInsertedFlag) + { + /* Wait card inserted. */ + do + { + if (cdType == kSDMMCHOST_DetectCardByGpioCD) + { + SDMMCHOST_DetectCardByGpio(); + } + else + { + SDMMCHOST_DetectCardInsertByHost(base, cdType == kSDMMCHOST_DetectCardByHostDATA3); + } + + } while (waitCardStatus != s_sdInsertedFlag); + } + + return kStatus_Success; +} + +bool SDMMCHOST_IsCardPresent(void) +{ + return s_sdInsertedFlag; +} + +void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + if (pwr != NULL) + { + pwr->powerOff(); + SDMMCHOST_Delay(pwr->powerOffDelay_ms); + } + else + { + /* disable the card power */ + SDIF_EnableCardPower(base, false); + /* Delay several milliseconds to make card stable. */ + SDMMCHOST_Delay(500U); + } +} + +void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr) +{ + /* use user define the power on function */ + if (pwr != NULL) + { + pwr->powerOn(); + SDMMCHOST_Delay(pwr->powerOnDelay_ms); + } + else + { + /* Enable the card power */ + SDIF_EnableCardPower(base, true); + /* Delay several milliseconds to make card stable. */ + SDMMCHOST_Delay(500U); + } +} + +status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData) +{ + sdif_host_t *sdifHost = (sdif_host_t *)host; + + /* init event timer. */ + //SDMMCEVENT_InitTimer(); + + /* Initialize SDIF. */ + sdifHost->config.endianMode = kSDMMCHOST_EndianModeLittle; + sdifHost->config.responseTimeout = 0xFFU; + sdifHost->config.cardDetDebounce_Clock = 0xFFFFFFU; + sdifHost->config.dataTimeout = 0xFFFFFFU; + SDIF_Init(sdifHost->base, &(sdifHost->config)); + + /* Define transfer function. */ + sdifHost->transfer = SDMMCHOST_TransferFunction; + + SDMMCHOST_CardDetectInit(sdifHost->base, (sdmmchost_detect_card_t *)userData); + + return kStatus_Success; +} + +void SDMMCHOST_Reset(SDMMCHOST_TYPE *base) +{ + /* reserved for future */ +} + +void SDMMCHOST_Deinit(void *host) +{ + sdif_host_t *sdifHost = (sdif_host_t *)host; + SDIF_Deinit(sdifHost->base); + SDMMCHOST_CardDetectDeinit(); +} + +void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base) +{ + /* reserved for future */ +} diff --git a/target/TARGET_NXP/fsl_sdmmc_host.h b/target/TARGET_NXP/fsl_sdmmc_host.h new file mode 100644 index 0000000..f6b47a0 --- /dev/null +++ b/target/TARGET_NXP/fsl_sdmmc_host.h @@ -0,0 +1,736 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_HOST_H +#define _FSL_SDMMC_HOST_H + +#include "fsl_common.h" +#include "board.h" +#if defined(FSL_FEATURE_SOC_SDHC_COUNT) && FSL_FEATURE_SOC_SDHC_COUNT > 0U +#include "fsl_sdhc.h" +#elif defined(FSL_FEATURE_SOC_SDIF_COUNT) && FSL_FEATURE_SOC_SDIF_COUNT > 0U +#include "fsl_sdif.h" +#elif defined(FSL_FEATURE_SOC_USDHC_COUNT) && FSL_FEATURE_SOC_USDHC_COUNT > 0U +#include "fsl_usdhc.h" +#endif + +/*! + * @addtogroup CARD + * @{ + */ + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/* Common definition for support and not support macro */ +#define SDMMCHOST_NOT_SUPPORT 0U /*!< use this define to indicate the host not support feature*/ +#define SDMMCHOST_SUPPORT 1U /*!< use this define to indicate the host support feature*/ + +/* Common definition for board support SDR104/HS200/HS400 frequency */ +/* SDR104 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_SDR104_FREQ +#define SDMMCHOST_SUPPORT_SDR104_FREQ BOARD_SD_HOST_SUPPORT_SDR104_FREQ +#else +#define SDMMCHOST_SUPPORT_SDR104_FREQ SD_CLOCK_208MHZ +#endif +/* HS200 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_HS200_FREQ +#define SDMMCHOST_SUPPORT_HS200_FREQ BOARD_SD_HOST_SUPPORT_HS200_FREQ +#else +#define SDMMCHOST_SUPPORT_HS200_FREQ MMC_CLOCK_HS200 +#endif +/* HS400 mode freq */ +#if defined BOARD_SD_HOST_SUPPORT_HS400_FREQ +#define SDMMCHOST_SUPPORT_HS400_FREQ BOARD_SD_HOST_SUPPORT_HS400_FREQ +#else +#define SDMMCHOST_SUPPORT_HS400_FREQ MMC_CLOCK_HS400 +#endif + +/* Common definition for SDMMCHOST transfer complete timeout */ +#define SDMMCHOST_TRANSFER_COMPLETE_TIMEOUT (500U) +/* Common definition for card detect timeout */ +#define SDMMCHOST_CARD_DETECT_TIMEOUT (~0U) + +/* Common definition for IRQ */ +#if defined(__CORTEX_M) +#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (NVIC_SetPriority(id, priority)) +#else +#define SDMMCHOST_SET_IRQ_PRIORITY(id, priority) (GIC_SetPriority(id, priority)) +#endif + +#define SDMMCHOST_ENABLE_IRQ(id) (EnableIRQ(id)) + +/*********************************************************SDHC**********************************************************/ +#if (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_SDHC_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ +#define MMC_HOST_IRQ BOARD_SDHC_IRQ +#define SD_HOST_BASEADDR BOARD_SDHC_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SDHC_CLK_FREQ +#define SD_HOST_IRQ BOARD_SDHC_IRQ + +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (0U) +#define CARD_BUS_FREQ_100MHZ1 (0U) +#define CARD_BUS_FREQ_200MHZ (0U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (0U) +#define CARD_BUS_STRENGTH_2 (0U) +#define CARD_BUS_STRENGTH_3 (0U) +#define CARD_BUS_STRENGTH_4 (0U) +#define CARD_BUS_STRENGTH_5 (0U) +#define CARD_BUS_STRENGTH_6 (0U) +#define CARD_BUS_STRENGTH_7 (0U) + +#define SDMMCHOST_TYPE SDHC_Type +#define SDMMCHOST_CONFIG sdhc_host_t +#define SDMMCHOST_TRANSFER sdhc_transfer_t +#define SDMMCHOST_COMMAND sdhc_command_t +#define SDMMCHOST_DATA sdhc_data_t +#define SDMMCHOST_BUS_WIDTH_TYPE sdhc_data_bus_width_t +#define SDMMCHOST_CAPABILITY sdhc_capability_t +#define SDMMCHOST_BOOT_CONFIG sdhc_boot_config_t + +#define CARD_DATA0_STATUS_MASK (1U << kSDHC_Data0LineLevelFlag) +#define CARD_DATA0_NOT_BUSY (1U << kSDHC_Data0LineLevelFlag) +#define CARD_DATA1_STATUS_MASK (1U << kSDHC_Data1LineLevelFlag) +#define CARD_DATA2_STATUS_MASK (1U << kSDHC_Data2LineLevelFlag) +#define CARD_DATA3_STATUS_MASK (1U << kSDHC_Data3LineLevelFlag) + +#define kSDMMCHOST_DATABUSWIDTH1BIT kSDHC_DataBusWidth1Bit /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kSDHC_DataBusWidth4Bit /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kSDHC_DataBusWidth8Bit /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST (1U) +#define SDMMCHOST_TUNING_ERROR (2U) + +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION sdhc_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDHC_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (SDHC_GetPresentStatusFlags(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) (SDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDHC_SetDataBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDHC_SetCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDHC_EnableSdClock(base, enable)) +#define SDMMCHOST_RESET_TUNING(base, timeout) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDHC_TransferDataFailed +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDHC_SendCommandFailed +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() +#define SDMMCHOST_ENABLE_SD_POWER(enable) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDHC_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDHC_CD_PORT_IRQ +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (SDHC_EnableInterruptStatus(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (SDHC_GetInterruptStatusFlags(base) & kSDHC_CardInsertionFlag) +#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (SDHC_GetInterruptStatusFlags(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_DISABLE(base) \ + (SDHC_DisableInterruptSignal(base, kSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (SDHC_EnableInterruptSignal(base, kSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (SDHC_CardDetectByData3(base, flag)) +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (SDHC_SetMmcBootConfig(base, config)) +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_SDHC_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDHC_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) + +/*! @brief SDHC host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportAdma = kSDHC_SupportAdmaFlag, + kSDMMCHOST_SupportHighSpeed = kSDHC_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kSDHC_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kSDHC_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kSDHC_SupportV330Flag, + kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kSDHC_Support4BitFlag, + kSDMMCHOST_Support8BitBusWidth = kSDHC_Support8BitFlag, + kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, +}; + +/* Endian mode. */ +#define SDHC_ENDIAN_MODE kSDHC_EndianModeLittle + +/* DMA mode */ +#define SDHC_DMA_MODE kSDHC_DmaModeAdma2 +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (SDHC_ADMA2_ADDRESS_ALIGN) + +/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */ +#define SDHC_READ_WATERMARK_LEVEL (0x80U) +#define SDHC_WRITE_WATERMARK_LEVEL (0x80U) + +/* ADMA table length united as word. + * + * SD card driver can't support ADMA1 transfer mode currently. + * One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time. + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + */ +#define SDHC_ADMA_TABLE_WORDS (8U) + +/*********************************************************SDIF**********************************************************/ +#elif(defined(FSL_FEATURE_SOC_SDIF_COUNT) && (FSL_FEATURE_SOC_SDIF_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_SDIF_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ +#define MMC_HOST_IRQ BOARD_SDIF_IRQ +#define SD_HOST_BASEADDR BOARD_SDIF_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SDIF_CLK_FREQ +#define SD_HOST_IRQ BOARD_SDIF_IRQ + +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (0U) +#define CARD_BUS_FREQ_100MHZ1 (0U) +#define CARD_BUS_FREQ_200MHZ (0U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (0U) +#define CARD_BUS_STRENGTH_2 (0U) +#define CARD_BUS_STRENGTH_3 (0U) +#define CARD_BUS_STRENGTH_4 (0U) +#define CARD_BUS_STRENGTH_5 (0U) +#define CARD_BUS_STRENGTH_6 (0U) +#define CARD_BUS_STRENGTH_7 (0U) + +#define SDMMCHOST_TYPE SDIF_Type +#define SDMMCHOST_CONFIG sdif_host_t +#define SDMMCHOST_TRANSFER sdif_transfer_t +#define SDMMCHOST_COMMAND sdif_command_t +#define SDMMCHOST_DATA sdif_data_t +#define SDMMCHOST_BUS_WIDTH_TYPE sdif_bus_width_t +#define SDMMCHOST_CAPABILITY sdif_capability_t +#define SDMMCHOST_BOOT_CONFIG void + +#define CARD_DATA0_STATUS_MASK SDIF_STATUS_DATA_BUSY_MASK +#define CARD_DATA0_NOT_BUSY 0U + +#define CARD_DATA1_STATUS_MASK (0U) +#define CARD_DATA2_STATUS_MASK (0U) +#define CARD_DATA3_STATUS_MASK (0U) + +#define kSDMMCHOST_DATABUSWIDTH1BIT kSDIF_Bus1BitWidth /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kSDIF_Bus4BitWidth /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kSDIF_Bus8BitWidth /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (0U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (1U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (4U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST (1U) +#define SDMMCHOST_TUNING_ERROR (2U) +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION sdif_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (SDIF_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (SDIF_GetControllerStatus(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \ + (SDIF_SetCardClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (SDIF_SetCardBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (SDIF_SendCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_IO_STRENGTH(speed, strength) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ADJUST_MANUAL_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_MANUAL_TUNING_ENABLE(base, flag) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) (SDIF_EnableCardClock(base, enable)) +#define SDMMCHOST_RESET_TUNING(base, timeout) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) + +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() +#define SDMMCHOST_ENABLE_SD_POWER(enable) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (0U) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (0U) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) +#define SDMMCHOST_CARD_DETECT_STATUS() BOARD_SDIF_CD_STATUS() +#define SDMMCHOST_CARD_DETECT_INIT() BOARD_SDIF_CD_GPIO_INIT() +#define SDMMCHOST_CARD_DETECT_INTERRUPT_STATUS() BOARD_SDIF_CD_INTERRUPT_STATUS() +#define SDMMCHOST_CARD_DETECT_INTERRUPT_CLEAR(flag) BOARD_SDIF_CD_CLEAR_INTERRUPT(flag) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_SDIF_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_IRQ BOARD_SDIF_CD_PORT_IRQ +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_SDIF_DataTransferFail +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_SDIF_SendCmdFail +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_SDIF_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_SDIF_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (SDIF_EnableInterrupt(base, kSDIF_CardDetect)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base, data3) (SDIF_DetectCardInsert(base, data3)) + +/*! @brief SDIF host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportHighSpeed = kSDIF_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kSDIF_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kSDIF_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kSDIF_SupportV330Flag, + kSDMMCHOST_SupportV300 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kSDIF_Support4BitFlag, + kSDMMCHOST_Support8BitBusWidth = + SDMMCHOST_NOT_SUPPORT, /* mask the 8 bit here,user can change depend on your board */ + kSDMMCHOST_SupportDDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR104 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportSDR50 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS200 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, + +}; + +/*! @brief DMA table length united as word + * One dma table item occupy four words which can transfer maximum 2*8188 bytes in dual DMA mode + * and 8188 bytes in chain mode + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + * user need check the DMA descriptor table lenght if bigger enough. + */ +#define SDIF_DMA_TABLE_WORDS (0x40U) +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (4U) + +/*********************************************************USDHC**********************************************************/ +#elif(defined(FSL_FEATURE_SOC_USDHC_COUNT) && (FSL_FEATURE_SOC_USDHC_COUNT > 0U)) + +/*define host baseaddr ,clk freq, IRQ number*/ +#define MMC_HOST_BASEADDR BOARD_MMC_HOST_BASEADDR +#define MMC_HOST_CLK_FREQ BOARD_MMC_HOST_CLK_FREQ +#define MMC_HOST_IRQ BOARD_MMC_HOST_IRQ +#define SD_HOST_BASEADDR BOARD_SD_HOST_BASEADDR +#define SD_HOST_CLK_FREQ BOARD_SD_HOST_CLK_FREQ +#define SD_HOST_IRQ BOARD_SD_HOST_IRQ + +#define SDMMCHOST_TYPE USDHC_Type +#define SDMMCHOST_CONFIG usdhc_host_t +#define SDMMCHOST_TRANSFER usdhc_transfer_t +#define SDMMCHOST_COMMAND usdhc_command_t +#define SDMMCHOST_DATA usdhc_data_t +#define SDMMCHOST_BOOT_CONFIG usdhc_boot_config_t +#define CARD_DATA0_STATUS_MASK (1U << kUSDHC_Data0LineLevelFlag) +#define CARD_DATA1_STATUS_MASK (1U << kUSDHC_Data1LineLevelFlag) +#define CARD_DATA2_STATUS_MASK (1U << kUSDHC_Data2LineLevelFlag) +#define CARD_DATA3_STATUS_MASK (1U << kUSDHC_Data3LineLevelFlag) +#define CARD_DATA0_NOT_BUSY (1U << kUSDHC_Data0LineLevelFlag) + +#define SDMMCHOST_BUS_WIDTH_TYPE usdhc_data_bus_width_t +#define SDMMCHOST_CAPABILITY usdhc_capability_t + +#define kSDMMCHOST_DATABUSWIDTH1BIT kUSDHC_DataBusWidth1Bit /*!< 1-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH4BIT kUSDHC_DataBusWidth4Bit /*!< 4-bit mode */ +#define kSDMMCHOST_DATABUSWIDTH8BIT kUSDHC_DataBusWidth8Bit /*!< 8-bit mode */ + +#define SDMMCHOST_STANDARD_TUNING_START (10U) /*!< standard tuning start point */ +#define SDMMCHOST_TUINIG_STEP (2U) /*!< standard tuning step */ +#define SDMMCHOST_RETUNING_TIMER_COUNT (0U) /*!< Re-tuning timer */ +#define SDMMCHOST_TUNING_DELAY_MAX (0x7FU) +#define SDMMCHOST_RETUNING_REQUEST kStatus_USDHC_ReTuningRequest +#define SDMMCHOST_TUNING_ERROR kStatus_USDHC_TuningError +#define SDMMCHOST_TRANSFER_DATA_ERROR kStatus_USDHC_TransferDataFailed +#define SDMMCHOST_TRANSFER_CMD_ERROR kStatus_USDHC_SendCommandFailed +/* define for card bus speed/strength cnofig */ +#define CARD_BUS_FREQ_50MHZ (0U) +#define CARD_BUS_FREQ_100MHZ0 (1U) +#define CARD_BUS_FREQ_100MHZ1 (2U) +#define CARD_BUS_FREQ_200MHZ (3U) + +#define CARD_BUS_STRENGTH_0 (0U) +#define CARD_BUS_STRENGTH_1 (1U) +#define CARD_BUS_STRENGTH_2 (2U) +#define CARD_BUS_STRENGTH_3 (3U) +#define CARD_BUS_STRENGTH_4 (4U) +#define CARD_BUS_STRENGTH_5 (5U) +#define CARD_BUS_STRENGTH_6 (6U) +#define CARD_BUS_STRENGTH_7 (7U) + +#define SDMMCHOST_STROBE_DLL_DELAY_TARGET (7U) +#define SDMMCHOST_STROBE_DLL_DELAY_UPDATE_INTERVAL (4U) + +/* function pointer define */ +#define SDMMCHOST_TRANSFER_FUNCTION usdhc_transfer_function_t +#define GET_SDMMCHOST_CAPABILITY(base, capability) (USDHC_GetCapability(base, capability)) +#define GET_SDMMCHOST_STATUS(base) (USDHC_GetPresentStatusFlags(base)) +#define SDMMCHOST_SET_CARD_CLOCK(base, sourceClock_HZ, busClock_HZ) \ + (USDHC_SetSdClock(base, sourceClock_HZ, busClock_HZ)) +#define SDMMCHOST_ENABLE_CARD_CLOCK(base, enable) +#define SDMMCHOST_FORCE_SDCLOCK_ON(base, enable) (USDHC_ForceClockOn(base, enable)) +#define SDMMCHOST_SET_CARD_BUS_WIDTH(base, busWidth) (USDHC_SetDataBusWidth(base, busWidth)) +#define SDMMCHOST_SEND_CARD_ACTIVE(base, timeout) (USDHC_SetCardActive(base, timeout)) +#define SDMMCHOST_SWITCH_VOLTAGE180V(base, enable18v) (UDSHC_SelectVoltage(base, enable18v)) +#define SDMMCHOST_SWITCH_VOLTAGE120V(base, enable12v) +#define SDMMCHOST_CONFIG_SD_IO(speed, strength) BOARD_SD_Pin_Config(speed, strength) +#define SDMMCHOST_CONFIG_MMC_IO(speed, strength) BOARD_MMC_Pin_Config(speed, strength) +#define SDMMCHOST_SWITCH_VCC_TO_180V() +#define SDMMCHOST_SWITCH_VCC_TO_330V() + +#if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (!FSL_FEATURE_USDHC_HAS_SDR50_MODE) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (0U) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (1U) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (0U) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) +#else +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_ENABLE(base, flag) \ + (USDHC_EnableStandardTuning(base, SDMMCHOST_STANDARD_TUNING_START, SDMMCHOST_TUINIG_STEP, flag)) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_STATUS(base) (USDHC_GetExecuteStdTuningStatus(base)) +#define SDMMCHOST_EXECUTE_STANDARD_TUNING_RESULT(base) (USDHC_CheckStdTuningResult(base)) +#define SDMMCHOST_AUTO_STANDARD_RETUNING_TIMER(base) (USDHC_SetRetuningTimer(base, SDMMCHOST_RETUNING_TIMER_COUNT)) +#define SDMMCHOST_EXECUTE_MANUAL_TUNING_ENABLE(base, flag) (USDHC_EnableManualTuning(base, flag)) +#define SDMMCHOST_ADJUST_TUNING_DELAY(base, delay) (USDHC_AdjustDelayForManualTuning(base, delay)) +#define SDMMCHOST_AUTO_TUNING_ENABLE(base, flag) (USDHC_EnableAutoTuning(base, flag)) +#define SDMMCHOST_CHECK_TUNING_ERROR(base) (USDHC_CheckTuningError(base)) +#endif + +#define SDMMCHOST_AUTO_TUNING_CONFIG(base) (USDHC_EnableAutoTuningForCmdAndData(base)) +#define SDMMCHOST_RESET_TUNING(base, timeout) \ + { \ + (USDHC_Reset(base, kUSDHC_ResetTuning | kUSDHC_ResetData | kUSDHC_ResetCommand, timeout)); \ + } + +#define SDMMCHOST_ENABLE_DDR_MODE(base, flag, nibblePos) (USDHC_EnableDDRMode(base, flag, nibblePos)) + +#if FSL_FEATURE_USDHC_HAS_HS400_MODE +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) (USDHC_EnableHS400Mode(base, flag)) +#define SDMMCHOST_RESET_STROBE_DLL(base) (USDHC_ResetStrobeDLL(base)) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) (USDHC_EnableStrobeDLL(base, flag)) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) (USDHC_ConfigStrobeDLL(base, delay, updateInterval)) +#define SDMMCHOST_GET_STROBE_DLL_STATUS (base)(USDHC_GetStrobeDLLStatus(base)) +#else +#define SDMMCHOST_ENABLE_HS400_MODE(base, flag) +#define SDMMCHOST_RESET_STROBE_DLL(base) +#define SDMMCHOST_ENABLE_STROBE_DLL(base, flag) +#define SDMMCHOST_CONFIG_STROBE_DLL(base, delay, updateInterval) +#define SDMMCHOST_GET_STROBE_DLL_STATUS(base) +#endif + +#define SDMMCHOST_ENABLE_MMC_BOOT(base, flag) (USDHC_EnableMmcBoot(base, flag)) +#define SDMMCHOST_SETMMCBOOTCONFIG(base, config) (USDHC_SetMmcBootConfig(base, config)) +/* sd card power */ +#define SDMMCHOST_INIT_SD_POWER() BOARD_USDHC_SDCARD_POWER_CONTROL_INIT() +#define SDMMCHOST_ENABLE_SD_POWER(enable) BOARD_USDHC_SDCARD_POWER_CONTROL(enable) +/* mmc card power */ +#define SDMMCHOST_INIT_MMC_POWER() BOARD_USDHC_MMCCARD_POWER_CONTROL_INIT() +#define SDMMCHOST_ENABLE_MMC_POWER(enable) BOARD_USDHC_MMCCARD_POWER_CONTROL(enable) +/* sd card detect through gpio */ +#define SDMMCHOST_CARD_DETECT_GPIO_STATUS() BOARD_USDHC_CD_STATUS() +#define SDMMCHOST_CARD_DETECT_GPIO_INIT() BOARD_USDHC_CD_GPIO_INIT() +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS() BOARD_USDHC_CD_INTERRUPT_STATUS() +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_STATUS_CLEAR(flag) BOARD_USDHC_CD_CLEAR_INTERRUPT(flag) +#define SDMMCHOST_CARD_DETECT_GPIO_INTERRUPT_HANDLER BOARD_USDHC_CD_PORT_IRQ_HANDLER +#define SDMMCHOST_CARD_DETECT_GPIO_IRQ BOARD_USDHC_CD_PORT_IRQ +/* sd card detect through host CD */ +#define SDMMCHOST_CARD_DETECT_INSERT_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_ENABLE(base) (USDHC_EnableInterruptStatus(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_STATUS(base) (USDHC_DetectCardInsert(base)) +#define SDMMCHOST_CARD_DETECT_REMOVE_STATUS(base) (USDHC_GetInterruptStatusFlags(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_INSERT_INTERRUPT_ENABLE(base) \ + (USDHC_EnableInterruptSignal(base, kUSDHC_CardInsertionFlag)) +#define SDMMCHOST_CARD_DETECT_REMOVE_INTERRUPT_ENABLE(base) (USDHC_EnableInterruptSignal(base, kUSDHC_CardRemovalFlag)) +#define SDMMCHOST_CARD_DETECT_DATA3_ENABLE(base, flag) (USDHC_CardDetectByData3(base, flag)) + +/* define card detect pin voltage level when card inserted */ +#if defined BOARD_USDHC_CARD_INSERT_CD_LEVEL +#define SDMMCHOST_CARD_INSERT_CD_LEVEL BOARD_USDHC_CARD_INSERT_CD_LEVEL +#else +#define SDMMCHOST_CARD_INSERT_CD_LEVEL (0U) +#endif +#define SDMMCHOST_ENABLE_TUNING_FLAG(data) (data.dataType = kUSDHC_TransferDataTuning) +#define SDMMCHOST_ENABLE_BOOT_FLAG(data) (data.dataType = kUSDHC_TransferDataBoot) +#define SDMMCHOST_ENABLE_BOOT_CONTINOUS_FLAG(data) (data.dataType = kUSDHC_TransferDataBootcontinous) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_SIZE(config) (config->blockSize) +#define SDMMCHOST_GET_HOST_CONFIG_BLOCK_COUNT(config) (config->blockCount) +#define SDMMCHOST_GET_HOST_CONFIG_BOOT_MODE(config) (config->bootMode) +#define SDMMCHOST_EMPTY_CMD_FLAG(command) (command.type = kCARD_CommandTypeEmpty) +/*! @brief USDHC host capability*/ +enum _host_capability +{ + kSDMMCHOST_SupportAdma = kUSDHC_SupportAdmaFlag, + kSDMMCHOST_SupportHighSpeed = kUSDHC_SupportHighSpeedFlag, + kSDMMCHOST_SupportDma = kUSDHC_SupportDmaFlag, + kSDMMCHOST_SupportSuspendResume = kUSDHC_SupportSuspendResumeFlag, + kSDMMCHOST_SupportV330 = kUSDHC_SupportV330Flag, /* this define should depend on your board config */ + kSDMMCHOST_SupportV300 = kUSDHC_SupportV300Flag, /* this define should depend on your board config */ +#if defined(BOARD_SD_SUPPORT_180V) && !BOARD_SD_SUPPORT_180V + kSDMMCHOST_SupportV180 = SDMMCHOST_NOT_SUPPORT, /* this define should depend on you board config */ +#else + kSDMMCHOST_SupportV180 = kUSDHC_SupportV180Flag, /* this define should depend on you board config */ +#endif + kSDMMCHOST_SupportV120 = SDMMCHOST_NOT_SUPPORT, + kSDMMCHOST_Support4BitBusWidth = kUSDHC_Support4BitFlag, +#if defined(BOARD_MMC_SUPPORT_8BIT_BUS) +#if BOARD_MMC_SUPPORT_8BIT_BUS + kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag, +#else + kSDMMCHOST_Support8BitBusWidth = SDMMCHOST_NOT_SUPPORT, +#endif +#else + kSDMMCHOST_Support8BitBusWidth = kUSDHC_Support8BitFlag, +#endif + kSDMMCHOST_SupportDDR50 = kUSDHC_SupportDDR50Flag, + kSDMMCHOST_SupportSDR104 = kUSDHC_SupportSDR104Flag, + kSDMMCHOST_SupportSDR50 = kUSDHC_SupportSDR50Flag, + kSDMMCHOST_SupportHS200 = kUSDHC_SupportSDR104Flag, +#if FSL_FEATURE_USDHC_HAS_HS400_MODE + kSDMMCHOST_SupportHS400 = SDMMCHOST_SUPPORT +#else + kSDMMCHOST_SupportHS400 = SDMMCHOST_NOT_SUPPORT, +#endif +}; + +/* Endian mode. */ +#define USDHC_ENDIAN_MODE kUSDHC_EndianModeLittle + +/* DMA mode */ +#define USDHC_DMA_MODE kUSDHC_DmaModeAdma2 +/* address align */ +#define SDMMCHOST_DMA_BUFFER_ADDR_ALIGN (USDHC_ADMA2_ADDRESS_ALIGN) + +/* Read/write watermark level. The bigger value indicates DMA has higher read/write performance. */ +#define USDHC_READ_WATERMARK_LEVEL (0x80U) +#define USDHC_WRITE_WATERMARK_LEVEL (0x80U) + +/* ADMA table length united as word. + * + * One ADMA2 table item occupy two words which can transfer maximum 0xFFFFU bytes one time. + * The more data to be transferred in one time, the bigger value of SDHC_ADMA_TABLE_WORDS need to be set. + */ +#define USDHC_ADMA_TABLE_WORDS (8U) /* define the ADMA descriptor table length */ +#define USDHC_ADMA2_ADDR_ALIGN (4U) /* define the ADMA2 descriptor table addr align size */ +#define USDHC_READ_BURST_LEN (8U) /*!< number of words USDHC read in a single burst */ +#define USDHC_WRITE_BURST_LEN (8U) /*!< number of words USDHC write in a single burst */ +#define USDHC_DATA_TIMEOUT (0xFU) /*!< data timeout counter value */ + +#endif /* (defined(FSL_FEATURE_SOC_SDHC_COUNT) && (FSL_FEATURE_SOC_SDHC_COUNT > 0U)) */ + +/*! @brief card detect callback definition */ +typedef void (*sdmmchost_cd_callback_t)(bool isInserted, void *userData); + +/*! @brief host Endian mode +* corresponding to driver define +*/ +enum _sdmmchost_endian_mode +{ + kSDMMCHOST_EndianModeBig = 0U, /*!< Big endian mode */ + kSDMMCHOST_EndianModeHalfWordBig = 1U, /*!< Half word big endian mode */ + kSDMMCHOST_EndianModeLittle = 2U, /*!< Little endian mode */ +}; + +/*! @brief sd card detect type */ +typedef enum _sdmmchost_detect_card_type +{ + kSDMMCHOST_DetectCardByGpioCD, /*!< sd card detect by CD pin through GPIO */ + kSDMMCHOST_DetectCardByHostCD, /*!< sd card detect by CD pin through host */ + kSDMMCHOST_DetectCardByHostDATA3, /*!< sd card detect by DAT3 pin through host */ +} sdmmchost_detect_card_type_t; + +/*! @brief sd card detect */ +typedef struct _sdmmchost_detect_card +{ + sdmmchost_detect_card_type_t cdType; /*!< card detect type */ + uint32_t cdTimeOut_ms; /*!< card detect timeout which allow 0 - 0xFFFFFFF, value 0 will return immediately, value + 0xFFFFFFFF will block until card is insert */ + + sdmmchost_cd_callback_t cardInserted; /*!< card inserted callback which is meaningful for interrupt case */ + sdmmchost_cd_callback_t cardRemoved; /*!< card removed callback which is meaningful for interrupt case */ + + void *userData; /*!< user data */ +} sdmmchost_detect_card_t; + +/*! @brief card power control function pointer */ +typedef void (*sdmmchost_pwr_t)(void); + +/*! @brief card power control */ +typedef struct _sdmmchost_pwr_card +{ + sdmmchost_pwr_t powerOn; /*!< power on function pointer */ + uint32_t powerOnDelay_ms; /*!< power on delay */ + + sdmmchost_pwr_t powerOff; /*!< power off function pointer */ + uint32_t powerOffDelay_ms; /*!< power off delay */ +} sdmmchost_pwr_card_t; + +/******************************************************************************* + * API + ******************************************************************************/ +#if defined(__cplusplus) +extern "C" { +#endif + +/*! + * @name adaptor function + * @{ + */ + +/*! + * @brief host not support function, this function is used for host not support feature + * @param void parameter ,used to avoid build warning + * @retval kStatus_Fail ,host do not suppport + */ +static inline status_t SDMMCHOST_NotSupport(void *parameter) +{ + parameter = parameter; + return kStatus_Success; +} + +/*! + * @brief Detect card insert, only need for SD cases. + * @param base the pointer to host base address + * @param cd card detect configuration + * @param waitCardStatus status which user want to wait + * @retval kStatus_Success detect card insert + * @retval kStatus_Fail card insert event fail + */ +status_t SDMMCHOST_WaitCardDetectStatus(SDMMCHOST_TYPE *hostBase, + const sdmmchost_detect_card_t *cd, + bool waitCardStatus); + +/*! + * @brief check card is present or not. + * @retval true card is present + * @retval false card is not present + */ +bool SDMMCHOST_IsCardPresent(void); + +/*! + * @brief Init host controller. + * @param host the pointer to host structure in card structure. + * @param userData specific user data + * @retval kStatus_Success host init success + * @retval kStatus_Fail event fail + */ +status_t SDMMCHOST_Init(SDMMCHOST_CONFIG *host, void *userData); + +/*! + * @brief reset host controller. + * @param host base address. + */ +void SDMMCHOST_Reset(SDMMCHOST_TYPE *base); + +/*! + * @brief host controller error recovery. + * @param host base address. + */ +void SDMMCHOST_ErrorRecovery(SDMMCHOST_TYPE *base); + +/*! + * @brief Deinit host controller. + * @param host the pointer to host structure in card structure. + */ +void SDMMCHOST_Deinit(void *host); + +/*! + * @brief host power off card function. + * @param base host base address. + * @param pwr depend on user define power configuration. + */ +void SDMMCHOST_PowerOffCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief host power on card function. + * @param base host base address. + * @param pwr depend on user define power configuration. + */ +void SDMMCHOST_PowerOnCard(SDMMCHOST_TYPE *base, const sdmmchost_pwr_card_t *pwr); + +/*! + * @brief SDMMC host delay function. + * @param milliseconds delay counter. + */ +void SDMMCHOST_Delay(uint32_t milliseconds); + +/* @} */ + +#if defined(__cplusplus) +} +#endif + +#endif /* _FSL_SDMMC_HOST_H */ diff --git a/target/TARGET_NXP/fsl_sdmmc_spec.h b/target/TARGET_NXP/fsl_sdmmc_spec.h new file mode 100644 index 0000000..c20ec2e --- /dev/null +++ b/target/TARGET_NXP/fsl_sdmmc_spec.h @@ -0,0 +1,1164 @@ +/* + * Copyright (c) 2015, Freescale Semiconductor, Inc. + * Copyright 2016-2018 NXP + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _FSL_SDMMC_SPEC_H_ +#define _FSL_SDMMC_SPEC_H_ + +#include + +/******************************************************************************* + * Definitions + ******************************************************************************/ +/*! @brief SD/MMC card initialization clock frequency */ +#define SDMMC_CLOCK_400KHZ (400000U) +/*! @brief SD card bus frequency 1 in high-speed mode */ +#define SD_CLOCK_25MHZ (25000000U) +/*! @brief SD card bus frequency 2 in high-speed mode */ +#define SD_CLOCK_50MHZ (50000000U) +/*! @brief SD card bus frequency in SDR50 mode */ +#define SD_CLOCK_100MHZ (100000000U) +/*! @brief SD card bus frequency in SDR104 mode */ +#define SD_CLOCK_208MHZ (208000000U) +/*! @brief MMC card bus frequency 1 in high-speed mode */ +#define MMC_CLOCK_26MHZ (26000000U) +/*! @brief MMC card bus frequency 2 in high-speed mode */ +#define MMC_CLOCK_52MHZ (52000000U) +/*! @brief MMC card bus frequency in high-speed DDR52 mode */ +#define MMC_CLOCK_DDR52 (52000000U) +/*! @brief MMC card bus frequency in high-speed HS200 mode */ +#define MMC_CLOCK_HS200 (200000000U) +/*! @brief MMC card bus frequency in high-speed HS400 mode */ +#define MMC_CLOCK_HS400 (400000000U) + +/*!@brief mask convert */ +#define SDMMC_MASK(bit) (1U << (bit)) + +/*! @brief Card status bit in R1 */ +enum _sdmmc_r1_card_status_flag +{ + kSDMMC_R1OutOfRangeFlag = 31, /*!< Out of range status bit */ + kSDMMC_R1AddressErrorFlag = 30, /*!< Address error status bit */ + kSDMMC_R1BlockLengthErrorFlag = 29, /*!< Block length error status bit */ + kSDMMC_R1EraseSequenceErrorFlag = 28, /*!< Erase sequence error status bit */ + kSDMMC_R1EraseParameterErrorFlag = 27, /*!< Erase parameter error status bit */ + kSDMMC_R1WriteProtectViolationFlag = 26, /*!< Write protection violation status bit */ + kSDMMC_R1CardIsLockedFlag = 25, /*!< Card locked status bit */ + kSDMMC_R1LockUnlockFailedFlag = 24, /*!< lock/unlock error status bit */ + kSDMMC_R1CommandCrcErrorFlag = 23, /*!< CRC error status bit */ + kSDMMC_R1IllegalCommandFlag = 22, /*!< Illegal command status bit */ + kSDMMC_R1CardEccFailedFlag = 21, /*!< Card ecc error status bit */ + kSDMMC_R1CardControllerErrorFlag = 20, /*!< Internal card controller error status bit */ + kSDMMC_R1ErrorFlag = 19, /*!< A general or an unknown error status bit */ + kSDMMC_R1CidCsdOverwriteFlag = 16, /*!< Cid/csd overwrite status bit */ + kSDMMC_R1WriteProtectEraseSkipFlag = 15, /*!< Write protection erase skip status bit */ + kSDMMC_R1CardEccDisabledFlag = 14, /*!< Card ecc disabled status bit */ + kSDMMC_R1EraseResetFlag = 13, /*!< Erase reset status bit */ + kSDMMC_R1ReadyForDataFlag = 8, /*!< Ready for data status bit */ + kSDMMC_R1SwitchErrorFlag = 7, /*!< Switch error status bit */ + kSDMMC_R1ApplicationCommandFlag = 5, /*!< Application command enabled status bit */ + kSDMMC_R1AuthenticationSequenceErrorFlag = 3, /*!< error in the sequence of authentication process */ +}; + +/*! @brief R1 all the error flag */ +#define SDMMC_R1_ALL_ERROR_FLAG \ + (SDMMC_MASK(kSDMMC_R1OutOfRangeFlag) | SDMMC_MASK(kSDMMC_R1AddressErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1BlockLengthErrorFlag) | SDMMC_MASK(kSDMMC_R1EraseSequenceErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1EraseParameterErrorFlag) | SDMMC_MASK(kSDMMC_R1WriteProtectViolationFlag) | \ + SDMMC_MASK(kSDMMC_R1CardIsLockedFlag) | SDMMC_MASK(kSDMMC_R1LockUnlockFailedFlag) | \ + SDMMC_MASK(kSDMMC_R1CommandCrcErrorFlag) | SDMMC_MASK(kSDMMC_R1IllegalCommandFlag) | \ + SDMMC_MASK(kSDMMC_R1CardEccFailedFlag) | SDMMC_MASK(kSDMMC_R1CardControllerErrorFlag) | \ + SDMMC_MASK(kSDMMC_R1ErrorFlag) | SDMMC_MASK(kSDMMC_R1CidCsdOverwriteFlag) | \ + SDMMC_MASK(kSDMMC_R1AuthenticationSequenceErrorFlag)) + +/*! @brief R1: current state */ +#define SDMMC_R1_CURRENT_STATE(x) (((x)&0x00001E00U) >> 9U) + +/*! @brief CURRENT_STATE filed in R1 */ +typedef enum _sdmmc_r1_current_state +{ + kSDMMC_R1StateIdle = 0U, /*!< R1: current state: idle */ + kSDMMC_R1StateReady = 1U, /*!< R1: current state: ready */ + kSDMMC_R1StateIdentify = 2U, /*!< R1: current state: identification */ + kSDMMC_R1StateStandby = 3U, /*!< R1: current state: standby */ + kSDMMC_R1StateTransfer = 4U, /*!< R1: current state: transfer */ + kSDMMC_R1StateSendData = 5U, /*!< R1: current state: sending data */ + kSDMMC_R1StateReceiveData = 6U, /*!< R1: current state: receiving data */ + kSDMMC_R1StateProgram = 7U, /*!< R1: current state: programming */ + kSDMMC_R1StateDisconnect = 8U, /*!< R1: current state: disconnect */ +} sdmmc_r1_current_state_t; + +/*! @brief Error bit in SPI mode R1 */ +enum _sdspi_r1_error_status_flag +{ + kSDSPI_R1InIdleStateFlag = (1U << 0U), /*!< In idle state */ + kSDSPI_R1EraseResetFlag = (1U << 1U), /*!< Erase reset */ + kSDSPI_R1IllegalCommandFlag = (1U << 2U), /*!< Illegal command */ + kSDSPI_R1CommandCrcErrorFlag = (1U << 3U), /*!< Com crc error */ + kSDSPI_R1EraseSequenceErrorFlag = (1U << 4U), /*!< Erase sequence error */ + kSDSPI_R1AddressErrorFlag = (1U << 5U), /*!< Address error */ + kSDSPI_R1ParameterErrorFlag = (1U << 6U), /*!< Parameter error */ +}; + +/*! @brief Error bit in SPI mode R2 */ +enum _sdspi_r2_error_status_flag +{ + kSDSPI_R2CardLockedFlag = (1U << 0U), /*!< Card is locked */ + kSDSPI_R2WriteProtectEraseSkip = (1U << 1U), /*!< Write protect erase skip */ + kSDSPI_R2LockUnlockFailed = (1U << 1U), /*!< Lock/unlock command failed */ + kSDSPI_R2ErrorFlag = (1U << 2U), /*!< Unknown error */ + kSDSPI_R2CardControllerErrorFlag = (1U << 3U), /*!< Card controller error */ + kSDSPI_R2CardEccFailedFlag = (1U << 4U), /*!< Card ecc failed */ + kSDSPI_R2WriteProtectViolationFlag = (1U << 5U), /*!< Write protect violation */ + kSDSPI_R2EraseParameterErrorFlag = (1U << 6U), /*!< Erase parameter error */ + kSDSPI_R2OutOfRangeFlag = (1U << 7U), /*!< Out of range */ + kSDSPI_R2CsdOverwriteFlag = (1U << 7U), /*!< CSD overwrite */ +}; + +/*! @brief The bit mask for COMMAND VERSION field in R7 */ +#define SDSPI_R7_VERSION_SHIFT (28U) +/*! @brief The bit mask for COMMAND VERSION field in R7 */ +#define SDSPI_R7_VERSION_MASK (0xFU) +/*! @brief The bit shift for VOLTAGE ACCEPTED field in R7 */ +#define SDSPI_R7_VOLTAGE_SHIFT (8U) +/*! @brief The bit mask for VOLTAGE ACCEPTED field in R7 */ +#define SDSPI_R7_VOLTAGE_MASK (0xFU) +/*! @brief The bit mask for VOLTAGE 2.7V to 3.6V field in R7 */ +#define SDSPI_R7_VOLTAGE_27_36_MASK (0x1U << SDSPI_R7_VOLTAGE_SHIFT) +/*! @brief The bit shift for ECHO field in R7 */ +#define SDSPI_R7_ECHO_SHIFT (0U) +/*! @brief The bit mask for ECHO field in R7 */ +#define SDSPI_R7_ECHO_MASK (0xFFU) + +/*! @brief Data error token mask */ +#define SDSPI_DATA_ERROR_TOKEN_MASK (0xFU) +/*! @brief Data Error Token mask bit */ +enum _sdspi_data_error_token +{ + kSDSPI_DataErrorTokenError = (1U << 0U), /*!< Data error */ + kSDSPI_DataErrorTokenCardControllerError = (1U << 1U), /*!< Card controller error */ + kSDSPI_DataErrorTokenCardEccFailed = (1U << 2U), /*!< Card ecc error */ + kSDSPI_DataErrorTokenOutOfRange = (1U << 3U), /*!< Out of range */ +}; + +/*! @brief Data Token */ +typedef enum _sdspi_data_token +{ + kSDSPI_DataTokenBlockRead = 0xFEU, /*!< Single block read, multiple block read */ + kSDSPI_DataTokenSingleBlockWrite = 0xFEU, /*!< Single block write */ + kSDSPI_DataTokenMultipleBlockWrite = 0xFCU, /*!< Multiple block write */ + kSDSPI_DataTokenStopTransfer = 0xFDU, /*!< Stop transmission */ +} sdspi_data_token_t; + +/* Data Response Token mask */ +#define SDSPI_DATA_RESPONSE_TOKEN_MASK (0x1FU) /*!< Mask for data response bits */ +/*! @brief Data Response Token */ +typedef enum _sdspi_data_response_token +{ + kSDSPI_DataResponseTokenAccepted = 0x05U, /*!< Data accepted */ + kSDSPI_DataResponseTokenCrcError = 0x0BU, /*!< Data rejected due to CRC error */ + kSDSPI_DataResponseTokenWriteError = 0x0DU, /*!< Data rejected due to write error */ +} sdspi_data_response_token_t; + +/*! @brief SD card individual commands */ +typedef enum _sd_command +{ + kSD_SendRelativeAddress = 3U, /*!< Send Relative Address */ + kSD_Switch = 6U, /*!< Switch Function */ + kSD_SendInterfaceCondition = 8U, /*!< Send Interface Condition */ + kSD_VoltageSwitch = 11U, /*!< Voltage Switch */ + kSD_SpeedClassControl = 20U, /*!< Speed Class control */ + kSD_EraseWriteBlockStart = 32U, /*!< Write Block Start */ + kSD_EraseWriteBlockEnd = 33U, /*!< Write Block End */ + kSD_SendTuningBlock = 19U, /*!< Send Tuning Block */ +} sd_command_t; + +/*! @brief SDSPI individual commands */ +typedef enum _sdspi_command +{ + kSDSPI_CommandCrc = 59U, /*!< Command crc protection on/off */ +} sdspi_command_t; + +/*! @brief SD card individual application commands */ +typedef enum _sd_application_command +{ + kSD_ApplicationSetBusWdith = 6U, /*!< Set Bus Width */ + kSD_ApplicationStatus = 13U, /*!< Send SD status */ + kSD_ApplicationSendNumberWriteBlocks = 22U, /*!< Send Number Of Written Blocks */ + kSD_ApplicationSetWriteBlockEraseCount = 23U, /*!< Set Write Block Erase Count */ + kSD_ApplicationSendOperationCondition = 41U, /*!< Send Operation Condition */ + kSD_ApplicationSetClearCardDetect = 42U, /*!< Set Connnect/Disconnect pull up on detect pin */ + kSD_ApplicationSendScr = 51U, /*!< Send Scr */ +} sd_application_command_t; + +/*! @brief SD card command class */ +enum _sdmmc_command_class +{ + kSDMMC_CommandClassBasic = (1U << 0U), /*!< Card command class 0 */ + kSDMMC_CommandClassBlockRead = (1U << 2U), /*!< Card command class 2 */ + kSDMMC_CommandClassBlockWrite = (1U << 4U), /*!< Card command class 4 */ + kSDMMC_CommandClassErase = (1U << 5U), /*!< Card command class 5 */ + kSDMMC_CommandClassWriteProtect = (1U << 6U), /*!< Card command class 6 */ + kSDMMC_CommandClassLockCard = (1U << 7U), /*!< Card command class 7 */ + kSDMMC_CommandClassApplicationSpecific = (1U << 8U), /*!< Card command class 8 */ + kSDMMC_CommandClassInputOutputMode = (1U << 9U), /*!< Card command class 9 */ + kSDMMC_CommandClassSwitch = (1U << 10U), /*!< Card command class 10 */ +}; + +/*! @brief OCR register in SD card */ +enum _sd_ocr_flag +{ + kSD_OcrPowerUpBusyFlag = 31, /*!< Power up busy status */ + kSD_OcrHostCapacitySupportFlag = 30, /*!< Card capacity status */ + kSD_OcrCardCapacitySupportFlag = kSD_OcrHostCapacitySupportFlag, /*!< Card capacity status */ + kSD_OcrSwitch18RequestFlag = 24, /*!< Switch to 1.8V request */ + kSD_OcrSwitch18AcceptFlag = kSD_OcrSwitch18RequestFlag, /*!< Switch to 1.8V accepted */ + kSD_OcrVdd27_28Flag = 15, /*!< VDD 2.7-2.8 */ + kSD_OcrVdd28_29Flag = 16, /*!< VDD 2.8-2.9 */ + kSD_OcrVdd29_30Flag = 17, /*!< VDD 2.9-3.0 */ + kSD_OcrVdd30_31Flag = 18, /*!< VDD 2.9-3.0 */ + kSD_OcrVdd31_32Flag = 19, /*!< VDD 3.0-3.1 */ + kSD_OcrVdd32_33Flag = 20, /*!< VDD 3.1-3.2 */ + kSD_OcrVdd33_34Flag = 21, /*!< VDD 3.2-3.3 */ + kSD_OcrVdd34_35Flag = 22, /*!< VDD 3.3-3.4 */ + kSD_OcrVdd35_36Flag = 23, /*!< VDD 3.4-3.5 */ +}; + +/*! @brief SD card specification version number */ +enum _sd_specification_version +{ + kSD_SpecificationVersion1_0 = (1U << 0U), /*!< SD card version 1.0-1.01 */ + kSD_SpecificationVersion1_1 = (1U << 1U), /*!< SD card version 1.10 */ + kSD_SpecificationVersion2_0 = (1U << 2U), /*!< SD card version 2.00 */ + kSD_SpecificationVersion3_0 = (1U << 3U), /*!< SD card version 3.0 */ +}; + +/*! @brief SD card bus width */ +typedef enum _sd_data_bus_width +{ + kSD_DataBusWidth1Bit = 0U, /*!< SD data bus width 1-bit mode */ + kSD_DataBusWidth4Bit = 1U, /*!< SD data bus width 4-bit mode */ +} sd_data_bus_width_t; + +/*! @brief SD card switch mode */ +typedef enum _sd_switch_mode +{ + kSD_SwitchCheck = 0U, /*!< SD switch mode 0: check function */ + kSD_SwitchSet = 1U, /*!< SD switch mode 1: set function */ +} sd_switch_mode_t; + +/*! @brief SD card CSD register flags */ +enum _sd_csd_flag +{ + kSD_CsdReadBlockPartialFlag = (1U << 0U), /*!< Partial blocks for read allowed [79:79] */ + kSD_CsdWriteBlockMisalignFlag = (1U << 1U), /*!< Write block misalignment [78:78] */ + kSD_CsdReadBlockMisalignFlag = (1U << 2U), /*!< Read block misalignment [77:77] */ + kSD_CsdDsrImplementedFlag = (1U << 3U), /*!< DSR implemented [76:76] */ + kSD_CsdEraseBlockEnabledFlag = (1U << 4U), /*!< Erase single block enabled [46:46] */ + kSD_CsdWriteProtectGroupEnabledFlag = (1U << 5U), /*!< Write protect group enabled [31:31] */ + kSD_CsdWriteBlockPartialFlag = (1U << 6U), /*!< Partial blocks for write allowed [21:21] */ + kSD_CsdFileFormatGroupFlag = (1U << 7U), /*!< File format group [15:15] */ + kSD_CsdCopyFlag = (1U << 8U), /*!< Copy flag [14:14] */ + kSD_CsdPermanentWriteProtectFlag = (1U << 9U), /*!< Permanent write protection [13:13] */ + kSD_CsdTemporaryWriteProtectFlag = (1U << 10U), /*!< Temporary write protection [12:12] */ +}; + +/*! @brief SD card SCR register flags */ +enum _sd_scr_flag +{ + kSD_ScrDataStatusAfterErase = (1U << 0U), /*!< Data status after erases [55:55] */ + kSD_ScrSdSpecification3 = (1U << 1U), /*!< Specification version 3.00 or higher [47:47]*/ +}; + +/*! @brief SD timing function number */ +enum _sd_timing_function +{ + kSD_FunctionSDR12Deafult = 0U, /*!< SDR12 mode & default*/ + kSD_FunctionSDR25HighSpeed = 1U, /*!< SDR25 & high speed*/ + kSD_FunctionSDR50 = 2U, /*!< SDR50 mode*/ + kSD_FunctionSDR104 = 3U, /*!< SDR104 mode*/ + kSD_FunctionDDR50 = 4U, /*!< DDR50 mode*/ +}; + +/*! @brief SD group number */ +enum _sd_group_num +{ + kSD_GroupTimingMode = 0U, /*!< acess mode group*/ + kSD_GroupCommandSystem = 1U, /*!< command system group*/ + kSD_GroupDriverStrength = 2U, /*!< driver strength group*/ + kSD_GroupCurrentLimit = 3U, /*!< current limit group*/ +}; + +/*! @brief SD card timing mode flags */ +typedef enum _sd_timing_mode +{ + kSD_TimingSDR12DefaultMode = 0U, /*!< Identification mode & SDR12 */ + kSD_TimingSDR25HighSpeedMode = 1U, /*!< High speed mode & SDR25 */ + kSD_TimingSDR50Mode = 2U, /*!< SDR50 mode*/ + kSD_TimingSDR104Mode = 3U, /*!< SDR104 mode */ + kSD_TimingDDR50Mode = 4U, /*!< DDR50 mode */ +} sd_timing_mode_t; + +/*! @brief SD card driver strength */ +typedef enum _sd_driver_strength +{ + kSD_DriverStrengthTypeB = 0U, /*!< default driver strength*/ + kSD_DriverStrengthTypeA = 1U, /*!< driver strength TYPE A */ + kSD_DriverStrengthTypeC = 2U, /*!< driver strength TYPE C */ + kSD_DriverStrengthTypeD = 3U, /*!< driver strength TYPE D */ +} sd_driver_strength_t; + +/*! @brief SD card current limit */ +typedef enum _sd_max_current +{ + kSD_CurrentLimit200MA = 0U, /*!< default current limit */ + kSD_CurrentLimit400MA = 1U, /*!< current limit to 400MA */ + kSD_CurrentLimit600MA = 2U, /*!< current limit to 600MA */ + kSD_CurrentLimit800MA = 3U, /*!< current limit to 800MA */ +} sd_max_current_t; + +/*! @brief SD/MMC card common commands */ +typedef enum _sdmmc_command +{ + kSDMMC_GoIdleState = 0U, /*!< Go Idle State */ + kSDMMC_AllSendCid = 2U, /*!< All Send CID */ + kSDMMC_SetDsr = 4U, /*!< Set DSR */ + kSDMMC_SelectCard = 7U, /*!< Select Card */ + kSDMMC_SendCsd = 9U, /*!< Send CSD */ + kSDMMC_SendCid = 10U, /*!< Send CID */ + kSDMMC_StopTransmission = 12U, /*!< Stop Transmission */ + kSDMMC_SendStatus = 13U, /*!< Send Status */ + kSDMMC_GoInactiveState = 15U, /*!< Go Inactive State */ + kSDMMC_SetBlockLength = 16U, /*!< Set Block Length */ + kSDMMC_ReadSingleBlock = 17U, /*!< Read Single Block */ + kSDMMC_ReadMultipleBlock = 18U, /*!< Read Multiple Block */ + kSDMMC_SetBlockCount = 23U, /*!< Set Block Count */ + kSDMMC_WriteSingleBlock = 24U, /*!< Write Single Block */ + kSDMMC_WriteMultipleBlock = 25U, /*!< Write Multiple Block */ + kSDMMC_ProgramCsd = 27U, /*!< Program CSD */ + kSDMMC_SetWriteProtect = 28U, /*!< Set Write Protect */ + kSDMMC_ClearWriteProtect = 29U, /*!< Clear Write Protect */ + kSDMMC_SendWriteProtect = 30U, /*!< Send Write Protect */ + kSDMMC_Erase = 38U, /*!< Erase */ + kSDMMC_LockUnlock = 42U, /*!< Lock Unlock */ + kSDMMC_ApplicationCommand = 55U, /*!< Send Application Command */ + kSDMMC_GeneralCommand = 56U, /*!< General Purpose Command */ + kSDMMC_ReadOcr = 58U, /*!< Read OCR */ +} sdmmc_command_t; + +/*! @brief sdio card cccr register addr */ +enum _sdio_cccr_reg +{ + kSDIO_RegCCCRSdioVer = 0x00U, /*!< CCCR & SDIO version*/ + kSDIO_RegSDVersion = 0x01U, /*!< SD version */ + kSDIO_RegIOEnable = 0x02U, /*!< io enable register */ + kSDIO_RegIOReady = 0x03U, /*!< io ready register */ + kSDIO_RegIOIntEnable = 0x04U, /*!< io interrupt enable register */ + kSDIO_RegIOIntPending = 0x05U, /*!< io interrupt pending register */ + kSDIO_RegIOAbort = 0x06U, /*!< io abort register */ + kSDIO_RegBusInterface = 0x07U, /*!< bus interface register */ + kSDIO_RegCardCapability = 0x08U, /*!< card capability register */ + kSDIO_RegCommonCISPointer = 0x09U, /*!< common CIS pointer register */ + kSDIO_RegBusSuspend = 0x0C, /*!< bus suspend register */ + kSDIO_RegFunctionSelect = 0x0DU, /*!< function select register */ + kSDIO_RegExecutionFlag = 0x0EU, /*!< execution flag register */ + kSDIO_RegReadyFlag = 0x0FU, /*!< ready flag register */ + kSDIO_RegFN0BlockSizeLow = 0x10U, /*!< FN0 block size register */ + kSDIO_RegFN0BlockSizeHigh = 0x11U, /*!< FN0 block size register */ + kSDIO_RegPowerControl = 0x12U, /*!< power control register */ + kSDIO_RegHighSpeed = 0x13U, /*!< high speed register */ +}; + +/*! @brief sdio card individual commands */ +typedef enum _sdio_command +{ + kSDIO_SendRelativeAddress = 3U, /*!< send relative address */ + kSDIO_SendOperationCondition = 5U, /*!< send operation condition */ + kSDIO_SendInterfaceCondition = 8U, /*!< send interface condition */ + kSDIO_RWIODirect = 52U, /*!< read/write IO direct command */ + kSDIO_RWIOExtended = 53U, /*!< read/write IO extended command */ +} sdio_command_t; + +/*! @brief sdio card individual commands */ +typedef enum _sdio_func_num +{ + kSDIO_FunctionNum0, /*!< sdio function0*/ + kSDIO_FunctionNum1, /*!< sdio function1*/ + kSDIO_FunctionNum2, /*!< sdio function2*/ + kSDIO_FunctionNum3, /*!< sdio function3*/ + kSDIO_FunctionNum4, /*!< sdio function4*/ + kSDIO_FunctionNum5, /*!< sdio function5*/ + kSDIO_FunctionNum6, /*!< sdio function6*/ + kSDIO_FunctionNum7, /*!< sdio function7*/ + kSDIO_FunctionMemory, /*!< for combo card*/ +} sdio_func_num_t; + +#define SDIO_CMD_ARGUMENT_RW_POS (31U) /*!< read/write flag position */ +#define SDIO_CMD_ARGUMENT_FUNC_NUM_POS (28U) /*!< function number position */ +#define SDIO_DIRECT_CMD_ARGUMENT_RAW_POS (27U) /*!< direct raw flag position */ +#define SDIO_CMD_ARGUMENT_REG_ADDR_POS (9U) /*!< direct reg addr position */ +#define SDIO_CMD_ARGUMENT_REG_ADDR_MASK (0x1FFFFU) /*!< direct reg addr mask */ +#define SDIO_DIRECT_CMD_DATA_MASK (0xFFU) /*!< data mask */ + +#define SDIO_EXTEND_CMD_ARGUMENT_BLOCK_MODE_POS (27U) /*!< extended command argument block mode bit position */ +#define SDIO_EXTEND_CMD_ARGUMENT_OP_CODE_POS (26U) /*!< extended command argument OP Code bit position */ +#define SDIO_EXTEND_CMD_BLOCK_MODE_MASK (0x08000000U) /*!< block mode mask */ +#define SDIO_EXTEND_CMD_OP_CODE_MASK (0x04000000U) /*!< op code mask */ +#define SDIO_EXTEND_CMD_COUNT_MASK (0x1FFU) /*!< byte/block count mask */ +#define SDIO_MAX_BLOCK_SIZE (2048U) /*!< max block size */ +#define SDIO_FBR_BASE(x) (x * 0x100U) /*!< function basic register */ +#define SDIO_TPL_CODE_END (0xFFU) /*!< tuple end */ +#define SDIO_TPL_CODE_MANIFID (0x20U) /*!< manufacturer ID */ +#define SDIO_TPL_CODE_FUNCID (0x21U) /*!< function ID */ +#define SDIO_TPL_CODE_FUNCE (0x22U) /*!< function extension tuple*/ +/*! @brief sdio command response flag */ +enum _sdio_status_flag +{ + kSDIO_StatusCmdCRCError = 0x8000U, /*!< the CRC check of the previous cmd fail*/ + kSDIO_StatusIllegalCmd = 0x4000U, /*!< cmd illegal for the card state */ + kSDIO_StatusR6Error = 0x2000U, /*!< special for R6 error status */ + kSDIO_StatusError = 0x0800U, /*!< A general or an unknown error occurred */ + kSDIO_StatusFunctionNumError = 0x0200U, /*!< invail function error */ + kSDIO_StatusOutofRange = 0x0100U, /*!< cmd argument was out of the allowed range*/ +}; + +/*! @brief sdio operation condition flag */ +enum _sdio_ocr_flag +{ + kSDIO_OcrPowerUpBusyFlag = 31, /*!< Power up busy status */ + kSDIO_OcrIONumber = 28, /*!< number of IO function */ + kSDIO_OcrMemPresent = 27, /*!< memory present flag */ + + kSDIO_OcrVdd20_21Flag = 8, /*!< VDD 2.0-2.1 */ + kSDIO_OcrVdd21_22Flag = 9, /*!< VDD 2.1-2.2 */ + kSDIO_OcrVdd22_23Flag = 10, /*!< VDD 2.2-2.3 */ + kSDIO_OcrVdd23_24Flag = 11, /*!< VDD 2.3-2.4 */ + kSDIO_OcrVdd24_25Flag = 12, /*!< VDD 2.4-2.5 */ + kSDIO_OcrVdd25_26Flag = 13, /*!< VDD 2.5-2.6 */ + kSDIO_OcrVdd26_27Flag = 14, /*!< VDD 2.6-2.7 */ + kSDIO_OcrVdd27_28Flag = 15, /*!< VDD 2.7-2.8 */ + kSDIO_OcrVdd28_29Flag = 16, /*!< VDD 2.8-2.9 */ + kSDIO_OcrVdd29_30Flag = 17, /*!< VDD 2.9-3.0 */ + kSDIO_OcrVdd30_31Flag = 18, /*!< VDD 2.9-3.0 */ + kSDIO_OcrVdd31_32Flag = 19, /*!< VDD 3.0-3.1 */ + kSDIO_OcrVdd32_33Flag = 20, /*!< VDD 3.1-3.2 */ + kSDIO_OcrVdd33_34Flag = 21, /*!< VDD 3.2-3.3 */ + kSDIO_OcrVdd34_35Flag = 22, /*!< VDD 3.3-3.4 */ + kSDIO_OcrVdd35_36Flag = 23, /*!< VDD 3.4-3.5 */ +}; + +/*! @brief sdio capability flag */ +enum _sdio_capability_flag +{ + kSDIO_CCCRSupportDirectCmdDuringDataTrans = (1U << 0U), /*!< support direct cmd during data transfer */ + kSDIO_CCCRSupportMultiBlock = (1U << 1U), /*!< support multi block mode */ + kSDIO_CCCRSupportReadWait = (1U << 2U), /*!< support read wait */ + kSDIO_CCCRSupportSuspendResume = (1U << 3U), /*!< support suspend resume */ + kSDIO_CCCRSupportIntDuring4BitDataTrans = (1U << 4U), /*!< support interrupt during 4-bit data transfer */ + kSDIO_CCCRSupportLowSpeed1Bit = (1U << 6U), /*!< support low speed 1bit mode */ + kSDIO_CCCRSupportLowSpeed4Bit = (1U << 7U), /*!< support low speed 4bit mode */ + kSDIO_CCCRSupportMasterPowerControl = (1U << 8U), /*!< support master power control */ + kSDIO_CCCRSupportHighSpeed = (1U << 9U), /*!< support high speed */ + kSDIO_CCCRSupportContinuousSPIInt = (1U << 10U), /*!< support continuous SPI interrupt */ +}; + +/*! @brief sdio fbr flag */ +enum _sdio_fbr_flag +{ + kSDIO_FBRSupportCSA = (1U << 0U), /*!< function support CSA */ + kSDIO_FBRSupportPowerSelection = (1U << 1U), /*!< function support power selection */ +}; + +/*! @brief sdio bus width */ +typedef enum _sdio_bus_width +{ + kSDIO_DataBus1Bit = 0x00U, /*!< 1bit bus mode */ + kSDIO_DataBus4Bit = 0X02U, /*!< 4 bit bus mode*/ +} sdio_bus_width_t; + +/*! @brief MMC card individual commands */ +typedef enum _mmc_command +{ + kMMC_SendOperationCondition = 1U, /*!< Send Operation Condition */ + kMMC_SetRelativeAddress = 3U, /*!< Set Relative Address */ + kMMC_SleepAwake = 5U, /*!< Sleep Awake */ + kMMC_Switch = 6U, /*!< Switch */ + kMMC_SendExtendedCsd = 8U, /*!< Send EXT_CSD */ + kMMC_ReadDataUntilStop = 11U, /*!< Read Data Until Stop */ + kMMC_BusTestRead = 14U, /*!< Test Read */ + kMMC_SendingBusTest = 19U, /*!< test bus width cmd*/ + kMMC_WriteDataUntilStop = 20U, /*!< Write Data Until Stop */ + kMMC_SendTuningBlock = 21U, /*!< MMC sending tuning block */ + kMMC_ProgramCid = 26U, /*!< Program CID */ + kMMC_EraseGroupStart = 35U, /*!< Erase Group Start */ + kMMC_EraseGroupEnd = 36U, /*!< Erase Group End */ + kMMC_FastInputOutput = 39U, /*!< Fast IO */ + kMMC_GoInterruptState = 40U, /*!< Go interrupt State */ +} mmc_command_t; + +/*! @brief MMC card classified as voltage range */ +typedef enum _mmc_classified_voltage +{ + kMMC_ClassifiedVoltageHigh = 0U, /*!< High-voltage MMC card */ + kMMC_ClassifiedVoltageDual = 1U, /*!< Dual-voltage MMC card */ +} mmc_classified_voltage_t; + +/*! @brief MMC card classified as density level */ +typedef enum _mmc_classified_density +{ + kMMC_ClassifiedDensityWithin2GB = 0U, /*!< Density byte is less than or equal 2GB */ + kMMC_ClassifiedDensityHigher2GB = 1U, /* Density byte is higher than 2GB */ +} mmc_classified_density_t; + +/*! @brief The bit mask for VOLTAGE WINDOW 1.70V to 1.95V field in OCR */ +#define MMC_OCR_V170TO195_SHIFT (7U) +/*! @brief The bit mask for VOLTAGE WINDOW 1.70V to 1.95V field in OCR */ +#define MMC_OCR_V170TO195_MASK (0x00000080U) +/*! @brief The bit shift for VOLTAGE WINDOW 2.00V to 2.60V field in OCR */ +#define MMC_OCR_V200TO260_SHIFT (8U) +/*! @brief The bit mask for VOLTAGE WINDOW 2.00V to 2.60V field in OCR */ +#define MMC_OCR_V200TO260_MASK (0x00007F00U) +/*! @brief The bit shift for VOLTAGE WINDOW 2.70V to 3.60V field in OCR */ +#define MMC_OCR_V270TO360_SHIFT (15U) +/*! @brief The bit mask for VOLTAGE WINDOW 2.70V to 3.60V field in OCR */ +#define MMC_OCR_V270TO360_MASK (0x00FF8000U) +/*! @brief The bit shift for ACCESS MODE field in OCR */ +#define MMC_OCR_ACCESS_MODE_SHIFT (29U) +/*! @brief The bit mask for ACCESS MODE field in OCR */ +#define MMC_OCR_ACCESS_MODE_MASK (0x60000000U) +/*! @brief The bit shift for BUSY field in OCR */ +#define MMC_OCR_BUSY_SHIFT (31U) +/*! @brief The bit mask for BUSY field in OCR */ +#define MMC_OCR_BUSY_MASK (1U << MMC_OCR_BUSY_SHIFT) + +/*! @brief MMC card access mode(Access mode in OCR). */ +typedef enum _mmc_access_mode +{ + kMMC_AccessModeByte = 0U, /*!< The card should be accessed as byte */ + kMMC_AccessModeSector = 2U, /*!< The card should be accessed as sector */ +} mmc_access_mode_t; + +/*! @brief MMC card voltage window(VDD voltage window in OCR). */ +typedef enum _mmc_voltage_window +{ + kMMC_VoltageWindowNone = 0U, /*!< voltage window is not define by user*/ + kMMC_VoltageWindow120 = 0x01U, /*!< Voltage window is 1.20V */ + kMMC_VoltageWindow170to195 = 0x02U, /*!< Voltage window is 1.70V to 1.95V */ + kMMC_VoltageWindows270to360 = 0x1FFU, /*!< Voltage window is 2.70V to 3.60V */ +} mmc_voltage_window_t; + +/*! @brief CSD structure version(CSD_STRUCTURE in CSD). */ +typedef enum _mmc_csd_structure_version +{ + kMMC_CsdStrucureVersion10 = 0U, /*!< CSD version No. 1.0 */ + kMMC_CsdStrucureVersion11 = 1U, /*!< CSD version No. 1.1 */ + kMMC_CsdStrucureVersion12 = 2U, /*!< CSD version No. 1.2 */ + kMMC_CsdStrucureVersionInExtcsd = 3U, /*!< Version coded in Extended CSD */ +} mmc_csd_structure_version_t; + +/*! @brief MMC card specification version(SPEC_VERS in CSD). */ +typedef enum _mmc_specification_version +{ + kMMC_SpecificationVersion0 = 0U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion1 = 1U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion2 = 2U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion3 = 3U, /*!< Allocated by MMCA */ + kMMC_SpecificationVersion4 = 4U, /*!< Version 4.1/4.2/4.3/4.41-4.5-4.51-5.0 */ +} mmc_specification_version_t; + +/*! @brief The bit shift for FREQUENCY UNIT field in TRANSFER SPEED(TRAN-SPEED in Extended CSD) */ +#define MMC_TRANSFER_SPEED_FREQUENCY_UNIT_SHIFT (0U) +/*! @brief The bit mask for FRQEUENCY UNIT in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_FREQUENCY_UNIT_MASK (0x07U) +/*! @brief The bit shift for MULTIPLIER field in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_MULTIPLIER_SHIFT (3U) +/*! @brief The bit mask for MULTIPLIER field in TRANSFER SPEED */ +#define MMC_TRANSFER_SPEED_MULTIPLIER_MASK (0x78U) + +/*! @brief Read the value of FREQUENCY UNIT in TRANSFER SPEED. */ +#define READ_MMC_TRANSFER_SPEED_FREQUENCY_UNIT(CSD) \ + (((CSD.transferSpeed) & MMC_TRANSFER_SPEED_FREQUENCY_UNIT_MASK) >> MMC_TRANSFER_SPEED_FREQUENCY_UNIT_SHIFT) +/*! @brief Read the value of MULTIPLER filed in TRANSFER SPEED. */ +#define READ_MMC_TRANSFER_SPEED_MULTIPLIER(CSD) \ + (((CSD.transferSpeed) & MMC_TRANSFER_SPEED_MULTIPLIER_MASK) >> MMC_TRANSFER_SPEED_MULTIPLIER_SHIFT) + +/*! @brief MMC card Extended CSD fix version(EXT_CSD_REV in Extended CSD) */ +enum _mmc_extended_csd_revision +{ + kMMC_ExtendedCsdRevision10 = 0U, /*!< Revision 1.0 */ + kMMC_ExtendedCsdRevision11 = 1U, /*!< Revision 1.1 */ + kMMC_ExtendedCsdRevision12 = 2U, /*!< Revision 1.2 */ + kMMC_ExtendedCsdRevision13 = 3U, /*!< Revision 1.3 MMC4.3*/ + kMMC_ExtendedCsdRevision14 = 4U, /*!< Revision 1.4 obsolete*/ + kMMC_ExtendedCsdRevision15 = 5U, /*!< Revision 1.5 MMC4.41*/ + kMMC_ExtendedCsdRevision16 = 6U, /*!< Revision 1.6 MMC4.5*/ + kMMC_ExtendedCsdRevision17 = 7U, /*!< Revision 1.7 MMC5.0 */ +}; + +/*! @brief MMC card command set(COMMAND_SET in Extended CSD) */ +typedef enum _mmc_command_set +{ + kMMC_CommandSetStandard = 0U, /*!< Standard MMC */ + kMMC_CommandSet1 = 1U, /*!< Command set 1 */ + kMMC_CommandSet2 = 2U, /*!< Command set 2 */ + kMMC_CommandSet3 = 3U, /*!< Command set 3 */ + kMMC_CommandSet4 = 4U, /*!< Command set 4 */ +} mmc_command_set_t; + +/*! @brief boot support(BOOT_INFO in Extended CSD) */ +enum _mmc_support_boot_mode +{ + kMMC_SupportAlternateBoot = 1U, /*!< support alternative boot mode*/ + kMMC_SupportDDRBoot = 2U, /*!< support DDR boot mode*/ + kMMC_SupportHighSpeedBoot = 4U, /*!< support high speed boot mode*/ +}; +/*! @brief The power class value bit mask when bus in 4 bit mode */ +#define MMC_POWER_CLASS_4BIT_MASK (0x0FU) +/*! @brief The power class current value bit mask when bus in 8 bit mode */ +#define MMC_POWER_CLASS_8BIT_MASK (0xF0U) + +/*! @brief MMC card high-speed timing(HS_TIMING in Extended CSD) */ +typedef enum _mmc_high_speed_timing +{ + kMMC_HighSpeedTimingNone = 0U, /*!< MMC card using none high-speed timing */ + kMMC_HighSpeedTiming = 1U, /*!< MMC card using high-speed timing */ + kMMC_HighSpeed200Timing = 2U, /*!< MMC card high speed 200 timing*/ + kMMC_HighSpeed400Timing = 3U, /*!< MMC card high speed 400 timing*/ +} mmc_high_speed_timing_t; + +/*! @brief The number of data bus width type */ +#define MMC_DATA_BUS_WIDTH_TYPE_NUMBER (3U) +/*! @brief MMC card data bus width(BUS_WIDTH in Extended CSD) */ +typedef enum _mmc_data_bus_width +{ + kMMC_DataBusWidth1bit = 0U, /*!< MMC data bus width is 1 bit */ + kMMC_DataBusWidth4bit = 1U, /*!< MMC data bus width is 4 bits */ + kMMC_DataBusWidth8bit = 2U, /*!< MMC data bus width is 8 bits */ + kMMC_DataBusWidth4bitDDR = 5U, /*!< MMC data bus width is 4 bits ddr */ + kMMC_DataBusWidth8bitDDR = 6U, /*!< MMC data bus width is 8 bits ddr */ +} mmc_data_bus_width_t; + +/*! @brief MMC card boot partition enabled(BOOT_PARTITION_ENABLE in Extended CSD) */ +typedef enum _mmc_boot_partition_enable +{ + kMMC_BootPartitionEnableNot = 0U, /*!< Device not boot enabled (default) */ + kMMC_BootPartitionEnablePartition1 = 1U, /*!< Boot partition 1 enabled for boot */ + kMMC_BootPartitionEnablePartition2 = 2U, /*!< Boot partition 2 enabled for boot */ + kMMC_BootPartitionEnableUserAera = 7U, /*!< User area enabled for boot */ +} mmc_boot_partition_enable_t; + +/*! @brief boot mode configuration + * Note: HS200 & HS400 is not support during BOOT operation. + */ +typedef enum _mmc_boot_timing_mode +{ + kMMC_BootModeSDRWithDefaultTiming = 0U << 3U, /*!< boot mode single data rate with backward compatiable timings */ + kMMC_BootModeSDRWithHighSpeedTiming = 1U << 3U, /*!< boot mode single data rate with high speed timing */ + kMMC_BootModeDDRTiming = 2U << 3U, /*!< boot mode dual date rate */ +} mmc_boot_timing_mode_t; + +/*! @brief MMC card boot partition write protect configurations + * All the bits in BOOT_WP register, except the two R/W bits B_PERM_WP_DIS + * and B_PERM_WP_EN, shall only be written once per power cycle.The protection + * mdde intended for both boot areas will be set with a single write. + */ +typedef enum _mmc_boot_partition_wp +{ + kMMC_BootPartitionWPDisable = 0x50U, /*!< boot partition write protection disable */ + kMMC_BootPartitionPwrWPToBothPartition = + 0x01U, /*!< power on period write protection apply to both boot partitions */ + kMMC_BootPartitionPermWPToBothPartition = 0x04U, /*!< permanent write protection apply to both boot partitions */ + + kMMC_BootPartitionPwrWPToPartition1 = (1U << 7U) | 1U, /*!< power on period write protection apply to partition1 */ + kMMC_BootPartitionPwrWPToPartition2 = (1U << 7U) | 3U, /*!< power on period write protection apply to partition2 */ + + kMMC_BootPartitionPermWPToPartition1 = + (1U << 7U) | (1U << 2U), /*!< permanent write protection apply to partition1 */ + kMMC_BootPartitionPermWPToPartition2 = + (1U << 7U) | (3U << 2U), /*!< permanent write protection apply to partition2 */ + + kMMC_BootPartitionPermWPToPartition1PwrWPToPartition2 = + (1U << 7U) | (1U << 2U) | + 3U, /*!< permanent write protection apply to partition1, power on period write protection apply to partition2 */ + kMMC_BootPartitionPermWPToPartition2PwrWPToPartition1 = + (1U << 7U) | (3U << 2U) | + 1U, /*!< permanent write protection apply to partition2, power on period write protection apply to partition1 */ +} mmc_boot_partition_wp_t; + +/*! @brief MMC card boot partition write protect status */ +enum _mmc_boot_partition_wp_status +{ + kMMC_BootPartitionNotProtected = 0U, /*!< boot partition not protected */ + kMMC_BootPartitionPwrProtected = 1U, /*!< boot partition is power on period write protected */ + kMMC_BootPartitionPermProtected = 2U, /*!< boot partition is permanently protected */ +}; + +/*! @brief MMC card partition to be accessed(BOOT_PARTITION_ACCESS in Extended CSD) */ +typedef enum _mmc_access_partition +{ + kMMC_AccessPartitionUserAera = 0U, /*!< No access to boot partition (default), normal partition */ + kMMC_AccessPartitionBoot1 = 1U, /*!< Read/Write boot partition 1 */ + kMMC_AccessPartitionBoot2 = 2U, /*!< Read/Write boot partition 2*/ + kMMC_AccessRPMB = 3U, /*!< Replay protected mem block */ + kMMC_AccessGeneralPurposePartition1 = 4U, /*!< access to general purpose partition 1 */ + kMMC_AccessGeneralPurposePartition2 = 5U, /*!< access to general purpose partition 2 */ + kMMC_AccessGeneralPurposePartition3 = 6U, /*!< access to general purpose partition 3 */ + kMMC_AccessGeneralPurposePartition4 = 7U, /*!< access to general purpose partition 4 */ +} mmc_access_partition_t; + +/*! @brief The bit shift for PARTITION ACCESS filed in BOOT CONFIG (BOOT_CONFIG in Extend CSD) */ +#define MMC_PARTITION_CONFIG_PARTITION_ACCESS_SHIFT (0U) +/*! @brief The bit mask for PARTITION ACCESS field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ACCESS_MASK (0x00000007U) +/*! @brief The bit shift for PARTITION ENABLE field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ENABLE_SHIFT (3U) +/*! @brief The bit mask for PARTITION ENABLE field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_PARTITION_ENABLE_MASK (0x00000038U) +/*! @brief The bit shift for ACK field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_BOOT_ACK_SHIFT (6U) +/*! @brief The bit mask for ACK field in BOOT CONFIG */ +#define MMC_PARTITION_CONFIG_BOOT_ACK_MASK (0x00000040U) +/*! @brief The bit shift for BOOT BUS WIDTH field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BUS_WIDTH_SHIFT (0U) +/*! @brief The bit mask for BOOT BUS WIDTH field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BUS_WIDTH_MASK (3U) +/*! @brief The bit shift for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_RESET_BUS_CONDITION_SHIFT (2U) +/*! @brief The bit mask for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_RESET_BUS_CONDITION_MASK (4U) +/*! @brief The bit mask for BOOT BUS WIDTH RESET field in BOOT CONFIG */ +#define MMC_BOOT_BUS_CONDITION_BOOT_MODE_MASK (0x18U) + +/*! @brief MMC card CSD register flags */ +enum _mmc_csd_flag +{ + kMMC_CsdReadBlockPartialFlag = (1U << 0U), /*!< Partial blocks for read allowed */ + kMMC_CsdWriteBlockMisalignFlag = (1U << 1U), /*!< Write block misalignment */ + kMMC_CsdReadBlockMisalignFlag = (1U << 2U), /*!< Read block misalignment */ + kMMC_CsdDsrImplementedFlag = (1U << 3U), /*!< DSR implemented */ + kMMC_CsdWriteProtectGroupEnabledFlag = (1U << 4U), /*!< Write protect group enabled */ + kMMC_CsdWriteBlockPartialFlag = (1U << 5U), /*!< Partial blocks for write allowed */ + kMMC_ContentProtectApplicationFlag = (1U << 6U), /*!< Content protect application */ + kMMC_CsdFileFormatGroupFlag = (1U << 7U), /*!< File format group */ + kMMC_CsdCopyFlag = (1U << 8U), /*!< Copy flag */ + kMMC_CsdPermanentWriteProtectFlag = (1U << 9U), /*!< Permanent write protection */ + kMMC_CsdTemporaryWriteProtectFlag = (1U << 10U), /*!< Temporary write protection */ +}; + +/*! @brief Extended CSD register access mode(Access mode in CMD6). */ +typedef enum _mmc_extended_csd_access_mode +{ + kMMC_ExtendedCsdAccessModeCommandSet = 0U, /*!< Command set related setting */ + kMMC_ExtendedCsdAccessModeSetBits = 1U, /*!< Set bits in specific byte in Extended CSD */ + kMMC_ExtendedCsdAccessModeClearBits = 2U, /*!< Clear bits in specific byte in Extended CSD */ + kMMC_ExtendedCsdAccessModeWriteBits = 3U, /*!< Write a value to specific byte in Extended CSD */ +} mmc_extended_csd_access_mode_t; + +/*! @brief EXT CSD byte index */ +typedef enum _mmc_extended_csd_index +{ + kMMC_ExtendedCsdIndexBootPartitionWP = 173U, /*!< Boot partition write protect */ + kMMC_ExtendedCsdIndexEraseGroupDefinition = 175U, /*!< Erase Group Def */ + kMMC_ExtendedCsdIndexBootBusConditions = 177U, /*!< Boot Bus conditions */ + kMMC_ExtendedCsdIndexBootConfigWP = 178U, /*!< Boot config write protect */ + kMMC_ExtendedCsdIndexPartitionConfig = 179U, /*!< Partition Config, before BOOT_CONFIG */ + kMMC_ExtendedCsdIndexBusWidth = 183U, /*!< Bus Width */ + kMMC_ExtendedCsdIndexHighSpeedTiming = 185U, /*!< High-speed Timing */ + kMMC_ExtendedCsdIndexPowerClass = 187U, /*!< Power Class */ + kMMC_ExtendedCsdIndexCommandSet = 191U, /*!< Command Set */ +} mmc_extended_csd_index_t; + +/*! @brief mmc driver strength */ +enum _mmc_driver_strength +{ + kMMC_DriverStrength0 = 0U, /*!< Driver type0 ,nominal impedance 50ohm */ + kMMC_DriverStrength1 = 1U, /*!< Driver type1 ,nominal impedance 33ohm */ + kMMC_DriverStrength2 = 2U, /*!< Driver type2 ,nominal impedance 66ohm */ + kMMC_DriverStrength3 = 3U, /*!< Driver type3 ,nominal impedance 100ohm */ + kMMC_DriverStrength4 = 4U, /*!< Driver type4 ,nominal impedance 40ohm */ +}; + +/*! @brief mmc extended csd flags*/ +typedef enum _mmc_extended_csd_flags +{ + kMMC_ExtCsdExtPartitionSupport = (1 << 0U), /*!< partitioning support[160] */ + kMMC_ExtCsdEnhancePartitionSupport = (1 << 1U), /*!< partitioning support[160] */ + kMMC_ExtCsdPartitioningSupport = (1 << 2U), /*!< partitioning support[160] */ + kMMC_ExtCsdPrgCIDCSDInDDRModeSupport = (1 << 3U), /*!< CMD26 and CMD27 are support dual data rate [130]*/ + kMMC_ExtCsdBKOpsSupport = (1 << 4U), /*!< background operation feature support [502]*/ + kMMC_ExtCsdDataTagSupport = (1 << 5U), /*!< data tag support[499]*/ + kMMC_ExtCsdModeOperationCodeSupport = (1 << 6U), /*!< mode operation code support[493]*/ +} mmc_extended_csd_flags_t; + +/*! @brief MMC card boot mode */ +enum _mmc_boot_mode +{ + kMMC_BootModeNormal = 0U, /*!< Normal boot */ + kMMC_BootModeAlternative = 1U, /*!< Alternative boot */ +}; + +/*! @brief The length of Extended CSD register, unit as bytes. */ +#define MMC_EXTENDED_CSD_BYTES (512U) + +/*! @brief MMC card default relative address */ +#define MMC_DEFAULT_RELATIVE_ADDRESS (2U) + +/*! @brief SD card product name length united as bytes. */ +#define SD_PRODUCT_NAME_BYTES (5U) + +/*! @brief sdio card FBR register */ +typedef struct _sdio_fbr +{ + uint8_t flags; /*!< current io flags */ + uint8_t ioStdFunctionCode; /*!< current io standard function code */ + uint8_t ioExtFunctionCode; /*!< current io extended function code*/ + uint32_t ioPointerToCIS; /*!< current io pointer to CIS */ + uint32_t ioPointerToCSA; /*!< current io pointer to CSA*/ + uint16_t ioBlockSize; /*!< current io block size */ +} sdio_fbr_t; + +/*! @brief sdio card common CIS */ +typedef struct _sdio_common_cis +{ + /* manufacturer identification string tuple */ + uint16_t mID; /*!< manufacturer code */ + uint16_t mInfo; /*!< manufacturer information */ + + /*function identification tuple */ + uint8_t funcID; /*!< function ID */ + + /* function extension tuple */ + uint16_t fn0MaxBlkSize; /*!< function 0 max block size */ + uint8_t maxTransSpeed; /*!< max data transfer speed for all function */ + +} sdio_common_cis_t; + +/*! @brief sdio card function CIS */ +typedef struct _sdio_func_cis +{ + /*function identification tuple */ + uint8_t funcID; /*!< function ID */ + + /* function extension tuple */ + uint8_t funcInfo; /*!< function info */ + uint8_t ioVersion; /*!< level of application specification this io support */ + uint32_t cardPSN; /*!< product serial number */ + uint32_t ioCSASize; /*!< avaliable CSA size for io */ + uint8_t ioCSAProperty; /*!< CSA property */ + uint16_t ioMaxBlockSize; /*!< io max transfer data size */ + uint32_t ioOCR; /*!< io ioeration condition */ + uint8_t ioOPMinPwr; /*!< min current in operation mode */ + uint8_t ioOPAvgPwr; /*!< average current in operation mode */ + uint8_t ioOPMaxPwr; /*!< max current in operation mode */ + uint8_t ioSBMinPwr; /*!< min current in standby mode */ + uint8_t ioSBAvgPwr; /*!< average current in standby mode */ + uint8_t ioSBMaxPwr; /*!< max current in standby mode */ + + uint16_t ioMinBandWidth; /*!< io min transfer bandwidth */ + uint16_t ioOptimumBandWidth; /*!< io optimum transfer bandwidth */ + uint16_t ioReadyTimeout; /*!< timeout value from enalbe to ready */ + uint16_t ioHighCurrentAvgCurrent; /*!< the average peak current (mA) + when IO operating in high current mode */ + uint16_t ioHighCurrentMaxCurrent; /*!< the max peak current (mA) + when IO operating in high current mode */ + uint16_t ioLowCurrentAvgCurrent; /*!< the average peak current (mA) + when IO operating in lower current mode */ + uint16_t ioLowCurrentMaxCurrent; /*!< the max peak current (mA) + when IO operating in lower current mode */ +} sdio_func_cis_t; + +/*! @brief SD AU start value */ +#define SD_AU_START_VALUE (1U) +/*! @brief SD UHS AU start value */ +#define SD_UHS_AU_START_VALUE (7U) + +/*! @brief SD card status */ +typedef struct _sd_status +{ + uint8_t busWidth; /*!< current buswidth */ + uint8_t secureMode; /*!< secured mode */ + uint16_t cardType; /*!< sdcard type */ + uint32_t protectedSize; /*!< size of protected area */ + uint8_t speedClass; /*!< speed class of card */ + uint8_t performanceMove; /*!< Performance of move indicated by 1[MB/S]step */ + uint8_t auSize; /*!< size of AU */ + uint16_t eraseSize; /*!< number of AUs to be erased at a time */ + uint8_t eraseTimeout; /*!< timeout value for erasing areas specified by UNIT OF ERASE AU */ + uint8_t eraseOffset; /*!< fixed offset value added to erase time */ + uint8_t uhsSpeedGrade; /*!< speed grade for UHS mode */ + uint8_t uhsAuSize; /*!< size of AU for UHS mode */ +} sd_status_t; + +/*! @brief SD card CID register */ +typedef struct _sd_cid +{ + uint8_t manufacturerID; /*!< Manufacturer ID [127:120] */ + uint16_t applicationID; /*!< OEM/Application ID [119:104] */ + uint8_t productName[SD_PRODUCT_NAME_BYTES]; /*!< Product name [103:64] */ + uint8_t productVersion; /*!< Product revision [63:56] */ + uint32_t productSerialNumber; /*!< Product serial number [55:24] */ + uint16_t manufacturerData; /*!< Manufacturing date [19:8] */ +} sd_cid_t; + +/*! @brief SD card CSD register */ +typedef struct _sd_csd +{ + uint8_t csdStructure; /*!< CSD structure [127:126] */ + uint8_t dataReadAccessTime1; /*!< Data read access-time-1 [119:112] */ + uint8_t dataReadAccessTime2; /*!< Data read access-time-2 in clock cycles (NSAC*100) [111:104] */ + uint8_t transferSpeed; /*!< Maximum data transfer rate [103:96] */ + uint16_t cardCommandClass; /*!< Card command classes [95:84] */ + uint8_t readBlockLength; /*!< Maximum read data block length [83:80] */ + uint16_t flags; /*!< Flags in _sd_csd_flag */ + uint32_t deviceSize; /*!< Device size [73:62] */ + /* Following fields from 'readCurrentVddMin' to 'deviceSizeMultiplier' exist in CSD version 1 */ + uint8_t readCurrentVddMin; /*!< Maximum read current at VDD min [61:59] */ + uint8_t readCurrentVddMax; /*!< Maximum read current at VDD max [58:56] */ + uint8_t writeCurrentVddMin; /*!< Maximum write current at VDD min [55:53] */ + uint8_t writeCurrentVddMax; /*!< Maximum write current at VDD max [52:50] */ + uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */ + + uint8_t eraseSectorSize; /*!< Erase sector size [45:39] */ + uint8_t writeProtectGroupSize; /*!< Write protect group size [38:32] */ + uint8_t writeSpeedFactor; /*!< Write speed factor [28:26] */ + uint8_t writeBlockLength; /*!< Maximum write data block length [25:22] */ + uint8_t fileFormat; /*!< File format [11:10] */ +} sd_csd_t; + +/*! @brief The bit shift for RATE UNIT field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_RATE_UNIT_SHIFT (0U) +/*! @brief The bit mask for RATE UNIT field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_RATE_UNIT_MASK (0x07U) +/*! @brief The bit shift for TIME VALUE field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_TIME_VALUE_SHIFT (2U) +/*! @brief The bit mask for TIME VALUE field in TRANSFER SPEED */ +#define SD_TRANSFER_SPEED_TIME_VALUE_MASK (0x78U) +/*! @brief Read the value of FREQUENCY UNIT in TRANSFER SPEED field */ +#define SD_RD_TRANSFER_SPEED_RATE_UNIT(x) \ + (((x.transferSpeed) & SD_TRANSFER_SPEED_RATE_UNIT_MASK) >> SD_TRANSFER_SPEED_RATE_UNIT_SHIFT) +/*! @brief Read the value of TIME VALUE in TRANSFER SPEED field */ +#define SD_RD_TRANSFER_SPEED_TIME_VALUE(x) \ + (((x.transferSpeed) & SD_TRANSFER_SPEED_TIME_VALUE_MASK) >> SD_TRANSFER_SPEED_TIME_VALUE_SHIFT) + +/*! @brief SD card SCR register */ +typedef struct _sd_scr +{ + uint8_t scrStructure; /*!< SCR Structure [63:60] */ + uint8_t sdSpecification; /*!< SD memory card specification version [59:56] */ + uint16_t flags; /*!< SCR flags in _sd_scr_flag */ + uint8_t sdSecurity; /*!< Security specification supported [54:52] */ + uint8_t sdBusWidths; /*!< Data bus widths supported [51:48] */ + uint8_t extendedSecurity; /*!< Extended security support [46:43] */ + uint8_t commandSupport; /*!< Command support bits [33:32] 33-support CMD23, 32-support cmd20*/ + uint32_t reservedForManufacturer; /*!< reserved for manufacturer usage [31:0] */ +} sd_scr_t; + +/*! @brief MMC card product name length united as bytes. */ +#define MMC_PRODUCT_NAME_BYTES (6U) +/*! @brief MMC card CID register. */ +typedef struct _mmc_cid +{ + uint8_t manufacturerID; /*!< Manufacturer ID */ + uint16_t applicationID; /*!< OEM/Application ID */ + uint8_t productName[MMC_PRODUCT_NAME_BYTES]; /*!< Product name */ + uint8_t productVersion; /*!< Product revision */ + uint32_t productSerialNumber; /*!< Product serial number */ + uint8_t manufacturerData; /*!< Manufacturing date */ +} mmc_cid_t; + +/*! @brief MMC card CSD register. */ +typedef struct _mmc_csd +{ + uint8_t csdStructureVersion; /*!< CSD structure [127:126] */ + uint8_t systemSpecificationVersion; /*!< System specification version [125:122] */ + uint8_t dataReadAccessTime1; /*!< Data read access-time 1 [119:112] */ + uint8_t dataReadAccessTime2; /*!< Data read access-time 2 in CLOCK cycles (NSAC*100) [111:104] */ + uint8_t transferSpeed; /*!< Max. bus clock frequency [103:96] */ + uint16_t cardCommandClass; /*!< card command classes [95:84] */ + uint8_t readBlockLength; /*!< Max. read data block length [83:80] */ + uint16_t flags; /*!< Contain flags in _mmc_csd_flag */ + uint16_t deviceSize; /*!< Device size [73:62] */ + uint8_t readCurrentVddMin; /*!< Max. read current @ VDD min [61:59] */ + uint8_t readCurrentVddMax; /*!< Max. read current @ VDD max [58:56] */ + uint8_t writeCurrentVddMin; /*!< Max. write current @ VDD min [55:53] */ + uint8_t writeCurrentVddMax; /*!< Max. write current @ VDD max [52:50] */ + uint8_t deviceSizeMultiplier; /*!< Device size multiplier [49:47] */ + uint8_t eraseGroupSize; /*!< Erase group size [46:42] */ + uint8_t eraseGroupSizeMultiplier; /*!< Erase group size multiplier [41:37] */ + uint8_t writeProtectGroupSize; /*!< Write protect group size [36:32] */ + uint8_t defaultEcc; /*!< Manufacturer default ECC [30:29] */ + uint8_t writeSpeedFactor; /*!< Write speed factor [28:26] */ + uint8_t maxWriteBlockLength; /*!< Max. write data block length [25:22] */ + uint8_t fileFormat; /*!< File format [11:10] */ + uint8_t eccCode; /*!< ECC code [9:8] */ +} mmc_csd_t; + +/*! @brief MMC card Extended CSD register (unit: byte). */ +typedef struct _mmc_extended_csd +{ + /*uint8_t SecureRemoveType;*/ /*!< secure removal type[16]*/ + /*uint8_t enProductStateAware;*/ /*!< product state awareness enablement[17]*/ + /*uint32_t maxPreLoadDataSize;*/ /*!< max preload data size[21-18]*/ + /*uint32_t preLoadDataSize;*/ /*!< pre-load data size[25-22]*/ + /*uint8_t ffuStatus;*/ /*!< FFU status [26]*/ + /*uint8_t modeOperationCode;*/ /*!< mode operation code[29]*/ + /*uint8_t modeConfig;*/ /*!< mode config [30]*/ + /*uint8_t cacheCtrl;*/ /*!< control to turn on/off cache[33]*/ + /*uint8_t pwroffNotify;*/ /*!< power off notification[34]*/ + /*uint8_t packedCmdFailIndex;*/ /*!< packed cmd fail index [35]*/ + /*uint8_t packedCmdStatus;*/ /*!< packed cmd status[36]*/ + /*uint32_t contextConfig[4U];*/ /*!< context configuration[51-37]*/ + /*uint16_t extPartitionAttr;*/ /*!< extended partitions attribut[53-52]*/ + /*uint16_t exceptEventStatus;*/ /*!< exception events status[55-54]*/ + /*uint16_t exceptEventControl;*/ /*!< exception events control[57-56]*/ + /*uint8_t toReleaseAddressedGroup;*/ /*!< number of group to be released[58]*/ + /*uint8_t class6CmdCtrl;*/ /*!< class 6 command control[59]*/ + /*uint8_t intTimeoutEmu;*/ /*!< 1st initiallization after disabling sector size emu[60]*/ + /*uint8_t sectorSize;*/ /*!< sector size[61] */ + /*uint8_t sectorSizeEmu;*/ /*!< sector size emulation[62]*/ + /*uint8_t nativeSectorSize;*/ /*!< native sector size[63]*/ + /*uint8_t periodWakeup;*/ /*!< period wakeup [131]*/ + /*uint8_t tCASESupport;*/ /*!< package case temperature is controlled[132]*/ + /*uint8_t productionStateAware;*/ /*!< production state awareness[133]*/ + /*uint32_t enhanceUsrDataStartAddr;*/ /*!< enhanced user data start addr [139-136]*/ + /*uint32_t enhanceUsrDataSize;*/ /*!< enhanced user data area size[142-140]*/ + /*uint32_t generalPartitionSize[3];*/ /*!< general purpose partition size[154-143]*/ + uint8_t partitionAttribute; /*!< partition attribute [156]*/ + /*uint32_t maxEnhanceAreaSize;*/ /*!< max enhance area size [159-157]*/ + /*uint8_t hpiManagementEn;*/ /*!< HPI management [161]*/ + /*uint8_t writeReliabilityParameter;*/ /*!< write reliability parameter register[166] */ + /*uint8_t writeReliabilitySet;*/ /*!< write reliability setting register[167] */ + /*uint8_t rpmbSizeMult;*/ /*!< RPMB size multi [168]*/ + /*uint8_t fwConfig;*/ /*!< FW configuration[169]*/ + uint8_t userWP; /*!< user write protect register[171] */ + uint8_t bootPartitionWP; /*!< boot write protect register[173]*/ + uint8_t bootWPStatus; /*!< boot write protect status register[174]*/ + uint8_t highDensityEraseGroupDefinition; /*!< High-density erase group definition [175] */ + uint8_t bootDataBusConditions; /*!< Boot bus conditions [177] */ + uint8_t bootConfigProtect; /*!< Boot config protection [178]*/ + uint8_t partitionConfig; /*!< Boot configuration [179] */ + uint8_t eraseMemoryContent; /*!< Erased memory content [181] */ + uint8_t dataBusWidth; /*!< Data bus width mode [183] */ + uint8_t highSpeedTiming; /*!< High-speed interface timing [185] */ + uint8_t powerClass; /*!< Power class [187] */ + uint8_t commandSetRevision; /*!< Command set revision [189] */ + uint8_t commandSet; /*!< Command set [191] */ + uint8_t extendecCsdVersion; /*!< Extended CSD revision [192] */ + uint8_t csdStructureVersion; /*!< CSD structure version [194] */ + uint8_t cardType; /*!< Card Type [196] */ + uint8_t ioDriverStrength; /*!< IO driver strength [197] */ + /*uint8_t OutofInterruptBusyTiming;*/ /*!< out of interrupt busy timing [198] */ + /*uint8_t partitionSwitchTiming;*/ /*!< partition switch timing [199] */ + uint8_t powerClass52MHz195V; /*!< Power Class for 52MHz @ 1.95V [200] */ + uint8_t powerClass26MHz195V; /*!< Power Class for 26MHz @ 1.95V [201] */ + uint8_t powerClass52MHz360V; /*!< Power Class for 52MHz @ 3.6V [202] */ + uint8_t powerClass26MHz360V; /*!< Power Class for 26MHz @ 3.6V [203] */ + uint8_t minimumReadPerformance4Bit26MHz; /*!< Minimum Read Performance for 4bit at 26MHz [205] */ + uint8_t minimumWritePerformance4Bit26MHz; /*!< Minimum Write Performance for 4bit at 26MHz [206] */ + uint8_t minimumReadPerformance8Bit26MHz4Bit52MHz; + /*!< Minimum read Performance for 8bit at 26MHz/4bit @52MHz [207] */ + uint8_t minimumWritePerformance8Bit26MHz4Bit52MHz; + /*!< Minimum Write Performance for 8bit at 26MHz/4bit @52MHz [208] */ + uint8_t minimumReadPerformance8Bit52MHz; /*!< Minimum Read Performance for 8bit at 52MHz [209] */ + uint8_t minimumWritePerformance8Bit52MHz; /*!< Minimum Write Performance for 8bit at 52MHz [210] */ + uint32_t sectorCount; /*!< Sector Count [215:212] */ + /*uint8_t sleepNotificationTimeout;*/ /*!< sleep notification timeout [216]*/ + uint8_t sleepAwakeTimeout; /*!< Sleep/awake timeout [217] */ + /*uint8_t productionStateAwareTimeout;*/ /*!< Production state awareness timeout [218]*/ + uint8_t sleepCurrentVCCQ; /*!< Sleep current (VCCQ) [219] */ + uint8_t sleepCurrentVCC; /*!< Sleep current (VCC) [220] */ + uint8_t highCapacityWriteProtectGroupSize; /*!< High-capacity write protect group size [221] */ + uint8_t reliableWriteSectorCount; /*!< Reliable write sector count [222] */ + uint8_t highCapacityEraseTimeout; /*!< High-capacity erase timeout [223] */ + uint8_t highCapacityEraseUnitSize; /*!< High-capacity erase unit size [224] */ + uint8_t accessSize; /*!< Access size [225] */ + /*uint8_t secureTrimMultiplier;*/ /*!< secure trim multiplier[229]*/ + /*uint8_t secureEraseMultiplier;*/ /*!< secure erase multiplier[230]*/ + /*uint8_t secureFeatureSupport;*/ /*!< secure feature support[231]*/ + /*uint32_t trimMultiplier;*/ /*!< trim multiplier[232]*/ + uint8_t minReadPerformance8bitAt52MHZDDR; /*!< Minimum read performance for 8bit at DDR 52MHZ[234]*/ + uint8_t minWritePerformance8bitAt52MHZDDR; /*!< Minimum write performance for 8bit at DDR 52MHZ[235]*/ + uint8_t powerClass200MHZVCCQ130VVCC360V; /*!< power class for 200MHZ, at VCCQ= 1.3V,VCC=3.6V[236]*/ + uint8_t powerClass200MHZVCCQ195VVCC360V; /*!< power class for 200MHZ, at VCCQ= 1.95V,VCC=3.6V[237]*/ + uint8_t powerClass52MHZDDR195V; /*!< power class for 52MHZ,DDR at Vcc 1.95V[238]*/ + uint8_t powerClass52MHZDDR360V; /*!< power class for 52MHZ,DDR at Vcc 3.6V[239]*/ + /*uint8_t iniTimeoutAP;*/ /*!< 1st initialization time after partitioning[241]*/ + /*uint32_t correctPrgSectorNum;*/ /*!< correct prg sectors number[245-242]*/ + /*uint8_t bkOpsStatus;*/ /*!< background operations status[246]*/ + /*uint8_t powerOffNotifyTimeout;*/ /*!< power off notification timeout[247]*/ + /*uint8_t genericCMD6Timeout;*/ /*!< generic CMD6 timeout[248]*/ + uint32_t cacheSize; /*!< cache size[252-249]*/ + uint8_t powerClass200MHZDDR360V; /*!< power class for 200MHZ, DDR at VCC=2.6V[253]*/ + /*uint32_t fwVer[2U];*/ /*!< fw VERSION [261-254]*/ + /*uint16_t deviceVer;*/ /*!< device version[263-262]*/ + /*uint8_t optimalTrimSize;*/ /*!< optimal trim size[264]*/ + /*uint8_t optimalWriteSize;*/ /*!< optimal write size[265]*/ + /*uint8_t optimalReadSize;*/ /*!< optimal read size[266]*/ + /*uint8_t preEolInfo;*/ /*!< pre EOL information[267]*/ + /*uint8_t deviceLifeTimeEstimationA;*/ /*!< device life time estimation typeA[268]*/ + /*uint8_t deviceLifeTimeEstimationB;*/ /*!< device life time estimation typeB[269]*/ + /*uint32_t correctPrgFWSectorNum;*/ /*!< number of FW sectors correctly programmed[305-302]*/ + /*uint32_t ffuArg;*/ /*!< FFU argument[490-487]*/ + /*uint8_t operationCodeTimeout;*/ /*!< operation code timeout[491]*/ + /*uint8_t supportMode;*/ /*!< support mode [493]*/ + uint8_t extPartitionSupport; /*!< extended partition attribute support[494]*/ + /*uint8_t largeUnitSize;*/ /*!< large unit size[495]*/ + /*uint8_t contextManageCap;*/ /*!< context management capability[496]*/ + /*uint8_t tagResourceSize;*/ /*!< tag resource size[497]*/ + /*uint8_t tagUnitSize;*/ /*!< tag unit size[498]*/ + /*uint8_t maxPackedWriteCmd;*/ /*!< max packed write cmd[500]*/ + /*uint8_t maxPackedReadCmd;*/ /*!< max packed read cmd[501]*/ + /*uint8_t hpiFeature;*/ /*!< HPI feature[503]*/ + uint8_t supportedCommandSet; /*!< Supported Command Sets [504] */ + /*uint8_t extSecurityCmdError;*/ /*!< extended security commands error[505]*/ +} mmc_extended_csd_t; + +/*! @brief The bit shift for COMMAND SET field in SWITCH command. */ +#define MMC_SWITCH_COMMAND_SET_SHIFT (0U) +/*! @brief The bit mask for COMMAND set field in SWITCH command. */ +#define MMC_SWITCH_COMMAND_SET_MASK (0x00000007U) +/*! @brief The bit shift for VALUE field in SWITCH command */ +#define MMC_SWITCH_VALUE_SHIFT (8U) +/*! @brief The bit mask for VALUE field in SWITCH command */ +#define MMC_SWITCH_VALUE_MASK (0x0000FF00U) +/*! @brief The bit shift for BYTE INDEX field in SWITCH command */ +#define MMC_SWITCH_BYTE_INDEX_SHIFT (16U) +/*! @brief The bit mask for BYTE INDEX field in SWITCH command */ +#define MMC_SWITCH_BYTE_INDEX_MASK (0x00FF0000U) +/*! @brief The bit shift for ACCESS MODE field in SWITCH command */ +#define MMC_SWITCH_ACCESS_MODE_SHIFT (24U) +/*! @brief The bit mask for ACCESS MODE field in SWITCH command */ +#define MMC_SWTICH_ACCESS_MODE_MASK (0x03000000U) + +/*! @brief MMC Extended CSD configuration. */ +typedef struct _mmc_extended_csd_config +{ + mmc_command_set_t commandSet; /*!< Command set */ + uint8_t ByteValue; /*!< The value to set */ + uint8_t ByteIndex; /*!< The byte index in Extended CSD(mmc_extended_csd_index_t) */ + mmc_extended_csd_access_mode_t accessMode; /*!< Access mode */ +} mmc_extended_csd_config_t; + +/*! @brief MMC card boot configuration definition. */ +typedef struct _mmc_boot_config +{ + bool enableBootAck; /*!< Enable boot ACK */ + mmc_boot_partition_enable_t bootPartition; /*!< Boot partition */ + + mmc_boot_timing_mode_t bootTimingMode; /*!< boot mode */ + mmc_data_bus_width_t bootDataBusWidth; /*!< Boot data bus width */ + bool retainBootbusCondition; /*!< If retain boot bus width and boot mode conditions */ + + bool pwrBootConfigProtection; /*!< Disable the change of boot configuration register bits from at this point + until next power cycle or next H/W reset operation */ + bool premBootConfigProtection; /*!< Disable the change of boot configuration register bits permanently */ + + mmc_boot_partition_wp_t bootPartitionWP; /*!< boot partition write protect configurations */ + +} mmc_boot_config_t; + +#endif /* _FSL_SDMMC_SPEC_H_ */ diff --git a/target/TARGET_NXP/sdio_device.c b/target/TARGET_NXP/sdio_device.c new file mode 100644 index 0000000..0da019f --- /dev/null +++ b/target/TARGET_NXP/sdio_device.c @@ -0,0 +1,180 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "fsl_sd.h" +#include "pinmap.h" +#include "sdio_device.h" + +/* Array of SD peripheral base address. */ +static SDIF_Type *const sd_addrs[] = SDIF_BASE_PTRS; +static sd_card_t g_sd; + +extern void sdio_clock_setup(void); + +/** + * @brief Initializes the SD card device. + * @retval SD status + */ +uint8_t SDIO_Init(void) +{ + uint32_t reg; + + /*! @brief SDMMC host detect card configuration */ + sdmmchost_detect_card_t s_sdCardDetect = { + .cdType = kSDMMCHOST_DetectCardByGpioCD, + .cdTimeOut_ms = (~0U), + }; + + sdio_clock_setup(); + + /* SD POW_EN */ + pin_function(P0_9, 2); + pin_mode(P0_9, PullNone); + + /* SD DAT3 */ + pin_function(P1_0, 2); + pin_mode(P1_0, PullNone); + reg = IOCON->PIO[1][0]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[1][0] = reg; + + /* SD DAT2 */ + pin_function(P0_31, 2); + pin_mode(P0_31, PullNone); + reg = IOCON->PIO[0][31]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][31] = reg; + + /* SD DAT1 */ + pin_function(P0_25, 2); + pin_mode(P0_25, PullNone); + reg = IOCON->PIO[0][25]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][25] = reg; + + /* SD DAT0 */ + pin_function(P0_24, 2); + pin_mode(P0_24, PullNone); + reg = IOCON->PIO[0][24]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][24] = reg; + + /* SD CLK */ + pin_function(P0_7, 2); + pin_mode(P0_7, PullNone); + reg = IOCON->PIO[0][7]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][7] = reg; + + /* SD CMD */ + pin_function(P0_8, 2); + pin_mode(P0_8, PullNone); + reg = IOCON->PIO[0][8]; + reg |= IOCON_PIO_SLEW_MASK; + IOCON->PIO[0][8] = reg; + + g_sd.host.base = SD_HOST_BASEADDR; + g_sd.host.sourceClock_Hz = SD_HOST_CLK_FREQ; + /* card detect type */ + g_sd.usrParam.cd = &s_sdCardDetect; +#if defined DEMO_SDCARD_POWER_CTRL_FUNCTION_EXIST + g_sd.usrParam.pwr = &s_sdCardPwrCtrl; +#endif + + /* SD host init function */ + if (SD_Init(&g_sd) != kStatus_Success) { + return MSD_ERROR; + } + + return MSD_OK; +} + +/** + * @brief DeInitializes the SD card device. + * @retval SD status + */ +uint8_t SDIO_DeInit(void) +{ + SD_Deinit(&g_sd); + + return MSD_OK; +} + +/** + * @brief Reads block(s) from a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param ReadAddr: Address from where data is to be read + * @param NumOfBlocks: Number of SD blocks to read + * @param Timeout: Timeout for read operation + * @retval SD status + */ +uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_ReadBlocks(&g_sd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != kStatus_Success) { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Writes block(s) to a specified address in an SD card, in polling mode. + * @param pData: Pointer to the buffer that will contain the data to transmit + * @param WriteAddr: Address from where data is to be written + * @param NumOfBlocks: Number of SD blocks to write + * @param Timeout: Timeout for write operation + * @retval SD status + */ +uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_WriteBlocks(&g_sd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != kStatus_Success) { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +/** + * @brief Erases the specified memory area of the given SD card. + * @param StartAddr: Start byte address + * @param NumOfBlocks: Number of SD blocks to erase + * @retval SD status + */ +uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t NumOfBlocks) +{ + uint8_t sd_state = MSD_OK; + + if (SD_EraseBlocks(&g_sd, StartAddr, NumOfBlocks) != kStatus_Success) + { + sd_state = MSD_ERROR; + } + + return sd_state; +} + +uint32_t SDIO_GetBlockSize(void) +{ + return g_sd.blockSize; +} + +uint32_t SDIO_GetBlockCount(void) +{ + return g_sd.blockCount; +} + diff --git a/target/TARGET_NXP/sdio_device.h b/target/TARGET_NXP/sdio_device.h new file mode 100644 index 0000000..db099f8 --- /dev/null +++ b/target/TARGET_NXP/sdio_device.h @@ -0,0 +1,52 @@ +/* mbed Microcontroller Library + * Copyright (c) 2019 ARM Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __MBED_SDIO_DEVICE_H +#define __MBED_SDIO_DEVICE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Exported constants */ +/* + * @brief SD status structure definition + */ +#define MSD_OK ((uint8_t)0x00) +#define MSD_ERROR ((uint8_t)0x01) + +/* + * @brief SD transfer state definition + */ +#define SD_TRANSFER_OK ((uint8_t)0x00) +#define SD_TRANSFER_BUSY ((uint8_t)0x01) + +/* Exported functions */ +uint8_t SDIO_Init(void); +uint8_t SDIO_DeInit(void); +uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t EndAddr); +uint32_t SDIO_GetBlockSize(void); +uint32_t SDIO_GetBlockCount(void); + +#ifdef __cplusplus +} +#endif + +#endif + From b89250529149e92d8acf10f7f5b9b0becfa2af41 Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 17:58:00 +0200 Subject: [PATCH 19/23] Restructure NXP implementation --- target/TARGET_NXP/sdio_device.h | 52 ------------------- .../TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c | 0 .../TARGET_LPC55S69/drivers}/board.h | 0 .../TARGET_LPC55S69/drivers}/fsl_sd.c | 0 .../TARGET_LPC55S69/drivers}/fsl_sd.h | 0 .../drivers}/fsl_sdmmc_common.c | 0 .../drivers}/fsl_sdmmc_common.h | 0 .../TARGET_LPC55S69/drivers}/fsl_sdmmc_host.c | 0 .../TARGET_LPC55S69/drivers}/fsl_sdmmc_host.h | 0 .../TARGET_LPC55S69/drivers}/fsl_sdmmc_spec.h | 0 10 files changed, 52 deletions(-) delete mode 100644 target/TARGET_NXP/sdio_device.h rename target/TARGET_NXP/sdio_device.c => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/board.h (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sd.c (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sd.h (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sdmmc_common.c (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sdmmc_common.h (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sdmmc_host.c (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sdmmc_host.h (100%) rename {target/TARGET_NXP => targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers}/fsl_sdmmc_spec.h (100%) diff --git a/target/TARGET_NXP/sdio_device.h b/target/TARGET_NXP/sdio_device.h deleted file mode 100644 index db099f8..0000000 --- a/target/TARGET_NXP/sdio_device.h +++ /dev/null @@ -1,52 +0,0 @@ -/* mbed Microcontroller Library - * Copyright (c) 2019 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __MBED_SDIO_DEVICE_H -#define __MBED_SDIO_DEVICE_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -/* Exported constants */ -/* - * @brief SD status structure definition - */ -#define MSD_OK ((uint8_t)0x00) -#define MSD_ERROR ((uint8_t)0x01) - -/* - * @brief SD transfer state definition - */ -#define SD_TRANSFER_OK ((uint8_t)0x00) -#define SD_TRANSFER_BUSY ((uint8_t)0x01) - -/* Exported functions */ -uint8_t SDIO_Init(void); -uint8_t SDIO_DeInit(void); -uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); -uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); -uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t EndAddr); -uint32_t SDIO_GetBlockSize(void); -uint32_t SDIO_GetBlockCount(void); - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/target/TARGET_NXP/sdio_device.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c similarity index 100% rename from target/TARGET_NXP/sdio_device.c rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c diff --git a/target/TARGET_NXP/board.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/board.h similarity index 100% rename from target/TARGET_NXP/board.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/board.h diff --git a/target/TARGET_NXP/fsl_sd.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c similarity index 100% rename from target/TARGET_NXP/fsl_sd.c rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c diff --git a/target/TARGET_NXP/fsl_sd.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.h similarity index 100% rename from target/TARGET_NXP/fsl_sd.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.h diff --git a/target/TARGET_NXP/fsl_sdmmc_common.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.c similarity index 100% rename from target/TARGET_NXP/fsl_sdmmc_common.c rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.c diff --git a/target/TARGET_NXP/fsl_sdmmc_common.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.h similarity index 100% rename from target/TARGET_NXP/fsl_sdmmc_common.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_common.h diff --git a/target/TARGET_NXP/fsl_sdmmc_host.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.c similarity index 100% rename from target/TARGET_NXP/fsl_sdmmc_host.c rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.c diff --git a/target/TARGET_NXP/fsl_sdmmc_host.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.h similarity index 100% rename from target/TARGET_NXP/fsl_sdmmc_host.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_host.h diff --git a/target/TARGET_NXP/fsl_sdmmc_spec.h b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_spec.h similarity index 100% rename from target/TARGET_NXP/fsl_sdmmc_spec.h rename to targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sdmmc_spec.h From 744451e3b92ee6f9959e54bce583d77af7f3a6fb Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Wed, 27 Mar 2019 18:19:51 +0200 Subject: [PATCH 20/23] Update to "new" API --- .../TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c | 76 ++++++++----------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c index 0da019f..f5f0bd7 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c @@ -15,7 +15,9 @@ */ #include "fsl_sd.h" #include "pinmap.h" -#include "sdio_device.h" +#include "sdio_api.h" + +#if DEVICE_SDIO /* Array of SD peripheral base address. */ static SDIF_Type *const sd_addrs[] = SDIF_BASE_PTRS; @@ -23,11 +25,7 @@ static sd_card_t g_sd; extern void sdio_clock_setup(void); -/** - * @brief Initializes the SD card device. - * @retval SD status - */ -uint8_t SDIO_Init(void) +int sdio_init(void) { uint32_t reg; @@ -101,28 +99,16 @@ uint8_t SDIO_Init(void) return MSD_OK; } -/** - * @brief DeInitializes the SD card device. - * @retval SD status - */ -uint8_t SDIO_DeInit(void) +int sdio_deinit(void) { SD_Deinit(&g_sd); return MSD_OK; } -/** - * @brief Reads block(s) from a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read - * @param Timeout: Timeout for read operation - * @retval SD status - */ -uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; if (SD_ReadBlocks(&g_sd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != kStatus_Success) { sd_state = MSD_ERROR; @@ -131,17 +117,9 @@ uint8_t SDIO_ReadBlocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks return sd_state; } -/** - * @brief Writes block(s) to a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write - * @param Timeout: Timeout for write operation - * @retval SD status - */ -uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; if (SD_WriteBlocks(&g_sd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != kStatus_Success) { sd_state = MSD_ERROR; @@ -150,17 +128,12 @@ uint8_t SDIO_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBloc return sd_state; } -/** - * @brief Erases the specified memory area of the given SD card. - * @param StartAddr: Start byte address - * @param NumOfBlocks: Number of SD blocks to erase - * @retval SD status - */ -uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t NumOfBlocks) +int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) { - uint8_t sd_state = MSD_OK; + int sd_state = MSD_OK; - if (SD_EraseBlocks(&g_sd, StartAddr, NumOfBlocks) != kStatus_Success) + uint32_t blocks = (EndAddr - StartAddr) / g_sd.blockSize; + if (SD_EraseBlocks(&g_sd, StartAddr, blocks) != kStatus_Success) { sd_state = MSD_ERROR; } @@ -168,13 +141,28 @@ uint8_t SDIO_Erase(uint32_t StartAddr, uint32_t NumOfBlocks) return sd_state; } -uint32_t SDIO_GetBlockSize(void) +int sdio_get_card_state(void) { - return g_sd.blockSize; + int sd_state = MSD_OK; + + if (!SD_CheckReadOnly(&g_sd)) { + sd_state = MSD_ERROR; + } + + return sd_state; } -uint32_t SDIO_GetBlockCount(void) +void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) { - return g_sd.blockCount; + CardInfo->CardType = 4; + CardInfo->CardVersion = g_sd.version; + CardInfo->Class = 0; + CardInfo->RelCardAdd = g_sd.relativeAddress; + CardInfo->BlockNbr = g_sd.blockCount; + CardInfo->BlockSize = g_sd.blockSize; + CardInfo->LogBlockNbr = g_sd.blockCount; + CardInfo->LogBlockSize = g_sd.blockSize; } + +#endif // DEVICE_SDIO From a0681324a0b247cd10f14a6043a53c1d810eb631 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Fri, 9 Aug 2019 02:40:19 -0500 Subject: [PATCH 21/23] Fix some warnings (tested on GCC 8) --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 4 ++-- .../TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c | 2 -- .../TARGET_LPC55S69/drivers/fsl_sd.c | 22 ++++++++++++------- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 4 ++-- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 4 ++-- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index 7b4d709..d3acbad 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -104,9 +104,9 @@ int SDIOBlockDevice::init() sdio_get_card_info(&_cardInfo); _is_initialized = true; - debug_if(SD_DBG, "SD initialized: type: %d version: %d class: %d\n", + debug_if(SD_DBG, "SD initialized: type: %lu version: %lu class: %lu\n", _cardInfo.CardType, _cardInfo.CardVersion, _cardInfo.Class); - debug_if(SD_DBG, "SD size: %d MB\n", + debug_if(SD_DBG, "SD size: %lu MB\n", _cardInfo.LogBlockNbr / 2 / 1024); // get sectors count from cardinfo diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c index f5f0bd7..49ce901 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c @@ -19,8 +19,6 @@ #if DEVICE_SDIO -/* Array of SD peripheral base address. */ -static SDIF_Type *const sd_addrs[] = SDIF_BASE_PTRS; static sd_card_t g_sd; extern void sdio_clock_setup(void); diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c index 0cbb8b7..5d586dc 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/drivers/fsl_sd.c @@ -38,7 +38,7 @@ static status_t SD_SendWriteSuccessBlocks(sd_card_t *card, uint32_t *blocks); * @retval kStatus_SDMMC_CardNotSupport Card doesn't support. * @retval kStatus_Success Operate successfully. */ -static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress); +static inline status_t SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress); /*! * @brief Send GO_IDLE command to set the card to be idle state. @@ -47,7 +47,7 @@ static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeA * @retval kStatus_SDMMC_TransferFailed Transfer failed. * @retval kStatus_Success Operate successfully. */ -static status_t inline SD_GoIdle(sd_card_t *card); +static inline status_t SD_GoIdle(sd_card_t *card); /*! * @brief Send STOP_TRANSMISSION command after multiple blocks read/write. @@ -66,7 +66,7 @@ static status_t SD_StopTransmission(sd_card_t *card); * @retval kStatus_SDMMC_TransferFailed Transfer failed. * @retval kStatus_Success Operate successfully. */ -static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize); +static inline status_t SD_SetBlockSize(sd_card_t *card, uint32_t blockSize); /*! * @brief Send GET_RCA command to get card relative address. @@ -288,7 +288,7 @@ static status_t SD_Transfer(sd_card_t *card, SDMMCHOST_TRANSFER *content, uint32 * @retval kStatus_SDMMC_TuningFail tuning fail. * @retval kStatus_SDMMC_TransferFailed transfer fail */ -static status_t inline SD_ExecuteTuning(sd_card_t *card); +static inline status_t SD_ExecuteTuning(sd_card_t *card); /******************************************************************************* * Variables @@ -314,28 +314,28 @@ static uint32_t s_sdAuSizeMap[] = {0, /******************************************************************************* * Code ******************************************************************************/ -static status_t inline SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress) +static inline status_t SD_SendApplicationCmd(sd_card_t *card, uint32_t relativeAddress) { assert(card); return SDMMC_SendApplicationCommand(card->host.base, card->host.transfer, relativeAddress); } -static status_t inline SD_GoIdle(sd_card_t *card) +static inline status_t SD_GoIdle(sd_card_t *card) { assert(card); return SDMMC_GoIdle(card->host.base, card->host.transfer); } -static status_t inline SD_SetBlockSize(sd_card_t *card, uint32_t blockSize) +static inline status_t SD_SetBlockSize(sd_card_t *card, uint32_t blockSize) { assert(card); return SDMMC_SetBlockSize(card->host.base, card->host.transfer, blockSize); } -static status_t inline SD_ExecuteTuning(sd_card_t *card) +static inline status_t SD_ExecuteTuning(sd_card_t *card) { assert(card); @@ -1162,6 +1162,8 @@ static status_t SD_SelectBusTiming(sd_card_t *card) } SDMMC_LOG("\r\nNote: SDR104 mode is not supported by card"); + /* FALLTHROUGH */ + case kSD_TimingDDR50Mode: error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionDDR50); if (error == kStatus_Success) @@ -1174,6 +1176,8 @@ static status_t SD_SelectBusTiming(sd_card_t *card) } SDMMC_LOG("\r\nNote: DDR50 mode is not supported by card"); + /* FALLTHROUGH */ + case kSD_TimingSDR50Mode: error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR50); if (error == kStatus_Success) @@ -1185,6 +1189,8 @@ static status_t SD_SelectBusTiming(sd_card_t *card) } SDMMC_LOG("\r\nNote: SDR50 mode is not supported by card"); + /* FALLTHROUGH */ + case kSD_TimingSDR25HighSpeedMode: error = SD_SelectFunction(card, kSD_GroupTimingMode, kSD_FunctionSDR25HighSpeed); if (error == kStatus_Success) diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index 17aa05a..d242544 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -121,7 +121,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) hdma_sdio_rx.Init.PeriphBurst = DMA_PBURST_INC4; if (HAL_DMA_Init(&hdma_sdio_rx) != HAL_OK) { - error("SDIO DMA Init error at %d in %s", __FILE__, __LINE__); + error("SDIO DMA Init error at %d in %s", __LINE__, __FILE__); } __HAL_LINKDMA(hsd, hdmarx, hdma_sdio_rx); @@ -148,7 +148,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) hdma_sdio_tx.Init.PeriphBurst = DMA_PBURST_INC4; if (HAL_DMA_Init(&hdma_sdio_tx) != HAL_OK) { - error("SDIO DMA Init error at %d in %s", __FILE__, __LINE__); + error("SDIO DMA Init error at %d in %s", __LINE__, __FILE__); } __HAL_LINKDMA(hsd, hdmatx, hdma_sdio_tx); diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index c344de3..6c1b84b 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -120,7 +120,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) hdma_sdmmc_rx.Init.PeriphBurst = DMA_PBURST_INC4; if (HAL_DMA_Init(&hdma_sdmmc_rx) != HAL_OK) { - error("SDMMC DMA Init error at %d in %s", __FILE__, __LINE__); + error("SDMMC DMA Init error at %d in %s", __LINE__, __FILE__); } __HAL_LINKDMA(hsd, hdmarx, hdma_sdmmc_rx); @@ -147,7 +147,7 @@ void HAL_SD_MspInit(SD_HandleTypeDef *hsd) hdma_sdmmc_tx.Init.PeriphBurst = DMA_PBURST_INC4; if (HAL_DMA_Init(&hdma_sdmmc_tx) != HAL_OK) { - error("SDMMC DMA Init error at %d in %s", __FILE__, __LINE__); + error("SDMMC DMA Init error at %d in %s", __LINE__, __FILE__); } __HAL_LINKDMA(hsd, hdmatx, hdma_sdmmc_tx); From c18f61407891400c3300d3d30814afa14c218ab4 Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Fri, 9 Aug 2019 03:16:50 -0500 Subject: [PATCH 22/23] Only wait (and require USTICKER) when DEVICE_SDIO_ASYNC --- .../storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index d3acbad..e09525f 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -17,7 +17,9 @@ #include "sdio_api.h" +#if DEVICE_SDIO_ASYNC #include "us_ticker_api.h" +#endif #include "SDIOBlockDevice.h" #include "platform/mbed_debug.h" @@ -335,6 +337,7 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); unlock(); return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; +#if DEVICE_SDIO_ASYNC } else { uint32_t tickstart = us_ticker_read(); while (sdio_get_card_state() != SD_TRANSFER_OK) { @@ -344,6 +347,7 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; } } +#endif } unlock(); From 19bca26a199f2afb99af6adb8b547f59963bc8fb Mon Sep 17 00:00:00 2001 From: Mathias Brossard Date: Wed, 4 Sep 2019 17:22:22 -0500 Subject: [PATCH 23/23] Remove CamelCase symbols --- .../COMPONENT_SDIO/SDIOBlockDevice.cpp | 169 +++++++++--------- .../COMPONENT_SDIO/SDIOBlockDevice.h | 24 +-- .../blockdevice/COMPONENT_SDIO/mbed_lib.json | 2 +- hal/sdio_api.h | 61 ++++--- .../TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c | 34 ++-- targets/TARGET_STM/TARGET_STM32F4/sdio_api.c | 40 ++--- targets/TARGET_STM/TARGET_STM32F7/sdio_api.c | 40 ++--- 7 files changed, 184 insertions(+), 186 deletions(-) diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp index e09525f..eb88252 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.cpp @@ -31,24 +31,24 @@ using namespace mbed; * defines */ -#define SD_DBG 0 /*!< 1 - Enable debugging */ -#define SD_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */ - -#define SD_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ -#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ -#define SD_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ -#define SD_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ -#define SD_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ -#define SD_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ -#define SD_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */ -#define SD_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */ -#define SD_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */ -#define SD_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */ -#define SD_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */ -#define SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */ -#define SD_BLOCK_DEVICE_ERROR_READBLOCKS -5013 /*!< read data blocks from SD failed */ -#define SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS -5014 /*!< write data blocks to SD failed */ -#define SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS -5015 /*!< erase data blocks to SD failed */ +#define SDIO_DBG 0 /*!< 1 - Enable debugging */ +#define SDIO_CMD_TRACE 0 /*!< 1 - Enable SD command tracing */ + +#define SDIO_BLOCK_DEVICE_ERROR_WOULD_BLOCK -5001 /*!< operation would block */ +#define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED -5002 /*!< unsupported operation */ +#define SDIO_BLOCK_DEVICE_ERROR_PARAMETER -5003 /*!< invalid parameter */ +#define SDIO_BLOCK_DEVICE_ERROR_NO_INIT -5004 /*!< uninitialized */ +#define SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE -5005 /*!< device is missing or not connected */ +#define SDIO_BLOCK_DEVICE_ERROR_WRITE_PROTECTED -5006 /*!< write protected */ +#define SDIO_BLOCK_DEVICE_ERROR_UNUSABLE -5007 /*!< unusable card */ +#define SDIO_BLOCK_DEVICE_ERROR_NO_RESPONSE -5008 /*!< No response from device */ +#define SDIO_BLOCK_DEVICE_ERROR_CRC -5009 /*!< CRC error */ +#define SDIO_BLOCK_DEVICE_ERROR_ERASE -5010 /*!< Erase error: reset/sequence */ +#define SDIO_BLOCK_DEVICE_ERROR_WRITE -5011 /*!< SPI Write error: !SPI_DATA_ACCEPTED */ +#define SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE -5012 /*!< unsupported blocksize, only 512 byte supported */ +#define SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS -5013 /*!< read data blocks from SD failed */ +#define SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS -5014 /*!< write data blocks to SD failed */ +#define SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS -5015 /*!< erase data blocks to SD failed */ #define BLOCK_SIZE_HC 512 /*!< Block size supported for SD card is 512 bytes */ @@ -59,10 +59,10 @@ using namespace mbed; #define SDCARD_V2HC 3 /**< v2.x High capacity SD card */ #define CARD_UNKNOWN 4 /**< Unknown or unsupported card */ -SDIOBlockDevice::SDIOBlockDevice(PinName cardDetect) : _cardDetect(cardDetect), - _is_initialized(0), - _sectors(0), - _init_ref_count(0) +SDIOBlockDevice::SDIOBlockDevice(PinName card_detect) : _card_detect(card_detect), + _is_initialized(0), + _sectors(0), + _init_ref_count(0) { // Only HC block size is supported. _block_size = BLOCK_SIZE_HC; @@ -78,7 +78,7 @@ SDIOBlockDevice::~SDIOBlockDevice() int SDIOBlockDevice::init() { - debug_if(SD_DBG, "init Card...\r\n"); + debug_if(SDIO_DBG, "init Card...\r\n"); lock(); @@ -93,9 +93,9 @@ int SDIOBlockDevice::init() return BD_ERROR_OK; } - if (isPresent() == false) { + if (is_present() == false) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; } int status = sdio_init(); @@ -104,18 +104,18 @@ int SDIOBlockDevice::init() return BD_ERROR_DEVICE_ERROR; } - sdio_get_card_info(&_cardInfo); + sdio_get_card_info(&_card_info); _is_initialized = true; - debug_if(SD_DBG, "SD initialized: type: %lu version: %lu class: %lu\n", - _cardInfo.CardType, _cardInfo.CardVersion, _cardInfo.Class); - debug_if(SD_DBG, "SD size: %lu MB\n", - _cardInfo.LogBlockNbr / 2 / 1024); - - // get sectors count from cardinfo - _sectors = _cardInfo.LogBlockNbr; - if (BLOCK_SIZE_HC != _cardInfo.BlockSize) { + debug_if(SDIO_DBG, "SDIO initialized: type: %lu version: %lu class: %lu\n", + _card_info.card_type, _card_info.card_version, _card_info.card_class); + debug_if(SDIO_DBG, "SDIO size: %lu MB\n", + _card_info.log_block_count / 2 / 1024); + + // get sectors count from card_info + _sectors = _card_info.log_block_count; + if (BLOCK_SIZE_HC != _card_info.block_size) { unlock(); - return SD_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE; + return SDIO_BLOCK_DEVICE_ERROR_UNSUPPORTED_BLOCKSIZE; } unlock(); @@ -124,7 +124,7 @@ int SDIOBlockDevice::init() int SDIOBlockDevice::deinit() { - debug_if(SD_DBG, "deinit Card...\r\n"); + debug_if(SDIO_DBG, "deinit SDIO Card...\r\n"); lock(); if (!_is_initialized) { @@ -153,26 +153,26 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) { int status = 0; lock(); - if (isPresent() == false) { + if (is_present() == false) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; } if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; } if (!is_valid_read(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; } - uint32_t *_buffer = static_cast(buffer); + uint8_t *_buffer = static_cast(buffer); // ReadBlocks uses byte unit address // SDHC and SDXC Cards different addressing is handled in ReadBlocks() - bd_addr_t blockCnt = size / _block_size; + bd_addr_t block_count = size / _block_size; addr = addr / _block_size; #if DEVICE_SDIO_ASYNC @@ -183,14 +183,14 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) // wait until SD ready if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; } } } // receive the data : one block/ multiple blocks is handled in ReadBlocks() - status = sdio_readblocks_async(_buffer, addr, blockCnt); - debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = sdio_read_blocks_async(_buffer, addr, block_count); + debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); if (status == MSD_OK) { // wait until DMA finished @@ -198,7 +198,7 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) while (sdio_read_pending() != SD_TRANSFER_OK) { if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; } } // make sure card is ready @@ -207,21 +207,21 @@ int SDIOBlockDevice::read(void *buffer, bd_addr_t addr, bd_size_t size) // wait until SD ready if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; } } } else { - debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SDIO_DBG, "SDIO read_blocks failed! addr: %lld block_count: %lld \n", addr, block_count); unlock(); - return SD_BLOCK_DEVICE_ERROR_READBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; } #else - status = sdio_readblocks(_buffer, addr, blockCnt); - debug_if(SD_DBG, "ReadBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = sdio_read_blocks(_buffer, addr, block_count); + debug_if(SDIO_DBG, "SDIO read blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); if (status != MSD_OK) { - debug_if(SD_DBG, "ReadBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); - status = SD_BLOCK_DEVICE_ERROR_READBLOCKS; + debug_if(SDIO_DBG, "SDIO read blocks failed! addr: %lld block_count: %lld \n", addr, block_count); + status = SDIO_BLOCK_DEVICE_ERROR_READ_BLOCKS; } #endif @@ -234,26 +234,25 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) int status = 0; lock(); - if (isPresent() == false) { + if (is_present() == false) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; } if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; } if (!is_valid_program(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; } - // HAL layer uses uint32_t for addr/size - uint32_t *_buffer = (uint32_t *)(buffer); + uint8_t *_buffer = (uint8_t *)(buffer); // Get block count - bd_size_t blockCnt = size / _block_size; + bd_size_t block_count = size / _block_size; addr = addr / _block_size; #if DEVICE_SDIO_ASYNC @@ -264,13 +263,13 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) // wait until SD ready if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; } } } - status = sdio_writeblocks_async(_buffer, addr, blockCnt); - debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + status = sdio_write_blocks_async(_buffer, addr, block_count); + debug_if(SDIO_DBG, "SDIO write blocks async dbgtest addr: %lld block_count: %lld \n", addr, block_count); if (status == MSD_OK) { // wait until DMA finished @@ -278,7 +277,7 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) while (sdio_write_pending() != SD_TRANSFER_OK) { if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; } } // make sure card is ready @@ -287,22 +286,22 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) // wait until SD ready if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; } } } else { - debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SDIO_DBG, "SDIO write blocks async failed! addr: %lld block_count: %lld \n", addr, block_count); unlock(); - return SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; } #else - status = sdio_writeblocks(_buffer, addr, blockCnt); + status = sdio_write_blocks(_buffer, addr, block_count); - debug_if(SD_DBG, "WriteBlocks dbgtest addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SDIO_DBG, "SDIO write blocks dbgtest addr: %lld block_count: %lld \n", addr, block_count); if (status != MSD_OK) { - debug_if(SD_DBG, "WriteBlocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); - status = SD_BLOCK_DEVICE_ERROR_WRITEBLOCKS; + debug_if(SDIO_DBG, "SDIO write blocks failed! addr: %lld block_count: %lld \n", addr, block_count); + status = SDIO_BLOCK_DEVICE_ERROR_WRITE_BLOCKS; } #endif @@ -312,31 +311,31 @@ int SDIOBlockDevice::program(const void *buffer, bd_addr_t addr, bd_size_t size) int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) { - debug_if(SD_DBG, "trim Card...\r\n"); + debug_if(SDIO_DBG, "SDIO trim Card...\r\n"); lock(); - if (isPresent() == false) { + if (is_present() == false) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_DEVICE; + return SDIO_BLOCK_DEVICE_ERROR_NO_DEVICE; } if (!_is_initialized) { unlock(); - return SD_BLOCK_DEVICE_ERROR_NO_INIT; + return SDIO_BLOCK_DEVICE_ERROR_NO_INIT; } if (!_is_valid_trim(addr, size)) { unlock(); - return SD_BLOCK_DEVICE_ERROR_PARAMETER; + return SDIO_BLOCK_DEVICE_ERROR_PARAMETER; } - bd_size_t blockCnt = size / _block_size; + bd_size_t block_count = size / _block_size; addr = addr / _block_size; - int status = sdio_erase(addr, blockCnt); + int status = sdio_erase(addr, block_count); if (status != 0) { - debug_if(SD_DBG, "Erase blocks failed! addr: %lld blockCnt: %lld \n", addr, blockCnt); + debug_if(SDIO_DBG, "SDIO erase blocks failed! addr: %lld block_count: %lld \n", addr, block_count); unlock(); - return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS; #if DEVICE_SDIO_ASYNC } else { uint32_t tickstart = us_ticker_read(); @@ -344,7 +343,7 @@ int SDIOBlockDevice::trim(bd_addr_t addr, bd_size_t size) // wait until SD ready if ((us_ticker_read() - tickstart) >= MBED_CONF_SDIO_CMD_TIMEOUT) { unlock(); - return SD_BLOCK_DEVICE_ERROR_ERASEBLOCKS; + return SDIO_BLOCK_DEVICE_ERROR_ERASE_BLOCKS; } } #endif @@ -373,7 +372,7 @@ void SDIOBlockDevice::debug(bool dbg) { } -bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) +bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) const { return ( addr % _erase_size == 0 && @@ -381,10 +380,10 @@ bool SDIOBlockDevice::_is_valid_trim(bd_addr_t addr, bd_size_t size) addr + size <= this->size()); } -bool SDIOBlockDevice::isPresent(void) +bool SDIOBlockDevice::is_present(void) { - if (_cardDetect.is_connected()) { - return (_cardDetect.read() == 0); + if (_card_detect.is_connected()) { + return (_card_detect.read() == 0); } else { return true; } diff --git a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h index a3a1fe8..a73f4a2 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h +++ b/components/storage/blockdevice/COMPONENT_SDIO/SDIOBlockDevice.h @@ -21,13 +21,17 @@ #if DEVICE_SDIO #include "BlockDevice.h" -#include "DigitalIn.h" -#include "PlatformMutex.h" +#include "drivers/DigitalIn.h" +#include "platform/PlatformMutex.h" #include "sdio_api.h" +#ifndef MBED_CONF_SDIO_CD +#define MBED_CONF_SDIO_CD NC +#endif + class SDIOBlockDevice : public mbed::BlockDevice { public: - SDIOBlockDevice(PinName cardDetect = NC); + SDIOBlockDevice(PinName card_detect = MBED_CONF_SDIO_CD); virtual ~SDIOBlockDevice(); /** Initialize a block device * @@ -113,7 +117,7 @@ class SDIOBlockDevice : public mbed::BlockDevice { * * @note check physical present switch. Maybe not support by hardware, then function will always return true. */ - virtual bool isPresent(void); + virtual bool is_present(void); /** Get the BlockDevice class type. * @@ -122,26 +126,24 @@ class SDIOBlockDevice : public mbed::BlockDevice { virtual const char *get_type() const; private: - mbed::DigitalIn _cardDetect; + mbed::DigitalIn _card_detect; bool _is_initialized; bd_size_t _block_size; bd_size_t _erase_size; bd_size_t _sectors; uint32_t _init_ref_count; - SDIO_Cardinfo_t _cardInfo; + sdio_card_info_t _card_info; PlatformMutex _mutex; - virtual void lock() - { + virtual void lock() { _mutex.lock(); } - virtual void unlock() - { + virtual void unlock() { _mutex.unlock(); } - bool _is_valid_trim(bd_addr_t addr, bd_size_t size); + bool _is_valid_trim(bd_addr_t addr, bd_size_t size) const; }; #endif // DEVICE_SDIO diff --git a/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json b/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json index 03a7de6..39a8fa8 100644 --- a/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json +++ b/components/storage/blockdevice/COMPONENT_SDIO/mbed_lib.json @@ -6,7 +6,7 @@ }, "target_overrides": { "DISCO_F469NI": { - "CMD_TIMEOUT": 30000 + "CMD_TIMEOUT": 30000 } } } diff --git a/hal/sdio_api.h b/hal/sdio_api.h index 5fb49e7..480d6a0 100644 --- a/hal/sdio_api.h +++ b/hal/sdio_api.h @@ -1,4 +1,3 @@ - /** \addtogroup hal */ /** @{*/ /* mbed Microcontroller Library @@ -36,15 +35,15 @@ extern "C" */ typedef struct { - uint32_t CardType; /* Specifies the card Type */ - uint32_t CardVersion; /* Specifies the card version */ - uint32_t Class; /* Specifies the class of the card class */ - uint32_t RelCardAdd; /* Specifies the Relative Card Address */ - uint32_t BlockNbr; /* Specifies the Card Capacity in blocks */ - uint32_t BlockSize; /* Specifies one block size in bytes */ - uint32_t LogBlockNbr; /* Specifies the Card logical Capacity in blocks */ - uint32_t LogBlockSize; /* Specifies logical block size in bytes */ -} SDIO_Cardinfo_t; + uint32_t card_type; /* Specifies the card Type */ + uint32_t card_version; /* Specifies the card version */ + uint32_t card_class; /* Specifies the class of the card class */ + uint32_t rel_card_addr; /* Specifies the Relative Card Address */ + uint32_t block_count; /* Specifies the Card Capacity in blocks */ + uint32_t block_size; /* Specifies one block size in bytes */ + uint32_t log_block_count; /* Specifies the Card logical Capacity in blocks */ + uint32_t log_block_size; /* Specifies logical block size in bytes */ +} sdio_card_info_t; /** * @brief SD status structure definition @@ -72,41 +71,41 @@ int sdio_deinit(void); /** * @brief Reads block(s) from a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read + * @param data: Pointer to the buffer that will contain the data to transmit + * @param address: Address from where data is to be read + * @param block_count: Number of SD blocks to read * @retval SD status */ -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count); /** * @brief Writes block(s) to a specified address in an SD card, in polling mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write + * @param data: Pointer to the buffer that will contain the data to transmit + * @param address: Address from where data is to be written + * @param block_count: Number of SD blocks to write * @retval SD status */ -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count); #if DEVICE_SDIO_ASYNC /** * @brief Reads block(s) from a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param ReadAddr: Address from where data is to be read - * @param NumOfBlocks: Number of SD blocks to read + * @param data: Pointer to the buffer that will contain the data to transmit + * @param address: Address from where data is to be read + * @param block_count: Number of SD blocks to read * @retval SD status */ -int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks); +int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count); /** * @brief Writes block(s) to a specified address in an SD card, in DMA mode. - * @param pData: Pointer to the buffer that will contain the data to transmit - * @param WriteAddr: Address from where data is to be written - * @param NumOfBlocks: Number of SD blocks to write + * @param data: Pointer to the buffer that will contain the data to transmit + * @param address: Address from where data is to be written + * @param block_count: Number of SD blocks to write * @retval SD status */ -int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks); +int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count); /** * @brief Check if a DMA operation is pending @@ -130,11 +129,11 @@ int sdio_write_pending(void); /** * @brief Erases the specified memory area of the given SD card. - * @param StartAddr: Start byte address - * @param EndAddr: End byte address + * @param start_address: Start byte address + * @param end_address: End byte address * @retval SD status */ -int sdio_erase(uint32_t StartAddr, uint32_t EndAddr); +int sdio_erase(uint32_t start_address, uint32_t end_address); /** * @brief Gets the current SD card data status. @@ -148,10 +147,10 @@ int sdio_get_card_state(void); /** * @brief Get SD information about specific SD card. - * @param CardInfo: Pointer to HAL_SD_CardInfoTypedef structure + * @param card_info: Pointer to HAL_SD_CardInfoTypedef structure * @retval None */ -void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo); +void sdio_get_card_info(sdio_card_info_t *card_info); /**@}*/ diff --git a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c index 49ce901..03cbb2a 100644 --- a/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c +++ b/targets/TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC55S69/TARGET_M33_NS/sdio_api.c @@ -104,35 +104,34 @@ int sdio_deinit(void) return MSD_OK; } -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (SD_ReadBlocks(&g_sd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != kStatus_Success) { + if (SD_ReadBlocks(&g_sd, data, address, block_count) != kStatus_Success) { sd_state = MSD_ERROR; } return sd_state; } -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (SD_WriteBlocks(&g_sd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != kStatus_Success) { + if (SD_WriteBlocks(&g_sd, data, address, block_count) != kStatus_Success) { sd_state = MSD_ERROR; } return sd_state; } -int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) +int sdio_erase(uint32_t start_address, uint32_t end_address) { int sd_state = MSD_OK; - uint32_t blocks = (EndAddr - StartAddr) / g_sd.blockSize; - if (SD_EraseBlocks(&g_sd, StartAddr, blocks) != kStatus_Success) - { + uint32_t blocks = (end_address - start_address) / g_sd.blockSize; + if (SD_EraseBlocks(&g_sd, start_address, blocks) != kStatus_Success) { sd_state = MSD_ERROR; } @@ -150,17 +149,16 @@ int sdio_get_card_state(void) return sd_state; } -void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) +void sdio_get_card_info(sdio_card_info_t *card_info) { - CardInfo->CardType = 4; - CardInfo->CardVersion = g_sd.version; - CardInfo->Class = 0; - CardInfo->RelCardAdd = g_sd.relativeAddress; - CardInfo->BlockNbr = g_sd.blockCount; - CardInfo->BlockSize = g_sd.blockSize; - CardInfo->LogBlockNbr = g_sd.blockCount; - CardInfo->LogBlockSize = g_sd.blockSize; + card_info->card_type = 4; + card_info->card_version = g_sd.version; + card_info->card_class = 0; + card_info->rel_card_addr = g_sd.relativeAddress; + card_info->block_count = g_sd.blockCount; + card_info->block_size = g_sd.blockSize; + card_info->log_block_count = g_sd.blockCount; + card_info->log_block_size = g_sd.blockSize; } - #endif // DEVICE_SDIO diff --git a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c index d242544..a904714 100644 --- a/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F4/sdio_api.c @@ -311,11 +311,11 @@ int sdio_deinit(void) return sd_state; } -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) + if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)data, address, block_count, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -323,11 +323,11 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) return sd_state; } -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) + if (HAL_SD_WriteBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -337,13 +337,13 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) #if DEVICE_SDIO_ASYNC -int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; /* Read block(s) in DMA transfer mode */ - if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK) + if (HAL_SD_ReadBlocks_DMA(&hsd, data, address, block_count) != HAL_OK) { sd_state = MSD_ERROR; SD_DMA_ReadPendingState = SD_TRANSFER_OK; @@ -352,13 +352,13 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc return sd_state; } -int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; /* Write block(s) in DMA transfer mode */ - if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK) + if (HAL_SD_WriteBlocks_DMA(&hsd, data, address, block_count) != HAL_OK) { sd_state = MSD_ERROR; SD_DMA_WritePendingState = SD_TRANSFER_OK; @@ -369,11 +369,11 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl #endif // DEVICE_SDIO_ASYNC -int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) +int sdio_erase(uint32_t start_address, uint32_t end_address) { int sd_state = MSD_OK; - if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) + if (HAL_SD_Erase(&hsd, start_address, end_address) != HAL_OK) { sd_state = MSD_ERROR; } @@ -386,23 +386,23 @@ int sdio_get_card_state(void) return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } -void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) +void sdio_get_card_info(sdio_card_info_t *card_info) { /* Get SD card Information, copy structure for portability */ HAL_SD_CardInfoTypeDef HAL_CardInfo; HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo); - if (CardInfo) + if (card_info) { - CardInfo->CardType = HAL_CardInfo.CardType; - CardInfo->CardVersion = HAL_CardInfo.CardVersion; - CardInfo->Class = HAL_CardInfo.Class; - CardInfo->RelCardAdd = HAL_CardInfo.RelCardAdd; - CardInfo->BlockNbr = HAL_CardInfo.BlockNbr; - CardInfo->BlockSize = HAL_CardInfo.BlockSize; - CardInfo->LogBlockNbr = HAL_CardInfo.LogBlockNbr; - CardInfo->LogBlockSize = HAL_CardInfo.LogBlockSize; + card_info->card_type = HAL_CardInfo.CardType; + card_info->card_version = HAL_CardInfo.CardVersion; + card_info->card_class = HAL_CardInfo.Class; + card_info->rel_card_addr = HAL_CardInfo.RelCardAdd; + card_info->block_count = HAL_CardInfo.BlockNbr; + card_info->block_size = HAL_CardInfo.BlockSize; + card_info->log_block_count = HAL_CardInfo.LogBlockNbr; + card_info->log_block_size = HAL_CardInfo.LogBlockSize; } } diff --git a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c index 6c1b84b..117eb51 100644 --- a/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c +++ b/targets/TARGET_STM/TARGET_STM32F7/sdio_api.c @@ -310,11 +310,11 @@ int sdio_deinit(void) return sd_state; } -int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_read_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (HAL_SD_ReadBlocks(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) + if (HAL_SD_ReadBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -322,11 +322,11 @@ int sdio_readblocks(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) return sd_state; } -int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_write_blocks(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; - if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, CMD_TIMEOUT) != HAL_OK) + if (HAL_SD_WriteBlocks(&hsd, data, address, block_count, CMD_TIMEOUT) != HAL_OK) { sd_state = MSD_ERROR; } @@ -334,13 +334,13 @@ int sdio_writeblocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) return sd_state; } -int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBlocks) +int sdio_read_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; SD_DMA_ReadPendingState = SD_TRANSFER_BUSY; /* Read block(s) in DMA transfer mode */ - if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)pData, ReadAddr, NumOfBlocks) != HAL_OK) + if (HAL_SD_ReadBlocks_DMA(&hsd, data, address, block_count) != HAL_OK) { sd_state = MSD_ERROR; SD_DMA_ReadPendingState = SD_TRANSFER_OK; @@ -349,13 +349,13 @@ int sdio_readblocks_async(uint32_t *pData, uint32_t ReadAddr, uint32_t NumOfBloc return sd_state; } -int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks) +int sdio_write_blocks_async(uint8_t *data, uint32_t address, uint32_t block_count) { int sd_state = MSD_OK; SD_DMA_WritePendingState = SD_TRANSFER_BUSY; /* Write block(s) in DMA transfer mode */ - if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks) != HAL_OK) + if (HAL_SD_WriteBlocks_DMA(&hsd, data, address, block_count) != HAL_OK) { sd_state = MSD_ERROR; SD_DMA_WritePendingState = SD_TRANSFER_OK; @@ -364,11 +364,11 @@ int sdio_writeblocks_async(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBl return sd_state; } -int sdio_erase(uint32_t StartAddr, uint32_t EndAddr) +int sdio_erase(uint32_t start_address, uint32_t end_address) { int sd_state = MSD_OK; - if (HAL_SD_Erase(&hsd, StartAddr, EndAddr) != HAL_OK) + if (HAL_SD_Erase(&hsd, start_address, end_address) != HAL_OK) { sd_state = MSD_ERROR; } @@ -381,23 +381,23 @@ int sdio_get_card_state(void) return ((HAL_SD_GetCardState(&hsd) == HAL_SD_CARD_TRANSFER) ? SD_TRANSFER_OK : SD_TRANSFER_BUSY); } -void sdio_get_card_info(SDIO_Cardinfo_t *CardInfo) +void sdio_get_card_info(sdio_card_info_t *card_info) { /* Get SD card Information, copy structure for portability */ HAL_SD_CardInfoTypeDef HAL_CardInfo; HAL_SD_GetCardInfo(&hsd, &HAL_CardInfo); - if (CardInfo) + if (card_info) { - CardInfo->CardType = HAL_CardInfo.CardType; - CardInfo->CardVersion = HAL_CardInfo.CardVersion; - CardInfo->Class = HAL_CardInfo.Class; - CardInfo->RelCardAdd = HAL_CardInfo.RelCardAdd; - CardInfo->BlockNbr = HAL_CardInfo.BlockNbr; - CardInfo->BlockSize = HAL_CardInfo.BlockSize; - CardInfo->LogBlockNbr = HAL_CardInfo.LogBlockNbr; - CardInfo->LogBlockSize = HAL_CardInfo.LogBlockSize; + card_info->card_type = HAL_CardInfo.CardType; + card_info->card_version = HAL_CardInfo.CardVersion; + card_info->card_class = HAL_CardInfo.Class; + card_info->rel_card_addr = HAL_CardInfo.RelCardAdd; + card_info->block_count = HAL_CardInfo.BlockNbr; + card_info->block_size = HAL_CardInfo.BlockSize; + card_info->log_block_count = HAL_CardInfo.LogBlockNbr; + card_info->log_block_size = HAL_CardInfo.LogBlockSize; } }