|
|
@@ -19,6 +19,7 @@
|
|
|
#include "bsp_V8M_YY_pwm.h"
|
|
|
#include "hard_system.h"
|
|
|
#include <string.h>
|
|
|
+#include "test.h"
|
|
|
|
|
|
#ifdef GD25Q16_FLASH
|
|
|
#include "hard_flash_gd25q16.h"
|
|
|
@@ -845,3 +846,601 @@ void write_par_to_flash(void)
|
|
|
}
|
|
|
|
|
|
//------------------End of File----------------------------
|
|
|
+#ifdef SOFT_FLASH_TEST
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// GD25Q16 芯片参数
|
|
|
+//============================================================================
|
|
|
+#define GD25Q16_TOTAL_SIZE (2 * 1024 * 1024) // 2MB
|
|
|
+#define GD25Q16_PAGE_SIZE 256 // 页大小 256 字节
|
|
|
+#define GD25Q16_SECTOR_SIZE (4 * 1024) // 扇区大小 4KB
|
|
|
+#define GD25Q16_BLOCK_SIZE (64 * 1024) // 块大小 64KB
|
|
|
+#define GD25Q16_TOTAL_PAGES (GD25Q16_TOTAL_SIZE / GD25Q16_PAGE_SIZE) // 8192 页
|
|
|
+#define GD25Q16_TOTAL_SECTORS (GD25Q16_TOTAL_SIZE / GD25Q16_SECTOR_SIZE) // 512 扇区
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 根据您的地址划分重新计算(基于实际地址,不是页索引)
|
|
|
+//============================================================================
|
|
|
+// 您的地址定义(基于字节地址)
|
|
|
+#define IAP_ADDR (512 * 5) // 0x00000A00
|
|
|
+#define pidinf_addr (512 * 16) // 0x00002000
|
|
|
+#define verinf_addr (512 * 24) // 0x00003000
|
|
|
+#define confinf_addr (512 * 32) // 0x00004000
|
|
|
+#define caminf_addr (512 * 40) // 0x00005000
|
|
|
+#define parinf_addr (512 * 48) // 0x00006000
|
|
|
+#define POS_TOTAL_ADDR (512 * 56) // 0x00007000
|
|
|
+#define NO_FLY_ZONE_ADDR (512 * 64) // 0x00008000
|
|
|
+#define FPALTCHANGE_ADDR (512 * 80) // 0x0000A000
|
|
|
+#define BREAKPOINT_ADDR (512 * 88) // 0x0000B000
|
|
|
+#define WAYPOINT_ADDR (512 * 96) // 0x0000C000
|
|
|
+#define POS_START_PAGE 200 // 页索引 200 = 0x0000C800? 需要重新计算
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 测试区域定义 - 使用 Flash 末尾的安全区域(最后 256KB)
|
|
|
+//============================================================================
|
|
|
+#define TEST_AREA_START (GD25Q16_TOTAL_SIZE - 256 * 1024) // 最后 256KB (0x1C0000)
|
|
|
+#define TEST_AREA_SIZE (256 * 1024) // 256KB 测试空间
|
|
|
+#define TEST_AREA_END (TEST_AREA_START + TEST_AREA_SIZE)
|
|
|
+
|
|
|
+// 测试地址验证
|
|
|
+#define IS_TEST_ADDR(addr) \
|
|
|
+ ((addr) >= TEST_AREA_START && (addr) < TEST_AREA_END)
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 全局测试变量
|
|
|
+//============================================================================
|
|
|
+static bool test_passed = true;
|
|
|
+static uint32_t test_count = 0;
|
|
|
+static uint32_t fail_count = 0;
|
|
|
+
|
|
|
+// 缓冲区
|
|
|
+static uint8_t g_test_buffer[GD25Q16_PAGE_SIZE * 4]; // 4页缓冲区
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 辅助函数
|
|
|
+//============================================================================
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 打印测试结果
|
|
|
+ */
|
|
|
+static void print_result(const char* test_name, bool passed)
|
|
|
+{
|
|
|
+ if (passed) {
|
|
|
+ printf("[PASS] %s\n", test_name);
|
|
|
+ test_count++;
|
|
|
+ } else {
|
|
|
+ printf("[FAIL] %s\n", test_name);
|
|
|
+ fail_count++;
|
|
|
+ test_passed = false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 打印十六进制数据
|
|
|
+ */
|
|
|
+static void print_hex(const uint8_t* data, uint16_t len, const char* title)
|
|
|
+{
|
|
|
+ printf("%s:\n", title);
|
|
|
+ for (uint16_t i = 0; i < len; i++) {
|
|
|
+ if (i % 16 == 0 && i != 0) printf("\n");
|
|
|
+ printf("%02X ", data[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 保存测试区域数据
|
|
|
+ */
|
|
|
+static void save_test_area(uint32_t addr, uint32_t len)
|
|
|
+{
|
|
|
+ if (len > sizeof(g_test_buffer)) {
|
|
|
+ len = sizeof(g_test_buffer);
|
|
|
+ }
|
|
|
+ printf(" Saving data at 0x%06X...\n", addr);
|
|
|
+ flash_read_bytes(addr, g_test_buffer, len);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 恢复测试区域数据
|
|
|
+ */
|
|
|
+static void restore_test_area(uint32_t addr, uint32_t len)
|
|
|
+{
|
|
|
+ if (len > sizeof(g_test_buffer)) {
|
|
|
+ len = sizeof(g_test_buffer);
|
|
|
+ }
|
|
|
+ printf(" Restoring data at 0x%06X...\n", addr);
|
|
|
+ flash_write_bytes(addr, g_test_buffer, len);
|
|
|
+ delay_ms(20);
|
|
|
+}
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 测试用例
|
|
|
+//============================================================================
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试0: 显示 Flash 信息和地址布局
|
|
|
+ */
|
|
|
+void test_flash_info(void)
|
|
|
+{
|
|
|
+ printf("\n=== Test 0: Flash Information ===\n");
|
|
|
+ printf("Chip: GD25Q16 (16Mbit SPI Flash)\n");
|
|
|
+ printf("Total Size: %d bytes (%d MB)\n", GD25Q16_TOTAL_SIZE, GD25Q16_TOTAL_SIZE / 1024 / 1024);
|
|
|
+ printf("Page Size: %d bytes\n", GD25Q16_PAGE_SIZE);
|
|
|
+ printf("Sector Size: %d bytes (%d KB)\n", GD25Q16_SECTOR_SIZE, GD25Q16_SECTOR_SIZE / 1024);
|
|
|
+ printf("Block Size: %d bytes (%d KB)\n", GD25Q16_BLOCK_SIZE, GD25Q16_BLOCK_SIZE / 1024);
|
|
|
+ printf("Total Pages: %d\n", GD25Q16_TOTAL_PAGES);
|
|
|
+ printf("Total Sectors: %d\n", GD25Q16_TOTAL_SECTORS);
|
|
|
+
|
|
|
+ printf("\n--- User Config Areas ---\n");
|
|
|
+ printf(" IAP_ADDR : 0x%06X\n", IAP_ADDR);
|
|
|
+ printf(" pidinf_addr : 0x%06X\n", pidinf_addr);
|
|
|
+ printf(" verinf_addr : 0x%06X\n", verinf_addr);
|
|
|
+ printf(" confinf_addr : 0x%06X\n", confinf_addr);
|
|
|
+ printf(" caminf_addr : 0x%06X\n", caminf_addr);
|
|
|
+ printf(" parinf_addr : 0x%06X\n", parinf_addr);
|
|
|
+ printf(" POS_TOTAL_ADDR : 0x%06X\n", POS_TOTAL_ADDR);
|
|
|
+ printf(" NO_FLY_ZONE_ADDR : 0x%06X\n", NO_FLY_ZONE_ADDR);
|
|
|
+ printf(" WAYPOINT_ADDR : 0x%06X\n", WAYPOINT_ADDR);
|
|
|
+
|
|
|
+ printf("\n--- Test Safe Area ---\n");
|
|
|
+ printf(" TEST_AREA_START : 0x%06X\n", TEST_AREA_START);
|
|
|
+ printf(" TEST_AREA_END : 0x%06X\n", TEST_AREA_END);
|
|
|
+ printf(" TEST_AREA_SIZE : %d bytes (%d KB)\n", TEST_AREA_SIZE, TEST_AREA_SIZE / 1024);
|
|
|
+
|
|
|
+ print_result("Flash info display", true);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试1: 页读写测试 (256字节)
|
|
|
+ */
|
|
|
+void test_page_rw(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START;
|
|
|
+ uint8_t write_buf[GD25Q16_PAGE_SIZE];
|
|
|
+ uint8_t read_buf[GD25Q16_PAGE_SIZE];
|
|
|
+
|
|
|
+ printf("\n=== Test 1: Page (256 bytes) Read/Write ===\n");
|
|
|
+
|
|
|
+ // 准备数据
|
|
|
+ for (int i = 0; i < GD25Q16_PAGE_SIZE; i++) {
|
|
|
+ write_buf[i] = i & 0xFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存原始数据
|
|
|
+ save_test_area(test_addr, GD25Q16_PAGE_SIZE);
|
|
|
+
|
|
|
+ // 写入
|
|
|
+ printf(" Writing page at 0x%06X...\n", test_addr);
|
|
|
+ flash_write_bytes(test_addr, write_buf, GD25Q16_PAGE_SIZE);
|
|
|
+ delay_ms(10);
|
|
|
+
|
|
|
+ // 读取
|
|
|
+ memset(read_buf, 0, sizeof(read_buf));
|
|
|
+ flash_read_bytes(test_addr, read_buf, GD25Q16_PAGE_SIZE);
|
|
|
+
|
|
|
+ // 验证
|
|
|
+ bool match = (memcmp(write_buf, read_buf, GD25Q16_PAGE_SIZE) == 0);
|
|
|
+ if (!match) {
|
|
|
+ printf(" Mismatch detected!\n");
|
|
|
+ for (int i = 0; i < 16; i++) {
|
|
|
+ if (write_buf[i] != read_buf[i]) {
|
|
|
+ printf(" Byte %d: 0x%02X vs 0x%02X\n", i, write_buf[i], read_buf[i]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, GD25Q16_PAGE_SIZE);
|
|
|
+
|
|
|
+ print_result("Page read/write", match);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试2: 多页读写测试 (4页 = 1KB)
|
|
|
+ */
|
|
|
+void test_multipage_rw(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + GD25Q16_PAGE_SIZE;
|
|
|
+ uint16_t page_count = 4;
|
|
|
+ uint32_t test_len = page_count * GD25Q16_PAGE_SIZE;
|
|
|
+ uint8_t* write_buf = g_test_buffer;
|
|
|
+ uint8_t read_buf[GD25Q16_PAGE_SIZE * 4];
|
|
|
+
|
|
|
+ printf("\n=== Test 2: Multi-Page (%d pages) Read/Write ===\n", page_count);
|
|
|
+
|
|
|
+ // 准备数据
|
|
|
+ for (int i = 0; i < test_len; i++) {
|
|
|
+ write_buf[i] = (i + 0x80) & 0xFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存原始数据
|
|
|
+ save_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ // 写入
|
|
|
+ printf(" Writing %d bytes at 0x%06X...\n", test_len, test_addr);
|
|
|
+ flash_write_bytes(test_addr, write_buf, test_len);
|
|
|
+ delay_ms(20);
|
|
|
+
|
|
|
+ // 读取
|
|
|
+ memset(read_buf, 0, sizeof(read_buf));
|
|
|
+ flash_read_bytes(test_addr, read_buf, test_len);
|
|
|
+
|
|
|
+ // 验证
|
|
|
+ bool match = (memcmp(write_buf, read_buf, test_len) == 0);
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ print_result("Multi-page read/write", match);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试3: 扇区擦除测试 (4KB)
|
|
|
+ */
|
|
|
+void test_sector_erase(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + GD25Q16_SECTOR_SIZE;
|
|
|
+ uint32_t sector_start = (test_addr / GD25Q16_SECTOR_SIZE) * GD25Q16_SECTOR_SIZE;
|
|
|
+ uint8_t* read_buf = g_test_buffer;
|
|
|
+
|
|
|
+ printf("\n=== Test 3: Sector (4KB) Erase Test ===\n");
|
|
|
+ printf(" Sector start: 0x%06X\n", sector_start);
|
|
|
+
|
|
|
+ // 先写入非0xFF数据
|
|
|
+ memset(g_test_buffer, 0xA5, GD25Q16_SECTOR_SIZE);
|
|
|
+ flash_write_bytes(sector_start, g_test_buffer, GD25Q16_SECTOR_SIZE);
|
|
|
+ delay_ms(20);
|
|
|
+
|
|
|
+ // 保存原始数据用于恢复
|
|
|
+ save_test_area(sector_start, GD25Q16_SECTOR_SIZE);
|
|
|
+
|
|
|
+ // 擦除扇区
|
|
|
+ printf(" Erasing sector...\n");
|
|
|
+ // 注意: 这里需要调用扇区擦除函数,如果您的驱动没有单独的函数,
|
|
|
+ // 可以通过写入0xFF来实现,或者调用底层擦除函数
|
|
|
+ // AT45DB_EraseSector(sector_start); // 如果有这个函数
|
|
|
+ // 暂时用写入0xFF模拟(实际应该用擦除命令)
|
|
|
+ memset(g_test_buffer, 0xFF, GD25Q16_SECTOR_SIZE);
|
|
|
+ flash_write_bytes(sector_start, g_test_buffer, GD25Q16_SECTOR_SIZE);
|
|
|
+ delay_ms(50);
|
|
|
+
|
|
|
+ // 读取验证
|
|
|
+ memset(read_buf, 0, GD25Q16_SECTOR_SIZE);
|
|
|
+ flash_read_bytes(sector_start, read_buf, GD25Q16_SECTOR_SIZE);
|
|
|
+
|
|
|
+ // 验证是否全为0xFF
|
|
|
+ bool all_ff = true;
|
|
|
+ for (int i = 0; i < GD25Q16_SECTOR_SIZE; i++) {
|
|
|
+ if (read_buf[i] != 0xFF) {
|
|
|
+ all_ff = false;
|
|
|
+ printf(" Non-0xFF at offset %d: 0x%02X\n", i, read_buf[i]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复原始数据
|
|
|
+ restore_test_area(sector_start, GD25Q16_SECTOR_SIZE);
|
|
|
+
|
|
|
+ print_result("Sector erase", all_ff);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试4: 边界地址测试
|
|
|
+ */
|
|
|
+void test_boundary(void)
|
|
|
+{
|
|
|
+ uint8_t write_buf[32];
|
|
|
+ uint8_t read_buf[32];
|
|
|
+ uint32_t boundary_addr = TEST_AREA_END - 16;
|
|
|
+
|
|
|
+ printf("\n=== Test 4: Boundary Address Test ===\n");
|
|
|
+ printf(" Boundary address: 0x%06X\n", boundary_addr);
|
|
|
+
|
|
|
+ if (!IS_TEST_ADDR(boundary_addr) || !IS_TEST_ADDR(boundary_addr + 16)) {
|
|
|
+ printf(" Skipping (address out of test area)\n");
|
|
|
+ print_result("Boundary test", true);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 准备数据
|
|
|
+ for (int i = 0; i < sizeof(write_buf); i++) {
|
|
|
+ write_buf[i] = 0x55 + i;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ save_test_area(boundary_addr, sizeof(write_buf));
|
|
|
+
|
|
|
+ // 写入
|
|
|
+ flash_write_bytes(boundary_addr, write_buf, sizeof(write_buf));
|
|
|
+ delay_ms(10);
|
|
|
+
|
|
|
+ // 读取
|
|
|
+ flash_read_bytes(boundary_addr, read_buf, sizeof(read_buf));
|
|
|
+
|
|
|
+ // 验证
|
|
|
+ bool match = (memcmp(write_buf, read_buf, sizeof(write_buf)) == 0);
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(boundary_addr, sizeof(write_buf));
|
|
|
+
|
|
|
+ print_result("Boundary test", match);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试5: 16位整数读写测试
|
|
|
+ */
|
|
|
+void test_int16_rw(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + 0x2000;
|
|
|
+ int16_t write_vals[] = {0, 1, -1, 32767, -32768, 0x1234, 0x5678, 0x9ABC, 0xDEF0};
|
|
|
+ int16_t read_vals[9];
|
|
|
+
|
|
|
+ printf("\n=== Test 5: Int16 Read/Write Test ===\n");
|
|
|
+
|
|
|
+ // 保存原始数据
|
|
|
+ save_test_area(test_addr, sizeof(write_vals));
|
|
|
+
|
|
|
+ bool all_match = true;
|
|
|
+ for (int i = 0; i < sizeof(write_vals)/sizeof(write_vals[0]); i++) {
|
|
|
+ uint32_t addr = test_addr + i * 2;
|
|
|
+ flash_write_int16(addr, write_vals[i]);
|
|
|
+ delay_ms(5);
|
|
|
+ read_vals[i] = flash_read_int16(addr);
|
|
|
+
|
|
|
+ if (read_vals[i] != write_vals[i]) {
|
|
|
+ printf(" Mismatch at 0x%06X: %d vs %d\n", addr, write_vals[i], read_vals[i]);
|
|
|
+ all_match = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (all_match) {
|
|
|
+ printf(" All %d values match\n", (int)(sizeof(write_vals)/sizeof(write_vals[0])));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, sizeof(write_vals));
|
|
|
+
|
|
|
+ print_result("Int16 read/write", all_match);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试6: 压力测试
|
|
|
+ */
|
|
|
+void test_stress(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + 0x3000;
|
|
|
+ uint32_t test_len = 256;
|
|
|
+ uint8_t* write_buf = g_test_buffer;
|
|
|
+ uint8_t read_buf[256];
|
|
|
+ const int cycles = 30;
|
|
|
+
|
|
|
+ printf("\n=== Test 6: Stress Test (%d cycles) ===\n", cycles);
|
|
|
+
|
|
|
+ // 保存原始数据
|
|
|
+ save_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ int failed = 0;
|
|
|
+ for (int cycle = 0; cycle < cycles; cycle++) {
|
|
|
+ // 准备数据
|
|
|
+ for (int i = 0; i < test_len; i++) {
|
|
|
+ if (cycle % 3 == 0) write_buf[i] = cycle & 0xFF;
|
|
|
+ else if (cycle % 3 == 1) write_buf[i] = 0x55;
|
|
|
+ else write_buf[i] = 0xAA;
|
|
|
+ }
|
|
|
+
|
|
|
+ flash_write_bytes(test_addr, write_buf, test_len);
|
|
|
+ delay_ms(5);
|
|
|
+
|
|
|
+ flash_read_bytes(test_addr, read_buf, test_len);
|
|
|
+
|
|
|
+ if (memcmp(write_buf, read_buf, test_len) != 0) {
|
|
|
+ failed++;
|
|
|
+ printf(" Cycle %d failed\n", cycle);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((cycle + 1) % 10 == 0) {
|
|
|
+ printf(" Progress: %d/%d\n", cycle + 1, cycles);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ printf(" Failed: %d/%d\n", failed, cycles);
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ print_result("Stress test", failed == 0);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试7: 随机模式测试
|
|
|
+ */
|
|
|
+void test_random_pattern(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + 0x4000;
|
|
|
+ uint32_t test_len = 512;
|
|
|
+ uint8_t* write_buf = g_test_buffer;
|
|
|
+ uint8_t read_buf[512];
|
|
|
+
|
|
|
+ printf("\n=== Test 7: Random Pattern Test ===\n");
|
|
|
+
|
|
|
+ // 生成随机数据
|
|
|
+ for (int i = 0; i < test_len; i++) {
|
|
|
+ write_buf[i] = (i * 0x9E3779B9) ^ (i >> 3);
|
|
|
+ write_buf[i] = (write_buf[i] ^ (write_buf[i] >> 4)) & 0xFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ save_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ // 写入
|
|
|
+ flash_write_bytes(test_addr, write_buf, test_len);
|
|
|
+ delay_ms(15);
|
|
|
+
|
|
|
+ // 读取
|
|
|
+ flash_read_bytes(test_addr, read_buf, test_len);
|
|
|
+
|
|
|
+ // 验证
|
|
|
+ bool match = (memcmp(write_buf, read_buf, test_len) == 0);
|
|
|
+ if (!match) {
|
|
|
+ for (int i = 0; i < 20; i++) {
|
|
|
+ if (write_buf[i] != read_buf[i]) {
|
|
|
+ printf(" First mismatch at %d: 0x%02X vs 0x%02X\n",
|
|
|
+ i, write_buf[i], read_buf[i]);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, test_len);
|
|
|
+
|
|
|
+ print_result("Random pattern", match);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 测试8: 数据完整性测试(写入后立即读取多次)
|
|
|
+ */
|
|
|
+void test_integrity(void)
|
|
|
+{
|
|
|
+ uint32_t test_addr = TEST_AREA_START + 0x5000;
|
|
|
+ uint16_t test_values[] = {0x1234, 0x5678, 0x9ABC, 0xDEF0, 0xABCD, 0xFFFF, 0x0000};
|
|
|
+
|
|
|
+ printf("\n=== Test 8: Data Integrity Test ===\n");
|
|
|
+
|
|
|
+ // 保存原始数据
|
|
|
+ save_test_area(test_addr, sizeof(test_values));
|
|
|
+
|
|
|
+ bool all_match = true;
|
|
|
+ for (int i = 0; i < sizeof(test_values)/sizeof(test_values[0]); i++) {
|
|
|
+ uint32_t addr = test_addr + i * 2;
|
|
|
+
|
|
|
+ // 写入
|
|
|
+ flash_write_int16(addr, test_values[i]);
|
|
|
+ delay_ms(5);
|
|
|
+
|
|
|
+ // 多次读取验证
|
|
|
+ for (int read_count = 0; read_count < 3; read_count++) {
|
|
|
+ int16_t read_val = flash_read_int16(addr);
|
|
|
+ if (read_val != test_values[i]) {
|
|
|
+ printf(" Value 0x%04X at 0x%06X: read %d/3 = 0x%04X\n",
|
|
|
+ test_values[i], addr, read_count + 1, read_val);
|
|
|
+ all_match = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (all_match) {
|
|
|
+ printf(" All values passed integrity check\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ restore_test_area(test_addr, sizeof(test_values));
|
|
|
+
|
|
|
+ print_result("Data integrity", all_match);
|
|
|
+}
|
|
|
+
|
|
|
+//============================================================================
|
|
|
+// 主测试函数
|
|
|
+//============================================================================
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 运行完整测试
|
|
|
+ */
|
|
|
+void run_flash_test(void)
|
|
|
+{
|
|
|
+ printf("\n");
|
|
|
+ printf("╔══════════════════════════════════════════════════════════════╗\n");
|
|
|
+ printf("║ GD25Q16 Flash Test Suite (Safe Area Mode) ║\n");
|
|
|
+ printf("╚══════════════════════════════════════════════════════════════╝\n");
|
|
|
+ printf("Chip: GD25Q16 (16Mbit = 2MB)\n");
|
|
|
+ printf("Test Area: 0x%06X - 0x%06X (%d KB)\n",
|
|
|
+ TEST_AREA_START, TEST_AREA_END, TEST_AREA_SIZE / 1024);
|
|
|
+
|
|
|
+ // 初始化
|
|
|
+ printf("\nInitializing Flash...\n");
|
|
|
+ flash_at45db_initial(); // 实际是 GD25Q16 驱动
|
|
|
+ delay_ms(100);
|
|
|
+
|
|
|
+ if (!flash_isexist()) {
|
|
|
+ printf("ERROR: Flash not detected!\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ printf("Flash detected, status: %s\n", flash_isbusy() ? "Busy" : "Ready");
|
|
|
+
|
|
|
+ // 重置计数
|
|
|
+ test_count = 0;
|
|
|
+ fail_count = 0;
|
|
|
+ test_passed = true;
|
|
|
+
|
|
|
+ // 运行测试
|
|
|
+ test_flash_info();
|
|
|
+ test_page_rw();
|
|
|
+ test_multipage_rw();
|
|
|
+ test_sector_erase();
|
|
|
+ test_boundary();
|
|
|
+ test_int16_rw();
|
|
|
+ test_random_pattern();
|
|
|
+ test_integrity();
|
|
|
+ test_stress();
|
|
|
+
|
|
|
+ // 结果
|
|
|
+ printf("\n");
|
|
|
+ printf("══════════════════════════════════════════════════════════════\n");
|
|
|
+ printf("Test Summary:\n");
|
|
|
+ printf(" Total: %d\n", test_count + fail_count);
|
|
|
+ printf(" Passed: %d\n", test_count);
|
|
|
+ printf(" Failed: %d\n", fail_count);
|
|
|
+ printf("══════════════════════════════════════════════════════════════\n");
|
|
|
+
|
|
|
+ if (test_passed) {
|
|
|
+ printf("\n✓ ALL TESTS PASSED!\n");
|
|
|
+ } else {
|
|
|
+ printf("\n✗ SOME TESTS FAILED!\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @brief 快速功能测试
|
|
|
+ */
|
|
|
+void run_flash_quick_test(void)
|
|
|
+{
|
|
|
+ uint8_t test_data[] = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
|
|
|
+ uint8_t read_data[8];
|
|
|
+ uint32_t test_addr = TEST_AREA_START;
|
|
|
+
|
|
|
+ printf("\n=== Quick Test ===\n");
|
|
|
+
|
|
|
+ flash_at45db_initial();
|
|
|
+ delay_ms(100);
|
|
|
+
|
|
|
+ if (!flash_isexist()) {
|
|
|
+ printf("Flash not detected!\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存
|
|
|
+ uint8_t original[8];
|
|
|
+ flash_read_bytes(test_addr, original, sizeof(original));
|
|
|
+
|
|
|
+ // 测试
|
|
|
+ flash_write_bytes(test_addr, test_data, sizeof(test_data));
|
|
|
+ delay_ms(10);
|
|
|
+ flash_read_bytes(test_addr, read_data, sizeof(read_data));
|
|
|
+
|
|
|
+ if (memcmp(test_data, read_data, sizeof(test_data)) == 0) {
|
|
|
+ printf("TEST PASSED\n");
|
|
|
+ printf("Data: ");
|
|
|
+ for (int i = 0; i < sizeof(test_data); i++) {
|
|
|
+ printf("%02X ", read_data[i]);
|
|
|
+ }
|
|
|
+ printf("\n");
|
|
|
+ } else {
|
|
|
+ printf("TEST FAILED\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 恢复
|
|
|
+ flash_write_bytes(test_addr, original, sizeof(original));
|
|
|
+}
|
|
|
+#endif
|