-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add flash emulation layer for native
[flashsim] Fix broken unit tests [flashsim] Add documentation [flashsim] Properly namespace error enum [flashsim] Fix header not renamed [fs] replace custom error codes with errnos
- Loading branch information
Showing
14 changed files
with
1,008 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Copyright (C) Lucas Jenß | ||
* | ||
* 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 native | ||
* @{ | ||
*/ | ||
|
||
/** | ||
* @file | ||
* @brief Emulates the MCI storage driver by providing an in-memory | ||
* backend. It is 8MiB by default and its size can be increased | ||
* using `NATIVE_MCI_SIZE_MULTIPLIER` which gets multiplied by | ||
* one MiB, resulting in the actual size of the virtual disk. | ||
* Additional parameters are: | ||
* | ||
* Sector (page) size: 512B | ||
* Eerase Block size: 512KiB (524288 Bytes) | ||
* | ||
* @author Lucas Jenß <lucas@x3ro.de> | ||
* | ||
*/ | ||
|
||
#include <string.h> | ||
#include <stdbool.h> | ||
#include "diskio.h" | ||
|
||
#include "storage/flash_sim.h" | ||
|
||
#define ENABLE_DEBUG (0) | ||
#include "debug.h" | ||
|
||
#ifndef NATIVE_MCI_SIZE_MULTIPLIER | ||
#define NATIVE_MCI_SIZE_MULTIPLIER 8 | ||
#endif | ||
|
||
#define NATIVE_MCI_SIZE (1024 * 1024 * NATIVE_MCI_SIZE_MULTIPLIER) | ||
#define NATIVE_MCI_SECTOR_SIZE (512) | ||
#define NATIVE_MCI_BLOCK_SIZE (512 * 1024) | ||
#define NATIVE_MCI_SECTOR_COUNT (NATIVE_MCI_SIZE / NATIVE_MCI_SECTOR_SIZE) | ||
|
||
flash_sim fs; | ||
|
||
bool _validate_parameters(unsigned long sector, unsigned char count) { | ||
if(count < 1) { | ||
return false; | ||
} | ||
|
||
if(sector + count > NATIVE_MCI_SECTOR_COUNT) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
DSTATUS MCI_initialize(void) { | ||
fs.page_size = NATIVE_MCI_SECTOR_SIZE; | ||
fs.block_size = NATIVE_MCI_BLOCK_SIZE; | ||
fs.storage_size = NATIVE_MCI_SIZE; | ||
flash_sim_init(&fs); | ||
|
||
return RES_OK; | ||
} | ||
|
||
DSTATUS MCI_status(void) { | ||
return RES_OK; | ||
} | ||
|
||
/* Read |count| sectors starting at |sector| (LBA) */ | ||
DRESULT MCI_read(unsigned char *buff, unsigned long sector, unsigned char count) { | ||
if(!_validate_parameters(sector, count)) { | ||
return RES_PARERR; | ||
} | ||
|
||
for(unsigned int i=0; i<count; i++) { | ||
unsigned char *page_buffer = buff + (i * NATIVE_MCI_SECTOR_SIZE); | ||
flash_sim_read(&fs, page_buffer, sector + i); | ||
} | ||
|
||
return RES_OK; | ||
} | ||
|
||
/* Write |count| sectors starting at |sector| (LBA) */ | ||
DRESULT MCI_write(const unsigned char *buff, unsigned long sector, unsigned char count) { | ||
if(!_validate_parameters(sector, count)) { | ||
return RES_PARERR; | ||
} | ||
|
||
for(unsigned int i=0; i<count; i++) { | ||
unsigned char *page_buffer = ((unsigned char*) buff) + (i * NATIVE_MCI_SECTOR_SIZE); | ||
flash_sim_write(&fs, page_buffer, sector + i); | ||
} | ||
|
||
return RES_OK; | ||
} | ||
|
||
DRESULT MCI_ioctl( | ||
unsigned char ctrl, /* Control code */ | ||
void *buff /* Buffer to send/receive data block */ | ||
) { | ||
DRESULT res = RES_ERROR; | ||
unsigned long block; | ||
|
||
switch(ctrl) { | ||
|
||
/* Get number of sectors on the disk (unsigned long) */ | ||
case GET_SECTOR_COUNT: | ||
*(unsigned long *) buff = NATIVE_MCI_SECTOR_COUNT; | ||
res = RES_OK; | ||
break; | ||
|
||
/* Get sector (page) size (unsigned short) */ | ||
case GET_SECTOR_SIZE: | ||
*(unsigned short *) buff = NATIVE_MCI_SECTOR_SIZE; | ||
res = RES_OK; | ||
break; | ||
|
||
/* Get erase block size (unsigned long) */ | ||
case GET_BLOCK_SIZE: | ||
*(unsigned long *) buff = NATIVE_MCI_BLOCK_SIZE; | ||
res = RES_OK; | ||
break; | ||
|
||
/* Erase a block of sectors */ | ||
case CTRL_ERASE_SECTOR: | ||
block = *(unsigned long *)buff; | ||
|
||
if(!_validate_parameters(block, 1)) { | ||
return RES_PARERR; | ||
} | ||
|
||
flash_sim_erase(&fs, block); | ||
res = RES_OK; | ||
break; | ||
|
||
/* Get card type flags (1 byte) */ | ||
case MMC_GET_TYPE: | ||
// Not implemented | ||
break; | ||
|
||
/* Get CSD (16 bytes) */ | ||
case MMC_GET_CSD: | ||
// Not implemented | ||
break; | ||
|
||
/* Get CID (16 bytes) */ | ||
case MMC_GET_CID: | ||
// Not implemented | ||
break; | ||
|
||
/* Get OCR (4 bytes) */ | ||
case MMC_GET_OCR: | ||
// Not implemented | ||
break; | ||
|
||
/* Receive SD status as a data block (64 bytes) */ | ||
case MMC_GET_SDSTAT: | ||
// Not implemented | ||
break; | ||
|
||
/* No-Ops for virtual MCI */ | ||
case CTRL_SYNC: /* Make sure that all data has been written on the media */ | ||
case CTRL_POWER: /* Power on/off */ | ||
res = RES_OK; | ||
break; | ||
|
||
default: | ||
res = RES_PARERR; | ||
} | ||
|
||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
/* | ||
* Copyright (C) 2015 Lucas Jenß | ||
* | ||
* 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 sys_storage | ||
* @brief | ||
* @{ | ||
* | ||
* @brief Simulates flash memory for easier testing of storage subsystems | ||
* @author Lucas Jenß <lucas@x3ro.de> | ||
*/ | ||
|
||
#ifndef _FS_FLASH_SIM_H | ||
#define _FS_FLASH_SIM_H | ||
|
||
#include <stdint.h> | ||
#include <stdbool.h> | ||
#include <stdio.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* @brief Configuration for the flash simulation layer | ||
*/ | ||
typedef struct flash_sim { | ||
uint32_t page_size; //!< Page size to be emulated | ||
uint32_t block_size; //!< Block size (must be a multiple of the page size) | ||
uint64_t storage_size; //!< Total amount of storage to be made available | ||
|
||
uint32_t pages; //!< Number of pages (computed from the above) | ||
FILE *_fp; //!< File descriptor for the file simulating the flash device | ||
} flash_sim; | ||
|
||
|
||
/** | ||
* @brief Initialize the flash simulation layer with the given configuration struct | ||
* @param fs Configuration | ||
* @return 0 on success | ||
* @return -EINVAL if the given configuration struct was invalid | ||
* @return -EBADFD if there was an error with the file used for simulated storage | ||
* @return Any error #flash_sim_format may return | ||
*/ | ||
int flash_sim_init(flash_sim *fs); | ||
|
||
/** | ||
* @brief Erases all blocks of the simulated flash device | ||
* @param fs Configuration | ||
* | ||
* @return 0 on success | ||
* @return -ENODEV if device has not been initialized | ||
* @return -EBADFD if there was an error with the file used for simulated storage | ||
*/ | ||
int flash_sim_format(flash_sim *fs); | ||
|
||
/** | ||
* @brief Reads the given page into the provided buffer | ||
* @param fs Configuration | ||
* @param buffer Target buffer (must be >= the size of a page) | ||
* @param page Absolute page index to be read | ||
* | ||
* @return 0 on success | ||
* @return -ENODEV if device has not been initialized | ||
* @return -EFAULT if given page was out of range | ||
*/ | ||
int flash_sim_read(const flash_sim *fs, void *buffer, uint32_t page); | ||
|
||
/** | ||
* @brief Partially reads data from the given page into the target buffer | ||
* @param fs Configuration | ||
* @param buffer Target buffer (must be >= the provided length) | ||
* @param page Absolute page index to be read | ||
* @param offset Offset inside the page from which to start reading | ||
* @param length Amount of bytes to read | ||
* | ||
* @return 0 on success | ||
* @return Any error #flash_sim_read may return | ||
*/ | ||
int flash_sim_read_partial(const flash_sim *fs, | ||
void *buffer, | ||
uint32_t page, | ||
uint32_t offset, | ||
uint32_t length); | ||
|
||
/** | ||
* @brief Writes the provided buffer to the given page | ||
* @param fs Configuration | ||
* @param buffer Source buffer (must be >= the size of a page) | ||
* @param page Absolute page index to be written to | ||
* | ||
* @return 0 on success | ||
* @return -ENODEV if device has not been initialized | ||
* @return -EIO if trying to perform an invalid write operation (e.g., setting bits | ||
* back to 1 without erasing first) | ||
* @return -EBADFD if there was an error with the file used for simulated storage | ||
* @return -EFAULT if given page was out of range | ||
* @return Any error #flash_sim_read may return | ||
*/ | ||
int flash_sim_write(const flash_sim *fs, const void *buffer, uint32_t page); | ||
|
||
/** | ||
* @brief Partially writes data from the provided buffer to the given page | ||
* @param fs Configuration | ||
* @param buffer Target buffer (must be >= the provided length) | ||
* @param page Absolute page index to be written to | ||
* @param offset Offset inside the page indicating where to start writing | ||
* @param length Amount of bytes to write | ||
* | ||
* @return 0 on success | ||
* @return Any error #flash_sim_read may return | ||
* @return Any error #flash_sim_write may return | ||
*/ | ||
int flash_sim_write_partial(const flash_sim *fs, | ||
const void *buffer, | ||
uint32_t page, | ||
uint32_t offset, | ||
uint32_t length); | ||
|
||
/** | ||
* @brief Erase the given block | ||
* @param fs Configuration | ||
* @param block Absolute block index | ||
* | ||
* @return 0 on success | ||
* @return -ENODEV if device has not been initialized | ||
* @return -EBADFD if there was an error with the file used for simulated storage | ||
* @return -EFAULT if given page was out of range | ||
*/ | ||
int flash_sim_erase(const flash_sim *fs, uint32_t block); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif | ||
/** @} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/* | ||
* Copyright (C) 2015 Lucas Jenß | ||
* | ||
* 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 sys_storage Data Storage | ||
* @ingroup sys | ||
* | ||
* @brief RIOT's data storage subsystem | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# flash_sim | ||
|
||
Implements an emulation of flash memory with its common properties: | ||
|
||
* Per-page read | ||
* Per-page write-once | ||
* Per-sector erase |
Oops, something went wrong.