2019-07-25 02:02:32 +02:00
|
|
|
#include "spi_test.h"
|
|
|
|
#include "timer.h"
|
|
|
|
#include "ui.h"
|
|
|
|
#include "spi.h"
|
|
|
|
|
|
|
|
void SPITestWaitWriteEnd(CardType type) {
|
|
|
|
while (SPIWaitWriteEnd(type));
|
|
|
|
}
|
|
|
|
|
|
|
|
int SPITestEraseSector(CardType type, u32 offset, u8 actualCmd) {
|
|
|
|
u8 cmd[4] = { actualCmd, (u8)(offset >> 16), (u8)(offset >> 8), (u8) offset };
|
2019-07-27 01:58:20 +02:00
|
|
|
if(type == NO_CHIP) return 0xC8E13404;
|
2019-07-25 02:02:32 +02:00
|
|
|
|
|
|
|
int res = SPIWaitWriteEnd(type);
|
|
|
|
|
|
|
|
if( (res = SPIEnableWriting(type)) ) return res;
|
|
|
|
if( (res = SPIWriteRead(type, cmd, 4, NULL, 0, NULL, 0)) ) return res;
|
|
|
|
SPITestWaitWriteEnd(type);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 SPITestEraseAll(CardType type, u32 size, u8 actualCmd, u32 eraseSize) {
|
|
|
|
u32 offset;
|
|
|
|
u64 timer = timer_start();
|
|
|
|
for(offset = 0; offset < size; offset += eraseSize) {
|
|
|
|
SPITestEraseSector(type, offset, actualCmd);
|
|
|
|
}
|
|
|
|
return timer_ticks(timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
u64 SPITestWriteAll(CardType type, u32 size, u8 actualCmd, u32 pageSize, u8 *buf) {
|
|
|
|
memset(buf, 0, size);
|
|
|
|
u8 cmd[4] = { actualCmd, 0, 0, 0 };
|
|
|
|
u32 offset = 0;
|
|
|
|
u64 timer = timer_start();
|
|
|
|
for(offset = 0; offset < size; offset += pageSize) {
|
|
|
|
cmd[1] = (u8)(offset >> 16);
|
|
|
|
cmd[2] = (u8)(offset >> 8);
|
|
|
|
cmd[3] = (u8) offset;
|
|
|
|
SPIEnableWriting(type);
|
|
|
|
SPIWriteRead(type, cmd, 4, NULL, 0, buf, pageSize);
|
|
|
|
SPIWaitWriteEnd(type);
|
|
|
|
}
|
|
|
|
return timer_ticks(timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
int SPITestBytes(CardType t, u32 id, u8 *buf, u8 byte, const char *word, u32 size) {
|
|
|
|
u32 offset;
|
|
|
|
SPIReadSaveData(t, 0, buf, size);
|
|
|
|
for(offset = 0; offset < size; offset++) {
|
|
|
|
if(buf[offset] != byte) {
|
|
|
|
if(word && !ShowPrompt(true, "ID: 0x%06lX\n1: Could not %s\n*0x%06lX = 0x%02hhX", id, word, offset, buf[offset])) return -1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SPIFlashTest(void) {
|
2019-07-27 01:58:20 +02:00
|
|
|
CardType t = ShowPrompt(true, "Does the cart have IR?") ? FLASH_512KB_1_INFRARED : FLASH_256KB_1;
|
2019-07-25 02:02:32 +02:00
|
|
|
u32 size;
|
|
|
|
u32 pageSize;
|
|
|
|
u32 jedecid;
|
|
|
|
if(SPIReadJEDECIDAndStatusReg(t, &jedecid, NULL)) return;
|
|
|
|
if(!ShowPrompt(true, "ID: 0x%06lX\nDo flash test on this cart?\nThis will overwrite it completely\nseveral times!", jedecid)) return;
|
|
|
|
size = ShowHexPrompt(0, 8, "Memory size?");
|
|
|
|
u8 *buf = calloc(size, 1);
|
|
|
|
if (buf == NULL) {
|
|
|
|
ShowPrompt(false, "Malloc failed!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pageSize = ShowHexPrompt(0, 8, "Page size?");
|
|
|
|
// method 1:
|
|
|
|
u64 time1 = SPITestWriteAll(t, size, 0x0A, pageSize, buf);
|
|
|
|
int result1 = SPITestBytes(t, jedecid, buf, 0x00, "write", size);
|
|
|
|
if(result1 < 0) {
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ShowPrompt(false, "ID: 0x%06lX\nWriting all took %llu\nError: %d", jedecid, time1, result1);
|
|
|
|
// method 2: Erasing
|
|
|
|
u8 eraseCommand;
|
|
|
|
u32 eraseSize;
|
|
|
|
for(eraseCommand = 0xC0; eraseCommand < 0xE0; eraseCommand++) {
|
|
|
|
ShowString("Testing %hhX", eraseCommand);
|
|
|
|
SPITestEraseSector(t, 0, eraseCommand);
|
|
|
|
SPIReadSaveData(t, 0, buf, size);
|
|
|
|
for(eraseSize = 0; eraseSize < size && buf[eraseSize] == 0xff; eraseSize++);
|
|
|
|
if(eraseSize) {
|
|
|
|
SPITestWriteAll(t, eraseSize, 0x02, pageSize, buf);
|
|
|
|
if(SPITestBytes(t, jedecid, buf, 0x00, "reset", size) < 0) {
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ShowPrompt(true, "ID: 0x%06lX\n0x%02hhX erased %lu bytes\nTest?", jedecid, eraseCommand, eraseSize)) {
|
|
|
|
u64 eraseTime = SPITestEraseAll(t, size, eraseCommand, eraseSize);
|
|
|
|
int eraseResult = SPITestBytes(t, jedecid, buf, 0xFF, "erase", size);
|
|
|
|
if(eraseResult < 0) {
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
u64 writeTime = SPITestWriteAll(t, size, 0x02, pageSize, buf);
|
|
|
|
int writeResult = SPITestBytes(t, jedecid, buf, 0x00, "write", size);
|
|
|
|
if(eraseResult < 0) {
|
|
|
|
free(buf);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ShowPrompt(false, "ID: 0x%06lX\n0x%02hhX erases %lu bytes\nErase: %llu (%d)\nWrite: %llu (%d)\nTotal: %llu", jedecid, eraseCommand, eraseSize, eraseTime, eraseResult, writeTime, writeResult, eraseTime + writeTime);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(buf);
|
|
|
|
|
|
|
|
}
|
|
|
|
|