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
|
USEMODULE += xtimer
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter mtd_sdcard,$(USEMODULE)))
|
||||||
|
USEMODULE += mtd
|
||||||
|
USEMODULE += sdcard_spi
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter nrfmin,$(USEMODULE)))
|
ifneq (,$(filter nrfmin,$(USEMODULE)))
|
||||||
FEATURES_REQUIRED += radio_nrfmin
|
FEATURES_REQUIRED += radio_nrfmin
|
||||||
FEATURES_REQUIRED += periph_cpuid
|
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).
|
* @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);
|
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_cid(sdcard_spi_t *card);
|
||||||
static sd_rw_response_t _read_csd(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 _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*/
|
/* 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);
|
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);
|
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 */
|
/* 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
|
/* 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 */
|
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;
|
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;
|
int trans_ret;
|
||||||
unsigned trans_bytes = 0;
|
unsigned trans_bytes = 0;
|
||||||
char in_temp;
|
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);
|
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)
|
int nbl, sd_rw_response_t *state)
|
||||||
{
|
{
|
||||||
_select_card_spi(card);
|
_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)
|
int nblocks, sd_rw_response_t *state)
|
||||||
{
|
{
|
||||||
if (nblocks > 1) {
|
if (nblocks > 1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user