From 8126ebead8469b843a7ba54c957a1c34ae7a677d Mon Sep 17 00:00:00 2001 From: Carl John Kugler III Date: Wed, 24 Mar 2021 11:41:27 -0600 Subject: [PATCH] Improve support for multiple SD cards --- README.md | 28 ++-- ff14a/source/ffconf.h | 4 +- ff14a/source/ffsystem.c | 3 +- no-OS-FatFS.c | 197 +++++++++++++++++------- sd_driver/hw_config.c | 85 ++++++---- sd_driver/hw_config.h | 7 +- sd_driver/sd_card.c | 67 ++++---- sd_driver/sd_card.h | 4 +- sd_driver/sd_spi.c | 10 +- sd_driver/sd_spi.h | 2 +- src/ff_stdio.c | 30 ++-- src/glue.c | 4 +- tests/app4-IO_module_function_checker.c | 4 +- tests/simple.c | 124 ++++++--------- 14 files changed, 331 insertions(+), 238 deletions(-) diff --git a/README.md b/README.md index 3e941df..4ec34d0 100644 --- a/README.md +++ b/README.md @@ -38,21 +38,21 @@ I have been able to push the SPI baud rate as far as 20,833,333 which increases ![image](https://www.raspberrypi.org/documentation/rp2040/getting-started/static/64b50c4316a7aefef66290dcdecda8be/Pico-R3-SDK11-Pinout.svg "Pinout") -| | SPI0 | GPIO | Pin | SPI | MicroSD 0 | -| --- | ---- | ---- | --- | -------- | --------- | -| MOSI| TX | 16 | 25 | DI | DI | -| CS0 | CSn | 17 | 22 | SS or CS | CS | -| SCK | SCK | 18 | 24 | SCLK | CLK | -| MISO| RX | 19 | 21 | DO | DO | -| CD | | 22 | 29 | | CD | -| GND | | | 18,23 | | GND | -| 3v3 | | | 36 | | 3v3 | +| | SPI0 | GPIO | Pin | SPI | MicroSD 0 | +| ----- | ---- | ----- | --- | -------- | --------- | +| MOSI | TX | 16 | 25 | DI | DI | +| CS0 | CSn | 17 | 22 | SS or CS | CS | +| SCK | SCK | 18 | 24 | SCLK | CLK | +| MISO | RX | 19 | 21 | DO | DO | +| CD | | 22 | 29 | | CD | +| GND | | | 18,23 | | GND | +| 3v3 | | | 36 | | 3v3 | ## Construction: * The wiring is so simple that I didn't bother with a schematic. I just referred to the table above, wiring point-to-point from the Pin column on the Pico to the MicroSD 0 column on the Transflash. * You can choose to use either or both of the Pico's SPIs. -* To add a second SD card on the same SPI, connect it in parallel, except that it will need a unique GPIO for the Card Select/Slave Select (CSn) and another for Card Detect (CD). +* To add a second SD card on the same SPI, connect it in parallel, except that it will need a unique GPIO for the Card Select/Slave Select (CSn) and another for Card Detect (CD) (optional). * Wires should be kept short and direct. SPI operates at HF radio frequencies. ## Firmware: @@ -142,6 +142,10 @@ stop_logger: help: Shows this command help. ``` + +## Troubleshooting +* Logic analyzer: + ## Next Steps There is a example data logging application in `data_log_demo.c`. It can be launched from the CLI with the `start_logger` command. @@ -167,3 +171,7 @@ and `#include "ff.h"`. ![image](https://github.com/carlk3/FreeRTOS-FAT-CLI-for-RPi-Pico/blob/master/images/IMG_1481.JPG "Prototype") Happy hacking! + +## Appendix: Adding a Second Card +* #define FF_VOLUMES 2 in ff14a/source/ffconf.h + diff --git a/ff14a/source/ffconf.h b/ff14a/source/ffconf.h index 58e9ebd..4fee671 100644 --- a/ff14a/source/ffconf.h +++ b/ff14a/source/ffconf.h @@ -163,7 +163,7 @@ / Drive/Volume Configurations /---------------------------------------------------------------------------*/ -#define FF_VOLUMES 1 +#define FF_VOLUMES 2 /* Number of volumes (logical drives) to be used. (1-10) */ @@ -260,7 +260,7 @@ */ -#define FF_FS_LOCK 1 +#define FF_FS_LOCK 0 // Note: 0 since we're not bothering with f_closedir /* The option FF_FS_LOCK switches file lock function to control duplicated file open / and illegal operation to open objects. This option must be 0 when FF_FS_READONLY / is 1. diff --git a/ff14a/source/ffsystem.c b/ff14a/source/ffsystem.c index ad5d737..e45ea2f 100644 --- a/ff14a/source/ffsystem.c +++ b/ff14a/source/ffsystem.c @@ -3,7 +3,8 @@ /* (C)ChaN, 2018 */ /*------------------------------------------------------------------------*/ - +#include +// #include "ff.h" diff --git a/no-OS-FatFS.c b/no-OS-FatFS.c index f3155be..5cb31da 100644 --- a/no-OS-FatFS.c +++ b/no-OS-FatFS.c @@ -15,7 +15,6 @@ #include "rtc.h" #include "sd_card.h" -extern void ls(); extern void lliot(); extern void simple(); extern void big_file_test(const char *const pathname, size_t size, @@ -24,7 +23,19 @@ extern void vCreateAndVerifyExampleFiles(const char *pcMountPath); extern void vStdioWithCWDTest(const char *pcMountPath); extern bool process_logger(); -static FATFS fs; +typedef struct { + FATFS fatfs; + char const *const name; +} fatfs_dscr_t; +static fatfs_dscr_t fatfs_dscrs[2] = {{.name = "0:"}, {.name = "1:"}}; +static FATFS *get_fs_by_name(const char *name) { + for (size_t i = 0; i < count_of(fatfs_dscrs); ++i) { + if (0 == strcmp(fatfs_dscrs[i].name, name)) { + return &fatfs_dscrs[i].fatfs; + } + } + return NULL; +} static bool logger_enabled; static const uint32_t period = 1000; @@ -83,6 +94,14 @@ static void run_setrtc() { // bool r = rtc_set_datetime(&t); setrtc(&t); } +static void run_lliot() { + size_t pnum = 0; + char *arg1 = strtok(NULL, " "); + if (arg1) { + pnum = strtoul(arg1, NULL, 0); + } + lliot(pnum); +} static void run_date() { char buf[128] = {0}; time_t epoch_secs = time(NULL); @@ -97,15 +116,24 @@ static void run_date() { } static void run_format() { char *arg1 = strtok(NULL, " "); - if (!arg1) arg1 = ""; + FATFS *p_fs = get_fs_by_name(arg1); + if (!p_fs) { + printf("Unknown logical drive number: \"%s\"", arg1); + return; + } /* Format the drive with default parameters */ FRESULT fr = f_mkfs(arg1, 0, 0, FF_MAX_SS * 2); if (FR_OK != fr) printf("f_mkfs error: %s (%d)\n", FRESULT_str(fr), fr); } static void run_mount() { char *arg1 = strtok(NULL, " "); - if (!arg1) arg1 = ""; - FRESULT fr = f_mount(&fs, arg1, 1); + if (!arg1) arg1 = "0:"; + FATFS *p_fs = get_fs_by_name(arg1); + if (!p_fs) { + printf("Unknown logical drive number: \"%s\"", arg1); + return; + } + FRESULT fr = f_mount(p_fs, arg1, 1); if (FR_OK != fr) printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); } static void run_unmount() { @@ -114,20 +142,30 @@ static void run_unmount() { FRESULT fr = f_unmount(arg1); if (FR_OK != fr) printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); } +static void run_chdrive() { + char *arg1 = strtok(NULL, " "); + if (!arg1) arg1 = "0:"; + FRESULT fr = f_chdrive(arg1); + if (FR_OK != fr) printf("f_mount error: %s (%d)\n", FRESULT_str(fr), fr); +} static void run_getfree() { char *arg1 = strtok(NULL, " "); - if (!arg1) arg1 = ""; + if (!arg1) arg1 = "0:"; DWORD fre_clust, fre_sect, tot_sect; /* Get volume information and free clusters of drive */ - FATFS *p_fatfs = &fs; - FRESULT fr = f_getfree(arg1, &fre_clust, &p_fatfs); + FATFS *p_fs = get_fs_by_name(arg1); + if (!p_fs) { + printf("Unknown logical drive number: \"%s\"", arg1); + return; + } + FRESULT fr = f_getfree(arg1, &fre_clust, &p_fs); if (FR_OK != fr) { printf("f_getfree error: %s (%d)\n", FRESULT_str(fr), fr); return; } /* Get total sectors and free sectors */ - tot_sect = (p_fatfs->n_fatent - 2) * p_fatfs->csize; - fre_sect = fre_clust * p_fatfs->csize; + tot_sect = (p_fs->n_fatent - 2) * p_fs->csize; + fre_sect = fre_clust * p_fs->csize; /* Print the free space (assuming 512 bytes/sector) */ printf("%10lu KiB total drive space.\n%10lu KiB available.\n", tot_sect / 2, fre_sect / 2); @@ -150,6 +188,58 @@ static void run_mkdir() { FRESULT fr = f_mkdir(arg1); if (FR_OK != fr) printf("f_mkfs error: %s (%d)\n", FRESULT_str(fr), fr); } +void ls(const char *dir) { + char cwdbuf[FF_LFN_BUF] = {0}; + FRESULT fr; /* Return value */ + char const *p_dir; + if (dir[0]) { + p_dir = dir; + } else { + fr = f_getcwd(cwdbuf, sizeof cwdbuf); + if (FR_OK != fr) { + printf("f_getcwd error: %s (%d)\n", FRESULT_str(fr), fr); + return; + } + p_dir = cwdbuf; + } + printf("Directory Listing: %s\n", p_dir); + DIR dj; /* Directory object */ + FILINFO fno; /* File information */ + memset (&dj, 0, sizeof dj); + memset (&fno, 0, sizeof fno); + fr = f_findfirst(&dj, &fno, p_dir, "*"); + if (FR_OK != fr) { + printf("f_findfirst error: %s (%d)\n", FRESULT_str(fr), fr); + return; + } + while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */ + /* Create a string that includes the file name, the file size and the + attributes string. */ + const char *pcWritableFile = "writable file", + *pcReadOnlyFile = "read only file", + *pcDirectory = "directory"; + const char *pcAttrib; + /* Point pcAttrib to a string that describes the file. */ + if (fno.fattrib & AM_DIR) { + pcAttrib = pcDirectory; + } else if (fno.fattrib & AM_RDO) { + pcAttrib = pcReadOnlyFile; + } else { + pcAttrib = pcWritableFile; + } + /* Create a string that includes the file name, the file size and the + attributes string. */ + printf("%s [%s] [size=%llu]\n", fno.fname, pcAttrib, fno.fsize); + + fr = f_findnext(&dj, &fno); /* Search for next item */ + } + f_closedir(&dj); +} +static void run_ls() { + char *arg1 = strtok(NULL, " "); + if (!arg1) arg1 = ""; + ls(arg1); +} static void run_cat() { char *arg1 = strtok(NULL, " "); if (!arg1) { @@ -189,7 +279,9 @@ static void run_big_file_test() { uint32_t seed = atoi(pcSeed); big_file_test(pcPathName, size, seed); } -static void run_cdef() { vCreateAndVerifyExampleFiles("/cdef"); } +static void run_cdef() { + f_mkdir("/cdef"); // fake mountpoint + vCreateAndVerifyExampleFiles("/cdef"); } static void run_swcwdt() { vStdioWithCWDTest("/cdef"); } static void run_start_logger() { logger_enabled = true; @@ -206,68 +298,54 @@ typedef struct { } cmd_def_t; static cmd_def_t cmds[] = { - { - "setrtc", - run_setrtc, - "setrtc
:\n" - " Set Real Time Clock\n" - " Parameters: new date (DD MM YY) new time in 24-hour format " - "(hh mm ss)\n" - "\te.g.:setrtc 16 3 21 0 4 0", - }, + {"setrtc", run_setrtc, + "setrtc
:\n" + " Set Real Time Clock\n" + " Parameters: new date (DD MM YY) new time in 24-hour format " + "(hh mm ss)\n" + "\te.g.:setrtc 16 3 21 0 4 0"}, {"date", run_date, "date:\n Print current date and time"}, - { - "lliot", - lliot, - "lliot :\n !DESTRUCTIVE! Low Level I/O Driver Test\n" - "\te.g.: lliot sd0", - }, - { - "format", - run_format, - "format []:\n" - " Creates an FAT/exFAT volume on the logical drive.\n" - "\te.g.: format 0:", - }, - { - "mount", - run_mount, - "mount []:\n" - " Register the work area of the volume\n" - "\te.g.: mount 0:" - }, - { - "getfree", - run_getfree, - "getfree []:\n" - " Print the free space on drive" - }, + {"lliot", run_lliot, + "lliot :\n !DESTRUCTIVE! Low Level I/O Driver Test\n" + "\te.g.: lliot 1"}, + {"format", run_format, + "format []:\n" + " Creates an FAT/exFAT volume on the logical drive.\n" + "\te.g.: format 0:"}, + {"mount", run_mount, + "mount []:\n" + " Register the work area of the volume\n" + "\te.g.: mount 0:"}, {"unmount", run_unmount, "unmount :\n" " Unregister the work area of the volume"}, + {"chdrive", run_chdrive, + "chdrive :\n" + " Changes the current directory of the logical drive.\n" + " Specifies the directory to be set as current directory.\n" + "\te.g.: chdrive 1:"}, + {"getfree", run_getfree, + "getfree []:\n" + " Print the free space on drive"}, {"cd", run_cd, "cd :\n" - " Changes the current directory of the logical drive. Also, the current " - "drive can be changed.\n" + " Changes the current directory of the logical drive.\n" " Specifies the directory to be set as current directory.\n" - "\te.g.: cd 1:/dir1"}, + "\te.g.: cd /dir1"}, {"mkdir", run_mkdir, "mkdir :\n" " Make a new directory.\n" " Specifies the name of the directory to be created.\n" "\te.g.: mkdir /dir1"}, - {"ls", ls, "ls:\n List directory"}, + {"ls", run_ls, "ls:\n List directory"}, {"cat", run_cat, "cat :\n Type file contents"}, {"simple", simple, "simple:\n Run simple FS tests"}, - { - "big_file_test", - run_big_file_test, - "big_file_test :\n" - " Writes random data to file .\n" - " must be multiple of 512.\n" - "\te.g.: big_file_test bf 1048576 1\n" - "\tor: big_file_test big3G-3 0xC0000000 3", - }, + {"big_file_test", run_big_file_test, + "big_file_test :\n" + " Writes random data to file .\n" + " must be multiple of 512.\n" + "\te.g.: big_file_test bf 1048576 1\n" + "\tor: big_file_test big3G-3 0xC0000000 3"}, {"cdef", run_cdef, "cdef:\n Create Disk and Example Files\n" " Expects card to be already formatted and mounted"}, @@ -349,6 +427,7 @@ int main() { stdio_init_all(); time_init(); adc_init(); + sd_init_driver(); printf("\033[2J\033[H"); // Clear Screen printf("\n> "); diff --git a/sd_driver/hw_config.c b/sd_driver/hw_config.c index 1fb80d5..e0d152c 100644 --- a/sd_driver/hw_config.c +++ b/sd_driver/hw_config.c @@ -23,26 +23,28 @@ socket, which SPI it is driven by, and how it is wired. */ #include - -// Make it easier to spot errors: -#include "hw_config.h" +// #include "my_debug.h" +// +#include "hw_config.h" void spi0_dma_isr(); // Hardware Configuration of SPI "objects" // Note: multiple SD cards can be driven by one SPI if they use different slave // selects. -static spi_t spi[] = { // One for each SPI. +static spi_t spis[] = { // One for each SPI. { .hw_inst = spi0, // SPI component - .miso_gpio = 19, - .mosi_gpio = 16, + .miso_gpio = 16, + .mosi_gpio = 19, .sck_gpio = 18, - //.baud_rate = 1000 * 1000, //DEBUG - .baud_rate = 12500 * 1000, // The limitation here is SPI slew rate. + /* The choice of SD card matters! SanDisk runs at the highest speed. PNY + can only mangage 5 MHz. Those are all I've tried. */ + .baud_rate = 5000 * 1000, + //.baud_rate = 12500 * 1000, // The limitation here is SPI slew rate. //.baud_rate = 25 * 1000 * 1000, // Actual frequency: 20833333. Has - // worked for me. + // worked for me with SanDisk. // Following attributes are dynamically assigned .dma_isr = spi0_dma_isr, @@ -51,39 +53,56 @@ static spi_t spi[] = { // One for each SPI. // Hardware Configuration of the SD Card "objects" static sd_card_t sd_cards[] = { // One for each SD card - {.pcName = "0:", // Name used to mount device - .spi = &spi[0], // Pointer to the SPI driving this card - .ss_gpio = 17, // The SPI slave select GPIO for this SD card - .card_detect_gpio = 22, // Card detect - .card_detected_true = 1, // What the GPIO read returns when a card is - // present. Use -1 if there is no card detect. - // Following attributes are dynamically assigned - .m_Status = STA_NOINIT, - .sectors = 0, - .card_type = 0, - }}; + { + .pcName = "0:", // Name used to mount device + .spi = &spis[0], // Pointer to the SPI driving this card + .ss_gpio = 17, // The SPI slave select GPIO for this SD card + .card_detect_gpio = 22, // Card detect + .card_detected_true = 1, // What the GPIO read returns when a card is + // present. Use -1 if there is no card detect. + // Following attributes are dynamically assigned + .m_Status = STA_NOINIT, + .sectors = 0, + .card_type = 0, + }, + { + .pcName = "1:", // Name used to mount device + .spi = &spis[0], // Pointer to the SPI driving this card + .ss_gpio = 15, // The SPI slave select GPIO for this SD card + .card_detect_gpio = 14, // Card detect + .card_detected_true = 1, // What the GPIO read returns when a card is + // present. Use -1 if there is no card detect. + // Following attributes are dynamically assigned + .m_Status = STA_NOINIT, + .sectors = 0, + .card_type = 0, + }}; -void spi0_dma_isr() { spi_irq_handler(&spi[0]); } +void spi0_dma_isr() { spi_irq_handler(&spis[0]); } /* ********************************************************************** */ +size_t sd_get_num() { return count_of(sd_cards); } +sd_card_t *sd_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &sd_cards[num]; + } else { + return NULL; + } +} sd_card_t *sd_get_by_name(const char *const name) { size_t i; - for (i = 0; i < sizeof(sd_cards) / sizeof(sd_cards[0]); ++i) { - if (0 == strcmp(sd_cards[i].pcName, name)) break; - } - if (sizeof(sd_cards) / sizeof(sd_cards[0]) == i) { - DBG_PRINTF("FF_SDDiskInit: unknown name %s\n", name); - return NULL; + for (i = 0; i < sd_get_num(); ++i) { + if (0 == strcmp(sd_cards[i].pcName, name)) return &sd_cards[i]; } - return &sd_cards[i]; + DBG_PRINTF("FF_SDDiskInit: unknown name %s\n", name); + return NULL; } - -sd_card_t *sd_get_by_num(size_t num) { - if (num <= sizeof(sd_cards) / sizeof(sd_cards[0])) { - return &sd_cards[num]; +size_t spi_get_num() { return count_of(spis); } +spi_t *spi_get_by_num(size_t num) { + if (num <= sd_get_num()) { + return &spis[num]; } else { return NULL; } } - /* [] END OF FILE */ diff --git a/sd_driver/hw_config.h b/sd_driver/hw_config.h index 62f0f25..ba35805 100644 --- a/sd_driver/hw_config.h +++ b/sd_driver/hw_config.h @@ -2,8 +2,9 @@ #include "sd_card.h" -sd_card_t *sd_get_by_name(const char *const name); +size_t sd_get_num(); sd_card_t *sd_get_by_num(size_t num); - - +sd_card_t *sd_get_by_name(const char *const name); +size_t spi_get_num(); +spi_t *spi_get_by_num(size_t num); /* [] END OF FILE */ diff --git a/sd_driver/sd_card.c b/sd_driver/sd_card.c index 8f17ab2..789a2a7 100644 --- a/sd_driver/sd_card.c +++ b/sd_driver/sd_card.c @@ -147,13 +147,14 @@ */ /* Standard includes. */ -#include "sd_card.h" - #include #include - +// #include "my_debug.h" +#include "hw_config.h" // Hardware Configuration of the SPI and SD Card "objects" #include "sd_spi.h" +// +#include "sd_card.h" #define SD_CRC_ENABLED 1 @@ -162,21 +163,20 @@ static bool crc_on = true; #endif -// Hardware Configuration of the SPI and SD Card "objects" -#include "hw_config.h" - #define TRACE_PRINTF(fmt, args...) -//#define TRACE_PRINTF task_printf +//#define TRACE_PRINTF printf #define TRC_PR_ADD(fmt, args...) //#define TRC_PR_ADD printf #define TRACE_PRINTF2(fmt, args...) -//#define TRACE_PRINTF2(format, ...) \ -// { \ -// printf(format, __VA_ARGS__); \ -// fflush(stdout); \ -// } +/* +#define TRACE_PRINTF2(format, ...) \ + { \ + printf(format, __VA_ARGS__); \ + fflush(stdout); \ + } +*/ /* Control Tokens */ #define SPI_DATA_RESPONSE_MASK (0x1F) @@ -275,6 +275,8 @@ typedef enum { #define SPI_CMD(x) (0x40 | (x & 0x3f)) +static bool driver_initialized; + static uint8_t sd_cmd_spi(sd_card_t *this, cmdSupported cmd, uint32_t arg) { uint8_t response; char cmdPacket[PACKET_SIZE]; @@ -541,9 +543,6 @@ bool sd_card_detect(sd_card_t *this) { return true; } /*!< Check GPIO to detect SD */ - gpio_init(this->card_detect_gpio); - gpio_pull_up(this->card_detect_gpio); - gpio_set_dir(this->card_detect_gpio, GPIO_IN); if (gpio_get(this->card_detect_gpio) == this->card_detected_true) { // The socket is now occupied this->m_Status &= ~STA_NODISK; @@ -574,7 +573,9 @@ static uint32_t sd_go_idle_state(sd_card_t *this) { if (R1_IDLE_STATE == response) { break; } + sd_unlock(this); busy_wait_us(100 * 1000); + sd_lock(this); } return response; } @@ -785,17 +786,13 @@ uint64_t sd_sectors(sd_card_t *this) { return sectors; } -int sd_init(sd_card_t *this) { +int sd_init_card(sd_card_t *this) { TRACE_PRINTF("> %s\n", __FUNCTION__); + myASSERT(driver_initialized); // STA_NOINIT = 0x01, /* Drive not initialized */ // STA_NODISK = 0x02, /* No medium in the drive */ // STA_PROTECT = 0x04 /* Write protected */ - if (!my_spi_init(this->spi)) { - return this->m_Status; - } - sd_spi_init(this); - // Make sure there's a card in the socket before proceeding sd_card_detect(this); if (this->m_Status & STA_NODISK) { @@ -837,12 +834,6 @@ int sd_init(sd_card_t *this) { // Return the disk status return this->m_Status; } -int sd_deinit(sd_card_t *this) { - this->m_Status |= STA_NOINIT; - this->card_type = SDCARD_NONE; - // Return the disk status - return this->m_Status; -} // SPI function to wait till chip is ready and sends start token static bool sd_wait_token(sd_card_t *this, uint8_t token) { @@ -1108,4 +1099,26 @@ int sd_write_blocks(sd_card_t *this, const uint8_t *buffer, return status; } + +bool sd_init_driver() { + for (size_t i = 0; i < sd_get_num(); ++i) { + sd_card_t *this = sd_get_by_num(i); + gpio_init(this->card_detect_gpio); + gpio_pull_up(this->card_detect_gpio); + gpio_set_dir(this->card_detect_gpio, GPIO_IN); + // Chip select is active-low, so we'll initialise it to a driven-high + // state. + gpio_init(this->ss_gpio); + gpio_put(this->ss_gpio, 1); // Avoid any glitches when enabling output + gpio_set_dir(this->ss_gpio, GPIO_OUT); + gpio_put(this->ss_gpio, 1); // In case set_dir does anything + } + for (size_t i = 0; i < spi_get_num(); ++i) { + spi_t *this = spi_get_by_num(i); + if (!my_spi_init(this)) return false; + } + driver_initialized = true; + return true; +} + /* [] END OF FILE */ diff --git a/sd_driver/sd_card.h b/sd_driver/sd_card.h index be6bbc0..807d0bf 100644 --- a/sd_driver/sd_card.h +++ b/sd_driver/sd_card.h @@ -60,8 +60,8 @@ enum { }; #endif -int sd_init(sd_card_t *this); -int sd_deinit(sd_card_t *this); +bool sd_init_driver(); +int sd_init_card(sd_card_t *this); int sd_write_blocks(sd_card_t *this, const uint8_t *buffer, uint64_t ulSectorNumber, uint32_t blockCnt); int sd_read_blocks(sd_card_t *this, uint8_t *buffer, uint64_t ulSectorNumber, diff --git a/sd_driver/sd_spi.c b/sd_driver/sd_spi.c index 078050f..65ed4a6 100644 --- a/sd_driver/sd_spi.c +++ b/sd_driver/sd_spi.c @@ -34,7 +34,7 @@ void sd_spi_go_low_frequency(sd_card_t *this) { // Would do nothing if this->ss_gpio were set to GPIO_FUNC_SPI. void sd_spi_select(sd_card_t *this) { uint8_t fill = SPI_FILL_CHAR; - spi_write_blocking(this->spi->hw_inst, &fill, 1); + spi_write_blocking(this->spi->hw_inst, &fill, 1); // asm volatile("nop \n nop \n nop"); // FIXME gpio_put(this->ss_gpio, 0); //asm volatile("nop \n nop \n nop"); // FIXME @@ -80,14 +80,6 @@ bool sd_spi_transfer(sd_card_t *this, const uint8_t *tx, uint8_t *rx, return spi_transfer(this->spi, tx, rx, length); } -//void sd_spi_init_manual() { -void sd_spi_init(sd_card_t *this) { - // Chip select is active-low, so we'll initialise it to a driven-high - // state. - gpio_init(this->ss_gpio); - gpio_put(this->ss_gpio, 1); - gpio_set_dir(this->ss_gpio, GPIO_OUT); -} void sd_spi_init_pl022(sd_card_t *this) { // Let the PL022 SPI handle it. // the CS line is brought high between each byte during transmission. diff --git a/sd_driver/sd_spi.h b/sd_driver/sd_spi.h index df1940c..3fd3db2 100644 --- a/sd_driver/sd_spi.h +++ b/sd_driver/sd_spi.h @@ -26,7 +26,7 @@ void sd_spi_release(sd_card_t *this); //void sd_spi_deselect(sd_card_t *this); void sd_spi_go_low_frequency(sd_card_t *this); void sd_spi_go_high_frequency(sd_card_t *this); -void sd_spi_init(sd_card_t *this); +bool sd_spi_init(sd_card_t *this); #endif diff --git a/src/ff_stdio.c b/src/ff_stdio.c index 6b1a270..a8e30df 100644 --- a/src/ff_stdio.c +++ b/src/ff_stdio.c @@ -8,8 +8,8 @@ #include "my_debug.h" // -#include "ff_stdio.h" #include "f_util.h" +#include "ff_stdio.h" bool tracing = true; @@ -91,7 +91,8 @@ FF_FILE *ff_fopen(const char *pcFile, const char *pcMode) { FRESULT fr = f_open(fp, pcFile, posix2mode(pcMode)); errno = fresult2errno(fr); if (FR_OK != fr) { - if (tracing) printf("%s error: %s (%d)\n", __func__, FRESULT_str(fr), fr); + if (tracing) + printf("%s error: %s (%d)\n", __func__, FRESULT_str(fr), fr); free(fp); fp = 0; } @@ -185,16 +186,23 @@ char *ff_getcwd(char *pcBuffer, size_t xBufferLength) { // TCHAR* buff, /* [OUT] Buffer to return path name */ // UINT len /* [IN] The length of the buffer */ //); - FRESULT fr = f_getcwd(pcBuffer, xBufferLength); + char buf[xBufferLength]; + FRESULT fr = f_getcwd(buf, xBufferLength); if (tracing && FR_OK != fr) printf("%s error: %s (%d)\n", __func__, FRESULT_str(fr), fr); errno = fresult2errno(fr); // If the current working directory name was successfully written to // pcBuffer then pcBuffer is returned. Otherwise NULL is returned. - if (FR_OK == fr) + if (FR_OK == fr) { + if ('/' != buf[0]) { + char *p = strchr(buf, '/'); + if (!p) p = buf; + strncpy(pcBuffer, p, xBufferLength); + } return pcBuffer; - else + } else { return NULL; + } } int ff_mkdir(const char *pcDirectoryName) { TRACE_PRINTF("%s(pxStream=%s)\n", __func__, pcDirectoryName); @@ -208,7 +216,7 @@ int ff_mkdir(const char *pcDirectoryName) { return -1; } int ff_fputc(int iChar, FF_FILE *pxStream) { - //TRACE_PRINTF("%s(iChar=%c,pxStream=%p)\n", __func__, iChar, pxStream); + // TRACE_PRINTF("%s(iChar=%c,pxStream=%p)\n", __func__, iChar, pxStream); // FRESULT f_write ( // FIL* fp, /* [IN] Pointer to the file object structure */ // const void* buff, /* [IN] Pointer to the data to be written */ @@ -233,7 +241,7 @@ int ff_fputc(int iChar, FF_FILE *pxStream) { } } int ff_fgetc(FF_FILE *pxStream) { - //TRACE_PRINTF("%s(pxStream=%p)\n", __func__, pxStream); + // TRACE_PRINTF("%s(pxStream=%p)\n", __func__, pxStream); // FRESULT f_read ( // FIL* fp, /* [IN] File object */ // void* buff, /* [OUT] Buffer to store read data */ @@ -310,7 +318,7 @@ int ff_fseek(FF_FILE *pxStream, int iOffset, int iWhence) { return -1; } int ff_findfirst(const char *pcDirectory, FF_FindData_t *pxFindData) { - TRACE_PRINTF("%s(%s)\n", __func__, pcDirectory); + TRACE_PRINTF("%s(%s)\n", __func__, pcDirectory); // FRESULT f_findfirst ( // DIR* dp, /* [OUT] Poninter to the directory object */ // FILINFO* fno, /* [OUT] Pointer to the file information structure @@ -372,13 +380,17 @@ FF_FILE *ff_truncate(const char *pcFileName, long lTruncateSize) { } FRESULT fr = f_open(fp, pcFileName, FA_CREATE_ALWAYS | FA_WRITE); if (tracing && FR_OK != fr) - printf("%s error: %s (%d)\n", __func__, FRESULT_str(fr), fr); + printf("%s: f_open error: %s (%d)\n", __func__, FRESULT_str(fr), fr); errno = fresult2errno(fr); if (FR_OK != fr) return NULL; fr = f_lseek(fp, lTruncateSize); errno = fresult2errno(fr); + if (tracing && FR_OK != fr) + printf("%s: f_lseek error: %s (%d)\n", __func__, FRESULT_str(fr), fr); if (FR_OK != fr) return NULL; fr = f_truncate(fp); + if (tracing && FR_OK != fr) + printf("%s: f_truncate error: %s (%d)\n", __func__, FRESULT_str(fr), fr); errno = fresult2errno(fr); if (FR_OK == fr) return fp; diff --git a/src/glue.c b/src/glue.c index 55930eb..e8bcf5a 100644 --- a/src/glue.c +++ b/src/glue.c @@ -28,7 +28,7 @@ DSTATUS disk_status(BYTE pdrv /* Physical drive nmuber to identify the drive */ TRACE_PRINTF(">>> %s\n", __FUNCTION__); sd_card_t *p_sd = sd_get_by_num(pdrv); if (!p_sd) return RES_PARERR; - return sd_init(p_sd); + return sd_init_card(p_sd); } /*-----------------------------------------------------------------------*/ @@ -41,7 +41,7 @@ DSTATUS disk_initialize( TRACE_PRINTF(">>> %s\n", __FUNCTION__); sd_card_t *p_sd = sd_get_by_num(pdrv); if (!p_sd) return RES_PARERR; - return sd_init(p_sd); + return sd_init_card(p_sd); } static int sdrc2dresult(int sd_rc) { diff --git a/tests/app4-IO_module_function_checker.c b/tests/app4-IO_module_function_checker.c index 0199ccf..8bac19d 100644 --- a/tests/app4-IO_module_function_checker.c +++ b/tests/app4-IO_module_function_checker.c @@ -296,13 +296,13 @@ int test_diskio ( //int main (int argc, char* argv[]) -int lliot() +int lliot(size_t pnum) { int rc; DWORD buff[FF_MAX_SS]; /* Working buffer (4 sector in size) */ /* Check function/compatibility of the physical drive #0 */ - rc = test_diskio(0, 3, buff, sizeof buff); + rc = test_diskio(pnum, 3, buff, sizeof buff); if (rc) { printf("Sorry the function/compatibility test failed. (rc=%d)\nFatFs will not work with this disk driver.\n", rc); diff --git a/tests/simple.c b/tests/simple.c index 181c854..b540e46 100644 --- a/tests/simple.c +++ b/tests/simple.c @@ -5,8 +5,8 @@ #include #include // -#include "ff.h" #include "f_util.h" +#include "ff.h" // Maximum number of elements in buffer #define BUFFER_MAX_LEN 10 @@ -14,89 +14,55 @@ #define TRACE_PRINTF(fmt, args...) //#define TRACE_PRINTF printf -void ls() { - char pcWriteBuffer[128] = {0}; +extern void ls(const char *dir); + +void simple() { + printf("\nSimple Test\n"); - FRESULT fr; /* Return value */ - fr = f_getcwd(pcWriteBuffer, sizeof pcWriteBuffer); + char cwdbuf[FF_LFN_BUF - 12] = {0}; + FRESULT fr = f_getcwd(cwdbuf, sizeof cwdbuf); if (FR_OK != fr) { printf("f_getcwd error: %s (%d)\n", FRESULT_str(fr), fr); return; } - printf("Directory Listing: %s\n", pcWriteBuffer); - - DIR dj; /* Directory object */ - FILINFO fno; /* File information */ - memset (&dj, 0, sizeof dj); - memset (&fno, 0, sizeof fno); - TRACE_PRINTF("%s: f_findfirst(path=%s)\n", __func__, pcWriteBuffer); - fr = f_findfirst(&dj, &fno, pcWriteBuffer, "*"); - if (FR_OK != fr) { - printf("f_findfirst error: %s (%d)\n", FRESULT_str(fr), fr); - return; - } - while (fr == FR_OK && fno.fname[0]) { /* Repeat while an item is found */ - /* Create a string that includes the file name, the file size and the - attributes string. */ - const char *pcWritableFile = "writable file", - *pcReadOnlyFile = "read only file", - *pcDirectory = "directory"; - const char *pcAttrib; - /* Point pcAttrib to a string that describes the file. */ - if (fno.fattrib & AM_DIR) { - pcAttrib = pcDirectory; - } else if (fno.fattrib & AM_RDO) { - pcAttrib = pcReadOnlyFile; - } else { - pcAttrib = pcWritableFile; - } - /* Create a string that includes the file name, the file size and the - attributes string. */ - printf("%s [%s] [size=%llu]\n", fno.fname, pcAttrib, fno.fsize); - - fr = f_findnext(&dj, &fno); /* Search for next item */ - } - - f_closedir(&dj); -} - -void simple() { - printf("\nSimple Test\n"); - // Open the numbers file printf("Opening \"numbers.txt\"... "); FIL f; - FRESULT fc = f_open(&f, "numbers.txt", FA_READ | FA_WRITE); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); + fr = f_open(&f, "numbers.txt", FA_READ | FA_WRITE); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); fflush(stdout); - if (FR_OK != fc && FR_NO_FILE != fc) { - printf("f_open error: %s (%d)\n", FRESULT_str(fc), fc); + if (FR_OK != fr && FR_NO_FILE != fr) { + printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); return; - } else if (FR_NO_FILE == fc) { + } else if (FR_NO_FILE == fr) { // Create the numbers file if it doesn't exist printf("No file found, creating a new file... "); fflush(stdout); - fc = f_open(&f, "numbers.txt", - FA_CREATE_ALWAYS | FA_WRITE | FA_READ); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); - if (FR_OK != fc) printf("f_open error: %s (%d)\n", FRESULT_str(fc), fc); + fr = f_open(&f, "numbers.txt", FA_CREATE_ALWAYS | FA_WRITE | FA_READ); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); + if (FR_OK != fr) printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); fflush(stdout); for (int i = 0; i < 10; i++) { printf("\rWriting numbers (%d/%d)... ", i, 10); fflush(stdout); - fc = f_printf(&f, " %d\n", i); - if (FR_OK != fc) { + // When the string was written successfuly, it returns number of + // character encoding units written to the file. When the function + // failed due to disk full or any error, a negative value will be + // returned. + int rc = f_printf(&f, " %d\n", i); + if (rc < 0) { printf("Fail :(\n"); - printf("f_printf error: %s (%d)\n", FRESULT_str(fc), fc); + printf("f_printf error: %s (%d)\n", FRESULT_str(fr), fr); } } printf("\rWriting numbers (%d/%d)... OK\n", 10, 10); fflush(stdout); printf("Seeking file... "); - fc = f_lseek(&f, 0); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); - if (FR_OK != fc) printf("f_lseek error: %s (%d)\n", FRESULT_str(fc), fc); + fr = f_lseek(&f, 0); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); + if (FR_OK != fr) + printf("f_lseek error: %s (%d)\n", FRESULT_str(fr), fr); fflush(stdout); } // Go through and increment the numbers @@ -134,23 +100,25 @@ void simple() { // Close the file which also flushes any cached writes printf("Closing \"numbers.txt\"... "); - fc = f_close(&f); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); - if (FR_OK != fc) printf("f_close error: %s (%d)\n", FRESULT_str(fc), fc); + fr = f_close(&f); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); + if (FR_OK != fr) printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); fflush(stdout); - ls(); + ls(""); - fc = f_chdir("/"); - if (FR_OK != fc) printf("chdir error: %s (%d)\n", FRESULT_str(fc), fc); + fr = f_chdir("/"); + if (FR_OK != fr) printf("chdir error: %s (%d)\n", FRESULT_str(fr), fr); - ls(); + ls(""); // Display the numbers file - printf("Opening \"numbers.txt\"... "); - fc = f_open(&f, "numbers.txt", FA_READ); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); - if (FR_OK != fc) printf("f_open error: %s (%d)\n", FRESULT_str(fc), fc); + char pathbuf[FF_LFN_BUF] = {0}; + snprintf(pathbuf, sizeof pathbuf, "%s/%s", cwdbuf, "numbers.txt"); + printf("Opening \"%s\"... ", pathbuf); + fr = f_open(&f, pathbuf, FA_READ); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); + if (FR_OK != fr) printf("f_open error: %s (%d)\n", FRESULT_str(fr), fr); fflush(stdout); printf("numbers:\n"); @@ -158,16 +126,16 @@ void simple() { // int c = f_getc(f); char c; UINT br; - fc = f_read(&f, &c, sizeof c, &br); - if (FR_OK != fc) - printf("f_read error: %s (%d)\n", FRESULT_str(fc), fc); + fr = f_read(&f, &c, sizeof c, &br); + if (FR_OK != fr) + printf("f_read error: %s (%d)\n", FRESULT_str(fr), fr); else printf("%c", c); } - printf("\nClosing \"numbers.txt\"... "); - fc = f_close(&f); - printf("%s\n", (FR_OK != fc ? "Fail :(" : "OK")); - if (FR_OK != fc) printf("f_close error: %s (%d)\n", FRESULT_str(fc), fc); + printf("\nClosing \"%s\"... ", pathbuf); + fr = f_close(&f); + printf("%s\n", (FR_OK != fr ? "Fail :(" : "OK")); + if (FR_OK != fr) printf("f_close error: %s (%d)\n", FRESULT_str(fr), fr); fflush(stdout); }