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