Merged in f5soh/librepilot/update_credits (pull request #529)
[librepilot.git] / flight / pios / posix / libraries / yaffs2 / ynorsim.c
blob378a073247cf6218c84c30fc34105b40cbd39053
1 /*
2 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
4 * Copyright (C) 2002-2011 Aleph One Ltd.
5 * for Toby Churchill Ltd and Brightstar Engineering
7 * Created by Charles Manning <charles@aleph1.co.uk>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
14 #include "ynorsim.h"
16 #include <stdio.h>
17 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <unistd.h>
20 #include <time.h>
22 #include "pios_trace.h"
24 #define YNORSIM_FNAME "emfile-nor"
26 /* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to
27 * simulate bit flipping as the programming happens.
28 * A low value results in faster simulation with less chance of encountering a partially programmed
29 * word.
32 // #define YNORSIM_BIT_CHANGES 15
33 #define YNORSIM_BIT_CHANGES 2
35 #if 0
36 /* Simulate 32MB of flash in 256k byte blocks.
37 * This stuff is x32.
40 #define YNORSIM_BLOCK_SIZE_U32 (256 * 1024 / 4)
41 #define YNORSIM_DEV_SIZE_U32 (32 * 1024 * 1024 / 4)
42 #else
43 /* Simulate 8MB of flash in 256k byte blocks.
44 * This stuff is x32.
47 #define YNORSIM_BLOCK_SIZE_U32 (256 * 1024 / 4)
48 #define YNORSIM_DEV_SIZE_U32 (8 * 1024 * 1024 / 4)
49 #endif
51 struct nor_sim {
52 int n_blocks;
53 int block_size_bytes;
54 int file_size;
55 u32 *word;
56 int initialised;
57 char *fname;
58 int remaining_ops;
59 int nops_so_far;
62 int ops_multiplier = 500;
63 extern int random_seed;
64 extern int simulate_power_failure;
66 static void NorError(struct nor_sim *sim)
68 printf("Nor error on device %s\n", sim->fname);
69 while (1) {}
72 static void ynorsim_save_image(struct nor_sim *sim)
74 int h;
76 pios_trace(PIOS_TRACE_TEST, "ynorsim_save_image");
77 h = open(sim->fname, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
78 write(h, sim->word, sim->file_size);
79 close(h);
82 static void ynorsim_restore_image(struct nor_sim *sim)
84 int h;
86 pios_trace(PIOS_TRACE_TEST, "ynorsim_restore_image");
87 h = open(sim->fname, O_RDONLY, S_IREAD | S_IWRITE);
88 memset(sim->word, 0xFF, sim->file_size);
89 read(h, sim->word, sim->file_size);
90 close(h);
93 static void ynorsim_power_fail(struct nor_sim *sim)
95 ynorsim_save_image(sim);
96 exit(1);
99 static void ynorsim_maybe_power_fail(struct nor_sim *sim)
101 sim->nops_so_far++;
102 sim->remaining_ops--;
103 if (simulate_power_failure && sim->remaining_ops < 1) {
104 printf("Simulated power failure after %d operations\n",
105 sim->nops_so_far);
106 ynorsim_power_fail(sim);
110 static void ynorsim_ready(struct nor_sim *sim)
112 if (sim->initialised) {
113 return;
115 srand(random_seed);
116 sim->remaining_ops = 1000000000;
117 sim->remaining_ops =
118 (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
119 ynorsim_restore_image(sim);
120 sim->initialised = 1;
123 /* Public functions. */
125 void ynorsim_rd32(struct nor_sim *sim, u32 *addr, u32 *buf, int nwords)
127 sim = sim;
128 while (nwords > 0) {
129 *buf = *addr;
130 buf++;
131 addr++;
132 nwords--;
136 void ynorsim_wr_one_word32(struct nor_sim *sim, u32 *addr, u32 val)
138 u32 tmp;
139 u32 m;
140 int i;
142 tmp = *addr;
143 if (val & ~tmp) {
144 /* Fail due to trying to change a zero into a 1 */
145 printf("attempt to set a zero to one (%x)->(%x)\n", tmp, val);
146 NorError(sim);
149 for (i = 0; i < YNORSIM_BIT_CHANGES; i++) {
150 m = 1 << (rand() & 31);
151 if (!(m & val)) {
152 tmp &= ~m;
153 *addr = tmp;
154 ynorsim_maybe_power_fail(sim);
158 *addr = tmp & val;
159 ynorsim_maybe_power_fail(sim);
162 void ynorsim_wr32(struct nor_sim *sim, u32 *addr, u32 *buf, int nwords)
164 while (nwords > 0) {
165 ynorsim_wr_one_word32(sim, addr, *buf);
166 addr++;
167 buf++;
168 nwords--;
172 void ynorsim_erase(struct nor_sim *sim, u32 *addr)
174 /* Todo... bit flipping */
175 pios_trace(PIOS_TRACE_TEST, "ynorsim_erase");
176 memset(addr, 0xFF, sim->block_size_bytes);
179 struct nor_sim *ynorsim_initialise(char *name, int n_blocks,
180 int block_size_bytes)
182 struct nor_sim *sim;
184 sim = malloc(sizeof(*sim));
185 if (!sim) {
186 return NULL;
189 memset(sim, 0, sizeof(*sim));
190 sim->n_blocks = n_blocks;
191 sim->block_size_bytes = block_size_bytes;
192 sim->file_size = n_blocks * block_size_bytes;
193 sim->word = malloc(sim->file_size);
194 sim->fname = strdup(name);
196 if (!sim->word) {
197 return NULL;
200 ynorsim_ready(sim);
201 return sim;
204 void ynorsim_shutdown(struct nor_sim *sim)
206 ynorsim_save_image(sim);
207 sim->initialised = 0;
210 u32 *ynorsim_get_base(struct nor_sim *sim)
212 return sim->word;