;*************************************************************************** ; ; File Name :'cf.asm" ; Title :Compact Flash Common Memory Mode Driver ; Date :2004.05.12. ; Version :1.0.0 ; Support telephone :+36-70-333-4034, old: +36-30-9541-658 VFX ; Support fax : ; Support Email :info@vfx.hu ; Target MCU :AVR ; ;*************************************************************************** ; D E S C R I P T I O N ; ; Memory Interface to a compact flash card. ; Compact flash card is used in memory mapped mode. ; Registers are located at ADR_CFC in external RAM space of Mega128 ; ; ;*************************************************************************** ; M O D I F I C A T I O N H I S T O R Y ; ; ; rev. date who why ; ---- ---------- --- ------------------------------------ ; 0.01 2004.05.12 VFX Creation ; ;*************************************************************************** ;Hardware ;*************************************************************************** ;* ;* SYSCLK: f=16.000 MHz (T= 62.5 ns) ;* ;*************************************************************************** ; ; ;************************************************************************** ;* Hardware Def. ; ; CompactFlash hardware definitions ; Table 34: Memory Mapped Decoding ; -REG A10 A9-A4 A3 A2 A1 A0 Offset -OE=0 -WE=0 Notes ; 1 0 X 0 0 0 0 0 Even RD Data Even WR Data 1, 2 ; 1 0 X 0 0 0 1 1 Error Features 1, 2 ; 1 0 X 0 0 1 0 2 Sector Count Sector Count ; 1 0 X 0 0 1 1 3 Sector No. Sector No. ; 1 0 X 0 1 0 0 4 Cylinder Low Cylinder Low ; 1 0 X 0 1 0 1 5 Cylinder High Cylinder High ; 1 0 X 0 1 1 0 6 Select Card/Head Select Card/Head ; 1 0 X 0 1 1 1 7 Status Command ; 1 0 X 1 0 0 0 8 Dup. Even RD Data Dup. Even WR Data 2 ; 1 0 X 1 0 0 1 9 Dup. Odd RD Data Dup. Odd WR Data 2 ; 1 0 X 1 1 0 1 D Dup. Error Dup. Features 2 ; 1 0 X 1 1 1 0 E Alt Status Device Ctl ; 1 0 X 1 1 1 1 F Drive Address Reserved ; 1 1 X X X X 0 8 Even RD Data Even WR Data 3 ; 1 1 X X X X 1 9 Odd RD Data Odd WR Data 3 ;Note: 1) Register 0 is accessed with -CE1 low and -CE2 low as a word register ;on the combined Odd Data Bus and Even Data Bus (D15-D0). This register may ;also be accessed by a pair of byte accesses to the offset 0 with -CE1 low and ;-CE2 high. Note that the address space of this word register overlaps ;the address space of the Error and Feature byte-wide registers that lie at ;offset 1. When accessed twice as byte register with -CE1 low, the first byte ;to be accessed is the even byte of the word and the second byte accessed ;is the odd byte of the equivalent word access. ;A byte access to address 0 with -CE1 high and -CE2 low accesses the error ;(read) or feature (write) register. ;2) Registers at offset 8, 9 and D are non-overlapping duplicates of the ;registers at offset 0 and 1. Register 8 is equivalent to register 0, ;while register 9 accesses the odd byte. Therefore, if the registers are byte ;accessed in the order 9 then 8 the data will be transferred odd byte then even ;byte. Repeated byte accesses to register 8 or 0 will access consecutive ;(even then odd) bytes from the data buffer. Repeated word accesses to register ;8, 9 or 0 will access consecutive words from the data buffer. Repeated byte ;accesses to register 9 are not supported. However, repeated alternating byte ;accesses to registers 8 then 9 will access consecutive (even then odd) bytes ;from the data buffer. Byte accesses to register 9 access only the odd byte of ;the data. ;3) Accesses to even addresses between 400h and 7FFh access register 8. ;Accesses to odd addresses between 400h and 7FFh access register 9. This ;1 Kbyte memory window to the data register is provided so that hosts can ;perform memory to memory block moves to the data register when the register ;lies in memory space. ; ; ;CF register addresses ; .equ CF_EvenData = ADR_CFC+0x08 ;Dupl. DAta .equ CF_OddData = ADR_CFC+0x09 ;Dupl. Data .equ CF_Error = ADR_CFC+0x0D ;Dupl. Errors / Features .equ CF_SECCOUNT = ADR_CFC+0x02 ;Sectorcount .equ CF_LBA0 = ADR_CFC+0x03 ;LBA 0-7 .equ CF_LBA1 = ADR_CFC+0x04 ;LBA 8-15 .equ CF_LBA2 = ADR_CFC+0x05 ;LBA 16-23 .equ CF_LBA3 = ADR_CFC+0x06 ;LBA 24-27 .equ CF_STACOM = ADR_CFC+0x07 ;Status / Command .equ CF_DecCont = ADR_CFC+0x0E ; ;Class 1 ;Upon receipt of a Class 1 command, the CompactFlash Storage Card sets BSY ;within 400 nsec. ;Class 2 ;Upon receipt of a Class 2 command, the CompactFlash Storage Card sets BSY ;within 400 nsec, sets up the sector buffer for a write operation, sets DRQ ;within 700 usec, and clears BSY within 400 nsec of setting DRQ. ;Class 3 ;Upon receipt of a Class 3 command, the CompactFlash Storage Card sets BSY ;within 400 nsec, sets up the sector buffer for a write operation, sets DRQ ;within 20 msec (assuming no re-assignments), and clears BSY within 400 nsec ;of setting DRQ. ;Table 37: CF-ATA Command Set ; ;Class COMMAND Code FR SC SN CY DH LBA ;1 Check Power Mode E5h or 98h - - - - D - ;1 Execute Drive Diagnostic 90h - - - - D - ;1 Erase Sector(s) C0h - Y Y Y Y Y ;1 Flush Cache E7h - - - - D - ;2 Format Track 50h - Y - Y Y Y ;1 Identify Drive ECh - - - - D - ;1 Idle E3h or 97h - Y - - D - ;1 Idle Immediate E1h or 95h - - - - D - ;1 Initialize Drive Parameters 91h - Y - - Y - ;1 Key Management Structure Read B9 Feature 0-127 C C C C D C - ;1 Key Management Read Keying Material B9 Feature 80 C C C C D C - ;2 Key Management Change Key Management Value B9 Feature 81 C C C C D C - ;1 NOP 00h - - - - D - ;1 Read Buffer E4h - - - - D - ;1 Read Long Sector 22h or 23h - - Y Y Y Y ;1 Read Multiple C4h - Y Y Y Y Y ;1 Read Sector(s) 20h or 21h - Y Y Y Y Y ;1 Read Verify Sector(s) 40h or 41h - Y Y Y Y Y ;1 Recalibrate 1Xh - - - - D - ;1 Request Sense 03h - - - - D - ;1 Security Disable Password F6h - - - - D - ;1 Security Erase Prepare F3h - - - - D - ;1 Security Erase Unit F4h - - - - D - ;1 Security Freeze Lock F5h - - - - D - ;1 Security Set Password F1h - - - - D - ;1 Security Unlock F2h - - - - D - ;1 Seek 7Xh - - Y Y Y Y ;1 Set Features EFh Y - - - D - ;1 Set Multiple Mode C6h - Y - - D - ;1 Set Sleep Mode E6h or 99h - - - - D - ;1 Standby E2h or 96h - - - - D - ;1 Standby Immediate E0h or 94h - - - - D - ;1 Translate Sector 87h - Y Y Y Y Y ;1 Wear Level F5h - - - - Y - ;2 Write Buffer E8h - - - - D - ;2 Write Long Sector 32h or 33h - - Y Y Y Y ;3 Write Multiple C5h - Y Y Y Y Y ;3 Write Multiple w/o Erase CDh - Y Y Y Y Y ;2 Write Sector(s) 30h or 31h - Y Y Y Y Y ;2 Write Sector(s) w/o Erase 38h - Y Y Y Y Y ;3 Write Verify 3Ch - Y Y Y Y Y ; ;Definitions: ;FR = Features Register ;SC = Sector Count Register ;SN = Sector Number Register ;CY = Cylinder Registers ;DH = Card/Drive/Head Register ;LBA = Logical Block Address Mode Supported (see command descriptions for use). ;Y - The register contains a valid parameter for this command. For the Drive/Head Register Y ;means both the CompactFlash Storage Card and head parameters are used; D - only the ;CompactFlash Storage Card parameter is valid and not the head parameter; C - The register ;contains command specific data (see command descriptions for use). ; ;CF-ATA Command Set .equ CF_CMD_READ_SEC = 0x20 .equ CF_CMD_WRITE_SEC = 0x30 .equ CF_CMD_IDENTIFY = 0xEC .equ CFRDY = 2 ;bit 2 = 1 CF ready .equ CFVS1 = 3 ;bit 3 = 0 CF in slot ;*************************************************************************************** ;*** Definition of the status register bits ;*** ;*** Bit7 Bit0 ;*** BSY DRDY DWF DSC DRQ CORR IDX ERR ;*************************************************************************************** .equ CFC_STATUS_BSY = 0x80 ;Busy flag .equ CFC_STATUS_DRDY = 0x40 ;Drive ready .equ CFC_STATUS_DWF = 0x20 ;Drive write fault .equ CFC_STATUS_DSC = 0x10 ;Drive seek complete .equ CFC_STATUS_DRQ = 0x08 ;Data request .equ CFC_STATUS_CORR = 0x04 ;Corrected data .equ CFC_STATUS_IDX = 0x02 ;Index .equ CFC_STATUS_ERR = 0x01 ;Error ; ;*************************************************************************** ;**** VARIABLES .DSEG ;*************************************************************************** .ESEG ;*************************************************************************** ;**** CODE SEG ;*************************************************************************** .CSEG ;******************************************************** ;CFRdy ; ; Wait until CF not busy ; ; Out: c= 0 no error ; 1 error ; ; Alt: R16,R17 ; CFHWRdy: lds R16,ADR_CFST bst R16,CFVS1 ;CF inserted? brtc CFHWRdy0 rjmp CFDrvError CFHWRdy0: lds R16,ADR_CFST bst R16,CFRDY ;CF ready? brtc CFHWRdy clc ret ;******************************************************** ;CFWaitDRQ ; ; Wait until Data will available ; ; Out: c= 0 no error ; 1 error ; ; Alt: R16,R17 ; CFWaitDRQ: rcall CFHWRdy brcc CFWaitDRQ00 ret CFWaitDRQ00: lds R16,CF_STACOM bst R16,0 brtc CFWaitDRQ0 CFWaitErr: ldi R16,low(0xFFF0) ;Error in last command ldi R17,high(0xFFF0) ;ide keresunk egy error kodot!!! sec ret CFWaitDRQ0: andi R16,0xF8 cpi R16,0x58 brne CFWaitDRQ clc ret ;******************************************************** ;CFWaitReady ; ; Wait until CF will ready ; ; Out: c= 0 no error ; 1 error ; ; Alt: R16,R17 ; CFWaitReady: rcall CFHWRdy brcc CFWaitRdy0 ret CFWaitRdy0: lds R16,CF_STACOM bst R16,0 brts CFWaitErr CFWaitReady01: andi R16,0xF0 cpi R16,0x50 brne CFWaitReady clc ret ;******************************************************** ;CFReadSector ; ; In: R13:R12:R11:R10 - LBA sector number ; Page: Y - Pointer to Data Buffer [512 byte] ; Z - Phis. Drive Descriptor ; ; Out: c= 0 no error ; 1 error ; CFReadSector: ldd R0,Z+MaxSector+0 ldd R1,Z+MaxSector+1 ldd R2,Z+MaxSector+2 ldd R3,Z+MaxSector+3 cp R10,R0 cpc R11,R1 cpc R12,R2 cpc R13,R3 brcs CFReadSec00 ldi R16,low(ERROR_SECTOR_NOT_FOUND) ;Sector number too big ldi R17,high(ERROR_SECTOR_NOT_FOUND) sec ret CFReadSec00: std Z+CurrentSector+0,R10 std Z+CurrentSector+1,R11 std Z+CurrentSector+2,R12 std Z+CurrentSector+3,R13 rcall CFWaitReady brcc CFReadSec01 ret ;Error in last command CFReadSec01: ldi R16,1 sts CF_SECCOUNT,R16 nop sts CF_LBA0,R10 ;D7..D0 nop sts CF_LBA1,R11 ;D15..D8 nop sts CF_LBA2,R12 ;D23..D16 ldi R16,0x0F and R16,R13 ori R16,0xE0 ;set LBA mode sts CF_LBA3,R16 ;D27..D24 + LBA mode + Drive0 ldi R16,CF_CMD_READ_SEC sts CF_STACOM,R16 ;Set Read Sector Command ldi XL,0 ldi XH,1 ;if X==0 -> X=256 word; movw R0,YL ;save Y reg. rcall CFWaitDrq brcc CFReadSec02 ret ;Drive error CFReadSec02: lds R16,ADR_CFST bst R16,CFVS1 ;CF inserted? brts CFDrvError bst R16,CFRDY ;CF ready? brtc CFReadSec02 lds R16,CF_EvenData st Y+,R16 lds R16,CF_OddData st Y+,R16 sbiw XL,1 brne CFReadSec02 movw YL,R0 ;restore Y reg. clc ret CFDrvError: ldi R16,low(ERROR_BAD_UNIT) ldi R17,high(ERROR_BAD_UNIT) ;Drive not present sec ret ;******************************************************** ;CFWriteSector ; ; In: R13:R12:R11:R10 - LBA sector number ; Page: Y - Pointer to Data Buffer [512 byte] ; Z - Phis. Drive Descriptor ; ; Out: c= 0 no error ; 1 error ; CFWriteSector: ldd R0,Z+MaxSector+0 ldd R1,Z+MaxSector+1 ldd R2,Z+MaxSector+2 ldd R3,Z+MaxSector+3 cp R10,R0 cpc R11,R1 cpc R12,R2 cpc R13,R3 brcs CFWriteSec00 ldi R16,low(ERROR_SECTOR_NOT_FOUND) ;Sector number too big ldi R17,high(ERROR_SECTOR_NOT_FOUND) sec ret CFWriteSec00: rcall CFWaitReady brcc CFWriteSec01 ret ;Error in last command CFWriteSec01: ldi R16,1 sts CF_SECCOUNT,R16 nop sts CF_LBA0,R10 ;D7..D0 nop sts CF_LBA1,R11 ;D15..D8 nop sts CF_LBA2,R12 ;D23..D16 ldi R16,0x0F and R16,R13 ori R16,0xE0 ;set LBA mode sts CF_LBA3,R16 ;D27..D24 + LBA mode + Drive0 ldi R16,CF_CMD_WRITE_SEC sts CF_STACOM,R16 ;Write sector command ldi XL,0 ldi XH,1 ;if X==0 -> X=256 word; movw R0,YL rcall CFWaitDrq brcc CFWriteSec02 ret ;Drive error CFWriteSec02: lds R16,ADR_CFST bst R16,CFVS1 ;CF inserted? brts CFDrvError bst R16,CFRDY ;CF ready? brtc CFWriteSec02 ld R16,Y+ sts CF_EvenData,R16 ld R16,Y+ sts CF_OddData,R16 sbiw XL,1 brne CFWriteSec02 movw YL,R0 clc ret ;******************************************************** ;CFResetDevice ; ; In: - ; ; Out: c= 0 no error ; 1 error R17:R16 error code ; CFResetDevice: ldi R16,0b00000100 ;Force SW reset sts ADR_CFC+0x0E,R16 ;Device Control Register ldi R16,64 CFRes0: dec R17 brne CFRes0 dec R16 brne CFRes0 clr R16 sts ADR_CFC+0x0E,R16 ;Device Control Register rcall CFWaitReady ret ;******************************************************** ;CFIdentify ; ; In: Z - Phis. Drive Descriptor ; Page: Y - Pointer to temporary Data Buffer [512 byte] ; ; Out: c= 0 no error ; 1 error ; CFIdentify: rcall CFWaitReady brcc CFIdent01 ret ;Error code in R17:R16 CFIdent01: ldi R16,1 sts CF_SECCOUNT,R16 clr R16 sts CF_LBA0,R16 nop sts CF_LBA1,R16 nop sts CF_LBA2,R16 ldi R16,0xE0 sts CF_LBA3,R16 ldi R16,CF_CMD_IDENTIFY sts CF_STACOM,R16 ldi XL,0 ;read fixed 256 word ldi XH,1 movw R0,YL call CFWaitDRQ brcc CFIdent02 ret ;Drive error CFIdent02: lds R16,CF_EvenData st Y+,R16 nop lds R16,CF_OddData st Y+,R16 sbiw XL,1 brne CFIdent02 movw YL,R0 clr R0 ldd R16,Y+0 ;CF IDs: 848Ah cpi R16,0x8A brne CFIDs0 ldd R16,Y+1 cpi R16,0x84 brne CFIDs0 inc R0 CFIDs0: std Z+MediaFlag,R0 ;Store CF ID ldi R16,RemovableMedia std Z+MediaType,R16 ldi R16,0x80 std Z+DiskNumber,R16 ;First HDD => HDD0 ldd R16,Y+2 ;Default tracks/cylinders ldd R17,Y+3 std Z+Cylinders+0,R16 std Z+Cylinders+1,R17 ldd R16,Y+6 ;Default Heads std Z+Heads,R16 ldd R16,Y+12 ;default Sectors per track std Z+SectorsPerTrack,R16 ldd R16,Y+14 ;Number of Sectors per Card std Z+MaxSector+2,R16 ;MSW -LSW !!! ldd R16,Y+15 std Z+MaxSector+3,R16 ldd R16,Y+16 std Z+MaxSector+0,R16 ldd R16,Y+17 std Z+MaxSector+1,R16 clc ret