smc_dtc_format.fsm
来自「HID-Ukey底层源码实现(st72651芯片) windows上层驱动」· FSM 代码 · 共 455 行
FSM
455 行
;===================================================================
;
; SMART MEDIA CARD
;
;===================================================================
;---------------
; smc_dtc_format
;---------------
; Check spare area
; call send_cmd_address with CMD 0x50 & 0x00
; call init_read_spare without any param
; on error, goto next cluster
; Erase the cluster
; call send_cmd_address with CMD 0x60 & 0xD0
; call read_status without any param
; on error, mark this cluster as bad and goto next cluster
; Write all 0's to the cluster
; call send_cmd_00 without any param
; call write_zero_to_all_pages with CMD 0x80 & 0x10
; Read all 0's
; call send_cmd_address with CMD 0x00 & 0x40
; on error, mark this cluster as bad and goto next cluster
; call read_check_cluster without any param
; on error, mark this cluster as bad and goto next cluster
; Erase the cluster
; call send_cmd_address with CMD 0x60 & 0xD0
; call read_status without any param
; on error, mark this cluster as bad and goto next cluster
:clear_cluster_pages
;-------------------
; get the 2nd command,
LD A CMP10 ; it is either 0x10 for write or 0xD0 for erase
EXCHANGE
BSET4
JP :time_to_go_home
LD MSB 14
LD LSB 5
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00E5
LD A DATA_BUFFER0
CLC
ADDER8 X ; increase the page address
LD DATA_BUFFER0 ; and save it
CLC
LD A CMP00 ; get the page counter
SUB8 X
CP A=>X ; check the page counter
JP :save_page_counter
:time_to_go_home
;--------------- On this point:
; After ERASE CMP11 = 0x60 (1st CMD) ADR0 = 0x00E4 or 0x00E3
; CMP10 = 0xD0 (2nd CMD) ADR1 = xxxx
; After WRITE
; CMP11 = 0x02 (for compare write 0x0210 bytes)
; CMP10 = 0x10 (2nd CMD)
; ADR0 = 0x00E4 or 0x00E3
; ADR1 = 0x0210 (after compare write 0x210 bytes)
STATUS STOP
;--------------------------------------------------------
; START ADDRESS FOR send sequential read command
;--------------------------------------------------------
:send_cmd_00
;-----------
LD MSB 0
CP ALWAYS
; 1st CMD will be 0x00
; 2nd CMD will be 0x10
JP :pre_send_cmd_address0
;------------------------------------------------------------------
; START ADDRESS FOR 1st step of erasing
;------------------------------------------------------------------
:send_cmd_for_erase
LD MSB 6
LD LSB 0
LD CMP11 ; 1st CMD of ERASE = 0x60
LD MSB 13 ; 2nd CMD of ERASE = 0xD0
CP ALWAYS
JP :pre_send_cmd_address
;------------------------------------------------------------------
; START ADDRESS FOR 1st step of check spare area
;------------------------------------------------------------------
:send_cmd_for_check
LD MSB 5
CP ALWAYS ; 1st CMD of READ SPARE = 0x50, 2nd CMD = 0x50 too
JP :send_cmd_for_read_1
;------------------------------------------------------------------
; START ADDRESS FOR 1st step of reading 0's
;------------------------------------------------------------------
:send_cmd_for_read
LD MSB 0
:send_cmd_for_read_1
LD LSB 0
LD CMP11 ; 1st CMD of READ = 0x00
; 2nd CMD is 0x00 too
CP ALWAYS
JP :pre_send_cmd_address
;------------------
:write_zero_to_all_pages
;-----------------------
LD MSB 15
LD LSB 15
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00FF, points to page counter
LD A DATA_BUFFER0
:save_page_counter
;-----------------
LD CMP00 ; save the page counter in CMP00
LD MSB 8
:pre_send_cmd_address0
LD LSB 0
LD CMP11 ; 1st CMD of WRITE All 0's = 0x80
LD MSB 1 ; 2nd CMD of WRITE All 0's = 0x10
:pre_send_cmd_address
LD CMP10
;------------------------------------------------------------------
; START ADDRESS FOR send command and address
; 0x1637 is the command, either 0x50, 0x60 or 0x80
; 0x1638 is the 2nd cmd, either 0x00, 0xD0 or 0x10
; 0x1639 is the page number
; 0x1636 is the number of address bytes, either 3 or 4
; 0x1633-0x1635: The address bytes
;------------------------------------------------------------------
:send_cmd_address
;---------------- CHECK ERASE WRITE READ
; CMD11 = 1st CMD 0x50 0x60 0x80 0x00
; CMD10 = 2nd CMD 0x50 0xD0 0x10 0x00
LD MSB 0
LD ADR_BUFFER01 ; clear the high byte of the pointer 0
LD LSB 1
LD X ; X = 1
LD MSB 14
LD LSB 6
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00E6
LD MSB 1 ;data_flash port = output
LD LSB 9 ;DATA_FLASH Port driven by FCI
LD CTRL_FCI ;PARALLEL Port driven by FCI
LD A CMP11 ; get the 1st command
LD DATA_FLASH ; output the command
LD MSB 0
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 9
LD DR_PARALLEL ; WE = 0, CLE = 1
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
; if (CMD1 != 0) latch the address
; if (CMD1 == 0 && CMD2 != 0) return (CMD-00)
; if (CMD1 == 0 && CMD2 == 0) latch the address (READ)
LD A CMP11
CP A=>X ; check 1st CMD is 0?
JP :latch_address
LD A CMP10
CP A=>X ; check 2nd CMD is 0?
JP :non_write_go_back
;--------------------------------------------------
; START ADDRESS FOR address_latch_cycle
;--------------------------------------------------
:latch_address
LD MSB 0
LD LSB 14
LD DR_PARALLEL ; ALE = 1, WE = 1
LD A DATA_BUFFER0 ; buffer pointer 0 = 0x00E6
SUB16 ADR_BUFFER0
LD Y ; Y = number of address bytes
DECY
LD A CMP10 ; get the 2nd CMD
EXCHANGE
BSET4 ; check the 2nd cmd, skip send CA0-7 0 on ERASE (0xD0)
JP :send_next_addrss_byte
LD A ADR_BUFFER01 ; clear A as the first byte, it is always 0
:loop_send_address
; -----------------
LD DATA_FLASH
LD MSB 0
LD LSB 12
LD DR_PARALLEL ; ALE = 1, WE = 0
LD LSB 14
LD DR_PARALLEL ; ALE = 1, WE = 1
:send_next_addrss_byte
;---------------------
LD A DATA_BUFFER0 ; buffer pointer 0 = 0x00E5, 0x00E4, 0x00E3(only for 4 bytes address)
SUB16 ADR_BUFFER0
DECY
JP :loop_send_address
LD LSB 10 ; recover the interface lines
LD DR_PARALLEL ; RD = 1, WE = 1
LD A CMP11 ; get the 1st CMD
EXCHANGE
BSET4 ; test the 1st command is the 0x80
JP :write_all_zeros
; for non-write command, go back
;---------------------------------
:non_write_go_back
STATUS STOP
:write_all_zeros
;---------------
LD LSB 2
LD CMP11 ; CMP1 = 0x0210; CMP10 is the 2nd CMD
LD LSB 0
LD ADR_BUFFER10
LD ADR_BUFFER11 ; buffer pointer 1 = 0x0000
:loop_write_zeros
LD LSB 0
LD DATA_FLASH
LD LSB 8
LD DR_PARALLEL ; WE = 0
LD LSB 10
LD DR_PARALLEL ; WE = 1
ADDER16 ADR_BUFFER1
CP ADR_BUFFER1<CMP1
JP :loop_write_zeros
;-----------------------------------------------------------
; START ADDRESS FOR 2nd enter of erase block
;-----------------------------------------------------------
:send_write_erase_cmd
LD A CMP10 ; get the 2nd CMD
LD DATA_FLASH
LD MSB 0
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 9
LD DR_PARALLEL ; WE = 0, CLE = 1
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
:wait_write_erase_busy
;---------------------
LD A DR_PARALLEL
EXCHANGE
BCLR1
JP :wait_write_erase_busy
LD MSB 7
LD LSB 0
LD DATA_FLASH ; send command of Read_Status
LD MSB 0
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 9
LD DR_PARALLEL ; WE = 0, CLE = 1
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
; LD MSB 0 ;data_flash port = input
LD LSB 9 ;DATA_FLASH Port driven by FCI
LD CTRL_FCI ;PARALLEL Port driven by FCI
LD LSB 2
LD DR_PARALLEL
LD LSB 10
LD DR_PARALLEL
LD A DATA_FLASH ; read the status
BCLR1 ; check the status bit
JP :erase_write_pass
:cluster_read_write_error
;------------------------
NOP
STATUS STOP ERROR
:erase_write_pass
;----------------
LD A ADR_BUFFER01 ; ADR_BUFFER01 = 0x00
CP ALWAYS
BRANCH :clear_cluster_pages
;--------------------------------------------------------
; START ADDRESS FOR read and check all 0's
;--------------------------------------------------------
:read_check_cluster
;------------------
LD MSB 0 ;data_flash port = input
LD LSB 9 ;DATA_FLASH Port driven by FCI
LD CTRL_FCI ;PARALLEL Port driven by FCI
LD LSB 2
LD CMP11
LD LSB 15
LD CMP10
LD MSB 15
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00FF, points to the page counter
LD A DATA_BUFFER0
LD Y
DECY
:loop_read_all_pages
;-------------------
LD A ADR_BUFFER00
LD ADR_BUFFER10
LD ADR_BUFFER11 ; ADR1 = 0xFFFF
:wait_read_page
LD A DR_PARALLEL
EXCHANGE
BCLR1
JP :wait_read_page
:loop_read_page
;--------------
LD A CMP11
LD DR_PARALLEL ; RD = 0
LD LSB 10
LD DR_PARALLEL ; RD = 1
LD A DATA_FLASH
CP A=>X
JP :cluster_read_write_error
ADDER16 ADR_BUFFER1
CP ADR_BUFFER1<CMP1
JP :loop_read_page
DECY
JP :loop_read_all_pages
STATUS STOP
;---------------------------------------------------------------
; START ADDRESS FOR read_spare & check_spare
; redundant area is read to address of 1F0-1FF
;------------------------------------------------------------------------------------------------
; 1F0 | 1F1 | 1F2 | 1F3 | 1F4 | 1F5 | 1F6 | 1F7 | 1F8 | 1F9 | 1FA | 1FB | 1FC | 1FD | 1FE | 1FF |
; Reserved Field | DAT | BLK | Address1 | ECC Field-2 | Address2 | ECC Field-1 |
;------------------------------------------------------------------------------------------------
:init_read_spare
;---------------
LD MSB 15
LD LSB 0
LD Y ; Y = 0xF0
LD MSB 2
LD BUFFER_MNGT ; segment offset = 1, going to use <Y> for reading spare area
EXCHANGE
LD CMP00 ; CMP00 = 0x02, used for toggling bit for reading
; LD MSB 0 ; data_flash port = intput
LD LSB 9 ; DATA_FLASH Port driven by FCI
LD CTRL_FCI ; PARALLEL Port driven by FCI
:test_busy_line
;--------------
LD A DR_PARALLEL
EXCHANGE
BCLR1
JP :test_busy_line
; read_spare
;-----------
:read_spare
LD A CMP00
LD DR_PARALLEL ; RD = 0
LD LSB 10
LD DR_PARALLEL ; RD = 1
LD A DATA_FLASH ; load DATA_FLASH
LD <Y>
INCY
JP :read_spare
;------------------------------------------
; check Block_Status has no more than one 0
;------------------------------------------
LD A ADR_BUFFER01
LD CMP01
LD A X
LD ADR_BUFFER11
LD CMP00 ; CMP0 = 0x0001
LD LSB 8 ; Y = 0x08; points to a pattern array as following
LD Y ; { ~0x00, ~0x01, ~0x02, ~0x04, ~0x08, ~0x10, ~0x20, ~0x40, ~0x80 }
LD MSB 15
LD LSB 5
LD ADR_BUFFER10 ; pointer 1 = 0x01F5, points to Block_Status of the redundant area
:check_Block_Status
;------------------
LD A DATA_BUFFER1
LD X
LD A <Y>
CP A<X
JP :check_Block_Status_next
LD X
LD A DATA_BUFFER1
CP A=>X
; we found one match on the array
JP :good_Block_Status
:check_Block_Status_next
;-----------------------
DECY
JP :check_Block_Status
:cluster_error
;-------------
STATUS STOP ERROR
:good_Block_Status
;-----------------
LD A ADR_BUFFER11
LD X ; X = 1
ADDER16 ADR_BUFFER1 ; buffer pointer 1 = 0x01F6
LD A DATA_BUFFER1 ; high byte of Address1
LD ADR_BUFFER01
ADDER16 ADR_BUFFER1
LD A DATA_BUFFER1
LD ADR_BUFFER00 ; ADR_BUFFER0 = Address1-Field
CP ADR_BUFFER0<CMP0 ; check with 0x0001, it may be a CIS
; if it is a CIS, claim it as error and return
JP :cluster_error
LD MSB 15
LD LSB 11
LD ADR_BUFFER10 ; skip the ECC Field-2
LD A DATA_BUFFER1
LD CMP01
ADDER16 ADR_BUFFER1
LD A DATA_BUFFER1
LD CMP00 ; CMP0 = Address2-Field
CP ADR_BUFFER0<CMP0
JP :cluster_error
SUB16 ADR_BUFFER0
CP ADR_BUFFER0=>CMP0
JP :cluster_error
STATUS STOP
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?