From N64brew Wiki
Jump to navigation Jump to search

Flash memory provides games with 1 Mebibit (= 128 kibibyte) of non volatile memory to keep game progress saved after console shutdown. This is the biggest capacity offered among save types. Contrary to SRAM this kind of memory doesn't require an external battery to keep data saved. Similar to SRAM, it is accessed using the PI bus at address 0x0800_0000 (eg. with Domain 2 timings).

Trivia: the Ultra SDK offered a way to access multiple Flash chips and mapped them at address 0x0800_0000 | (chip_num << 17). But no known game used more than 1 Flash chip.

Note: The flash chip is a custom design (manufactured by Macronix and Matsushita), but it seems at least similar in part to the MX29L1611 model which has a public datasheet.

The 1Mebibit Flash memory is organized as 8 sectors, each composed of 128 pages, with each pages being 128 bytes.

Sector Range (bytes) Range (pages)
0 0x0000_0000 - 0x0000_3FFF 0x000 - 0x07F
1 0x0000_4000 - 0x0000_7FFF 0x080 - 0x0FF
2 0x0000_8000 - 0x0000_BFFF 0x100 - 0x17F
3 0x0000_C000 - 0x0000_FFFF 0x180 - 0x1FF
4 0x0001_0000 - 0x0001_3FFF 0x200 - 0x27F
5 0x0001_4000 - 0x0001_7FFF 0x280 - 0x2FF
6 0x0001_8000 - 0x0001_BFFF 0x300 - 0x37F
7 0x0001_C000 - 0x0001_FFFF 0x380 - 0x3FF

Reading flash memory is done using DMA and reads full pages (eg. blocks of 128 bytes).

A DMA read operation may not cross a 256 page boundary, it must be splitted to avoid crossing 256*128 bytes addresses. Consequently this also means that a single DMA can only be at most 256 pages long, and only if it is aligned at a 256-page boundary. Example: reading pages 254 to 520 should be splitted in 3 DMA : pages 254-255 in the first DMA, 256-511 in the second, and 512-520 in the last.

A dummy IO at 0x0800_0000 may also be required after setting flash into ReadArray mode an before doing the DMAs.

Also, cart address for DMA depends on the flash model: 0x0800_0000 + page_num * 128 (for models XXX) and 0x0800_0000 + page_num * 64 (for models 0x00 (ProtoA), 0x01(A) and 0x1E(C)).

Writing flash memory also has specificities. Before writing a page (this is called "programming a page"), it must be in erased state (eg. all bits reset to '1'). Indeed, programming a page can only flip bits from '1' to '0' (the other way '0' to '1' can only be done during erasure).

Erasing can be done either by sector (eg. 128 pages at a time), or for the full chip.

Programming is done page by page (eg. in blocks of 128 bytes) and is a 2 step process:

1. send "load page data" command, then DMA 128 bytes using cart_address == 0x0800_0000

2. send "program page N" command, and wait for completion by busy polling program busy bit.

Programming notes

PI BSD Dom2 should be configured with the following values :

  • latency = 0x5 ((5+1)*16 = 96ns)
  • pulse = 0xc ((12+1)*16 = 208ns)
  • page_size = 0xf ((2^(15+2) = 128KiB - eg. we send the address only once at beginning of transfer)
  • release = 0x2 ((2+1)*16 = 48ns)

Flash chip exposes a Command Internal Register (32bits, write only), mapped at 0x0801_0000 to serve as an interface between the CPU and internal Flash operations.

Note that, CIR is write only and cannot be read. Otherwise it's address would conflict with "regular" data addresses when reading.

Commands recognized by CIR are given below:

0x3c00_0000 chip erase setup

First phase of chip erase cycle. Must be followed by erase command to perform full chip erasure.

0x4b00_XXXX sector erase setup

First phase of sector erase cycle. Must be followed by erase command to perform sector erasure.

With XXXX being a page number belonging to the sector to erase.

example: XXXX = 0123, will erase sector 2 (eg. pages [0x100 - 0x17F])

Warning: Almost all emulator (and maybe some flashcarts) only erase a single page and not the full sector.

0x7800_0000 erase

Second phase of sector/chip erase cycle.

Will start the actual sector or chip erasure (eg. reset bits to "1").

Status erase_busy bit (0x02) will be set during the operation, and cleared once finished.

Status erase_ok bit (0x08) will be set if operation was done successfully.

Upon completion, chip will transition to status register mode.

0xa500_XXXX program page

Second phase of page programming cycle.

With XXXX being the page to be programmed with bytes loaded after "load byte page" command.

Status program_busy bit (0x01) will be set during the operation and cleared once finished.

Status program_ok bit (0x04) will be set if operation was done successfully.

Upon completion, chip will transition to status register mode.

Warning: before programming a page, it must be in an erased state.

Note: flash models (NEW) may need to be in "load bye page" mode before sending program page command to CIR.

0xb400 0000 load byte page

First phase of page programming cycle.

Internal page buffer will be accessible at address 0x0800_0000

Setting it's content is usually done using a 128-byte DMA at address 0x0800_0000.

0xd200 0000 status register mode

status register is now accessible at address 0x0800_0000

Can be read using 32-bit MMIO read and keeping only least significant byte.

Can be cleared using 32-bit MMIO zero-write.

Status register bits:

0x01: program_busy

0x02: erase_busy

0x04: program_ok

0x08: erase_ok

0x40: unknown (maybe some kind of suspend ?)

other bits are probably reserved

0xe100 0000 id mode

silicon_id content is now accessible at address 0x0800_0000.

Can be read using a 8-byte length DMA.


0x1111_8001: flash type ID

0xXXXX_YYYY: manufacturer + device code

Name Manufacturer Code Device Code
MX29L0000 0x00C2 (Macronix) 0x0000 OLD
MX29L0001 0x00C2 0x0001 OLD
MX29L1100 0x00C2 0x001E OLD
MX29L1101_A 0x00C2 0x001D NEW
MX29L1101_B 0x00C2 0x0084 NEW
MX29L1101_C 0x00C2 0x008E NEW
MN63F8MPN 0x0032 (Matsishita) 0x00F1 NEW

0xf000 0000 read mode

flash array data is now accessible at address 0x0800_0000.

A dummy 32bit read at 0x0800_0000 may be required before doing DMA to read full pages.

Also a single DMA may not cross 256 page boundaries. It must be splitted at these boundaries.

For older models, read addresses are divided by 2:

OLD: address = 0x0800_0000 + page_num * 64

NEW: address = 0x0800_0000 + page_num * 128

Trivia: For all commands bits 31-28 are the inverse of bits 27-24.