mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-26 03:34:15 +01:00
Port agb_flash from pokeruby
This commit is contained in:
parent
b4a39100c0
commit
7dad2846f8
1079
asm/libagbbackup.s
1079
asm/libagbbackup.s
File diff suppressed because it is too large
Load Diff
@ -333,7 +333,7 @@ sub_8152908: @ 8152908
|
|||||||
lsls r0, 24
|
lsls r0, 24
|
||||||
lsrs r4, r0, 24
|
lsrs r4, r0, 24
|
||||||
adds r0, r4, 0
|
adds r0, r4, 0
|
||||||
bl ProgramFlashSectorsAndVerify
|
bl ProgramFlashSectorAndVerify
|
||||||
cmp r0, 0
|
cmp r0, 0
|
||||||
bne _08152924
|
bne _08152924
|
||||||
movs r0, 0x1
|
movs r0, 0x1
|
||||||
@ -1876,7 +1876,7 @@ _08153654:
|
|||||||
ble _08153654
|
ble _08153654
|
||||||
adds r0, r6, 0
|
adds r0, r6, 0
|
||||||
adds r1, r7, 0
|
adds r1, r7, 0
|
||||||
bl ProgramFlashSectorsAndVerify
|
bl ProgramFlashSectorAndVerify
|
||||||
cmp r0, 0
|
cmp r0, 0
|
||||||
bne _08153680
|
bne _08153680
|
||||||
movs r0, 0x1
|
movs r0, 0x1
|
||||||
|
@ -197,7 +197,9 @@ SECTIONS {
|
|||||||
{
|
{
|
||||||
asm/libgcnmultiboot.o(.text);
|
asm/libgcnmultiboot.o(.text);
|
||||||
asm/libmks4agb.o(.text);
|
asm/libmks4agb.o(.text);
|
||||||
asm/libagbbackup.o(.text);
|
src/agb_flash.o(.text);
|
||||||
|
src/agb_flash_1m.o(.text);
|
||||||
|
src/agb_flash_mx.o(.text);
|
||||||
asm/librtc.o(.text);
|
asm/librtc.o(.text);
|
||||||
asm/librfu.o(.text);
|
asm/librfu.o(.text);
|
||||||
asm/libagbsyscall.o(.text);
|
asm/libagbsyscall.o(.text);
|
||||||
@ -230,7 +232,10 @@ SECTIONS {
|
|||||||
lib_rodata :
|
lib_rodata :
|
||||||
ALIGN(4)
|
ALIGN(4)
|
||||||
{
|
{
|
||||||
data/libagbbackup_rodata.o(.rodata);
|
src/agb_flash.o(.rodata);
|
||||||
|
src/agb_flash_1m.o(.rodata);
|
||||||
|
src/agb_flash_mx.o(.rodata);
|
||||||
|
src/agb_flash_le.o(.rodata);
|
||||||
data/librtc_rodata.o(.rodata);
|
data/librtc_rodata.o(.rodata);
|
||||||
data/librfu_rodata.o(.rodata);
|
data/librfu_rodata.o(.rodata);
|
||||||
tools/agbcc/lib/libgcc.a:_divdi3.o(.rodata);
|
tools/agbcc/lib/libgcc.a:_divdi3.o(.rodata);
|
||||||
|
295
src/agb_flash.c
Normal file
295
src/agb_flash.c
Normal file
@ -0,0 +1,295 @@
|
|||||||
|
#include "gba/gba.h"
|
||||||
|
#include "gba/flash_internal.h"
|
||||||
|
|
||||||
|
static u8 sTimerNum;
|
||||||
|
static u16 sTimerCount;
|
||||||
|
static vu16 *sTimerReg;
|
||||||
|
static u16 sSavedIme;
|
||||||
|
|
||||||
|
u8 gFlashTimeoutFlag;
|
||||||
|
u8 (*PollFlashStatus)(u8 *);
|
||||||
|
u16 (*WaitForFlashWrite)(u8 phase, u8 *addr, u8 lastData);
|
||||||
|
u16 (*ProgramFlashSector)(u16 sectorNum, u8 *src);
|
||||||
|
const struct FlashType *gFlash;
|
||||||
|
u16 (*ProgramFlashByte)(u16 sectorNum, u32 offset, u8 data);
|
||||||
|
u16 gFlashNumRemainingBytes;
|
||||||
|
u16 (*EraseFlashChip)();
|
||||||
|
u16 (*EraseFlashSector)(u16 sectorNum);
|
||||||
|
const u16 *gFlashMaxTime;
|
||||||
|
|
||||||
|
void SetReadFlash1(u16 *dest);
|
||||||
|
|
||||||
|
void SwitchFlashBank(u8 bankNum)
|
||||||
|
{
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0xB0);
|
||||||
|
FLASH_WRITE(0x0000, bankNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DELAY() \
|
||||||
|
do { \
|
||||||
|
vu16 i; \
|
||||||
|
for (i = 20000; i != 0; i--) \
|
||||||
|
; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
u16 ReadFlashId(void)
|
||||||
|
{
|
||||||
|
u16 flashId;
|
||||||
|
u16 readFlash1Buffer[0x20];
|
||||||
|
u8 (*readFlash1)(u8 *);
|
||||||
|
|
||||||
|
SetReadFlash1(readFlash1Buffer);
|
||||||
|
readFlash1 = (u8 (*)(u8 *))((s32)readFlash1Buffer + 1);
|
||||||
|
|
||||||
|
// Enter ID mode.
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0x90);
|
||||||
|
DELAY();
|
||||||
|
|
||||||
|
flashId = readFlash1(FLASH_BASE + 1) << 8;
|
||||||
|
flashId |= readFlash1(FLASH_BASE);
|
||||||
|
|
||||||
|
// Leave ID mode.
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0xF0);
|
||||||
|
FLASH_WRITE(0x5555, 0xF0);
|
||||||
|
DELAY();
|
||||||
|
|
||||||
|
return flashId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlashTimerIntr(void)
|
||||||
|
{
|
||||||
|
if (sTimerCount != 0 && --sTimerCount == 0)
|
||||||
|
gFlashTimeoutFlag = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 SetFlashTimerIntr(u8 timerNum, void (**intrFunc)(void))
|
||||||
|
{
|
||||||
|
if (timerNum >= 4)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sTimerNum = timerNum;
|
||||||
|
sTimerReg = ®_TMCNT(sTimerNum);
|
||||||
|
*intrFunc = FlashTimerIntr;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartFlashTimer(u8 phase)
|
||||||
|
{
|
||||||
|
const u16 *maxTime = &gFlashMaxTime[phase * 3];
|
||||||
|
sSavedIme = REG_IME;
|
||||||
|
REG_IME = 0;
|
||||||
|
sTimerReg[1] = 0;
|
||||||
|
REG_IE |= (INTR_FLAG_TIMER0 << sTimerNum);
|
||||||
|
gFlashTimeoutFlag = 0;
|
||||||
|
sTimerCount = *maxTime++;
|
||||||
|
*sTimerReg++ = *maxTime++;
|
||||||
|
*sTimerReg-- = *maxTime++;
|
||||||
|
REG_IF = (INTR_FLAG_TIMER0 << sTimerNum);
|
||||||
|
REG_IME = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopFlashTimer(void)
|
||||||
|
{
|
||||||
|
REG_IME = 0;
|
||||||
|
*sTimerReg++ = 0;
|
||||||
|
*sTimerReg-- = 0;
|
||||||
|
REG_IE &= ~(INTR_FLAG_TIMER0 << sTimerNum);
|
||||||
|
REG_IME = sSavedIme;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 ReadFlash1(u8 *addr)
|
||||||
|
{
|
||||||
|
return *addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetReadFlash1(u16 *dest)
|
||||||
|
{
|
||||||
|
u16 *src;
|
||||||
|
u16 i;
|
||||||
|
|
||||||
|
PollFlashStatus = (u8 (*)(u8 *))((s32)dest + 1);
|
||||||
|
|
||||||
|
src = (u16 *)ReadFlash1;
|
||||||
|
src = (u16 *)((s32)src ^ 1);
|
||||||
|
|
||||||
|
i = ((s32)SetReadFlash1 - (s32)ReadFlash1) >> 1;
|
||||||
|
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
*dest++ = *src++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFlash_Core(u8 *src, u8 *dest, u32 size)
|
||||||
|
{
|
||||||
|
while (size-- != 0)
|
||||||
|
{
|
||||||
|
*dest++ = *src++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadFlash(u16 sectorNum, u32 offset, u8 *dest, u32 size)
|
||||||
|
{
|
||||||
|
u8 *src;
|
||||||
|
u16 i;
|
||||||
|
u16 readFlash_Core_Buffer[0x40];
|
||||||
|
u16 *funcSrc;
|
||||||
|
u16 *funcDest;
|
||||||
|
void (*readFlash_Core)(u8 *, u8 *, u32);
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
|
||||||
|
{
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcSrc = (u16 *)ReadFlash_Core;
|
||||||
|
funcSrc = (u16 *)((s32)funcSrc ^ 1);
|
||||||
|
funcDest = readFlash_Core_Buffer;
|
||||||
|
|
||||||
|
i = ((s32)ReadFlash - (s32)ReadFlash_Core) >> 1;
|
||||||
|
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
*funcDest++ = *funcSrc++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
readFlash_Core = (void (*)(u8 *, u8 *, u32))((s32)readFlash_Core_Buffer + 1);
|
||||||
|
|
||||||
|
src = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
|
||||||
|
|
||||||
|
readFlash_Core(src, dest, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 VerifyFlashSector_Core(u8 *src, u8 *tgt, u32 size)
|
||||||
|
{
|
||||||
|
while (size-- != 0)
|
||||||
|
{
|
||||||
|
if (*tgt++ != *src++)
|
||||||
|
return (u32)(tgt - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 VerifyFlashSector(u16 sectorNum, u8 *src)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u16 verifyFlashSector_Core_Buffer[0x80];
|
||||||
|
u16 *funcSrc;
|
||||||
|
u16 *funcDest;
|
||||||
|
u8 *tgt;
|
||||||
|
u16 size;
|
||||||
|
u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
|
||||||
|
{
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
}
|
||||||
|
|
||||||
|
funcSrc = (u16 *)VerifyFlashSector_Core;
|
||||||
|
funcSrc = (u16 *)((s32)funcSrc ^ 1);
|
||||||
|
funcDest = verifyFlashSector_Core_Buffer;
|
||||||
|
|
||||||
|
i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
|
||||||
|
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
*funcDest++ = *funcSrc++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
|
||||||
|
|
||||||
|
tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
|
||||||
|
size = gFlash->sector.size;
|
||||||
|
|
||||||
|
return verifyFlashSector_Core(src, tgt, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 VerifyFlashSectorNBytes(u16 sectorNum, u8 *src, u32 n)
|
||||||
|
{
|
||||||
|
u16 i;
|
||||||
|
u16 verifyFlashSector_Core_Buffer[0x80];
|
||||||
|
u16 *funcSrc;
|
||||||
|
u16 *funcDest;
|
||||||
|
u8 *tgt;
|
||||||
|
u32 (*verifyFlashSector_Core)(u8 *, u8 *, u32);
|
||||||
|
|
||||||
|
if (gFlash->romSize == FLASH_ROM_SIZE_1M)
|
||||||
|
{
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
}
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
funcSrc = (u16 *)VerifyFlashSector_Core;
|
||||||
|
funcSrc = (u16 *)((s32)funcSrc ^ 1);
|
||||||
|
funcDest = verifyFlashSector_Core_Buffer;
|
||||||
|
|
||||||
|
i = ((s32)VerifyFlashSector - (s32)VerifyFlashSector_Core) >> 1;
|
||||||
|
|
||||||
|
while (i != 0)
|
||||||
|
{
|
||||||
|
*funcDest++ = *funcSrc++;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyFlashSector_Core = (u32 (*)(u8 *, u8 *, u32))((s32)verifyFlashSector_Core_Buffer + 1);
|
||||||
|
|
||||||
|
tgt = FLASH_BASE + (sectorNum << gFlash->sector.shift);
|
||||||
|
|
||||||
|
return verifyFlashSector_Core(src, tgt, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ProgramFlashSectorAndVerify(u16 sectorNum, u8 *src)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
u32 result;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
result = ProgramFlashSector(sectorNum, src);
|
||||||
|
if (result != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result = VerifyFlashSector(sectorNum, src);
|
||||||
|
if (result == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ProgramFlashSectorAndVerifyNBytes(u16 sectorNum, u8 *src, u32 n)
|
||||||
|
{
|
||||||
|
u8 i;
|
||||||
|
u32 result;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
result = ProgramFlashSector(sectorNum, src);
|
||||||
|
if (result != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result = VerifyFlashSectorNBytes(sectorNum, src, n);
|
||||||
|
if (result == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
86
src/agb_flash_1m.c
Normal file
86
src/agb_flash_1m.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "gba/gba.h"
|
||||||
|
#include "gba/flash_internal.h"
|
||||||
|
|
||||||
|
static const char AgbLibFlashVersion[] = "FLASH1M_V103";
|
||||||
|
|
||||||
|
const struct FlashSetupInfo * const sSetupInfos[] =
|
||||||
|
{
|
||||||
|
&MX29L010,
|
||||||
|
&LE26FV10N1TS,
|
||||||
|
&DefaultFlash
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 IdentifyFlash(void)
|
||||||
|
{
|
||||||
|
u16 result;
|
||||||
|
u16 flashId;
|
||||||
|
const struct FlashSetupInfo * const *setupInfo;
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
flashId = ReadFlashId();
|
||||||
|
|
||||||
|
setupInfo = sSetupInfos;
|
||||||
|
result = 1;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if ((*setupInfo)->type.ids.separate.makerId == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (flashId == (*setupInfo)->type.ids.joined)
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupInfo++;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgramFlashByte = (*setupInfo)->programFlashByte;
|
||||||
|
ProgramFlashSector = (*setupInfo)->programFlashSector;
|
||||||
|
EraseFlashChip = (*setupInfo)->eraseFlashChip;
|
||||||
|
EraseFlashSector = (*setupInfo)->eraseFlashSector;
|
||||||
|
WaitForFlashWrite = (*setupInfo)->WaitForFlashWrite;
|
||||||
|
gFlashMaxTime = (*setupInfo)->maxTime;
|
||||||
|
gFlash = &(*setupInfo)->type;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 WaitForFlashWrite_Common(u8 phase, u8 *addr, u8 lastData)
|
||||||
|
{
|
||||||
|
u16 result = 0;
|
||||||
|
u8 status;
|
||||||
|
|
||||||
|
StartFlashTimer(phase);
|
||||||
|
|
||||||
|
while ((status = PollFlashStatus(addr)) != lastData)
|
||||||
|
{
|
||||||
|
if (status & 0x20)
|
||||||
|
{
|
||||||
|
// The write operation exceeded the flash chip's time limit.
|
||||||
|
|
||||||
|
if (PollFlashStatus(addr) == lastData)
|
||||||
|
break;
|
||||||
|
|
||||||
|
FLASH_WRITE(0x5555, 0xF0);
|
||||||
|
result = phase | 0xA000u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gFlashTimeoutFlag)
|
||||||
|
{
|
||||||
|
if (PollFlashStatus(addr) == lastData)
|
||||||
|
break;
|
||||||
|
|
||||||
|
FLASH_WRITE(0x5555, 0xF0);
|
||||||
|
result = phase | 0xC000u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StopFlashTimer();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
31
src/agb_flash_le.c
Normal file
31
src/agb_flash_le.c
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "gba/gba.h"
|
||||||
|
#include "gba/flash_internal.h"
|
||||||
|
|
||||||
|
const u16 leMaxTime[] =
|
||||||
|
{
|
||||||
|
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct FlashSetupInfo LE26FV10N1TS =
|
||||||
|
{
|
||||||
|
ProgramFlashByte_MX,
|
||||||
|
ProgramFlashSector_MX,
|
||||||
|
EraseFlashChip_MX,
|
||||||
|
EraseFlashSector_MX,
|
||||||
|
WaitForFlashWrite_Common,
|
||||||
|
leMaxTime,
|
||||||
|
{
|
||||||
|
131072, // ROM size
|
||||||
|
{
|
||||||
|
4096, // sector size
|
||||||
|
12, // bit shift to multiply by sector size (4096 == 1 << 12)
|
||||||
|
32, // number of sectors
|
||||||
|
0 // appears to be unused
|
||||||
|
},
|
||||||
|
{ 3, 1 }, // wait state setup data
|
||||||
|
{ { 0x62, 0x13 } } // ID
|
||||||
|
}
|
||||||
|
};
|
193
src/agb_flash_mx.c
Normal file
193
src/agb_flash_mx.c
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#include "gba/gba.h"
|
||||||
|
#include "gba/flash_internal.h"
|
||||||
|
|
||||||
|
const u16 mxMaxTime[] =
|
||||||
|
{
|
||||||
|
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
10, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
2000, 65469, TIMER_ENABLE | TIMER_INTR_ENABLE | TIMER_256CLK,
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct FlashSetupInfo MX29L010 =
|
||||||
|
{
|
||||||
|
ProgramFlashByte_MX,
|
||||||
|
ProgramFlashSector_MX,
|
||||||
|
EraseFlashChip_MX,
|
||||||
|
EraseFlashSector_MX,
|
||||||
|
WaitForFlashWrite_Common,
|
||||||
|
mxMaxTime,
|
||||||
|
{
|
||||||
|
131072, // ROM size
|
||||||
|
{
|
||||||
|
4096, // sector size
|
||||||
|
12, // bit shift to multiply by sector size (4096 == 1 << 12)
|
||||||
|
32, // number of sectors
|
||||||
|
0 // appears to be unused
|
||||||
|
},
|
||||||
|
{ 3, 1 }, // wait state setup data
|
||||||
|
{ { 0xC2, 0x09 } } // ID
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct FlashSetupInfo DefaultFlash =
|
||||||
|
{
|
||||||
|
ProgramFlashByte_MX,
|
||||||
|
ProgramFlashSector_MX,
|
||||||
|
EraseFlashChip_MX,
|
||||||
|
EraseFlashSector_MX,
|
||||||
|
WaitForFlashWrite_Common,
|
||||||
|
mxMaxTime,
|
||||||
|
{
|
||||||
|
131072, // ROM size
|
||||||
|
{
|
||||||
|
4096, // sector size
|
||||||
|
12, // bit shift to multiply by sector size (4096 == 1 << 12)
|
||||||
|
32, // number of sectors
|
||||||
|
0 // appears to be unused
|
||||||
|
},
|
||||||
|
{ 3, 1 }, // wait state setup data
|
||||||
|
{ { 0x00, 0x00 } } // ID of 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
u16 EraseFlashChip_MX(void)
|
||||||
|
{
|
||||||
|
u16 result;
|
||||||
|
u16 readFlash1Buffer[0x20];
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
|
||||||
|
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0x80);
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0x10);
|
||||||
|
|
||||||
|
SetReadFlash1(readFlash1Buffer);
|
||||||
|
|
||||||
|
result = WaitForFlashWrite(3, FLASH_BASE, 0xFF);
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 EraseFlashSector_MX(u16 sectorNum)
|
||||||
|
{
|
||||||
|
u16 numTries;
|
||||||
|
u16 result;
|
||||||
|
u8 *addr;
|
||||||
|
u16 readFlash1Buffer[0x20];
|
||||||
|
|
||||||
|
if (sectorNum >= gFlash->sector.count)
|
||||||
|
return 0x80FF;
|
||||||
|
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
|
||||||
|
numTries = 0;
|
||||||
|
|
||||||
|
try_erase:
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
|
||||||
|
|
||||||
|
addr = FLASH_BASE + (sectorNum << gFlash->sector.shift);
|
||||||
|
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0x80);
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
*addr = 0x30;
|
||||||
|
|
||||||
|
SetReadFlash1(readFlash1Buffer);
|
||||||
|
|
||||||
|
result = WaitForFlashWrite(2, addr, 0xFF);
|
||||||
|
|
||||||
|
if (!(result & 0xA000) || numTries > 3)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
numTries++;
|
||||||
|
|
||||||
|
goto try_erase;
|
||||||
|
|
||||||
|
done:
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | WAITCNT_SRAM_8;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ProgramFlashByte_MX(u16 sectorNum, u32 offset, u8 data)
|
||||||
|
{
|
||||||
|
u8 *addr;
|
||||||
|
u16 readFlash1Buffer[0x20];
|
||||||
|
|
||||||
|
if (offset >= gFlash->sector.size)
|
||||||
|
return 0x8000;
|
||||||
|
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
|
||||||
|
addr = FLASH_BASE + (sectorNum << gFlash->sector.shift) + offset;
|
||||||
|
|
||||||
|
SetReadFlash1(readFlash1Buffer);
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
|
||||||
|
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0xA0);
|
||||||
|
*addr = data;
|
||||||
|
|
||||||
|
return WaitForFlashWrite(1, addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static u16 ProgramByte(u8 *src, u8 *dest)
|
||||||
|
{
|
||||||
|
FLASH_WRITE(0x5555, 0xAA);
|
||||||
|
FLASH_WRITE(0x2AAA, 0x55);
|
||||||
|
FLASH_WRITE(0x5555, 0xA0);
|
||||||
|
*dest = *src;
|
||||||
|
|
||||||
|
return WaitForFlashWrite(1, dest, *src);
|
||||||
|
}
|
||||||
|
|
||||||
|
u16 ProgramFlashSector_MX(u16 sectorNum, u8 *src)
|
||||||
|
{
|
||||||
|
u16 result;
|
||||||
|
u8 *dest;
|
||||||
|
u16 readFlash1Buffer[0x20];
|
||||||
|
|
||||||
|
if (sectorNum >= gFlash->sector.count)
|
||||||
|
return 0x80FF;
|
||||||
|
|
||||||
|
result = EraseFlashSector_MX(sectorNum);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
SwitchFlashBank(sectorNum / SECTORS_PER_BANK);
|
||||||
|
sectorNum %= SECTORS_PER_BANK;
|
||||||
|
|
||||||
|
SetReadFlash1(readFlash1Buffer);
|
||||||
|
|
||||||
|
REG_WAITCNT = (REG_WAITCNT & ~WAITCNT_SRAM_MASK) | gFlash->wait[0];
|
||||||
|
|
||||||
|
gFlashNumRemainingBytes = gFlash->sector.size;
|
||||||
|
dest = FLASH_BASE + (sectorNum << gFlash->sector.shift);
|
||||||
|
|
||||||
|
while (gFlashNumRemainingBytes > 0)
|
||||||
|
{
|
||||||
|
result = ProgramByte(src, dest);
|
||||||
|
|
||||||
|
if (result != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
gFlashNumRemainingBytes--;
|
||||||
|
src++;
|
||||||
|
dest++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user