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:
Sat Mar 24 16:27:20 2018 +0000
Revision:
0:131c3e1d831e
1.0.0 Release

Who changed what in which revision?

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