bd: Adopted the block device api in the SDBlockDevice

pull/3762/head
Christopher Haster 2017-01-20 11:55:05 -06:00 committed by Simon Hughes
parent 4633d3129d
commit 03a332c5eb
5 changed files with 373 additions and 173 deletions

View File

@ -58,13 +58,13 @@ public:
* *
* @return 0 on success or a negative error code on failure * @return 0 on success or a negative error code on failure
*/ */
virtual bd_error_t init() = 0; virtual bd_error_t init();
/** Deinitialize a block device /** Deinitialize a block device
* *
* @return 0 on success or a negative error code on failure * @return 0 on success or a negative error code on failure
*/ */
virtual bd_error_t deinit() = 0; virtual bd_error_t deinit();
/** Read blocks from a block device /** Read blocks from a block device
* *
@ -73,7 +73,7 @@ public:
* @param size Size to read in bytes, must be a multiple of read block size * @param size Size to read in bytes, must be a multiple of read block size
* @return 0 on success, negative error code on failure * @return 0 on success, negative error code on failure
*/ */
virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size) = 0; virtual bd_error_t read(void *buffer, bd_addr_t addr, bd_size_t size);
/** Program blocks to a block device /** Program blocks to a block device
* *

View File

@ -116,15 +116,16 @@
/* If the target has no SPI support then SDCard is not supported */ /* If the target has no SPI support then SDCard is not supported */
#ifdef DEVICE_SPI #ifdef DEVICE_SPI
#include "SDFileSystem.h" #include "SDBlockDevice.h"
#include "mbed_debug.h" #include "mbed_debug.h"
#define SD_COMMAND_TIMEOUT 5000 #define SD_COMMAND_TIMEOUT 5000
#define SD_DBG 0 #define SD_DBG 0
SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) : SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs)
FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0) { : _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0)
{
_cs = 1; _cs = 1;
// Set default to 100kHz for initialisation and 1MHz for data transfer // Set default to 100kHz for initialisation and 1MHz for data transfer
@ -132,6 +133,13 @@ SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs,
_transfer_sck = 1000000; _transfer_sck = 1000000;
} }
SDBlockDevice::~SDBlockDevice()
{
if (_is_initialized) {
deinit();
}
}
#define R1_IDLE_STATE (1 << 0) #define R1_IDLE_STATE (1 << 0)
#define R1_ERASE_RESET (1 << 1) #define R1_ERASE_RESET (1 << 1)
#define R1_ILLEGAL_COMMAND (1 << 2) #define R1_ILLEGAL_COMMAND (1 << 2)
@ -150,8 +158,9 @@ SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs,
#define SDCARD_V2 2 #define SDCARD_V2 2
#define SDCARD_V2HC 3 #define SDCARD_V2HC 3
int SDFileSystem::initialise_card() { bd_error_t SDBlockDevice::_initialise_card()
_dbg = SD_DBG; {
_dbg = SD_DBG;
// Set to SCK for initialisation, and clock card with cs = 1 // Set to SCK for initialisation, and clock card with cs = 1
_spi.lock(); _spi.lock();
_spi.frequency(_init_sck); _spi.frequency(_init_sck);
@ -164,36 +173,38 @@ int SDFileSystem::initialise_card() {
// send CMD0, should return with all zeros except IDLE STATE set (bit 0) // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
if (_cmd(0, 0) != R1_IDLE_STATE) { if (_cmd(0, 0) != R1_IDLE_STATE) {
debug_if(_dbg, "No disk, or could not put SD card in to SPI idle state\n"); debug_if(_dbg, "No disk, or could not put SD card in to SPI idle state\n");
return SDCARD_FAIL; return BD_ERROR_NO_DEVICE;
} }
// send CMD8 to determine whther it is ver 2.x // send CMD8 to determine whther it is ver 2.x
int r = _cmd8(); int r = _cmd8();
if (r == R1_IDLE_STATE) { if (r == R1_IDLE_STATE) {
return initialise_card_v2(); return _initialise_card_v2();
} else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) { } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
return initialise_card_v1(); return _initialise_card_v1();
} else { } else {
debug_if(_dbg, "Not in idle state after sending CMD8 (not an SD card?)\n"); debug_if(_dbg, "Not in idle state after sending CMD8 (not an SD card?)\n");
return SDCARD_FAIL; return BD_ERROR_DEVICE_ERROR;
} }
} }
int SDFileSystem::initialise_card_v1() { bd_error_t SDBlockDevice::_initialise_card_v1()
{
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
_cmd(55, 0); _cmd(55, 0);
if (_cmd(41, 0) == 0) { if (_cmd(41, 0) == 0) {
cdv = 512; _block_size = 512;
debug_if(_dbg, "\n\rInit: SEDCARD_V1\n\r"); debug_if(_dbg, "\n\rInit: SEDCARD_V1\n\r");
return SDCARD_V1; return BD_ERROR_OK;
} }
} }
debug_if(_dbg, "Timeout waiting for v1.x card\n"); debug_if(_dbg, "Timeout waiting for v1.x card\n");
return SDCARD_FAIL; return BD_ERROR_DEVICE_ERROR;
} }
int SDFileSystem::initialise_card_v2() { bd_error_t SDBlockDevice::_initialise_card_v2()
{
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) { for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
wait_ms(50); wait_ms(50);
_cmd58(); _cmd58();
@ -201,22 +212,24 @@ int SDFileSystem::initialise_card_v2() {
if (_cmd(41, 0x40000000) == 0) { if (_cmd(41, 0x40000000) == 0) {
_cmd58(); _cmd58();
debug_if(_dbg, "\n\rInit: SDCARD_V2\n\r"); debug_if(_dbg, "\n\rInit: SDCARD_V2\n\r");
cdv = 1; _block_size = 1;
return SDCARD_V2; return BD_ERROR_OK;
} }
} }
debug_if(_dbg, "Timeout waiting for v2.x card\n"); debug_if(_dbg, "Timeout waiting for v2.x card\n");
return SDCARD_FAIL; return BD_ERROR_DEVICE_ERROR;
} }
int SDFileSystem::disk_initialize() { bd_error_t SDBlockDevice::init()
lock(); {
_is_initialized = initialise_card(); _lock.lock();
if (_is_initialized == 0) { bd_error_t err = _initialise_card();
_is_initialized = (err == BD_ERROR_OK);
if (!_is_initialized) {
debug_if(_dbg, "Fail to initialize card\n"); debug_if(_dbg, "Fail to initialize card\n");
unlock(); _lock.unlock();
return 1; return err;
} }
debug_if(_dbg, "init card = %d\n", _is_initialized); debug_if(_dbg, "init card = %d\n", _is_initialized);
_sectors = _sd_sectors(); _sectors = _sd_sectors();
@ -224,85 +237,119 @@ int SDFileSystem::disk_initialize() {
// Set block length to 512 (CMD16) // Set block length to 512 (CMD16)
if (_cmd(16, 512) != 0) { if (_cmd(16, 512) != 0) {
debug_if(_dbg, "Set 512-byte block timed out\n"); debug_if(_dbg, "Set 512-byte block timed out\n");
unlock(); _lock.unlock();
return 1; return BD_ERROR_DEVICE_ERROR;
} }
// Set SCK for data transfer // Set SCK for data transfer
_spi.frequency(_transfer_sck); _spi.frequency(_transfer_sck);
unlock(); _lock.unlock();
return BD_ERROR_OK;
}
bd_error_t SDBlockDevice::deinit()
{
return 0; return 0;
} }
int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count) { bd_error_t SDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
lock(); {
if (!_is_initialized) { if (!is_valid_program(addr, size)) {
unlock(); return BD_ERROR_PARAMETER;
return -1;
} }
for (uint32_t b = block_number; b < block_number + count; b++) { _lock.lock();
if (!_is_initialized) {
_lock.unlock();
return BD_ERROR_NO_INIT;
}
const uint8_t *buffer = static_cast<const uint8_t*>(b);
while (size > 0) {
bd_addr_t block = addr / 512;
// set write address for single block (CMD24) // set write address for single block (CMD24)
if (_cmd(24, b * cdv) != 0) { if (_cmd(24, block * _block_size) != 0) {
unlock(); _lock.unlock();
return 1; return BD_ERROR_DEVICE_ERROR;
} }
// send the data block // send the data block
_write(buffer, 512); _write(buffer, 512);
buffer += 512; buffer += 512;
addr += 512;
size -= 512;
} }
_lock.unlock();
unlock();
return 0; return 0;
} }
int SDFileSystem::disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count) { bd_error_t SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
lock(); {
if (!is_valid_read(addr, size)) {
return BD_ERROR_PARAMETER;
}
_lock.lock();
if (!_is_initialized) { if (!_is_initialized) {
unlock(); _lock.unlock();
return -1; return BD_ERROR_PARAMETER;
} }
for (uint32_t b = block_number; b < block_number + count; b++) { uint8_t *buffer = static_cast<uint8_t *>(b);
while (size > 0) {
bd_addr_t block = addr / 512;
// set read address for single block (CMD17) // set read address for single block (CMD17)
if (_cmd(17, b * cdv) != 0) { if (_cmd(17, block * _block_size) != 0) {
unlock(); _lock.unlock();
return 1; return BD_ERROR_DEVICE_ERROR;
} }
// receive the data // receive the data
_read(buffer, 512); _read(buffer, 512);
buffer += 512; buffer += 512;
addr += 512;
size -= 512;
} }
_lock.unlock();
unlock();
return 0; return 0;
} }
int SDFileSystem::disk_status() { bd_error_t SDBlockDevice::erase(bd_addr_t addr, bd_size_t size)
lock(); {
// FATFileSystem::disk_status() returns 0 when initialized return 0;
int ret = _is_initialized ? 0 : 1;
unlock();
return ret;
} }
int SDFileSystem::disk_sync() { return 0; } bd_size_t SDBlockDevice::get_read_size()
uint32_t SDFileSystem::disk_sectors() { {
lock(); return 512;
uint32_t sectors = _sectors;
unlock();
return sectors;
} }
void SDFileSystem::debug(bool dbg){ bd_size_t SDBlockDevice::get_program_size()
{
return 512;
}
bd_size_t SDBlockDevice::get_erase_size()
{
return 512;
}
bd_size_t SDBlockDevice::size()
{
_lock.lock();
bd_size_t sectors = _sectors;
_lock.unlock();
return 512*sectors;
}
void SDBlockDevice::debug(bool dbg)
{
_dbg = dbg; _dbg = dbg;
} }
// PRIVATE FUNCTIONS // PRIVATE FUNCTIONS
int SDFileSystem::_cmd(int cmd, int arg) { int SDBlockDevice::_cmd(int cmd, int arg) {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
@ -329,7 +376,7 @@ int SDFileSystem::_cmd(int cmd, int arg) {
_spi.unlock(); _spi.unlock();
return -1; // timeout return -1; // timeout
} }
int SDFileSystem::_cmdx(int cmd, int arg) { int SDBlockDevice::_cmdx(int cmd, int arg) {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
@ -357,7 +404,7 @@ int SDFileSystem::_cmdx(int cmd, int arg) {
} }
int SDFileSystem::_cmd58() { int SDBlockDevice::_cmd58() {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
int arg = 0; int arg = 0;
@ -390,7 +437,7 @@ int SDFileSystem::_cmd58() {
return -1; // timeout return -1; // timeout
} }
int SDFileSystem::_cmd8() { int SDBlockDevice::_cmd8() {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
@ -422,7 +469,7 @@ int SDFileSystem::_cmd8() {
return -1; // timeout return -1; // timeout
} }
int SDFileSystem::_read(uint8_t *buffer, uint32_t length) { int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
@ -442,7 +489,7 @@ int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
return 0; return 0;
} }
int SDFileSystem::_write(const uint8_t*buffer, uint32_t length) { int SDBlockDevice::_write(const uint8_t*buffer, uint32_t length) {
_spi.lock(); _spi.lock();
_cs = 0; _cs = 0;
@ -488,7 +535,7 @@ static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
return bits; return bits;
} }
uint32_t SDFileSystem::_sd_sectors() { uint32_t SDBlockDevice::_sd_sectors() {
uint32_t c_size, c_size_mult, read_bl_len; uint32_t c_size, c_size_mult, read_bl_len;
uint32_t block_len, mult, blocknr, capacity; uint32_t block_len, mult, blocknr, capacity;
uint32_t hc_c_size; uint32_t hc_c_size;
@ -515,7 +562,7 @@ uint32_t SDFileSystem::_sd_sectors() {
switch (csd_structure) { switch (csd_structure) {
case 0: case 0:
cdv = 512; _block_size = 512;
c_size = ext_bits(csd, 73, 62); c_size = ext_bits(csd, 73, 62);
c_size_mult = ext_bits(csd, 49, 47); c_size_mult = ext_bits(csd, 49, 47);
read_bl_len = ext_bits(csd, 83, 80); read_bl_len = ext_bits(csd, 83, 80);
@ -525,11 +572,11 @@ uint32_t SDFileSystem::_sd_sectors() {
blocknr = (c_size + 1) * mult; blocknr = (c_size + 1) * mult;
capacity = blocknr * block_len; capacity = blocknr * block_len;
blocks = capacity / 512; blocks = capacity / 512;
debug_if(_dbg, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks); debug_if(_dbg, "\n\rSDBlockDevice\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
break; break;
case 1: case 1:
cdv = 1; _block_size = 1;
hc_c_size = ext_bits(csd, 63, 48); hc_c_size = ext_bits(csd, 63, 48);
blocks = (hc_c_size+1)*1024; blocks = (hc_c_size+1)*1024;
debug_if(_dbg, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks); debug_if(_dbg, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);

View File

@ -0,0 +1,158 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2012 ARM Limited
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef MBED_SD_BLOCK_DEVICE_H
#define MBED_SD_BLOCK_DEVICE_H
/* If the target has no SPI support then SDCard is not supported */
#ifdef DEVICE_SPI
#include "BlockDevice.h"
#include "mbed.h"
/** Access an SD Card using SPI
*
* @code
* #include "mbed.h"
* #include "SDBlockDevice.h"
*
* SDBlockDevice sd(p5, p6, p7, p12); // mosi, miso, sclk, cs
* uint8_t block[512] = "Hello World!\n";
*
* int main() {
* sd.init();
* sd.write(block, 0, 512);
* sd.read(block, 0, 512);
* printf("%s", block);
* sd.deinit();
* }
*/
class SDBlockDevice : public BlockDevice {
public:
/** Lifetime of an SD card
*/
SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs);
virtual ~SDBlockDevice();
/** Initialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t init();
/** Deinitialize a block device
*
* @return 0 on success or a negative error code on failure
*/
virtual bd_error_t 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 bd_error_t 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 bd_error_t program(const void *buffer, bd_addr_t addr, bd_size_t size);
/** Erase blocks on a block device
*
* The state of an erased block is undefined until it has been programmed
*
* @param addr Address of block to begin erasing
* @param size Size to erase in bytes, must be a multiple of erase block size
* @return 0 on success, negative error code on failure
*/
virtual bd_error_t erase(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();
/** 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();
/** Get the size of a eraseable block
*
* @return Size of a eraseable block in bytes
* @note Must be a multiple of the program size
*/
virtual bd_size_t get_erase_size();
/** Get the total size of the underlying device
*
* @return Size of the underlying device in bytes
*/
virtual bd_size_t size();
/** Enable or disable debugging
*
* @param State of debugging
*/
virtual void debug(bool dbg);
private:
int _cmd(int cmd, int arg);
int _cmdx(int cmd, int arg);
int _cmd8();
int _cmd58();
bd_error_t _initialise_card();
bd_error_t _initialise_card_v1();
bd_error_t _initialise_card_v2();
int _read(uint8_t * buffer, uint32_t length);
int _write(const uint8_t *buffer, uint32_t length);
uint32_t _sd_sectors();
uint32_t _sectors;
uint32_t _init_sck;
uint32_t _transfer_sck;
SPI _spi;
DigitalOut _cs;
unsigned _block_size;
bool _is_initialized;
bool _dbg;
Mutex _lock;
};
#endif /* DEVICE_SPI */
#endif /* MBED_SD_BLOCK_DEVICE_H */

View File

@ -1,98 +0,0 @@
/* mbed Microcontroller Library
* Copyright (c) 2006-2012 ARM Limited
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef MBED_SDFILESYSTEM_H
#define MBED_SDFILESYSTEM_H
/* If the target has no SPI support then SDCard is not supported */
#ifdef DEVICE_SPI
#include "mbed.h"
#include "FATFileSystem.h"
#include <stdint.h>
/** Access the filesystem on an SD Card using SPI
*
* @code
* #include "mbed.h"
* #include "SDFileSystem.h"
*
* SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs
*
* int main() {
* FILE *fp = fopen("/sd/myfile.txt", "w");
* fprintf(fp, "Hello World!\n");
* fclose(fp);
* }
*/
class SDFileSystem : public FATFileSystem {
public:
/** Create the File System for accessing an SD Card using SPI
*
* @param mosi SPI mosi pin connected to SD Card
* @param miso SPI miso pin conencted to SD Card
* @param sclk SPI sclk pin connected to SD Card
* @param cs DigitalOut pin used as SD Card chip select
* @param name The name used to access the virtual filesystem
*/
SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name);
virtual int disk_initialize();
virtual int disk_status();
virtual int disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count);
virtual int disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count);
virtual int disk_sync();
virtual uint32_t disk_sectors();
void debug(bool dbg);
protected:
int _cmd(int cmd, int arg);
int _cmdx(int cmd, int arg);
int _cmd8();
int _cmd58();
int initialise_card();
int initialise_card_v1();
int initialise_card_v2();
int _read(uint8_t * buffer, uint32_t length);
int _write(const uint8_t *buffer, uint32_t length);
uint32_t _sd_sectors();
uint32_t _sectors;
void set_init_sck(uint32_t sck) { _init_sck = sck; }
// Note: The highest SPI clock rate is 20 MHz for MMC and 25 MHz for SD
void set_transfer_sck(uint32_t sck) { _transfer_sck = sck; }
uint32_t _init_sck;
uint32_t _transfer_sck;
SPI _spi;
DigitalOut _cs;
int cdv;
int _is_initialized;
bool _dbg;
};
#endif /* DEVICE_SPI */
#endif /* MBED_SDFILESYSTEM_H */

View File

@ -0,0 +1,93 @@
/* 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 "mbed.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include "SDBlockDevice.h"
#include <stdlib.h>
using namespace utest::v1;
#ifndef SD_INSTALLED
#define SD_INSTALLED false
#endif
#ifndef SD_PINS
#if defined(TARGET_K64F)
#define SD_PINS PTE3, PTE1, PTE2, PTE4
#endif
#endif
#if !SD_INSTALLED
#error [NOT_SUPPORTED] SD card required
#endif
#define BLOCK_SIZE 512
uint8_t write_block[BLOCK_SIZE];
uint8_t read_block[BLOCK_SIZE];
// Simple test which read/writes a block
void test_read_write() {
SDBlockDevice bd(SD_PINS);
int err = bd.init();
TEST_ASSERT_EQUAL(0, err);
printf("read size: %llu\r\n", bd.get_read_size());
printf("program size: %llu\r\n", bd.get_program_size());
printf("erase size: %llu\r\n", bd.get_erase_size());
// Fill with random sequence
srand(1);
for (int i = 0; i < BLOCK_SIZE; i++) {
write_block[i] = 0xff & rand();
}
// Write, sync, and read the block
err = bd.write(write_block, 0, BLOCK_SIZE);
TEST_ASSERT_EQUAL(0, err);
err = bd.read(read_block, 0, BLOCK_SIZE);
TEST_ASSERT_EQUAL(0, err);
// Check that the data was unmodified
srand(1);
for (int i = 0; i < BLOCK_SIZE; i++) {
TEST_ASSERT_EQUAL(0xff & rand(), read_block[i]);
}
err = bd.deinit();
TEST_ASSERT_EQUAL(0, err);
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases) {
GREENTEA_SETUP(10, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Testing read write of a block", test_read_write),
};
Specification specification(test_setup, cases);
int main() {
return !Harness::run(specification);
}