1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

native: add mtd-compliant flash emulation

This commit is contained in:
Vincent Dupont 2016-07-11 09:53:13 +02:00
parent 49ebf55b0d
commit 9e8cb3d135
10 changed files with 287 additions and 1 deletions

View File

@ -1,3 +1,7 @@
ifneq (,$(filter netdev_default gnrc_netdev_default,$(USEMODULE)))
USEMODULE += netdev2_tap
endif
ifneq (,$(filter mtd,$(USEMODULE)))
USEMODULE += mtd_native
endif

View File

@ -18,6 +18,10 @@
#include "board_internal.h"
#ifdef MODULE_MTD
#include "mtd_native.h"
#endif
/**
* Nothing to initialize at the moment.
* Turns the red LED on and the green LED off.
@ -28,3 +32,28 @@ void board_init(void)
LED1_ON;
puts("RIOT native board initialized.");
}
#ifdef MODULE_MTD
#ifndef MTD_NATIVE_PAGE_SIZE
#define MTD_NATIVE_PAGE_SIZE 256
#endif
#ifndef MTD_NATIVE_SECTOR_SIZE
#define MTD_NATIVE_SECTOR_SIZE 4096
#endif
#ifndef MTD_NATIVE_SECTOR_NUM
#define MTD_NATIVE_SECTOR_NUM 2048
#endif
#ifndef MTD_NATIVE_FILENAME
#define MTD_NATIVE_FILENAME "MEMORY.bin"
#endif
mtd_native_dev_t mtd0 = {
.dev = {
.driver = &native_flash_driver,
.sector_count = MTD_NATIVE_SECTOR_NUM,
.pages_per_sector = MTD_NATIVE_SECTOR_SIZE / MTD_NATIVE_PAGE_SIZE,
.page_size = MTD_NATIVE_PAGE_SIZE,
},
.fname = MTD_NATIVE_FILENAME,
};
#endif

View File

@ -30,6 +30,10 @@
extern "C" {
#endif
#ifdef MODULE_MTD
#include "mtd_native.h"
#endif
/**
* @brief LED handlers
* @{
@ -49,6 +53,13 @@ void _native_LED_RED_TOGGLE(void);
#define LED1_TOGGLE (_native_LED_GREEN_TOGGLE())
/** @} */
#ifdef MODULE_MTD
#define MTD_0 mtd0
/** mtd flash emulation device */
extern mtd_native_dev_t mtd0;
#endif
#ifdef __cplusplus
}
#endif

View File

@ -6,6 +6,9 @@ DIRS += vfs
ifneq (,$(filter netdev2_tap,$(USEMODULE)))
DIRS += netdev2_tap
endif
ifneq (,$(filter mtd_native,$(USEMODULE)))
DIRS += mtd
endif
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* 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 mtd
* @defgroup mtd_native Native MTD
* @{
* @brief mtd flash emulation for native
*
* @file
*
* @author Vincent Dupont <vincent@otakeys.com>
*/
#ifndef MTD_NATIVE_H
#define MTD_NATIVE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "mtd.h"
/** mtd native descriptor */
typedef struct mtd_native_dev {
mtd_dev_t dev; /**< mtd generic device */
const char *fname; /**< filename to use for memory emulation */
} mtd_native_dev_t;
/**
* @brief Native mtd flash driver
*/
extern const mtd_desc_t native_flash_driver;
#ifdef __cplusplus
}
#endif
#endif /* MTD_NATIVE_H */
/** @} */

View File

@ -124,6 +124,10 @@ extern int (*real_unlink)(const char *);
extern long int (*real_random)(void);
extern const char* (*real_gai_strerror)(int errcode);
extern FILE* (*real_fopen)(const char *path, const char *mode);
extern int (*real_fclose)(FILE *stream);
extern int (*real_fseek)(FILE *stream, long offset, int whence);
extern int (*real_fputc)(int c, FILE *stream);
extern int (*real_fgetc)(FILE *stream);
extern mode_t (*real_umask)(mode_t cmask);
extern ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt);

5
cpu/native/mtd/Makefile Normal file
View File

@ -0,0 +1,5 @@
MODULE := mtd_native
include $(RIOTBASE)/Makefile.base
INCLUDES = $(NATIVEINCLUDES)

154
cpu/native/mtd/mtd_native.c Normal file
View File

@ -0,0 +1,154 @@
/*
* Copyright (C) 2016 OTA keys S.A.
*
* 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 mtd_native
* @{
* @brief mtd flash emulation for native
*
* @file
*
* @author Vincent Dupont <vincent@otakeys.com>
*/
#include <stdio.h>
#include <assert.h>
#include <inttypes.h>
#include <errno.h>
#include "mtd.h"
#include "mtd_native.h"
#include "native_internal.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
static int _init(mtd_dev_t *dev)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
DEBUG("mtd_native: init, filename=%s\n", _dev->fname);
FILE *f = real_fopen(_dev->fname, "r");
if (!f) {
DEBUG("mtd_native: init: creating file %s\n", name);
f = real_fopen(_dev->fname, "w+");
if (!f) {
return -EIO;
}
size_t size = dev->sector_count * dev->pages_per_sector * dev->page_size;
for (size_t i = 0; i < size; i++) {
real_fputc(0xff, f);
}
}
real_fclose(f);
return 0;
}
static int _read(mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
DEBUG("mtd_native: read from page %" PRIu32 " count %" PRIu32 "\n", addr, size);
if (addr + size > mtd_size) {
return -EOVERFLOW;
}
FILE *f = real_fopen(_dev->fname, "r");
if (!f) {
return -EIO;
}
real_fseek(f, addr, SEEK_SET);
size = real_fread(buff, 1, size, f);
real_fclose(f);
return size;
}
static int _write(mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
size_t sector_size = dev->pages_per_sector * dev->page_size;
DEBUG("mtd_native: write from page %" PRIu32 " count %" PRIu32 "\n", addr, size);
if (addr + size > mtd_size) {
return -EOVERFLOW;
}
if (((addr % sector_size) + size) > sector_size) {
return -EOVERFLOW;
}
FILE *f = real_fopen(_dev->fname, "r+");
if (!f) {
return -EIO;
}
real_fseek(f, addr, SEEK_SET);
for (size_t i = 0; i < size; i++) {
uint8_t c = real_fgetc(f);
real_fseek(f, -1, SEEK_CUR);
real_fputc(c & ((uint8_t*)buff)[i], f);
}
real_fclose(f);
return size;
}
static int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t size)
{
mtd_native_dev_t *_dev = (mtd_native_dev_t*) dev;
size_t mtd_size = dev->sector_count * dev->pages_per_sector * dev->page_size;
size_t sector_size = dev->pages_per_sector * dev->page_size;
DEBUG("mtd_native: erase from sector %" PRIu32 " count %" PRIu32 "\n", addr, size);
if (addr + size > mtd_size) {
return -EOVERFLOW;
}
if (((addr % sector_size) != 0) || ((size % sector_size) != 0)) {
return -EOVERFLOW;
}
FILE *f = real_fopen(_dev->fname, "r+");
if (!f) {
return -EIO;
}
real_fseek(f, addr, SEEK_SET);
for (size_t i = 0; i < size; i++) {
real_fputc(0xff, f);
}
real_fclose(f);
return 0;
}
static int _power(mtd_dev_t *dev, enum mtd_power_state power)
{
(void) dev;
(void) power;
return -ENOTSUP;
}
const mtd_desc_t native_flash_driver = {
.read = _read,
.power = _power,
.write = _write,
.erase = _erase,
.init = _init,
};
/** @} */

View File

@ -65,7 +65,16 @@ const char *_native_unix_socket_path = NULL;
netdev2_tap_params_t netdev2_tap_params[NETDEV2_TAP_MAX];
#endif
static const char short_opts[] = ":hi:s:deEoc:";
#ifdef MODULE_MTD_NATIVE
#include "board.h"
#include "mtd_native.h"
#endif
static const char short_opts[] = ":hi:s:deEoc:"
#ifdef MODULE_MTD_NATIVE
"m:"
#endif
"";
static const struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' },
{ "id", required_argument, NULL, 'i' },
@ -75,6 +84,9 @@ static const struct option long_opts[] = {
{ "stderr-noredirect", no_argument, NULL, 'E' },
{ "stdout-pipe", no_argument, NULL, 'o' },
{ "uart-tty", required_argument, NULL, 'c' },
#ifdef MODULE_MTD_NATIVE
{ "mtd", required_argument, NULL, 'm' },
#endif
{ NULL, 0, NULL, '\0' },
};
@ -230,6 +242,11 @@ void usage_exit(int status)
" -c <tty>, --uart-tty=<tty>\n"
" specify TTY device for UART. This argument can be used multiple\n"
" times (up to UART_NUMOF)\n");
#ifdef MODULE_MTD_NATIVE
real_printf(
" -m <mtd>, --mtd=<mtd>\n"
" specify the file name of mtd emulated device\n");
#endif
real_exit(status);
}
@ -285,6 +302,11 @@ __attribute__((constructor)) static void startup(int argc, char **argv)
case 'c':
tty_uart_setup(uart++, optarg);
break;
#ifdef MODULE_MTD_NATIVE
case 'm':
mtd0.fname = strndup(optarg, PATH_MAX - 1);
break;
#endif
default:
usage_exit(EXIT_FAILURE);
}

View File

@ -89,6 +89,10 @@ int (*real_unlink)(const char *);
long int (*real_random)(void);
const char* (*real_gai_strerror)(int errcode);
FILE* (*real_fopen)(const char *path, const char *mode);
int (*real_fclose)(FILE *stream);
int (*real_fseek)(FILE *stream, long offset, int whence);
int (*real_fputc)(int c, FILE *stream);
int (*real_fgetc)(FILE *stream);
mode_t (*real_umask)(mode_t cmask);
ssize_t (*real_writev)(int fildes, const struct iovec *iov, int iovcnt);
@ -472,6 +476,10 @@ void _native_init_syscalls(void)
*(void **)(&real_clearerr) = dlsym(RTLD_NEXT, "clearerr");
*(void **)(&real_umask) = dlsym(RTLD_NEXT, "umask");
*(void **)(&real_writev) = dlsym(RTLD_NEXT, "writev");
*(void **)(&real_fclose) = dlsym(RTLD_NEXT, "fclose");
*(void **)(&real_fseek) = dlsym(RTLD_NEXT, "fseek");
*(void **)(&real_fputc) = dlsym(RTLD_NEXT, "fputc");
*(void **)(&real_fgetc) = dlsym(RTLD_NEXT, "fgetc");
#ifdef __MACH__
#else
*(void **)(&real_clock_gettime) = dlsym(RTLD_NEXT, "clock_gettime");