X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs2.git;a=blobdiff_plain;f=direct%2Fynorsim.c;fp=direct%2Fynorsim.c;h=569e0ded1e9e40746de4da50ee2d551e6da2074e;hp=0000000000000000000000000000000000000000;hb=49942b13d7cfbdba72c18de0f37d16d81b4372a8;hpb=9f0dab8f26ae946761792c1b2de425b3232ee6e1 diff --git a/direct/ynorsim.c b/direct/ynorsim.c new file mode 100644 index 0000000..569e0de --- /dev/null +++ b/direct/ynorsim.c @@ -0,0 +1,156 @@ + + +#include "ynorsim.h" + + + +#include +#include +#include +#include +#include + +#define YNORSIM_FNAME "ynorsimdata" + +/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to + *simulate bit flipping as the programming happens. + * A low value results in faster simulation with less chance of encountering a partially programmed + * word. + */ + +//#define YNORSIM_BIT_CHANGES 15 +#define YNORSIM_BIT_CHANGES 1 + +/* Simulate 32MB of flash in 256k byte blocks. + * This stuff is x32. + */ + +#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4) +#define YNORSIM_DEV_SIZE_U32 (32*1024 * 1024/4) + +static __u32 word[YNORSIM_DEV_SIZE_U32]; + + +static void NorError(void) +{ + printf("Nor error\n"); + while(1){} +} + +static void ynorsim_SaveImage(void) +{ + int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + write(h,word,sizeof(word)); + close(h); +} + +static void ynorsim_RestoreImage(void) +{ + int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE); + memset(word,0xFF,sizeof(word)); + read(h,word,sizeof(word)); + close(h); +} + + +static void ynorsim_PowerFail(void) +{ + ynorsim_SaveImage(); + exit(1); +} + +static int initialised = 0; +static int remaining_ops; +static int nops_so_far; + +static void ynorsim_MaybePowerFail(void) +{ + + nops_so_far++; + + + remaining_ops--; + if(remaining_ops < 1){ + printf("Simulated power failure after %d operations\n",nops_so_far); + ynorsim_PowerFail(); + } +} + +static void ynorsim_Ready(void) +{ + if(initialised) + return; + srand(time(NULL)); + remaining_ops = 1000000000; + remaining_ops = (rand() % 10000) * 10000; + ynorsim_RestoreImage(); +} + +void ynorsim_Read32(__u32 *addr,__u32 *buf, int nwords) +{ + while(nwords > 0){ + *buf = *addr; + buf++; + addr++; + nwords--; + } +} + +void ynorsim_WriteOneWord32(__u32 *addr,__u32 val) +{ + __u32 tmp; + __u32 m; + int i; + + tmp = *addr; + if(val & ~tmp){ + // Fail due to trying to change a zero into a 1 + printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val); + NorError(); + } + + for(i = 0; i < YNORSIM_BIT_CHANGES; i++){ + m = 1 << (rand() & 31); + if(!(m & val)){ + tmp &= ~m; + *addr = tmp; + ynorsim_MaybePowerFail(); + } + + } + + *addr = tmp & val; + ynorsim_MaybePowerFail(); +} + +void ynorsim_Write32(__u32 *addr, __u32 *buf, int nwords) +{ + while(nwords >0){ + ynorsim_WriteOneWord32(addr,*buf); + addr++; + buf++; + nwords--; + } +} + +void ynorsim_EraseBlock(__u32 *addr) +{ + /* Todo... bit flipping */ + memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4); +} + +void ynorsim_Initialise(void) +{ + ynorsim_Ready(); +} + +void ynorsim_Shutdown(void) +{ + ynorsim_SaveImage(); + initialised=0; +} + +__u32 *ynorsim_GetBase(void) +{ + return word; +}