Callisto4Bootloader: test/c4_qspi_test.c Source File

Callisto4Bootloader

c4_qspi_test.c
Go to the documentation of this file.
1
11 /*******************************************************************************
12 * Includes
13 ******************************************************************************/
14
15 #include "c4_qspi_test.h"
16 #include "c4_qspi.h"
17 #include "c4_privilege_modes.h"
18
19 #include "lib/c4_qspi_types.h"
20
21 #include <stddef.h>
22
23 /*******************************************************************************
24 * Defines
25 ******************************************************************************/
26 #ifndef min
27 # define min(a, b) ((a)<(b)?(a):(b))
28 #endif
29 /*******************************************************************************
30 * Structures
31 ******************************************************************************/
32
33 /*******************************************************************************
34 * Prototypes
35 ******************************************************************************/
36
52 exit_code_t doWriteTest(uint32_t startSector, uint32_t offset, const char *pattern, uint32_t noBytes);
53
67 exit_code_t doReadTest(uint32_t startSector, uint32_t offset, uint32_t noBytes);
68
69
83 exit_code_t doEraseTest(uint32_t startSector, uint32_t offset, uint32_t noBytes);
84
85 /*******************************************************************************
86 * Variables
87 ******************************************************************************/
88 extern flexspi_nor_config_t sFlashConfig;
89 extern bool FLASH_INITIALISED;
90
91 /*******************************************************************************
92 * Interface Implementation
93 ******************************************************************************/
94 exit_code_t QSPI_test(void)
95 {
96 exit_code_t rc = C4_ERR_OK;
97
98 uint32_t sector = 512;
99
100 C4_PRINT("%s\n", __FUNCTION__);
101
102 if (!FLASH_INITIALISED)
103 {
104 C4_PRINT("QSPI uninitialised\n");
105 }
106 else
107 {
108 C4_PRINT("QSPI must be uninitialised at the start of tests.\n");
109 rc = C4_ERR_UNINITIALISED;
110 }
111
112 uint8_t testBuf[10];
113 C4_PRINT("Testing uninitialised calls\n");
114 if ((C4_ERR_OK == rc) &&
115 (C4_ERR_UNINITIALISED != C4_QSPI_write(FlexSPI_AMBA_BASE, 4, (uint8_t *)"Uninitialised")))
116 {
117 C4_PRINT("Uninitialised call to write test fail\n");
118 rc = C4_ERR_UNINITIALISED;
119 }
120 if ((C4_ERR_OK == rc) &&
121 (C4_ERR_UNINITIALISED != C4_QSPI_read(FlexSPI_AMBA_BASE, 4, testBuf)))
122 {
123 C4_PRINT("Uninitialised call to read test fail\n");
124 rc = C4_ERR_UNINITIALISED;
125 }
126 if ((C4_ERR_OK == rc) &&
127 (C4_ERR_UNINITIALISED != C4_QSPI_erase(FlexSPI_AMBA_BASE, 4)))
128 {
129 C4_PRINT("Uninitialised call to erase test fail\n");
130 rc = C4_ERR_UNINITIALISED;
131 }
132
133 // Now call initialise function.
134 rc = C4_QSPI_init();
135
136 C4_PRINT("Testing write range\n");
137 // test write before QSPI range is rejected.
138 if ((C4_ERR_OK == rc) &&
139 (C4_ERR_RANGE != C4_QSPI_write(FlexSPI_AMBA_BASE-1, 4, (uint8_t *)"fail")))
140 {
141 C4_PRINT("Write before flash test fail\n");
142 rc = C4_ERR_RANGE;
143 }
144 // test write after QSPI range is rejected.
145 if ((C4_ERR_OK == rc) &&
146 (C4_ERR_RANGE != C4_QSPI_write(FlexSPI_AMBA_BASE + sFlashConfig.memConfig.sflashA1Size-3, 4, (uint8_t *)"fail")))
147 {
148 C4_PRINT("Write after flash test fail\n");
149 rc = C4_ERR_RANGE;
150 }
151
152 C4_PRINT("Testing read range\n");
153 // test read before QSPI range is rejected.
154 if ((C4_ERR_OK == rc) &&
155 (C4_ERR_RANGE != C4_QSPI_read(FlexSPI_AMBA_BASE-1, 4, testBuf)))
156 {
157 C4_PRINT("Read before flash test fail\n");
158 rc = C4_ERR_RANGE;
159 }
160 // test read after QSPI range is rejected.
161 if ((C4_ERR_OK == rc) &&
162 (C4_ERR_RANGE != C4_QSPI_read(FlexSPI_AMBA_BASE + sFlashConfig.memConfig.sflashA1Size-3, 4, testBuf)))
163 {
164 C4_PRINT("Read after flash test fail\n");
165 rc = C4_ERR_RANGE;
166 }
167 C4_PRINT("Testing erase range\n");
168 // test erase before QSPI range is rejected.
169 if ((C4_ERR_OK == rc) &&
170 (C4_ERR_RANGE != C4_QSPI_erase(FlexSPI_AMBA_BASE-1, 4)))
171 {
172 C4_PRINT("Erase before flash test fail\n");
173 rc = C4_ERR_RANGE;
174 }
175 // test erase after QSPI range is rejected.
176 if ((C4_ERR_OK == rc) &&
177 (C4_ERR_RANGE != C4_QSPI_erase(FlexSPI_AMBA_BASE + sFlashConfig.memConfig.sflashA1Size-3, 4)))
178 {
179 C4_PRINT("Erase after flash test fail\n");
180 rc = C4_ERR_RANGE;
181 }
182
183 if (C4_ERR_OK == rc)
184 {
185 C4_PRINT("Testing flash functions\n");
186 C4_PRINT("Case 0 write whole sector %ld\n", sector);
187 rc = doWriteTest(sector, 0, "0", 0);
188 }
189 ++sector;
190
191 // case 1 write at the beginning of a sector
192 if (C4_ERR_OK == rc)
193 {
194 C4_PRINT("Case 1 write bytes at beginning of sector %ld\n", sector);
195 rc = doWriteTest(sector, 0, "1", 1);
196 ++sector;
197 }
198
199 // case 2 write at the end of a sector
200 if (C4_ERR_OK == rc)
201 {
202 C4_PRINT("Case 2 write bytes at end of sector %ld\n", sector);
203 rc = doWriteTest(sector, C4_FLASH_SECTOR_SIZE - 3, "2", 3);
204 ++sector;
205 }
206
207 // case 3 write bytes in the middle of a sector
208 if (C4_ERR_OK == rc)
209 {
210 C4_PRINT("Case 3 write bytes in the middle of sector %ld\n", sector);
211 char three[513];
212 memset(three, '3', 512);
213 three[512] = '\0';
214 rc = doWriteTest(sector, C4_FLASH_SECTOR_SIZE / 2, three, 1234);
215 ++sector;
216 }
217
218 // case 4 write spanning two sectors with one byte in second
219 if (C4_ERR_OK == rc)
220 {
221 C4_PRINT("Case 4 write bytes at spanning two partial sectors from %ld\n", sector);
222 char four[C4_FLASH_SECTOR_SIZE / 2 + 2];
223 memset(four, '4', C4_FLASH_SECTOR_SIZE / 2 + 1);
224 four[C4_FLASH_SECTOR_SIZE / 2] = '\0';
225 rc = doWriteTest(sector, C4_FLASH_SECTOR_SIZE / 2, four, C4_FLASH_SECTOR_SIZE / 2 + 1);
226 sector+=2;
227 }
228
229 // case 5 write spanning two complete sectors
230 if (C4_ERR_OK == rc)
231 {
232 C4_PRINT("Case 5 write bytes spanning two complete sectors from %ld\n", sector);
233 char five[C4_FLASH_SECTOR_SIZE * 2 + 1];
234 memset(five, '5', C4_FLASH_SECTOR_SIZE * 2);
235 five[C4_FLASH_SECTOR_SIZE * 2] = '\0';
236 rc = doWriteTest(sector, 0, five, C4_FLASH_SECTOR_SIZE * 2);
237 sector+=2;
238 }
239
240 // case 6 write spanning three sectors
241 if (C4_ERR_OK == rc)
242 {
243 C4_PRINT("Case 6 write bytes spanning three sectors from %ld\n", sector);
244 char six[C4_FLASH_SECTOR_SIZE * 2 + 1];
245 memset(six, '6', C4_FLASH_SECTOR_SIZE * 2);
246 six[C4_FLASH_SECTOR_SIZE * 2] = '\0';
247 rc = doWriteTest(sector, 1, six, C4_FLASH_SECTOR_SIZE * 2);
248 sector+=3;
249 }
250
251 // case 7 write spanning four sectors
252 if (C4_ERR_OK == rc)
253 {
254 C4_PRINT("Case 7 write bytes spanning four sectors from %ld\n", sector);
255 char seven[C4_FLASH_SECTOR_SIZE * 3 + 1];
256 memset(seven, '7', C4_FLASH_SECTOR_SIZE * 3);
257 seven[C4_FLASH_SECTOR_SIZE * 3] = '\0';
258 rc = doWriteTest(sector, 10, seven, C4_FLASH_SECTOR_SIZE * 3);
259 sector+=4;
260 }
261
262 if (C4_ERR_OK == rc)
263 {
264 C4_PRINT("Case 8 read bytes sector%ld\n", sector);
265 rc = doReadTest(sector, 10, 100);
266 ++sector;
267 }
268
269 return rc;
270 }
271
272 /*************************************************************************
273 * Local Functions
274 ************************************************************************/
275
276
277 exit_code_t doWriteTest(uint32_t startSector, uint32_t offset, const char *pattern, uint32_t noBytes)
278 {
279 exit_code_t rc = C4_ERR_OK;
280 const uintptr_t mapAddr = startSector * C4_FLASH_SECTOR_SIZE + FlexSPI_AMBA_BASE;
281
282 // calculate number of bytes involved in this test i.e. number of sectors used * sector size.
283 // startByte = offset ->
284 // firstByte = (startByte / C4_FLASH_SECTOR_SIZE) * C4_FLASH_SECTOR_SIZE
285 // endbyte = offset + noBytes - 1
286 // lastByte = ((endByte / C4_FLASH_SECTOR_SIZE) + 1) * C4_FLASH_SECTOR_SIZE) - 1)
287 //
288 // If noBytes == 0 then the test length is one sector
289
290 const uint32_t testLen = (noBytes ?
291 ( (offset + noBytes - 1) / C4_FLASH_SECTOR_SIZE - offset / C4_FLASH_SECTOR_SIZE + 1) * C4_FLASH_SECTOR_SIZE :
292 C4_FLASH_SECTOR_SIZE);
293 C4_PRINT("%s(%ld, %ld, 0x%p, %ld) - testing bytes %ld\n",
294 // C4_PRINT("%s(%d, %d, \"%s\", %d) - testing bytes %d\n",
295 __FUNCTION__, startSector, offset, pattern, noBytes, testLen);
296 char buffer[testLen+1];
297
298 // clear sector with '0's
299 memset(buffer, '0', testLen);
300 buffer[testLen] = '\0';
301 // C4_PRINT("Clearing sectors with \"%s\"\n %d @ 0x%p\n", buffer, testLen, buffer);
302 rc = C4_QSPI_write(mapAddr, testLen, (uint8_t *)buffer);
303
304 // write pattern
305 uint32_t bytesWritten = 0;
306 while (noBytes > bytesWritten)
307 {
308 uint32_t bytesToWrite = min(noBytes - bytesWritten, strlen(pattern));
309 C4_PRINT("LINE %d noBytes %ld bytesWritten %ld bytesToWrite %ld\n", __LINE__, noBytes, bytesWritten, bytesToWrite);
310 rc = C4_QSPI_write(mapAddr + offset + bytesWritten, bytesToWrite, (uint8_t *)pattern);
311 bytesWritten += bytesToWrite;
312 }
313
314 // test region before pattern - up to offset
315 if ((offset > 0) && (C4_ERR_OK == rc))
316 {
317 C4_PRINT("Test before pattern 0x%p-0x%p\n", (void *)mapAddr, (void *)(mapAddr + offset - 1));
318 if ( (rc = memcmp((void *)(mapAddr), buffer, offset)) )
319 {
320 C4_PRINT("LINE %d Memory test failed before pattern %d\n", __LINE__, rc);
321 rc = C4_ERR_FAILED;
322 }
323 }
324
325 //test pattern - from offset to offset + noBytes - 1
326 if ((noBytes > 0) && (C4_ERR_OK == rc))
327 {
328 C4_PRINT("Test pattern 0x%p-0x%p\n", (void *)(mapAddr + offset), (void *)(mapAddr + offset + noBytes - 1));
329 uint32_t bytesRead = 0;
330 while (noBytes > bytesRead)
331 {
332 uint32_t bytesToRead = min(noBytes - bytesRead, strlen(pattern));
333 if( (rc = memcmp((void *)(mapAddr + offset + bytesRead), pattern, bytesToRead)) )
334 {
335 C4_PRINT("LINE %d Memory test failed inside pattern %d\n", __LINE__, rc);
336 rc = C4_ERR_FAILED;
337 break;
338 }
339 bytesRead += bytesToRead;
340 }
341 }
342
343 //test region after pattern - from offset + noBytes to testLen
344 if ((offset + noBytes < testLen) && (C4_ERR_OK == rc))
345 {
346 C4_PRINT("Test after pattern 0x%p-0x%p\n", (void *)(mapAddr + offset + noBytes), (void *)(mapAddr + testLen - 1));
347 if ( (rc = memcmp((void *)(mapAddr + offset + noBytes), buffer, testLen - offset - noBytes)) )
348 {
349 C4_PRINT("LINE %d Memory test failed after pattern %d\n", __LINE__, rc);
350 rc = C4_ERR_FAILED;
351 }
352 }
353 return rc;
354 }
355
356
357 /*************************************************************************/
358 const char loremIpsum[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent ut massa odio. Maecenas non porta neque, facilisis iaculis nulla. In faucibus congue semper. Donec commodo tempus erat, in auctor lectus. Donec scelerisque malesuada venenatis. Sed est lacus, malesuada at est et, congue iaculis ex. Nulla non mollis velit. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nullam iaculis pharetra tincidunt. Praesent tincidunt rhoncus lacus, at mattis libero efficitur sit amet. Nulla scelerisque ante ex. Pellentesque lobortis enim augue, a imperdiet nunc luctus pretium. Donec pellentesque mi diam, hendrerit molestie magna laoreet ut. Donec condimentum ipsum urna, vitae consectetur augue pharetra vulputate. Fusce consequat, justo vestibulum pharetra placerat, sapien lorem dapibus magna, et hendrerit elit eros at nibh. Praesent vitae condimentum tortor.\n"\
359 "Phasellus in mattis leo, et vulputate dolor. In tortor sem, ultrices facilisis ante non, lacinia tempus ante. Maecenas pretium neque sed sapien porttitor tincidunt. Sed vestibulum rutrum varius. Donec fringilla commodo ligula quis tristique. Suspendisse dapibus sollicitudin accumsan. Ut lobortis ut elit nec ultrices. Pellentesque eget egestas lacus, quis dictum mi. Praesent pretium quam vel tortor venenatis, quis iaculis enim feugiat. Quisque sodales neque ut ex scelerisque, ut ornare odio rutrum. Duis ac dolor vel dui dictum facilisis. Cras pretium sem vitae sem facilisis varius. Aenean lobortis mauris felis, eget bibendum augue sodales eu. Quisque at elit massa. Aenean dignissim tortor vitae dui tincidunt, in pellentesque magna lacinia.\n"\
360 "Nulla facilisi. Etiam bibendum diam vestibulum, lacinia magna in, blandit neque. Pellentesque rhoncus enim eget lectus vulputate placerat. Pellentesque pharetra finibus rhoncus. Mauris eget elit vitae lectus viverra tristique. Phasellus eleifend ipsum eget placerat rhoncus. Aenean viverra felis eu ipsum hendrerit, non pulvinar nisl molestie. Nullam varius nulla eros, at congue velit malesuada eu. In sapien ligula, rhoncus vel nulla vitae, aliquet posuere quam. Donec a metus nec libero egestas blandit eleifend in libero. In vel est viverra, pharetra enim at, posuere arcu.\n"\
361 "Donec nec porttitor massa. Fusce nec pellentesque nibh. Pellentesque ullamcorper tortor nulla, eu tempor massa sodales commodo. Praesent facilisis felis at dolor aliquam rutrum. Aenean metus risus, dictum et pretium vitae, porta quis diam. Nunc gravida ipsum efficitur ex ullamcorper, sit amet dictum ipsum vestibulum. Morbi ac posuere ligula, ut vulputate dolor. Praesent vitae lorem purus. In ultricies urna enim, in suscipit purus dapibus eu. Quisque nec purus lobortis quam venenatis tempus eu ut libero. Praesent vitae diam faucibus, laoreet neque sed, posuere neque. Sed a auctor enim, vel auctor odio.\n"\
362 "Aenean sodales nulla a eros porttitor, ac vestibulum sem vulputate. Quisque dui sapien, hendrerit ac neque sed, egestas placerat nisi. Sed facilisis odio ac libero pellentesque consectetur. Maecenas lobortis consectetur tortor, vitae aliquet tellus lobortis nec. Nullam imperdiet commodo leo, et posuere neque aliquet vel. Maecenas porttitor ligula at feugiat lacinia. Maecenas et volutpat risus. Nullam condimentum ante lacus, ac tristique libero commodo ut. Nulla ac blandit purus. Nam a ullamcorper enim, id mattis mi. Aliquam maximus dolor elit, vel venenatis nisi ultricies faucibus. Duis eget nisi id neque efficitur faucibus eu at massa.\n"\
363 "In pellentesque lectus ut justo bibendum, non mattis turpis aliquam. Quisque egestas quis ligula id malesuada. Quisque nec faucibus mauris, sed blandit diam. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam quis leo orci. Donec tincidunt id risus eget posuere. Duis nec commodo lectus, feugiat egestas dolor. Praesent faucibus accumsan facilisis. Vivamus congue nec libero nec placerat. Etiam vel eleifend velit. Maecenas magna lectus, mollis at turpis id, convallis dictum orci. Aliquam ac leo euismod, vehicula nulla eu, ultricies purus. Morbi eget arcu vel diam sodales vulputate. Cras hendrerit magna est, non ullamcorper libero fermentum nec. In hac habitasse platea dictumst.\n"\
364 "Aliquam elit diam, lobortis vel commodo ut, convallis nec turpis. Fusce accumsan, eros eget egestas tempor, leo urna laoreet mi, eu dictum nisi augue nec justo. Morbi sodales fringilla luctus. Nullam rhoncus lectus risus. Integer et dignissim purus, id aliquet enim. Phasellus fringilla, magna eu finibus imperdiet, nibh quam consectetur velit, vitae tristique turpis augue vel ex. Quisque id lacinia quam. Aenean vitae ornare risus, mattis pretium purus. Sed tortor urna, malesuada eget tristique pharetra, semper eleifend nisl.\n"\
365 "Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed et metus facilisis, tincidunt leo eget, dapibus tortor. Vivamus pulvinar massa tellus, non varius purus convallis sed. Nulla eleifend, ligula et vulputate sagittis, velit turpis vulputate odio, eget hendrerit risus sapien vitae velit. Donec eu nulla nec tortor malesuada congue. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In tempor, lacus eu ornare dapibus, magna est pretium lectus, ac mattis felis urna nec quam. Mauris in ullamcorper nisi. Sed eu orci tellus.\n"\
366 "Duis ac dui felis. Quisque dictum libero at dictum lacinia. Morbi efficitur id leo vel iaculis. Mauris tempor leo volutpat odio auctor, quis consequat sapien pharetra. Aliquam dignissim arcu diam, ac consequat risus vulputate et. Fusce condimentum ut ipsum aliquet iaculis. Nulla accumsan luctus massa ac faucibus. Duis sagittis porta urna, a imperdiet sapien. Nulla mi leo, fermentum non quam vel, tristique cursus felis. Cras eu lorem vitae mi finibus iaculis.\n"\
367 "Morbi cursus dapibus ornare. Nullam viverra lorem lacus, et varius ipsum fermentum in. Phasellus nulla nunc, iaculis at porta eget, tristique vel lacus. Nullam mi velit, maximus eget nunc maximus, fermentum pellentesque est. Nam sollicitudin, neque eu cursus aliquet, nisl odio condimentum sapien, vel volutpat ante nisi vitae libero. Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse maximus porttitor nibh quis ornare. Nunc pulvinar auctor purus non pellentesque.\n"\
368 "Quisque nec vulputate leo. In elementum massa vel varius ullamcorper. Ut ultricies vulputate tortor, at viverra erat condimentum at. Ut suscipit tincidunt semper. Vivamus vel fringilla elit. Morbi varius cursus lacus consectetur iaculis. Integer id enim et sapien aliquet fringilla vel eu velit. Mauris sed tincidunt augue. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Nunc convallis ac tortor eu tincidunt. Nunc pulvinar imperdiet nisl ut ullamcorper. Vestibulum convallis pulvinar massa. Maecenas molestie nisi diam, et vestibulum dolor viverra at.\n"\
369 "Aliquam finibus turpis sit amet orci sodales, eget lacinia tellus interdum. Nulla vitae libero eget dui elementum hendrerit. Phasellus dictum pretium sem, nec viverra felis vestibulum ut. Aenean ipsum lorem, pharetra sed aliquet sed, sagittis vel arcu. Nam ac tellus lacinia velit ultricies finibus. Aenean vel commodo odio, ac scelerisque tortor. Fusce odio est, bibendum ac commodo ac, faucibus sed nibh. Nunc eget ligula quam. Fusce dictum vel eros ut porta.\n"\
370 "Integer tincidunt eget lacus ac ultrices. Interdum et malesuada fames ac ante ipsum primis in faucibus. Suspendisse lorem odio, lacinia vel eros in, commodo eleifend eros. Pellentesque sodales, lacus eu placerat tempus, purus dui venenatis risus, at dignissim libero turpis tincidunt mi. Nunc volutpat semper eros, consequat pharetra orci imperdiet in. Donec condimentum nisi nec ipsum porttitor fringilla. Etiam a quam quam. Fusce ut fermentum turpis, eu egestas nulla. Ut nec tristique nisl. Sed orci lacus, porttitor at purus vel, pharetra dignissim nunc. Proin aliquet, mi quis euismod rutrum, ligula nunc aliquam dolor, ut gravida libero turpis in diam. Morbi in turpis dictum, volutpat erat vel, condimentum enim. Curabitur finibus est ut erat tincidunt, sit amet tincidunt lacus tristique. Morbi convallis elementum turpis, vitae ultrices turpis ultricies quis. Etiam sodales diam sit amet consequat varius.\n"\
371 "Phasellus suscipit sapien at pulvinar tincidunt. Nam non pharetra mauris. Praesent nec ligula mattis, mollis lacus vel, tincidunt libero. Nam quis pretium ligula, quis sodales mauris. Nullam mollis auctor elementum. Vestibulum justo mi, aliquam venenatis viverra eu, blandit ut eros. Maecenas euismod tellus neque, quis blandit augue molestie nec. Phasellus quis erat vitae velit rutrum sodales congue eu nisl. Sed eu nibh eu est bibendum sollicitudin ut ac dolor. Ut posuere arcu eu leo lacinia eleifend. Aenean varius ex eu suscipit varius. Nulla et mattis felis. Suspendisse ultrices ut metus non ultrices. Ut eget bibendum nulla.\n"\
372 "Sed semper dapibus interdum. Mauris elementum lorem et enim blandit, vel aliquet tortor porta. Etiam diam lacus, pulvinar non tempus vel, volutpat et lacus. Maecenas nec vulputate ex, at lobortis eros. Morbi in ante felis. Fusce vel tincidunt velit. Pellentesque quis velit diam. Nullam accumsan mi augue, in luctus metus sagittis ut. Morbi tincidunt nisi a nisi lobortis imperdiet.\n"\
373 "Integer eu fringilla urna. Curabitur fermentum orci euismod tellus rutrum, at ullamcorper quam sollicitudin. Duis gravida erat at ultricies vestibulum. Morbi a lectus quis lectus vestibulum molestie vel sit amet ante. Nulla porttitor, est a auctor vulputate, libero ipsum faucibus mauris, faucibus egestas sapien orci et lacus. Maecenas vehicula erat eget magna pharetra, ut rhoncus turpis scelerisque. Integer laoreet commodo lorem, ac vulputate orci rhoncus eget. Praesent ultricies elit eu nunc malesuada tincidunt. Donec eget ornare ex. Etiam elit lacus, rhoncus at nisi maximus, feugiat elementum orci. Proin molestie tellus eget massa facilisis, eu auctor quam ultrices. Sed finibus, dui sed ultricies aliquet, nunc magna dolor.\n";
374
375
376 /*************************************************************************/
377
378 exit_code_t doReadTest(uint32_t startSector, uint32_t offset, uint32_t noBytes)
379 {
380 exit_code_t rc = C4_ERR_OK;
381 const uintptr_t mapAddr = startSector * C4_FLASH_SECTOR_SIZE + FlexSPI_AMBA_BASE;
382
383 // calculate number of bytes involved in this test i.e. number of sectors used * sector size.
384 // startByte = offset ->
385 // firstByte = (startByte / C4_FLASH_SECTOR_SIZE) * C4_FLASH_SECTOR_SIZE
386 // endbyte = offset + noBytes - 1
387 // lastByte = ((endByte / C4_FLASH_SECTOR_SIZE) + 1) * C4_FLASH_SECTOR_SIZE) - 1)
388 //
389 // If noBytes == 0 then the test length is one sector
390
391 const uint32_t testLen = (noBytes ?
392 ( (offset + noBytes - 1) / C4_FLASH_SECTOR_SIZE - offset / C4_FLASH_SECTOR_SIZE + 1) * C4_FLASH_SECTOR_SIZE :
393 C4_FLASH_SECTOR_SIZE);
394
395 C4_PRINT("%s(%ld, %ld, %ld) - testing bytes %ld\n",
396 __FUNCTION__, startSector, offset, noBytes, testLen);
397 uint8_t buffer[noBytes+1];
398
399 // write some data
400 rc = C4_QSPI_write(mapAddr, testLen, (uint8_t *)loremIpsum);
401
402 // read pattern
403 rc = C4_QSPI_read(mapAddr + offset, noBytes, buffer);
404
405
406 //test that data read matches the text that we wrote - from offset to offset + noBytes - 1
407 if (noBytes > 0)
408 {
409 C4_PRINT("Test text 0x%p-0x%p\n", (void *)(mapAddr + offset), (void *)(mapAddr + offset + noBytes - 1));
410 if( (rc = memcmp((void *)(loremIpsum + offset), buffer, noBytes)) )
411 {
412 C4_PRINT("LINE %d Memory test failed inside pattern %d\n", __LINE__, rc);
413 rc = C4_ERR_FAILED;
414 }
415 }
416 return rc;
417 }
418
419 /*************************************************************************/
420
421 exit_code_t doEraseTest(uint32_t startSector, uint32_t offset, uint32_t noBytes)
422 {
423 exit_code_t rc = C4_ERR_OK;
424
425 const uintptr_t mapAddr = startSector * C4_FLASH_SECTOR_SIZE + FlexSPI_AMBA_BASE;
426
427 // calculate number of bytes involved in this test i.e. number of sectors used * sector size.
428 // startByte = offset ->
429 // firstByte = (startByte / C4_FLASH_SECTOR_SIZE) * C4_FLASH_SECTOR_SIZE
430 // endbyte = offset + noBytes - 1
431 // lastByte = ((endByte / C4_FLASH_SECTOR_SIZE) + 1) * C4_FLASH_SECTOR_SIZE) - 1)
432 //
433 // If noBytes == 0 then the test length is one sector
434
435 const uint32_t testLen = (noBytes ?
436 ( (offset + noBytes - 1) / C4_FLASH_SECTOR_SIZE - offset / C4_FLASH_SECTOR_SIZE + 1) * C4_FLASH_SECTOR_SIZE :
437 C4_FLASH_SECTOR_SIZE);
438
439 C4_PRINT("%s(%ld, %ld, %ld) - testing bytes %ld\n",
440 __FUNCTION__, startSector, offset, noBytes, testLen);
441 char buffer[testLen+1];
442
443 // clear sector with '0's
444 memset(buffer, '0', testLen);
445 buffer[testLen] = '\0';
446 // C4_PRINT("Clearing sectors with \"%s\"\n %d @ 0x%p\n", buffer, testLen, buffer);
447 rc = C4_QSPI_write(mapAddr, testLen, (uint8_t *)buffer);
448
449 // perform erase
450 rc = C4_QSPI_erase(mapAddr + offset, noBytes);
451
452 // test region before erase - up to offset
453 if ((offset > 0) && (C4_ERR_OK == rc))
454 {
455 C4_PRINT("Test before erase 0x%p-0x%p\n", (void *)(mapAddr), (void *)(mapAddr + offset - 1));
456 if ( (rc = memcmp((void *)(mapAddr), buffer, offset)) )
457 {
458 C4_PRINT("LINE %d Memory test failed before pattern %d\n", __LINE__, rc);
459 rc = C4_ERR_FAILED;
460 }
461 }
462
463 //test erase - from offset to offset + noBytes - 1
464 if ((noBytes > 0) && (C4_ERR_OK == rc))
465 {
466 C4_PRINT("Test erase 0x%p-0x%p\n", (void *)(mapAddr + offset), (void *)(mapAddr + offset + noBytes - 1));
467 uint8_t testBuf[noBytes+1];
468 memset(testBuf, 0xFFC, noBytes);
469 testBuf[noBytes] = '\0';
470
471 if( (rc = memcmp((void *)(mapAddr + offset), testBuf, noBytes)) )
472 {
473 C4_PRINT("LINE %d Memory test failed inside pattern %d\n", __LINE__, rc);
474 rc = C4_ERR_FAILED;
475 }
476 }
477
478 //test region after erase - from offset + noBytes to testLen
479 if ((offset + noBytes < testLen) && (C4_ERR_OK == rc))
480 {
481 C4_PRINT("Test after erase 0x%p-0x%p\n", (void *)(mapAddr + offset + noBytes), (void *)(mapAddr + testLen - 1));
482 if ( (rc = memcmp((void *)(mapAddr + offset + noBytes), buffer, testLen - offset - noBytes)) )
483 {
484 C4_PRINT("LINE %d Memory test failed after pattern %d\n", __LINE__, rc);
485 rc = C4_ERR_FAILED;
486 }
487 }
488
489 return rc;
490 }
C4_FLASH_SECTOR_SIZE
#define C4_FLASH_SECTOR_SIZE
Definition: c4_qspi_types.h:25
C4_QSPI_read
exit_code_t C4_QSPI_read(uintptr_t addr, size_t len, uint8_t *pData)
Read data from QSPI flash memory.
Definition: c4_qspi.c:184
FLASH_INITIALISED
bool FLASH_INITIALISED
Definition: c4_qspi.c:66
sFlashConfig
flexspi_nor_config_t sFlashConfig
Definition: c4_qspi.c:64
c4_qspi_types.h
Private header file for QSPI interface to allow definitions to be shared with test.
loremIpsum
const char loremIpsum[]
Definition: c4_qspi_test.c:352
C4_QSPI_write
exit_code_t C4_QSPI_write(uintptr_t addr, size_t len, const uint8_t *pData)
Write data to QSPI flash memory.
Definition: c4_qspi.c:230
c4_qspi.h
Interface to QSPI Flash.
exit_code_t
exit_code_t
Enumeration of error codes.
Definition: c4_error_codes.h:96
C4_QSPI_erase
exit_code_t C4_QSPI_erase(uintptr_t addr, size_t len)
Erase region in QSPI flash memory.
Definition: c4_qspi.c:123
FlexSPI_AMBA_BASE
#define FlexSPI_AMBA_BASE
Definition: MIMXRT1062.h:20168
_flexspi_nor_config::memConfig
flexspi_mem_config_t memConfig
Common memory configuration info via FlexSPI.
Definition: flexspi_nor_flash.h:186
QSPI_test
exit_code_t QSPI_test(void)
Run through a set of read and write tests on QSPI Flash.
Definition: c4_qspi_test.c:89
doReadTest
exit_code_t doReadTest(uint32_t startSector, uint32_t offset, uint32_t noBytes)
Test the QSPI flash read function.
Definition: c4_qspi_test.c:372
C4_PRINT
#define C4_PRINT(...)
Wrapper to call print as a privileged operation.
Definition: c4_privilege_modes.h:109
doWriteTest
exit_code_t doWriteTest(uint32_t startSector, uint32_t offset, const char *pattern, uint32_t noBytes)
Perform a write-read test on the QSPI flash functions.
Definition: c4_qspi_test.c:271
_FlexSPIConfig::sflashA1Size
uint32_t sflashA1Size
[0x050-0x053] Size of Flash connected to A1
Definition: fsl_flexspi.h:225
min
#define min(a, b)
Definition: c4_qspi_test.c:26
C4_QSPI_init
exit_code_t C4_QSPI_init(void)
Initialise the flexSPI interface to QSPI.
Definition: c4_qspi.c:74
c4_privilege_modes.h
Provide mechanisms to specify which stack to use and for the processor to operate in Unprivileged mod...
doEraseTest
exit_code_t doEraseTest(uint32_t startSector, uint32_t offset, uint32_t noBytes)
Test the QSPI flash byte-erase function.
Definition: c4_qspi_test.c:415
c4_qspi_test.h
_flexspi_nor_config
Definition: flexspi_nor_flash.h:184