test_wl.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "esp_spi_flash.h"
  5. #include "esp_partition.h"
  6. #include "wear_levelling.h"
  7. #include "WL_Flash.h"
  8. #include "SpiFlash.h"
  9. #include "catch.hpp"
  10. #include "sdkconfig.h"
  11. extern "C" void _spi_flash_init(const char* chip_size, size_t block_size, size_t sector_size, size_t page_size, const char* partition_bin);
  12. extern SpiFlash spiflash;
  13. #define TEST_COUNT_MAX 100
  14. TEST_CASE("write and read back data", "[wear_levelling]")
  15. {
  16. _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
  17. esp_err_t result;
  18. wl_handle_t wl_handle;
  19. int flash_handle;
  20. const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
  21. // Mount wear-levelled partition
  22. result = wl_mount(partition, &wl_handle);
  23. REQUIRE(result == ESP_OK);
  24. // Get the sector size
  25. uint32_t sector_size = wl_sector_size(wl_handle);
  26. REQUIRE(sector_size == CONFIG_WL_SECTOR_SIZE);
  27. uint8_t* data = (uint8_t*) malloc(partition->size);
  28. uint8_t* read = (uint8_t*) malloc(partition->size);
  29. uint32_t sectors = partition->size / sector_size;
  30. // Generate data
  31. for(uint32_t sector = 0; sector < sectors; sector++)
  32. {
  33. uint32_t sector_address = sector * sector_size;
  34. for(uint32_t i = 0; i < sector_size / sizeof(i); i++)
  35. {
  36. ((uint32_t*) data)[i] = sector_address + i;
  37. }
  38. }
  39. // Write data
  40. result = wl_write(wl_handle, 0, data, partition->size);
  41. REQUIRE(result == ESP_OK);
  42. // Read data
  43. result = wl_read(wl_handle, 0, read, partition->size);
  44. REQUIRE(result == ESP_OK);
  45. // Verify that written and read data match
  46. REQUIRE(memcmp(data, read, partition->size));
  47. // Erase some ranges
  48. result = wl_erase_range(wl_handle, 0, sector_size);
  49. REQUIRE(result == ESP_OK);
  50. result = wl_erase_range(wl_handle, 12288, sector_size * 2);
  51. REQUIRE(result == ESP_OK);
  52. result = wl_erase_range(wl_handle, 28672, sector_size * 3);
  53. REQUIRE(result == ESP_OK);
  54. // Expected data after erasure
  55. memset(data + 0, 0xFF, sector_size);
  56. memset(data + 12288, 0xFF, sector_size * 2);
  57. memset(data + 28672, 0xFF, sector_size * 3);
  58. // Read again, with erased ranges
  59. result = wl_read(wl_handle, 0, read, partition->size);
  60. REQUIRE(result == ESP_OK);
  61. // Verify that written and read data match
  62. REQUIRE(memcmp(data, read, partition->size));
  63. // Unmount
  64. result = wl_unmount(wl_handle);
  65. REQUIRE(result == ESP_OK);
  66. free(data);
  67. free(read);
  68. }
  69. TEST_CASE("power down test", "[wear_levelling]")
  70. {
  71. _spi_flash_init(CONFIG_ESPTOOLPY_FLASHSIZE, CONFIG_WL_SECTOR_SIZE * 16, CONFIG_WL_SECTOR_SIZE, CONFIG_WL_SECTOR_SIZE, "partition_table.bin");
  72. esp_err_t result;
  73. wl_handle_t wl_handle;
  74. int flash_handle;
  75. const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_ANY, "storage");
  76. // Mount wear-levelled partition
  77. result = wl_mount(partition, &wl_handle);
  78. REQUIRE(result == ESP_OK);
  79. // Get wl partition information
  80. size_t sector_size = wl_sector_size(wl_handle);
  81. int32_t sectors_count = wl_size(wl_handle) / sector_size;
  82. uint32_t add_const = 0;
  83. uint32_t *sector_data = new uint32_t[sector_size / sizeof(uint32_t)];
  84. // Fill partition with check data
  85. for (int32_t i = 0; i < sectors_count; i++) {
  86. REQUIRE(wl_erase_range(wl_handle, i * sector_size, sector_size) == ESP_OK);
  87. for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
  88. uint32_t temp_data = i * sector_size + add_const + m;
  89. sector_data[m] = temp_data;
  90. }
  91. REQUIRE(wl_write(wl_handle, i * sector_size, sector_data, sector_size) == ESP_OK);
  92. }
  93. for (int32_t i = 0; i < sectors_count; i++) {
  94. result |= wl_read(wl_handle, i * sector_size, sector_data, sector_size);
  95. for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
  96. uint32_t temp_data = i * sector_size + add_const + m;
  97. REQUIRE(temp_data == sector_data[m]);
  98. if (temp_data != sector_data[m]) {
  99. printf("Error - read: %08x, expected %08x\n", sector_data[m], temp_data);
  100. }
  101. }
  102. }
  103. // Perform test
  104. int32_t max_count = 100;
  105. int32_t max_check_count = TEST_COUNT_MAX;
  106. printf("used_sectors_count=%d\n", max_check_count);
  107. for (int32_t k = 0; k < max_check_count; k++) {
  108. spiflash.set_total_erase_cycles_limit(max_count);
  109. int32_t err_sector = -1;
  110. for (int32_t i = 0; i < sectors_count; i++) {
  111. result = ESP_OK;
  112. result = wl_erase_range(wl_handle, i * sector_size, sector_size);
  113. if (result != ESP_OK) {
  114. err_sector = i;
  115. break;
  116. }
  117. for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
  118. uint32_t temp_data = i * sector_size + add_const + m;
  119. sector_data[m] = temp_data;
  120. }
  121. result = wl_write(wl_handle, i * sector_size, sector_data, sector_size);
  122. if (result != ESP_OK) {
  123. err_sector = i;
  124. break;
  125. }
  126. }
  127. if (err_sector >= 0) {
  128. max_count++;
  129. } else {
  130. max_count = 0;
  131. }
  132. spiflash.set_total_erase_cycles_limit(0);
  133. result = wl_unmount(wl_handle);
  134. REQUIRE(result == ESP_OK);
  135. result = wl_mount(partition, &wl_handle);
  136. REQUIRE(result == ESP_OK);
  137. for (int32_t i = 0; i < sectors_count; i++) {
  138. if (i != err_sector) {
  139. result |= wl_read(wl_handle, i * sector_size, sector_data, sector_size);
  140. for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
  141. uint32_t temp_data = i * sector_size + add_const + m;
  142. REQUIRE(temp_data == sector_data[m]);
  143. if (temp_data != sector_data[m]) {
  144. printf("Error - read: %08x, expected %08x, m=%i, sector=%i\n", sector_data[m], temp_data, m, i);
  145. }
  146. }
  147. }
  148. }
  149. if (err_sector != -1) {
  150. result |= wl_erase_range(wl_handle, err_sector * sector_size, sector_size);
  151. for (uint32_t m = 0; m < sector_size / sizeof(uint32_t); m++) {
  152. uint32_t temp_data = err_sector * sector_size + add_const + m;
  153. sector_data[m] = temp_data;
  154. }
  155. result |= wl_write(wl_handle, err_sector * sector_size, sector_data, sector_size);
  156. }
  157. spiflash.reset_total_erase_cycles();
  158. printf("[%3.f%%] err_sector=%i\n", (float)k / ((float)max_check_count) * 100.0f, err_sector);
  159. }
  160. delete[] sector_data;
  161. // Unmount
  162. result = wl_unmount(wl_handle);
  163. REQUIRE(result == ESP_OK);
  164. }