1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/mtd_sdcard/mtd_sdcard.c
Benjamin Valentin 7d291b5707 drivers/mtd_sdard: implement page-wise read() and write()
SD cards are usually larger than 4 GiB, so using 32 bit addressing will
break once they are filled to a certain extend.

Implement read_page() and write_page() which at a page size of 512
should work for SD cards of up to 2 TiB.

The read() and write() functions will ignore any offset that is not aligned
with the page boundary, so do the same for the new functions, but at least
report an error.
2020-08-18 17:25:39 +02:00

162 lines
4.5 KiB
C

/*
* Copyright (C) 2017 HAW-Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
*/
/**
* @ingroup drivers_mtd_sdcard
* @{
*
* @file
* @brief Driver for using sdcard_spi via mtd interface
*
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
*
* @}
*/
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "mtd.h"
#include "mtd_sdcard.h"
#include "sdcard_spi.h"
#include "sdcard_spi_internal.h"
#include "kernel_defines.h"
#include <inttypes.h>
#include <errno.h>
static int mtd_sdcard_init(mtd_dev_t *dev)
{
DEBUG("mtd_sdcard_init\n");
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
if ((mtd_sd->sd_card->init_done == true) ||
(sdcard_spi_init(mtd_sd->sd_card, mtd_sd->params) == 0)) {
/* erasing whole sectors is handled internally by the card so you can
delete single blocks (i.e. pages) */
dev->pages_per_sector = 1;
dev->sector_count = sdcard_spi_get_sector_count(mtd_sd->sd_card);
/* sdcard_spi always uses the fixed block size of SD-HC cards */
dev->page_size = SD_HC_BLOCK_SIZE;
return 0;
}
return -EIO;
}
static int mtd_sdcard_read(mtd_dev_t *dev, void *buff, uint32_t addr,
uint32_t size)
{
DEBUG("mtd_sdcard_read: addr:%" PRIu32 " size:%" PRIu32 "\n", addr, size);
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
sd_rw_response_t err;
sdcard_spi_read_blocks(mtd_sd->sd_card, addr / SD_HC_BLOCK_SIZE,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
if (err == SD_RW_OK) {
return 0;
}
return -EIO;
}
static int mtd_sdcard_read_page(mtd_dev_t *dev, void *buff, uint32_t page,
uint32_t offset, uint32_t size)
{
DEBUG("mtd_sdcard_read_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n",
page, offset, size);
if (offset) {
return -ENOTSUP;
}
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
sd_rw_response_t err;
int res = sdcard_spi_read_blocks(mtd_sd->sd_card, page,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
if (err != SD_RW_OK) {
return -EIO;
}
return res * SD_HC_BLOCK_SIZE;
}
static int mtd_sdcard_write(mtd_dev_t *dev, const void *buff, uint32_t addr,
uint32_t size)
{
DEBUG("mtd_sdcard_write: addr:%" PRIu32 " size:%" PRIu32 "\n", addr, size);
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
sd_rw_response_t err;
sdcard_spi_write_blocks(mtd_sd->sd_card, addr / SD_HC_BLOCK_SIZE,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
if (err == SD_RW_OK) {
return 0;
}
return -EIO;
}
static int mtd_sdcard_write_page(mtd_dev_t *dev, const void *buff, uint32_t page,
uint32_t offset, uint32_t size)
{
DEBUG("mtd_sdcard_write_page: page:%" PRIu32 " offset:%" PRIu32 " size:%" PRIu32 "\n",
page, offset, size);
if (offset) {
return -ENOTSUP;
}
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
sd_rw_response_t err;
int res = sdcard_spi_write_blocks(mtd_sd->sd_card, page,
buff, SD_HC_BLOCK_SIZE,
size / SD_HC_BLOCK_SIZE, &err);
if (err != SD_RW_OK) {
return -EIO;
}
return res * SD_HC_BLOCK_SIZE;
}
static int mtd_sdcard_erase(mtd_dev_t *dev,
uint32_t addr,
uint32_t size)
{
DEBUG("mtd_sdcard_erase: addr:%" PRIu32 " size:%" PRIu32 "\n", addr, size);
(void)dev;
(void)addr;
(void)size;
if (!IS_ACTIVE(CONFIG_MTD_SDCARD_ERASE)) {
return 0;
}
else {
return -ENOTSUP; /* explicit erase currently not supported */
}
}
static int mtd_sdcard_power(mtd_dev_t *dev, enum mtd_power_state power)
{
(void)dev;
(void)power;
/* TODO: implement power down of sdcard in sdcard_spi
(make use of sdcard_spi_params_t.power pin) */
return -ENOTSUP; /* currently not supported */
}
const mtd_desc_t mtd_sdcard_driver = {
.init = mtd_sdcard_init,
.read = mtd_sdcard_read,
.read_page = mtd_sdcard_read_page,
.write = mtd_sdcard_write,
.write_page = mtd_sdcard_write_page,
.erase = mtd_sdcard_erase,
.power = mtd_sdcard_power,
};