www.pudn.com > cf_sector_RW.rar > cf_routines.asm
**********************************************************************
* Code to perform CompactFlash Memory Card Operations
* Author: Miguel Hernandez IV
* Filename: cf_routines.asm
* Date: 07-30-01
* Revised: 11-04-01, minor updates to prepare for publication.
**********************************************************************
* This file contains a set of '54x code functions used to access a
* Compact Flash card. The concepts implemented here are documented
* in an application note titled, "Compact Flash Memory Card
* Interface for the TMS320VC54x", TI Literature number SPRA803.
*
* These functions are C-callable, but they can also be called from
* assembly code as long as the calling code follows the calling
* conventions. The first (left most) argument must be placed in
* accumulator A, and the remaning arguments must be placed on the
* stack in reverse order. If a value is returned, it is placed in
* in accumulator A. Here's an example of calling one of these
* functions from assembly:
*
* LD #0, A ;Put 1st arg in A
* PSHM BL ;Push next arg on stack
* LD #1, B ;Get next arg
* NOP
* PSHM BL ;Push next arg on stack
* CALL _CF_IssueCommand ;Call the function
* POPM BL ;Pop arguments off stack
* POPM BL ;Pop arguments off stack
*
* Refer to Chapter 6 of, "TMS320C54x Optimizing C/C++ Compiler
* User's Guide", TI Literature number SPRU103 for more information
* on this.
**********************************************************************
* Note: Some of the functions in this example terminate on an error
* condition by branching to the C exit function. An error flag
* is set in these functions prior to exiting. A more
* sophisticated error processing scheme should be implemented
* for real applications.
**********************************************************************
.mmregs
.include "cf_io_space.inc"
**********************************************************************
* Macros
**********************************************************************
**** Read an ATA Register
ATARegRead .macro ATAReg, RegState
CALL _CF_CheckReadyStatus
PORTR #ATAReg, *(RegState)
.endm
**** Write an ATA Register
ATARegWrite .macro ATARegParam, ATAReg
CALL _CF_CheckReadyStatus
PORTW *(ATARegParam), #ATAReg
.endm
**********************************************************************
* Function Definitions
**********************************************************************
.def _DSP_Init
.def _CF_HardwareReset
.def _CF_CheckBusyStatus
.def _CF_CheckReadyStatus
.def _CF_CheckDrqStatus
.def _CF_CheckErrorStatus
.def _CF_IssueCommand
.def _CF_IdentifyDrive
.def _ReadCF
.def _WriteCF
.def _CF_Present
.global C$$EXIT ;C exit label
**********************************************************************
* Uninitialized Variables
**********************************************************************
.bss Status, 1 ;status register state
.bss CrdHeadSt, 1
.bss ErrorSt, 1
.bss SectCntSt, 1
.bss SectNumSt, 1
.bss CylnLowSt, 1
.bss CylnHighSt, 1
.bss BusyTimeOut, 1 ;Busy Timeout Indicator
.bss RDYTimeOut, 1 ;RDY Timeout Indicator
.bss DRQTimeOut, 1 ;DRQ Timeout Indicator
.bss PhySector, 2 ;LBA
.bss SectNum, 1
.bss CylnLow, 1
.bss CylnHigh, 1
.bss CrdHead, 1
.bss SectCnt, 1
.bss Command, 1
.bss ReadBuffer, 256 ;1 sector
**********************************************************************
* Data to be written to the CompactFlash Memory Card (1 sector), is
* read from a file ("cf_write_buffer.dat"). In a real application,
* the buffer should be filled from a true data source rather than
* than this example file.
**********************************************************************
.data
WriteBuffer .copy "cf_write_buffer.dat"
**********************************************************************
**********************************************************************
* Initial LBA value
* This variable should be modified before the _CF_IssueCommand
* subroutine when the desired LBA value changes for subsequent
* CF reads and writes
**********************************************************************
.global _LBA
_LBA .ulong 6000
**********************************************************************
**********************************************************************
* Begin code section
.text
**********************************************************************
**********************************************************************
* _CF_IdentifyDrive
* Issue identify drive command
**********************************************************************
_CF_IdentifyDrive:
LD #0, A ;LBA is a dont care term for this command
LD *(_CIdentifyDrive), B ;_CIdentifyDrive
NOP
PSHM BL ;push Command on stack
LD #1, B ;SectorCount = 1
NOP
PSHM BL ;push SectorCount on stack
CALL _CF_IssueCommand ;issue Identify Drive command
POPM BL ;pop SectorCount off stack
POPM BL ;pop _CIdentifyDrive off stack
CALL _CF_CheckDrqStatus ;CF ready for data transfer?
STM #ReadBuffer, AR3 ;AR3 = IdentDrvBuf
; (beginning address)
STM #255, BRC ;loop 256 times
RPTB done-1
PORTR #WrdDataReg, *AR3+ ;read 256 words
; (1 sector = 512 bytes)
; from the CF Data
; Register
done:
CALL _CF_CheckReadyStatus ;cf ready?
RET ;return
**********************************************************************
* _CF_CheckBusyStatus
* Routine to check the BUSY bit in the Status Register
* * BUSY = 1 => CompactFlash is Busy
* if routine times out, set BusyTimeOut and exit
* * BUSY = 0 => CompactFlash is not Busy
**********************************************************************
_CF_CheckBusyStatus:
ST #0, *(BusyTimeOut) ;initialize BusyTimeOut indicator
STM #5000, BRC ;BRC = 5000
RPTB BusyStatusLoop-1 ;loop
PORTR #StatusReg, *(Status) ;read the status register, save
; state in 'Status'
STM #Status, AR2 ;AR2 = Status
***** BUSY = 1?
BIT *AR2, #15-7 ;TC = D7 = BUSY Bit
NOP
NOP
BC Not_Busy, NTC ;loop until BUSY = 0
; or until the process times out
RPT #0x7FFF ;delay
NOP
BusyStatusLoop:
ST #1, *(BusyTimeOut) ;CheckBusyStatus has timed out
NOP
NOP
B C$$EXIT ;exit
Not_Busy: ;CF is not Busy
RET
**********************************************************************
* _CF_CheckReadyStatus
* CheckReadyStatus
* Routine to check the RDY bit in the Status Register
* RDY indicates when the CompactFlash is ready to perform operations
* * RDY = 0 => not ready
* * RDY = 1 => ready
*
* * Initialize timeout variable
* * Initialize Card/Head Register with Drive 0 and LBA mode
* * Checks the Busy status
* * Wait for RDY = 1
* * if RDY = 0, decrement TimeOut
* - software delay
* - if TimeOut = 0, exit and set RDYTimeOut
**********************************************************************
_CF_CheckReadyStatus:
CALL _CF_CheckBusyStatus
ST #0, *(RDYTimeOut) ;initialize RDYTimeOut indicator
STM #5000, BRC ;BRC = 5000
RPTB ReadyStatusLoop-1 ;loop
PORTR #StatusReg, *(Status) ;read the status register, save
; state in 'Status'
STM #Status, AR2 ;AR2 = Status
***** RDY = 1?
BIT *AR2, #15-6 ;TC = D6 = RDY Bit
BC Ready, TC ;loop until RDY = 1
; or until the process times out
RPT #0x7FFF ;delay
NOP
ReadyStatusLoop:
ST #1, *(RDYTimeOut) ;CheckReadyStatus has timed out
NOP
NOP
B C$$EXIT ;exit
Ready: ;CF is ready
CALL _CF_CheckErrorStatus
RET
**********************************************************************
* _CF_CheckDrqStatus
* Routine to check the DRQ bit in the Status Register
* * DRQ = 1 => CompactFlash ready for data transfer
*
* * Initialize timeout variable
* - Wait for DRQ = 1
* - if DRQ = 0, decrement TimeOut
* - software delay
* - if TimeOut = 0, exit and set DRQTimeOut
**********************************************************************
_CF_CheckDrqStatus:
ST #0, *(DRQTimeOut) ;initialize DRQTimeOut indicator
STM #5000, BRC ;BRC = 5000
RPTB DRQStatusLoop-1 ;loop
PORTR #StatusReg, *(Status);read the status register, save
; state in 'Status'
STM #Status, AR2 ;AR2 = Status
***** DRQ = 1?
BIT *AR2, #15-3 ;TC = D3 = DRQ Bit
BC DRQ_Ready, TC ;loop until DRQ = 1
; or until the process times out
RPT #0x7FFF ;delay
NOP
DRQStatusLoop:
ST #1, *(DRQTimeOut) ;CheckDrqStatus has timed out
NOP
NOP
B C$$EXIT ;exit
DRQ_Ready: ;CF is ready for data transfer
RET
**********************************************************************
* _DSP_Init
* Routine to initalize the C54x
**********************************************************************
_DSP_Init:
STM #0xFFA8, PMST
STM #0x7000, SWWSR ;max amt of wait-states
STM #0x8002, BSCR ;BH = 1, EXIO = 0
STM #0x0000, 0x002B ;SWWSM = 0
STM #0,CLKMD
RPT #100
NOP
STM #0x4007,CLKMD
RSBX SXM ;disable sign extension
RET
**********************************************************************
* _CF_HardwareReset
* Routine to issue a hardware reset. The XF pin is used to control
* CF card reset. XF must be asserted for at least 25us (microseconds)
**********************************************************************
_CF_HardwareReset:
RSBX XF ;assert /RESET
RPT #07FFFh
NOP
RPT #07FFFh
NOP
SSBX XF ;deassert /RESET
CALL _CF_CheckReadyStatus
RET
**********************************************************************
* _CF_IssueCommand
* Routine to issue commands to the CompactFlash.
* * initializes the Sector Count, Sector Number, Cylinder High/Low,
* Card/Head, and Command Registers
* * uses bitwise AND and OR operations to set the LBA
**********************************************************************
_CF_IssueCommand:
RSBX SXM ;disable sign extension -RDP-
STL A, *(PhySector+1) ;save first arg (PhysicalSector) in LBA
STH A, *(PhySector)
nop
nop
nop
nop
LD *SP(1), A ;load arg SectorCount in A
STL A, *(SectCnt) ;save SectorCount in SectCnt
LD *SP(2), A ;load arg Command in A
STL A, *(Command) ;save Command in variable Command
**** write sector count register
ATARegWrite SectCnt, SectCntReg
**** initialize A Accumulator with low word in variable LBA
LD *(PhySector+1), A
**** load Sector Number Register
LD #0x000000FF, B
AND A, B ;clear unwanted bits
STL B, *(SectNum) ;save in SectNum
ATARegWrite SectNum, SectNumReg
**** load Cylinder Low Register
LD #0x0000FF00, B
AND A, B ;clear unwanted bits
STL B, -8, *(CylnLow) ;save in CylnLow
ATARegWrite CylnLow, CylnLowReg
**** initialize A Accumulator with high word in variable LBA
LD *(PhySector), A
**** load Cylinder High Register
LD #0x000000FF, B
AND A, B ;clear unwanted bits
STL B, *(CylnHigh) ;save in CylnHigh
ATARegWrite CylnHigh, CylnHighReg
**** load Card/Head Register
LD #0x0000000F, B
AND A,-8, B ;clear unwanted bits
LD #0xe0, A ;LBA = 1, DRV = 0
; LBA(27-24) = 0
OR A, B
STL B, *(CrdHead) ;initalize LBA(27-24)
ATARegWrite CrdHead, CrdHeadReg
**** write command register
ATARegWrite Command, CommandReg
RET
**********************************************************************
* _ReadCF
* Read from the CompactFlash
*
* * issue read command
* * if Sector Count Register = 0 => 256 sectors to transfer
* * A: Check DRQ
* * read 1 sector
* * multiple sector transfers? continue from A:
**********************************************************************
_ReadCF:
***** Prepare the parameters that are to be passed to _CF_IssueCommand
LD *(_CReadSectors), B ;_CReadSectors
NOP ;clear pipeline conflict
PSHM BL ;push Command on stack
LD *SP(1), B ;load SectorCount in B
NOP
PSHM BL ;push SectorCount on stack
STLM B, AR4 ;store SectorCount in AR4
STM #0, AR0 ;store zero in AR0
***** Determine the number of sectors that are to be transferred
CMPR EQ, AR4 ;SectorCount = 0?
;TC=1 Yes
;TC=0 No
NOP ;NOP to prepare for XC
XC 2, TC ;If SectorCount = 0
STM #256, AR3 ; XferSectors = 256
XC 2, NTC ;Else
STLM B, AR3 ; XferSectors = SectorCount
NOP
***** Issue the Read Sectors Command
CALL _CF_IssueCommand ;issue Read Sectors command
POPM BL ;pop SectorCount off stack
POPM BL ;pop _CReadSectors off stack
***** the BANZ mnemonic checks XferSectors at the end of the
***** read process. XferSectors must be subtracted by one so
***** that the correct number of sectors are transferred
LDM AR3, B
SUB #1, B ;XferSectors = XferSectors-1
STLM B, AR3
***** Read from the CompactFlash
read_outer:
CALL _CF_CheckDrqStatus ;CF ready for data transfer?
STM #ReadBuffer, AR5 ;AR5 = ReadBuffer (beginning address)
RPT #255
PORTR #WrdDataReg, *AR5+ ;read 256 words
; (1 sector = 512 bytes)
; from the CF Data
; Register
**********************************************************************
* - the data read into ReadBuffer should be processed at this point
* - array ReadBuffer will be overwritten during multiple sector
* transfers
**********************************************************************
BANZ read_outer, *AR3- ;loop until all sectors have been
; transferred
CALL _CF_CheckBusyStatus
RET
**********************************************************************
* _WriteCF
**********************************************************************
_WriteCF:
***** Prepare the parameters that are to be passed to _CF_IssueCommand
LD *(_CWriteSectors), B ;_CWriteSectors
NOP ;clear pipeline conflict
PSHM BL ;push Command on stack
LD *SP(1), B ;load SectorCount in B
NOP
PSHM BL ;push SectorCount on stack
STLM B, AR4 ;store SectorCount in AR4
STM #0, AR0 ;store zero in AR0
***** Determine the number of sectors that are to be transferred
CMPR EQ, AR4 ;SectorCount = 0?
;TC=1 Yes
;TC=0 No
NOP ;NOP to prepare for XC
XC 2, TC ;If SectorCount = 0
STM #256, AR3 ; XferSectors = 256
XC 2, NTC ;Else
STLM B, AR3 ; XferSectors = SectorCount
NOP
***** Issue the Write Sectors Command
CALL _CF_IssueCommand ;issue Write Sectors command
POPM BL ;pop SectorCount off stack
POPM BL ;pop _CWriteSectors off stack
***** the BANZ mnemonic checks XferSectors at the end of the
***** read process. XferSectors must be subtracted by one so
***** that the correct number of sectors are transferred
LDM AR3, B
SUB #1, B ;XferSectors = XferSectors-1
STLM B, AR3
***** Write to the CompactFlash
write_outer:
CALL _CF_CheckDrqStatus ;CF ready for data transfer?
addm #1,*(WriteBuffer)
STM #WriteBuffer, AR5 ;AR5 = WriteBuffer (beginning address)
STM #255,BRC
RPTB WRITE_DATA-1
PORTW *AR5+, #WrdDataReg ;read 256 words
; (1 sector = 512 bytes)
; from the CF Data
; Register
NOP
WRITE_DATA:
**********************************************************************
* - the data written into WriteBuffer should be updated with new
* data here. This updated data will be written to the CompactFlash.
* if WriteBuffer is not updated, the previous data will be duplicated
* in the CompactFlash
**********************************************************************
nop
nop
BANZ write_outer, *AR3- ;loop until all sectors have been
; transferred
CALL _CF_CheckBusyStatus
RET
**********************************************************************
* _CF_CheckErrorStatus
* Routine to check the ERR bit in the Status Register
* if ERR = 1, read the Error Register, save state in
* ErrorSt, and exit
**********************************************************************
_CF_CheckErrorStatus:
ST #0, *(ErrorSt) ;initialize ErrorSt to zero
PORTR #StatusReg, *(Status) ;read status register
STM #Status, AR2 ;AR2=Status
***** ERR = 1?
BIT*AR2, #15-0 ;TC = D0 = ERR bit
NOP
NOP
BC No_Error, NTC ;ERR = 0 => end routine
;ERR = 1 => read error register
Error:
PORTR #ErrorReg, *(ErrorSt) ;read error register and save state
NOP
NOP
B C$$EXIT ;exit
No_Error:
RET
**********************************************************************
* _CF_Present
* This routine checks to see if the CompactFlash is properly
* inserted in its socket. Since this code is not written to
* support hotplug, the status is only checked once. If the
* card is not present then the system will have to be powered
* down for card insertion.
* If the card is deteced, the function returns a true value,
* otherwise a false value is returned.
* - This routine should be modified to handle specific system
* requirements
**********************************************************************
_CF_Present:
LD #0, A ;Set return value to false
BC not_inserted, NBIO ;BIO = 1 => CF not inserted correctly
;BIO = 0 => CF inserted correctly
NOP
NOP
LD #1, A ;Set return value to true
RET ;Card present, return normally
not_inserted: ;Card not present
RET ;exit
**********************************************************************
; THIS PROGRAM IS PROVIDED "AS IS". TI MAKES NO WARRANTIES OR
; REPRESENTATIONS, EITHER EXPRESS, IMPLIED OR STATUTORY,
; INCLUDING ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
; FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
; COMPLETENESS OF RESPONSES, RESULTS AND LACK OF NEGLIGENCE.
; TI DISCLAIMS ANY WARRANTY OF TITLE, QUIET ENJOYMENT, QUIET
; POSSESSION, AND NON-INFRINGEMENT OF ANY THIRD PARTY
; INTELLECTUAL PROPERTY RIGHTS WITH REGARD TO THE PROGRAM OR
; YOUR USE OF THE PROGRAM.
;
; IN NO EVENT SHALL TI BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
; CONSEQUENTIAL OR INDIRECT DAMAGES, HOWEVER CAUSED, ON ANY
; THEORY OF LIABILITY AND WHETHER OR NOT TI HAS BEEN ADVISED
; OF THE POSSIBILITY OF SUCH DAMAGES, ARISING IN ANY WAY OUT
; OF THIS AGREEMENT, THE PROGRAM, OR YOUR USE OF THE PROGRAM.
; EXCLUDED DAMAGES INCLUDE, BUT ARE NOT LIMITED TO, COST OF
; REMOVAL OR REINSTALLATION, COMPUTER TIME, LABOR COSTS, LOSS
; OF GOODWILL, LOSS OF PROFITS, LOSS OF SAVINGS, OR LOSS OF
; USE OR INTERRUPTION OF BUSINESS. IN NO EVENT WILL TI'S
; AGGREGATE LIABILITY UNDER THIS AGREEMENT OR ARISING OUT OF
; YOUR USE OF THE PROGRAM EXCEED FIVE HUNDRED DOLLARS
; (U.S.$500).
;
; Unless otherwise stated, the Program written and copyrighted
; by Texas Instruments is distributed as "freeware". You may,
; only under TI's copyright in the Program, use and modify the
; Program without any charge or restriction. You may
; distribute to third parties, provided that you transfer a
; copy of this license to the third party and the third party
; agrees to these terms by its first use of the Program. You
; must reproduce the copyright notice and any other legend of
; ownership on each copy or partial copy, of the Program.
;
; You acknowledge and agree that the Program contains
; copyrighted material, trade secrets and other TI proprietary
; information and is protected by copyright laws,
; international copyright treaties, and trade secret laws, as
; well as other intellectual property laws. To protect TI's
; rights in the Program, you agree not to decompile, reverse
; engineer, disassemble or otherwise translate any object code
; versions of the Program to a human-readable form. You agree
; that in no event will you alter, remove or destroy any
; copyright notice included in the Program. TI reserves all
; rights not specifically granted under this license. Except
; as specifically provided herein, nothing in this agreement
; shall be construed as conferring by implication, estoppel,
; or otherwise, upon you, any license or other right under any
; TI patents, copyrights or trade secrets.
;
; You may not use the Program in non-TI devices.