From 742cbe3d4090d62ee5f871e487ce88145d12c04e Mon Sep 17 00:00:00 2001 From: Paul Selkirk Date: Sun, 19 Feb 2017 14:14:10 -0500 Subject: Simplify spiflash test code slightly, add keystore test code. --- projects/board-test/Makefile | 2 +- projects/board-test/keystore-perf.c | 198 ++++++++++++++++++++++++++++++++++++ projects/board-test/spiflash-perf.c | 68 +++++++------ spiflash_n25q128.c | 2 +- stm-keystore.h | 1 + 5 files changed, 239 insertions(+), 32 deletions(-) create mode 100644 projects/board-test/keystore-perf.c diff --git a/projects/board-test/Makefile b/projects/board-test/Makefile index 0e60229..bb6a8cf 100644 --- a/projects/board-test/Makefile +++ b/projects/board-test/Makefile @@ -1,4 +1,4 @@ -TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe rtc-test spiflash-perf +TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe rtc-test spiflash-perf keystore-perf all: $(TEST:=.elf) diff --git a/projects/board-test/keystore-perf.c b/projects/board-test/keystore-perf.c new file mode 100644 index 0000000..7af4893 --- /dev/null +++ b/projects/board-test/keystore-perf.c @@ -0,0 +1,198 @@ +/* + * Test read/write/erase performance of the flash keystore. + */ + +#include "string.h" + +#include "stm-init.h" +#include "stm-led.h" +#include "stm-uart.h" +#include "stm-keystore.h" + +/* + * 1. Read the entire flash by subsectors, ignoring data. + */ +static void test_read_data(void) +{ + uint8_t read_buf[KEYSTORE_SUBSECTOR_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE); + if (err != 1) { + uart_send_string("ERROR: keystore_read_data returned "); + uart_send_integer(err, 0); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * Read the flash data and verify it against a known pattern. + */ +static void _read_verify(uint8_t *vrfy_buf) +{ + uint8_t read_buf[KEYSTORE_SUBSECTOR_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE); + if (err != 1) { + uart_send_string("ERROR: keystore_read_data returned "); + uart_send_integer(err, 0); + uart_send_string("\r\n"); + break; + } + if (memcmp(read_buf, vrfy_buf, KEYSTORE_SUBSECTOR_SIZE) != 0) { + uart_send_string("ERROR: verify failed in subsector "); + uart_send_integer(i, 0); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2a. Erase the entire flash by sectors. + */ +static void test_erase_sector(void) +{ + uint32_t i; + int err; + + for (i = 0; i < KEYSTORE_NUM_SECTORS; ++i) { + err = keystore_erase_sectors(i, i); + if (err != 1) { + uart_send_string("ERROR: keystore_erase_sector returned "); + uart_send_integer(err, 0); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2b. Erase the entire flash by subsectors. + */ +static void test_erase_subsector(void) +{ + uint32_t i; + int err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_erase_subsectors(i, i); + if (err != 1) { + uart_send_string("ERROR: keystore_erase_subsector returned "); + uart_send_integer(err, 0); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2c. Read the entire flash, verify erasure. + */ +static void test_verify_erase(void) +{ + uint8_t vrfy_buf[KEYSTORE_SUBSECTOR_SIZE]; + uint32_t i; + + for (i = 0; i < sizeof(vrfy_buf); ++i) + vrfy_buf[i] = 0xFF; + + _read_verify(vrfy_buf); +} + +/* + * 3a. Write the entire flash with a pattern. + */ +static void test_write_data(void) +{ + uint8_t write_buf[KEYSTORE_SUBSECTOR_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < sizeof(write_buf); ++i) + write_buf[i] = i & 0xFF; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_write_data(i * KEYSTORE_SUBSECTOR_SIZE, write_buf, KEYSTORE_SUBSECTOR_SIZE); + if (err != 1) { + uart_send_string("ERROR: keystore_write_data returned "); + uart_send_integer(err, 0); + uart_send_string(" for subsector "); + uart_send_integer(i, 0); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 3b. Read the entire flash, verify data. + */ +static void test_verify_write(void) +{ + uint8_t vrfy_buf[KEYSTORE_SUBSECTOR_SIZE]; + uint32_t i; + + for (i = 0; i < sizeof(vrfy_buf); ++i) + vrfy_buf[i] = i & 0xFF; + + _read_verify(vrfy_buf); +} + +static void _time_check(char *label, const uint32_t t0, uint32_t n_rounds) +{ + uint32_t t = HAL_GetTick() - t0; + + uart_send_string(label); + uart_send_integer(t / 1000, 0); + uart_send_char('.'); + uart_send_integer(t % 1000, 3); + uart_send_string(" sec"); + if (n_rounds > 1) { + uart_send_string(" for "); + uart_send_integer(n_rounds, 0); + uart_send_string(" rounds, "); + uart_send_integer(t / n_rounds, 0); + uart_send_char('.'); + uart_send_integer(((t % n_rounds) * 100) / n_rounds, 2); + uart_send_string(" ms each"); + } + uart_send_string("\r\n"); +} + +#define time_check(_label_, _expr_, _n_) \ + do { \ + uint32_t _t = HAL_GetTick(); \ + (_expr_); \ + _time_check(_label_, _t, _n_); \ + } while (0) + +int main(void) +{ + stm_init(); + uart_set_default(STM_UART_MGMT); + + if (keystore_check_id() != 1) { + uart_send_string("ERROR: keystore_check_id failed\r\n"); + return 0; + } + + uart_send_string("Starting...\r\n"); + + time_check("read data ", test_read_data(), KEYSTORE_NUM_SUBSECTORS); + time_check("erase sector ", test_erase_sector(), KEYSTORE_NUM_SECTORS); + time_check("erase subsector ", test_erase_subsector(), KEYSTORE_NUM_SUBSECTORS); + time_check("verify erase ", test_verify_erase(), KEYSTORE_NUM_SUBSECTORS); + time_check("write data ", test_write_data(), KEYSTORE_NUM_SUBSECTORS); + time_check("verify write ", test_verify_write(), KEYSTORE_NUM_SUBSECTORS); + + uart_send_string("Done.\r\n\r\n"); + return 0; +} diff --git a/projects/board-test/spiflash-perf.c b/projects/board-test/spiflash-perf.c index 7265098..52d3c0f 100644 --- a/projects/board-test/spiflash-perf.c +++ b/projects/board-test/spiflash-perf.c @@ -22,18 +22,6 @@ extern struct spiflash_ctx keystore_ctx; static struct spiflash_ctx *ctx = &keystore_ctx; -/* - * Based on _wait_while_wip in spiflash_n25q128.c, but can be more - * aggressive about re-checking. - */ -static inline void _wait_while_wip(uint32_t delay) -{ - while (n25q128_get_wip_flag(ctx) != HAL_OK) { - if (delay != 0) - HAL_Delay(delay); - } -} - /* * 1. Read the entire flash by pages, ignoring data. */ @@ -149,10 +137,25 @@ static void test_verify_erase(void) _read_verify(vrfy_buf); } +/* + * Borrowed from spiflash_n25q128.c, since n25q128_write_page doesn't call it. + */ +inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) +{ + int i; + while (timeout--) { + i = n25q128_get_wip_flag(ctx); + if (i < 0) return 0; + if (! i) break; + HAL_Delay(10); + } + return 1; +} + /* * 3a. Write the entire flash with a pattern. */ -static void test_write_page(uint32_t delay) +static void test_write_page(void) { uint8_t write_buf[N25Q128_PAGE_SIZE]; uint32_t i; @@ -163,6 +166,8 @@ static void test_write_page(uint32_t delay) for (i = 0; i < N25Q128_NUM_PAGES; ++i) { err = n25q128_write_page(ctx, i, write_buf); + if (err == 1) + err = _wait_while_wip(ctx, 1000); if (err != 1) { uart_send_string("ERROR: n25q128_write_page returned "); uart_send_integer(err, 0); @@ -171,7 +176,6 @@ static void test_write_page(uint32_t delay) uart_send_string("\r\n"); break; } - _wait_while_wip(delay); } } @@ -197,11 +201,17 @@ static void _time_check(char *label, const uint32_t t0, uint32_t n_rounds) uart_send_integer(t / 1000, 0); uart_send_char('.'); uart_send_integer(t % 1000, 3); - uart_send_string(" sec for "); - uart_send_integer(n_rounds, 0); - uart_send_string(" rounds, "); - uart_send_integer((t + n_rounds/2) / n_rounds, 0); - uart_send_string(" ms each\r\n"); + uart_send_string(" sec"); + if (n_rounds > 1) { + uart_send_string(" for "); + uart_send_integer(n_rounds, 0); + uart_send_string(" rounds, "); + uart_send_integer(t / n_rounds, 0); + uart_send_char('.'); + uart_send_integer(((t % n_rounds) * 100) / n_rounds, 2); + uart_send_string(" ms each"); + } + uart_send_string("\r\n"); } #define time_check(_label_, _expr_, _n_) \ @@ -221,17 +231,15 @@ int main(void) return 0; } - uart_send_string("Starting...\r\n\r\n"); - - time_check("read_page ", test_read_page(), N25Q128_NUM_PAGES); - time_check("erase_sector ", test_erase_sector(), N25Q128_NUM_SECTORS); - time_check("erase_subsector ", test_erase_subsector(), N25Q128_NUM_SUBSECTORS); - time_check("erase_bulk ", test_erase_bulk(), 1); - time_check("verify_erase ", test_verify_erase(), N25Q128_NUM_PAGES); - time_check("write_page 0ms ", test_write_page(0), N25Q128_NUM_PAGES); - time_check("write_page 1ms ", test_write_page(1), N25Q128_NUM_PAGES); - time_check("write_page 10ms ", test_write_page(10), N25Q128_NUM_PAGES); - time_check("verify_write ", test_verify_write(), N25Q128_NUM_PAGES); + uart_send_string("Starting...\r\n"); + + time_check("read page ", test_read_page(), N25Q128_NUM_PAGES); + time_check("erase sector ", test_erase_sector(), N25Q128_NUM_SECTORS); + time_check("erase subsector ", test_erase_subsector(), N25Q128_NUM_SUBSECTORS); + time_check("erase bulk ", test_erase_bulk(), 1); + time_check("verify erase ", test_verify_erase(), N25Q128_NUM_PAGES); + time_check("write page ", test_write_page(), N25Q128_NUM_PAGES); + time_check("verify write ", test_verify_write(), N25Q128_NUM_PAGES); uart_send_string("Done.\r\n\r\n"); return 0; diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c index 68f96f1..371bef2 100644 --- a/spiflash_n25q128.c +++ b/spiflash_n25q128.c @@ -220,7 +220,7 @@ inline int _wait_while_wip(struct spiflash_ctx *ctx, uint32_t timeout) int i; while (timeout--) { i = n25q128_get_wip_flag(ctx); - if (i < 0) return 0; // impossible + if (i < 0) return 0; if (! i) break; HAL_Delay(10); } diff --git a/stm-keystore.h b/stm-keystore.h index 9054db5..437cdf6 100644 --- a/stm-keystore.h +++ b/stm-keystore.h @@ -39,6 +39,7 @@ #include "spiflash_n25q128.h" #define KEYSTORE_PAGE_SIZE N25Q128_PAGE_SIZE +#define KEYSTORE_NUM_PAGES N25Q128_NUM_PAGES #define KEYSTORE_SECTOR_SIZE N25Q128_SECTOR_SIZE #define KEYSTORE_NUM_SECTORS N25Q128_NUM_SECTORS #define KEYSTORE_SUBSECTOR_SIZE N25Q128_SUBSECTOR_SIZE -- cgit v1.2.3