Removal of SD card driver (SDBlockDevice module) and related test cases (moved into https://github.com/ARMmbed/sd-driver repository).

pull/3762/head
Simon Hughes 2017-02-14 16:45:25 +00:00
parent a79062f876
commit b8e31c8156
9 changed files with 0 additions and 3560 deletions

View File

@ -1,536 +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.
*
*/
/* The following copyright notice is reproduced from the glibc project
* REF_LICENCE_GLIBC
*
* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
* This file is part of the GNU C Library.
*
* The GNU C Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The GNU C Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the GNU C Library; see the file COPYING.LIB. If
* not, write to the Free Software Foundation, Inc., 675 Mass Ave,
* Cambridge, MA 02139, USA.
*/
/** @file basic.cpp POSIX File API (stdio) test cases
*
* Consult the documentation under the test-case functions for
* a description of the individual test case.
*/
#include "mbed.h"
#include "FATFileSystem.h"
#include "SDBlockDevice.h"
#include "test_env.h"
#include "fsfat_debug.h"
#include "fsfat_test.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
/* retarget.h is included after errno.h so symbols are mapped to
* consistent values for all toolchains */
#include "platform/retarget.h"
using namespace utest::v1;
/* DEVICE_SPI
* This symbol is defined in targets.json if the target has a SPI interface, which is required for SDCard support.
* FSFAT_SDCARD_INSTALLTED
* 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 uncomment the #define FSFAT_SDCARD_INSTALLED directive for the target.
*
* Notes
* The following 2 lines should be instated to perform the tests in this file:
* #define FSFAT_SDCARD_INSTALLED
* #define DEVICE_SPI
*/
#if defined(DEVICE_SPI) && defined(FSFAT_SDCARD_INSTALLED)
#define FSFAT_BASIC_TEST_00 fsfat_basic_test_00
#define FSFAT_BASIC_TEST_01 fsfat_basic_test_01
#define FSFAT_BASIC_TEST_02 fsfat_basic_test_02
#define FSFAT_BASIC_TEST_03 fsfat_basic_test_03
#define FSFAT_BASIC_TEST_04 fsfat_basic_test_04
#define FSFAT_BASIC_MSG_BUF_SIZE 256
static const char *sd_file_path = "/sd/out.txt";
static const char *sd_mount_pt = "sd";
const int FSFAT_BASIC_DATA_SIZE = 256;
static char fsfat_basic_msg_g[FSFAT_BASIC_MSG_BUF_SIZE];
#if defined(TARGET_KL25Z)
SDBlockDevice sd(PTD2, PTD3, PTD1, PTD0);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_KL46Z) || defined(TARGET_KL43Z)
SDBlockDevice sd(PTD6, PTD7, PTD5, PTD4);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_K64F) || defined(TARGET_K66F)
SDBlockDevice sd(PTE3, PTE1, PTE2, PTE4);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_K22F)
SDBlockDevice sd(PTD6, PTD7, PTD5, PTD4);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_K20D50M)
SDBlockDevice sd(PTD2, PTD3, PTD1, PTC2);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_nRF51822)
SDBlockDevice sd(p12, p13, p15, p14);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_NUCLEO_F030R8) || \
defined(TARGET_NUCLEO_F070RB) || \
defined(TARGET_NUCLEO_F072RB) || \
defined(TARGET_NUCLEO_F091RC) || \
defined(TARGET_NUCLEO_F103RB) || \
defined(TARGET_NUCLEO_F302R8) || \
defined(TARGET_NUCLEO_F303RE) || \
defined(TARGET_NUCLEO_F334R8) || \
defined(TARGET_NUCLEO_F401RE) || \
defined(TARGET_NUCLEO_F410RB) || \
defined(TARGET_NUCLEO_F411RE) || \
defined(TARGET_NUCLEO_L053R8) || \
defined(TARGET_NUCLEO_L073RZ) || \
defined(TARGET_NUCLEO_L152RE)
SDBlockDevice sd(D11, D12, D13, D10);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_DISCO_F051R8) || \
defined(TARGET_NUCLEO_L031K6)
SDBlockDevice sd(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_LPC2368)
SDBlockDevice sd(p11, p12, p13, p14);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_LPC11U68)
SDBlockDevice sd(D11, D12, D13, D10);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_LPC1549)
SDBlockDevice sd(D11, D12, D13, D10);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_RZ_A1H)
SDBlockDevice sd(P8_5, P8_6, P8_3, P8_4);
FATFileSystem fs(sd_mount_pt, &sd);
#elif defined(TARGET_LPC11U37H_401)
SDBlockDevice sd(SDMOSI, SDMISO, SDSCLK, SDSSEL);
FATFileSystem fs(sd_mount_pt, &sd);
#else
#error "[NOT SUPPORTED] Instantiate SDBlockDevice sd(p11, p12, p13, p14) with the correct pin specification for target"
#endif
#define FSFAT_BASIC_MSG(_buf, _max_len, _fmt, ...) \
do \
{ \
snprintf((_buf), (_max_len), (_fmt), __VA_ARGS__); \
}while(0);
/** @brief fopen test case
*
* - open a file
* - generate random data items, write the item to the file and store a coy in a buffer for later use.
* - close the file.
* - open the file.
* - read the data items from the file and check they are the same as write.
* - close the file.
*
* @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
*/
static control_t fsfat_basic_test_00()
{
uint8_t data_written[FSFAT_BASIC_DATA_SIZE] = { 0 };
bool read_result = false;
bool write_result = false;
// Fill data_written buffer with random data
// Write these data into the file
FSFAT_FENTRYLOG("%s:entered\n", __func__);
{
printf("SD: Writing ... ");
FILE *f = fopen(sd_file_path, "w");
if (f) {
for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
data_written[i] = rand() % 0XFF;
fprintf(f, "%c", data_written[i]);
}
write_result = true;
fclose(f);
}
printf("[%s]\r\n", write_result ? "OK" : "FAIL");
}
TEST_ASSERT_MESSAGE(write_result == true, "Error: write_result is set to false.");
// Read back the data from the file and store them in data_read
{
printf("SD: Reading data ... ");
FILE *f = fopen(sd_file_path, "r");
if (f) {
read_result = true;
for (int i = 0; i < FSFAT_BASIC_DATA_SIZE; i++) {
uint8_t data = fgetc(f);
if (data != data_written[i]) {
read_result = false;
break;
}
}
fclose(f);
}
printf("[%s]\r\n", read_result ? "OK" : "FAIL");
}
TEST_ASSERT_MESSAGE(read_result == true, "Error: read_result is set to false.");
return CaseNext;
}
/** @brief test-fseek.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
*
* @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
*/
static control_t fsfat_basic_test_01()
{
FILE *fp, *fp1;
int i, j;
int ret = 0;
FSFAT_FENTRYLOG("%s:entered\n", __func__);
fp = fopen (sd_file_path, "w+");
if (fp == NULL) {
printf("errno=%d\n", errno);
TEST_ASSERT_MESSAGE(false, "error");
return CaseNext;
}
for (i = 0; i < 256; i++) {
putc (i, fp);
}
/* FIXME: freopen() should open the specified file closing the first stream. As can be seen from the
* code below, the old file descriptor fp can still be used, and this should not happen.
*/
fp1 = freopen (sd_file_path, "r", fp);
TEST_ASSERT_MESSAGE(fp1 == fp, "Error: cannot open file for reading");
for (i = 1; i <= 255; i++) {
ret = fseek (fp, (long) -i, SEEK_END);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s:Error: fseek() failed (ret=%d).\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
if ((j = getc (fp)) != 256 - i) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: SEEK_END failed (j=%d)\n", __func__, j);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
ret = fseek (fp, (long) i, SEEK_SET);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (ret=%d).\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
if ((j = getc (fp)) != i) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (j=%d).\n", __func__, j);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
}
if ((ret = fseek (fp, (long) i, SEEK_SET))) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_SET (ret=%d).\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
}
if ((ret = fseek (fp, (long) (i >= 128 ? -128 : 128), SEEK_CUR))) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_CUR (ret=%d).\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
}
if ((j = getc (fp)) != (i >= 128 ? i - 128 : i + 128)) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot SEEK_CUR (j=%d).\n", __func__, j);
TEST_ASSERT_MESSAGE(ret == 0, fsfat_basic_msg_g);
}
}
fclose (fp);
remove(sd_file_path);
return CaseNext;
}
/** @brief test_rdwr.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
*
* WARNING: this test does not currently work. See WARNING comments below.
*
* @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
*/
static control_t fsfat_basic_test_02()
{
static const char hello[] = "Hello, world.\n";
static const char replace[] = "Hewwo, world.\n";
static const size_t replace_from = 2, replace_to = 4;
const char *filename = sd_file_path;
char buf[BUFSIZ];
FILE *f;
int lose = 0;
int32_t ret = 0;
char *rets = NULL;
FSFAT_FENTRYLOG("%s:entered\n", __func__);
f = fopen(filename, "w+");
if (f == NULL) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Cannot open file for writing (filename=%s).\n", __func__, filename);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
ret = fputs(hello, f);
if (ret == EOF) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fputs() failed to write string to file (filename=%s, string=%s).\n", __func__, filename, hello);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
rewind(f);
rets = fgets(buf, sizeof(buf), f);
if (rets == NULL) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fgets() failed to get string from file (filename=%s).\n", __func__, filename);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
rets = NULL;
rewind(f);
ret = fputs(buf, f);
if (ret == EOF) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: fputs() failed to write string to file (filename=%s, string=%s).\n", __func__, filename, buf);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
rewind(f);
{
register size_t i;
for (i = 0; i < replace_from; ++i)
{
int c = getc(f);
if (c == EOF)
{
printf("EOF at %u.\n", i);
lose = 1;
break;
}
else if (c != hello[i])
{
printf("Got '%c' instead of '%c' at %u.\n",
(unsigned char) c, hello[i], i);
lose = 1;
break;
}
}
}
/* WARNING: printf("%s: here1. (lose = %d)\n", __func__, lose); */
{
long int where = ftell(f);
if (where == replace_from)
{
register size_t i;
for (i = replace_from; i < replace_to; ++i) {
if (putc(replace[i], f) == EOF) {
printf("putc('%c') got %s at %u.\n",
replace[i], strerror(errno), i);
lose = 1;
break;
}
/* WARNING: The problem seems to be that putc() is not writing the 'w' chars into the file
* printf("%s: here1.5. (char = %c, char as int=%d, ret=%d) \n", __func__, replace[i], (int) replace[i], ret);
*/
}
}
else if (where == -1L)
{
printf("ftell got %s (should be at %u).\n",
strerror(errno), replace_from);
lose = 1;
}
else
{
printf("ftell returns %ld; should be %u.\n", where, replace_from);
lose = 1;
}
}
if (!lose)
{
rewind(f);
memset(buf, 0, BUFSIZ);
if (fgets(buf, sizeof(buf), f) == NULL)
{
printf("fgets got %s.\n", strerror(errno));
lose = 1;
}
else if (strcmp(buf, replace))
{
printf("Read \"%s\" instead of \"%s\".\n", buf, replace);
lose = 1;
}
}
if (lose) {
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: Test Failed. Losing file (filename=%s).\n", __func__, filename);
TEST_ASSERT_MESSAGE(false, fsfat_basic_msg_g);
}
remove(filename);
return CaseNext;
}
/** @brief temptest.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
*
* tmpnam() is currently not implemented
*
* @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
*/
static control_t fsfat_basic_test_03()
{
char *fn = NULL;
FSFAT_FENTRYLOG("%s:entered\n", __func__);
fn = tmpnam((char *) NULL);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: appeared to generate a filename when function is not implemented.\n", __func__);
TEST_ASSERT_MESSAGE(fn == NULL, fsfat_basic_msg_g);
return CaseNext;
}
static bool fsfat_basic_fileno_check(const char *name, FILE *stream, int fd)
{
/* ARMCC stdio.h currently does not define fileno() */
#ifndef TOOLCHAIN_ARM_STD
int sfd = fileno (stream);
FSFAT_DBGLOG("(fileno (%s) = %d) %c= %d\n", name, sfd, sfd == fd ? '=' : '!', fd);
if (sfd == fd) {
return true;
} else {
return false;
}
#else
/* For ARMCC behave as though test had passed. */
return true;
#endif /* TOOLCHAIN_ARM_STD */
}
/* defines for next test case */
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef STDERR_FILENO
#define STDERR_FILENO 2
#endif
/** @brief tst-fileno.c test ported from glibc project. See the licence at REF_LICENCE_GLIBC.
*
* WARNING: this test does not currently work. See WARNING comments below.
*
*
* @return on success returns CaseNext to continue to next test case, otherwise will assert on errors.
*/
static control_t fsfat_basic_test_04()
{
int ret = -1;
ret = fsfat_basic_fileno_check("stdin", stdin, STDIN_FILENO);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stdin does not have expected file number (expected=%d, fileno=%d.\n", __func__, stdin, fileno(stdin));
TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
ret = fsfat_basic_fileno_check("stdout", stdout, STDOUT_FILENO);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stdout does not have expected file number (expected=%d, fileno=%d.\n", __func__, stdout, fileno(stdout));
TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
ret = fsfat_basic_fileno_check("stderr", stderr, STDERR_FILENO);
FSFAT_BASIC_MSG(fsfat_basic_msg_g, FSFAT_BASIC_MSG_BUF_SIZE, "%s: Error: stderr does not have expected file number (expected=%d, fileno=%d.\n", __func__, stderr, fileno(stderr));
TEST_ASSERT_MESSAGE(ret == true, fsfat_basic_msg_g);
//*/
return CaseNext;
}
#else
#define FSFAT_BASIC_TEST_00 fsfat_basic_test_dummy
#define FSFAT_BASIC_TEST_01 fsfat_basic_test_dummy
#define FSFAT_BASIC_TEST_02 fsfat_basic_test_dummy
#define FSFAT_BASIC_TEST_03 fsfat_basic_test_dummy
#define FSFAT_BASIC_TEST_04 fsfat_basic_test_dummy
/** @brief fsfat_basic_test_dummy Dummy test case for testing when platform doesnt have an SDCard installed.
*
* @return success always
*/
static control_t fsfat_basic_test_dummy()
{
printf("Null test\n");
return CaseNext;
}
#endif /* defined(DEVICE_SPI) && defined(FSFAT_SDCARD_INSTALLED) */
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(300, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FSFAT_BASIC_TEST_00: fopen()/fgetc()/fprintf()/fclose() test.", FSFAT_BASIC_TEST_00),
Case("FSFAT_BASIC_TEST_01: fopen()/fseek()/fclose() test.", FSFAT_BASIC_TEST_01),
Case("FSFAT_BASIC_TEST_03: tmpnam() test.", FSFAT_BASIC_TEST_03),
Case("FSFAT_BASIC_TEST_04: fileno() test.", FSFAT_BASIC_TEST_04),
/* WARNING: Test case not working but currently not required for PAL support
* Case("FSFAT_BASIC_TEST_02: fopen()/fgets()/fputs()/ftell()/rewind()/remove() test.", FSFAT_BASIC_TEST_02)
*/
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,312 +0,0 @@
# FAT32 Filesystem Support README #
Simon Hughes
20170131
Version 0.03
# Executive Summary
These notes are intended to help the mbed client team adopt the mbedOS POSIX File API support. The notes cover:
- Brief notes on how to setup the mbedOS development environment, including links to other resources.
- How to build the mbedOS test cases.
- How to run the POSIX File API test case.
Note the following:
- The mbedOS FAT32/SDCard support implements a POSIX File API for off-chip, persistent file storage.
- The FAT32/SDCard support was present in mbedOS 2, but was moved to the "unsupported" area of the source tree in mbedOS 5.
This is because there are currently no FAT32/SDCard POSIX API test cases in the public repository, software quality is hence unknown, and the features are therefore unsupported.
- The implementation of new test cases is an active development activity. So far, one test binary (basic.cpp) has been implemented and is available on the mbed-os branch called 'feature-storage'. The test case support
is being enhanced as a matter of urgency.
- The work described here is intended to make the POSIX File API available to the mbed client team before the Christmas holidays.
Further test cases will be implemented and when completed, the work will be merged into the public repository master branch. In the meantime,
the work is available from feature-storage branch.
# Getting Started
This section describes how to build and run the POSIX file API test case. The following steps are covered:
- [Installing the Tools](#installing-the-tools). This section briefly describes how to setup the mbedos development environment.
- [Git Clone the Public mbedOS Repo](#git-clone-the-mbedos-repo). This section describes how to git clone the mbedOS repository containing the FAT32/SDCard and POSIX File API test case of interest.
- [Build the mbedOS Test Cases](#build-the-mbedos-test-cases). This section describes how to build the mbedOS test cases.
- [Insert a microSD Card Into the K64F](#insert-sdcard-into-k64f).This section describes how to format (if required) a microSD card prior to running the tests.
- [Run the POSIX File Test Case](#run-the-posix-file-test-cases).This section describes how to run the POSIX file test case basic.cpp.
### <a name="installing-the-tools"></a> Installing the Tools
The following tools should be installed:
- arm-none-eabi-gcc. See [mbedOS Development Environment Setup Howto Notes][MBED_DEVENV_NOTES] for guidance.
- Python 2.7.9 or later. See [mbedOS Development Environment Setup Howto Notes][MBED_DEVENV_NOTES] for guidance.
- mbed Greentea. This is the mbedOS test tool.
- Git Bash. See [mbedOS Development Environment Setup Howto Notes][MBED_DEVENV_NOTES] for guidance.
- mbed-cli. This is the tool used to make mbedOS application and test builds.
Using a Git Bash terminal, setup mbed-cli in the following way:
simhug01@E107851:/d/demo_area$ git clone git@github.com:/armmbed/mbed-cli
<trace removed>
simhug01@E107851:/d/demo_area$ pushd mbed-cli
simhug01@E107851:/d/demo_area/mbed-cli/$ python.exe setup.py install
simhug01@E107851:/d/demo_area/mbed-cli/$ popd
Using a Git Bash terminal, setup Greentea in the following way:
simhug01@E107851:/d/demo_area$ git clone git@github.com:/armmbed/greentea
<trace removed>
simhug01@E107851:/d/demo_area$ pushd greentea
simhug01@E107851:/d/demo_area/greentea/$ python.exe setup.py install
simhug01@E107851:/d/demo_area/greentea/$ popd
simhug01@E107851:/d/demo_area/$
### <a name="git-clone-the-mbedos-repo"></a> Git Clone the Public mbedOS Repo
Get a clone of public mbedOS repository in the following way
simhug01@E107851:/d/demo_area$ mkdir ex_app1
simhug01@E107851:/d/demo_area$ pushd ex_app1
simhug01@E107851:/d/demo_area/ex_app1$ git clone git@github.com:/armmbed/mbed-os
<trace removed>
simhug01@E107851:/d/demo_area/ex_app1$
### <a name="build-the-mbedos-test-cases"></a> Build the mbedOS Test Cases
Switch to the `feature-storage` branch using the following commands:
simhug01@E107851:/d/demo_area/ex_app1$ pushd mbed-os
simhug01@E107851:/d/demo_area/ex_app1$ git branch
* master
feature-storage
<other branches deleted>
simhug01@E107851:/d/demo_area/ex_app1$ git checkout feature-storage
Switched to branch 'feature-storage'
simhug01@E107851:/d/demo_area/ex_app1$ git branch
master
* feature-storage
<other branches deleted>
simhug01@E107851:/d/demo_area/ex_app1$
Build the test cases for the K64F target using the following commands:
simhug01@E107851:/d/demo_area/ex_app1$ mbed -v test --compile -t GCC_ARM -m K64F -DFSFAT_SDCARD_INSTALLED 2>&1 | tee build_tests_gcc_20161219_1007.txt
<trace removed>
simhug01@E107851:/d/demo_area/ex_app1$
The complete [build log][BUILD-TESTS-GCC-20161219-1007] is available for reference.
### <a name="insert-sdcard-into-k64f"></a> Insert SDCard into K64F
The test cases have been run on a K64F with the following microSDHC cards:
- Kingston 2GB mircoSDHC card.
- Kingston 8GB mircoSDHC card.
- SanDisk 16GB mircoSDHC ultra card.
If the card requires formatting then the following procedure is known to work:
- Insert microSD card into SD adapter in USB stick (or similar) so the microSD card can be insert into windows PC.
- Within file explorer, right click/Format on the USB drive.
- Select FAT32, 4096 cluster size, Quick Format.
- Format the drive.
The microSD card should then be ready for use in the K64F.
### <a name="run-the-posix-file-test-cases"></a> Run the POSIX File Test Case
To setup for running the test cases, complete the following steps:
- Insert a micro SDCard into K64F SDCard socket.
- Connect the K64F development board to your PC using a suitable USB cable.
All tests can be run using the following command:
simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS
<trace removed>
However, it's possible to run a particular test case using the following .json file:
{
"builds": {
"K64F-GCC_ARM": {
"binary_type": "bootable",
"tests": {
"mbed-os-features-storage-feature_storage-tests-fs-fat-basic": {
"binaries": [
{
"path": "BUILD/tests/K64F/GCC_ARM/mbed-os/features/storage/FEATURE_STORAGE/TESTS/fs-fat/basic/basic.bin"
}
]
}
},
"toolchain": "GCC_ARM",
"base_path": "BUILD/tests/K64F/GCC_ARM",
"baud_rate": 9600,
"platform": "K64F"
}
}
}
Store the above text in a file called `ex_app1_fat_basic_spec.json` in the ex_app1 directory. The test can be run using the following command:
simhug01@E107851:/d/demo_area/ex_app1$ mbedgt -VS --test-spec=ex_app1_fat_basic_spec.json 2>&1 | tee run_tests_master_gcc_ex_app2_fat_basic_20161219_1011.txt
<trace removed>
On a successful run, the following table will be shown at the end of the log:
mbedgt: test suite 'mbed-os-features-storage-feature_storage-tests-fs-fat-basic' ..................... OK in 15.86 sec
test case: 'FSFAT_test_00: fopen()/fgetc()/fprintf()/fclose() test.' ......................... OK in 0.90 sec
test case: 'FSFAT_test_01: fopen()/fseek()/fclose() test.' ................................... OK in 0.32 sec
mbedgt: test case summary: 2 passes, 0 failures
mbedgt: all tests finished!
mbedgt: shuffle seed: 0.7720862854
mbedgt: test suite report:
+--------------+---------------+-------------------------------------------------------------+--------+--------------------+-------------+
| target | platform_name | test suite | result | elapsed_time (sec) | copy_method |
+--------------+---------------+-------------------------------------------------------------+--------+--------------------+-------------+
| K64F-GCC_ARM | K64F | mbed-os-features-storage-feature_storage-tests-fs-fat-basic | OK | 15.86 | shell |
+--------------+---------------+-------------------------------------------------------------+--------+--------------------+-------------+
mbedgt: test suite results: 1 OK
mbedgt: test case report:
+--------------+---------------+-------------------------------------------------------------+---------------------------------------------------------+--------+--------+--------+--------------------+
| target | platform_name | test suite | test case | passed | failed | result | elapsed_time (sec) |
+--------------+---------------+-------------------------------------------------------------+---------------------------------------------------------+--------+--------+--------+--------------------+
| K64F-GCC_ARM | K64F | mbed-os-features-storage-feature_storage-tests-fs-fat-basic | FSFAT_test_00: fopen()/fgetc()/fprintf()/fclose() test. | 1 | 0 | OK | 0.9 |
| K64F-GCC_ARM | K64F | mbed-os-features-storage-feature_storage-tests-fs-fat-basic | FSFAT_test_01: fopen()/fseek()/fclose() test. | 1 | 0 | OK | 0.32 |
+--------------+---------------+-------------------------------------------------------------+---------------------------------------------------------+--------+--------+--------+--------------------+
mbedgt: test case results: 2 OK
mbedgt: completed in 16.53 sec
The full [test output log][RUN-TESTS-GCC-20161219-1011] is available for reference.
# POSIX File API
mbedOS supports a subset of the POSIX File API, as outlined below:
- [clearerr()][MAN_CLEARERR].
- STATUS: Basic testing implemented. Working.
- [fclose()][MAN_FCLOSE].
- STATUS: Basic testing implemented. Working.
- [ferror()][MAN_CLEARERR].
- STATUS: Basic testing implemented.
- STATUS: GCC_ARM: Working.
- STATUS: ARMCC: ARMCC has problem with ferror(filep) where filep is NULL. Appears to work for non-NULL pointer.
- [fgetc()][MAN_FGETS].
- STATUS: Basic testing implemented. Working.
- [fgets()][MAN_FGETS].
- STATUS: Basic testing implemented. Working.
- [fputc()][MAN_FPUTS].
- STATUS: Unknown.
- [fputs()][MAN_FPUTS].
- STATUS: Basic testing implemented. Working.
- [fprintf()][MAN_FPRINTF].
- STATUS: Basic testing implemented. Working.
- [fopen()][MAN_FOPEN].
- STATUS: Basic testing implemented. Working.
- [freopen()][MAN_FOPEN].
- STATUS: This is not tested.
- [fread()][MAN_FREAD].
- STATUS: Basic testing implemented. Working.
- STATUS: n x 25kB stress test working.
- [ftell()][MAN_FTELL].
- STATUS: Basic testing implemented. Working.
- [fwrite()][MAN_FWRITE].
- STATUS: Basic testing implemented. Working.
- STATUS: n x 25kB stress test working.
- [fseek()][MAN_FSEEK]
- STATUS: Basic testing implemented. Working.
- [getc()][MAN_FGETS].
- STATUS: Basic testing implemented. Working.
- [gets()][MAN_FGETS].
- STATUS: Unknown.
- [putc()][MAN_FPUTS].
- STATUS: Unknown.
- [puts()][MAN_FPUTS].
- STATUS: Unknown.
- [remove()][MAN_REMOVE]
- STATUS: Basic testing implemented. Working.
- [rewind()][MAN_REWIND].
- STATUS: Basic testing implemented. Working.
- [stat()][MAN_STAT]
- STATUS: Implemented. Working.
- STATUS: Not supported by ARMCC/IAR libc.
- tmpfile()
- STATUS: Not implemented.
- tmpnam()
- STATUS: Not implemented.
Supported directory related operations are as follows:
- closedir().
- STATUS: Implemented. Working.
- mkdir().
- STATUS: Basic testing implemented. Working.
- opendir().
- STATUS: Implemented. Working.
- readdir().
- STATUS: Implemented. Working.
- [remove()][MAN_REMOVE]
- STATUS: Basic testing implemented. Working.
- rename()
- STATUS: Implemented. Not tested.
- rewinddir().
- STATUS: Implemented. Found not to work. Test case not present in repo.
- seekdir()
- STATUS: Implemented. Found not to work. Test case not present in repo.
- telldir().
- STATUS: Implemented. Found not to work. Test case not present in repo.
## errno
Basic errno reporting is supported, tested and known to be working. This will be extended
as further test cases are implemented.
## Miscellaneous Information
The FAT32/SDCard support is at the following location in the source code tree:
<mbed-os_src_root>\features\storage\FEATURE_STORAGE\fs
The FAT32/SDCard test cases are at following locations in the source code tree:
<mbed-os_src_root>\features\storage\FEATURE_STORAGE\TESTS\filesystem\basic\basic.cpp
<mbed-os_src_root>\features\storage\FEATURE_STORAGE\TESTS\filesystem\fopen\fopen.cpp
# Further Reading
* The [mbedOS Development Environment Setup Notes][MBED_DEVENV_NOTES].
* The example mbedOS build log [BUILD-TESTS-GCC-20161219-1007][BUILD-TESTS-GCC-20161219-1007] for reference.
* The example mbedOS test run log [RUN-TESTS-GCC-20161219-1011][RUN-TESTS-GCC-20161219-1011] for reference.
[MBED_DEVENV_NOTES]: https://github.com/ARMmbed/meVo/blob/master/docs/ARM_MBED/TN/ARM_MBED_TN_0017/12-mbed_devenv_setup_how_to_notes.docx
[BUILD-TESTS-GCC-20161219-1007]: https://github.com/ARMmbed/meVo/blob/master/docs/ARM_MBED/TN/ARM_MBED_TN_0017/build_tests_gcc_20161219_1007.txt
[RUN-TESTS-GCC-20161219-1011]: https://github.com/ARMmbed/meVo/blob/master/docs/ARM_MBED/TN/ARM_MBED_TN_0017/run_tests_master_gcc_ex_app2_fat_basic_20161219_1011.txt
[MAN_CLEARERR]: https://linux.die.net/man/3/clearerr
[MAN_FCLOSE]: https://linux.die.net/man/3/fclose
[MAN_FGETS]: https://linux.die.net/man/3/fgets
[MAN_FOPEN]: https://linux.die.net/man/3/fopen
[MAN_FPRINTF]: https://linux.die.net/man/3/fprintf
[MAN_FPUTS]: https://linux.die.net/man/3/fputs
[MAN_FREAD]: https://linux.die.net/man/3/fread
[MAN_FSEEK]: https://linux.die.net/man/3/fseek
[MAN_FWRITE]: https://linux.die.net/man/3/fwrite
[MAN_REMOVE]: https://linux.die.net/man/3/remove
[MAN_REWIND]: https://linux.die.net/man/3/rewind
[MAN_STAT]: https://linux.die.net/man/2/stat
[MAN_FTELL]: https://linux.die.net/man/3/ftell

View File

@ -1,592 +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.
*/
/* Introduction
* ------------
* SD and MMC cards support a number of interfaces, but common to them all
* is one based on SPI. This is the one I'm implmenting because it means
* it is much more portable even though not so performant, and we already
* have the mbed SPI Interface!
*
* The main reference I'm using is Chapter 7, "SPI Mode" of:
* http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
*
* SPI Startup
* -----------
* The SD card powers up in SD mode. The SPI interface mode is selected by
* asserting CS low and sending the reset command (CMD0). The card will
* respond with a (R1) response.
*
* CMD8 is optionally sent to determine the voltage range supported, and
* indirectly determine whether it is a version 1.x SD/non-SD card or
* version 2.x. I'll just ignore this for now.
*
* ACMD41 is repeatedly issued to initialise the card, until "in idle"
* (bit 0) of the R1 response goes to '0', indicating it is initialised.
*
* You should also indicate whether the host supports High Capicity cards,
* and check whether the card is high capacity - i'll also ignore this
*
* SPI Protocol
* ------------
* The SD SPI protocol is based on transactions made up of 8-bit words, with
* the host starting every bus transaction by asserting the CS signal low. The
* card always responds to commands, data blocks and errors.
*
* The protocol supports a CRC, but by default it is off (except for the
* first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
* I'll leave the CRC off I think!
*
* Standard capacity cards have variable data block sizes, whereas High
* Capacity cards fix the size of data block to 512 bytes. I'll therefore
* just always use the Standard Capacity cards with a block size of 512 bytes.
* This is set with CMD16.
*
* You can read and write single blocks (CMD17, CMD25) or multiple blocks
* (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
* the card gets a read command, it responds with a response token, and then
* a data token or an error.
*
* SPI Command Format
* ------------------
* Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
*
* +---------------+------------+------------+-----------+----------+--------------+
* | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
* +---------------+------------+------------+-----------+----------+--------------+
*
* As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
*
* All Application Specific commands shall be preceded with APP_CMD (CMD55).
*
* SPI Response Format
* -------------------
* The main response format (R1) is a status byte (normally zero). Key flags:
* idle - 1 if the card is in an idle state/initialising
* cmd - 1 if an illegal command code was detected
*
* +-------------------------------------------------+
* R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
* +-------------------------------------------------+
*
* R1b is the same, except it is followed by a busy signal (zeros) until
* the first non-zero byte when it is ready again.
*
* Data Response Token
* -------------------
* Every data block written to the card is acknowledged by a byte
* response token
*
* +----------------------+
* | xxx | 0 | status | 1 |
* +----------------------+
* 010 - OK!
* 101 - CRC Error
* 110 - Write Error
*
* Single Block Read and Write
* ---------------------------
*
* Block transfers have a byte header, followed by the data, followed
* by a 16-bit CRC. In our case, the data will always be 512 bytes.
*
* +------+---------+---------+- - - -+---------+-----------+----------+
* | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
* +------+---------+---------+- - - -+---------+-----------+----------+
*/
/* If the target has no SPI support then SDCard is not supported */
#ifdef DEVICE_SPI
#include "SDBlockDevice.h"
#include "mbed_debug.h"
#define SD_COMMAND_TIMEOUT 5000
#define SD_DBG 0
SDBlockDevice::SDBlockDevice(PinName mosi, PinName miso, PinName sclk, PinName cs)
: _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0)
{
_cs = 1;
// Set default to 100kHz for initialisation and 1MHz for data transfer
_init_sck = 100000;
_transfer_sck = 1000000;
}
SDBlockDevice::~SDBlockDevice()
{
if (_is_initialized) {
deinit();
}
}
#define R1_IDLE_STATE (1 << 0)
#define R1_ERASE_RESET (1 << 1)
#define R1_ILLEGAL_COMMAND (1 << 2)
#define R1_COM_CRC_ERROR (1 << 3)
#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
#define R1_ADDRESS_ERROR (1 << 5)
#define R1_PARAMETER_ERROR (1 << 6)
// Types
// - v1.x Standard Capacity
// - v2.x Standard Capacity
// - v2.x High Capacity
// - Not recognised as an SD Card
#define SDCARD_FAIL 0
#define SDCARD_V1 1
#define SDCARD_V2 2
#define SDCARD_V2HC 3
bd_error_t SDBlockDevice::_initialise_card()
{
_dbg = SD_DBG;
// Set to SCK for initialisation, and clock card with cs = 1
_spi.lock();
_spi.frequency(_init_sck);
_cs = 1;
for (int i = 0; i < 16; i++) {
_spi.write(0xFF);
}
_spi.unlock();
// send CMD0, should return with all zeros except IDLE STATE set (bit 0)
if (_cmd(0, 0) != R1_IDLE_STATE) {
debug_if(_dbg, "No disk, or could not put SD card in to SPI idle state\n");
return BD_ERROR_NO_DEVICE;
}
// send CMD8 to determine whther it is ver 2.x
int r = _cmd8();
if (r == R1_IDLE_STATE) {
return _initialise_card_v2();
} else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
return _initialise_card_v1();
} else {
debug_if(_dbg, "Not in idle state after sending CMD8 (not an SD card?)\n");
return BD_ERROR_DEVICE_ERROR;
}
}
bd_error_t SDBlockDevice::_initialise_card_v1()
{
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
_cmd(55, 0);
if (_cmd(41, 0) == 0) {
_block_size = 512;
debug_if(_dbg, "\n\rInit: SEDCARD_V1\n\r");
return BD_ERROR_OK;
}
}
debug_if(_dbg, "Timeout waiting for v1.x card\n");
return BD_ERROR_DEVICE_ERROR;
}
bd_error_t SDBlockDevice::_initialise_card_v2()
{
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
wait_ms(50);
_cmd58();
_cmd(55, 0);
if (_cmd(41, 0x40000000) == 0) {
_cmd58();
debug_if(_dbg, "\n\rInit: SDCARD_V2\n\r");
_block_size = 1;
return BD_ERROR_OK;
}
}
debug_if(_dbg, "Timeout waiting for v2.x card\n");
return BD_ERROR_DEVICE_ERROR;
}
bd_error_t SDBlockDevice::init()
{
_lock.lock();
bd_error_t err = _initialise_card();
_is_initialized = (err == BD_ERROR_OK);
if (!_is_initialized) {
debug_if(_dbg, "Fail to initialize card\n");
_lock.unlock();
return err;
}
debug_if(_dbg, "init card = %d\n", _is_initialized);
_sectors = _sd_sectors();
// Set block length to 512 (CMD16)
if (_cmd(16, 512) != 0) {
debug_if(_dbg, "Set 512-byte block timed out\n");
_lock.unlock();
return BD_ERROR_DEVICE_ERROR;
}
// Set SCK for data transfer
_spi.frequency(_transfer_sck);
_lock.unlock();
return BD_ERROR_OK;
}
bd_error_t SDBlockDevice::deinit()
{
return 0;
}
bd_error_t SDBlockDevice::program(const void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_program(addr, size)) {
return BD_ERROR_PARAMETER;
}
_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)
if (_cmd(24, block * _block_size) != 0) {
_lock.unlock();
return BD_ERROR_DEVICE_ERROR;
}
// send the data block
_write(buffer, 512);
buffer += 512;
addr += 512;
size -= 512;
}
_lock.unlock();
return 0;
}
bd_error_t SDBlockDevice::read(void *b, bd_addr_t addr, bd_size_t size)
{
if (!is_valid_read(addr, size)) {
return BD_ERROR_PARAMETER;
}
_lock.lock();
if (!_is_initialized) {
_lock.unlock();
return BD_ERROR_PARAMETER;
}
uint8_t *buffer = static_cast<uint8_t *>(b);
while (size > 0) {
bd_addr_t block = addr / 512;
// set read address for single block (CMD17)
if (_cmd(17, block * _block_size) != 0) {
_lock.unlock();
return BD_ERROR_DEVICE_ERROR;
}
// receive the data
_read(buffer, 512);
buffer += 512;
addr += 512;
size -= 512;
}
_lock.unlock();
return 0;
}
bd_error_t SDBlockDevice::erase(bd_addr_t addr, bd_size_t size)
{
return 0;
}
bd_size_t SDBlockDevice::get_read_size()
{
return 512;
}
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;
}
// PRIVATE FUNCTIONS
int SDBlockDevice::_cmd(int cmd, int arg) {
_spi.lock();
_cs = 0;
// send a command
_spi.write(0x40 | cmd);
_spi.write(arg >> 24);
_spi.write(arg >> 16);
_spi.write(arg >> 8);
_spi.write(arg >> 0);
_spi.write(0x95);
// wait for the repsonse (response[7] == 0)
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
int response = _spi.write(0xFF);
if (!(response & 0x80)) {
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return response;
}
}
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return -1; // timeout
}
int SDBlockDevice::_cmdx(int cmd, int arg) {
_spi.lock();
_cs = 0;
// send a command
_spi.write(0x40 | cmd);
_spi.write(arg >> 24);
_spi.write(arg >> 16);
_spi.write(arg >> 8);
_spi.write(arg >> 0);
_spi.write(0x95);
// wait for the repsonse (response[7] == 0)
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
int response = _spi.write(0xFF);
if (!(response & 0x80)) {
_cs = 1;
_spi.unlock();
return response;
}
}
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return -1; // timeout
}
int SDBlockDevice::_cmd58() {
_spi.lock();
_cs = 0;
int arg = 0;
// send a command
_spi.write(0x40 | 58);
_spi.write(arg >> 24);
_spi.write(arg >> 16);
_spi.write(arg >> 8);
_spi.write(arg >> 0);
_spi.write(0x95);
// wait for the repsonse (response[7] == 0)
for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
int response = _spi.write(0xFF);
if (!(response & 0x80)) {
int ocr = _spi.write(0xFF) << 24;
ocr |= _spi.write(0xFF) << 16;
ocr |= _spi.write(0xFF) << 8;
ocr |= _spi.write(0xFF) << 0;
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return response;
}
}
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return -1; // timeout
}
int SDBlockDevice::_cmd8() {
_spi.lock();
_cs = 0;
// send a command
_spi.write(0x40 | 8); // CMD8
_spi.write(0x00); // reserved
_spi.write(0x00); // reserved
_spi.write(0x01); // 3.3v
_spi.write(0xAA); // check pattern
_spi.write(0x87); // crc
// wait for the repsonse (response[7] == 0)
for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
char response[5];
response[0] = _spi.write(0xFF);
if (!(response[0] & 0x80)) {
for (int j = 1; j < 5; j++) {
response[i] = _spi.write(0xFF);
}
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return response[0];
}
}
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return -1; // timeout
}
int SDBlockDevice::_read(uint8_t *buffer, uint32_t length) {
_spi.lock();
_cs = 0;
// read until start byte (0xFF)
while (_spi.write(0xFF) != 0xFE);
// read data
for (uint32_t i = 0; i < length; i++) {
buffer[i] = _spi.write(0xFF);
}
_spi.write(0xFF); // checksum
_spi.write(0xFF);
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return 0;
}
int SDBlockDevice::_write(const uint8_t*buffer, uint32_t length) {
_spi.lock();
_cs = 0;
// indicate start of block
_spi.write(0xFE);
// write the data
for (uint32_t i = 0; i < length; i++) {
_spi.write(buffer[i]);
}
// write the checksum
_spi.write(0xFF);
_spi.write(0xFF);
// check the response token
if ((_spi.write(0xFF) & 0x1F) != 0x05) {
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return 1;
}
// wait for write to finish
while (_spi.write(0xFF) == 0);
_cs = 1;
_spi.write(0xFF);
_spi.unlock();
return 0;
}
static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
uint32_t bits = 0;
uint32_t size = 1 + msb - lsb;
for (uint32_t i = 0; i < size; i++) {
uint32_t position = lsb + i;
uint32_t byte = 15 - (position >> 3);
uint32_t bit = position & 0x7;
uint32_t value = (data[byte] >> bit) & 1;
bits |= value << i;
}
return bits;
}
uint32_t SDBlockDevice::_sd_sectors() {
uint32_t c_size, c_size_mult, read_bl_len;
uint32_t block_len, mult, blocknr, capacity;
uint32_t hc_c_size;
uint32_t blocks;
// CMD9, Response R2 (R1 byte + 16-byte block read)
if (_cmdx(9, 0) != 0) {
debug_if(_dbg, "Didn't get a response from the disk\n");
return 0;
}
uint8_t csd[16];
if (_read(csd, 16) != 0) {
debug_if(_dbg, "Couldn't read csd response from disk\n");
return 0;
}
// csd_structure : csd[127:126]
// c_size : csd[73:62]
// c_size_mult : csd[49:47]
// read_bl_len : csd[83:80] - the *maximum* read block length
int csd_structure = ext_bits(csd, 127, 126);
switch (csd_structure) {
case 0:
_block_size = 512;
c_size = ext_bits(csd, 73, 62);
c_size_mult = ext_bits(csd, 49, 47);
read_bl_len = ext_bits(csd, 83, 80);
block_len = 1 << read_bl_len;
mult = 1 << (c_size_mult + 2);
blocknr = (c_size + 1) * mult;
capacity = blocknr * block_len;
blocks = capacity / 512;
debug_if(_dbg, "\n\rSDBlockDevice\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
break;
case 1:
_block_size = 1;
hc_c_size = ext_bits(csd, 63, 48);
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);
break;
default:
debug_if(_dbg, "CSD struct unsupported\r\n");
return 0;
};
return blocks;
}
#endif /* DEVICE_SPI */

View File

@ -1,158 +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_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,93 +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.
*/
#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);
}

View File

@ -1,88 +0,0 @@
/** @file fsfat_debug.h
*
* component debug header file.
*/
#ifndef __FSFAT_DEBUG
#define __FSFAT_DEBUG
#include <stdint.h>
#include <assert.h>
#include <stdio.h>
/* Debug Support */
#define FSFAT_LOG_NONE 0
#define FSFAT_LOG_ERR 1
#define FSFAT_LOG_WARN 2
#define FSFAT_LOG_NOTICE 3
#define FSFAT_LOG_INFO 4
#define FSFAT_LOG_DEBUG 5
#define FSFAT_LOG_FENTRY 6
#define FSFAT_LOG(_fmt, ...) \
do \
{ \
printf(_fmt, __VA_ARGS__); \
}while(0);
#define noFSFAT_DEBUG
#ifdef FSFAT_DEBUG
extern uint32_t fsfat_optDebug_g;
extern uint32_t fsfat_optLogLevel_g;
/* uncomment for asserts to work */
/* #undef NDEBUG */
// todo: port to mbedOSV3++ #include <core-util/assert.h>
#define FSFAT_INLINE
// todo: port to mbedOSV3++ #define FSFAT_ASSERT CORE_UTIL_ASSERT
#define FSFAT_ASSERT(...)
#define FSFAT_DBGLOG(_fmt, ...) \
do \
{ \
if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_DEBUG)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
#define FSFAT_ERRLOG(_fmt, ...) \
do \
{ \
if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_ERR)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
#define FSFAT_FENTRYLOG(_fmt, ...) \
do \
{ \
if(fsfat_optDebug_g && (fsfat_optLogLevel_g >= FSFAT_LOG_FENTRY)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
#else
#define FSFAT_ASSERT(_x) do { } while(0)
#define FSFAT_INLINE inline
#define FSFAT_DBGLOG(_fmt, ...) do { } while(0)
#define FSFAT_ERRLOG(_fmt, ...) do { } while(0)
#define FSFAT_FENTRYLOG(_fmt, ...) do { } while(0)
#endif /* FSFAT_DEBUG */
#endif /*__FSFAT_DEBUG*/

View File

@ -1,117 +0,0 @@
/* @file fsfat_test.c
*
* 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.
*
* test support code implementation file.
*/
#include "fsfat_debug.h"
#include "fsfat_test.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include <ctype.h>
#ifdef FSFAT_DEBUG
uint32_t fsfat_optDebug_g = 1;
uint32_t fsfat_optLogLevel_g = FSFAT_LOG_NONE; /*FSFAT_LOG_NONE|FSFAT_LOG_ERR|FSFAT_LOG_DEBUG|FSFAT_LOG_FENTRY */
#endif
/* ruler for measuring text strings */
/* 1 1 1 1 1 1 1 1 1 1 2 2 2 */
/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE] = {
0x2d, 0xf3, 0x31, 0x4c, 0x11, 0x4f, 0xde, 0x0d, 0xbd, 0xbc, 0xa6, 0x78, 0x36, 0x5c, 0x1d, 0x28,
0x5f, 0xa9, 0x10, 0x65, 0x54, 0x45, 0x21, 0x1a, 0x88, 0xfe, 0x76, 0x45, 0xb9, 0xac, 0x65, 0x9a,
0x34, 0x9d, 0x73, 0x10, 0xb4, 0xa9, 0x2e, 0x90, 0x95, 0x68, 0xac, 0xfe, 0xc5, 0x2d, 0x15, 0x03,
0x34, 0x70, 0xf1, 0x1d, 0x48, 0xa1, 0xa0, 0xed, 0x5c, 0x2f, 0xf5, 0x2b, 0xb9, 0x84, 0xbb, 0x45,
0x32, 0xdd, 0xb1, 0x33, 0x95, 0x2a, 0xbc, 0x26, 0xf0, 0x89, 0xba, 0xf4, 0xbd, 0xf9, 0x5d, 0x2e,
0x6e, 0x11, 0xc6, 0xa7, 0x78, 0xfc, 0xc9, 0x0e, 0x6b, 0x38, 0xba, 0x14, 0x1b, 0xab, 0x4c, 0x20,
0x91, 0xe4, 0xb0, 0xf1, 0x2b, 0x14, 0x07, 0x6b, 0xb5, 0xcd, 0xe3, 0x49, 0x75, 0xac, 0xe8, 0x98,
0xf1, 0x58, 0x8f, 0xd9, 0xc4, 0x8f, 0x00, 0x17, 0xb5, 0x06, 0x6a, 0x33, 0xbd, 0xa7, 0x40, 0x5a,
0xbf, 0x49, 0xf7, 0x27, 0x1b, 0x4c, 0x3e, 0x6f, 0xe3, 0x08, 0x1f, 0xfd, 0xa6, 0xd4, 0xc7, 0x5f,
0xa4, 0xa6, 0x82, 0xad, 0x19, 0xd5, 0x5c, 0xd8, 0x3a, 0x49, 0x85, 0xc9, 0x21, 0x83, 0xf6, 0xc6,
0x84, 0xf9, 0x76, 0x89, 0xf3, 0x2d, 0x17, 0x50, 0x97, 0x38, 0x48, 0x9a, 0xe1, 0x82, 0xcd, 0xac,
0xa8, 0x1d, 0xd7, 0x96, 0x5e, 0xb3, 0x08, 0xa8, 0x3a, 0xc7, 0x2b, 0x05, 0xaf, 0xdc, 0x16, 0xdf,
0x48, 0x0f, 0x2a, 0x7e, 0x3a, 0x82, 0xd7, 0x80, 0xd6, 0x49, 0x27, 0x5d, 0xe3, 0x07, 0x62, 0xb3,
0xc3, 0x6c, 0xba, 0xb2, 0xaa, 0x9f, 0xd9, 0x03, 0x0d, 0x27, 0xa8, 0xe0, 0xd6, 0xee, 0x79, 0x4b,
0xd6, 0x97, 0x99, 0xb7, 0x11, 0xd6, 0x0d, 0x34, 0xae, 0x99, 0x4a, 0x93, 0x95, 0xd0, 0x5a, 0x34,
0x19, 0xa2, 0x69, 0x57, 0xcf, 0x7c, 0x3d, 0x98, 0x88, 0x5d, 0x04, 0xf2, 0xd7, 0xac, 0xa5, 0x63
};
/* @brief test utility function to delete the file identified by filename
*/
int32_t fsfat_test_delete(const char* filename)
{
FSFAT_FENTRYLOG("%s:entered.\r\n", __func__);
return remove(filename);
}
/* @brief test utility function to create a 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(const char* filename, const char* data, size_t len)
{
int32_t ret = -1;
FILE *fp = NULL;
FSFAT_FENTRYLOG("%s:entered (filename=%s, len=%d).\n", __func__, filename, (int) len);
fp = fopen(filename, "w+");
if(fp == NULL){
return ret;
}
ret = fwrite((const void*) data, len, 1, fp);
if(ret < 0){
fclose(fp);
return ret;
}
fclose(fp);
return ret;
}
/* @brief support function for generating a kv_name
* @param name buffer to hold kv name
* @param len length of kv name to generate
*
*/
int32_t fsfat_test_filename_gen(char* name, const size_t len)
{
size_t i;
uint32_t pos = 0;
const char* buf = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!$-_@";
const int buf_len = strlen(buf);
FSFAT_FENTRYLOG("%s:entered\n", __func__);
for(i = 0; i < len; i++)
{
pos = rand() % (buf_len);
name[i] = buf[pos];
}
return 0;
}

View File

@ -1,74 +0,0 @@
/** @file fsfat_test.h
*
* 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.
*
* Header file for test support data structures and function API.
*/
#ifndef __FSFAT_TEST_H
#define __FSFAT_TEST_H
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Defines */
//#define FSFAT_INIT_1_TABLE_HEAD { "a", ""}
#define FSFAT_INIT_1_TABLE_MID_NODE { "/sd/01234567.txt", "abcdefghijklmnopqrstuvwxyz"}
//#define FSFAT_INIT_1_TABLE_TAIL { "/sd/fopentst/hello/world/animal/wobbly/dog/foot/backrght.txt", "present"}
#define FSFAT_TEST_RW_TABLE_SENTINEL 0xffffffff
#define FSFAT_TEST_BYTE_DATA_TABLE_SIZE 256
#define FSFAT_UTEST_MSG_BUF_SIZE 256
#define FSFAT_UTEST_DEFAULT_TIMEOUT_MS 10000
#define FSFAT_MBED_HOSTTEST_TIMEOUT 60
#define FSFAT_MAX_FILE_BASENAME 8
#define FSFAT_MAX_FILE_EXTNAME 3
#define FSFAT_BUF_MAX_LENGTH 64
#define FSFAT_FILENAME_MAX_LENGTH 255
/* support macro for make string for utest _MESSAGE macros, which dont support formatted output */
#define FSFAT_TEST_UTEST_MESSAGE(_buf, _max_len, _fmt, ...) \
do \
{ \
snprintf((_buf), (_max_len), (_fmt), __VA_ARGS__); \
}while(0);
/*
* Structures
*/
/* kv data for test */
typedef struct fsfat_kv_data_t {
const char* filename;
const char* value;
} fsfat_kv_data_t;
extern const uint8_t fsfat_test_byte_data_table[FSFAT_TEST_BYTE_DATA_TABLE_SIZE];
int32_t fsfat_test_create(const char* filename, const char* data, size_t len);
int32_t fsfat_test_delete(const char* key_name);
int32_t fsfat_test_filename_gen(char* name, const size_t len);
#ifdef __cplusplus
}
#endif
#endif /* __FSFAT_TEST_H */