Block device class for creating a block device to access a SD/MMC card via SD/MMC interface on DISCO_F746NG

Dependencies:   BSP_DISCO_F746NG

Dependents:   DISCO-F746NG_BLOCK_DEVICE_SDCARD DISCO-F746NG_BLOCK_DEVICE_WITH_FAT_FILESYSTEM_ON_SDCARD SDReaderTest

Block device class for creating a block device to access a SD/MMC card via SD/MMC interface on DISCO_F746NG development board. This block device API provides an interface for access to block-based storage. You can use a block device to back a full file system or write to it directly. More about Block Devices

http://www.st.com/content/ccc/fragment/product_related/rpn_information/board_photo/group0/ea/c4/6d/73/c3/f5/46/e2/stm32f746g-disco/files/stm32f746g-disco.jpg/_jcr_content/translations/en.stm32f746g-disco.jpg

Simple example how to use the block device

/* Example file of using SD/MMC Block device Library for MBED-OS
 * Copyright 2017 Roy Krikke
 *
 * 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 "SDBlockDeviceDISCOF746NG.h"

DigitalOut led (LED1);

// Instantiate the Block Device for sd card on DISCO-F746NG
SDBlockDeviceDISCOF746NG bd;
uint8_t block[512] = "Hello World!\n";

int
main ()
{
    Serial pc (SERIAL_TX, SERIAL_RX);
    pc.baud(115200);
    printf("Start\n");

    // Call the SDBlockDeviceDISCOF746NG instance initialisation method.
    printf("sd card init...\n");
    if (0 != bd.init()) {
        printf("Init failed \n");
        return -1;
    }

    printf("sd size: %llu\n", bd.size());
    printf("sd read size: %llu\n", bd.get_read_size());
    printf("sd program size: %llu\n", bd.get_program_size());
    printf("sd erase size: %llu\n\n", bd.get_erase_size());

    printf("sd erase...\n");
    if (0 != bd.erase (0, bd.get_erase_size())) {
        printf("Error Erasing block \n");
    }

    // Write some the data block to the device
    printf("sd write: %s\n", block);
    if (0 == bd.program(block, 0, 512)) {
        // read the data block from the device
        printf("sd read: ");
        if (0 == bd.read(block, 0, 512)) {
            // print the contents of the block
            printf("%s", block);
        }
    }

////////////////////////////////////////////////////////////////////////////////

    for(int i; i < 10; i++) {
        memset(block, i, sizeof(block));
        if(bd.program(block, (i*512), sizeof(block)) != 0) {
            printf("Error at: %i\r\n",i);
        }
    }

    if(bd.erase((1*512), sizeof(block)) != 0) {
        printf("Error Erasing block\n");
    }

    memset(block, 'x', sizeof(block));
    if(bd.program(block, (1*512), sizeof(block)) != 0) {
        printf("Error\r\n");
    }

////////////////////////////////////////////////////////////////////////////////

    // Call the BD_SD_DISCO_F746NG instance de-initialisation method.
    printf("sd card deinit...\n");
    if (0 != bd.deinit()) {
        printf ("Deinit failed \n");
        return -1;
    }

    // Blink led with 2 Hz
    while(true) {
        led = !led;
        wait (0.5);
    }
}

Simple example how to use the block device to create a file on a FAT file system

/* Example file of using SD/MMC Block device Library for MBED-OS
 * Copyright 2017 Roy Krikke
 *
 * 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 "FATFileSystem.h"
#include "SDBlockDeviceDISCOF746NG.h"
#include <stdio.h>
#include <errno.h>

DigitalOut led (LED1);

// Instantiate the Block Device for sd card on DISCO-F746NG
SDBlockDeviceDISCOF746NG bd;
FATFileSystem fs ("fs");

void
return_error (int ret_val)
{
    if(ret_val)
        printf ("Failure. %d\r\n", ret_val);
    else
        printf ("done.\r\n");
}

void
errno_error (void* ret_val)
{
    if(ret_val == NULL)
        printf (" Failure. %d \r\n", errno);
    else
        printf (" done.\r\n");
}

int
main ()
{
    Serial pc (SERIAL_TX, SERIAL_RX);
    pc.baud(115200);
    printf("Start\n");

    int error = 0;
    printf("Welcome to the filesystem example.\r\n"
           "Formatting a FAT, RAM-backed filesystem. ");
    error = FATFileSystem::format(&bd);
    return_error(error);

    printf("Mounting the filesystem on \"/fs\". ");
    error = fs.mount(&bd);
    return_error(error);

    printf("Opening a new file, numbers.txt.");
    FILE* fd = fopen("/fs/numbers.txt", "w");
    errno_error(fd);

    for (int i = 0; i < 20; i++) {
        printf("Writing decimal numbers to a file (%d/20)\r", i);
        fprintf(fd, "%d\r\n", i);
    }
    printf("Writing decimal numbers to a file (20/20) done.\r\n");

    printf("Closing file.");
    fclose(fd);
    printf(" done.\r\n");

    printf("Re-opening file read-only.");
    fd = fopen("/fs/numbers.txt", "r");
    errno_error(fd);

    printf("Dumping file to screen.\r\n");
    char buff[16] = { 0 };
    while(!feof (fd)) {
        int size = fread(&buff[0], 1, 15, fd);
        fwrite(&buff[0], 1, size, stdout);
    }
    printf("EOF.\r\n");

    printf("Closing file.");
    fclose(fd);
    printf(" done.\r\n");

    printf("Opening root directory.");
    DIR* dir = opendir("/fs/");
    errno_error(fd);

    struct dirent* de;
    printf("Printing all filenames:\r\n");
    while((de = readdir (dir)) != NULL) {
        printf("  %s\r\n", &(de->d_name)[0]);
    }

    printf("Closeing root directory. ");
    error = closedir(dir);
    return_error(error);
    printf("Filesystem Demo complete.\r\n");

    // Blink led with 2 Hz
    while(true) {
        led = !led;
        wait (0.5);
    }
}

Committer:
roykrikke
Date:
Wed Apr 04 19:43:06 2018 +0000
Revision:
1:d1d99cfe13df
Code Style & Formatting

Who changed what in which revision?

UserRevisionLine numberNew contents of line
roykrikke 1:d1d99cfe13df 1 /* SD/MMC Block device Library for MBED-OS
roykrikke 1:d1d99cfe13df 2 * Copyright 2017 Roy Krikke
roykrikke 1:d1d99cfe13df 3 *
roykrikke 1:d1d99cfe13df 4 * Licensed under the Apache License, Version 2.0 (the "License");
roykrikke 1:d1d99cfe13df 5 * you may not use this file except in compliance with the License.
roykrikke 1:d1d99cfe13df 6 * You may obtain a copy of the License at
roykrikke 1:d1d99cfe13df 7 *
roykrikke 1:d1d99cfe13df 8 * http://www.apache.org/licenses/LICENSE-2.0
roykrikke 1:d1d99cfe13df 9 *
roykrikke 1:d1d99cfe13df 10 * Unless required by applicable law or agreed to in writing, software
roykrikke 1:d1d99cfe13df 11 * distributed under the License is distributed on an "AS IS" BASIS,
roykrikke 1:d1d99cfe13df 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
roykrikke 1:d1d99cfe13df 13 * See the License for the specific language governing permissions and
roykrikke 1:d1d99cfe13df 14 * limitations under the License.
roykrikke 1:d1d99cfe13df 15 *
roykrikke 1:d1d99cfe13df 16 */
roykrikke 1:d1d99cfe13df 17
roykrikke 1:d1d99cfe13df 18 #ifndef BD_SD_DISCO_F746NG_H
roykrikke 1:d1d99cfe13df 19 #define BD_SD_DISCO_F746NG_H
roykrikke 1:d1d99cfe13df 20
roykrikke 1:d1d99cfe13df 21 #include "mbed.h"
roykrikke 1:d1d99cfe13df 22 #include "BlockDevice.h"
roykrikke 1:d1d99cfe13df 23 #include "platform/PlatformMutex.h"
roykrikke 1:d1d99cfe13df 24 #include "stm32746g_discovery_sd.h"
roykrikke 1:d1d99cfe13df 25
roykrikke 1:d1d99cfe13df 26 #define BD_SD_DISCO_F746NG_MAJOR_VERSION 1
roykrikke 1:d1d99cfe13df 27 #define BD_SD_DISCO_F746NG_MINOR_VERSION 0
roykrikke 1:d1d99cfe13df 28 #define BD_SD_DISCO_F746NG_PATCH_VERSION 0
roykrikke 1:d1d99cfe13df 29
roykrikke 1:d1d99cfe13df 30 /**
roykrikke 1:d1d99cfe13df 31 * BD_SD_DISCO_F746NG class.
roykrikke 1:d1d99cfe13df 32 * Block device class for creating a block device to access a SD/MMC card via SD/MMC interface on DISCO_F746NG
roykrikke 1:d1d99cfe13df 33 *
roykrikke 1:d1d99cfe13df 34 * Example:
roykrikke 1:d1d99cfe13df 35 * @code
roykrikke 1:d1d99cfe13df 36 * #include "mbed.h"
roykrikke 1:d1d99cfe13df 37 * #include "SDBlockDeviceDISCOF746NG.h"
roykrikke 1:d1d99cfe13df 38 *
roykrikke 1:d1d99cfe13df 39 * DigitalOut led (LED1);
roykrikke 1:d1d99cfe13df 40 *
roykrikke 1:d1d99cfe13df 41 * // Instantiate the Block Device for sd card on DISCO-F746NG
roykrikke 1:d1d99cfe13df 42 * SDBlockDeviceDISCOF746NG bd;
roykrikke 1:d1d99cfe13df 43 * uint8_t block[512] = "Hello World!\n";
roykrikke 1:d1d99cfe13df 44 *
roykrikke 1:d1d99cfe13df 45 * int
roykrikke 1:d1d99cfe13df 46 * main () {
roykrikke 1:d1d99cfe13df 47 * Serial pc(SERIAL_TX, SERIAL_RX);
roykrikke 1:d1d99cfe13df 48 * pc.baud (115200);
roykrikke 1:d1d99cfe13df 49 * printf("Start\n");
roykrikke 1:d1d99cfe13df 50 *
roykrikke 1:d1d99cfe13df 51 * // Call the SDBlockDevice-DISCO-F746NG instance initialisation method.
roykrikke 1:d1d99cfe13df 52 * printf("sd card init...\n");
roykrikke 1:d1d99cfe13df 53 * if (0 != bd.init ()) {
roykrikke 1:d1d99cfe13df 54 * printf("Init failed \n");
roykrikke 1:d1d99cfe13df 55 * return -1;
roykrikke 1:d1d99cfe13df 56 * }
roykrikke 1:d1d99cfe13df 57 *
roykrikke 1:d1d99cfe13df 58 * printf("sd size: %llu\n", bd.size ());
roykrikke 1:d1d99cfe13df 59 * printf("sd read size: %llu\n", bd.get_read_size ());
roykrikke 1:d1d99cfe13df 60 * printf("sd program size: %llu\n", bd.get_program_size ());
roykrikke 1:d1d99cfe13df 61 * printf("sd erase size: %llu\n\n", bd.get_erase_size ());
roykrikke 1:d1d99cfe13df 62 *
roykrikke 1:d1d99cfe13df 63 * printf("sd erase...\n");
roykrikke 1:d1d99cfe13df 64 * if (0 != bd.erase (0, bd.get_erase_size ())) {
roykrikke 1:d1d99cfe13df 65 * printf ("Error Erasing block \n");
roykrikke 1:d1d99cfe13df 66 * }
roykrikke 1:d1d99cfe13df 67 *
roykrikke 1:d1d99cfe13df 68 * // Write some the data block to the device
roykrikke 1:d1d99cfe13df 69 * printf("sd write: %s\n", block);
roykrikke 1:d1d99cfe13df 70 * if (0 == bd.program (block, 0, 512)) {
roykrikke 1:d1d99cfe13df 71 * // read the data block from the device
roykrikke 1:d1d99cfe13df 72 * printf ("sd read: ");
roykrikke 1:d1d99cfe13df 73 * if (0 == bd.read (block, 0, 512)) {
roykrikke 1:d1d99cfe13df 74 * // print the contents of the block
roykrikke 1:d1d99cfe13df 75 * printf ("%s", block);
roykrikke 1:d1d99cfe13df 76 * }
roykrikke 1:d1d99cfe13df 77 * }
roykrikke 1:d1d99cfe13df 78 *
roykrikke 1:d1d99cfe13df 79 * // Call the BD_SD_DISCO_F746NG instance de-initialisation method.
roykrikke 1:d1d99cfe13df 80 * printf("sd card deinit...\n");
roykrikke 1:d1d99cfe13df 81 * if(0 != bd.deinit ()) {
roykrikke 1:d1d99cfe13df 82 * printf ("Deinit failed \n");
roykrikke 1:d1d99cfe13df 83 * return -1;
roykrikke 1:d1d99cfe13df 84 * }
roykrikke 1:d1d99cfe13df 85 *
roykrikke 1:d1d99cfe13df 86 * // Blink led with 2 Hz
roykrikke 1:d1d99cfe13df 87 * while(true) {
roykrikke 1:d1d99cfe13df 88 * led = !led;
roykrikke 1:d1d99cfe13df 89 * wait (0.5);
roykrikke 1:d1d99cfe13df 90 * }
roykrikke 1:d1d99cfe13df 91 * }
roykrikke 1:d1d99cfe13df 92 * @endcode
roykrikke 1:d1d99cfe13df 93 *
roykrikke 1:d1d99cfe13df 94 */
roykrikke 1:d1d99cfe13df 95 class SDBlockDeviceDISCOF746NG : public BlockDevice
roykrikke 1:d1d99cfe13df 96 {
roykrikke 1:d1d99cfe13df 97 public:
roykrikke 1:d1d99cfe13df 98
roykrikke 1:d1d99cfe13df 99 /** Lifetime of the memory block device
roykrikke 1:d1d99cfe13df 100 *
roykrikke 1:d1d99cfe13df 101 * Only a block size of 512 bytes is supported
roykrikke 1:d1d99cfe13df 102 *
roykrikke 1:d1d99cfe13df 103 */
roykrikke 1:d1d99cfe13df 104 SDBlockDeviceDISCOF746NG();
roykrikke 1:d1d99cfe13df 105 virtual ~SDBlockDeviceDISCOF746NG();
roykrikke 1:d1d99cfe13df 106
roykrikke 1:d1d99cfe13df 107 /** Initialize a block device
roykrikke 1:d1d99cfe13df 108 *
roykrikke 1:d1d99cfe13df 109 * @return 0 on success or a negative error code on failure
roykrikke 1:d1d99cfe13df 110 */
roykrikke 1:d1d99cfe13df 111 virtual int init();
roykrikke 1:d1d99cfe13df 112
roykrikke 1:d1d99cfe13df 113 /** Deinitialize a block device
roykrikke 1:d1d99cfe13df 114 *
roykrikke 1:d1d99cfe13df 115 * @return 0 on success or a negative error code on failure
roykrikke 1:d1d99cfe13df 116 */
roykrikke 1:d1d99cfe13df 117 virtual int deinit();
roykrikke 1:d1d99cfe13df 118
roykrikke 1:d1d99cfe13df 119 /** Read blocks from a block device
roykrikke 1:d1d99cfe13df 120 *
roykrikke 1:d1d99cfe13df 121 * @param buffer Buffer to read blocks into
roykrikke 1:d1d99cfe13df 122 * @param addr Address of block to begin reading from
roykrikke 1:d1d99cfe13df 123 * @param size Size to read in bytes, must be a multiple of read block size
roykrikke 1:d1d99cfe13df 124 * @return 0 on success, negative error code on failure
roykrikke 1:d1d99cfe13df 125 */
roykrikke 1:d1d99cfe13df 126 virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
roykrikke 1:d1d99cfe13df 127
roykrikke 1:d1d99cfe13df 128 /** Program blocks to a block device
roykrikke 1:d1d99cfe13df 129 *
roykrikke 1:d1d99cfe13df 130 * The blocks must have been erased prior to being programmed
roykrikke 1:d1d99cfe13df 131 *
roykrikke 1:d1d99cfe13df 132 * @param buffer Buffer of data to write to blocks
roykrikke 1:d1d99cfe13df 133 * @param addr Address of block to begin writing to
roykrikke 1:d1d99cfe13df 134 * @param size Size to write in bytes, must be a multiple of program block size
roykrikke 1:d1d99cfe13df 135 * @return 0 on success, negative error code on failure
roykrikke 1:d1d99cfe13df 136 */
roykrikke 1:d1d99cfe13df 137 virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
roykrikke 1:d1d99cfe13df 138
roykrikke 1:d1d99cfe13df 139 /** Erase blocks on a block device
roykrikke 1:d1d99cfe13df 140 *
roykrikke 1:d1d99cfe13df 141 * The state of an erased block is undefined until it has been programmed
roykrikke 1:d1d99cfe13df 142 *
roykrikke 1:d1d99cfe13df 143 * @param addr Address of block to begin erasing
roykrikke 1:d1d99cfe13df 144 * @param size Size to erase in bytes, must be a multiple of erase block size
roykrikke 1:d1d99cfe13df 145 * @return 0 on success, negative error code on failure
roykrikke 1:d1d99cfe13df 146 */
roykrikke 1:d1d99cfe13df 147 virtual int erase(bd_addr_t addr, bd_size_t size);
roykrikke 1:d1d99cfe13df 148
roykrikke 1:d1d99cfe13df 149 /** Get the size of a readable block
roykrikke 1:d1d99cfe13df 150 *
roykrikke 1:d1d99cfe13df 151 * @return Size of a readable block in bytes
roykrikke 1:d1d99cfe13df 152 */
roykrikke 1:d1d99cfe13df 153 virtual bd_size_t get_read_size() const;
roykrikke 1:d1d99cfe13df 154
roykrikke 1:d1d99cfe13df 155 /** Get the size of a programable block
roykrikke 1:d1d99cfe13df 156 *
roykrikke 1:d1d99cfe13df 157 * @return Size of a programable block in bytes
roykrikke 1:d1d99cfe13df 158 */
roykrikke 1:d1d99cfe13df 159 virtual bd_size_t get_program_size() const;
roykrikke 1:d1d99cfe13df 160
roykrikke 1:d1d99cfe13df 161 /** Get the size of a eraseable block
roykrikke 1:d1d99cfe13df 162 *
roykrikke 1:d1d99cfe13df 163 * @return Size of a eraseable block in bytes
roykrikke 1:d1d99cfe13df 164 */
roykrikke 1:d1d99cfe13df 165 virtual bd_size_t get_erase_size() const;
roykrikke 1:d1d99cfe13df 166
roykrikke 1:d1d99cfe13df 167 /** Get the total size of the underlying device
roykrikke 1:d1d99cfe13df 168 *
roykrikke 1:d1d99cfe13df 169 * @return Size of the underlying device in bytes
roykrikke 1:d1d99cfe13df 170 */
roykrikke 1:d1d99cfe13df 171 virtual bd_size_t size() const;
roykrikke 1:d1d99cfe13df 172
roykrikke 1:d1d99cfe13df 173 private:
roykrikke 1:d1d99cfe13df 174 uint8_t _card_type;
roykrikke 1:d1d99cfe13df 175 bd_size_t _read_size;
roykrikke 1:d1d99cfe13df 176 bd_size_t _program_size;
roykrikke 1:d1d99cfe13df 177 bd_size_t _erase_size;
roykrikke 1:d1d99cfe13df 178 bd_size_t _block_size;
roykrikke 1:d1d99cfe13df 179 bd_size_t _capacity_in_blocks;
roykrikke 1:d1d99cfe13df 180 BSP_SD_CardInfo _current_card_info;
roykrikke 1:d1d99cfe13df 181 uint8_t _sd_state;
roykrikke 1:d1d99cfe13df 182 uint32_t _timeout;
roykrikke 1:d1d99cfe13df 183 PlatformMutex _mutex;
roykrikke 1:d1d99cfe13df 184 bool _is_initialized;
roykrikke 1:d1d99cfe13df 185
roykrikke 1:d1d99cfe13df 186 virtual void
roykrikke 1:d1d99cfe13df 187 lock () {
roykrikke 1:d1d99cfe13df 188 _mutex.lock();
roykrikke 1:d1d99cfe13df 189 }
roykrikke 1:d1d99cfe13df 190
roykrikke 1:d1d99cfe13df 191 virtual void
roykrikke 1:d1d99cfe13df 192 unlock() {
roykrikke 1:d1d99cfe13df 193 _mutex.unlock ();
roykrikke 1:d1d99cfe13df 194 }
roykrikke 1:d1d99cfe13df 195
roykrikke 1:d1d99cfe13df 196 };
roykrikke 1:d1d99cfe13df 197
roykrikke 1:d1d99cfe13df 198 #endif /* BD_SD_DISCO_F746NG_H */