sm卡的接口源程序
2012-11-22
标签:

;-----------------------------------------------;

; SM - Get SM type and initialize SM properties

;

; Call: none

; Ret: C=0: successful, SmPages are valid

; C=1: unknown type

sm_gettype:

ldiw Y,SmSign ; Y = Pointer to SM property structure

cbi PORTC,CE ; CE="L"

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_ID ; Cmd: Read ID

rcall sm_write ; /

cbi PORTC,CLE ; Address Phase: CLE="L", ALE="H"

sbi PORTC,ALE ; /

ldi r16,0x00 ; Addr: 0

rcall sm_write ; /

cbi PORTC,ALE ; Data Phase: CLE="L", ALE="L"

outi DDRA,0 ; Disable data out

outi PORTA,-1 ; Pull-up

rcall sm_read ; Read mfr code

st Y+,r16 ; /

rcall sm_read ; Read device code

st Y+,r16 ; /

sbi PORTC,CE ; CE = "H"

cpi r16,Sign8 ; Is device size 8MB ?

brne PC+8 ; no, skip

sti Y+,byte2(Pages8); Initialize as 8MB

sti Y+,byte3(Pages8);

sti Y+,Blkp8-1 ;

ret ; /

cpi r16,Sign16 ; Is device size 16MB ?

brne PC+8 ; no, skip

sti Y+,byte2(Pages16); Initialize as 16MB

sti Y+,byte3(Pages16);

sti Y+,Blkp16-1 ;

ret ; /

cpi r16,Sign32 ; Is device size 32MB ?

brne PC+8 ; no, skip

sti Y+,byte2(Pages32); Initialize as 32MB

sti Y+,byte3(Pages32);

sti Y+,Blkp32-1 ;

ret ; /

cpi r16,Sign64 ; Is device size 64MB ?

brne PC+8 ; no, skip

sti Y+,byte2(Pages64); Initialize as 64MB

sti Y+,byte3(Pages64);

sti Y+,Blkp64-1 ;

ret ; /

cpi r16,Sign128 ; Is device size 128MB ?

brne PC+8 ; no, skip

sti Y+,byte2(Pages128); Initialize as 128MB

sti Y+,byte3(Pages128);

sti Y+,Blkp128-1 ;

ret ; /

ret ; Unknown device type

;-----------------------------------------------;

; SM - Test and erase current block

;

; Call: _PageX = Page(block) to be checked

; Ret: r16,r17,r18,r19,_Loop = broken

; C=0 : Successful, Block is erased.

; C=1 : Bad block.

sm_chk_blk:

rcall sm_erase ; Erase

brcs sc_ret ; /

ldi r19,0x55 ; Write 0x55,0xAA....

rcall sc_fill ;

brcs sc_ret ; /

rcall sc_chk ; Verify

brcs sc_ret ; /

rcall sm_erase ; Erase

brcs sc_ret ; /

ldi r19,0xaa ; Write 0xAA,0x55....

rcall sc_fill ;

brcs sc_ret ; /

rcall sc_chk ; Verify

brcs sc_ret ; /

rcall sm_erase ; Erase

sc_ret: sbi PORTC,CE ; CE = "H"

ret

sc_fill:

push _PageL

push _PageM

push _PageH

lds _Loop,SmPPB ; Block count

inc _Loop ;

scf_sl: rcall sm_wr_set ;---- Block filling loop

ldi r18,512/2 ; Page count

out PORTA,r19 ;---- Page filling loop

cbi PORTC,WE ; Write Even byte

sbi PORTC,WE ; /

com r19 ; P = !P

out PORTA,r19 ; Write Odd byte

cbi PORTC,WE ;

sbi PORTC,WE ; /

com r19 ; P = !P

dec r18 ; End of page ?

brne PC-9 ; no, continue

rcall sm_wr_start ; Start to write

brcs scf_err ; /

rcall next_page ; Page ++

dec _Loop ; End of block ?

brne scf_sl ; no, continue

clc

rjmp PC+2

scf_err:sec

pop _PageH

pop _PageM

pop _PageL

ret

sc_chk:

push _PageL

push _PageM

push _PageH

lds _Loop,SmPPB ; Block count

inc _Loop ;

com r19 ; P = !P

scc_sl: rcall sm_rd_page ;---- Block compare loop

ldi r18,512/2 ; Page count

cbi PORTC,RE ;---- Page compare loop

com r19 ; P = !P

in r16,PINA ; Read Even byte

sbi PORTC,RE ; /

cp r16,r19 ;

brne scc_err ;

cbi PORTC,RE ; Read Odd byte

com r19 ; P = !P

in r16,PINA ;

sbi PORTC,RE ; /

cp r16,r19 ;

brne scc_err ;

dec r18 ; End of page ?

brne PC-13 ; no, continue

rcall next_page ; Page ++

dec _Loop ; End of block ?

brne scc_sl ; no, continue

clc

rjmp PC+2

scc_err:sec

pop _PageH

pop _PageM

pop _PageL

ret

;-----------------------------------------------;

; SM - Receive 512 bytes of page data from HOST into SM

;

; Call: none

; Ret: r16-r19 = broken

;

;SCK ______---___---___---___---______

;MOSI -----000111222333444555666777----

sm_rcv512:

ldi r18,low(511)

ldi r19,high(511)

rcv1: in r16,PINB ; b0

bst r16,SCK

brtc PC-2

bst r16,MOSI

bld r17,0

in r16,PINB ; b1

bst r16,SCK

brts PC-2

bst r16,MOSI

bld r17,1

in r16,PINB ; b2

bst r16,SCK

brtc PC-2

bst r16,MOSI

bld r17,2

in r16,PINB ; b3

bst r16,SCK

brts PC-2

bst r16,MOSI

bld r17,3

in r16,PINB ; b4

bst r16,SCK

brtc PC-2

bst r16,MOSI

bld r17,4

in r16,PINB ; b5

bst r16,SCK

brts PC-2

bst r16,MOSI

bld r17,5

in r16,PINB ; b6

bst r16,SCK

brtc PC-2

bst r16,MOSI

bld r17,6

in r16,PINB ; b7

bst r16,SCK

brts PC-2

bst r16,MOSI

bld r17,7

out PORTA,r17 ; Write into SM

cbi PORTC,WE ;

sbi PORTC,WE ; /

subi r18,1 ; End of page ?

sbci r19,0 ; no, continue

brcc rcv1 ; /

ret

;-----------------------------------------------;

; SM - Reset device

;

; Call: none

; Ret: r16 = broken

sm_reset:

cbi PORTC,CE ; CE="L"

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_RES ; Cmd: Reset

rcall sm_write ; /

sbis PINC,BSY ; Wait for ready

rjmp PC-1 ; /

sbi PORTC,CE ; CE="H"

ret

;-----------------------------------------------;

; SM - Erase current block

;

; Call: _PageX = Page(Block) for erase

; Ret: r16 = broken

; C = 0:Successful, 1:error

sm_erase:

cbi PORTC,CE ; CE="L"

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_ERA1 ; Cmd: Erase 1

rcall sm_write ; /

cbi PORTC,CLE ; Address Phase: CLE="L", ALE="H"

sbi PORTC,ALE ; /

mov r16,_PageL ; Addr 1

rcall sm_write ; /

mov r16,_PageM ; Addr 2

rcall sm_write ; /

mov r16,_PageH ; Addr 3 (will be ignored at 32M or below SMs)

rcall sm_write ; /

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_ERA2 ; Cmd: Erase 2

rcall sm_write ; /

sbis PINC,BSY ; Wait for end of erase

rjmp PC-1 ; /

ldi r16,C_STA ; Cmd: Status

rcall sm_write ; /

cbi PORTC,CLE ; Data Phase: CLE="L", ALE="L"

rcall sm_read ; Read status into C

lsr r16 ; /

ret

;-----------------------------------------------;

; SM - Set ready to write

;

; Call: _PageX = Page for write

; Ret: r16 = broken

sm_wr_set:

cbi PORTC,CE ; CE="L"

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_RD0 ; Cmd: Cancel RD2 cmd

rcall sm_write ; /

ldi r16,C_WR ; Cmd: Write set

rcall sm_write ; /

cbi PORTC,CLE ; Address Phase: CLE="L", ALE="H"

sbi PORTC,ALE ; /

ldi r16,0x00 ; Addr 0

rcall sm_write ; /

mov r16,_PageL ; Addr 1

rcall sm_write ; /

mov r16,_PageM ; Addr 2

rcall sm_write ; /

mov r16,_PageH ; Addr 3 (will be ignored at 32M/16M SMs)

rcall sm_write ; /

cbi PORTC,ALE ; Data Phase: CLE="L", ALE="L"

ret

;-----------------------------------------------;

; SM - Write intrenal buffer into memory array

;

; Call: none

; Ret: C=0 : Successful

; C=1 : Error

sm_wr_start:

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

ldi r16,C_PRG ; Cmd: Write start

rcall sm_write ; /

sbis PINC,BSY ; Wait for ready

rjmp PC-1 ; /

ldi r16,C_STA ; Cmd: Read status

rcall sm_write ; /

cbi PORTC,CLE ; Data Phase: CLE="L", ALE="L"

rcall sm_read ; Read data

sbi PORTC,CE ; CE = "H"

lsr r16 ; Read status into C

ret

;-----------------------------------------------;

; SM - Read out a page data from memory array

; into transfer buffer

;

; Call: _PageX = Page# for read

; Ret: r16 = broken

;

; NOTE1: AT 32MB MEDIUM OR BELOW.

; The read transfer cycle is initiated after Addr2, following Addr3 will

; be ignored. But if Addr3 is given at the read transfer cycle has been

; completed, read data can become wrong. An interrupt between Addr2 and

; Addr3 will cause this problem. Therefore, all interrupts must be disabled

; during this routine is executed in order to avoid data collaption.

; NOTE2: Above problem has been fixed at this routine :-)

sm_rd_page2: ; Read a page and set pointer to offset 512

ldi r16,C_RD2 ; Cmd: Read2

rjmp PC+2 ;

sm_rd_page: ; Read a page and set pointer to offset 0

ldi r16,C_RD0 ; Cmd: Read

in _SrgTmp2,SREG ; Save I flag

cli ; Disable interrupts (TO AVOID DATA COLLAPTION)

cbi PORTC,CE ; CE="L"

sbi PORTC,CLE ; Command Phase: CLE="H", ALE="L"

cbi PORTC,ALE ; /

rcall sm_write ; Command

cbi PORTC,CLE ; Address Phase: CLE="L", ALE="H"

sbi PORTC,ALE ; /

ldi r16,0x00 ; Addr 0

rcall sm_write ; /

mov r16,_PageL ; Addr 1

rcall sm_write ; /

mov r16,_PageM ; Addr 2

rcall sm_write ; /

mov r16,_PageH ; Addr 3 (will be ignored at < 64M media)

rcall sm_write ; /

cbi PORTC,ALE ; Data Phase: CLE="L", ALE="L"

outi DDRA,0x00 ; Disable data out

outi PORTA,-1 ; Pull-up

out SREG,_SrgTmp2 ; Restore I flag

sbis PINC,BSY ; Wait for ready

rjmp PC-1 ; /

ret

;-----------------------------------------------;

; SM - Read/Write byte

;

; Call: r16 = data for write

; Ret: r16 = read data

sm_write:

out PORTA,r16 ; Set data for write

outi DDRA,0xff ; Enable data out

cbi PORTC,WE ; WE="L"

sbi PORTC,WE ; WE="H"

ret

sm_read:

cbi PORTC,RE ; RE="L"

nop ;

in r16,PINA ; Read

sbi PORTC,RE ; RE="H"

ret

可能会用到的工具/仪表
相关文章
推荐文章
热门文章
章节目录
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号