diff options
Diffstat (limited to 'projects/board-test')
-rw-r--r-- | projects/board-test/Makefile | 5 | ||||
-rw-r--r-- | projects/board-test/fmc-perf.c | 39 | ||||
-rw-r--r-- | projects/board-test/fmc-probe.c | 25 | ||||
-rw-r--r-- | projects/board-test/fmc-test.c | 83 | ||||
-rw-r--r-- | projects/board-test/keystore-perf.c | 197 | ||||
-rw-r--r-- | projects/board-test/led-test.c | 1 | ||||
-rw-r--r-- | projects/board-test/rtc-test.c | 75 | ||||
-rw-r--r-- | projects/board-test/short-test.c | 1 | ||||
-rw-r--r-- | projects/board-test/spiflash-perf.c | 249 | ||||
-rw-r--r-- | projects/board-test/uart-test.c | 1 |
10 files changed, 537 insertions, 139 deletions
diff --git a/projects/board-test/Makefile b/projects/board-test/Makefile index 9b1812f..45e75fc 100644 --- a/projects/board-test/Makefile +++ b/projects/board-test/Makefile @@ -1,4 +1,7 @@ -TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe rtc-test +TEST = led-test short-test uart-test fmc-test fmc-perf fmc-probe +ifeq (${BOARD},TARGET_CRYPTECH_ALPHA) +TEST += rtc-test spiflash-perf keystore-perf +endif all: $(TEST:=.elf) diff --git a/projects/board-test/fmc-perf.c b/projects/board-test/fmc-perf.c index 0c753a7..5af0946 100644 --- a/projects/board-test/fmc-perf.c +++ b/projects/board-test/fmc-perf.c @@ -1,7 +1,6 @@ /* * Test read/write performance of the fmc bus */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-fmc.h" @@ -32,14 +31,8 @@ static void sanity(void) uint32_t rnd, data; rnd = random(); - if (fmc_write_32(0, &rnd) != 0) { - uart_send_string("fmc_write_32 failed\r\n"); - Error_Handler(); - } - if (fmc_read_32(0, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_write_32(0, rnd); + fmc_read_32(0, &data); if (data != rnd) { uart_send_string("Data bus fail: expected "); uart_send_hex(rnd, 8); @@ -57,11 +50,11 @@ static void _time_check(char *label, const uint32_t t0) uint32_t t = HAL_GetTick() - t0; uart_send_string(label); - uart_send_integer(t / 1000, 0); + uart_send_integer(t / 1000, 1); uart_send_char('.'); uart_send_integer(t % 1000, 3); uart_send_string(" seconds, "); - uart_send_integer(((1000 * TEST_NUM_ROUNDS) / t), 0); + uart_send_integer(((1000 * TEST_NUM_ROUNDS) / t), 1); uart_send_string("/sec\r\n"); } @@ -77,10 +70,7 @@ static void test_read(void) uint32_t i, data; for (i = 0; i < TEST_NUM_ROUNDS; ++i) { - if (fmc_read_32(0, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_read_32(0, &data); } } @@ -89,33 +79,16 @@ static void test_write(void) uint32_t i; for (i = 0; i < TEST_NUM_ROUNDS; ++i) { - if (fmc_write_32(0, &i) != 0) { - uart_send_string("fmc_write_32 failed\r\n"); - Error_Handler(); - } + fmc_write_32(0, i); } } int main(void) { stm_init(); - - uart_send_string("Keep calm for Novena boot...\r\n"); - - // Blink blue LED for six seconds to not upset the Novena at boot. - led_on(LED_BLUE); - for (int i = 0; i < 12; i++) { - HAL_Delay(500); - led_toggle(LED_BLUE); - } - led_off(LED_BLUE); - // initialize rng MX_RNG_Init(); - // prepare fmc interface - fmc_init(); - sanity(); time_check("read ", test_read()); diff --git a/projects/board-test/fmc-probe.c b/projects/board-test/fmc-probe.c index 55d3521..38897ab 100644 --- a/projects/board-test/fmc-probe.c +++ b/projects/board-test/fmc-probe.c @@ -2,7 +2,6 @@ * in other cases, it will be the core name and version strings. */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-fmc.h" @@ -22,37 +21,15 @@ static uint32_t read0(uint32_t addr) { uint32_t data; - if (fmc_read_32(addr, &data) != 0) { - uart_send_string("fmc_read_32 failed\r\n"); - Error_Handler(); - } + fmc_read_32(addr, &data); return data; } int main(void) { - int i; - stm_init(); - - uart_send_string("Keep calm for Novena boot...\r\n"); - - // Blink blue LED for six seconds to not upset the Novena at boot. - led_on(LED_BLUE); - for (i = 0; i < 12; i++) { - HAL_Delay(500); - led_toggle(LED_BLUE); - } - - // prepare fmc interface - fmc_init(); - - // turn on green led, turn off other leds led_on(LED_GREEN); - led_off(LED_YELLOW); - led_off(LED_RED); - led_off(LED_BLUE); for (uint32_t addr = 0; addr < 0x00080000; addr += 4) { uint32_t data = read0(addr); diff --git a/projects/board-test/fmc-test.c b/projects/board-test/fmc-test.c index bc5a768..bd30dd5 100644 --- a/projects/board-test/fmc-test.c +++ b/projects/board-test/fmc-test.c @@ -4,8 +4,7 @@ /* This requires a special bitstream with a special test register. - See core/platform/novena/fmc/rtl/novena_fmc_top.v, sections marked - `ifdef test: + See core/platform/alpha/rtl/alpha_fmc_test.v: //---------------------------------------------------------------- // Dummy Register // @@ -34,11 +33,11 @@ //------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-fmc.h" #include "stm-uart.h" +#include "stm-fpgacfg.h" //------------------------------------------------------------------------------ // Defines @@ -76,6 +75,7 @@ int test_fpga_address_bus(void); // Defines //------------------------------------------------------------------------------ #define TEST_NUM_ROUNDS 100000 +#define VERBOSE 0 //------------------------------------------------------------------------------ @@ -88,7 +88,7 @@ int main(void) uart_send_string("Keep calm for FPGA bitstream loading...\r\n"); - // Blink blue LED until the FPGA reports it has loaded it's bitstream + // Blink blue LED until the FPGA reports it has loaded its bitstream led_on(LED_BLUE); while (! fpgacfg_check_done()) { for (i = 0; i < 4; i++) { @@ -100,9 +100,6 @@ int main(void) // initialize rng MX_RNG_Init(); - // prepare fmc interface - fmc_init(); - // turn on green led, turn off other leds led_on(LED_GREEN); led_off(LED_YELLOW); @@ -120,11 +117,15 @@ int main(void) // test address bus addr_test_ok = test_fpga_address_bus(); - uart_send_string("Data: "); - uart_send_integer(data_test_ok, 6); - uart_send_string(", addr: "); - uart_send_integer(addr_test_ok, 6); - uart_send_string("\r\n"); + if (VERBOSE || + (data_test_ok != TEST_NUM_ROUNDS || + addr_test_ok != TEST_NUM_ROUNDS)) { + uart_send_string("Data: "); + uart_send_integer(data_test_ok, 6); + uart_send_string(", addr: "); + uart_send_integer(addr_test_ok, 6); + uart_send_string("\r\n"); + } if (data_test_ok == TEST_NUM_ROUNDS && addr_test_ok == TEST_NUM_ROUNDS) { @@ -140,11 +141,12 @@ int main(void) } uart_send_string("Success "); - uart_send_integer(successful_runs, 0); + uart_send_integer(successful_runs, 1); uart_send_string(", fail "); - uart_send_integer(failed_runs, 0); - uart_send_string("\r\n\r\n"); - + uart_send_integer(failed_runs, 1); + uart_send_string("\r\n"); + if (VERBOSE) + uart_send_string("\r\n"); HAL_Delay(sleep); } @@ -156,7 +158,7 @@ int main(void) int test_fpga_data_bus(void) //------------------------------------------------------------------------------ { - int c, ok; + int c; uint32_t rnd, buf; HAL_StatusTypeDef hal_result; @@ -169,12 +171,10 @@ int test_fpga_data_bus(void) if (hal_result != HAL_OK) break; // write value to fpga at address 0 - ok = fmc_write_32(0, &rnd); - if (ok != 0) break; + fmc_write_32(0, rnd); // read value from fpga - ok = fmc_read_32(0, &buf); - if (ok != 0) break; + fmc_read_32(0, &buf); // compare (abort testing in case of error) if (buf != rnd) @@ -197,13 +197,16 @@ int test_fpga_data_bus(void) data_diff = buf; data_diff ^= rnd; - uart_send_string("Sample of data bus test data: expected "); - uart_send_binary(rnd, 32); - uart_send_string(", got "); - uart_send_binary(buf, 32); - uart_send_string(", diff "); - uart_send_binary(data_diff, 32); - uart_send_string("\r\n"); + if (VERBOSE || data_diff) { + uart_send_string("Sample of data bus test data: expected "); + uart_send_binary(rnd, 32); + uart_send_string(", got "); + uart_send_binary(buf, 32); + uart_send_string(", diff "); + uart_send_binary(data_diff, 32); + uart_send_string("\r\n"); + } + // return number of successful tests return c; } @@ -213,7 +216,7 @@ int test_fpga_data_bus(void) int test_fpga_address_bus(void) //------------------------------------------------------------------------------ { - int c, ok; + int c; uint32_t rnd, buf; HAL_StatusTypeDef hal_result; @@ -234,12 +237,10 @@ int test_fpga_address_bus(void) if (rnd == 0) continue; // write dummy value to fpga at some non-zero address - ok = fmc_write_32(rnd, &buf); - if (ok != 0) break; + fmc_write_32(rnd, buf); // read value from fpga - ok = fmc_read_32(0, &buf); - if (ok != 0) break; + fmc_read_32(0, &buf); // fpga receives address of 32-bit word, while we need // byte address here to compare @@ -266,13 +267,15 @@ int test_fpga_address_bus(void) addr_diff = buf; addr_diff ^= rnd; - uart_send_string("Sample of addr bus test data: expected "); - uart_send_binary(rnd, 32); - uart_send_string(", got "); - uart_send_binary(buf, 32); - uart_send_string(", diff "); - uart_send_binary(addr_diff, 32); - uart_send_string("\r\n"); + if (VERBOSE || addr_diff) { + uart_send_string("Sample of addr bus test data: expected "); + uart_send_binary(rnd, 32); + uart_send_string(", got "); + uart_send_binary(buf, 32); + uart_send_string(", diff "); + uart_send_binary(addr_diff, 32); + uart_send_string("\r\n"); + } return c; } diff --git a/projects/board-test/keystore-perf.c b/projects/board-test/keystore-perf.c new file mode 100644 index 0000000..c2aa4fb --- /dev/null +++ b/projects/board-test/keystore-perf.c @@ -0,0 +1,197 @@ +/* + * 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; + HAL_StatusTypeDef err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE); + if (err != HAL_OK) { + uart_send_string("ERROR: keystore_read_data returned "); + uart_send_integer(err, 1); + 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; + HAL_StatusTypeDef err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_read_data(i * KEYSTORE_SUBSECTOR_SIZE, read_buf, KEYSTORE_SUBSECTOR_SIZE); + if (err != HAL_OK) { + uart_send_string("ERROR: keystore_read_data returned "); + uart_send_integer(err, 1); + 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, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2a. Erase the entire flash by sectors. + */ +static void test_erase_sector(void) +{ + uint32_t i; + HAL_StatusTypeDef err; + + for (i = 0; i < KEYSTORE_NUM_SECTORS; ++i) { + err = keystore_erase_sector(i); + if (err != HAL_OK) { + uart_send_string("ERROR: keystore_erase_sector returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2b. Erase the entire flash by subsectors. + */ +static void test_erase_subsector(void) +{ + uint32_t i; + HAL_StatusTypeDef err; + + for (i = 0; i < KEYSTORE_NUM_SUBSECTORS; ++i) { + err = keystore_erase_subsector(i); + if (err != HAL_OK) { + uart_send_string("ERROR: keystore_erase_subsector returned "); + uart_send_integer(err, 1); + 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; + HAL_StatusTypeDef 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 != HAL_OK) { + uart_send_string("ERROR: keystore_write_data returned "); + uart_send_integer(err, 1); + uart_send_string(" for subsector "); + uart_send_integer(i, 1); + 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, 1); + 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, 1); + uart_send_string(" rounds, "); + uart_send_integer(t / n_rounds, 1); + 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(); + + if (keystore_check_id() != HAL_OK) { + 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 subsector ", test_erase_subsector(), KEYSTORE_NUM_SUBSECTORS); + time_check("erase sector ", test_erase_sector(), KEYSTORE_NUM_SECTORS); + 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/led-test.c b/projects/board-test/led-test.c index 7e72788..2ec7c9d 100644 --- a/projects/board-test/led-test.c +++ b/projects/board-test/led-test.c @@ -1,7 +1,6 @@ /* * Blink the four LEDs on the rev01 board in a pattern. */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" diff --git a/projects/board-test/rtc-test.c b/projects/board-test/rtc-test.c index b8a7511..bbb297a 100644 --- a/projects/board-test/rtc-test.c +++ b/projects/board-test/rtc-test.c @@ -8,7 +8,6 @@ */ #include <string.h> -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-uart.h" @@ -23,18 +22,18 @@ uint32_t i; uint32_t device_ready(uint16_t i2c_addr) { - uart_send_string2(STM_UART_MGMT, "Checking readiness of 0x"); - uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); - uart_send_string2(STM_UART_MGMT, "..."); + uart_send_string("Checking readiness of 0x"); + uart_send_hex(i2c_addr, 4); + uart_send_string("..."); if (rtc_device_ready(i2c_addr) == HAL_OK) { - uart_send_string2(STM_UART_MGMT, "OK\r\n"); + uart_send_string("OK\r\n"); return 1; } - uart_send_string2(STM_UART_MGMT, "Not ready (0x"); - uart_send_number2(STM_UART_MGMT, i, 4, 16); - uart_send_string2(STM_UART_MGMT, ")\r\n"); + uart_send_string("Not ready (0x"); + uart_send_hex(i, 4); + uart_send_string(")\r\n"); return 0; } @@ -44,34 +43,34 @@ void send_byte(const uint16_t i2c_addr, const uint8_t value) { uint8_t ch = value; - uart_send_string2(STM_UART_MGMT, "Sending "); - uart_send_number2(STM_UART_MGMT, ch, 2, 16); - uart_send_string2(STM_UART_MGMT, " to 0x"); - uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); - uart_send_string2(STM_UART_MGMT, "..."); + uart_send_string("Sending "); + uart_send_hex(ch, 2); + uart_send_string(" to 0x"); + uart_send_hex(i2c_addr, 4); + uart_send_string("..."); if (rtc_send_byte(i2c_addr, ch, 1000) != HAL_OK) { - uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + uart_send_string("Timeout\r\n"); Error_Handler(); } - uart_send_string2(STM_UART_MGMT, "OK\r\n"); + uart_send_string("OK\r\n"); } void read_bytes (uint8_t *buf, const uint16_t i2c_addr, const uint8_t len) { - uart_send_string2(STM_UART_MGMT, "Reading "); - uart_send_number2(STM_UART_MGMT, len, 3, 10); - uart_send_string2(STM_UART_MGMT, " bytes from 0x"); - uart_send_number2(STM_UART_MGMT, i2c_addr, 4, 16); - uart_send_string2(STM_UART_MGMT, "..."); + uart_send_string("Reading "); + uart_send_integer(len, 1); + uart_send_string(" bytes from 0x"); + uart_send_hex(i2c_addr, 4); + uart_send_string("..."); if (rtc_read_bytes(i2c_addr, buf, len, 1000) != HAL_OK) { - uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + uart_send_string("Timeout\r\n"); Error_Handler(); } - uart_send_string2(STM_UART_MGMT, "OK\r\n"); + uart_send_string("OK\r\n"); } void request_data(uint8_t *buf, const uint16_t i2c_addr, const uint8_t offset, const uint8_t bytes) @@ -85,8 +84,8 @@ void print_time() request_data(buf, RTC_RTC_ADDR, RTC_TIME_OFFSET, RTC_TIME_BYTES); for (i = 0; i < RTC_TIME_BYTES; i++) { - uart_send_number2(STM_UART_MGMT, buf[i], 2, 16); - uart_send_string2(STM_UART_MGMT, " "); + uart_send_hex(buf[i], 2); + uart_send_string(" "); } } @@ -94,37 +93,37 @@ void dump_sram() { request_data(buf, RTC_RTC_ADDR, 0x0, RTC_SRAM_TOTAL_BYTES); - uart_send_string2(STM_UART_MGMT, "SRAM contents:\r\n"); - uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_SRAM_TOTAL_BYTES); + uart_send_string("SRAM contents:\r\n"); + uart_send_hexdump(buf, 0, RTC_SRAM_TOTAL_BYTES); - uart_send_string2(STM_UART_MGMT, "\r\n"); + uart_send_string("\r\n"); } void dump_eeprom() { request_data(buf, RTC_EEPROM_ADDR, 0x0, RTC_EEPROM_TOTAL_BYTES); - uart_send_string2(STM_UART_MGMT, "EEPROM contents:\r\n"); - uart_send_hexdump(STM_UART_MGMT, buf, 0, RTC_EEPROM_TOTAL_BYTES); - uart_send_string2(STM_UART_MGMT, "\r\n"); + uart_send_string("EEPROM contents:\r\n"); + uart_send_hexdump(buf, 0, RTC_EEPROM_TOTAL_BYTES); + uart_send_string("\r\n"); request_data(buf, RTC_EEPROM_ADDR, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES); - uart_send_string2(STM_UART_MGMT, "EEPROM EUI-48:\r\n"); - uart_send_hexdump(STM_UART_MGMT, buf, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES); + uart_send_string("EEPROM EUI-48:\r\n"); + uart_send_hexdump(buf, RTC_EEPROM_EUI48_OFFSET, RTC_EEPROM_EUI48_BYTES); - uart_send_string2(STM_UART_MGMT, "\r\n"); + uart_send_string("\r\n"); } void enable_oscillator() { - uart_send_string2(STM_UART_MGMT, "Enabling oscillator...\r\n"); + uart_send_string("Enabling oscillator...\r\n"); if (rtc_enable_oscillator() != HAL_OK) { - uart_send_string2(STM_UART_MGMT, "Timeout\r\n"); + uart_send_string("Timeout\r\n"); Error_Handler(); } - uart_send_string2(STM_UART_MGMT, "OK\r\n"); + uart_send_string("OK\r\n"); } @@ -132,7 +131,7 @@ int main() { stm_init(); - uart_send_string2(STM_UART_MGMT, "\r\n\r\n*** Init done\r\n"); + uart_send_string("\r\n\r\n*** Init done\r\n"); dump_sram(); dump_eeprom(); @@ -148,7 +147,7 @@ main() print_time(buf); - uart_send_string2(STM_UART_MGMT, "\r\n\r\n"); + uart_send_string("\r\n\r\n"); HAL_GPIO_TogglePin(LED_PORT, LED_GREEN); DELAY(); diff --git a/projects/board-test/short-test.c b/projects/board-test/short-test.c index 27b8e7a..db0251b 100644 --- a/projects/board-test/short-test.c +++ b/projects/board-test/short-test.c @@ -5,7 +5,6 @@ * Toggles the BLUE LED slowly and the RED LED for every * character sent. */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-uart.h" diff --git a/projects/board-test/spiflash-perf.c b/projects/board-test/spiflash-perf.c new file mode 100644 index 0000000..36c6131 --- /dev/null +++ b/projects/board-test/spiflash-perf.c @@ -0,0 +1,249 @@ +/* + * Test read/write/erase performance of the N25Q128 SPI flash chip. + */ + +#include "string.h" + +#include "stm-init.h" +#include "stm-led.h" +#include "stm-uart.h" +#include "stm-keystore.h" +#include "spiflash_n25q128.h" + +/* + * Use the keystore memory for testing, because it's less involved than + * using the FPGA configuration memory, and less work to restore it to a + * useful configuration. + * + * However, rather than using the stm-keystore abstractions, this version + * goes straight to the low-level API. + */ + +extern struct spiflash_ctx keystore_ctx; +static struct spiflash_ctx *ctx = &keystore_ctx; + +/* + * 1a. Read the entire flash by pages, ignoring data. + */ +static void test_read_page(void) +{ + uint8_t read_buf[N25Q128_PAGE_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < N25Q128_NUM_PAGES; ++i) { + err = n25q128_read_page(ctx, i, read_buf); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_read_page returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 1b. Read the entire flash by subsectors, ignoring data. + */ +static void test_read_subsector(void) +{ + uint8_t read_buf[N25Q128_SUBSECTOR_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < N25Q128_NUM_SUBSECTORS; ++i) { + err = n25q128_read_subsector(ctx, i, read_buf); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_read_subsector returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * Read the flash data and verify it against a known pattern. + * It turns out that verification doesn't slow us down in any measurable + * way, because memcmp on 256 bytes is pretty inconsequential. + */ +static void _read_verify(uint8_t *vrfy_buf) +{ + uint8_t read_buf[N25Q128_PAGE_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < N25Q128_NUM_PAGES; ++i) { + err = n25q128_read_page(ctx, i, read_buf); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_read_page returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + break; + } + if (memcmp(read_buf, vrfy_buf, N25Q128_PAGE_SIZE) != 0) { + uart_send_string("ERROR: verify failed in page "); + uart_send_integer(i, 1); + 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 < N25Q128_NUM_SECTORS; ++i) { + err = n25q128_erase_sector(ctx, i); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_erase_sector returned "); + uart_send_integer(err, 1); + 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 < N25Q128_NUM_SUBSECTORS; ++i) { + err = n25q128_erase_subsector(ctx, i); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_erase_subsector returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 2c. Erase the entire flash in bulk. + */ +static void test_erase_bulk(void) +{ + int err; + + err = n25q128_erase_bulk(ctx); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_erase_bulk returned "); + uart_send_integer(err, 1); + uart_send_string("\r\n"); + } +} + +/* + * 2d. Read the entire flash, verify erasure. + */ +static void test_verify_erase(void) +{ + uint8_t vrfy_buf[N25Q128_PAGE_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_page(void) +{ + uint8_t write_buf[N25Q128_PAGE_SIZE]; + uint32_t i; + int err; + + for (i = 0; i < sizeof(write_buf); ++i) + write_buf[i] = i & 0xFF; + + for (i = 0; i < N25Q128_NUM_PAGES; ++i) { + err = n25q128_write_page(ctx, i, write_buf); + if (err != HAL_OK) { + uart_send_string("ERROR: n25q128_write_page returned "); + uart_send_integer(err, 1); + uart_send_string(" for page "); + uart_send_integer(i, 1); + uart_send_string("\r\n"); + break; + } + } +} + +/* + * 3b. Read the entire flash, verify data. + */ +static void test_verify_write(void) +{ + uint8_t vrfy_buf[N25Q128_PAGE_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, 1); + 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, 1); + uart_send_string(" rounds, "); + uart_send_integer(t / n_rounds, 1); + 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(); + + if (n25q128_check_id(ctx) != HAL_OK) { + uart_send_string("ERROR: n25q128_check_id failed\r\n"); + return 0; + } + + uart_send_string("Starting...\r\n"); + + time_check("read page ", test_read_page(), N25Q128_NUM_PAGES); + time_check("read subsector ", test_read_subsector(), N25Q128_NUM_SUBSECTORS); + time_check("erase subsector ", test_erase_subsector(), N25Q128_NUM_SUBSECTORS); + time_check("erase sector ", test_erase_sector(), N25Q128_NUM_SECTORS); + 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/projects/board-test/uart-test.c b/projects/board-test/uart-test.c index be06863..9a56dee 100644 --- a/projects/board-test/uart-test.c +++ b/projects/board-test/uart-test.c @@ -6,7 +6,6 @@ * Toggles the BLUE LED slowly and the GREEN LED for every * character sent. */ -#include "stm32f4xx_hal.h" #include "stm-init.h" #include "stm-led.h" #include "stm-uart.h" |