加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > 技术文章

sm卡的接口源程序

时间:2012-11-24  来源:123485.com  作者:9stone

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


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->技术文章
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门