Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

testusbhostFAT.ino 31KB

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