Add offset+len support to writes

Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/3f6222cf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3f6222cf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3f6222cf

Branch: refs/heads/develop
Commit: 3f6222cff16fa25f3d170b95cabe2daf6c9c171c
Parents: 92f8a32
Author: Fabio Utzig <[email protected]>
Authored: Tue Jan 3 22:59:45 2017 -0200
Committer: Fabio Utzig <[email protected]>
Committed: Fri Jan 20 07:27:40 2017 -0200

----------------------------------------------------------------------
 hw/drivers/flash/src/flash.c | 195 +++++++++++++++++++++++++-------------
 1 file changed, 130 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3f6222cf/hw/drivers/flash/src/flash.c
----------------------------------------------------------------------
diff --git a/hw/drivers/flash/src/flash.c b/hw/drivers/flash/src/flash.c
index 7b4c57a..0ffa2cc 100644
--- a/hw/drivers/flash/src/flash.c
+++ b/hw/drivers/flash/src/flash.c
@@ -67,11 +67,8 @@
 #define STATUS_BUSY                 (1 << 7)
 #define STATUS_CMP                  (1 << 6)
 
-#define MIN(n, m) (((n) < (m)) ? (n) : (m))
-
 /* TODO: make configurable to 512/528 */
 #define PAGE_SIZE                   512
-#define PAGE_BITS                   9
 
 /**
  * Reading memory (MEM_READ):
@@ -139,6 +136,8 @@ static struct hal_spi_settings at45db_settings = {
     .word_size  = HAL_SPI_WORD_SIZE_8BIT,
 };
 
+static uint8_t g_page_buffer[PAGE_SIZE];
+
 static struct flash_dev *
 cfg_dev(uint8_t id)
 {
@@ -160,8 +159,6 @@ static uint8_t read_status(struct flash_dev *flash)
 
     hal_gpio_write(flash->ss_pin, 1);
 
-    //printf("STATUS=[%02x]\n", val);
-
     return val;
 }
 
@@ -200,10 +197,65 @@ calc_page_count(uint32_t addr, size_t len)
 }
 
 static inline uint32_t
-next_page_addr(uint32_t addr)
+page_start_address(uint32_t addr)
 {
     /* FIXME: works only for 512? (powers of 2) */
-    return (addr & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+    return (addr & ~(PAGE_SIZE - 1));
+}
+
+static inline uint32_t
+page_next_addr(uint32_t addr)
+{
+    return (page_start_address(addr) + PAGE_SIZE);
+}
+
+/* FIXME: assume buf has enough space? */
+static uint16_t
+read_page(struct flash_dev *dev, uint32_t addr, uint16_t len, uint8_t *buf)
+{
+    uint16_t amount;
+    uint16_t pa;
+    uint16_t ba;
+    uint16_t n;
+    uint8_t val;
+
+    hal_gpio_write(dev->ss_pin, 0);
+
+    hal_spi_tx_val(dev->spi_num, MEM_READ);
+
+    pa = addr / PAGE_SIZE;
+    ba = addr % PAGE_SIZE;
+
+    val = (pa >> 6) & ~0x80;
+    hal_spi_tx_val(dev->spi_num, val);
+
+#if (PAGE_SIZE == 512)
+    val = (pa << 2) | ((ba >> 8) & 1);
+#else
+    val = (pa << 2) | ((ba >> 8) & 3);
+#endif
+    hal_spi_tx_val(dev->spi_num, val);
+
+    hal_spi_tx_val(dev->spi_num, ba);
+
+    hal_spi_tx_val(dev->spi_num, 0xff);
+    hal_spi_tx_val(dev->spi_num, 0xff);
+    hal_spi_tx_val(dev->spi_num, 0xff);
+    hal_spi_tx_val(dev->spi_num, 0xff);
+
+    if (len + ba <= PAGE_SIZE) {
+        amount = len;
+    } else {
+        amount = PAGE_SIZE - ba;
+    }
+
+    for (n = 0; n < amount; n++) {
+        buf[n] = hal_spi_tx_val(dev->spi_num, 0xff);
+    }
+
+    hal_gpio_write(dev->ss_pin, 1);
+
+    return amount;
 }
 
 int
@@ -242,10 +294,6 @@ int
 flash_read(uint8_t flash_id, uint32_t addr, void *buf, size_t len)
 {
     struct flash_dev *dev;
-    uint16_t pa;
-    uint16_t ba;
-    uint8_t val;
-    uint32_t n;
     uint16_t page_count;
     uint16_t amount;
     uint16_t index;
@@ -257,53 +305,16 @@ flash_read(uint8_t flash_id, uint32_t addr, void *buf, 
size_t len)
     }
 
     page_count = calc_page_count(addr, len);
-    index = 0;
     u8buf = (uint8_t *) buf;
+    index = 0;
+
     while (page_count--) {
         wait_ready(dev);
 
-        hal_gpio_write(dev->ss_pin, 0);
-
-        hal_spi_tx_val(dev->spi_num, MEM_READ);
-
-        pa = addr / PAGE_SIZE;
-        ba = addr % PAGE_SIZE;
-
-        /* < r, PA12-6 > */
-        val = (pa >> 6) & ~0x80;
-        hal_spi_tx_val(dev->spi_num, val);
-
-        /* < PA5-0, BA9-8 > */
+        amount = read_page(dev, addr, len, &u8buf[index]);
 
-#if (PAGE_SIZE == 512)
-        val = (pa << 2) | ((ba >> 8) & 1);
-#else
-        val = (pa << 2) | ((ba >> 8) & 3);
-#endif
-        hal_spi_tx_val(dev->spi_num, val);
-
-        /* < BA7-0 > */
-        hal_spi_tx_val(dev->spi_num, ba);
-
-        /* send 32 don't care bits */
-        hal_spi_tx_val(dev->spi_num, 0xff);
-        hal_spi_tx_val(dev->spi_num, 0xff);
-        hal_spi_tx_val(dev->spi_num, 0xff);
-        hal_spi_tx_val(dev->spi_num, 0xff);
-
-        if (len + ba <= PAGE_SIZE) {
-            amount = len;
-        } else {
-            amount = PAGE_SIZE - ba;
-        }
-
-        for (n = 0; n < amount; n++) {
-            u8buf[index++] = hal_spi_tx_val(dev->spi_num, 0xff);
-        }
-
-        hal_gpio_write(dev->ss_pin, 1);
-
-        addr = next_page_addr(addr);
+        addr = page_next_addr(addr);
+        index += amount;
         len -= amount;
     }
 
@@ -315,10 +326,12 @@ flash_write(uint8_t flash_id, uint32_t addr, const void 
*buf, size_t len)
 {
     struct flash_dev *dev;
     uint16_t pa;
-    //uint16_t bfa;
+    uint16_t bfa;
     uint32_t n;
+    uint32_t start_addr;
+    uint16_t index;
+    uint16_t amount;
     int page_count;
-    int offset;
     uint8_t *u8buf;
 
     dev = cfg_dev(flash_id);
@@ -327,23 +340,75 @@ flash_write(uint8_t flash_id, uint32_t addr, const void 
*buf, size_t len)
     }
 
     page_count = calc_page_count(addr, len);
-    offset = 0;
     u8buf = (uint8_t *) buf;
+    index = 0;
+
     while (page_count--) {
         wait_ready(dev);
 
+        bfa = addr % PAGE_SIZE;
+
+        /**
+         * If the page is not being written from the beginning,
+         * read first the current data to rewrite back.
+         *
+         * The whole page is read here for the case of some the
+         * real data ending before the end of the page, data must
+         * be written back again.
+         */
+        if (bfa || len < PAGE_SIZE) {
+            read_page(dev, page_start_address(addr), PAGE_SIZE, g_page_buffer);
+            wait_ready(dev);
+        }
+
         hal_gpio_write(dev->ss_pin, 0);
 
-        /* FIXME: ping-pong between page 1 and 2 */
+        /* TODO: ping-pong between page 1 and 2? */
         hal_spi_tx_val(dev->spi_num, BUF1_WRITE);
 
-        /* FIXME: always writing at 0 on buffer */
         hal_spi_tx_val(dev->spi_num, 0xff);
-        hal_spi_tx_val(dev->spi_num, 0xfc);
-        hal_spi_tx_val(dev->spi_num, 0);
 
-        for (n = 0; n < len; n++) {
-             hal_spi_tx_val(dev->spi_num, u8buf[n]);
+        start_addr = page_start_address(addr);
+
+        /* FIXME */
+#if (PAGE_SIZE == 512)
+        hal_spi_tx_val(dev->spi_num, (start_addr >> 8) & 1);
+#else
+        hal_spi_tx_val(dev->spi_num, (start_addr >> 8) & 3);
+#endif
+
+        hal_spi_tx_val(dev->spi_num, start_addr);
+
+        /**
+         * Write back extra stuff at the beginning of page.
+         */
+        if (bfa) {
+            amount = addr - start_addr;
+            for (n = 0; n < amount; n++) {
+                hal_spi_tx_val(dev->spi_num, g_page_buffer[n]);
+            }
+        }
+
+        if (len + bfa <= PAGE_SIZE) {
+            amount = len;
+        } else {
+            amount = PAGE_SIZE - bfa;
+        }
+
+        /**
+         * Write the stuff we're really want to write!
+         */
+        for (n = 0; n < amount; n++) {
+            hal_spi_tx_val(dev->spi_num, u8buf[index++]);
+        }
+
+        /**
+         * Write back extra stuff at the ending of page.
+         */
+        if (len < PAGE_SIZE) {
+            for (n = len; n < PAGE_SIZE; n++) {
+                hal_spi_tx_val(dev->spi_num, g_page_buffer[n]);
+            }
         }
 
         hal_gpio_write(dev->ss_pin, 1);
@@ -352,20 +417,20 @@ flash_write(uint8_t flash_id, uint32_t addr, const void 
*buf, size_t len)
 
         hal_gpio_write(dev->ss_pin, 0);
 
+        /* TODO: make command configurable (accept non erasing) */
         hal_spi_tx_val(dev->spi_num, BUF1_TO_MEM_ERASE);
 
         /* FIXME: check that pa doesn't overflow capacity */
         pa = addr / PAGE_SIZE;
 
-        printf("Writing at addr=%04lx, pa=%04x\n", addr, pa);
-
         hal_spi_tx_val(dev->spi_num, (pa >> 6) & ~0x80);
         hal_spi_tx_val(dev->spi_num, (pa << 2) | 0x3);
         hal_spi_tx_val(dev->spi_num, 0xff);
 
         hal_gpio_write(dev->ss_pin, 1);
 
-        offset += PAGE_SIZE;
+        addr = page_next_addr(addr);
+        len -= amount;
     }
 
     return 0;

Reply via email to