# HG changeset patch # User Daniel O'Connor # Date 1353116904 -37800 # Node ID a9cc07caa8014e1bc2aade76c8c575b47ef1f77e # Parent 1e2fa7396f983589ba45250815a28c5a53e470b5 Add stream read/write commands. diff -r 1e2fa7396f98 -r a9cc07caa801 flash.c --- a/flash.c Sat Nov 17 12:17:58 2012 +1030 +++ b/flash.c Sat Nov 17 12:18:24 2012 +1030 @@ -2,6 +2,7 @@ #include #include #include +#include #include "stm32f10x.h" #include "spi.h" @@ -20,7 +21,14 @@ "AAI", "BPL" }; - + +#define RW_IDLE 0 +#define RW_RUNNING 1 +#define RW_IDLE 0 + +static int writestate = RW_IDLE; +static int readstate = RW_IDLE; + void flashcmd(char **argv, int argc) { uint8_t status, tmp; @@ -63,8 +71,12 @@ } tmp = atoi(argv[1]); + flashstartread(tmp); + for (int i = 0; i < 16; i++) - printf("Read 0x%02x from 0x%06x\r\n", flashread(tmp + i), tmp + i); + printf("Read 0x%02x from 0x%06x\r\n", flashreadbyte(), tmp + i); + flashstopread(); + fputs("\r\n", stdout); } else if (!strcmp(argv[0], "wr")) { if (argc != 2) { @@ -74,11 +86,17 @@ tmp = atoi(argv[1]); - for (int i = 0; i < 16; i++) { - printf("Writing 0x%02x to 0x%06x\r\n", tmp + i, i); - flashwrite(tmp + i, i); + for (int i = 0; i < 16; i += 2) { + uint16_t data; + data = ((i + 1) << 8) | i; + printf("Writing 0x%04x to 0x%06x\r\n", data, tmp + i); + + if (i == 0) + flashstartwrite(tmp, data); + else + flashwriteword(data); } - + flashstopwrite(); } else if (!strcmp(argv[0], "id")) { printf("Flash ID = 0x%04hx (expect 0xbf41)\r\n", flashreadid()); } else { @@ -89,19 +107,24 @@ void flash4kerase(uint32_t addr) { - uint8_t cnt; - flashenablewrite(); /* Enable writing */ FL_SELECT(); /* Select device */ SPI_WriteByte(FL_4KERASE); /* Send command */ - SPI_WriteByte((addr & 0x00ff0000) >> 16); - SPI_WriteByte((addr & 0x0000ff00) >> 8); - SPI_WriteByte((addr & 0x000000ff)); /* Send address */ + SPI_WriteByte(addr >> 16); /* Send address */ + SPI_WriteByte(addr >> 8); + SPI_WriteByte(addr); FL_DESELECT(); + flashwait(); +} + +void +flashwait(void) { + uint8_t cnt; + /* Wait for not BUSY */ for (cnt = 0; (flashreadstatus() & FL_BUSY) != 0; cnt++) ; @@ -173,9 +196,9 @@ FL_SELECT(); /* Select device */ SPI_WriteByte(FL_READ); /* Send command */ - SPI_WriteByte((addr & 0x00ff0000) >> 16); - SPI_WriteByte((addr & 0x0000ff00) >> 8); - SPI_WriteByte((addr & 0x000000ff)); /* Send address */ + SPI_WriteByte(addr >> 16); /* Send address */ + SPI_WriteByte(addr >> 8); + SPI_WriteByte(addr); data = SPI_WriteByte(0x00); /* Read data */ FL_DESELECT(); /* De-select device */ @@ -190,10 +213,111 @@ FL_SELECT(); /* Select device */ SPI_WriteByte(FL_BYTEPROG); /* Send command */ - SPI_WriteByte((addr & 0x00ff0000) >> 16); - SPI_WriteByte((addr & 0x0000ff00) >> 8); - SPI_WriteByte((addr & 0x000000ff)); /* Send address */ + SPI_WriteByte(addr >> 16); /* Send address */ + SPI_WriteByte(addr >> 8); + SPI_WriteByte(addr); SPI_WriteByte(data); /* Write data */ FL_DESELECT(); /* De-select device */ + } + +/* + * fStream reading looks like so + * + */ + +void +flashstartread(uint32_t addr) { + assert(readstate == RW_IDLE); + + FL_SELECT(); /* Select device */ + + SPI_WriteByte(FL_READ); /* Send command */ + SPI_WriteByte(addr >> 16); /* Send address */ + SPI_WriteByte(addr >> 8); + SPI_WriteByte(addr); + + readstate = RW_RUNNING; +} + +uint8_t +flashreadbyte(void) { + assert(readstate == RW_RUNNING); + return SPI_WriteByte(0x00); /* Read data */ +} + +void +flashstopread(void) { + assert(readstate == RW_RUNNING); + + FL_DESELECT(); + + readstate = RW_IDLE; +} + +/* + * Auto increment writing looks like so + * + * Enable writing CS, WREN, nCS + * Send start address & first data word CS, AAI + addr + data, nCS + * Send subsequent words wait for nBUSY, CS, AAI + data, nCS + * ... + * Disable writing CS, WRDI, nCS + * + * XXX: EBSY command links SO to flash busy state, I don't think the + * STM32 could sample it without switching out of SPI mode. + */ +void +flashstartwrite(uint32_t addr, uint16_t data) { + assert(writestate == RW_IDLE); + + flashenablewrite(); /* Enable writes */ + + FL_SELECT(); /* Select device */ + + SPI_WriteByte(FL_AAIWP); /* Send command */ + SPI_WriteByte(addr >> 16); + SPI_WriteByte(addr >> 8); + SPI_WriteByte(addr & 0xff); /* Send address */ + + SPI_WriteByte(data & 0xff); /* Write LSB */ + SPI_WriteByte(data >> 8); /* Write MSB */ + + FL_DESELECT(); + + writestate = RW_RUNNING; +} + +void +flashwriteword(uint16_t data) { + assert(writestate == RW_RUNNING); + + flashwait(); /* Wait until not busy */ + + FL_SELECT(); /* Select device */ + + SPI_WriteByte(FL_AAIWP); /* Send command */ + SPI_WriteByte(data & 0xff); /* Write LSB */ + SPI_WriteByte(data >> 8); /* Write MSB */ + + FL_DESELECT(); /* De-select device */ +} + +void +flashstopwrite(void) { + assert(writestate == RW_RUNNING); + + flashwait(); /* Wait until not busy */ + + FL_SELECT(); /* Select device */ + + SPI_WriteByte(FL_WRDI); /* Send command */ + + FL_DESELECT(); /* Deselect device */ + + flashwait(); /* Wait until not busy */ + + writestate = RW_IDLE; +} + diff -r 1e2fa7396f98 -r a9cc07caa801 flash.h --- a/flash.h Sat Nov 17 12:17:58 2012 +1030 +++ b/flash.h Sat Nov 17 12:18:24 2012 +1030 @@ -7,6 +7,15 @@ uint8_t flashread(uint32_t addr); void flashenablewrite(void); void flashwrite(uint32_t addr, uint8_t data); +void flashwait(void); + +/* Streaming read/write */ +void flashstartread(uint32_t addr); +uint8_t flashreadbyte(void); +void flashstartwrite(uint32_t addr, uint16_t data); +void flashwriteword(uint16_t data); +void flashstopread(void); +void flashstopwrite(void); #define FL_BUSY (1<<0) #define FL_WEL (1<<1)