#include #include #include #include #include #include #include #include #include enum { // _xinfreq = 20_000_000, _xtlfreq = 20_000_000, _clkfreq = 200_000_000, DOWNLOAD_BAUD = 230_400, DEBUG_BAUD = DOWNLOAD_BAUD, HEAPSIZE = 4400, SD_BASE_PIN = 40,//16, PIN_DAT = SD_BASE_PIN | 3<<6, PIN_DAT0 = SD_BASE_PIN+0, // MISO PIN_DAT1 = SD_BASE_PIN+1, PIN_DAT2 = SD_BASE_PIN+2, PIN_DAT3 = SD_BASE_PIN+3, // CS PIN_CMD = SD_BASE_PIN+5,//4, // MOSI PIN_CLK = SD_BASE_PIN+4,//5, // SCLK PIN_RED = SD_BASE_PIN+6, // output to red LED, used as CMD response shifter PIN_CD = 39,//SD_BASE_PIN+7, // Card-Detect input, and power switch, and green LED CLK_DIV = 4, }; static void randfill( uint32_t *addr, size_t size, uint32_t state ) // "size" is number of longwords { __asm volatile { // "const" enforces XIP, "volatile" enforces Fcache wrfast #0, addr rep @.rend, size xoro32 state mov pb, 0-0 wflong pb .rend } } static size_t randcmp( const uint32_t *addr, size_t size, uint32_t state ) // "size" is number of longwords { __asm volatile { // "const" enforces XIP, "volatile" enforces Fcache rdfast #0, addr rep @.rend, size rflong pb xoro32 state cmp pb, 0-0 wz if_z sub size, #1 .rend } return size; // fail longword count } static void tester( const char *filename, const size_t kbytes, const size_t repeats ) { FILE *fh; size_t count, i; uint32_t tmr, seed, *buff; const size_t bytes = kbytes * 1024; buff = __builtin_alloca(bytes); // auto-frees upon return from tester() if( !buff ) { // auto-frees upon return from tester() printf(" malloc() failed!\n"); exit(1); } seed = _rnd(); randfill(buff, kbytes * 256, seed); errno = 0; fh = fopen(filename, "w"); if( !fh ) { printf(" fopen() for writing failed! errno = %d: %s\n", errno, strerror(errno)); exit(3); } printf(" Buffer = %d kB, ", kbytes); count = 0; tmr = _getus(); for( i = 0; i < repeats; i++ ) count += fwrite(buff, 1, bytes, fh) / 1024; fclose(fh); tmr = _getus() - tmr; printf(" Written %d kB at %d kB/s, ", count, _muldiv64(count, 1_000_000, tmr)); if( count != kbytes * repeats ) { printf(" Error: File not complete! errno = %d: %s\n", errno, strerror(errno)); exit(4); } errno = 0; fh = fopen(filename, "r"); if( !fh ) { printf(" fopen() for readback failed! errno = %d: %s\n", errno, strerror(errno)); exit(5); } count = 0; for( i = 0; i < repeats; i++ ) { if( bytes != fread(buff, 1, bytes, fh) ) break; count += randcmp(buff, kbytes * 256, seed) / 256; } if( count ) printf(" Mis-match! "); else printf(" Verified, "); rewind(fh); // read the file again, this time purely for speed check tmr = _getus(); for( i = 0; i < repeats; i++ ) count += fread(buff, 1, bytes, fh) / 1024; fclose(fh); tmr = _getus() - tmr; printf(" Read %d kB at %d kB/s\n", count, _muldiv64(count, 1_000_000, tmr)); /* uint32_t clkfrq, clkmod, offset = count / 4; for( ticks = 0; ticks < 40; ticks++ ) printf(" %08x", data2[offset + ticks]); umount("/sd"); clkmod = _clockmode(); clkfrq = _clockfreq(); _waitms(200); _clkset(0x01_0004_fb, 100_000_000); _setbaud(230400); printf("\n clkfreq = %d clkmode = 0x%x\n", _clockfreq(), _clockmode()); count = compare(data1, data2, kbytes); if( count == kbytes ) printf("Matches! :)\n"); else printf("Mis-match! :( Offset %d\n", count); mountsd(); if( fh = fopen(filename, "r") ) { ticks = _cnt(); count = fread(data2, 1, kbytes, fh); fclose(fh); ticks = _cnt() - ticks; printf(" Read %d of %d bytes at %d kB/s ", count, kbytes, (_muldiv64( count, _clockfreq(), ticks ) + 512) / 1024); count = compare(data1, data2, kbytes); if( count == kbytes ) printf("Matches! :)\n"); else printf("Mis-match! :( Offset %d\n", count); for( ticks = 0; ticks < 40; ticks++ ) printf(" %08x", data2[offset + ticks]); } umount("/sd"); _waitms(200); _clkset(clkmod, clkfrq); _setbaud(230400); printf("\n clkfreq = %d clkmode = 0x%x\n", _clockfreq(), _clockmode()); mountsd(); */ } static void shutdown( void ) { umount("/sd"); puts("\nexit\n"); // blank line for re-run separation _waitms(500); _clkset(0, 25_000_000); // cool running } int mountsd( void ) { printf(" Clock divider for SD card is %d (%d MHz)\n", CLK_DIV, _clockfreq() / (CLK_DIV * 1_000_000)); return mount("/sd", _vfs_open_sdsdcard( CLK_DIV, PIN_CLK, PIN_CMD, PIN_DAT0, PIN_CD, PIN_RED )); // return mount("/sd", _vfs_open_sdcard()); // return mount("/sd", _vfs_open_littlefs_flash(1,0)); } //=================================================================================== void main( void ) { int i; atexit(shutdown); printf(" clkfreq = %d clkmode = 0x%x\n", _clockfreq(), _clockmode()); //_pinl(56); // diag errno = 0; if( mountsd() ) { perror("mount fail"); } else { perror("mount"); for( i = 0; i < 4; i++ ) tester( "/sd/speed1.bin", 2, 1024 ); // 1024 x 2 KB = 2 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed2.bin", 4, 512 ); // 512 x 4 KB = 2 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed3.bin", 8, 512 ); // 512 x 8 KB = 4 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed4.bin", 16, 256 ); // 256 x 16 KB = 4 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed5.bin", 32, 256 ); // 256 x 32 KB = 8 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed6.bin", 64, 128 ); // 128 x 64 KB = 8 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed7.bin", 128, 128 ); // 128 x 128 KB = 16 MB puts(""); for( i = 0; i < 4; i++ ) tester( "/sd/speed8.bin", 256, 64 ); // 64 x 256 KB = 16 MB } exit(0); }