hard_flash_gd25q16.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869
  1. #include "board.h"
  2. #include "hard_flash_gd25q16.h"
  3. #include "hpm_spi_drv.h"
  4. #include "hpm_clock_drv.h"
  5. #include "hpm_gpio_drv.h"
  6. #include "hpm_gpio_drv.h"
  7. #include "hpm_gpiom_drv.h"
  8. #include "test.h"
  9. #ifdef GD25Q16_FLASH
  10. /* 使用 SPI2 作为示例,你可以根据需要修改 */
  11. #define AT45DB_SPI_BASE HPM_SPI2
  12. /******************SPI时钟频率*******************/
  13. #define AT45DB_CLK_FRE (42000000UL)
  14. /* GPIO 参数定义 - 根据实际硬件修改 */
  15. #define AT45DB_CS_GPIO_PTR HPM_GPIO0 /* GPIO 控制器基地址 */
  16. #define AT45DB_CS_PORT GPIO_DO_GPIOB /* GPIOB = 1 */
  17. #define AT45DB_CS_PIN 24 /* PIN24 */
  18. /* CS 控制宏 - 完全保留原名 */
  19. #define AT45db161_SPI_SELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 0)
  20. #define AT45db161_SPI_DESELECT() gpio_write_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN, 1)
  21. void gd25q16_cs_high(void)
  22. {
  23. AT45db161_SPI_DESELECT();
  24. }
  25. void gd25q16_cs_low(void)
  26. {
  27. AT45db161_SPI_SELECT();
  28. }
  29. /**
  30. * @brief SPI 读写一个字节
  31. */
  32. uint8_t SPI2_ReadWrite_Byte(uint8_t byte)
  33. {
  34. uint8_t rx_byte = 0;
  35. spi_control_config_t control_config;
  36. /* 配置传输控制 */
  37. spi_master_get_default_control_config(&control_config);
  38. control_config.common_config.trans_mode = spi_trans_write_read_together;
  39. control_config.master_config.cmd_enable = false;
  40. control_config.master_config.addr_enable = false;
  41. /* 执行传输 */
  42. spi_transfer(AT45DB_SPI_BASE,
  43. &control_config,
  44. NULL, NULL,
  45. &byte, 1,
  46. &rx_byte, 1);
  47. return rx_byte;
  48. }
  49. /**
  50. * @brief 写使能
  51. */
  52. static void GD25Q16_WriteEnable(void)
  53. {
  54. AT45db161_SPI_SELECT();
  55. SPI2_ReadWrite_Byte(GD25Q16_WRITE_ENABLE);
  56. AT45db161_SPI_DESELECT();
  57. }
  58. /**
  59. * @brief 扇区擦除
  60. */
  61. static void GD25Q16_Erase_Sector(uint32_t addr)
  62. {
  63. while(AT45DB_IS_BUSY() == 0);
  64. GD25Q16_WriteEnable();
  65. while(AT45DB_IS_BUSY() == 0);
  66. AT45db161_SPI_SELECT();
  67. SPI2_ReadWrite_Byte(GD25Q16SECTOR_ERASE);
  68. SPI2_ReadWrite_Byte((uint8_t)(addr >> 16));
  69. SPI2_ReadWrite_Byte((uint8_t)(addr >> 8));
  70. SPI2_ReadWrite_Byte((uint8_t)(addr));
  71. AT45db161_SPI_DESELECT();
  72. while(AT45DB_IS_BUSY() == 0);
  73. }
  74. static void spi2_clk_config(void)
  75. {
  76. /* SPI2 clock configure */
  77. clock_add_to_group(clock_spi2, 0);
  78. clock_set_source_divider(clock_spi2, clk_src_pll1_clk1, 5U); /* 80MHz */
  79. printf("spi2 clock is %d\r\n", clock_get_frequency(clock_spi2));
  80. }
  81. static void spi2_gpio_config(void)
  82. {
  83. HPM_IOC->PAD[IOC_PAD_PB25].FUNC_CTL = IOC_PB25_FUNC_CTL_SPI2_MISO;
  84. HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_SPI2_MOSI;
  85. HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_SPI2_SCLK | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK;
  86. // HPM_IOC->PAD[IOC_PAD_PB24].FUNC_CTL = IOC_PB24_FUNC_CTL_SPI2_CSN;
  87. // 软件控制CS
  88. gpiom_set_pin_controller(HPM_GPIOM, GPIOM_ASSIGN_GPIOB, 24, gpiom_soc_gpio0);
  89. gpio_set_pin_output(HPM_GPIO0, GPIO_OE_GPIOB, 24);
  90. gpio_write_pin(HPM_GPIO0, GPIO_DO_GPIOB, 24, 1);
  91. }
  92. /**
  93. * @brief 初始化 SPI 接口
  94. */
  95. void AT45db161_SPI_Configuration(void)
  96. {
  97. spi_timing_config_t timing_config = {0};
  98. spi_format_config_t format_config = {0};
  99. /* 初始化 SPI2 时钟和引脚 软件片选 IO对应硬件CS 可换成硬件*/
  100. spi2_clk_config();
  101. spi2_gpio_config(); /*软件CS CS 默认高电平 */
  102. /* 配置 SPI 时序(主模式)*/
  103. spi_master_get_default_timing_config(&timing_config);
  104. timing_config.master_config.clk_src_freq_in_hz = clock_get_frequency(clock_spi2);
  105. timing_config.master_config.sclk_freq_in_hz = AT45DB_CLK_FRE; // 20000000UL 20M 后续调整到42M
  106. if (status_success != spi_master_timing_init(HPM_SPI2, &timing_config)) {
  107. printf("SPI master timming init failed\n");
  108. }
  109. printf("SPI-Master transfer timing is configured.\n");
  110. printf("SPI-Master transfer source clock frequency: %dHz\n", timing_config.master_config.clk_src_freq_in_hz);
  111. printf("SPI-Master transfer sclk frequency: %dHz\n", timing_config.master_config.sclk_freq_in_hz);
  112. /* 配置 SPI 格式 */
  113. spi_master_get_default_format_config(&format_config);
  114. format_config.common_config.data_len_in_bits = 8; /* 8位数据 */
  115. format_config.common_config.mode = spi_master_mode; /* 主机模式 */
  116. format_config.common_config.cpol = spi_sclk_low_idle; /* CPOL=0 */
  117. format_config.common_config.cpha = spi_sclk_sampling_odd_clk_edges; /* CPHA=0 */
  118. spi_format_init(AT45DB_SPI_BASE, &format_config);
  119. printf("SPI-Master transfer format is configured.\n");
  120. }
  121. /**
  122. * @brief 初始化 flash 接口
  123. */
  124. void flash_at45db_init(void)
  125. {
  126. AT45db161_SPI_Configuration();
  127. }
  128. /**
  129. * @brief 查询是否准备好
  130. */
  131. uint8_t AT45DB_IS_BUSY(void)
  132. {
  133. uint8_t Status_Register;
  134. AT45db161_SPI_SELECT();
  135. SPI2_ReadWrite_Byte(GD25Q16_READ_STATE_REGISTER);
  136. Status_Register = SPI2_ReadWrite_Byte(0x00);
  137. AT45db161_SPI_DESELECT();
  138. /* GD25Q16: bit0=0 表示空闲,bit0=1 表示忙 */
  139. /* 原代码返回1表示准备好,所以需要取反 */
  140. if ((Status_Register & 0x01) != 0x01)
  141. return 1; /* 准备好 */
  142. return 0; /* 忙 */
  143. }
  144. /**
  145. * @brief 检查芯片是否存在
  146. */
  147. uint8_t AT45DB_Check(void)
  148. {
  149. uint8_t buf[3];
  150. //printf("AT45DB_Check: 开始读取JEDEC ID\n");
  151. // 检查CS引脚控制
  152. //printf(" CS引脚状态(读取前): %d\n",
  153. // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN));
  154. AT45db161_SPI_SELECT();
  155. //printf(" CS引脚状态(选中后): %d\n",
  156. // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN));
  157. // 发送读ID命令
  158. SPI2_ReadWrite_Byte(0x9F);
  159. // 读取ID
  160. buf[0] = SPI2_ReadWrite_Byte(0);
  161. buf[1] = SPI2_ReadWrite_Byte(0);
  162. buf[2] = SPI2_ReadWrite_Byte(0);
  163. AT45db161_SPI_DESELECT();
  164. // printf(" CS引脚状态(取消选中后): %d\n",
  165. // gpio_read_pin(AT45DB_CS_GPIO_PTR, AT45DB_CS_PORT, AT45DB_CS_PIN));
  166. // printf(" 读取到的JEDEC ID: 0x%02X 0x%02X 0x%02X\n", buf[0], buf[1], buf[2]);
  167. /* 厂商ID是 第一个字节 第二个字节是存储类型SPI FLASH 第三个字节是容量*/
  168. /* GD25Q16 的 ID 是 0xC8, 0x40, 0x15 */
  169. /* W25Q64 的ID 是 0xEF 0x40 0x17 */
  170. if ((buf[0] == 0xC8) && (buf[1] == 0x40) && (buf[2] == 0x15)) {
  171. printf(" ID匹配成功!\n");
  172. return 1;
  173. }
  174. //if ((buf[0] == 0xEF) && (buf[1] == 0x40) && (buf[2] == 0x15)) {
  175. // printf(" ID匹配成功!\n");
  176. // return 1;
  177. //}
  178. // if ((buf[0] == 0xEF) && (buf[1] == 0x40) && (buf[2] == 0x17)) {
  179. // printf(" ID匹配成功!\n");
  180. // return 1;
  181. //}
  182. printf(" ID不匹配!期望: 0xC8 0x40 0x15\n");
  183. return 0;
  184. }
  185. /**
  186. * @brief 读一页数据
  187. */
  188. void AT45DB_ReadPage(uint16_t Page_Add, uint8_t *pdata)
  189. {
  190. int i;
  191. if (Page_Add > 8192)
  192. return;
  193. while (AT45DB_IS_BUSY() == 0);
  194. uint32_t addr = Page_Add * 256;
  195. AT45db161_SPI_SELECT();
  196. SPI2_ReadWrite_Byte(GD25Q16_MM_PAGE_READ);
  197. SPI2_ReadWrite_Byte((int8_t)(addr >> 16));
  198. SPI2_ReadWrite_Byte((int8_t)(addr >> 8));
  199. SPI2_ReadWrite_Byte((int8_t)(addr));
  200. for (i = 0; i < 256; i++) {
  201. *pdata++ = SPI2_ReadWrite_Byte(0x00);
  202. }
  203. AT45db161_SPI_DESELECT();
  204. }
  205. /**
  206. * @brief 写一页数据
  207. */
  208. void AT45DB_WritePage(uint16_t page, uint8_t *Data)
  209. {
  210. uint16_t i;
  211. uint32_t addr = page * 256;
  212. if (page >= 8192)
  213. return;
  214. while (AT45DB_IS_BUSY() == 0);
  215. GD25Q16_WriteEnable();
  216. while (AT45DB_IS_BUSY() == 0);
  217. AT45db161_SPI_SELECT();
  218. SPI2_ReadWrite_Byte(GD25Q16_WRITE);
  219. SPI2_ReadWrite_Byte((uint8_t)(addr >> 16));
  220. SPI2_ReadWrite_Byte((uint8_t)(addr >> 8));
  221. SPI2_ReadWrite_Byte((uint8_t)(addr));
  222. for (i = 0; i < 256; i++) {
  223. SPI2_ReadWrite_Byte(Data[i]);
  224. }
  225. AT45db161_SPI_DESELECT();
  226. while (AT45DB_IS_BUSY() == 0);
  227. }
  228. /**
  229. * @brief 在一页内写入部分数据
  230. */
  231. void AT45DB_WriteBytes_OnOnePage(uint16_t page, uint8_t *Data, uint16_t len)
  232. {
  233. uint16_t i;
  234. if (page > 4095 || len > 256) return;
  235. while (AT45DB_IS_BUSY() == 0);
  236. AT45db161_SPI_SELECT();
  237. SPI2_ReadWrite_Byte(AT45DB_BUFFER_2_WRITE);
  238. SPI2_ReadWrite_Byte(0x00);
  239. SPI2_ReadWrite_Byte(0x00);
  240. SPI2_ReadWrite_Byte(0x00);
  241. for (i = 0; i < len; i++) {
  242. SPI2_ReadWrite_Byte(Data[i]);
  243. }
  244. AT45db161_SPI_DESELECT();
  245. while (AT45DB_IS_BUSY() == 0);
  246. if (page < 4096) {
  247. AT45db161_SPI_SELECT();
  248. SPI2_ReadWrite_Byte(GD25Q16_MM_PAGE_PROG_WITH_ERASE);
  249. SPI2_ReadWrite_Byte((uint8_t)(page >> 6));
  250. SPI2_ReadWrite_Byte((uint8_t)(page << 2));
  251. SPI2_ReadWrite_Byte(0x00);
  252. AT45db161_SPI_DESELECT();
  253. }
  254. }
  255. /**
  256. * @brief 从任意地址读取多个字节
  257. */
  258. void AT45DB_Read_Bytes(uint32_t add, uint8_t *pdata, uint16_t len)
  259. {
  260. int i, j, k;
  261. uint8_t temp[256];
  262. uint16_t page, offset;
  263. if (add > 8192 * 256) return;
  264. page = add / 256;
  265. offset = add % 256;
  266. AT45DB_ReadPage(page++, temp);
  267. for (i = offset; (len != 0) && (i < 256); len--, i++) {
  268. *pdata++ = temp[i];
  269. }
  270. if ((i == 256) && (len != 0)) {
  271. if (len > 256) {
  272. for (k = 0; k < len / 256; k++) {
  273. AT45DB_ReadPage(page++, temp);
  274. for (j = 0; j < 256; j++) {
  275. *pdata++ = temp[j];
  276. }
  277. }
  278. len -= 256 * k;
  279. }
  280. if (len != 0) {
  281. AT45DB_ReadPage(page, temp);
  282. for (j = 0; j < len; j++) {
  283. *pdata++ = temp[j];
  284. }
  285. }
  286. }
  287. }
  288. /**
  289. * @brief 从任意地址写入多个字节
  290. */
  291. void AT45DB_Write_Bytes(uint32_t add, uint8_t *pdata, uint16_t len)
  292. {
  293. uint8_t temp[256];
  294. uint16_t page, offset;
  295. uint16_t i, j, k;
  296. if (add > 8192 * 256) return;
  297. page = add / 256;
  298. offset = add % 256;
  299. AT45DB_ReadPage(page, temp);
  300. for (i = offset; (len != 0) && (i < 256); len--, i++) {
  301. temp[i] = *pdata++;
  302. }
  303. GD25Q16_Erase_Sector(add);
  304. AT45DB_WritePage(page++, temp);
  305. if ((i == 256) && (len != 0)) {
  306. if (len > 256) {
  307. for (k = 0; k < len / 256; k++) {
  308. for (j = 0; j < 256; j++) {
  309. temp[j] = *pdata++;
  310. }
  311. AT45DB_WritePage(page++, temp);
  312. }
  313. len -= 256 * k;
  314. }
  315. if (len != 0) {
  316. AT45DB_ReadPage(page, temp);
  317. for (j = 0; j < len; j++) {
  318. temp[j] = *pdata++;
  319. }
  320. AT45DB_WritePage(page, temp);
  321. }
  322. }
  323. }
  324. /**
  325. * @brief 写入浮点数
  326. */
  327. void AT45DB_Write_float(uint32_t add, float wvalue)
  328. {
  329. f_bytes data;
  330. data.value = wvalue;
  331. AT45DB_Write_Bytes(add, &data.byte[0], 4);
  332. }
  333. /**
  334. * @brief 读取浮点数
  335. */
  336. float AT45DB_Read_float(uint32_t add)
  337. {
  338. f_bytes data;
  339. data.value = 0;
  340. AT45DB_Read_Bytes(add, &data.byte[0], 4);
  341. return data.value;
  342. }
  343. /**
  344. * @brief 写入16位整数
  345. */
  346. void AT45DB_Write_int16(uint32_t add, int16_t wvalue)
  347. {
  348. i_bytes data;
  349. data.value = wvalue;
  350. AT45DB_Write_Bytes(add, &data.byte[0], 2);
  351. }
  352. /**
  353. * @brief 读取16位整数
  354. */
  355. int16_t AT45DB_Read_int16(uint32_t add)
  356. {
  357. i_bytes data;
  358. data.value = 0;
  359. AT45DB_Read_Bytes(add, &data.byte[0], 2);
  360. return data.value;
  361. }
  362. #endif /* GD25Q16_FLASH */
  363. /* 20260322 spi flash test pass 测试了W25Q64与Q16; note:ai 写测试例程太全面了*/
  364. #ifdef GD25Q16_TEST
  365. /**
  366. * @file test_gd25q16.c
  367. * @brief GD25Q16 SPI Flash 驱动测试程序
  368. *
  369. * 测试内容:
  370. * 1. 芯片 ID 读取和存在性检查
  371. * 2. 状态寄存器读取
  372. * 3. 页写入和页读取
  373. * 4. 任意地址写入和读取(跨页)
  374. * 5. 浮点数和整数读写
  375. * 6. 擦除功能验证
  376. */
  377. /* 测试缓冲区大小 */
  378. #define TEST_BUFFER_SIZE 512
  379. #define TEST_PAGE_NUM 100 /* 测试用的页号,范围 0-8191 */
  380. #define TEST_SECTOR_ADDR (TEST_PAGE_NUM * 256) /* 测试用的扇区起始地址 */
  381. /* 测试用的数据模式 */
  382. static const uint8_t test_pattern[] = {
  383. 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
  384. 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
  385. 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0,
  386. 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
  387. };
  388. /**
  389. * @brief 打印内存数据(十六进制格式)
  390. */
  391. static void print_hex_data(const uint8_t *data, uint16_t len, const char *title)
  392. {
  393. uint16_t i;
  394. printf("\n========== %s ==========\n", title);
  395. for (i = 0; i < len; i++) {
  396. printf("%02X ", data[i]);
  397. if ((i + 1) % 16 == 0) {
  398. printf("\n");
  399. }
  400. }
  401. if (len % 16 != 0) {
  402. printf("\n");
  403. }
  404. printf("========== 结束 ==========\n\n");
  405. }
  406. /**
  407. * @brief 比较两个内存块是否相等
  408. */
  409. static uint8_t compare_memory(const uint8_t *expected, const uint8_t *actual, uint16_t len)
  410. {
  411. uint16_t i;
  412. uint8_t match = 1;
  413. for (i = 0; i < len; i++) {
  414. if (expected[i] != actual[i]) {
  415. printf(" 数据不匹配 @ 偏移 %d: 期望 0x%02X, 实际 0x%02X\n",
  416. i, expected[i], actual[i]);
  417. match = 0;
  418. }
  419. }
  420. return match;
  421. }
  422. /**
  423. * @brief 测试 1:芯片检测和 ID 读取
  424. */
  425. static uint8_t test_chip_detection(void)
  426. {
  427. uint8_t result;
  428. printf("\n========================================\n");
  429. printf("测试 1:芯片检测\n");
  430. printf("========================================\n");
  431. result = AT45DB_Check();
  432. if (result) {
  433. printf("✅ 芯片检测成功!GD25Q16 存在\n");
  434. /* 手动读取 JEDEC ID 用于显示 */
  435. uint8_t buf[3];
  436. AT45db161_SPI_SELECT();
  437. SPI2_ReadWrite_Byte(0x9F);
  438. buf[0] = SPI2_ReadWrite_Byte(0);
  439. buf[1] = SPI2_ReadWrite_Byte(0);
  440. buf[2] = SPI2_ReadWrite_Byte(0);
  441. AT45db161_SPI_DESELECT();
  442. printf(" JEDEC ID: 0x%02X 0x%02X 0x%02X\n", buf[0], buf[1], buf[2]);
  443. printf(" 制造商: 0x%02X (GigaDevice)\n", buf[0]);
  444. printf(" 型号: 0x%02X%02X (GD25Q16)\n", buf[1], buf[2]);
  445. printf(" 容量: 16Mbit (2MByte)\n");
  446. return 1;
  447. } else {
  448. printf("❌ 芯片检测失败!请检查硬件连接\n");
  449. return 0;
  450. }
  451. }
  452. /**
  453. * @brief 测试 2:页写入和页读取
  454. */
  455. static uint8_t test_page_write_read(void)
  456. {
  457. uint8_t write_buf[256];
  458. uint8_t read_buf[256];
  459. uint16_t i;
  460. printf("\n========================================\n");
  461. printf("测试 2:页写入和页读取\n");
  462. printf("========================================\n");
  463. printf("测试页号: %d (地址: 0x%06X)\n", TEST_PAGE_NUM, TEST_PAGE_NUM * 256);
  464. /* 准备测试数据 */
  465. for (i = 0; i < 256; i++) {
  466. write_buf[i] = (uint8_t)(i + TEST_PAGE_NUM);
  467. }
  468. print_hex_data(write_buf, 32, "写入数据(前32字节)");
  469. /* 写入一页 */
  470. printf("正在写入数据...\n");
  471. AT45DB_WritePage(TEST_PAGE_NUM, write_buf);
  472. printf("✅ 页写入完成\n");
  473. /* 读取一页 */
  474. printf("正在读取数据...\n");
  475. AT45DB_ReadPage(TEST_PAGE_NUM, read_buf);
  476. printf("✅ 页读取完成\n");
  477. print_hex_data(read_buf, 32, "读取数据(前32字节)");
  478. /* 验证数据 */
  479. if (compare_memory(write_buf, read_buf, 256)) {
  480. printf("✅ 页写入/读取测试通过!\n");
  481. return 1;
  482. } else {
  483. printf("❌ 页写入/读取测试失败!\n");
  484. return 0;
  485. }
  486. }
  487. /**
  488. * @brief 测试 3:任意地址写入和读取(跨页)
  489. */
  490. static uint8_t test_random_address_write_read(void)
  491. {
  492. uint8_t write_buf[TEST_BUFFER_SIZE];
  493. uint8_t read_buf[TEST_BUFFER_SIZE];
  494. uint16_t i;
  495. uint32_t start_addr = TEST_SECTOR_ADDR + 100; /* 从页内偏移 100 开始 */
  496. printf("\n========================================\n");
  497. printf("测试 3:任意地址写入和读取(跨页测试)\n");
  498. printf("========================================\n");
  499. printf("起始地址: 0x%06X (页 %d, 偏移 %d)\n",
  500. start_addr, start_addr / 256, start_addr % 256);
  501. printf("数据长度: %d 字节 (跨页: %d 页)\n",
  502. TEST_BUFFER_SIZE, (start_addr + TEST_BUFFER_SIZE - 1) / 256 - start_addr / 256 + 1);
  503. /* 准备测试数据 */
  504. for (i = 0; i < TEST_BUFFER_SIZE; i++) {
  505. write_buf[i] = (uint8_t)(i % 256);
  506. }
  507. print_hex_data(write_buf, 32, "写入数据(前32字节)");
  508. /* 写入数据 */
  509. printf("正在写入数据...\n");
  510. AT45DB_Write_Bytes(start_addr, write_buf, TEST_BUFFER_SIZE);
  511. printf(" 数据写入完成\n");
  512. /* 读取数据 */
  513. printf("正在读取数据...\n");
  514. AT45DB_Read_Bytes(start_addr, read_buf, TEST_BUFFER_SIZE);
  515. printf(" 数据读取完成\n");
  516. print_hex_data(read_buf, 32, "读取数据(前32字节)");
  517. /* 验证数据 */
  518. if (compare_memory(write_buf, read_buf, TEST_BUFFER_SIZE)) {
  519. printf(" 任意地址写入/读取测试通过!\n");
  520. return 1;
  521. } else {
  522. printf(" 任意地址写入/读取测试失败!\n");
  523. return 0;
  524. }
  525. }
  526. /**
  527. * @brief 测试 4:浮点数读写
  528. */
  529. static uint8_t test_float_read_write(void)
  530. {
  531. uint32_t addr = TEST_SECTOR_ADDR + 400;
  532. float test_values[] = {3.14159f, 2.71828f, -123.456f, 0.0f, 999.999f};
  533. float read_value;
  534. uint8_t i;
  535. uint8_t all_pass = 1;
  536. printf("\n========================================\n");
  537. printf("测试 4:浮点数读写\n");
  538. printf("========================================\n");
  539. printf("测试地址: 0x%06X\n", addr);
  540. for (i = 0; i < sizeof(test_values) / sizeof(test_values[0]); i++) {
  541. printf("\n[测试 %d] 写入值: %f\n", i + 1, test_values[i]);
  542. AT45DB_Write_float(addr + i * 4, test_values[i]);
  543. read_value = AT45DB_Read_float(addr + i * 4);
  544. printf(" 读取值: %f\n", read_value);
  545. /* 浮点数比较,使用误差范围 */
  546. if ((test_values[i] - read_value) < 0.0001f &&
  547. (read_value - test_values[i]) < 0.0001f) {
  548. printf(" 验证通过\n");
  549. } else {
  550. printf(" 验证失败\n");
  551. all_pass = 0;
  552. }
  553. }
  554. if (all_pass) {
  555. printf("\n 浮点数读写测试通过!\n");
  556. return 1;
  557. } else {
  558. printf("\n 浮点数读写测试失败!\n");
  559. return 0;
  560. }
  561. }
  562. /**
  563. * @brief 测试 5:16位整数读写
  564. */
  565. static uint8_t test_int16_read_write(void)
  566. {
  567. uint32_t addr = TEST_SECTOR_ADDR + 500;
  568. int16_t test_values[] = {12345, -5678, 0, 32767, -32768};
  569. int16_t read_value;
  570. uint8_t i;
  571. uint8_t all_pass = 1;
  572. printf("\n========================================\n");
  573. printf("测试 5:16位整数读写\n");
  574. printf("========================================\n");
  575. printf("测试地址: 0x%06X\n", addr);
  576. for (i = 0; i < sizeof(test_values) / sizeof(test_values[0]); i++) {
  577. printf("\n[测试 %d] 写入值: %d\n", i + 1, test_values[i]);
  578. AT45DB_Write_int16(addr + i * 2, test_values[i]);
  579. read_value = AT45DB_Read_int16(addr + i * 2);
  580. printf(" 读取值: %d\n", read_value);
  581. if (test_values[i] == read_value) {
  582. printf(" 验证通过\n");
  583. } else {
  584. printf(" 验证失败\n");
  585. all_pass = 0;
  586. }
  587. }
  588. if (all_pass) {
  589. printf("\n 16位整数读写测试通过!\n");
  590. return 1;
  591. } else {
  592. printf("\n 16位整数读写测试失败!\n");
  593. return 0;
  594. }
  595. }
  596. /**
  597. * @brief 测试 6:擦除功能验证
  598. */
  599. static uint8_t test_erase_verify(void)
  600. {
  601. uint8_t read_buf[256];
  602. uint16_t i;
  603. uint8_t all_erased = 1;
  604. uint32_t test_addr = TEST_SECTOR_ADDR;
  605. printf("\n========================================\n");
  606. printf("测试 6:擦除功能验证\n");
  607. printf("========================================\n");
  608. printf("擦除扇区地址: 0x%06X (页 %d)\n", test_addr, test_addr / 256);
  609. /* 先写入已知数据 */
  610. printf("步骤 1: 写入测试数据...\n");
  611. for (i = 0; i < 256; i++) {
  612. read_buf[i] = (uint8_t)(0xAA);
  613. }
  614. AT45DB_WritePage(TEST_PAGE_NUM, read_buf);
  615. /* 验证写入成功 */
  616. AT45DB_ReadPage(TEST_PAGE_NUM, read_buf);
  617. for (i = 0; i < 256; i++) {
  618. if (read_buf[i] != 0xAA) {
  619. printf(" 数据写入验证失败\n");
  620. return 0;
  621. }
  622. }
  623. printf("测试数据写入成功\n");
  624. /* 执行扇区擦除 */
  625. printf("步骤 2: 执行扇区擦除...\n");
  626. GD25Q16_Erase_Sector(test_addr);
  627. printf("扇区擦除完成\n");
  628. /* 验证擦除结果(擦除后应该是 0xFF) */
  629. printf("步骤 3: 验证擦除结果...\n");
  630. AT45DB_ReadPage(TEST_PAGE_NUM, read_buf);
  631. for (i = 0; i < 256; i++) {
  632. if (read_buf[i] != 0xFF) {
  633. printf(" 地址 0x%06X: 期望 0xFF, 实际 0x%02X\n",
  634. test_addr + i, read_buf[i]);
  635. all_erased = 0;
  636. }
  637. }
  638. if (all_erased) {
  639. printf(" 所有字节验证为 0xFF\n");
  640. printf(" 擦除功能测试通过!\n");
  641. return 1;
  642. } else {
  643. printf(" 擦除功能测试失败!\n");
  644. return 0;
  645. }
  646. }
  647. /**
  648. * @brief 主测试函数
  649. */
  650. void test_gd25q16(void)
  651. {
  652. uint8_t test_result[6];
  653. uint8_t all_pass = 1;
  654. uint32_t start_time, end_time;
  655. printf("\n");
  656. printf("╔══════════════════════════════════════════════════════════╗\n");
  657. printf("║ GD25Q16 SPI Flash 驱动测试程序 ║\n");
  658. printf("╚══════════════════════════════════════════════════════════╝\n");
  659. /* 初始化 Flash */
  660. printf("\n正在初始化 SPI Flash...\n");
  661. flash_at45db_init();
  662. printf(" SPI Flash 初始化完成\n");
  663. /* 运行所有测试 */
  664. test_result[0] = test_chip_detection();
  665. if (!test_result[0]) {
  666. printf("\n 芯片检测失败,终止后续测试!\n");
  667. return;
  668. }
  669. test_result[1] = test_page_write_read();
  670. test_result[2] = test_random_address_write_read();
  671. test_result[3] = test_float_read_write();
  672. test_result[4] = test_int16_read_write();
  673. test_result[5] = test_erase_verify();
  674. /* 打印测试总结 */
  675. printf("\n");
  676. printf("╔══════════════════════════════════════════════════════════╗\n");
  677. printf("║ 测试总结 ║\n");
  678. printf("╠══════════════════════════════════════════════════════════╣\n");
  679. const char *test_names[] = {
  680. "芯片检测",
  681. "页写入/读取",
  682. "任意地址写入/读取",
  683. "浮点数读写",
  684. "16位整数读写",
  685. "擦除功能验证"
  686. };
  687. for (int i = 0; i < 6; i++) {
  688. printf("║ 测试 %d: %-20s : %s\n",
  689. i + 1,
  690. test_names[i],
  691. test_result[i] ? " 通过" : " 失败");
  692. if (!test_result[i]) all_pass = 0;
  693. }
  694. printf("╠══════════════════════════════════════════════════════════╣\n");
  695. if (all_pass) {
  696. printf("║ 最终结果: 所有测试通过!驱动工作正常 🎉 ║\n");
  697. } else {
  698. printf("║ 最终结果: 部分测试失败,请检查硬件或驱动 ⚠️ ║\n");
  699. }
  700. printf("╚══════════════════════════════════════════════════════════╝\n");
  701. }
  702. /**
  703. * @brief 简化的快速测试(仅测试基本功能)
  704. */
  705. void test_gd25q16_quick(void)
  706. {
  707. printf("\n=== GD25Q16 快速测试 ===\n");
  708. flash_at45db_init();
  709. /* 测试芯片存在 */
  710. if (AT45DB_Check()) {
  711. printf(" 芯片检测通过\n");
  712. } else {
  713. printf(" 芯片检测失败\n");
  714. return;
  715. }
  716. /* 简单读写测试 */
  717. uint8_t write_buf[32];
  718. uint8_t read_buf[32];
  719. for (int i = 0; i < 32; i++) {
  720. write_buf[i] = i;
  721. }
  722. AT45DB_Write_Bytes(0, write_buf, 32);
  723. AT45DB_Read_Bytes(0, read_buf, 32);
  724. if (memcmp(write_buf, read_buf, 32) == 0) {
  725. printf(" 读写测试通过\n");
  726. } else {
  727. printf(" 读写测试失败\n");
  728. }
  729. printf("=== 快速测试结束 ===\n");
  730. test_gd25q16();
  731. }
  732. #endif