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.