Created
August 5, 2018 20:04
-
-
Save c-mauderer/986f0cd88b1549e05f192d1569fe1b03 to your computer and use it in GitHub Desktop.
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
/* | |
* Copyright (c) 2017 Christian Mauderer <oss@c-mauderer.de> | |
* | |
* Permission is hereby granted, free of charge, to any person obtaining a copy | |
* of this software and associated documentation files (the "Software"), to deal | |
* in the Software without restriction, including without limitation the rights | |
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
* copies of the Software, and to permit persons to whom the Software is | |
* furnished to do so, subject to the following conditions: | |
* | |
* The above copyright notice and this permission notice shall be included in | |
* all copies or substantial portions of the Software. | |
* | |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
* SOFTWARE. | |
*/ | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#include <rtems.h> | |
#include <rtems/console.h> | |
#include <rtems/shell.h> | |
#include "yaffs2.h" | |
#define RTEMS_FILESYSTEM_TYPE_YAFFS "yaffs" | |
#define MOUNT_PATH "/mnt" | |
static void | |
Init(rtems_task_argument arg) | |
{ | |
rtems_status_code sc; | |
int rv; | |
(void)arg; | |
rv = mount_and_make_target_path( | |
NULL, | |
MOUNT_PATH, | |
RTEMS_FILESYSTEM_TYPE_YAFFS, | |
RTEMS_FILESYSTEM_READ_WRITE, | |
NULL | |
); | |
assert(rv == 0); | |
sc = rtems_shell_init( | |
"SHLL", | |
32*1024, | |
RTEMS_MAXIMUM_PRIORITY - 10, | |
CONSOLE_DEVICE_NAME, | |
false, | |
true, | |
NULL | |
); | |
assert(sc == RTEMS_SUCCESSFUL); | |
} | |
/* | |
* Configure RTEMS. | |
*/ | |
#define CONFIGURE_MICROSECONDS_PER_TICK 1000 | |
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER | |
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER | |
#define CONFIGURE_APPLICATION_NEEDS_STUB_DRIVER | |
#define CONFIGURE_APPLICATION_NEEDS_ZERO_DRIVER | |
#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK | |
#define CONFIGURE_FILESYSTEM_IMFS | |
#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM | |
#define CONFIGURE_HAS_OWN_FILESYSTEM_TABLE | |
#include <rtems/imfs.h> | |
const rtems_filesystem_table_t rtems_filesystem_table[] = { | |
{ "/", IMFS_initialize_support }, | |
{ RTEMS_FILESYSTEM_TYPE_IMFS, IMFS_initialize }, | |
{ RTEMS_FILESYSTEM_TYPE_YAFFS, yaffs_initialize }, | |
{ NULL, NULL } | |
}; | |
#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 32 | |
#define CONFIGURE_UNLIMITED_OBJECTS | |
#define CONFIGURE_UNIFIED_WORK_AREAS | |
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1 | |
#define CONFIGURE_INIT_TASK_STACK_SIZE (64*1024) | |
#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES | |
#define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT | |
#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE (32 * 1024) | |
#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 4 | |
#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (1 * 1024 * 1024) | |
#define CONFIGURE_BDBUF_READ_AHEAD_TASK_PRIORITY 97 | |
#define CONFIGURE_SWAPOUT_TASK_PRIORITY 97 | |
//#define CONFIGURE_STACK_CHECKER_ENABLED | |
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE | |
#define CONFIGURE_INIT | |
#include <rtems/confdefs.h> | |
/* | |
* Configure Shell. | |
*/ | |
#include <rtems/netcmds-config.h> | |
#include <bsp/irq-info.h> | |
#define CONFIGURE_SHELL_COMMANDS_INIT | |
#define CONFIGURE_SHELL_COMMANDS_ALL | |
#include <rtems/shellconfig.h> |
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
/* | |
* Based on code from Flickernoise | |
* Copyright (C) 2010, 2011 Sebastien Bourdeauducq | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, version 3 of the License. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
#include <assert.h> | |
#include <rtems.h> | |
#include <rtems/libio.h> | |
#include <rtems/seterr.h> | |
#include <rtems/userenv.h> | |
#include <errno.h> | |
#include <limits.h> | |
#include <stdlib.h> | |
#include <yaffs/rtems_yaffs.h> | |
#include <yaffs/yaffs_packedtags2.h> | |
#include "yaffs2.h" | |
#define MAXIMUM_YAFFS_MOUNTS 1 | |
#define SIMFLASH_BLOCKSIZE (1024) | |
#define SIMFLASH_NR_BLOCKS (110*1024) | |
#define SIMFLASH_SIZE (SIMFLASH_BLOCKSIZE * SIMFLASH_NR_BLOCKS) | |
#define SIMFLASH_CHUNK_TAGS_SIZE (16) | |
#define SIMFLASH_CHUNK_DATA_SIZE (512-SIMFLASH_CHUNK_TAGS_SIZE) | |
#define SIMFLASH_CHUNK_WHOLE_SIZE (SIMFLASH_CHUNK_DATA_SIZE + SIMFLASH_CHUNK_TAGS_SIZE) | |
struct yaffs_softc { | |
struct yaffs_dev *dev; | |
uint8_t *simflash; | |
unsigned int size; | |
unsigned int blocksize; | |
rtems_yaffs_os_handler free_os_context; | |
}; | |
static rtems_status_code my_read(uint8_t *simflash, void *buffer, size_t len, size_t offset) | |
{ | |
memcpy(buffer, &simflash[offset], len); | |
return RTEMS_SUCCESSFUL; | |
} | |
static rtems_status_code my_write(uint8_t *simflash, const void *buffer, size_t len, size_t offset) | |
{ | |
memcpy(&simflash[offset], buffer, len); | |
return RTEMS_SUCCESSFUL; | |
} | |
/* Flash access functions */ | |
static unsigned int chunk_address(struct yaffs_dev *dev, int c) | |
{ | |
struct yaffs_softc *sc = (struct yaffs_softc *)dev->driver_context; | |
unsigned int chunks_per_block = (unsigned int) dev->param.chunks_per_block; | |
return sc->blocksize*(c/chunks_per_block) | |
+ SIMFLASH_CHUNK_WHOLE_SIZE*(c%chunks_per_block); | |
} | |
static int write_chunk_tags(struct yaffs_dev *dev, int nand_chunk, const u8 *data, const struct yaffs_ext_tags *tags) | |
{ | |
struct yaffs_softc *sc = (struct yaffs_softc *)dev->driver_context; | |
unsigned int address; | |
//printf("%s %d (data=%p tags=%p)\n", __func__, nand_chunk, data, tags); | |
address = chunk_address(dev, nand_chunk); | |
if(data) | |
my_write(sc->simflash, data, SIMFLASH_CHUNK_DATA_SIZE, address); | |
if(tags) { | |
struct yaffs_packed_tags2_tags_only x; | |
yaffs_pack_tags2_tags_only(&x, tags); | |
my_write(sc->simflash, &x, SIMFLASH_CHUNK_TAGS_SIZE, | |
address+SIMFLASH_CHUNK_DATA_SIZE); | |
} | |
return YAFFS_OK; | |
} | |
static int read_chunk_tags(struct yaffs_dev *dev, int nand_chunk, u8 *data, struct yaffs_ext_tags *tags) | |
{ | |
struct yaffs_softc *sc = (struct yaffs_softc *)dev->driver_context; | |
unsigned int address; | |
//printf("%s %d (data=%p tags=%p)\n", __func__, nand_chunk, data, tags); | |
address = chunk_address(dev, nand_chunk); | |
if(data) | |
my_read(sc->simflash, data, SIMFLASH_CHUNK_DATA_SIZE, address); | |
if(tags) { | |
struct yaffs_packed_tags2_tags_only x; | |
my_read(sc->simflash, &x, SIMFLASH_CHUNK_TAGS_SIZE, address+SIMFLASH_CHUNK_DATA_SIZE); | |
yaffs_unpack_tags2_tags_only(tags, &x); | |
} | |
return YAFFS_OK; | |
} | |
static int bad_block(struct yaffs_dev *dev, int blockId) | |
{ | |
struct yaffs_ext_tags tags; | |
int chunk_nr; | |
chunk_nr = blockId * dev->param.chunks_per_block; | |
read_chunk_tags(dev, chunk_nr, NULL, &tags); | |
tags.block_bad = 1; | |
write_chunk_tags(dev, chunk_nr, NULL, &tags); | |
return YAFFS_OK; | |
} | |
static int query_block(struct yaffs_dev *dev, int blockId, enum yaffs_block_state *state, u32 *seq_number) | |
{ | |
struct yaffs_ext_tags tags; | |
int chunk_nr; | |
*seq_number = 0; | |
chunk_nr = blockId * dev->param.chunks_per_block; | |
read_chunk_tags(dev, chunk_nr, NULL, &tags); | |
if(tags.block_bad) | |
*state = YAFFS_BLOCK_STATE_DEAD; | |
else if(!tags.chunk_used) | |
*state = YAFFS_BLOCK_STATE_EMPTY; | |
else if(tags.chunk_used) { | |
*state = YAFFS_BLOCK_STATE_NEEDS_SCAN; | |
*seq_number = tags.seq_number; | |
} | |
return YAFFS_OK; | |
} | |
static int erase(struct yaffs_dev *dev, int blockId) | |
{ | |
struct yaffs_softc *sc = dev->driver_context; | |
memset(&(sc->simflash[blockId * SIMFLASH_BLOCKSIZE]), 0xff, | |
SIMFLASH_BLOCKSIZE); | |
return YAFFS_OK; | |
} | |
static int initialise(struct yaffs_dev *dev) | |
{ | |
struct yaffs_softc *sc = dev->driver_context; | |
sc->simflash = malloc(SIMFLASH_SIZE); | |
if (sc->simflash != 0) { | |
memset(sc->simflash, 0xff, SIMFLASH_SIZE); | |
return YAFFS_OK; | |
} else { | |
return YAFFS_FAIL; | |
} | |
} | |
static int mount_sema_created; | |
static rtems_id mount_sema; | |
static struct yaffs_softc *current_mounts[MAXIMUM_YAFFS_MOUNTS]; | |
static void unmount_handler(struct yaffs_dev *dev, void *os_context) | |
{ | |
struct yaffs_softc *softc = dev->driver_context; | |
int i; | |
rtems_semaphore_obtain(mount_sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); | |
for(i=0;i<MAXIMUM_YAFFS_MOUNTS;i++) { | |
if(current_mounts[i] == softc) { | |
current_mounts[i] = NULL; | |
break; | |
} | |
} | |
softc->free_os_context(dev, os_context); | |
free(softc); | |
free(dev); | |
rtems_semaphore_release(mount_sema); | |
} | |
static int flush_task_running; | |
static rtems_id flush_task_id; | |
static rtems_task flush_task(rtems_task_argument argument) | |
{ | |
int i; | |
struct yaffs_softc *sc; | |
rtems_yaffs_default_os_context *os_context; | |
(void) argument; | |
while(1) { | |
rtems_task_wake_after(10*100); | |
rtems_semaphore_obtain(mount_sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); | |
for(i=0;i<MAXIMUM_YAFFS_MOUNTS;i++) { | |
sc = current_mounts[i]; | |
if(sc != NULL) { | |
os_context = sc->dev->os_context; | |
os_context->os_context.lock(sc->dev, os_context); | |
yaffs_flush_whole_cache(sc->dev); | |
os_context->os_context.unlock(sc->dev, os_context); | |
} | |
} | |
rtems_semaphore_release(mount_sema); | |
} | |
} | |
int yaffs_initialize(rtems_filesystem_mount_table_entry_t *mt_entry, const void *data) | |
{ | |
int i; | |
int index; | |
struct yaffs_dev *dev; | |
struct yaffs_param *param; | |
struct yaffs_softc *softc; | |
rtems_yaffs_default_os_context *os_context; | |
rtems_yaffs_mount_data md; | |
rtems_status_code sc1, sc2; | |
int r; | |
if(!mount_sema_created) { | |
sc1 = rtems_semaphore_create( | |
rtems_build_name('Y', 'A', 'F', 'M'), | |
1, | |
RTEMS_LOCAL | |
| RTEMS_BINARY_SEMAPHORE | |
| RTEMS_INHERIT_PRIORITY | |
| RTEMS_PRIORITY, | |
0, | |
&mount_sema | |
); | |
if(sc1 != RTEMS_SUCCESSFUL) { | |
errno = ENOMEM; | |
return -1; | |
} | |
mount_sema_created = 1; | |
} | |
rtems_semaphore_obtain(mount_sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT); | |
index = -1; | |
for(i=0;i<MAXIMUM_YAFFS_MOUNTS;i++) { | |
if(current_mounts[i] == NULL) { | |
index = i; | |
break; | |
} | |
} | |
rtems_semaphore_release(mount_sema); | |
if(index == -1) { | |
errno = ENOMEM; | |
return -1; | |
} | |
dev = malloc(sizeof(struct yaffs_dev)); | |
if(dev == NULL) { | |
errno = ENOMEM; | |
return -1; | |
} | |
memset(dev, 0, sizeof(struct yaffs_dev)); | |
softc = malloc(sizeof(struct yaffs_softc)); | |
if(softc == NULL) { | |
errno = ENOMEM; | |
free(dev); | |
return -1; | |
} | |
softc->dev = dev; | |
softc->size = SIMFLASH_SIZE; | |
softc->blocksize = SIMFLASH_BLOCKSIZE; | |
if((sc1 != RTEMS_SUCCESSFUL)||(sc2 != RTEMS_SUCCESSFUL)) { | |
errno = EIO; | |
free(softc); | |
free(dev); | |
return -1; | |
} | |
os_context = malloc(sizeof(rtems_yaffs_default_os_context)); | |
if(os_context == NULL) { | |
errno = ENOMEM; | |
free(softc); | |
free(dev); | |
return -1; | |
} | |
r = rtems_yaffs_initialize_default_os_context(os_context); | |
if(r == -1) { | |
free(os_context); | |
free(softc); | |
free(dev); | |
return -1; | |
} | |
softc->free_os_context = os_context->os_context.unmount; | |
os_context->os_context.unmount = unmount_handler; | |
/* set parameters */ | |
dev->driver_context = softc; | |
dev->os_context = os_context; | |
dev->read_only = 0; | |
param = &(dev->param); | |
param->name = "simyaffs2"; | |
param->start_block = 0; | |
param->end_block = softc->size/softc->blocksize - 1; | |
param->chunks_per_block = softc->blocksize/SIMFLASH_CHUNK_WHOLE_SIZE; | |
param->total_bytes_per_chunk = SIMFLASH_CHUNK_WHOLE_SIZE; | |
param->n_reserved_blocks = 5; | |
param->n_caches = 15; | |
param->inband_tags = 1; | |
param->is_yaffs2 = 1; | |
param->no_tags_ecc = 1; | |
/* set callbacks */ | |
param->write_chunk_tags_fn = write_chunk_tags; | |
param->read_chunk_tags_fn = read_chunk_tags; | |
param->bad_block_fn = bad_block; | |
param->query_block_fn = query_block; | |
param->erase_fn = erase; | |
param->initialise_flash_fn = initialise; | |
md.dev = dev; | |
r = rtems_yaffs_mount_handler(mt_entry, &md); | |
if(r == -1) { | |
errno = ENOMEM; | |
softc->free_os_context(dev, os_context); | |
free(softc); | |
free(dev); | |
return -1; | |
} | |
current_mounts[index] = softc; | |
if(!flush_task_running) { | |
sc1 = rtems_task_create(rtems_build_name('F', 'L', 'S', 'H'), 220, 256*1024, | |
RTEMS_PREEMPT | RTEMS_NO_TIMESLICE | RTEMS_NO_ASR, | |
0, &flush_task_id); | |
assert(sc1 == RTEMS_SUCCESSFUL); | |
sc1 = rtems_task_start(flush_task_id, flush_task, 0); | |
assert(sc1 == RTEMS_SUCCESSFUL); | |
flush_task_running = 1; | |
} | |
return 0; | |
} |
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
/* | |
* Copyright (c) 2018 embedded brains GmbH. All rights reserved. | |
* | |
* embedded brains GmbH | |
* Dornierstr. 4 | |
* 82178 Puchheim | |
* Germany | |
* <rtems@embedded-brains.de> | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
*/ | |
#ifndef APP_YAFFS2_H | |
#define APP_YAFFS2_H | |
#include <rtems.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif /* __cplusplus */ | |
int yaffs_initialize(rtems_filesystem_mount_table_entry_t *mt_entry, const void *data); | |
#ifdef __cplusplus | |
} | |
#endif /* __cplusplus */ | |
#endif /* APP_YAFFS2_H */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment