STM32F429 demo update.
[lwext4.git] / demos / stm32f429_disco / main.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * - Redistributions of source code must retain the above copyright\r
10  *   notice, this list of conditions and the following disclaimer.\r
11  * - Redistributions in binary form must reproduce the above copyright\r
12  *   notice, this list of conditions and the following disclaimer in the\r
13  *   documentation and/or other materials provided with the distribution.\r
14  * - The name of the author may not be used to endorse or promote products\r
15  *   derived from this software without specific prior written permission.\r
16  *\r
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  */\r
28 \r
29 #include <config.h>\r
30 #include <hw_init.h>\r
31 \r
32 #include <stdio.h>\r
33 #include <stdlib.h>\r
34 #include <string.h>\r
35 #include <unistd.h>\r
36 #include <getopt.h>\r
37 #include <stdbool.h>\r
38 #include <time.h>\r
39 #include <unistd.h>\r
40 \r
41 #include <usb_msc_lwext4.h>\r
42 #include <ext4.h>\r
43 \r
44 /**@brief   Read-write size*/\r
45 #define READ_WRITE_SZIZE 1024 * 8\r
46 \r
47 /**@brief   Delay test (slower LCD scroll)*/\r
48 #define TEST_DELAY_MS    2000\r
49 \r
50 /**@brief   Input stream name.*/\r
51 char input_name[128] = "ext2";\r
52 \r
53 /**@brief   Read-write size*/\r
54 static int rw_szie  = READ_WRITE_SZIZE;\r
55 \r
56 /**@brief   Read-write size*/\r
57 static int rw_count = 100;\r
58 \r
59 /**@brief   Directory test count*/\r
60 static int dir_cnt  = 500;\r
61 \r
62 /**@brief   Static or dynamic cache mode*/\r
63 static bool cache_mode = false;\r
64 \r
65 /**@brief   Cleanup after test.*/\r
66 static bool cleanup_flag = false;\r
67 \r
68 /**@brief   Block device stats.*/\r
69 static bool bstat = false;\r
70 \r
71 /**@brief   Superblock stats.*/\r
72 static bool sbstat = false;\r
73 \r
74 /**@brief   File write buffer*/\r
75 static uint8_t wr_buff[READ_WRITE_SZIZE];\r
76 \r
77 /**@brief   File read buffer.*/\r
78 static uint8_t rd_buff[READ_WRITE_SZIZE];\r
79 \r
80 /**@brief   Block device handle.*/\r
81 static struct ext4_blockdev *bd;\r
82 \r
83 /**@brief   Block cache handle.*/\r
84 static struct ext4_bcache   *bc;\r
85 \r
86 static char* entry_to_str(uint8_t type)\r
87 {\r
88     switch(type){\r
89     case EXT4_DIRENTRY_UNKNOWN:\r
90         return "[UNK] ";\r
91     case EXT4_DIRENTRY_REG_FILE:\r
92         return "[FIL] ";\r
93     case EXT4_DIRENTRY_DIR:\r
94         return "[DIR] ";\r
95     case EXT4_DIRENTRY_CHRDEV:\r
96         return "[CHA] ";\r
97     case EXT4_DIRENTRY_BLKDEV:\r
98         return "[BLK] ";\r
99     case EXT4_DIRENTRY_FIFO:\r
100         return "[FIF] ";\r
101     case EXT4_DIRENTRY_SOCK:\r
102         return "[SOC] ";\r
103     case EXT4_DIRENTRY_SYMLINK:\r
104         return "[SYM] ";\r
105     default:\r
106         break;\r
107     }\r
108     return "[???]";\r
109 }\r
110 \r
111 static void dir_ls(const char *path)\r
112 {\r
113     int j = 0;\r
114     char sss[255];\r
115     ext4_dir d;\r
116     ext4_direntry *de;\r
117 \r
118     printf("********************\n");\r
119 \r
120     ext4_dir_open(&d, path);\r
121     de = ext4_dir_entry_get(&d, j++);\r
122     printf("ls %s\n", path);\r
123 \r
124     while(de){\r
125         memcpy(sss, de->name, de->name_length);\r
126         sss[de->name_length] = 0;\r
127         printf("%s", entry_to_str(de->inode_type));\r
128         printf("%s", sss);\r
129         printf("\n");\r
130         de = ext4_dir_entry_get(&d, j++);\r
131     }\r
132     printf("********************\n");\r
133     ext4_dir_close(&d);\r
134 }\r
135 \r
136 static void mp_stats(void)\r
137 {\r
138     struct ext4_mount_stats stats;\r
139     ext4_mount_point_stats("/mp/", &stats);\r
140 \r
141     printf("********************\n");\r
142     printf("ext4_mount_point_stats\n");\r
143     printf("inodes_count = %u\n", stats.inodes_count);\r
144     printf("free_inodes_count = %u\n", stats.free_inodes_count);\r
145     printf("blocks_count = %u\n", (uint32_t)stats.blocks_count);\r
146     printf("free_blocks_count = %u\n", (uint32_t)stats.free_blocks_count);\r
147     printf("block_size = %u\n", stats.block_size);\r
148     printf("block_group_count = %u\n", stats.block_group_count);\r
149     printf("blocks_per_group= %u\n", stats.blocks_per_group);\r
150     printf("inodes_per_group = %u\n", stats.inodes_per_group);\r
151     printf("volume_name = %s\n", stats.volume_name);\r
152 \r
153     printf("********************\n");\r
154 \r
155 }\r
156 \r
157 static void block_stats(void)\r
158 {\r
159     uint32_t i;\r
160 \r
161     printf("********************\n");\r
162     printf("ext4 blockdev stats\n");\r
163     printf("bdev->bread_ctr = %u\n", bd->bread_ctr);\r
164     printf("bdev->bwrite_ctr = %u\n", bd->bwrite_ctr);\r
165 \r
166 \r
167     printf("bcache->ref_blocks = %u\n", bc->ref_blocks);\r
168     printf("bcache->max_ref_blocks = %u\n", bc->max_ref_blocks);\r
169     printf("bcache->lru_ctr = %u\n", bc->lru_ctr);\r
170 \r
171     printf("\n");\r
172     for (i = 0; i < bc->cnt; ++i) {\r
173         printf("bcache->refctr[%d]= %u\n", i, bc->refctr[i]);\r
174     }\r
175 \r
176     printf("\n");\r
177     for (i = 0; i < bc->cnt; ++i) {\r
178         printf("bcache->lru_id[%d] = %u\n", i, bc->lru_id[i]);\r
179     }\r
180 \r
181     printf("\n");\r
182     for (i = 0; i < bc->cnt; ++i) {\r
183         printf("bcache->free_delay[%d] = %d\n", i, bc->free_delay[i]);\r
184     }\r
185 \r
186     printf("\n");\r
187     for (i = 0; i < bc->cnt; ++i) {\r
188         printf("bcache->lba[%d] = %u\n", i, (uint32_t)bc->lba[i]);\r
189     }\r
190 \r
191     printf("********************\n");\r
192 }\r
193 \r
194 static clock_t get_ms(void)\r
195 {\r
196     return hw_get_ms();\r
197 }\r
198 \r
199 static bool dir_test(int len)\r
200 {\r
201     ext4_file f;\r
202     int       r;\r
203     int       i;\r
204     char path[64];\r
205     clock_t diff;\r
206     clock_t stop;\r
207     clock_t start;\r
208     start = get_ms();\r
209 \r
210     printf("Directory create: /mp/dir1\n");\r
211     r = ext4_dir_mk("/mp/dir1");\r
212     if(r != EOK){\r
213         printf("Unable to create directory: /mp/dir1\n");\r
214         return false;\r
215     }\r
216 \r
217 \r
218 \r
219     printf("Add files to: /mp/dir1\n");\r
220     for (i = 0; i < len; ++i) {\r
221         sprintf(path, "/mp/dir1/f%d", i);\r
222         r = ext4_fopen(&f, path, "wb");\r
223         if(r != EOK){\r
224             printf("Unable to create file in directory: /mp/dir1 r = %d\n", r);\r
225             return false;\r
226         }\r
227     }\r
228 \r
229     stop =  get_ms();\r
230     diff = stop - start;\r
231     dir_ls("/mp/dir1");\r
232     printf("dir_test time: %d ms\n", (int)diff);\r
233     return true;\r
234 }\r
235 \r
236 \r
237 static bool file_test(void)\r
238 {\r
239     int r;\r
240     uint32_t  size;\r
241     ext4_file f;\r
242     int i;\r
243     clock_t start;\r
244     clock_t stop;\r
245     clock_t diff;\r
246     uint32_t kbps;\r
247     uint64_t size_bytes;\r
248     /*Add hello world file.*/\r
249     r = ext4_fopen(&f, "/mp/hello.txt", "wb");\r
250     r = ext4_fwrite(&f, "Hello World !\n", strlen("Hello World !\n"), 0);\r
251     r = ext4_fclose(&f);\r
252 \r
253 \r
254     printf("ext4_fopen: test1\n");\r
255 \r
256     start = get_ms();\r
257     r = ext4_fopen(&f, "/mp/test1", "wb");\r
258     if(r != EOK){\r
259         printf("ext4_fopen ERROR = %d\n", r);\r
260         return false;\r
261     }\r
262 \r
263     printf("ext4_write: %d * %d ...\n" , rw_szie, rw_count);\r
264     for (i = 0; i < rw_count; ++i) {\r
265 \r
266         memset(wr_buff, i % 10 + '0', rw_szie);\r
267 \r
268         r = ext4_fwrite(&f, wr_buff, rw_szie, &size);\r
269 \r
270         if((r != EOK) || (size != rw_szie))\r
271             break;\r
272 \r
273         if(!(i % (rw_count >> 3))){\r
274             printf("*");\r
275             fflush(stdout);\r
276         }\r
277     }\r
278 \r
279     if(i != rw_count){\r
280         printf("ERROR: rw_count = %d\n", i);\r
281         return false;\r
282     }\r
283 \r
284     printf(" OK\n");\r
285     stop = get_ms();\r
286     diff = stop - start;\r
287     size_bytes = rw_szie * rw_count;\r
288     size_bytes = (size_bytes * 1000) / 1024;\r
289     kbps = (size_bytes) / (diff + 1);\r
290     printf("file_test write time: %d ms\n", (int)diff);\r
291     printf("file_test write speed: %d KB/s\n", (int)kbps);\r
292     r = ext4_fclose(&f);\r
293     printf("ext4_fopen: test1\n");\r
294 \r
295 \r
296     start = get_ms();\r
297     r = ext4_fopen(&f, "/mp/test1", "r+");\r
298     if(r != EOK){\r
299         printf("ext4_fopen ERROR = %d\n", r);\r
300         return false;\r
301     }\r
302 \r
303     printf("ext4_read: %d * %d ...\n" , rw_szie, rw_count);\r
304 \r
305     for (i = 0; i < rw_count; ++i) {\r
306         memset(wr_buff, i % 10 + '0', rw_szie);\r
307         r = ext4_fread(&f, rd_buff, rw_szie, &size);\r
308 \r
309         if((r != EOK) || (size != rw_szie))\r
310             break;\r
311 \r
312         if(memcmp(rd_buff, wr_buff, rw_szie))\r
313             break;\r
314 \r
315 \r
316         if(!(i % (rw_count >> 3)))\r
317             printf("*");\r
318     }\r
319     if(i != rw_count){\r
320         printf("ERROR: rw_count = %d\n", i);\r
321         return false;\r
322     }\r
323     printf(" OK\n");\r
324     stop = get_ms();\r
325     diff = stop - start;\r
326     size_bytes = rw_szie * rw_count;\r
327     size_bytes = (size_bytes * 1000) / 1024;\r
328     kbps = (size_bytes) / (diff + 1);\r
329     printf("file_test read time: %d ms\n", (int)diff);\r
330     printf("file_test read speed: %d KB/s\n", kbps);\r
331     r = ext4_fclose(&f);\r
332 \r
333     return true;\r
334 \r
335 }\r
336 static void cleanup(void)\r
337 {\r
338     clock_t start;\r
339     clock_t stop;\r
340     clock_t diff;\r
341 \r
342     ext4_fremove("/mp/hello.txt");\r
343 \r
344     printf("cleanup: remove /mp/test1\n");\r
345     start = get_ms();\r
346     ext4_fremove("/mp/test1");\r
347     stop = get_ms();\r
348     diff = stop - start;\r
349     printf("cleanup: time: %d ms\n", (int)diff);\r
350 \r
351 \r
352     printf("cleanup: remove /mp/dir1\n");\r
353     start = get_ms();\r
354     ext4_dir_rm("/mp/dir1");\r
355     stop = get_ms();\r
356     diff = stop - start;\r
357     printf("cleanup: time: %d ms\n", (int)diff);\r
358 }\r
359 \r
360 static bool open_filedev(void)\r
361 {\r
362 \r
363     bd = ext4_usb_msc_get();\r
364     bc = ext4_usb_msc_cache_get();\r
365     if(!bd || !bc){\r
366         printf("Block device ERROR\n");\r
367         return false;\r
368     }\r
369     return true;\r
370 }\r
371 \r
372 static bool mount(void)\r
373 {\r
374     int r;\r
375 \r
376     if(!open_filedev())\r
377         return false;\r
378 \r
379     ext4_dmask_set(EXT4_DEBUG_ALL);\r
380 \r
381     r = ext4_device_register(bd, cache_mode ? 0 : bc, "ext4_filesim");\r
382     if(r != EOK){\r
383         printf("ext4_device_register ERROR = %d\n", r);\r
384         return false;\r
385     }\r
386 \r
387     r = ext4_mount("ext4_filesim", "/mp/");\r
388     if(r != EOK){\r
389         printf("ext4_mount ERROR = %d\n", r);\r
390         return false;\r
391     }\r
392 \r
393     return true;\r
394 }\r
395 \r
396 static bool umount(void)\r
397 {\r
398     int r = ext4_umount("/mp/");\r
399     if(r != EOK){\r
400         printf("ext4_umount: FAIL %d", r);\r
401         return false;\r
402     }\r
403     return true;\r
404 }\r
405 \r
406 \r
407 int main(void)\r
408 {\r
409     hw_init();\r
410 \r
411     setbuf(stdout, 0);\r
412     printf("Connect USB drive...\n");\r
413 \r
414     while(!hw_usb_connected())\r
415         hw_usb_process();\r
416     printf("USB drive connected\n");\r
417 \r
418     while(!hw_usb_enum_done())\r
419         hw_usb_process();\r
420     printf("USB drive enum done\n");\r
421 \r
422     hw_led_red(1);\r
423 \r
424     printf("Test conditions:\n");\r
425     printf("Imput name: %s\n", input_name);\r
426     printf("RW size: %d\n",  rw_szie);\r
427     printf("RW count: %d\n", rw_count);\r
428     printf("Cache mode: %s\n", cache_mode ? "dynamic" : "static");\r
429 \r
430 \r
431     hw_wait_ms(TEST_DELAY_MS);\r
432     if(!mount())\r
433         return EXIT_FAILURE;\r
434 \r
435     ext4_cache_write_back("/mp/", 1);\r
436     cleanup();\r
437 \r
438     if(sbstat){\r
439         hw_wait_ms(TEST_DELAY_MS);\r
440         mp_stats();\r
441     }\r
442 \r
443     hw_wait_ms(TEST_DELAY_MS);\r
444     dir_ls("/mp/");\r
445     if(!dir_test(dir_cnt))\r
446         return EXIT_FAILURE;\r
447 \r
448     hw_wait_ms(TEST_DELAY_MS);\r
449     if(!file_test())\r
450         return EXIT_FAILURE;\r
451 \r
452     dir_ls("/mp/");\r
453 \r
454     if(sbstat){\r
455         hw_wait_ms(TEST_DELAY_MS);\r
456         mp_stats();\r
457     }\r
458 \r
459     if(cleanup_flag){\r
460         hw_wait_ms(TEST_DELAY_MS);\r
461         cleanup();\r
462     }\r
463 \r
464     if(bstat){\r
465         hw_wait_ms(TEST_DELAY_MS);\r
466         block_stats();\r
467     }\r
468 \r
469     ext4_cache_write_back("/mp/", 0);\r
470     if(!umount())\r
471         return EXIT_FAILURE;\r
472 \r
473     printf("\nTest finished: OK\n");\r
474     printf("Press RESET to restart\n");\r
475 \r
476     while (1) {\r
477         hw_wait_ms(500);\r
478         hw_led_green(1);\r
479         hw_wait_ms(500);\r
480         hw_led_green(0);\r
481 \r
482     }\r
483 }\r
484 \r