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 + -
显示快捷键?