diff flash.c @ 25:a9cc07caa801

Add stream read/write commands.
author Daniel O'Connor <darius@dons.net.au>
date Sat, 17 Nov 2012 12:18:24 +1030
parents bd8e2cf04034
children 74efdb21ae5d
line wrap: on
line diff
--- 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 <stdint.h>
 #include <string.h>
 #include <stdlib.h>
+#include <assert.h>
 
 #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;
+}
+