altos: Move ao_storage_erase to shared code. Add len
authorKeith Packard <keithp@keithp.com>
Tue, 9 Jun 2020 04:01:31 +0000 (21:01 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 9 Jun 2020 04:17:55 +0000 (21:17 -0700)
This makes ao_storage_erase take an arbitrary length. The new version
erases each storage block if there's any un-erased data present, and
then also checks after erasing to make sure the block is clear.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/drivers/ao_m25.c
src/kernel/ao_config.h
src/kernel/ao_storage.c
src/kernel/ao_storage.h
src/micropeak-v2.0/ao_micropeak.c
src/stmf0/ao_storage_stm.c

index 72617cc4504f24f18966e1a80f1be4699d2a1fc9..ca0615e7c5b75e30c8e1eb0b50f98d741977f2e7 100644 (file)
@@ -239,7 +239,7 @@ ao_m25_scan(void)
  * Erase the specified sector
  */
 uint8_t
-ao_storage_erase(uint32_t pos) 
+ao_storage_device_erase(uint32_t pos)
 {
        ao_port_t       cs;
 
index 7e8e62f31a5ff6652588d6cb61b872f5c102de13..87509dff8df1e94d8b8b15866a5845d021c264c0 100644 (file)
@@ -38,7 +38,7 @@
 #include <ao_storage.h>
 
 #define ao_config_setup()              ao_storage_setup()
-#define ao_config_erase()              ao_storage_erase(ao_storage_config)
+#define ao_config_erase()              ao_storage_erase(ao_storage_config, ao_storage_block)
 #define ao_config_write(pos,bytes, len)        ao_storage_write(ao_storage_config+(pos), bytes, len)
 #define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len)
 #define ao_config_flush()              ao_storage_flush()
index cfd116f9791bc536ae2e5709ddc066a3d84f3d8e..73b31c6420005cc7ee75d65a19c5e1b0e6302842 100644 (file)
 #include <ao.h>
 #include <ao_storage.h>
 
+#define AO_STORAGE_DATA_SIZE   256
+
+static uint8_t storage_data[AO_STORAGE_DATA_SIZE];
+
 uint8_t
-ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len) 
+ao_storage_read(ao_pos_t pos, void *v_buf, uint16_t len)
 {
        uint8_t *buf = v_buf;
        uint16_t this_len;
@@ -81,7 +85,60 @@ ao_storage_write(ao_pos_t pos, void *v_buf, uint16_t len)
        return 1;
 }
 
-static uint8_t storage_data[128];
+uint8_t
+ao_storage_is_erased(uint32_t pos)
+{
+       uint32_t        read_pos;
+       uint32_t        read_len;
+       uint32_t        i;
+
+       read_pos = pos;
+       read_len = ao_storage_block;
+       while (read_len) {
+               uint32_t this_time = AO_STORAGE_DATA_SIZE;
+               if (this_time > read_len)
+                       this_time = read_len;
+               if (!ao_storage_read(read_pos, storage_data, this_time))
+                       return 0;
+               for (i = 0; i < this_time; i++)
+                       if (storage_data[i] != 0xff)
+                               return 0;
+               read_pos += this_time;
+               read_len -= this_time;
+       }
+       return 1;
+}
+
+uint8_t
+ao_storage_erase(uint32_t start_pos, uint32_t len)
+{
+       /* Round 'len' up to ao_storage_block units */
+       len = ((len + ao_storage_block - 1) / ao_storage_block) * ao_storage_block;
+
+       /*
+        * Start at the end of the area to erase so that the
+        * last block cleared is the first block; this will ensure
+        * that partially erased flight logs still appear in the list
+        * and can be re-erased.
+        */
+       uint32_t pos = start_pos + len - ao_storage_block;
+       while (len) {
+               int tries;
+
+#define MAX_TRIES      4       /* needs to be at least 2 */
+               for (tries = 0; tries < MAX_TRIES; tries++) {
+                       if (ao_storage_is_erased(pos))
+                               break;
+                       if (!ao_storage_device_erase(pos))
+                               return 0;
+               }
+               if (tries == MAX_TRIES)
+                       return 0;
+               pos -= ao_storage_block;
+               len -= ao_storage_block;
+       }
+       return 1;
+}
 
 static void
 ao_storage_dump(void) 
@@ -143,19 +200,16 @@ ao_storage_zap(void)
        uint32_t v = ao_cmd_hex();
        if (ao_cmd_status != ao_cmd_success)
                return;
-       ao_storage_erase((uint32_t) v << 8);
+       ao_storage_erase((uint32_t) v << 8, ao_storage_block);
 }
 
 static void
 ao_storage_zapall(void) 
 {
-       uint32_t        pos;
-
        ao_cmd_white();
        if (!ao_match_word("DoIt"))
                return;
-       for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block)
-               ao_storage_erase(pos);
+       ao_storage_erase(0, ao_storage_log_max);
 }
 
 #if AO_STORAGE_TEST
@@ -265,26 +319,26 @@ ao_storage_incr_check_block(uint32_t pos)
 static uint8_t
 ao_storage_test_block(uint32_t pos) 
 {
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" erase"); flush();
        if (!ao_storage_check_block(pos, 0xff))
                return 0;
        printf(" zero"); flush();
        if (!ao_storage_fill_check_block(pos, 0x00))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" 0xaa"); flush();
        if (!ao_storage_fill_check_block(pos, 0xaa))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" 0x55"); flush();
        if (!ao_storage_fill_check_block(pos, 0x55))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" increment"); flush();
        if (!ao_storage_incr_check_block(pos))
                return 0;
-       ao_storage_erase(pos);
+       ao_storage_erase(pos, ao_storage_block);
        printf(" pass\n"); flush();
        return 1;
 }
@@ -304,6 +358,27 @@ ao_storage_test(void)
        }
        printf("Test complete\n");
 }
+
+static void
+ao_storage_fill(void)
+{
+       uint32_t        pos;
+
+       ao_cmd_white();
+       if (!ao_match_word("DoIt"))
+               return;
+       printf("erase "); flush();
+       ao_storage_erase(0, ao_storage_log_max);
+       for (pos = 0; pos < sizeof (storage_data); pos++)
+               storage_data[pos] = (uint8_t) pos;
+       for (pos = 0; pos < ao_storage_log_max; pos += sizeof (storage_data)) {
+               if ((pos & 0xffff) == 0) {
+                       printf("Fill 0x%x\n", pos); flush();
+               }
+               ao_storage_write(pos, storage_data, sizeof (storage_data));
+       }
+       printf("Fill complete\n");
+}
 #endif /* AO_STORAGE_TEST */
 
 static void
@@ -325,6 +400,7 @@ const struct ao_cmds ao_storage_cmds[] = {
        { ao_storage_zapall,"Z <key>\0Erase all. <key> is doit with D&I" },
 #if AO_STORAGE_TEST
        { ao_storage_test, "V <key>\0Validate flash (destructive). <key> is doit with D&I" },
+       { ao_storage_fill, "F <key>\0Fill flash with data. <key> is doit with D&I" },
 #endif
        { 0, NULL },
 };
index cf37a824db0a1c986603fd0b267d9cce59bcaaf4..1c5867e09eed3e9dc78f79a9a00490d488c3d9a4 100644 (file)
@@ -66,7 +66,13 @@ ao_storage_read(ao_pos_t pos, void *buf, uint16_t len);
 
 /* Erase a block of storage. This always clears ao_storage_block bytes */
 uint8_t
-ao_storage_erase(ao_pos_t pos);
+ao_storage_erase(ao_pos_t pos, uint32_t len);
+
+/* Check storage starting at pos to see if the chunk there
+ * is erased
+ */
+uint8_t
+ao_storage_is_erased(uint32_t pos);
 
 /* Flush any pending writes to stable storage */
 void
@@ -88,6 +94,10 @@ ao_storage_device_read(ao_pos_t pos, void *buf, uint16_t len);
 uint8_t
 ao_storage_device_write(ao_pos_t pos, void *buf, uint16_t len);
 
+/* Erase device from pos through pos + ao_storage_block */
+uint8_t
+ao_storage_device_erase(uint32_t pos);
+
 /* Initialize low-level device bits */
 void
 ao_storage_device_init(void);
index f3fbc9f42ca016041026086b88b0e562e84574a0..c0242b91d5d77a106c1013e9854ba3cd83c49f19 100644 (file)
@@ -167,9 +167,7 @@ ao_battery_voltage(void)
 static void
 ao_log_erase(void)
 {
-       uint32_t        pos;
-       for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block)
-               ao_storage_erase(pos);
+       ao_storage_erase(0, ao_storage_log_max);
 }
 
 uint8_t        ao_on_battery;
index 111db04a12a4cf21893c99d2adae5af252831877..4ecdc7a526534644994a8fbb6a1ffbd8772bb4af 100644 (file)
@@ -128,24 +128,9 @@ _ao_flash_write(uint32_t pos, void *sv, uint16_t len)
        stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
 }
 
-static bool
-ao_storage_is_erased(uint32_t pos)
-{
-       uint16_t *flash = _ao_flash_addr(pos);
-       uint32_t i = ao_storage_block >> 1;
-
-       while (i--)
-               if (*flash++ != 0xffff)
-                       return false;
-       return true;
-}
-
 uint8_t
-ao_storage_erase(uint32_t pos)
+ao_storage_device_erase(uint32_t pos)
 {
-       if (ao_storage_is_erased(pos))
-               return 1;
-
        ao_arch_block_interrupts();
        ao_flash_unlock();