/* flashI2C.h */ #ifndef _flashI2C_h #define _flashI2C_h void flashI2CInit(void); void flashI2CTask(void); U16 flashI2CReg(U8 dev, U8 reg); // U8 flashRead(U8 dev, U8 address); // U8 flashWrite(U8 dev, U8 address); // U8 flashVerify(U8 dev, U8 sector); #endif /* _flashI2C_h */ /* flashI2C.c */ #include #include "compiler_defs.h" #include "processor.h" #include "config.h" #include "main.h" #include "tick.h" #include "i2c.h" #include "flashI2C.h" // read/write/verify byte/word/sector // i2c 50 0 0 4 // read first 4 bytes // i2c 50 0 0 0 1 2 3 0 // write first 4 bytes // serial flash // sector overhead|payload ( 16 + 48 bytes ) // overhead format ... checkword // payload identity ... data // ===(header)=== 0 1 2 3 4 5 6 7 8 9 a b c d e f // i2c 50 00 00 00 00 00 01 20 18 06 30 12 22 32 01 00 00 00 00 0 // dev addr fmt rev ====date=== ==time== cyc ====crc==== // ===(pcba)=== 0 1 2 3 4 5 6 7 8 9 a b c d e f // i2c 50 00 20 00 01 00 07 24 07 20 16 02 00 00 00 00 00 02 23 0 // dev addr model number ====dat==== bom mod sequence number // ===(code)=== hardware dd mm yy yy firmware boot+app // i2c 50 00 30 00 06 00 00 20 18 06 29 00 00 00 72 00 00 00 00 0 // dev addr =maj= =rev= ====date=== =maj= =ver= ====size=== #ifdef CONFIG_FLASH static struct { // see crc.c U8 bus; U8 dev; // i2c device select U16 count; // sector count } code flashDevs[] = {CONFIG_FLASH_DEVS}; #define FLASH_NUM_DEVS (sizeof(flashDevs) / sizeof(flashDevs[0])) static struct { enum {initFS, waitInitFS, idleFS, waitIdleFS, readFS, waitReadFS, writeFS, waitWriteFS, verifyFS, waitVerifyFS, endFS, exitFS} state; // U8 reg; U8 index; struct { // U16 usb[]; // vid/pid/... // U8 date[]; // code date stamp // U16 fwid; // pcba / rework // U16 hwid; // build major/minor // U8 verify; // sector crc // U8 strings; // annuciations U8 dev; // flash device select U16 count; // usable sector count U16 format; // format (other than 0xff) U16 version; // version (other than 0xff) U8 readReq; // U8 writeReq; } dev[FLASH_NUM_DEVS]; struct i2cRequestS i2c; U8 buffer[4]; U8 lastTick; U8 timer; U8 reset; U16 model; // base/batt U16 number; // type } xdata flash; void flashI2CInit(void) { U8 i; memset(&flash, 0, sizeof(flash)); for (i = 0; i < FLASH_NUM_DEVS; i++) { flash.dev[i].dev = flashDevs[i].dev; flash.dev[i].count = flashDevs[i].count; flash.dev[i].format = 0; flash.dev[i].version = 0; flash.dev[i].readReq = 0; // flash.dev[i].writeReq = 0; } // flash.reg = 0; flash.index = 0; // serial flash with model number flash.i2c.tx = flash.buffer; flash.i2c.rx = flash.buffer; flash.lastTick = tick; flash.timer = 0; flash.reset = 0; flash.model = 0; flash.number = 0; flash.state = initFS; // read flash config to shadow } bit flashResetPermission(bit assert) { bit permit; if (assert) { if (flash.state == initFS) permit = 1; else permit = 0; } else permit = 1; return permit; } void flashResetNotify(bit assert) { flash.reset = assert; } /* U8 flashRead(U8 dev, U16 addr) { // boost flash for fixed time return flash.data; } */ /* U8 flashWrite(U8 dev, U16 addr) { // boost flash for fixed time return flash.data; } */ /* U8 flashVerify(U8 dev, U8 sect) { // boost flash for fixed time return flash.status; } */ void flashI2CTask(void) { U8 i; while (tick != flash.lastTick) { flash.lastTick++; if (flash.timer) flash.timer--; if (flash.timer == 0) { for (i = 0; i < FLASH_NUM_DEVS; i++) flash.dev[i].readReq = 1; flash.timer = MS_NOM_TO_TICKS(1000); } } switch (flash.state) { case initFS: // verify / read / id if (!flash.reset) { // i2c 50 cl256k flash.i2c.addr = flashDevs[flash.index].dev; flash.buffer[0] = 0x00; // third 64 byte sector flash.buffer[1] = 0x20; // for model and number flash.i2c.txCount = 2; // flash address flash.i2c.rxCount = 4; // model number if (i2cTransfer(flashDevs[flash.index].bus, &flash.i2c) == I2C_RESULT_OK) { flash.state = waitInitFS; } } break; case waitInitFS: if (flash.i2c.result != I2C_RESULT_BUSY) { // i2c transaction complete ? if (flash.i2c.result == I2C_RESULT_OK) { flash.model = (flash.buffer[0] << 8) + flash.buffer[1]; flash.number = (flash.buffer[2] << 8) + flash.buffer[3]; flash.state = exitFS; } else { // try read value again flash.state = idleFS; } } break; case idleFS: // if (!flash.reset) { // i2c 50 cl256k flash.i2c.addr = flashDevs[flash.index].dev; if (flash.dev[flash.index].readReq) { flash.buffer[0] = 0x00; // flashDevs[flash.index].addr[15:8]; flash.buffer[1] = 0x00; // flashDevs[flash.index].addr[7:0]; flash.i2c.txCount = 2; // flash address flash.i2c.rxCount = 4; // msb lsb if (i2cTransfer(flashDevs[flash.index].bus, &flash.i2c) == I2C_RESULT_OK) { flash.dev[flash.index].readReq = 0; flash.state = waitIdleFS; } } /* else if (flash.dev[flash.index].writeReq) { } */ // } break; case waitIdleFS: // if (flash.i2c.result != I2C_RESULT_BUSY) { // i2c transaction complete ? if (flash.i2c.result == I2C_RESULT_OK) { flash.dev[flash.index].format = (flash.buffer[0] << 8) + flash.buffer[1]; flash.dev[flash.index].version = (flash.buffer[2] << 8) + flash.buffer[3]; flash.state = exitFS; } else { // try read value again flash.state = idleFS; } } break; case exitFS: flash.state = idleFS; break; } } U16 flashI2CReg(U8 dev, U8 reg) { U16 val; switch (reg) { case 0 : val = flash.dev[dev].count; break; // case 1 : val = flash.dev[dev].format; break; // case 2 : val = flash.dev[dev].version; break; case 1 : val = flash.model; break; case 2 : val = flash.number; break; // case 3 : val = flash.dev[dev].hwid; break; default : val = 0; break; } return val; } #endif /* CONFIG_FLASH */