8#include "w25q_validation.hpp"
16void W25QValidation::resetReport() {
17 _report.
status = W25Q_VALIDATION_STATUS_PASS;
18 _report.
failedTest = W25Q_VALIDATION_TEST_NONE;
26void W25QValidation::recordFailure(w25qValidationTestId_t testId, w25qValidationPhase_t phase,
27 uint32_t offset, uint8_t expectedValue, uint8_t actualValue) {
28 _report.
status = W25Q_VALIDATION_STATUS_FAIL;
36const char *W25QValidation::getTestName(w25qValidationTestId_t testId) {
38 case W25Q_VALIDATION_TEST_ERASED_STATE:
39 return "Erased-state test";
40 case W25Q_VALIDATION_TEST_SMALL_RANGE:
41 return "Small range read/write test";
42 case W25Q_VALIDATION_TEST_PATTERN:
43 return "Pattern data test";
44 case W25Q_VALIDATION_TEST_PAGE_BOUNDARY:
45 return "Page-boundary write test";
46 case W25Q_VALIDATION_TEST_NONE:
52const char *W25QValidation::getPhaseName(w25qValidationPhase_t phase) {
54 case W25Q_VALIDATION_PHASE_ERASE:
56 case W25Q_VALIDATION_PHASE_FILL:
58 case W25Q_VALIDATION_PHASE_VERIFY:
60 case W25Q_VALIDATION_PHASE_IDLE:
66void W25QValidation::printFailure()
const {
68 printf(
" Test : %s\r\n", getTestName(_report.
failedTest));
69 printf(
" Phase : %s\r\n", getPhaseName(_report.
failedPhase));
70 printf(
" Offset : 0x%06lX\r\n", (
unsigned long)_report.
failedOffset);
72 printf(
" Actual : 0x%02X\r\n", _report.
actualValue);
75bool W25QValidation::runErasedStateTest() {
77 _report.
failedTest = W25Q_VALIDATION_TEST_ERASED_STATE;
80 printf(
"[TEST 1] %s\r\n", getTestName(W25Q_VALIDATION_TEST_ERASED_STATE));
82 bool erased = _flash.
eraseSector(W25Q_VALIDATION_BASE_ADDR);
84 recordFailure(W25Q_VALIDATION_TEST_ERASED_STATE, W25Q_VALIDATION_PHASE_ERASE,
85 W25Q_VALIDATION_BASE_ADDR, 0xFF, 0x00);
92 uint8_t buf[W25Q_VALIDATION_SMALL_RANGE_SIZE];
93 bool readOk = _flash.
readBuffer(W25Q_VALIDATION_BASE_ADDR, buf,
sizeof(buf));
95 recordFailure(W25Q_VALIDATION_TEST_ERASED_STATE, W25Q_VALIDATION_PHASE_VERIFY,
96 W25Q_VALIDATION_BASE_ADDR, 0xFF, 0x00);
101 for (uint32_t offset = 0; offset <
sizeof(buf); offset++) {
102 if (buf[offset] != 0xFF) {
103 recordFailure(W25Q_VALIDATION_TEST_ERASED_STATE, W25Q_VALIDATION_PHASE_VERIFY,
104 W25Q_VALIDATION_BASE_ADDR + offset, 0xFF, buf[offset]);
114bool W25QValidation::runSmallRangeTest() {
116 _report.
failedTest = W25Q_VALIDATION_TEST_SMALL_RANGE;
119 printf(
"[TEST 2] %s\r\n", getTestName(W25Q_VALIDATION_TEST_SMALL_RANGE));
121 bool erased = _flash.
eraseSector(W25Q_VALIDATION_BASE_ADDR);
123 recordFailure(W25Q_VALIDATION_TEST_SMALL_RANGE, W25Q_VALIDATION_PHASE_ERASE,
124 W25Q_VALIDATION_BASE_ADDR, 0, 0);
129 uint8_t writeBuf[W25Q_VALIDATION_SMALL_RANGE_SIZE];
130 for (uint32_t offset = 0; offset <
sizeof(writeBuf); offset++) {
131 writeBuf[offset] = (uint8_t)(offset & 0xFFu);
135 bool written = _flash.
writeBuffer(W25Q_VALIDATION_BASE_ADDR, writeBuf,
sizeof(writeBuf));
137 recordFailure(W25Q_VALIDATION_TEST_SMALL_RANGE, W25Q_VALIDATION_PHASE_FILL,
138 W25Q_VALIDATION_BASE_ADDR, 0, 0);
143 _report.
failedPhase = W25Q_VALIDATION_PHASE_VERIFY;
144 uint8_t readBuf[W25Q_VALIDATION_SMALL_RANGE_SIZE];
145 bool readOk = _flash.
readBuffer(W25Q_VALIDATION_BASE_ADDR, readBuf,
sizeof(readBuf));
147 recordFailure(W25Q_VALIDATION_TEST_SMALL_RANGE, W25Q_VALIDATION_PHASE_VERIFY,
148 W25Q_VALIDATION_BASE_ADDR, 0, 0);
153 for (uint32_t offset = 0; offset <
sizeof(readBuf); offset++) {
154 uint8_t expectedValue = (uint8_t)(offset & 0xFFu);
155 if (readBuf[offset] != expectedValue) {
156 recordFailure(W25Q_VALIDATION_TEST_SMALL_RANGE, W25Q_VALIDATION_PHASE_VERIFY,
157 W25Q_VALIDATION_BASE_ADDR + offset, expectedValue, readBuf[offset]);
167bool W25QValidation::runPatternTest() {
168 static const uint8_t patterns[] = {
169 0x00u, 0xFFu, 0x55u, 0xAAu,
170 0x01u, 0x02u, 0x04u, 0x08u, 0x10u, 0x20u, 0x40u, 0x80u,
171 0xFEu, 0xFDu, 0xFBu, 0xF7u, 0xEFu, 0xDFu, 0xBFu, 0x7Fu
173 uint32_t patternCount = (uint32_t)(
sizeof(patterns) /
sizeof(patterns[0]));
176 _report.
failedTest = W25Q_VALIDATION_TEST_PATTERN;
178 printf(
"[TEST 3] %s\r\n", getTestName(W25Q_VALIDATION_TEST_PATTERN));
180 for (uint32_t patternIndex = 0; patternIndex < patternCount; patternIndex++) {
181 uint8_t expectedValue = patterns[patternIndex];
187 bool erased = _flash.
eraseSector(W25Q_VALIDATION_BASE_ADDR);
189 recordFailure(W25Q_VALIDATION_TEST_PATTERN, W25Q_VALIDATION_PHASE_ERASE,
190 W25Q_VALIDATION_BASE_ADDR, expectedValue, 0);
195 uint8_t writeBuf[W25Q_VALIDATION_PATTERN_TEST_SIZE];
196 for (uint32_t i = 0; i <
sizeof(writeBuf); i++) {
197 writeBuf[i] = expectedValue;
201 bool written = _flash.
writeBuffer(W25Q_VALIDATION_BASE_ADDR, writeBuf,
sizeof(writeBuf));
203 recordFailure(W25Q_VALIDATION_TEST_PATTERN, W25Q_VALIDATION_PHASE_FILL,
204 W25Q_VALIDATION_BASE_ADDR, expectedValue, 0);
209 _report.
failedPhase = W25Q_VALIDATION_PHASE_VERIFY;
210 uint8_t readBuf[W25Q_VALIDATION_PATTERN_TEST_SIZE];
211 bool readOk = _flash.
readBuffer(W25Q_VALIDATION_BASE_ADDR, readBuf,
sizeof(readBuf));
213 recordFailure(W25Q_VALIDATION_TEST_PATTERN, W25Q_VALIDATION_PHASE_VERIFY,
214 W25Q_VALIDATION_BASE_ADDR, expectedValue, 0);
219 for (uint32_t offset = 0; offset <
sizeof(readBuf); offset++) {
220 if (readBuf[offset] != expectedValue) {
221 recordFailure(W25Q_VALIDATION_TEST_PATTERN, W25Q_VALIDATION_PHASE_VERIFY,
222 W25Q_VALIDATION_BASE_ADDR + offset, expectedValue, readBuf[offset]);
228 printf(
" [%2lu/%2lu] Pattern 0x%02X PASS\r\n",
229 (
unsigned long)(patternIndex + 1), (
unsigned long)patternCount, expectedValue);
236bool W25QValidation::runPageBoundaryTest() {
238 _report.
failedTest = W25Q_VALIDATION_TEST_PAGE_BOUNDARY;
241 printf(
"[TEST 4] %s\r\n", getTestName(W25Q_VALIDATION_TEST_PAGE_BOUNDARY));
243 bool erased = _flash.
eraseSector(W25Q_VALIDATION_BASE_ADDR);
245 recordFailure(W25Q_VALIDATION_TEST_PAGE_BOUNDARY, W25Q_VALIDATION_PHASE_ERASE,
246 W25Q_VALIDATION_BASE_ADDR, 0, 0);
253 uint32_t startAddr = W25Q_VALIDATION_BASE_ADDR + (W25Q_PAGE_SIZE - 128u);
255 uint8_t writeBuf[W25Q_VALIDATION_BOUNDARY_TEST_SIZE];
256 for (uint32_t i = 0; i <
sizeof(writeBuf); i++) {
257 writeBuf[i] = (uint8_t)(i & 0xFFu);
261 bool written = _flash.
writeBuffer(startAddr, writeBuf,
sizeof(writeBuf));
263 recordFailure(W25Q_VALIDATION_TEST_PAGE_BOUNDARY, W25Q_VALIDATION_PHASE_FILL,
269 _report.
failedPhase = W25Q_VALIDATION_PHASE_VERIFY;
270 uint8_t readBuf[W25Q_VALIDATION_BOUNDARY_TEST_SIZE];
271 bool readOk = _flash.
readBuffer(startAddr, readBuf,
sizeof(readBuf));
273 recordFailure(W25Q_VALIDATION_TEST_PAGE_BOUNDARY, W25Q_VALIDATION_PHASE_VERIFY,
279 for (uint32_t offset = 0; offset <
sizeof(readBuf); offset++) {
280 uint8_t expectedValue = (uint8_t)(offset & 0xFFu);
281 if (readBuf[offset] != expectedValue) {
282 recordFailure(W25Q_VALIDATION_TEST_PAGE_BOUNDARY, W25Q_VALIDATION_PHASE_VERIFY,
283 startAddr + offset, expectedValue, readBuf[offset]);
296 printf(
"W25Q validation start\r\n\r\n");
297 printf(
"WARNING: this suite is destructive -- it overwrites the first sector\r\n");
298 printf(
"(%lu bytes) starting at address 0x%06lX.\r\n\r\n",
299 (
unsigned long)W25Q_SECTOR_SIZE, (
unsigned long)W25Q_VALIDATION_BASE_ADDR);
301 bool ok = runErasedStateTest();
305 ok = runSmallRangeTest();
310 ok = runPatternTest();
315 ok = runPageBoundaryTest();
319 printf(
"\r\nW25Q validation complete: PASS\r\n");
321 printf(
"\r\nW25Q validation complete: FAIL\r\n");
STM32 HAL SPI1 driver for a Winbond W25Q-series flash chip (Adafruit 5632/5633/5634),...
bool eraseSector(uint32_t addr)
Erases the single 4KB sector containing the given address.
bool readBuffer(uint32_t addr, uint8_t *buf, uint32_t len)
Reads len bytes starting at addr into buf.
bool writeBuffer(uint32_t addr, const uint8_t *data, uint32_t len)
Writes len bytes starting at addr, paging internally at 256-byte boundaries as the chip's Page Progra...
const w25qValidationReport_t * GetReport() const
Gets the most recent validation report without rerunning tests.
const w25qValidationReport_t * RunAll()
Runs every validation test in sequence, stopping at the first failure, printing progress and results ...
W25QValidation(W25QFlashSPI &flash)
Constructs the validation suite against an already-initialized driver.
Detailed validation report, persistent for the life of the W25QValidation instance.
uint32_t failedOffset
Byte offset (from W25Q_VALIDATION_BASE_ADDR) where the failure was detected.
uint8_t actualValue
Value actually read back at failedOffset.
uint8_t expectedValue
Value expected to be read back at failedOffset.
w25qValidationTestId_t failedTest
Which test failed, or NONE if status is PASS.
w25qValidationStatus_t status
Overall PASS/FAIL outcome of the last RunAll().
uint32_t testsRun
Count of tests that started running, whether they passed or failed.
w25qValidationPhase_t failedPhase
Which phase of failedTest failed (erase/fill/verify).