-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Took the work done as part of PR ARMmbed/mbed-os#8634 Signed-off-by: Mahesh Mahadevan <[email protected]>
- Loading branch information
1 parent
e4eac1c
commit 1ca1887
Showing
2 changed files
with
435 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
/* 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 "SDIOBlockDevice.h" | ||
#include "platform/mbed_debug.h" | ||
#include "target/sdio_device.h" | ||
|
||
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 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) | ||
{ | ||
// 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 = SDIO_Init(); | ||
if (BD_ERROR_OK != status) { | ||
unlock(); | ||
return BD_ERROR_DEVICE_ERROR; | ||
} | ||
|
||
_is_initialized = true; | ||
|
||
// get sectors count from cardinfo | ||
_sectors = SDIO_GetBlockCount(); | ||
if (BLOCK_SIZE_HC != SDIO_GetBlockSize()) { | ||
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 = SDIO_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<uint32_t *>(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; | ||
|
||
// receive the data : one block/ multiple blocks is handled in ReadBlocks() | ||
int 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; | ||
} | ||
|
||
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; | ||
|
||
int 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; | ||
} | ||
|
||
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 = SDIO_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; | ||
} | ||
|
||
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; | ||
} | ||
|
||
const char *SDIOBlockDevice::get_type() const | ||
{ | ||
return "SDIO"; | ||
} | ||
|
Oops, something went wrong.