mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
Merge pull request #7324 from MichelRottleuthner/sdcard_mtd
sdcard_spi: integrate to mtd interface
This commit is contained in:
parent
39426bba7d
commit
e5baef3810
@ -159,6 +159,11 @@ ifneq (,$(filter mpu9150,$(USEMODULE)))
|
||||
USEMODULE += xtimer
|
||||
endif
|
||||
|
||||
ifneq (,$(filter mtd_sdcard,$(USEMODULE)))
|
||||
USEMODULE += mtd
|
||||
USEMODULE += sdcard_spi
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nrfmin,$(USEMODULE)))
|
||||
FEATURES_REQUIRED += radio_nrfmin
|
||||
FEATURES_REQUIRED += periph_cpuid
|
||||
|
67
drivers/include/mtd_sdcard.h
Normal file
67
drivers/include/mtd_sdcard.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_mtd_sdcard mtd wrapper for sdcard_spi
|
||||
* @ingroup drivers_storage
|
||||
* @brief Driver for SD-cards using mtd interface
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Interface definition for mtd_sdcard driver
|
||||
*
|
||||
* @author Michel Rottleuthner <michel.rottleuthner@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef MTD_SDCARD_H
|
||||
#define MTD_SDCARD_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sdcard_spi.h"
|
||||
#include "mtd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for mtd_sdcard device
|
||||
*
|
||||
* This is an extension of the @c mtd_dev_t struct
|
||||
*/
|
||||
typedef struct {
|
||||
mtd_dev_t base; /**< inherit from mtd_dev_t object */
|
||||
sdcard_spi_t *sd_card; /**< sdcard_spi dev descriptor */
|
||||
const sdcard_spi_params_t *params; /**< params for sdcard_spi init */
|
||||
} mtd_sdcard_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief sdcards handle sector erase internally so it's possible to directly
|
||||
* write to the card without erasing the sector first.
|
||||
* Attention: an erase call will therefore NOT touch the content,
|
||||
* so disable this feature to ensure overriding the data.
|
||||
*/
|
||||
#ifndef MTD_SDCARD_SKIP_ERASE
|
||||
#define MTD_SDCARD_SKIP_ERASE (1)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief sdcard device operations table for mtd
|
||||
*/
|
||||
extern const mtd_desc_t mtd_sdcard_driver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MTD_SDCARD_H */
|
||||
/** @} */
|
@ -252,7 +252,7 @@ int sdcard_spi_read_blocks(sdcard_spi_t *card, int blockaddr, char *data, int bl
|
||||
*
|
||||
* @return number of sucessfully written blocks (0 if no block was written).
|
||||
*/
|
||||
int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, char *data, int blocksize,
|
||||
int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, const char *data, int blocksize,
|
||||
int nblocks, sd_rw_response_t *state);
|
||||
|
||||
/**
|
||||
|
3
drivers/mtd_sdcard/Makefile
Normal file
3
drivers/mtd_sdcard/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = mtd_sdcard
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
121
drivers/mtd_sdcard/mtd_sdcard.c
Normal file
121
drivers/mtd_sdcard/mtd_sdcard.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int mtd_sdcard_init(mtd_dev_t *mtd);
|
||||
static int mtd_sdcard_read(mtd_dev_t *mtd, void *dest, uint32_t addr,
|
||||
uint32_t size);
|
||||
static int mtd_sdcard_write(mtd_dev_t *mtd, const void *src, uint32_t addr,
|
||||
uint32_t size);
|
||||
static int mtd_sdcard_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size);
|
||||
static int mtd_sdcard_power(mtd_dev_t *mtd, enum mtd_power_state power);
|
||||
|
||||
const mtd_desc_t mtd_sdcard_driver = {
|
||||
.init = mtd_sdcard_init,
|
||||
.read = mtd_sdcard_read,
|
||||
.write = mtd_sdcard_write,
|
||||
.erase = mtd_sdcard_erase,
|
||||
.power = mtd_sdcard_power,
|
||||
};
|
||||
|
||||
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:%lu size:%lu\n", addr, size);
|
||||
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
|
||||
sd_rw_response_t err;
|
||||
int res = 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 res * SD_HC_BLOCK_SIZE;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int mtd_sdcard_write(mtd_dev_t *dev, const void *buff, uint32_t addr,
|
||||
uint32_t size)
|
||||
{
|
||||
DEBUG("mtd_sdcard_write: addr:%lu size:%lu\n", addr, size);
|
||||
mtd_sdcard_t *mtd_sd = (mtd_sdcard_t*)dev;
|
||||
sd_rw_response_t err;
|
||||
int res = 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 res * SD_HC_BLOCK_SIZE;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int mtd_sdcard_erase(mtd_dev_t *dev,
|
||||
uint32_t addr,
|
||||
uint32_t size)
|
||||
{
|
||||
DEBUG("mtd_sdcard_erase: addr:%lu size:%lu\n", addr, size);
|
||||
(void)dev;
|
||||
(void)addr;
|
||||
(void)size;
|
||||
|
||||
#if MTD_SDCARD_SKIP_ERASE == 1
|
||||
return 0;
|
||||
#else
|
||||
return -ENOTSUP; /* explicit erase currently not supported */
|
||||
#endif
|
||||
}
|
||||
|
||||
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 */
|
||||
}
|
@ -40,7 +40,7 @@ static sd_init_fsm_state_t _init_sd_fsm_step(sdcard_spi_t *card, sd_init_fsm_sta
|
||||
static sd_rw_response_t _read_cid(sdcard_spi_t *card);
|
||||
static sd_rw_response_t _read_csd(sdcard_spi_t *card);
|
||||
static sd_rw_response_t _read_data_packet(sdcard_spi_t *card, char token, char *data, int size);
|
||||
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char *data, int size);
|
||||
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, const char *data, int size);
|
||||
|
||||
/* CRC-7 (polynomial: x^7 + x^3 + 1) LSB of CRC-7 in a 8-bit variable is always 1*/
|
||||
static char _crc_7(const char *data, int n);
|
||||
@ -49,7 +49,7 @@ static char _crc_7(const char *data, int n);
|
||||
static uint16_t _crc_16(const char *data, size_t n);
|
||||
|
||||
/* use this transfer method instead of _transfer_bytes to force the use of 0xFF as dummy bytes */
|
||||
static inline int _transfer_bytes(sdcard_spi_t *card, char *out, char *in, unsigned int length);
|
||||
static inline int _transfer_bytes(sdcard_spi_t *card, const char *out, char *in, unsigned int length);
|
||||
|
||||
/* uses bitbanging for spi communication which allows to enable pull-up on the miso pin for
|
||||
greater card compatibility on platforms that don't have a hw pull up installed */
|
||||
@ -576,7 +576,7 @@ static inline int _hw_spi_rxtx_byte(sdcard_spi_t *card, char out, char *in){
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int _transfer_bytes(sdcard_spi_t *card, char *out, char *in, unsigned int length){
|
||||
static inline int _transfer_bytes(sdcard_spi_t *card, const char *out, char *in, unsigned int length){
|
||||
int trans_ret;
|
||||
unsigned trans_bytes = 0;
|
||||
char in_temp;
|
||||
@ -703,7 +703,7 @@ int sdcard_spi_read_blocks(sdcard_spi_t *card, int blockaddr, char *data, int bl
|
||||
}
|
||||
}
|
||||
|
||||
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char *data, int size)
|
||||
static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, const char *data, int size)
|
||||
{
|
||||
|
||||
spi_transfer_byte(card->params.spi_dev, GPIO_UNDEF, true, token);
|
||||
@ -758,7 +758,7 @@ static sd_rw_response_t _write_data_packet(sdcard_spi_t *card, char token, char
|
||||
}
|
||||
}
|
||||
|
||||
static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, char *data, int blsz,
|
||||
static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, const char *data, int blsz,
|
||||
int nbl, sd_rw_response_t *state)
|
||||
{
|
||||
_select_card_spi(card);
|
||||
@ -823,7 +823,7 @@ static inline int _write_blocks(sdcard_spi_t *card, char cmd_idx, int bladdr, ch
|
||||
}
|
||||
}
|
||||
|
||||
int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, char *data, int blocksize,
|
||||
int sdcard_spi_write_blocks(sdcard_spi_t *card, int blockaddr, const char *data, int blocksize,
|
||||
int nblocks, sd_rw_response_t *state)
|
||||
{
|
||||
if (nblocks > 1) {
|
||||
|
Loading…
Reference in New Issue
Block a user