'' +--------------------------------------------------------------------------+ '' | Cluso's Minimal SD Boot Test for P2 | '' +--------------------------------------------------------------------------+ '' | Author : (c)2012-2018 "Cluso99" (Ray Rodrick) | '' | License: MIT License - See end of file for terms of use | '' +--------------------------------------------------------------------------+ '' '' Acknowledgements to: '' Andy Schenk (Isonix), Kwabena W. Agyeman (Kye), Radical Eye Software, '' Dr Mike Green, Tomas Rokicki, ..and others '' +--------------------------------------------------------------------------+ '' RR20180417 v124e Candidate for P2 ROM (beta) '' f readFILE max_size (512-16)KB '' g make variables "res 1", cog_start0, '' h move variable constants to immediates in code '' remove hubset from _finishup; blocksh & SDtype as 'res 1' '' RR20180425 ij use pinxx; replace cmp x01 w cmpr ReplyR1 '' v125a fname res 3 '' bc waitx, tidy '' def _clusters --> _sectors, combine walk_dir into search_dir '' g run as hubexec '' h add org $1C0 to cog variables '' i change validate_csum to just check for "Prop" string (MBR/VOL) '' RR20180426 v126b fix validate_csum replyR1 --> reply '' c add exFAT ptn_type (no point as dir is incompatible) '' d MBR/VOL if "ProP" then start & length variant - not wkg!!! '' RR20180429 e MBR/VOL "Prop" wkg '' f remove exFAT ptn_type as currently cannot follow dir '' RR20180429 v127a test release ''============================[ CON ]============================================================ CON _clockfreq = 80_000_000 _freq = _clockfreq delay1s = _freq ' 1s (xtal * pll) delay5us = _freq / 200_000 ' 5us delay1ms = _freq / 1_000 ' 1ms ' microSD CV-A9 pins (note: can only be on PortB pins!!!) pinCS = 61 pinCLK = 60 pinDO = 59 pinDI = 58 CS = pinCS -32 CLK = pinCLK-32 DO = pinDO -32 DI = pinDI -32 initmask = 1<74 clocks with /CS=1 & DI=1 starting & ending with CLK=0 + '+-----------------------------------------------------------------------------+ mov outb, ##initmask ' 1<1-->0 djnz ctr1, #.count '/ waitx ##delay5us ' CLK=0 (idle) & /CS=1 '+-----------------------------------------------------------------------------+ '+ Software Reset: + '+ CMD0, PAR=$0, CRC=$95, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ Command0 getct starttime ' timeout up to CMD9 mov ctr1, #10 ' try a few times .again0 mov cmdout, #CMD0 mov cmdpar, #0 mov cmdcrc, #$95 '+-----------------------------------------------------------------------------+ call #cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ '\ $01(idle): SD/MMC, not fully validated if_nc jmp #Command8 '/ $00(good): (dane card response) '+-----------------------------------------------------------------------------+ waitx ##delay5us ' delay 5us djnz ctr1, #.again0 ' n: try again? jmp #fail00 ' '+=============================================================================+ ' we know we now have an SD/MMC card but its not fully validated yet... '+-----------------------------------------------------------------------------+ '+ Check Voltage: + '+ CMD8, PAR=$1AA, CRC=$87, REPLY=R1($01)+R7($xx1AA) ($05=try SDV1) + '+-----------------------------------------------------------------------------+ Command8 mov cmdout, #CMD8 mov cmdpar, #$1AA mov cmdcrc, #$87 '+-----------------------------------------------------------------------------+ call #cmdR1R7 ' /CS=0, send cmd, recv R1+R7, /CS=1 '+-----------------------------------------------------------------------------+ if_c_or_z jmp #.illegal ' j if <> $01 (not idle) .idle and reply, ##$FFF '\ cmp reply, #$1AA wz '/ R7[11:0]=$1AA ? mov cmdpar2, ##$40000000 ' preset for SDV2 if_ne jmp #fail98 ' n: unknown R7 jmp #Command55 ' y: CMD55+ACMD41($4000_0000) .illegal cmp replyR1, #$05 ' $05(illegal cmd) ? if_ne jmp #fail08 ' <>$01/$05 (not idle/illegal) mov cmdpar2, #0 ' try SDV1 ' CMD55+ACMD41($0) fall thru '+-----------------------------------------------------------------------------+ '+ Prefix to ACMD41 & ACMD23: + '+ CMD55, PAR=$0, CRC=$xx, REPLY=R1($01) + '+-----------------------------------------------------------------------------+ Command55 ' .again55 mov cmdout, #CMD55 ' mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ call #cmdRZA41 ' /CS=0, send cmd, recv R1, /CS=0(ena) '+-----------------------------------------------------------------------------+ if_c_or_z jmp #fail55 ' <>$01 (not idle) ' fall thru '+-----------------------------------------------------------------------------+ '+ Check SDV1/SDV2: (follows CMD55) + '+ ACMD41, PAR=$0, CRC=$xx, REPLY=R1($00) SD-V1 + '+ ACMD41, PAR=$40000000, CRC=$xx, REPLY=R1($00) SD-V2 + '+-----------------------------------------------------------------------------+ .CommandA41 mov cmdout, #ACMD41 ' mov cmdpar, cmdpar2 ' SDV1=0 / SDV2=$40000000 '+-----------------------------------------------------------------------------+ call #cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ if_nc_and_nz jmp #.again55 '$01(busy): CMD55+CMD41 again if_c jmp #fail41 ' <>$00/$01: error cmp cmdpar2, #0 wz ' SDV1 ? if_z mov blocksh, #9 ' y: #1 SDV1(byte address) if_z jmp #Command16 ' y: SDV1 does not use CMD58 ' SDV2 fall thru '+-----------------------------------------------------------------------------+ '+ Check OCR CCS bit: + '+ CMD58, PAR=$0, CRC=$xx, REPLY=R1($00)+R3(b30=1) + '+-----------------------------------------------------------------------------+ Command58 mov cmdout, #CMD58 ' SDHC ? mov cmdpar, #0 ' '+-----------------------------------------------------------------------------+ call #cmdR1R3 ' /CS=0, send cmd, recv R1+R3, /CS=1 '+-----------------------------------------------------------------------------+ if_c_or_nz jmp #fail58 ' <>$00(good): error test reply, ##$40000000 wz ' bit30=CCS=1? if_z mov blocksh, #9 ' n: #2 SDV2(byte address) if_nz mov blocksh, #0 ' y: #3 SDHC/SDV2(block address) '' if_nz jmp #Command9 ' y: does not req cmd16? ????????? ' SDV2(byte) fall thru '+-----------------------------------------------------------------------------+ '+ Force block size to 512 bytes: + '+ CMD16, PAR=$200, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ Command16 mov cmdout, #CMD16 ' force blocksize=512bytes mov cmdpar, ##512 ' 512 bytes '+-----------------------------------------------------------------------------+ call #cmdR1 ' /CS=0, send cmd, recv R1, /CS=1 '+-----------------------------------------------------------------------------+ if_nc_and_nz jmp #Command16 ' =$01(idle): again if_c_or_nz jmp #fail16 ' <>$00(good): error ' fall thru '+-----------------------------------------------------------------------------+ '+ Read CSD register (16 bytes): + '+ CMD9, PAR=$0, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ Command9 mov _bufad, ##hubdata ' where to store data mov cmdout, #CMD9 ' read CSD register mov bufad, _bufad ' where to store CSD call #readregister ' ' fall thru '+-----------------------------------------------------------------------------+ '+ Read CID register (16 bytes): + '+ CMD10, PAR=$0, CRC=$xx, REPLY=R1($00) + '+-----------------------------------------------------------------------------+ Command10 mov cmdout, #CMD10 ' read CID register mov bufad, _bufad ' where to store CID call #readregister ' ' fall thru '+-----------------------------------------------------------------------------+ '+ Read MBR/VBR (Sector 0): + '+-----------------------------------------------------------------------------+ readMBR mov _blocknr, ##mbr_begin ' VBR/MBR = SECTOR 0 call #read_sector ' read sector call #validate_csum ' valid -> load & run call #validate_mbr ' returns if valid '+-----------------------------------------------------------------------------+ '+ Read VOL (Sector x): + '+-----------------------------------------------------------------------------+ readVOL mov _blocknr, vol_begin ' VOL SECTOR# call #read_sector ' read sector call #validate_csum ' valid -> load & run call #validate_vol ' returns if valid '+-----------------------------------------------------------------------------+ '+ Read FSI (Sector x): + '+-----------------------------------------------------------------------------+ readFSI mov _blocknr, fsi_begin ' FSI SECTOR# call #read_sector ' read sector call #validate_fsi ' returns if valid '+-----------------------------------------------------------------------------+ '+ Read FAT (Sector x): + '+-----------------------------------------------------------------------------+ readFAT mov _blocknr, fat_begin ' FAT SECTOR# call #read_sector ' read sector '' call #validate_fat ' returns if valid '+-----------------------------------------------------------------------------+ '+ Read DIR (n Sectors): Search for "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ readDIR mov fname, ##_fname1a ' copy _fname1 -> fname mov fname+1, ##_fname1b ' mov fname+2, ##_fname1c ' call #search_dir ' search dir for if_e jmp #readFILE ' j if entry found mov fname, ##_fname2a ' copy _fname2 -> fname mov fname+1, ##_fname2b ' mov fname+2, ##_fname2c ' call #search_dir ' search dir for if_ne jmp #_failure ' not found, ' else fall thru '+-----------------------------------------------------------------------------+ '+ Read FILE (n Sectors): File "<_fname/_fname2>" + '+-----------------------------------------------------------------------------+ readFILE mov _blocknr, dat_begin ' DAT SECTOR# ' convert _sectors = file_size (bytes) into sectors to read fle _sectors, ##max_size ' limit max size to load add _sectors, #511 ' +sector if extra bytes shr _sectors, #9 ' sectors=file_size/512 ' load file's data - multiple sector(s) call #read_sector ' read sector djz _sectors, #.done .nextsector call #read_nxtsector ' read sector(s) djnz _sectors, #.nextsector .done '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ jmp #_success ' load Cog & jmp #$000 '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ '+-----------------------------------------------------------------------------+ ' Validate MBR/VOL CSUM $080-$17F="Prop". If valid, copy to Cog & Run '+-----------------------------------------------------------------------------+ validate_csum mov bufad, #$17C ' check long at $17C rdlong reply, bufad ' cmp reply, ##_csum wz ' ="Prop"? '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if_e jmp #_success80 ' load cog & jmp #$020 '+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmp reply, ##_csum2 wz ' ="ProP"? sector/size? if_ne jmp #validate_csum_ret ' return "NZ" mov bufad, #$174 ' get sector start rdlong dat_begin, bufad ' mov bufad, #$178 ' get length(bytes) rdlong _sectors, bufad ' jmp #readFILE ' simulate found validate_csum_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ ' Validate MBR (PTN0 table & signature) ' +$1BE[16] = = Ptn0 Table... ' verify +$1BE+$0[1] = $00/$80 = Ptn0 State ' verify +$1BE+$4[1] = $0B/$0C = Ptn0 Type ' calc +$1BE+$8[4] = = Ptn0 StartSector# --> vol_begin ' calc +$1BE+$C[4] = = Ptn0 SectorSize --> ptn_size ' verify +$1FE[2] = $55AA = signature '+-----------------------------------------------------------------------------+ validate_mbr mov bufad, _bufad ' MBR hub addr add bufad, #$1BE ' offset to PTN0 table rdbyte reply, bufad ' ptn_state and reply, #$7F cmp reply, #0 wz ' $00/80? inactive/active if_ne jmp #invalid_mbr ' add bufad, #$4 ' offset to ptn_type rdbyte reply, bufad ' ptn_type cmp reply, #$0C wz ' $0C=FAT32(LBA) if_ne cmp reply, #$0B wz ' $0B=FAT32(<=2TB) '''' if_ne cmp reply, #$07 wz ' $07=exFAT Do not allow!!! if_ne jmp #invalid_mbr ' add bufad, #($1FE-$1BE-$4) ' offset to $55AA signature rdword reply, bufad ' read cmp reply, ##$AA_55 wz ' we read it reversed! if_ne jmp #invalid_mbr ' mov bufad, _bufad ' MBR hub addr add bufad, #$1BE ' offset to PTN0 table '+-----------------------------------------------------------------------------+ ' Calculate the raw sector address (LBA) for the VOL sector (vol_begin)... ' vol_begin = LBA begin ptn0 $1BE+$08[4] (reversed & not long aligned!!!) '+-----------------------------------------------------------------------------+ add bufad, #$08 ' offset to start sector LBA rdlong vol_begin, bufad ' read '+-----------------------------------------------------------------------------+ ' Calculate the partition size in sectors ' ptn_size = #sectors in ptn0 $1BE+$0C[4] (reversed & not long aligned!!!) '+-----------------------------------------------------------------------------+ add bufad, #($0C-$08) ' offset to PTN0 size rdlong ptn_size, bufad ' read validate_mbr_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ ' Validate VOL... ' verify +$00B[2] = 512 = Bytes/Sector ' not chkd +$00D[1] = 64 = Sectors/Cluster PTN0SECCLU ' calc +$00E[2] = #ResvSectors --> PTN0RESV ' verify +$010[1] = 2 = #NoOfFATs PTN0NFATS ' ??? +$020[4] = #Sectors/PTN --> =ptn_size? ' calc +$024[4] = #Sectors/FAT --> PTN0SECFAT ' calc +$030[2] = #FileSystemInfo --> fsi_begin ' verify +$1FE[2] = $55AA = signature ' ' calc fat_begin = vol_begin + PTN0RESV ' calc dir_begin = fat_begin + (PTN0SECFAT * 2) '+-----------------------------------------------------------------------------+ validate_vol mov bufad, _bufad ' VOL hub locn add bufad, #$0B '\ offset to bytes/sector rdword reply, bufad '| read cmp reply, ##512 wz '| if_ne jmp #invalid_vol '/ add bufad, #($0E-$0B) ' offset to #ResvSectors rdword fat_begin, bufad '\ start of FAT table add fat_begin, vol_begin '/ add bufad, #($10-$0E) '\ offset to #nooffats rdbyte reply, bufad '| read cmp reply, #2 wz '| $02 PTN0NFATS if_ne jmp #invalid_vol '/ add bufad, #($24-$10) ' offset to #Sectors/FAT rdlong dir_begin, bufad '\ start of DATA (DIR table) shl dir_begin, #1 '| *2 add dir_begin, fat_begin '/ +base add bufad, #($30-$24) ' offset to #FileSystemSector rdword fsi_begin, bufad ' read add fsi_begin, vol_begin ' add vol_begin add bufad, #($1FE-$30) ' offset to $55AA signature rdword reply, bufad ' read cmp reply, ##$AA_55 wz ' we read it reversed! if_ne jmp #invalid_vol ' validate_vol_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ ' Validate FSI... ' verify +$000[4] = "RRaR" = signature ' verify +$1E4[4] = "rrAa" = signature ' verify +$1FE[2] = $55AA = signature '+-----------------------------------------------------------------------------+ validate_fsi mov bufad, _bufad ' FSI hub locn rdlong reply, bufad ' read cmp reply, ##$41615252 wz ' "RRaA" signature (reversed) add bufad, #$1E4 ' offset to signature rdlong reply, bufad ' read if_e cmp reply, ##$61417272 wz ' "rrAa" signature (reversed) add bufad, #($1FE-$1E4) ' offset to signature rdword reply, bufad ' read if_e cmp reply, ##$AA_55 wz ' $55AA signature (reversed) if_ne jmp #invalid_fsi ' validate_fsi_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ ' Validate FAT... ' nothing to validate '+-----------------------------------------------------------------------------+ 'validate_fat '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ invalid_mbr invalid_vol invalid_fsi invalid_fat jmp #fail100 ' fail to boot !!! '+-----------------------------------------------------------------------------+ '+-----------------------------------------------------------------------------+ '+ Search Directory for <_fname> entry: '+-----------------------------------------------------------------------------+ search_dir mov _blocknr, dir_begin ' DIR SECTOR# mov _sectors, ##PTN_SECCLU ' max sectors to scan (1 cluster) search_next call #read_sector ' read sector '+-----------------------------------------------------------------------------+ ' Walk Directory: (read DIR sectors) ' 16 x 32byte DIR(fname) entries per DIR sector ' +$00[1] = $00 = empty ' => $80 = deleted file ' search +$00[11] = 8.3 filename ' verify +$0B[1] = FileAttrib AND $D8,check $00 ' $01=read,02=hidden,04=system,08=volume,0F=longfile,10=dir,20=archive ' calc +$14[2] = FAT32: 1st cluster# HI -\-> cluster ' calc +$1A[2] = FAT32: 1st cluster# LO -/ ' calc +$1C[4] = FAT32: FileSize in bytes --> file_size ' calc dat_begin = dir_begin + ((cluster-2)<<6) ' returns: _sectors = file_size (bytes) if found ' _sectors = 1 not found & end of directory entries '+-----------------------------------------------------------------------------+ ' scan dir sector for files... .walk_dir mov _entries, #16 ' 16*32byte file entries mov bufad, _bufad ' dir hub locn ' scan this sector for filename entry... .scan rdlong reply, bufad '\ check this entry cmp reply, #0 wz '| $0 = empty? if_ne jmp #.check '| n: mov reply, #1 wz ' \ y: end of search jmp #search_dir_ret ' / return "NZ" .check cmp reply, fname wz '| check fname... add bufad, #4 '| rdlong reply, bufad '| if_e cmp reply, fname+1 wz '| add bufad, #4 '| rdlong reply, bufad '| and reply, ##$D8FFFFFF '| check atts b7+6+4+3 if_e cmp reply, fname+2 wz '| if_e jmp #.found '/ found! add bufad, #(32-8) ' next entry djnz _entries, #.scan ' jmp #.checked ' "NZ" not found this sector '+-----------------------------------------------------------------------------+ ' set: cluster = +$14[2] +$1A[2] ' filesize = +$1C[4] ' sector = ((cluster-2)<<6)+base ' where <<6 = *sectors/cluster, base=dir_begin '+-----------------------------------------------------------------------------+ .found add bufad, #($14-8) ' ptr to 1st cluster hi rdword dat_begin, bufad ' read shl dat_begin, #16 ' bytes 3&2 add bufad, #($1A-$14) ' ptr to 1st cluster lo rdword reply, bufad ' read or dat_begin, reply ' bytes 3-0 ' convert to sector# sub dat_begin, #2 '\ correct cluster addr(-2) shl dat_begin, #6 '| convert to sector add dat_begin, dir_begin '/ +base ' read filesize(bytes) add bufad, #($1C-$1A) ' ptr to filesize rdlong _sectors, bufad ' read into _sectors jmp #search_dir_ret ' return "Z" = found '+-----------------------------------------------------------------------------+ .checked add _blocknr, #1 ' next sector# djnz _sectors, #search_next search_dir_ret ' "NZ" if not found, ret ' "Z" if found '+=============================================================================+ '+-----------------------------------------------------------------------------+ ' Read Sector: '+-----------------------------------------------------------------------------+ read_nxtsector add _blocknr, #1 ' next sector# read_nxtslot add _bufad, ##512 ' next data slot read_sector mov blocknr, _blocknr ' sector# mov bufad, _bufad ' where to store data call #Command17 ' read sector (block) read_nxtsector_ret read_nxtslot_ret read_sector_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ Command17 mov bytescnt, ##512 ' read block (no. bytes) mov cmdout, #CMD17 ' mov cmdpar, blocknr ' shl cmdpar, blocksh ' <<0 or <<9 '+-----------------------------------------------------------------------------+ call #readblock ' read 512 bytes '+-----------------------------------------------------------------------------+ Command17_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ Read Block/Sector: (512 bytes) + '+ CMD9, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD10, PAR=$0, CRC=$xx, REPLY=R1($00) + '+ CMD17, PAR=blocknr, CRC=$xx, REPLY=R1($??) +n*$FF +($FE+block+CRC16) + '+-----------------------------------------------------------------------------+ readregister mov bytescnt, #16 ' CMD9,10: CSD,CID register mov cmdpar, #0 ' PAR=$0, 16 bytes readblock ' CMD17: PAR=sector, 512 bytes getct starttime ' timeout for cmd9,10,17 '+-----------------------------------------------------------------------------+ call #cmdRZtoken ' /CS=0, send cmd, recv R1, /CS=0(ena) '+-----------------------------------------------------------------------------+ if_nz jmp #fail17 ' <>$00(good): error call #getreply ' n*$FF+$FE cmp reply, #$FE wz ' $FE=valid Data Token if_nz jmp #fail97 ' .readbyte call #recvbyte ' read data byte wrbyte reply, bufad ' save byte add bufad, #1 ' bufad++ djnz bytescnt, #.readbyte ' byte-- call #recvbyte ' read CRC16 1/2 call #recvbyte ' read CRC16 2/2 ' NOTE: CRC16 not checked - do we want to do this? ?????????? '' outl #pinCLK ' CLK=0 (idle) already=0 outh #pinCS ' /CS=1 (disable) readregister_ret readblock_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SEND: CMDx, PARx, CRCx, GET REPLY + '+-----------------------------------------------------------------------------+ cmdRZA41 ' CMD55: R1 response cmdRZtoken ' CMD9,10,17: R1+$FE response mov cmdtype, #0 ' returns w /CS=0(ena) jmp #cmdxx CMDR1R3 ' CMD58: R1+R3 response cmdR1R7 ' CMD8: R1+R7 response cmdR1 ' CMD0,A41,16: R1 response mov cmdtype, ##csmask ' returns w /CS=1(disabled) cmdxx '+-----------------------------------------------------------------------------+ outl #pinCS ' /CS=0 (enable) '+-----------------------------------------------------------------------------+ call #sendFF ' send $FF byte first mov dataout, cmdout ' CMD call #sendbyte ' send cmd byte mov dataout, cmdpar ' Parameter call #sendlong ' send 4 bytes (MSB first) mov dataout, cmdcrc ' CRC call #sendbyte ' send crc byte '+-----------------------------------------------------------------------------+ call #getreply ' recv R1/R1+R3/R1+R7/RZ..+Token '+-----------------------------------------------------------------------------+ '' outl #pinCLK ' CLK=0 (idle) already=0 or outb, cmdtype ' /CS=1(disable) if reqd '+-----------------------------------------------------------------------------+ cmdRZA41_ret '\ returns w /CS=0 (enabled) cmdRZtoken_ret '/ cmdR1R3_ret '\ cmdR1R7_ret '| returns w /CS=1 (disabled) cmdR1_ret ret '/ '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ READ REPLY: R1/R1+R3/R1+R7/R1+token + '+-----------------------------------------------------------------------------+ getreply call #recvbyte ' recv R1 byte cmp reply, #$FF wz ' reply=$FF=busy ? if_nz jmp #.doneR1 ' n: ' starttime set in CMD0(for CMD0,8,55,A41,58,16) and CMD9,10,17(readblock) getct duration '\ check timeout ? sub duration, starttime '| cmp duration, ##delay1s wc '| if_c jmp #getreply '| n: try again jmp #fail90 '/ timeout: .doneR1 mov replyR1, reply ' save R1/Token reply '+-----------------------------------------------------------------------------+ cmp cmdout, #CMD8 wz if_nz cmp cmdout, #CMD58 wz if_nz jmp #.end ' ret if not CMD8/CMD58 '+-----------------------------------------------------------------------------+ call #recvlong ' R7=CMD8=volts/R3=CMD58=OCR '+-----------------------------------------------------------------------------+ .end '\ returns with... test replyR1, #1 wz '| nc+z replyR1=$00(success) cmpr replyR1, #$01 wc '| nc+nz replyR1=$01(idle) getreply_ret ret '/ c replyR1>$01(error) '+=============================================================================+ '+-----------------------------------------------------------------------------+ '+ SD SPI Send/Recv Routines... (write/read byte/long simultaneously) + '+ /CS=0 & CLK=0 on both entry and exit + '+-----------------------------------------------------------------------------+ recvlong neg dataout, #1 ' call here to Recv a Long (+send 1's) sendlong mov bitscnt, #32 ' call here to Send a Long (long=32bits) jmp #sendrecv sendFF ' call here to Send $FF Byte recvbyte neg dataout, #1 ' call here to Recv a Byte (+send 1's) sendbyte rol dataout, #24 ' call here to Send a Byte (msbit first) mov bitscnt, #8 ' (byte=8bits) sendrecv mov reply, #0 ' clear reply .nextbit rol dataout, #1 wc ' \ prepare output bit (DI=0/1).. outl #pinCLK ' | CLK=0 (already 0 first time) outc #pinDI ' / write output bit: output on CLK falling edge nop ' | setup time 12 clocks.. nop ' | ..(not reqd, just to be safe) outh #pinCLK ' \ CLK=1 testp #pinDO wc ' | read input bit: sample on CLK rising edge rcl reply, #1 ' / accum DO input bits djnz bitscnt, #.nextbit ' 8/32 bits? outl #pinCLK ' CLK=0 on exit recvlong_ret sendlong_ret sendFF_ret recvbyte_ret sendbyte_ret ret '+=============================================================================+ '+-----------------------------------------------------------------------------+ _success call #_finishup setq #cog_len-1 ' length -1 rdlong cog_start0, ##hubdata ' copy loaded code into cog jmp #$0 ' execute loaded cog code '+-----------------------------------------------------------------------------+ _success80 call #_finishup setq #cog_len80-1 ' length -1 rdlong cog_start0, ##hubdata ' copy loaded code into cog jmp #$020 ' execute loaded cog code from $080+ '+-----------------------------------------------------------------------------+ fail100 'add x3333_0000, #2 fail98 'add x3333_0000, #1 fail97 'add x3333_0000, #7 fail90 'add x3333_0000, #32 fail58 'add x3333_0000, #3 fail55 'add x3333_0000, #14 fail41 'add x3333_0000, #24 fail17 'add x3333_0000, #1 fail16 'add x3333_0000, #8 fail08 'add x3333_0000, #8 fail00 _failure call #_finishup .loop_here jmp #.loop_here ' OR GOTO SERIAL ??? ?????????? '+-----------------------------------------------------------------------------+ _finishup ' finish up outl #pinCLK ' n: CLK=0 (idle) outh #pinCS ' n: /CS=1 (disable) ''' hubset #$FF ' set clock to 80MHz ''' nop _finishup_ret ret '+-----------------------------------------------------------------------------+ {{ +------------------------------------------------------------------------------------------------------------------------------+ | TERMS OF USE: MIT License | +------------------------------------------------------------------------------------------------------------------------------+ |Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation | |files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, | |modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software| |is furnished to do so, subject to the following conditions: | | | |The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.| | | |THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | |WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR | |COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | +------------------------------------------------------------------------------------------------------------------------------+ }}