int CartCommand(char cmd, int data1, int data2)
{
CARDCMD_0 = cmd;
CARDCMD_1 = BYTE3(data1);
CARDCMD_2 = (unsigned int)(data1 << 8) >> 24;
CARDCMD_3 = (unsigned int)(data1 << 16) >> 24;
CARDCMD_4 = data1;
CARDCMD_5 = (unsigned int)(data2 << 16) >> 24;
CARDCMD_6 = data2;
CARDCMD_7 = 0;
REG_ROMCTRL = 0xA7180000;
while ( !(REG_ROMCTRL & 0x800000) )
;
return CARD_DATA_RD;
}
A lot of the cart commands can be mapped similarly to the commands seen on page 20 here: https://media.digikey.com/pdf/Data%20Sheets/Macronix/MX29LV160D(T,B).pdf
CartCommand(0x86, 0, 0);
appears before most 0x87 commands, 0x87 appears to interface directly to the chip documented above.
CartCommand(0x87, Addr, Data);
CartCommand(0x87, 0xXXXX, 0xF0);
Two types of erase commands, depends on the flashchip detected.
Type 1 can be implemented as the C below where it simply erases 4 bytes at a time.
void Erase_Type1(uint32_t offset, uint32_t length)
{
CartCommand(0x86, 0, 0);
CartCommand(0x87, 0x5555, 0xAA);
CartCommand(0x87, 0x2AAA, 0x55);
CartCommand(0x87, 0x5555, 0x80); // unlocks the flashchip?
CartCommand(0x87, 0x5555, 0xAA);
CartCommand(0x87, 0x2AAA, 0x55);
CartCommand(0x87, offset, 0x30);
uint32_t end_offset = offset + length;
while(offset > end_offset)
{
while ( CartCommand(0, offset, 0) != 0xFFFFFFFF )
{
// wait until it's 0xFFFFFFFF
// todo: some sort of timeout = failure
}
offset += 4;
}
CartCommand(0x87, 0x5555, 0xF0);
}
Type 2 is different
void Erase_Type2(uint32_t offset, uint32_t length)
{
CartCommand(0x86, 0, 0);
CartCommand(0x87, offset, 0x50);
CartCommand(0x87, offset, 0x20);
CartCommand(0x87, offset, 0xD0);
uint32_t result = CartCommand(0, offset, 0);
while ( !(result & 0x80) )
result = CartCommand(0, offset, 0);
CartCommand(0x87, offset, 0x50);
CartCommand(0x87, offset, 0xFF);
uint32_t end_offset = offset + length;
while(offset > end_offset)
{
while ( CartCommand(0, offset, 0) != 0xFFFFFFFF )
{
// wait until it's 0xFFFFFFFF
// todo: some sort of timeout = failure
}
offset += 4;
}
}
void Write_Type1(uint32_t offset, uint32_t data)
{
CartCommand(0x86, 0, 0);
CartCommand(0x87, offset, 0x50);
CartCommand(0x87, offset, 0x40);
CartCommand(0x87, offset, data);
uint32_t result = CartCommand(0, offset & 0xFFFFFFFC, 0);
while ( !(result & 0x80) )
result = CartCommand(0, offset & 0xFFFFFFFC, 0);
CartCommand(0x87, offset, 0x50);
CartCommand(0x87, offset, 0xFF);
}
void Write_Type2(uint32_t offset, uint32_t data)
{
CartCommand(0x86, 0, 0);
CartCommand(0x87, 0x5555, 0xAA);
CartCommand(0x87, 0x2AAA, 0x55);
CartCommand(0x87, 0x5555, 0xA0);
CartCommand(0x87, offset, data);
// todo: this has some crazy weird alignment shit
CartCommand(0, offset & 0xFFFFFFFC, 0);
CartCommand(0x87, 0x5555, 0xF0);
}
DSTT can have a lot of different flash chips, some are writeable, some are not. You can get information about the flash chip with the following cart commands:
CartCommand(0x86, 0, 0);
CartCommand(0x87, 0x5555, 0xAA);
CartCommand(0x87, 0x2AAA, 0x55);
CartCommand(0x87, 0x5555, 0x90);
g_DeviceType = CartCommand(0, 0, 0);
CartCommand(0x87, 0x5555, 0xF0);
if ( (g_DeviceType & 0xFF00FFFF) != 0x7F003437
&& (g_DeviceType & 0xFF00FFFF) != 0x7F00B537
&& (unsigned __int16)g_DeviceType != 0x41F
&& (unsigned __int16)g_DeviceType != 0x51F )
{
CartCommand(0x87, 0x5555, 0xAA);
CartCommand(0x87, 0x2AAA, 0x55);
CartCommand(0x87, 0x5555, 0x90);
v0 = CartCommand(0, 0x100, 0);
CartCommand(0x87, 0x5555, 0xF0);
if ( (unsigned __int16)v0 == 0xBA1C || (unsigned __int16)v0 == 0xB91C )
g_DeviceType = v0;
}
- 0x041F "ATMEL AT49BV001A(N)T"
- 0x051F "ATMEL AT49BV001A(N)"
- 0x1A37 "AMIC A29L800T"
- 0x3437 "AMIC A29L400T"
- 0x49B0 "SHARP LH28F160BGHB-BTL"
- 0x49C2 "MACRONIX MX29LV160BB"
- 0x5BC2 "MACRONIX MX29LV800B"
- 0x80BF "SST SST39LF/VF400A"
- 0x9020 "ST M28W160(B)T"
- 0x9089 "INTEL 28F160B3T"
- 0x9120 "ST M28W160(B)B"
- 0x912C "MICRON MT28F160A3-B"
- 0x9189 "INTEL 28F160B3B"
- 0x922C "MICRON MT28F160C3(4)-T"
- 0x9289 "INTEL 28F800B3T"
- 0x9320 "ST M28W800BB"
- 0x9389 "INTEL 28F800B3B"
- 0x9689 "INTEL 28F320B3T"
- 0x9789 "INTEL 28F320B3B"
- 0x9B37 "AMIC A29L800U"
- 0xA01F "ATMEL AT49BV8192*"
- 0xA31F "ATMEL AT49BV8192*T"
- 0xA7C2 "MACRONIX MX29LV320T"
- 0xA8C2 "MACRONIX MX29LV320B"
- 0xBA01 "SPANSION Am29LV400BB"
- 0xBA04 "SPANSION MBM29LV400BC"
- 0xBA1C "EON EN29LV400AB"
- 0xBA4A "ESI ES29LV400DB"
- 0xBAC2 "MACRONIX MX29LV400B"
- 0xB537 "AMIC A29L400U"
- 0xB91C "EON EN29LV400AT"
- 0xC11F "ATMEL AT49BV802*"
- 0xC298 "TOSHIBA TC58FVT160A"
- 0xC31F "ATMEL AT49BV802*T"
- 0xC420 "ST M29W160BT"
- 0xC4C2 "MACRONIX MX29LV160BT"
- 0xEF20 "ST M29W400B"
- 0x0B8A "DSTTi :P"
- 0x23AD "BRIGHT MICRO. BM29LV400T"
- 0x4398 "TOSHIBA TC58FVB160A"
- 0x4920 "ST M29W160BB"
- 0x5B20 "ST M29W800BT"
- 0x68B0 "SHARP LH28F160BG(H)-TTL"
- 0x69B0 "SHARP LH28F160BG(H)-BTL"
- 0x81BF "SST SST39LF/VF800A"
- 0x89BF "SST SST39LF/VF200A"
- 0x902C "MICRON MT28F160A3-T"
- 0x9220 "ST M28W800BT"
- 0x932C "MICRON MT28F160C3(4)-B"
- 0x9489 "INTEL 28F400B3T"
- 0x9589 "INTEL 28F400B3B"
- 0xABAD "BRIGHT MICRO. BM29LV400B"
- 0xB901 "SPANSION Am29LV400BT"
- 0xB904 "SPANSION MBM29LV400TC"
- 0xB9C2 "MACRONIX MX29LV400T"
- 0xB94A "ESI ES29LV400DT"
- 0xB952 "ALIANCE SEMI. AS29LV400T"
- 0xBA52 "ALIANCE SEMI. AS29LV400B"
- 0xCE20 "ST M28W160E(C)T"
- 0xCF20 "ST M28W160E(C)B"
- 0xD089 "INTEL 28F016B3T"
- 0xD189 "INTEL 28F016B3B"
- 0xD289 "INTEL 28F008B3T"
- 0xD389 "INTEL 28F008B3B"
- 0xD489 "INTEL 28F004B3T"
- 0xD520 "ST M29F400BT"
- 0xD589 "INTEL 28F004B3B"
- 0xD620 "ST M29F400BB"
- 0xD689 "INTEL 28F032B3T"
- 0xD720 "ST M29W800AT"
- 0xD789 "INTEL 28F032B3B"
- 0xDAC2 "MACRONIX MX29LV800T"
- 0xEE20 "ST M29W400T"