?? 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 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