FlashTest.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. //
  2. // Unit tests for the AP_Math rotations code
  3. //
  4. #include <AP_HAL/AP_HAL.h>
  5. #include <AP_Math/AP_Math.h>
  6. #include <AP_FlashStorage/AP_FlashStorage.h>
  7. #include <stdio.h>
  8. const AP_HAL::HAL& hal = AP_HAL::get_HAL();
  9. class FlashTest : public AP_HAL::HAL::Callbacks {
  10. public:
  11. // HAL::Callbacks implementation.
  12. void setup() override;
  13. void loop() override;
  14. private:
  15. static const uint32_t flash_sector_size = 32U * 1024U;
  16. uint8_t mem_buffer[AP_FlashStorage::storage_size];
  17. uint8_t mem_mirror[AP_FlashStorage::storage_size];
  18. // flash buffer
  19. uint8_t *flash[2];
  20. bool flash_write(uint8_t sector, uint32_t offset, const uint8_t *data, uint16_t length);
  21. bool flash_read(uint8_t sector, uint32_t offset, uint8_t *data, uint16_t length);
  22. bool flash_erase(uint8_t sector);
  23. bool flash_erase_ok(void);
  24. AP_FlashStorage storage{mem_buffer,
  25. flash_sector_size,
  26. FUNCTOR_BIND_MEMBER(&FlashTest::flash_write, bool, uint8_t, uint32_t, const uint8_t *, uint16_t),
  27. FUNCTOR_BIND_MEMBER(&FlashTest::flash_read, bool, uint8_t, uint32_t, uint8_t *, uint16_t),
  28. FUNCTOR_BIND_MEMBER(&FlashTest::flash_erase, bool, uint8_t),
  29. FUNCTOR_BIND_MEMBER(&FlashTest::flash_erase_ok, bool)};
  30. // write to storage and mem_mirror
  31. void write(uint16_t offset, const uint8_t *data, uint16_t length);
  32. bool erase_ok;
  33. };
  34. bool FlashTest::flash_write(uint8_t sector, uint32_t offset, const uint8_t *data, uint16_t length)
  35. {
  36. if (sector > 1) {
  37. AP_HAL::panic("FATAL: write to sector %u\n", (unsigned)sector);
  38. }
  39. if (offset + length > flash_sector_size) {
  40. AP_HAL::panic("FATAL: write to sector %u at offset %u length %u\n",
  41. (unsigned)sector,
  42. (unsigned)offset,
  43. (unsigned)length);
  44. }
  45. uint8_t *b = &flash[sector][offset];
  46. if ((offset & 1) || (length & 1)) {
  47. AP_HAL::panic("FATAL: invalid write at %u:%u len=%u\n",
  48. sector, offset, length);
  49. }
  50. const uint16_t *data16 = (const uint16_t *)data;
  51. uint16_t *b16 = (uint16_t *)&b[0];
  52. uint16_t len16 = length/2;
  53. for (uint16_t i=0; i<len16; i++) {
  54. if (data16[i] & !b16[i]) {
  55. AP_HAL::panic("FATAL: invalid write16 at %u:%u 0x%04x 0x%04x\n",
  56. sector, offset+i, b[i], data[i]);
  57. }
  58. #if !AP_FLASHSTORAGE_MULTI_WRITE
  59. if (data16[i] != b16[i] && data16[i] != 0xFFFF && b16[i] != 0xFFFF) {
  60. AP_HAL::panic("FATAL: invalid write16 at %u:%u 0x%04x 0x%04x\n",
  61. sector, offset+i, b[i], data[i]);
  62. }
  63. #endif
  64. b16[i] &= data16[i];
  65. }
  66. return true;
  67. }
  68. bool FlashTest::flash_read(uint8_t sector, uint32_t offset, uint8_t *data, uint16_t length)
  69. {
  70. if (sector > 1) {
  71. AP_HAL::panic("FATAL: read from sector %u\n", (unsigned)sector);
  72. }
  73. if (offset + length > flash_sector_size) {
  74. AP_HAL::panic("FATAL: read from sector %u at offset %u length %u\n",
  75. (unsigned)sector,
  76. (unsigned)offset,
  77. (unsigned)length);
  78. }
  79. memcpy(data, &flash[sector][offset], length);
  80. return true;
  81. }
  82. bool FlashTest::flash_erase(uint8_t sector)
  83. {
  84. if (sector > 1) {
  85. AP_HAL::panic("FATAL: erase sector %u\n", (unsigned)sector);
  86. }
  87. memset(&flash[sector][0], 0xFF, flash_sector_size);
  88. return true;
  89. }
  90. bool FlashTest::flash_erase_ok(void)
  91. {
  92. return erase_ok;
  93. }
  94. void FlashTest::write(uint16_t offset, const uint8_t *data, uint16_t length)
  95. {
  96. memcpy(&mem_mirror[offset], data, length);
  97. memcpy(&mem_buffer[offset], data, length);
  98. if (!storage.write(offset, length)) {
  99. if (erase_ok) {
  100. printf("Failed to write at %u for %u\n", offset, length);
  101. }
  102. }
  103. }
  104. /*
  105. * test flash storage
  106. */
  107. void FlashTest::setup(void)
  108. {
  109. hal.console->printf("AP_FlashStorage test\n");
  110. }
  111. void FlashTest::loop(void)
  112. {
  113. flash[0] = (uint8_t *)malloc(flash_sector_size);
  114. flash[1] = (uint8_t *)malloc(flash_sector_size);
  115. flash_erase(0);
  116. flash_erase(1);
  117. if (!storage.init()) {
  118. AP_HAL::panic("Failed first init()");
  119. }
  120. // fill with 10k random writes
  121. for (uint32_t i=0; i<5000000; i++) {
  122. uint16_t ofs = get_random16() % sizeof(mem_buffer);
  123. uint16_t length = get_random16() & 0x1F;
  124. length = MIN(length, sizeof(mem_buffer) - ofs);
  125. uint8_t data[length];
  126. for (uint8_t j=0; j<length; j++) {
  127. data[j] = get_random16() & 0xFF;
  128. }
  129. erase_ok = (i % 1000 == 0);
  130. write(ofs, data, length);
  131. if (erase_ok) {
  132. if (memcmp(mem_buffer, mem_mirror, sizeof(mem_buffer)) != 0) {
  133. AP_HAL::panic("FATAL: data mis-match at i=%u", (unsigned)i);
  134. }
  135. }
  136. }
  137. // force final write to allow for flush with erase_ok
  138. erase_ok = true;
  139. uint8_t b = 42;
  140. write(37, &b, 1);
  141. if (memcmp(mem_buffer, mem_mirror, sizeof(mem_buffer)) != 0) {
  142. AP_HAL::panic("FATAL: data mis-match before re-init");
  143. }
  144. // re-init
  145. printf("re-init\n");
  146. memset(mem_buffer, 0, sizeof(mem_buffer));
  147. if (!storage.init()) {
  148. AP_HAL::panic("Failed second init()");
  149. }
  150. if (memcmp(mem_buffer, mem_mirror, sizeof(mem_buffer)) != 0) {
  151. AP_HAL::panic("FATAL: data mis-match");
  152. }
  153. while (true) {
  154. hal.console->printf("TEST PASSED");
  155. hal.scheduler->delay(20000);
  156. }
  157. }
  158. FlashTest flashtest;
  159. AP_HAL_MAIN_CALLBACKS(&flashtest);