#include "board.h" #include "hard_flash_gd25q16.h" #include "hpm_spi_drv.h" #include "hpm_clock_drv.h" #include "hpm_gpio_drv.h" #include "hpm_gpio_drv.h" #include "hpm_gpiom_drv.h" #include "test.h" #ifdef GD25Q16_FLASH /* 使用 SPI2 作为示例,你可以根据需要修改 */ #define AT45DB_SPI_BASE HPM_SPI2 /******************SPI时钟频率*******************/ #define AT45DB_CLK_FRE (42000000UL) /* GPIO 参数定义 - 根据实际硬件修改 */ #define AT45DB_CS_GPIO_PTR HPM_GPIO0 /* GPIO 控制器基地址 */ #define AT45DB_CS_PORT GPIO_DO_GPIOB /* GPIOB = 1 */ #define AT45DB_CS_PIN 24 /* PIN24 */ /* CS 控制宏 - 完全保留原名 */ #define AT45db161_SPI_SELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 0) #define AT45db161_SPI_DESELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 1) void gd25q16_cs_high(void) { AT45db161_SPI_DESELECT(); } void gd25q16_cs_low(void) { AT45db161_SPI_SELECT(); } /** * @brief SPI 读写一个字节 */ uint8_t SPI2_ReadWrite_Byte(uint8_t byte) { uint8_t rx_byte = 0; spi_control_config_t control_config; /* 配置传输控制 */ spi_master_get_default_control_config(&control_config); control_config.common_config.trans_mode = spi_trans_write_read_together; control_config.master_config.cmd_enable = false; control_config.master_config.addr_enable = false; /* 执行传输 */ spi_transfer(AT45DB_SPI_BASE, &control_config, NULL, NULL, &byte, 1, &rx_byte, 1); return rx_byte; } /** * @brief 写使能 */ static void GD25Q16_WriteEnable(void) { AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16_WRITE_ENABLE); AT45db161_SPI_DESELECT(); } /** * @brief 扇区擦除 */ static void GD25Q16_Erase_Sector(uint32_t addr) { while(AT45DB_IS_BUSY() == 0); GD25Q16_WriteEnable(); while(AT45DB_IS_BUSY() == 0); AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16SECTOR_ERASE); SPI2_ReadWrite_Byte((uint8_t)(addr >> 16)); SPI2_ReadWrite_Byte((uint8_t)(addr >> 8)); SPI2_ReadWrite_Byte((uint8_t)(addr)); AT45db161_SPI_DESELECT(); while(AT45DB_IS_BUSY() == 0); } static void spi2_clk_config(void) { /* SPI2 clock configure */ clock_add_to_group(clock_spi2, 0); clock_set_source_divider(clock_spi2, clk_src_pll1_clk1, 5U); /* 80MHz */ printf("spi2 clock is %d\r\n", clock_get_frequency(clock_spi2)); } static void spi2_gpio_config(void) { HPM_IOC->PAD[IOC_PAD_PB25].FUNC_CTL = IOC_PB25_FUNC_CTL_SPI2_MISO; HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_SPI2_MOSI; HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; // HPM_IOC->PAD[IOC_PAD_PB24].FUNC_CTL = IOC_PB24_FUNC_CTL_SPI2_CSN; // 软件控制CS gpiom_set_pin_controller(HPM_GPIOM, GPIOM_ASSIGN_GPIOB, 24, gpiom_soc_gpio0); gpio_set_pin_output(HPM_GPIO0, GPIO_OE_GPIOB, 24); gpio_write_pin(HPM_GPIO0, GPIO_DO_GPIOB, 24, 1); } /** * @brief 初始化 SPI 接口 */ void AT45db161_SPI_Configuration(void) { spi_timing_config_t timing_config = {0}; spi_format_config_t format_config = {0}; /* 初始化 SPI2 时钟和引脚 软件片选 IO对应硬件CS 可换成硬件*/ spi2_clk_config(); spi2_gpio_config(); /*软件CS CS 默认高电平 */ /* 配置 SPI 时序(主模式)*/ spi_master_get_default_timing_config(&timing_config); timing_config.master_config.clk_src_freq_in_hz = clock_get_frequency(clock_spi2); timing_config.master_config.sclk_freq_in_hz = AT45DB_CLK_FRE; // 20000000UL 20M 后续调整到42M if (status_success != spi_master_timing_init(HPM_SPI2, &timing_config)) { printf("SPI master timming init failed\n"); } printf("SPI-Master transfer timing is configured.\n"); printf("SPI-Master transfer source clock frequency: %dHz\n", timing_config.master_config.clk_src_freq_in_hz); printf("SPI-Master transfer sclk frequency: %dHz\n", timing_config.master_config.sclk_freq_in_hz); /* 配置 SPI 格式 */ spi_master_get_default_format_config(&format_config); format_config.common_config.data_len_in_bits = 8; /* 8位数据 */ format_config.common_config.mode = spi_master_mode; /* 主机模式 */ format_config.common_config.cpol = spi_sclk_low_idle; /* CPOL=0 */ format_config.common_config.cpha = spi_sclk_sampling_odd_clk_edges; /* CPHA=0 */ spi_format_init(AT45DB_SPI_BASE, &format_config); printf("SPI-Master transfer format is configured.\n"); } /** * @brief 初始化 flash 接口 */ void flash_at45db_init(void) { AT45db161_SPI_Configuration(); } /** * @brief 查询是否准备好 */ uint8_t AT45DB_IS_BUSY(void) { uint8_t Status_Register; AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16_READ_STATE_REGISTER); Status_Register = SPI2_ReadWrite_Byte(0x00); AT45db161_SPI_DESELECT(); /* GD25Q16: bit0=0 表示空闲,bit0=1 表示忙 */ /* 原代码返回1表示准备好,所以需要取反 */ if ((Status_Register & 0x01) != 0x01) return 1; /* 准备好 */ return 0; /* 忙 */ } /** * @brief 检查芯片是否存在 */ uint8_t AT45DB_Check(void) { uint8_t buf[3]; //printf("AT45DB_Check: 开始读取JEDEC ID\n"); // 检查CS引脚控制 //printf(" CS引脚状态(读取前): %d\n", // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN)); AT45db161_SPI_SELECT(); //printf(" CS引脚状态(选中后): %d\n", // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN)); // 发送读ID命令 SPI2_ReadWrite_Byte(0x9F); // 读取ID buf[0] = SPI2_ReadWrite_Byte(0); buf[1] = SPI2_ReadWrite_Byte(0); buf[2] = SPI2_ReadWrite_Byte(0); AT45db161_SPI_DESELECT(); // printf(" CS引脚状态(取消选中后): %d\n", // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN)); // printf(" 读取到的JEDEC ID: 0x%02X 0x%02X 0x%02X\n", buf[0], buf[1], buf[2]); /* 厂商ID是 第一个字节 第二个字节是存储类型SPI FLASH 第三个字节是容量*/ /* GD25Q16 的 ID 是 0xC8, 0x40, 0x15 */ /* W25Q64 的ID 是 0xEF 0x40 0x17 */ if ((buf[0] == 0xC8) && (buf[1] == 0x40) && (buf[2] == 0x15)) { printf(" ID匹配成功!\n"); return 1; } //if ((buf[0] == 0xEF) && (buf[1] == 0x40) && (buf[2] == 0x15)) { // printf(" ID匹配成功!\n"); // return 1; //} // if ((buf[0] == 0xEF) && (buf[1] == 0x40) && (buf[2] == 0x17)) { // printf(" ID匹配成功!\n"); // return 1; //} printf(" ID不匹配!期望: 0xC8 0x40 0x15\n"); return 0; } /** * @brief 读一页数据 */ void AT45DB_ReadPage(uint16_t Page_Add, uint8_t *pdata) { int i; if (Page_Add > 8192) return; while (AT45DB_IS_BUSY() == 0); uint32_t addr = Page_Add * 256; AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16_MM_PAGE_READ); SPI2_ReadWrite_Byte((int8_t)(addr >> 16)); SPI2_ReadWrite_Byte((int8_t)(addr >> 8)); SPI2_ReadWrite_Byte((int8_t)(addr)); for (i = 0; i < 256; i++) { *pdata++ = SPI2_ReadWrite_Byte(0x00); } AT45db161_SPI_DESELECT(); } /** * @brief 写一页数据 */ void AT45DB_WritePage(uint16_t page, uint8_t *Data) { uint16_t i; uint32_t addr = page * 256; if (page >= 8192) return; while (AT45DB_IS_BUSY() == 0); GD25Q16_WriteEnable(); while (AT45DB_IS_BUSY() == 0); AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16_WRITE); SPI2_ReadWrite_Byte((uint8_t)(addr >> 16)); SPI2_ReadWrite_Byte((uint8_t)(addr >> 8)); SPI2_ReadWrite_Byte((uint8_t)(addr)); for (i = 0; i < 256; i++) { SPI2_ReadWrite_Byte(Data[i]); } AT45db161_SPI_DESELECT(); while (AT45DB_IS_BUSY() == 0); } /** * @brief 在一页内写入部分数据 */ void AT45DB_WriteBytes_OnOnePage(uint16_t page, uint8_t *Data, uint16_t len) { uint16_t i; if (page > 4095 || len > 256) return; while (AT45DB_IS_BUSY() == 0); AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(AT45DB_BUFFER_2_WRITE); SPI2_ReadWrite_Byte(0x00); SPI2_ReadWrite_Byte(0x00); SPI2_ReadWrite_Byte(0x00); for (i = 0; i < len; i++) { SPI2_ReadWrite_Byte(Data[i]); } AT45db161_SPI_DESELECT(); while (AT45DB_IS_BUSY() == 0); if (page < 4096) { AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(GD25Q16_MM_PAGE_PROG_WITH_ERASE); SPI2_ReadWrite_Byte((uint8_t)(page >> 6)); SPI2_ReadWrite_Byte((uint8_t)(page << 2)); SPI2_ReadWrite_Byte(0x00); AT45db161_SPI_DESELECT(); } } /** * @brief 从任意地址读取多个字节 */ void AT45DB_Read_Bytes(uint32_t add, uint8_t *pdata, uint16_t len) { int i, j, k; uint8_t temp[256]; uint16_t page, offset; if (add > 8192 * 256) return; page = add / 256; offset = add % 256; AT45DB_ReadPage(page++, temp); for (i = offset; (len != 0) && (i < 256); len--, i++) { *pdata++ = temp[i]; } if ((i == 256) && (len != 0)) { if (len > 256) { for (k = 0; k < len / 256; k++) { AT45DB_ReadPage(page++, temp); for (j = 0; j < 256; j++) { *pdata++ = temp[j]; } } len -= 256 * k; } if (len != 0) { AT45DB_ReadPage(page, temp); for (j = 0; j < len; j++) { *pdata++ = temp[j]; } } } } /** * @brief 从任意地址写入多个字节 */ void AT45DB_Write_Bytes(uint32_t add, uint8_t *pdata, uint16_t len) { uint8_t temp[256]; uint16_t page, offset; uint16_t i, j, k; if (add > 8192 * 256) return; page = add / 256; offset = add % 256; AT45DB_ReadPage(page, temp); for (i = offset; (len != 0) && (i < 256); len--, i++) { temp[i] = *pdata++; } GD25Q16_Erase_Sector(add); AT45DB_WritePage(page++, temp); if ((i == 256) && (len != 0)) { if (len > 256) { for (k = 0; k < len / 256; k++) { for (j = 0; j < 256; j++) { temp[j] = *pdata++; } AT45DB_WritePage(page++, temp); } len -= 256 * k; } if (len != 0) { AT45DB_ReadPage(page, temp); for (j = 0; j < len; j++) { temp[j] = *pdata++; } AT45DB_WritePage(page, temp); } } } /** * @brief 写入浮点数 */ void AT45DB_Write_float(uint32_t add, float wvalue) { f_bytes data; data.value = wvalue; AT45DB_Write_Bytes(add, &data.byte[0], 4); } /** * @brief 读取浮点数 */ float AT45DB_Read_float(uint32_t add) { f_bytes data; data.value = 0; AT45DB_Read_Bytes(add, &data.byte[0], 4); return data.value; } /** * @brief 写入16位整数 */ void AT45DB_Write_int16(uint32_t add, int16_t wvalue) { i_bytes data; data.value = wvalue; AT45DB_Write_Bytes(add, &data.byte[0], 2); } /** * @brief 读取16位整数 */ int16_t AT45DB_Read_int16(uint32_t add) { i_bytes data; data.value = 0; AT45DB_Read_Bytes(add, &data.byte[0], 2); return data.value; } #endif /* GD25Q16_FLASH */ /* 20260322 spi flash test pass 测试了W25Q64与Q16; note:ai 写测试例程太全面了*/ #ifdef GD25Q16_TEST /** * @file test_gd25q16.c * @brief GD25Q16 SPI Flash 驱动测试程序 * * 测试内容: * 1. 芯片 ID 读取和存在性检查 * 2. 状态寄存器读取 * 3. 页写入和页读取 * 4. 任意地址写入和读取(跨页) * 5. 浮点数和整数读写 * 6. 擦除功能验证 */ /* 测试缓冲区大小 */ #define TEST_BUFFER_SIZE 512 #define TEST_PAGE_NUM 100 /* 测试用的页号,范围 0-8191 */ #define TEST_SECTOR_ADDR (TEST_PAGE_NUM * 256) /* 测试用的扇区起始地址 */ /* 测试用的数据模式 */ static const uint8_t test_pattern[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; /** * @brief 打印内存数据(十六进制格式) */ static void print_hex_data(const uint8_t *data, uint16_t len, const char *title) { uint16_t i; printf("\n========== %s ==========\n", title); for (i = 0; i < len; i++) { printf("%02X ", data[i]); if ((i + 1) % 16 == 0) { printf("\n"); } } if (len % 16 != 0) { printf("\n"); } printf("========== 结束 ==========\n\n"); } /** * @brief 比较两个内存块是否相等 */ static uint8_t compare_memory(const uint8_t *expected, const uint8_t *actual, uint16_t len) { uint16_t i; uint8_t match = 1; for (i = 0; i < len; i++) { if (expected[i] != actual[i]) { printf(" 数据不匹配 @ 偏移 %d: 期望 0x%02X, 实际 0x%02X\n", i, expected[i], actual[i]); match = 0; } } return match; } /** * @brief 测试 1:芯片检测和 ID 读取 */ static uint8_t test_chip_detection(void) { uint8_t result; printf("\n========================================\n"); printf("测试 1:芯片检测\n"); printf("========================================\n"); result = AT45DB_Check(); if (result) { printf("✅ 芯片检测成功!GD25Q16 存在\n"); /* 手动读取 JEDEC ID 用于显示 */ uint8_t buf[3]; AT45db161_SPI_SELECT(); SPI2_ReadWrite_Byte(0x9F); buf[0] = SPI2_ReadWrite_Byte(0); buf[1] = SPI2_ReadWrite_Byte(0); buf[2] = SPI2_ReadWrite_Byte(0); AT45db161_SPI_DESELECT(); printf(" JEDEC ID: 0x%02X 0x%02X 0x%02X\n", buf[0], buf[1], buf[2]); printf(" 制造商: 0x%02X (GigaDevice)\n", buf[0]); printf(" 型号: 0x%02X%02X (GD25Q16)\n", buf[1], buf[2]); printf(" 容量: 16Mbit (2MByte)\n"); return 1; } else { printf("❌ 芯片检测失败!请检查硬件连接\n"); return 0; } } /** * @brief 测试 2:页写入和页读取 */ static uint8_t test_page_write_read(void) { uint8_t write_buf[256]; uint8_t read_buf[256]; uint16_t i; printf("\n========================================\n"); printf("测试 2:页写入和页读取\n"); printf("========================================\n"); printf("测试页号: %d (地址: 0x%06X)\n", TEST_PAGE_NUM, TEST_PAGE_NUM * 256); /* 准备测试数据 */ for (i = 0; i < 256; i++) { write_buf[i] = (uint8_t)(i + TEST_PAGE_NUM); } print_hex_data(write_buf, 32, "写入数据(前32字节)"); /* 写入一页 */ printf("正在写入数据...\n"); AT45DB_WritePage(TEST_PAGE_NUM, write_buf); printf("✅ 页写入完成\n"); /* 读取一页 */ printf("正在读取数据...\n"); AT45DB_ReadPage(TEST_PAGE_NUM, read_buf); printf("✅ 页读取完成\n"); print_hex_data(read_buf, 32, "读取数据(前32字节)"); /* 验证数据 */ if (compare_memory(write_buf, read_buf, 256)) { printf("✅ 页写入/读取测试通过!\n"); return 1; } else { printf("❌ 页写入/读取测试失败!\n"); return 0; } } /** * @brief 测试 3:任意地址写入和读取(跨页) */ static uint8_t test_random_address_write_read(void) { uint8_t write_buf[TEST_BUFFER_SIZE]; uint8_t read_buf[TEST_BUFFER_SIZE]; uint16_t i; uint32_t start_addr = TEST_SECTOR_ADDR + 100; /* 从页内偏移 100 开始 */ printf("\n========================================\n"); printf("测试 3:任意地址写入和读取(跨页测试)\n"); printf("========================================\n"); printf("起始地址: 0x%06X (页 %d, 偏移 %d)\n", start_addr, start_addr / 256, start_addr % 256); printf("数据长度: %d 字节 (跨页: %d 页)\n", TEST_BUFFER_SIZE, (start_addr + TEST_BUFFER_SIZE - 1) / 256 - start_addr / 256 + 1); /* 准备测试数据 */ for (i = 0; i < TEST_BUFFER_SIZE; i++) { write_buf[i] = (uint8_t)(i % 256); } print_hex_data(write_buf, 32, "写入数据(前32字节)"); /* 写入数据 */ printf("正在写入数据...\n"); AT45DB_Write_Bytes(start_addr, write_buf, TEST_BUFFER_SIZE); printf(" 数据写入完成\n"); /* 读取数据 */ printf("正在读取数据...\n"); AT45DB_Read_Bytes(start_addr, read_buf, TEST_BUFFER_SIZE); printf(" 数据读取完成\n"); print_hex_data(read_buf, 32, "读取数据(前32字节)"); /* 验证数据 */ if (compare_memory(write_buf, read_buf, TEST_BUFFER_SIZE)) { printf(" 任意地址写入/读取测试通过!\n"); return 1; } else { printf(" 任意地址写入/读取测试失败!\n"); return 0; } } /** * @brief 测试 4:浮点数读写 */ static uint8_t test_float_read_write(void) { uint32_t addr = TEST_SECTOR_ADDR + 400; float test_values[] = {3.14159f, 2.71828f, -123.456f, 0.0f, 999.999f}; float read_value; uint8_t i; uint8_t all_pass = 1; printf("\n========================================\n"); printf("测试 4:浮点数读写\n"); printf("========================================\n"); printf("测试地址: 0x%06X\n", addr); for (i = 0; i < sizeof(test_values) / sizeof(test_values[0]); i++) { printf("\n[测试 %d] 写入值: %f\n", i + 1, test_values[i]); AT45DB_Write_float(addr + i * 4, test_values[i]); read_value = AT45DB_Read_float(addr + i * 4); printf(" 读取值: %f\n", read_value); /* 浮点数比较,使用误差范围 */ if ((test_values[i] - read_value) < 0.0001f && (read_value - test_values[i]) < 0.0001f) { printf(" 验证通过\n"); } else { printf(" 验证失败\n"); all_pass = 0; } } if (all_pass) { printf("\n 浮点数读写测试通过!\n"); return 1; } else { printf("\n 浮点数读写测试失败!\n"); return 0; } } /** * @brief 测试 5:16位整数读写 */ static uint8_t test_int16_read_write(void) { uint32_t addr = TEST_SECTOR_ADDR + 500; int16_t test_values[] = {12345, -5678, 0, 32767, -32768}; int16_t read_value; uint8_t i; uint8_t all_pass = 1; printf("\n========================================\n"); printf("测试 5:16位整数读写\n"); printf("========================================\n"); printf("测试地址: 0x%06X\n", addr); for (i = 0; i < sizeof(test_values) / sizeof(test_values[0]); i++) { printf("\n[测试 %d] 写入值: %d\n", i + 1, test_values[i]); AT45DB_Write_int16(addr + i * 2, test_values[i]); read_value = AT45DB_Read_int16(addr + i * 2); printf(" 读取值: %d\n", read_value); if (test_values[i] == read_value) { printf(" 验证通过\n"); } else { printf(" 验证失败\n"); all_pass = 0; } } if (all_pass) { printf("\n 16位整数读写测试通过!\n"); return 1; } else { printf("\n 16位整数读写测试失败!\n"); return 0; } } /** * @brief 测试 6:擦除功能验证 */ static uint8_t test_erase_verify(void) { uint8_t read_buf[256]; uint16_t i; uint8_t all_erased = 1; uint32_t test_addr = TEST_SECTOR_ADDR; printf("\n========================================\n"); printf("测试 6:擦除功能验证\n"); printf("========================================\n"); printf("擦除扇区地址: 0x%06X (页 %d)\n", test_addr, test_addr / 256); /* 先写入已知数据 */ printf("步骤 1: 写入测试数据...\n"); for (i = 0; i < 256; i++) { read_buf[i] = (uint8_t)(0xAA); } AT45DB_WritePage(TEST_PAGE_NUM, read_buf); /* 验证写入成功 */ AT45DB_ReadPage(TEST_PAGE_NUM, read_buf); for (i = 0; i < 256; i++) { if (read_buf[i] != 0xAA) { printf(" 数据写入验证失败\n"); return 0; } } printf("测试数据写入成功\n"); /* 执行扇区擦除 */ printf("步骤 2: 执行扇区擦除...\n"); GD25Q16_Erase_Sector(test_addr); printf("扇区擦除完成\n"); /* 验证擦除结果(擦除后应该是 0xFF) */ printf("步骤 3: 验证擦除结果...\n"); AT45DB_ReadPage(TEST_PAGE_NUM, read_buf); for (i = 0; i < 256; i++) { if (read_buf[i] != 0xFF) { printf(" 地址 0x%06X: 期望 0xFF, 实际 0x%02X\n", test_addr + i, read_buf[i]); all_erased = 0; } } if (all_erased) { printf(" 所有字节验证为 0xFF\n"); printf(" 擦除功能测试通过!\n"); return 1; } else { printf(" 擦除功能测试失败!\n"); return 0; } } /** * @brief 主测试函数 */ void test_gd25q16(void) { uint8_t test_result[6]; uint8_t all_pass = 1; uint32_t start_time, end_time; printf("\n"); printf("╔══════════════════════════════════════════════════════════╗\n"); printf("║ GD25Q16 SPI Flash 驱动测试程序 ║\n"); printf("╚══════════════════════════════════════════════════════════╝\n"); /* 初始化 Flash */ printf("\n正在初始化 SPI Flash...\n"); flash_at45db_init(); printf(" SPI Flash 初始化完成\n"); /* 运行所有测试 */ test_result[0] = test_chip_detection(); if (!test_result[0]) { printf("\n 芯片检测失败,终止后续测试!\n"); return; } test_result[1] = test_page_write_read(); test_result[2] = test_random_address_write_read(); test_result[3] = test_float_read_write(); test_result[4] = test_int16_read_write(); test_result[5] = test_erase_verify(); /* 打印测试总结 */ printf("\n"); printf("╔══════════════════════════════════════════════════════════╗\n"); printf("║ 测试总结 ║\n"); printf("╠══════════════════════════════════════════════════════════╣\n"); const char *test_names[] = { "芯片检测", "页写入/读取", "任意地址写入/读取", "浮点数读写", "16位整数读写", "擦除功能验证" }; for (int i = 0; i < 6; i++) { printf("║ 测试 %d: %-20s : %s\n", i + 1, test_names[i], test_result[i] ? " 通过" : " 失败"); if (!test_result[i]) all_pass = 0; } printf("╠══════════════════════════════════════════════════════════╣\n"); if (all_pass) { printf("║ 最终结果: 所有测试通过!驱动工作正常 🎉 ║\n"); } else { printf("║ 最终结果: 部分测试失败,请检查硬件或驱动 ⚠️ ║\n"); } printf("╚══════════════════════════════════════════════════════════╝\n"); } /** * @brief 简化的快速测试(仅测试基本功能) */ void test_gd25q16_quick(void) { printf("\n=== GD25Q16 快速测试 ===\n"); flash_at45db_init(); /* 测试芯片存在 */ if (AT45DB_Check()) { printf(" 芯片检测通过\n"); } else { printf(" 芯片检测失败\n"); return; } /* 简单读写测试 */ uint8_t write_buf[32]; uint8_t read_buf[32]; for (int i = 0; i < 32; i++) { write_buf[i] = i; } AT45DB_Write_Bytes(0, write_buf, 32); AT45DB_Read_Bytes(0, read_buf, 32); if (memcmp(write_buf, read_buf, 32) == 0) { printf(" 读写测试通过\n"); } else { printf(" 读写测试失败\n"); } printf("=== 快速测试结束 ===\n"); test_gd25q16(); } #endif