]> git.gir.st - tmk_keyboard.git/blob - protocol/usb_hid/USB_Host_Shield_2.0/examples/testusbhostFAT/testusbhostFAT.ino
Squashed 'tmk_core/' changes from caca2c0..dc0e46e
[tmk_keyboard.git] / protocol / usb_hid / USB_Host_Shield_2.0 / examples / testusbhostFAT / testusbhostFAT.ino
1 /*
2 * Mega + USB storage + optional DS1307 + optional expansion RAM + funky status LED,
3 * Includes interactive debug level setting, and supports hot-plug.
4 *
5 * IMPORTANT! PLEASE USE Arduino 1.0.5 or better!
6 * Older versions HAVE MAJOR BUGS AND WILL NOT WORK AT ALL!
7 * Use of gcc-avr and lib-c that is newer than the Arduino version is even better.
8 * If you experience random crashes, use make.
9 * The options that the IDE use can generate bad code and cause the AVR to crash.
10 *
11 * This sketch requires the following libraries:
12 * https://github.com/felis/USB_Host_Shield_2.0 Install as 'USB_Host_Shield_2_0'
13 * https://github.com/xxxajk/xmem2 Install as 'xmem', provides memory services.
14 * https://github.com/xxxajk/generic_storage provides access to FAT file system.
15 * https://github.com/xxxajk/RTClib provides access to DS1307, or fake clock.
16 *
17 * Optional, to use the Makefile (Recommended! See above!):
18 * https://github.com/xxxajk/Arduino_Makefile_master
19 *
20 */
21
22 /////////////////////////////////////////////////////////////
23 // Please Note: //
24 // This section is for info with the Arduino IDE ONLY. //
25 // Unfortunately due to short sightedness of the Arduino //
26 // code team, that you must set the following in the //
27 // respective libraries. //
28 // Changing them here will have _NO_ effect! //
29 /////////////////////////////////////////////////////////////
30
31 // Uncomment to enable debugging
32 //#define DEBUG_USB_HOST
33 // This is where stderr/USB debugging goes to
34 //#define USB_HOST_SERIAL Serial3
35
36 // If you have external memory, setting this to 0 enables FAT table caches.
37 // The 0 setting is recommended only if you have external memory.
38 //#define _FS_TINY 1
39
40 //#define _USE_LFN 3
41 //#define _MAX_SS 512
42
43
44 /////////////////////////////////////////////////////////////
45 // End of Arduino IDE specific information //
46 /////////////////////////////////////////////////////////////
47
48 // You can set this to 0 if you are not using a USB hub.
49 // It will save a little bit of flash and RAM.
50 // Set to 1 if you want to use a hub.
51 #define WANT_HUB_TEST 1
52
53 // this is for XMEM2
54 #define EXT_RAM_STACK 1
55 #define EXT_RAM_HEAP 1
56 #define LOAD_XMEM
57
58 #if defined(CORE_TEENSY) && !defined(_AVR_)
59 #include <xmem.h>
60 #include <spi4teensy3.h>
61 #endif
62
63 #if defined(__AVR__)
64 #include <xmem.h>
65 #include <SPI.h>
66 #elif defined(ARDUINO_ARCH_SAM)
67 #include <SPI.h>
68 #endif
69
70 #if WANT_HUB_TEST
71 #include <usbhub.h>
72 #endif
73 #include <Wire.h>
74 #define LOAD_RTCLIB
75 #include <RTClib.h>
76 #include <masstorage.h>
77 #include <Storage.h>
78 #include <PCpartition/PCPartition.h>
79 #include <avr/interrupt.h>
80 #include <FAT/FAT.h>
81 #include <stdio.h>
82 #if defined(__AVR__)
83 static FILE tty_stdio;
84 static FILE tty_stderr;
85 volatile uint32_t LEDnext_time; // fade timeout
86 volatile uint32_t HEAPnext_time; // when to print out next heap report
87 volatile int brightness = 0; // how bright the LED is
88 volatile int fadeAmount = 80; // how many points to fade the LED by
89 #endif
90
91 USB Usb;
92
93 volatile uint8_t current_state = 1;
94 volatile uint8_t last_state = 0;
95 volatile bool fatready = false;
96 volatile bool partsready = false;
97 volatile bool notified = false;
98 volatile bool runtest = false;
99 volatile bool usbon = false;
100 volatile uint32_t usbon_time;
101 volatile bool change = false;
102 volatile bool reportlvl = false;
103 int cpart = 0;
104 PCPartition *PT;
105
106 #if WANT_HUB_TEST
107 #define MAX_HUBS 1
108 USBHub *Hubs[MAX_HUBS];
109 #endif
110
111 static PFAT *Fats[_VOLUMES];
112 static part_t parts[_VOLUMES];
113 static storage_t sto[_VOLUMES];
114
115 /*make sure this is a power of two. */
116 #define mbxs 128
117 static uint8_t My_Buff_x[mbxs]; /* File read buffer */
118
119 #if defined(__AVR__)
120
121 #define prescale1 ((1 << WGM12) | (1 << CS10))
122 #define prescale8 ((1 << WGM12) | (1 << CS11))
123 #define prescale64 ((1 << WGM12) | (1 << CS10) | (1 << CS11))
124 #define prescale256 ((1 << WGM12) | (1 << CS12))
125 #define prescale1024 ((1 << WGM12) | (1 << CS12) | (1 << CS10))
126
127 extern "C" {
128 extern unsigned int freeHeap();
129 }
130 static int tty_stderr_putc(char c, FILE *t) {
131 USB_HOST_SERIAL.write(c);
132 return 0;
133 }
134
135 static int __attribute__((unused)) tty_stderr_flush(FILE *t) {
136 USB_HOST_SERIAL.flush();
137 return 0;
138 }
139
140 static int tty_std_putc(char c, FILE *t) {
141 Serial.write(c);
142 return 0;
143 }
144
145 static int tty_std_getc(FILE *t) {
146 while(!Serial.available());
147 return Serial.read();
148 }
149
150 static int __attribute__((unused)) tty_std_flush(FILE *t) {
151 Serial.flush();
152 return 0;
153 }
154
155 #else
156 // Supposedly the DUE has stdio already pointing to serial...
157 #if !defined(ARDUINO_ARCH_SAM)
158 // But newlib needs this...
159 extern "C" {
160 int _write(int fd, const char *ptr, int len) {
161 int j;
162 for(j = 0; j < len; j++) {
163 if(fd == 1)
164 Serial.write(*ptr++);
165 else if(fd == 2)
166 USB_HOST_SERIAL.write(*ptr++);
167 }
168 return len;
169 }
170
171 int _read(int fd, char *ptr, int len) {
172 if(len > 0 && fd == 0) {
173 while(!Serial.available());
174 *ptr = Serial.read();
175 return 1;
176 }
177 return 0;
178 }
179
180 #include <sys/stat.h>
181
182 int _fstat(int fd, struct stat *st) {
183 memset(st, 0, sizeof (*st));
184 st->st_mode = S_IFCHR;
185 st->st_blksize = 1024;
186 return 0;
187 }
188
189 int _isatty(int fd) {
190 return (fd < 3) ? 1 : 0;
191 }
192 }
193 #endif // !defined(ARDUINO_ARCH_SAM)
194 #endif
195
196 void setup() {
197 bool serr = false;
198 for(int i = 0; i < _VOLUMES; i++) {
199 Fats[i] = NULL;
200 sto[i].private_data = new pvt_t;
201 ((pvt_t *)sto[i].private_data)->B = 255; // impossible
202 }
203 // Set this to higher values to enable more debug information
204 // minimum 0x00, maximum 0xff
205 UsbDEBUGlvl = 0x81;
206
207 #if !defined(CORE_TEENSY) && defined(__AVR__)
208 // make LED pin as an output:
209 pinMode(LED_BUILTIN, OUTPUT);
210 pinMode(2, OUTPUT);
211 // Ensure TX is off
212 _SFR_BYTE(UCSR0B) &= ~_BV(TXEN0);
213 // Initialize 'debug' serial port
214 USB_HOST_SERIAL.begin(115200);
215 // Do not start primary Serial port if already started.
216 if(bit_is_clear(UCSR0B, TXEN0)) {
217 Serial.begin(115200);
218 serr = true;
219 }
220
221
222 // Blink LED
223 delay(500);
224 analogWrite(LED_BUILTIN, 255);
225 delay(500);
226 analogWrite(LED_BUILTIN, 0);
227 delay(500);
228 #else
229 while(!Serial);
230 Serial.begin(115200); // On the Teensy 3.x we get a delay at least!
231 #endif
232 #if defined(__AVR__)
233 // Set up stdio/stderr
234 tty_stdio.put = tty_std_putc;
235 tty_stdio.get = tty_std_getc;
236 tty_stdio.flags = _FDEV_SETUP_RW;
237 tty_stdio.udata = 0;
238
239 tty_stderr.put = tty_stderr_putc;
240 tty_stderr.get = NULL;
241 tty_stderr.flags = _FDEV_SETUP_WRITE;
242 tty_stderr.udata = 0;
243
244 stdout = &tty_stdio;
245 stdin = &tty_stdio;
246 stderr = &tty_stderr;
247 #endif
248 printf_P(PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n"));
249 printf_P(PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl);
250 printf_P(PSTR("'+' and '-' increase/decrease by 0x01\r\n"));
251 printf_P(PSTR("'.' and ',' increase/decrease by 0x10\r\n"));
252 printf_P(PSTR("'t' will run a 10MB write/read test and print out the time it took.\r\n"));
253 printf_P(PSTR("'e' will toggle vbus off for a few moments.\r\n\r\n"));
254 printf_P(PSTR("Long filename support: "
255 #if _USE_LFN
256 "Enabled"
257 #else
258 "Disabled"
259 #endif
260 "\r\n"));
261 if(serr) {
262 fprintf_P(stderr, PSTR("\r\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nStart\r\n"));
263 fprintf_P(stderr, PSTR("Current UsbDEBUGlvl %02x\r\n"), UsbDEBUGlvl);
264 fprintf_P(stderr, PSTR("Long filename support: "
265 #if _USE_LFN
266 "Enabled"
267 #else
268 "Disabled"
269 #endif
270 "\r\n"));
271 }
272
273 #if !defined(CORE_TEENSY) && defined(__AVR__)
274 analogWrite(LED_BUILTIN, 255);
275 delay(500);
276 analogWrite(LED_BUILTIN, 0);
277 delay(500);
278 analogWrite(LED_BUILTIN, 255);
279 delay(500);
280 analogWrite(LED_BUILTIN, 0);
281 delay(500);
282 analogWrite(LED_BUILTIN, 255);
283 delay(500);
284 analogWrite(LED_BUILTIN, 0);
285 delay(500);
286
287 LEDnext_time = millis() + 1;
288 #if EXT_RAM
289 printf_P(PSTR("Total EXT RAM banks %i\r\n"), xmem::getTotalBanks());
290 #endif
291 printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
292 printf_P(PSTR("SP %x\r\n"), (uint8_t *)(SP));
293 #endif
294
295 // Even though I'm not going to actually be deleting,
296 // I want to be able to have slightly more control.
297 // Besides, it is easier to initialize stuff...
298 #if WANT_HUB_TEST
299 for(int i = 0; i < MAX_HUBS; i++) {
300 Hubs[i] = new USBHub(&Usb);
301 #if defined(__AVR__)
302 printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
303 #endif
304 }
305 #endif
306 // Initialize generic storage. This must be done before USB starts.
307 Init_Generic_Storage();
308
309 while(Usb.Init(1000) == -1) {
310 printf_P(PSTR("No USB HOST Shield?\r\n"));
311 Notify(PSTR("OSC did not start."), 0x40);
312 }
313
314 #if !defined(CORE_TEENSY) && defined(__AVR__)
315 cli();
316 TCCR3A = 0;
317 TCCR3B = 0;
318 // (0.01/(1/((16 *(10^6)) / 8))) - 1 = 19999
319 OCR3A = 19999;
320 TCCR3B |= prescale8;
321 TIMSK3 |= (1 << OCIE1A);
322 sei();
323
324 HEAPnext_time = millis() + 10000;
325 #endif
326 #if defined(__AVR__)
327 HEAPnext_time = millis() + 10000;
328 #endif
329 }
330
331 void serialEvent() {
332 // Adjust UsbDEBUGlvl level on-the-fly.
333 // + to increase, - to decrease, * to display current level.
334 // . to increase by 16, , to decrease by 16
335 // e to flick VBUS
336 // * to report debug level
337 if(Serial.available()) {
338 int inByte = Serial.read();
339 switch(inByte) {
340 case '+':
341 if(UsbDEBUGlvl < 0xff) UsbDEBUGlvl++;
342 reportlvl = true;
343 break;
344 case '-':
345 if(UsbDEBUGlvl > 0x00) UsbDEBUGlvl--;
346 reportlvl = true;
347 break;
348 case '.':
349 if(UsbDEBUGlvl < 0xf0) UsbDEBUGlvl += 16;
350 reportlvl = true;
351 break;
352 case ',':
353 if(UsbDEBUGlvl > 0x0f) UsbDEBUGlvl -= 16;
354 reportlvl = true;
355 break;
356 case '*':
357 reportlvl = true;
358 break;
359 case 't':
360 runtest = true;
361 break;
362 case 'e':
363 change = true;
364 usbon = false;
365 break;
366 }
367 }
368 }
369
370 #if !defined(CORE_TEENSY) && defined(__AVR__)
371 // ALL teensy versions LACK PWM ON LED
372
373 ISR(TIMER3_COMPA_vect) {
374 if((long)(millis() - LEDnext_time) >= 0L) {
375 LEDnext_time = millis() + 30;
376
377 // set the brightness of LED
378 analogWrite(LED_BUILTIN, brightness);
379
380 // change the brightness for next time through the loop:
381 brightness = brightness + fadeAmount;
382
383 // reverse the direction of the fading at the ends of the fade:
384 if(brightness <= 0) {
385 brightness = 0;
386 fadeAmount = -fadeAmount;
387 }
388 if(brightness >= 255) {
389 brightness = 255;
390 fadeAmount = -fadeAmount;
391 }
392 }
393 }
394 #endif
395
396 bool isfat(uint8_t t) {
397 return (t == 0x01 || t == 0x04 || t == 0x06 || t == 0x0b || t == 0x0c || t == 0x0e || t == 0x1);
398 }
399
400 void die(FRESULT rc) {
401 printf_P(PSTR("Failed with rc=%u.\r\n"), rc);
402 //for (;;);
403 }
404
405 void loop() {
406 FIL My_File_Object_x; /* File object */
407
408 #if defined(__AVR__)
409 // Print a heap status report about every 10 seconds.
410 if((long)(millis() - HEAPnext_time) >= 0L) {
411 if(UsbDEBUGlvl > 0x50) {
412 printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
413 }
414 HEAPnext_time = millis() + 10000;
415 }
416 TCCR3B = 0;
417 #endif
418 #if defined(CORE_TEENSY)
419 // Teensy suffers here, oh well...
420 serialEvent();
421 #endif
422 // Horrid! This sort of thing really belongs in an ISR, not here!
423 // We also will be needing to test each hub port, we don't do this yet!
424 if(!change && !usbon && (long)(millis() - usbon_time) >= 0L) {
425 change = true;
426 usbon = true;
427 }
428
429 if(change) {
430 change = false;
431 if(usbon) {
432 Usb.vbusPower(vbus_on);
433 printf_P(PSTR("VBUS on\r\n"));
434 } else {
435 Usb.vbusPower(vbus_off);
436 usbon_time = millis() + 2000;
437 }
438 }
439 Usb.Task();
440 current_state = Usb.getUsbTaskState();
441 if(current_state != last_state) {
442 if(UsbDEBUGlvl > 0x50)
443 printf_P(PSTR("USB state = %x\r\n"), current_state);
444 #if !defined(CORE_TEENSY) && defined(__AVR__)
445 if(current_state == USB_STATE_RUNNING) {
446 fadeAmount = 30;
447 }
448 #endif
449 if(current_state == USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE) {
450 #if !defined(CORE_TEENSY) && defined(__AVR__)
451 fadeAmount = 80;
452 #endif
453 partsready = false;
454 for(int i = 0; i < cpart; i++) {
455 if(Fats[i] != NULL)
456 delete Fats[i];
457 Fats[i] = NULL;
458 }
459 fatready = false;
460 notified = false;
461 cpart = 0;
462 }
463 last_state = current_state;
464 }
465
466 // only do any of this if usb is on
467 if(usbon) {
468 if(partsready && !fatready) {
469 if(cpart > 0) fatready = true;
470 }
471 // This is horrible, and needs to be moved elsewhere!
472 for(int B = 0; B < MAX_USB_MS_DRIVERS; B++) {
473 if((!partsready) && (UHS_USB_BulkOnly[B]->GetAddress())) {
474
475 // Build a list.
476 int ML = UHS_USB_BulkOnly[B]->GetbMaxLUN();
477 //printf("MAXLUN = %i\r\n", ML);
478 ML++;
479 for(int i = 0; i < ML; i++) {
480 if(UHS_USB_BulkOnly[B]->LUNIsGood(i)) {
481 partsready = true;
482 ((pvt_t *)(sto[i].private_data))->lun = i;
483 ((pvt_t *)(sto[i].private_data))->B = B;
484 sto[i].Reads = *UHS_USB_BulkOnly_Read;
485 sto[i].Writes = *UHS_USB_BulkOnly_Write;
486 sto[i].Status = *UHS_USB_BulkOnly_Status;
487 sto[i].Initialize = *UHS_USB_BulkOnly_Initialize;
488 sto[i].Commit = *UHS_USB_BulkOnly_Commit;
489 sto[i].TotalSectors = UHS_USB_BulkOnly[B]->GetCapacity(i);
490 sto[i].SectorSize = UHS_USB_BulkOnly[B]->GetSectorSize(i);
491 printf_P(PSTR("LUN:\t\t%u\r\n"), i);
492 printf_P(PSTR("Total Sectors:\t%08lx\t%lu\r\n"), sto[i].TotalSectors, sto[i].TotalSectors);
493 printf_P(PSTR("Sector Size:\t%04x\t\t%u\r\n"), sto[i].SectorSize, sto[i].SectorSize);
494 // get the partition data...
495 PT = new PCPartition;
496
497 if(!PT->Init(&sto[i])) {
498 part_t *apart;
499 for(int j = 0; j < 4; j++) {
500 apart = PT->GetPart(j);
501 if(apart != NULL && apart->type != 0x00) {
502 memcpy(&(parts[cpart]), apart, sizeof (part_t));
503 printf_P(PSTR("Partition %u type %#02x\r\n"), j, parts[cpart].type);
504 // for now
505 if(isfat(parts[cpart].type)) {
506 Fats[cpart] = new PFAT(&sto[i], cpart, parts[cpart].firstSector);
507 //int r = Fats[cpart]->Good();
508 if(Fats[cpart]->MountStatus()) {
509 delete Fats[cpart];
510 Fats[cpart] = NULL;
511 } else cpart++;
512 }
513 }
514 }
515 } else {
516 // try superblock
517 Fats[cpart] = new PFAT(&sto[i], cpart, 0);
518 //int r = Fats[cpart]->Good();
519 if(Fats[cpart]->MountStatus()) {
520 //printf_P(PSTR("Superblock error %x\r\n"), r);
521 delete Fats[cpart];
522 Fats[cpart] = NULL;
523 } else cpart++;
524
525 }
526 delete PT;
527 } else {
528 sto[i].Writes = NULL;
529 sto[i].Reads = NULL;
530 sto[i].Initialize = NULL;
531 sto[i].TotalSectors = 0UL;
532 sto[i].SectorSize = 0;
533 }
534 }
535
536 }
537 }
538
539 if(fatready) {
540 if(Fats[0] != NULL) {
541 struct Pvt * p;
542 p = ((struct Pvt *)(Fats[0]->storage->private_data));
543 if(!UHS_USB_BulkOnly[p->B]->LUNIsGood(p->lun)) {
544 // media change
545 #if !defined(CORE_TEENSY) && defined(__AVR__)
546 fadeAmount = 80;
547 #endif
548 partsready = false;
549 for(int i = 0; i < cpart; i++) {
550 if(Fats[i] != NULL)
551 delete Fats[i];
552 Fats[cpart] = NULL;
553 }
554 fatready = false;
555 notified = false;
556 cpart = 0;
557 }
558
559 }
560 }
561 if(fatready) {
562 FRESULT rc; /* Result code */
563 UINT bw, br, i;
564 if(!notified) {
565 #if !defined(CORE_TEENSY) && defined(__AVR__)
566 fadeAmount = 5;
567 #endif
568 notified = true;
569 FATFS *fs = NULL;
570 for(int zz = 0; zz < _VOLUMES; zz++) {
571 if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;
572 }
573 printf_P(PSTR("\r\nOpen an existing file (message.txt).\r\n"));
574 rc = f_open(&My_File_Object_x, "0:/MESSAGE.TXT", FA_READ);
575 if(rc) printf_P(PSTR("Error %i, message.txt not found.\r\n"), rc);
576 else {
577 printf_P(PSTR("\r\nType the file content.\r\n"));
578 for(;;) {
579 rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &br); /* Read a chunk of file */
580 if(rc || !br) break; /* Error or end of file */
581 for(i = 0; i < br; i++) {
582 /* Type the data */
583 if(My_Buff_x[i] == '\n')
584 Serial.write('\r');
585 if(My_Buff_x[i] != '\r')
586 Serial.write(My_Buff_x[i]);
587 Serial.flush();
588 }
589 }
590 if(rc) {
591 f_close(&My_File_Object_x);
592 goto out;
593 }
594
595 printf_P(PSTR("\r\nClose the file.\r\n"));
596 rc = f_close(&My_File_Object_x);
597 if(rc) goto out;
598 }
599 printf_P(PSTR("\r\nCreate a new file (hello.txt).\r\n"));
600 rc = f_open(&My_File_Object_x, "0:/Hello.TxT", FA_WRITE | FA_CREATE_ALWAYS);
601 if(rc) {
602 die(rc);
603 goto outdir;
604 }
605 printf_P(PSTR("\r\nWrite a text data. (Hello world!)\r\n"));
606 rc = f_write(&My_File_Object_x, "Hello world!\r\n", 14, &bw);
607 if(rc) {
608 goto out;
609 }
610 printf_P(PSTR("%u bytes written.\r\n"), bw);
611
612 printf_P(PSTR("\r\nClose the file.\r\n"));
613 rc = f_close(&My_File_Object_x);
614 if(rc) {
615 die(rc);
616 goto out;
617 }
618 outdir:{
619 #if _USE_LFN
620 char lfn[_MAX_LFN + 1];
621 FILINFO My_File_Info_Object_x; /* File information object */
622 My_File_Info_Object_x.lfname = lfn;
623 #endif
624 DIR My_Dir_Object_x; /* Directory object */
625 printf_P(PSTR("\r\nOpen root directory.\r\n"));
626 rc = f_opendir(&My_Dir_Object_x, "0:/");
627 if(rc) {
628 die(rc);
629 goto out;
630 }
631
632 printf_P(PSTR("\r\nDirectory listing...\r\n"));
633 #if defined(__AVR__)
634 printf_P(PSTR("Available heap: %u Bytes\r\n"), freeHeap());
635 #endif
636 for(;;) {
637 #if _USE_LFN
638 My_File_Info_Object_x.lfsize = _MAX_LFN;
639 #endif
640
641 rc = f_readdir(&My_Dir_Object_x, &My_File_Info_Object_x); /* Read a directory item */
642 if(rc || !My_File_Info_Object_x.fname[0]) break; /* Error or end of dir */
643
644 if(My_File_Info_Object_x.fattrib & AM_DIR) {
645 Serial.write('d');
646 } else {
647 Serial.write('-');
648 }
649 Serial.write('r');
650
651 if(My_File_Info_Object_x.fattrib & AM_RDO) {
652 Serial.write('-');
653 } else {
654 Serial.write('w');
655 }
656 if(My_File_Info_Object_x.fattrib & AM_HID) {
657 Serial.write('h');
658 } else {
659 Serial.write('-');
660 }
661
662 if(My_File_Info_Object_x.fattrib & AM_SYS) {
663 Serial.write('s');
664 } else {
665 Serial.write('-');
666 }
667
668 if(My_File_Info_Object_x.fattrib & AM_ARC) {
669 Serial.write('a');
670 } else {
671 Serial.write('-');
672 }
673
674 #if _USE_LFN
675 if(*My_File_Info_Object_x.lfname)
676 printf_P(PSTR(" %8lu %s (%s)\r\n"), My_File_Info_Object_x.fsize, My_File_Info_Object_x.fname, My_File_Info_Object_x.lfname);
677 else
678 #endif
679 printf_P(PSTR(" %8lu %s\r\n"), My_File_Info_Object_x.fsize, &(My_File_Info_Object_x.fname[0]));
680 }
681 }
682 out:
683 if(rc) die(rc);
684
685 DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);
686 printf_P(PSTR("\r\nTest completed.\r\n"));
687
688 }
689
690 if(runtest) {
691 ULONG ii, wt, rt, start, end;
692 FATFS *fs = NULL;
693 for(int zz = 0; zz < _VOLUMES; zz++) {
694 if(Fats[zz]->volmap == 0) fs = Fats[zz]->ffs;
695 }
696 runtest = false;
697 f_unlink("0:/10MB.bin");
698 printf_P(PSTR("\r\nCreate a new 10MB test file (10MB.bin).\r\n"));
699 rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_WRITE | FA_CREATE_ALWAYS);
700 if(rc) goto failed;
701 for(bw = 0; bw < mbxs; bw++) My_Buff_x[bw] = bw & 0xff;
702 fflush(stdout);
703 start = millis();
704 while(start == millis());
705 for(ii = 10485760LU / mbxs; ii > 0LU; ii--) {
706 rc = f_write(&My_File_Object_x, My_Buff_x, mbxs, &bw);
707 if(rc || !bw) goto failed;
708 }
709 rc = f_close(&My_File_Object_x);
710 if(rc) goto failed;
711 end = millis();
712 wt = (end - start) - 1;
713 printf_P(PSTR("Time to write 10485760 bytes: %lu ms (%lu sec) \r\n"), wt, (500 + wt) / 1000UL);
714 rc = f_open(&My_File_Object_x, "0:/10MB.bin", FA_READ);
715 fflush(stdout);
716 start = millis();
717 while(start == millis());
718 if(rc) goto failed;
719 for(;;) {
720 rc = f_read(&My_File_Object_x, My_Buff_x, mbxs, &bw); /* Read a chunk of file */
721 if(rc || !bw) break; /* Error or end of file */
722 }
723 end = millis();
724 if(rc) goto failed;
725 rc = f_close(&My_File_Object_x);
726 if(rc) goto failed;
727 rt = (end - start) - 1;
728 printf_P(PSTR("Time to read 10485760 bytes: %lu ms (%lu sec)\r\nDelete test file\r\n"), rt, (500 + rt) / 1000UL);
729 failed:
730 if(rc) die(rc);
731 DISK_IOCTL(fs->drv, CTRL_COMMIT, 0);
732 printf_P(PSTR("10MB timing test finished.\r\n"));
733 }
734 }
735 }
736 }
Imprint / Impressum