URL
https://opencores.org/ocsvn/rtf65002/rtf65002/trunk
Subversion Repositories rtf65002
[/] [rtf65002/] [trunk/] [software/] [asm/] [SDCard.asm] - Rev 40
Compare with Previous | Blame | View Log
; ============================================================================; __; \\__/ o\ (C) 2013, 2014 Robert Finch, Stratford; \ __ / All rights reserved.; \/_// robfinch<remove>@opencores.org; ||;;; This source file is free software: you can redistribute it and/or modify; it under the terms of the GNU Lesser General Public License as published; by the Free Software Foundation, either version 3 of the License, or; (at your option) any later version.;; This source file is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program. If not, see <http://www.gnu.org/licenses/>.;; SDCard.asm; ============================================================================;cpu RTF65002.codealign 4;------------------------------------------------------------------------------; Static device control block (SDBC) structure;------------------------------------------------------------------------------public SDCardDCB:align 4db "CARD1 " ; namedw 5 ; number of chars in namedw 16 ; typedw 1 ; nBPBdw 0 ; last ercdw 8388608 ; nBlocksdw SDCmdProcdw SDInitdw SDStatdw 1 ; reentrancy count (1 to 255 are valid)dw 0 ; single userdw 0 ; hJobdw 0 ; OSD1dw 0 ; OSD2dw 0 ; OSD3dw 0 ; OSD4dw 0 ; OSD5dw 0 ; OSD6SDOpTbl:dw SDNopdw SDInitdw SDMediaCheckdw SDBuildBPBdw SDNop ; GetChar ; GetChar()dw SDNop ; CheckForChar ; PeekChar()dw SDNop ; GetCharDirect ; unbuffered GetChar()dw SDNop ; CheckForCharDirect ; unbuffered PeekChar()dw SDNop ; PutChar ; KeybdPutChardw SDNop ; SetEchodw SDSetpos ; set positiondw SDReadBlocks ; block readdw SDWriteBlocks ; block writedw SDNopdw SDNopdw SDNopSDStat:rtsSDBuildBPB:rtsSDSetpos:rts;;------------------------------------------------------------------------------; SDCmdProc:; Device command processor.;; Parameters:; r1 = device #; r2 = opcode; r3 = position; r4 = number of blocks; r5 = pointer to data area;------------------------------------------------------------------------------SDCmdProc:cmp #16bne .0001phxphypush r4push r5mul r1,r1,#DCB_SIZE ; convert device number to DCB pointeradd #DCBsld r0,DCB_pDevInit,r1 ; check for an initialization routinebeq .0002 ; to see if device presentcmp r2,#MAX_DEV_OPbhi .0003pha ; save off DCB pointerjsr (SDOpTbl>>2,x)plxsta DCB_last_erc,x ; stuff the error return code in the DCB.ret:pop r5pop r4plyplxrts.0001:lda #E_BadDevNumrts.0002:lda #E_NoDevbra .ret.0003:lda #E_BadDevOpbra .ret;------------------------------------------------------------------------------; SDNop:; No-operation routine.;------------------------------------------------------------------------------SDNop:lda #E_Okrts;------------------------------------------------------------------------------;------------------------------------------------------------------------------SDMediaCheck:lda #E_Okrts;------------------------------------------------------------------------------; Initialize the SD card; Returns; acc = 0 if successful, 1 otherwise; Z=1 if successful, otherwise Z=0;------------------------------------------------------------------------------;message "SDInit"public SDInit:lda #SPI_INIT_SDsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnop.spi_init1lda SPIMASTER+SPI_TRANS_STATUS_REGnopnopcmp #SPI_TRANS_BUSYbeq .spi_init1lda SPIMASTER+SPI_TRANS_ERROR_REGand #3cmp #SPI_INIT_NO_ERRORbne spi_error; lda #spi_init_ok_msg; jsr DisplayStringBlda #0rtsspi_errorjsr DisplayBytelda #spi_init_error_msgjsr DisplayStringBlda SPIMASTER+SPI_RESP_BYTE1jsr DisplayBytelda SPIMASTER+SPI_RESP_BYTE2jsr DisplayBytelda SPIMASTER+SPI_RESP_BYTE3jsr DisplayBytelda SPIMASTER+SPI_RESP_BYTE4jsr DisplayBytelda #1rtsspi_delay:nopnoprts;------------------------------------------------------------------------------; SD read sector;; r1= sector number to read; r2= address to place read data; Returns:; r1 = 0 if successful;------------------------------------------------------------------------------;public SDReadSector:phxphypush r4sta SPIMASTER+SPI_SD_SECT_7_0_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_15_8_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_23_16_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_31_24_REGld r4,#20 ; retry count.spi_read_retry:; Force the reciever fifo to be empty, in case a prior error leaves it; in an unknown state.lda #1sta SPIMASTER+SPI_RX_FIFO_CTRL_REGlda #RW_READ_SD_BLOCKsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnop.spi_read_sect1:lda SPIMASTER+SPI_TRANS_STATUS_REGjsr spi_delay ; just a delay between consecutive status reg readscmp #SPI_TRANS_BUSYbeq .spi_read_sect1lda SPIMASTER+SPI_TRANS_ERROR_REGlsrlsrand #3cmp #SPI_READ_NO_ERRORbne .spi_read_errorldy #512 ; read 512 bytes from fifo.spi_read_sect2:lda SPIMASTER+SPI_RX_FIFO_DATA_REGsb r1,0,xinxdeybne .spi_read_sect2lda #0bra .spi_read_ret.spi_read_error:dec r4bne .spi_read_retryjsr DisplayBytelda #spi_read_error_msgjsr DisplayStringBlda #1.spi_read_ret:pop r4plyplxrts;------------------------------------------------------------------------------; BlocksToSectors:; Convert a logical block number (LBA) to a sector number;------------------------------------------------------------------------------BlocksToSectors:asl r1,r1,#1 ; 1k blocks = 2 sectorsrts;------------------------------------------------------------------------------; SDReadBlocks:;; Registers Affected: r1-r5; Parameters:; r1 = pointer to DCB; r3 = block number; r4 = number of blocks; r5 = pointer to data area;------------------------------------------------------------------------------public SDReadBlocks:cpy DCB_nBlocks,r1bhs .0002add r2,r3,r4cpx DCB_nBlocks,r1bhi .0003ld r2,r5 ; x = pointer to data buffertyajsr BlocksToSectors ; acc = sector numberphald r1,r4jsr BlocksToSectorstay ; y = # of blocks to readpla ; acc = sector number againjsr SDReadMultiplecmp #0bne .0001lda #E_Okrts.0001lda #E_ReadErrorrts.0002lda #E_BadBlockNumrts.0003:lda #E_TooManyBlocksrts;------------------------------------------------------------------------------; SDWriteBlocks:;; Parameters:; r1 = pointer to DCB; r3 = block number; r4 = number of blocks; r5 = pointer to data area;------------------------------------------------------------------------------public SDWriteBlocks:cpy DCB_nBlocks,r1bhs .0002add r2,r3,r4cpx DCB_nBlocks,r1bhi .0003ld r2,r5 ; x = pointer to data buffertyajsr BlocksToSectors ; acc = sector numberphald r1,r4jsr BlocksToSectorstay ; y = # of blocks to readpla ; acc = sector number againjsr SDWriteMultiplecmp #0bne .0001lda #E_Okrts.0001lda #E_WriteErrorrts.0002lda #E_BadBlockNumrts.0003:lda #E_TooManyBlocksrts;------------------------------------------------------------------------------; SDWriteSector:;; r1= sector number to write; r2= address to get data from; Returns:; r1 = 0 if successful;------------------------------------------------------------------------------;public SDWriteSector:phxphypha; Force the transmitter fifo to be empty, in case a prior error leaves it; in an unknown state.lda #1sta SPIMASTER+SPI_TX_FIFO_CTRL_REGnop ; give I/O time to respondnop; now fill up the transmitter fifoldy #512.spi_write_sect1:lb r1,0,xsta SPIMASTER+SPI_TX_FIFO_DATA_REGnop ; give the I/O time to respondnopinxdeybne .spi_write_sect1; set the sector number in the spi master address registersplasta SPIMASTER+SPI_SD_SECT_7_0_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_15_8_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_23_16_REGlsr r1,r1,#8sta SPIMASTER+SPI_SD_SECT_31_24_REG; issue the write commandlda #RW_WRITE_SD_BLOCKsta SPIMASTER+SPI_TRANS_TYPE_REGlda #SPI_TRANS_STARTsta SPIMASTER+SPI_TRANS_CTRL_REGnop.spi_write_sect2:lda SPIMASTER+SPI_TRANS_STATUS_REGnop ; just a delay between consecutive status reg readsnopcmp #SPI_TRANS_BUSYbeq .spi_write_sect2lda SPIMASTER+SPI_TRANS_ERROR_REGlsr r1,r1,#4and #3cmp #SPI_WRITE_NO_ERRORbne .spi_write_errorlda #0bra .spi_write_ret.spi_write_error:jsr DisplayBytelda #spi_write_error_msgjsr DisplayStringBlda #1.spi_write_ret:plyplxrts;------------------------------------------------------------------------------; SDReadMultiple: read multiple sectors;; r1= sector number to read; r2= address to write data; r3= number of sectors to read;; Returns:; r1 = 0 if successful;;------------------------------------------------------------------------------public SDReadMultiple:push r4ld r4,#0.spi_rm1:phajsr SDReadSectoradd r4,r4,r1add r2,r2,#512plainadeybne .spi_rm1ld r1,r4pop r4rts;------------------------------------------------------------------------------; SPI write multiple sector;; r1= sector number to write; r2= address to get data from; r3= number of sectors to write;; Returns:; r1 = 0 if successful;------------------------------------------------------------------------------;public SDWriteMultiple:push r4ld r4,#0.spi_wm1:phajsr SDWriteSectoradd r4,r4,r1 ; accumulate an error countadd r2,r2,#512 ; 512 bytes per sectorplainadeybne .spi_wm1ld r1,r4pop r4rts;------------------------------------------------------------------------------; read the partition table to find out where the boot sector is.; Returns; r1 = 0 everything okay, 1=read error; also Z=1=everything okay, Z=0=read error;------------------------------------------------------------------------------public SDReadPart:phxstz startSector ; default starting sectorlda #0 ; r1 = sector number (#0)ldx #BYTE_SECTOR_BUF ; r2 = target address (word to byte address)jsr SDReadSectorcmp #0bne .spi_rp1lb r1,BYTE_SECTOR_BUF+$1C9asl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1C8asl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1C7asl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1C6sta startSector ; r1 = 0, for okay statuslb r1,BYTE_SECTOR_BUF+$1CDasl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1CCasl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1CBasl r1,r1,#8orb r1,r1,BYTE_SECTOR_BUF+$1CAsta disk_size ; r1 = 0, for okay statusplxlda #0rts.spi_rp1:plxlda #1rts;------------------------------------------------------------------------------; Read the boot sector from the disk.; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.; Returns:; r1 = 0 means this card is bootable; r1 = 1 means a read error occurred; r1 = 2 means the card is not bootable;------------------------------------------------------------------------------public SDReadBoot:phxphypush r5lda startSector ; r1 = sector numberldx #BYTE_SECTOR_BUF ; r2 = target addressjsr SDReadSectorcmp #0bne spi_read_boot_errlb r1,BYTE_SECTOR_BUFcmp #$EBbne spi_eb_errspi_read_boot2:lda #msgFoundEBjsr DisplayStringBlb r1,BYTE_SECTOR_BUF+$1FE ; check for 0x55AA signaturecmp #$55bne spi_eb_errlb r1,BYTE_SECTOR_BUF+$1FF ; check for 0x55AA signaturecmp #$AAbne spi_eb_errpop r5plyplxlda #0 ; r1 = 0, for okay statusrtsspi_read_boot_err:pop r5plyplxlda #1rtsspi_eb_err:lda #msgNotFoundEBjsr DisplayStringBpop r5plyplxlda #2rtsmsgFoundEB:db "Found EB code.",CR,LF,0msgNotFoundEB:db "EB/55AA Code missing.",CR,LF,0
