FLASHLDR

From S1MP3 Wiki

Jump to: navigation, search

FLASHLDR is the component in the BROM, a part of the BLOD, which is responsible for loading the BREC from NAND flash.

Note: The following code and description were taken from the BROM of an ATJ2093H dated 2005-12-40(?). There may be minor differences between it and that of your device, most notably in the area of flash support.

It is copied by BLOD to 0400 and a call 0403 is made to initiate the loading process. The following is a reader's guide to the FLASHLDR. The full code (only partially commented) is here.

When the BLOD transfers control to it, the machine state is as follows:

a = aa (presumably low two bits of watchdog register retain values)
bc = 0000
de = 1200
hl = 8500
sp = 1ffe (initially 2000, return address pushed by call)

CPU is running at full speed (24MHz).

Contents

0400-0402: Variables

0400 flashtype        db 0  ; holds the detected flash type
0401 read_retry_count db 0
0402 read_retry_stat  db 0  ; notes whether ECC or RS correction was used

Flash types:

  • 00 -- 16K+512 small-block
  • 01 -- 128K+4K large-block
  • 02 -- 32K+1K small-block
  • 10 -- 4K+128 "small"-block (see below)
  • 20 -- 256K+8K large-block

0403-0469: Select and Initialize Flash

Initializes the flash controller, selects the first flash chip (on CE1), and attempts to do a reset followed by a wait-until-ready polling loop. If resetting the flash is unsuccessful, it attempts to verify the signature (55,AA,0F,F0) of an external ROM and tries booting from that. If neither is successful, the function returns 1.

046A-0676: Detect Flash Type

The flash type ID is read by a call to read_flash_id and a large compare-and-jump block of code (which could be written more compactly and efficiently, e.g. by using a table-lookup scheme) is used to determine the precise type of the flash. Eventually, all of the possible types are categorized into the following:

  • Large-block flash, 128K blocksize
  • Small-block flash, 16K blocksize
  • Large-block flash, 256K blocksize
  • Small-block flash, 4K blocksize (this is a weird one --- see below)
  • Small-block flash, 32K blocksize

Unknown flash types are also accommodated by trying, in the above order, all the types above, until one succeeds (returns 0).

0677-0980: Load BREC

The code to load the BREC into IPMM for each of the 5 flash types above is located here. There is much duplication of code between the types, which could be made considerably more compact and efficient.

Error detection and correction is performed for each 512-byte read, using first the integrated Reed-Solomon (511,503) codec, then basic ECC (22 bits per 256 bytes) if RS fails. This enables this code, which is located in BROM and thus not easily changed, to accommodate both types of error correction.

After all 16KB of the BREC is loaded, in each of the 5 paths the verify_brec routine is called to verify the signature and checksum, and rereads/failure returns done as appropriate.

0677-071B: 256K large-block

The BREC is loaded into IPMM by 8 page reads, broken down into 4 512-byte sectors each. The page address is incremented by 120 after the final read, to point to the second block.

071C-07C0: 128K large-block

The BREC is loaded into IPMM by 8 page reads, broken down into 4 512-byte sectors each. The page address is incremented by 56 after the final read, to point to the second block.

07C1-0858: 32K small-block

The BREC is loaded into IPMM by 32 512-byte page reads. The page address is incremented by 32 after the final read, to point to the second block.

0859-08E5: 16K small-block

The BREC is loaded into IPMM by 32 512-byte page reads. There is no need to increment the page address afterwards, as the BREC fills one block exactly.

08E6-0980: 4K small-block

This path and the subroutines it calls handles a special case, an odd flash structure; the Renesas K29V1G91T and K29V2G74WT, having a 4K blocksize, would be considered small-block under the current classification scheme, except that it also has a 2K pagesize and uses the large-block command set. Thus, the code for this path has an 8x4x512 load loop like the large-block paths, but does not increment the page address since the BREC takes 4 blocks in this flash.

0981-09B7: BREC verification

Implementation of signature-checking and checksum algorithm as described in BREC checksum.

09B8-0E63: Page Read/Error Correction

This region consists of code to read pages from the various flash types, as well as perform error checking/correction.

09B8-0AA9: large-block read

Reads 512 bytes by issuing two commands, FB and FA (mapping to 00 and 30, presumably), then performs verification/correction using either RS or ECC depending on what was selected.

0AAA-0AF8: large-block ECC read

Reads 4 ECC bytes in order l,h,e,d (when calling 0AF1) or 2 ECC bytes in order l,h (when calling 0AAA) by sending raw flash commands 00 and 30 and reading from external memory area.

0AF9-0BBB: 32K small-block read

Reads 512 bytes by issuing command ED (probably mapping to 00/01), then performs verification/correction using either RS or ECC depending on what was selected.

0BBC-0C0D: 32K small-block ECC read

Reads 4 ECC bytes in order l,h,e,d (when calling 0C06) or 2 ECC bytes in order l,h (when calling 0BBC) by sending raw flash command 50 and reading from external memory area.

0C0E-0CD0: 16K small-block read

Identical to 32K small-block read.

0CD1-0D22: 16K small-block ECC read

Identical to 32K small-block ECC read.

0D23-0E14: 4K small-block read

Identical to large-block read.

0E15-0E63: 4K small-block ECC read

Identical to large-block ECC read.

0E64-0E9A: CE select

0E64-0E66: Saved Registers

Registers 01, 02, and 28 are saved here when CE is selected, and restored when CE is unselected.

save_reg_01 db 0
save_reg_02 db 0
save_reg_28 db 0

0E67-0E88: Select CE

This routine saves the registers specified above and enables the CE specified by b.

0E89-0E9A: Unselect CE

Restore the registers saved by select_CE, effectively setting CE to whatever it was before select_CE was called.

0E9B-0ED9: Flash Status

0E9B-0ECF: Get Flash Status

Returns, for the currently selected flash, 0, 1, 2, or 3 for ready, timeout, write-protected, or error, respectively.

0ED0-0ED9: Reset and Get Status

Issues reset command to flash controller before calling the above procedure.

0EDA-108B: Error Correction

The code in this section is responsible for detecting and correcting errors using either Reed-Solomon or standard ECC.

0EDA-0EE2: ECC temporary variables

Stores ECC bytes, data buffer address, and ECC XOR result bytes.

0EE3-0FA0: Correct data ECC

Corrects a block of 256 bytes using 11-bit ECC.

  • l = ECC[6:3]
  • h = ECC[10:7]
  • e = ECC[2:0]
  • a = buffer memory bank
  • b = buffer high offset
  • c = buffer low offset

0FA1-1032: Correct spare ECC

Corrects a block of 8 bytes (in the spare area) using 6-bit ECC.

  • l = ECC[5:2]
  • h = ECC[1:0]
  • c = buffer low (non-banked offset)
  • b = buffer high (non-banked offset)

1033-107A: Correct data RS

Uses integrated Reed-Solomon codec to perform error correction on up to 4 bytes.

  • a = buffer memory bank
  • b = buffer high offset
  • c = buffer low offset

107B-108B: Compute Hamming Distance

For computing the number of error bits in ECC calculation.

  • b = number of bit pairs to compare
  • c = accumulation of number of bits
  • l = accumulation of the parity bits

108C-10BC: Read Flash ID

Issues standard 90 (if calling 108C) or non-standard 91 (if calling 109A) command to the flash, and returns 4 bytes of ID in order b, c, d, e. Note that only the first two (manufacturer ID and device ID) are guaranteed to be valid; the code at 046A-0676 uses this information appropriately based on the manufacturer ID.

10BD-11FF: Padding

323 0 bytes for padding, bringing the total size of FLASHLDR to 3.5KB. Judging by the amount of code duplication, with better coding this size could be reduced to <1KB. The current FLASHLDR could definitely be improved greatly, although its location in ROM prevents it.

Personal tools
about this site
Advertisement