Alchemy
Loading...
Searching...
No Matches

sst.c

Go to the documentation of this file.
4
6s32 RunFlashEraseVerifier(u8 *ptr, s32 (*verify)(u8 *));
7
9
10u16 _call_via_r3(s32 mode, u8 *address, u8 expected, FlashWaitProc wait);
11
12/// Issues the chip-erase command and waits for an erased byte.
14 u8 savedCode[64];
15 u16 result;
16 FlashWaitProc *wait;
17
18 REG_WAITCNT = (REG_WAITCNT & 0xFFFC) | gFlash->wait[0];
19
20 *(volatile u8 *)0x0E005555 = 0xAA;
21 *(volatile u8 *)0x0E002AAA = 0x55;
22 *(volatile u8 *)0x0E005555 = 0x80;
23 *(volatile u8 *)0x0E005555 = 0xAA;
24 *(volatile u8 *)0x0E002AAA = 0x55;
25 *(volatile u8 *)0x0E005555 = 0x10;
26
28
29 wait = &gFlash_Handler3;
30 result = _call_via_r3(3, (u8 *)0x0E000000, 255, *wait);
31
32 REG_WAITCNT = (REG_WAITCNT & 0xFFFC) | 3;
33
34 return result;
35}
36
37/// Erases one of sixteen sectors, restoring the cartridge wait setting
38/// afterward.
40 u8 savedCode[64];
41 u16 result;
42 u16 setting;
43 FlashWaitProc *wait;
44 const struct FlashType *chip;
45 volatile u16 *waitcnt;
46 volatile u8 *command;
47 volatile u8 *unlock;
48 volatile u8 *target;
49
50 if (sector > 15) {
51 return 0x80FF;
52 }
53
54 waitcnt = &REG_WAITCNT;
55 setting = *waitcnt & 0xFFFC;
56 chip = gFlash;
57 *waitcnt = setting | chip->wait[0];
58
59 target = (volatile u8 *)((sector << chip->sector.shift) + 0x0E000000);
60
61 command = (volatile u8 *)0x0E005555;
62 *command = 0xAA;
63 unlock = (volatile u8 *)0x0E002AAA;
64 *unlock = 0x55;
65 *command = 0x80;
66 *command = 0xAA;
67 *unlock = 0x55;
68 *target = 0x30;
69
71
73 result = _call_via_r3(2, (u8 *)target, 255, *wait);
74
75 *waitcnt = (*waitcnt & 0xFFFC) | 3;
76
77 return result;
78}
79
80/// Issues a byte-program command and waits for its destination to match.
81u16 ProgramFlashByte(u8 *source, u8 *destination) {
83
84 *(volatile u8 *)0x0e005555 = 0xaa;
85 *(volatile u8 *)0x0e002aaa = 0x55;
86 *(volatile u8 *)0x0e005555 = 0xa0;
87 *destination = *source;
89 return (*wait)(1, destination, *source);
90}
91
93
94/// Erases and verifies a sector with retries, then programs its bytes.
96 u8 ramCode[96];
97 u16 status;
98 u16 remaining;
99 u16 *sourceCode;
100 u16 *destinationCode;
101 u16 *counter;
102 u8 attempt;
103 u8 index;
104 u8 rounds;
105 const struct FlashType *chip;
106 volatile u16 *waitcnt;
107 u16 setting;
108 u8 *destination;
109
110 if (sector > 15) {
111 return 0x80FF;
112 }
113
114 destination = (u8 *)((sector << gFlash->sector.shift) + 0x0E000000);
115
116 sourceCode = (u16 *)((s32)CountRemainingErasedFlashBytes ^ 1);
117 destinationCode = (u16 *)ramCode;
118 remaining =
120 while (remaining != 0) {
121 *destinationCode = *sourceCode;
122 sourceCode++;
123 destinationCode++;
124 remaining = remaining - 2;
125 }
126
127 // Retry until erase verification succeeds or all 81 attempts fail.
128 attempt = 0;
129 for (;;) {
130 status = EraseFlashSector(sector);
131 if (status == 0) {
132 status = RunFlashEraseVerifier(destination, (s32 (*)(u8 *))(ramCode + 1));
133 if (status == 0) {
134 break;
135 }
136 }
137 attempt = attempt + 1;
138 if (attempt == 81) {
139 return status;
140 }
141 }
142
143 // A previously failed erase receives six more conditioning erases.
144 rounds = 1;
145 if (attempt != 0) {
146 rounds = 6;
147 }
148 index = 1;
149 while (index <= rounds) {
151 index = index + 1;
152 }
153
155
156 waitcnt = &REG_WAITCNT;
157 setting = *waitcnt & 0xFFFC;
158 chip = gFlash;
159 *waitcnt = setting | chip->wait[0];
160
161 // Program the verified sector, stopping at the first failed byte.
163 counter = &gFlashNumRemainingBytes;
164 while (*counter != 0) {
165 status = ProgramFlashByte(source, destination);
166 if (status != 0) {
167 break;
168 }
169 *counter = *counter - 1;
170 source++;
171 destination++;
172 }
173
174 REG_WAITCNT = (REG_WAITCNT & 0xFFFC) | 3;
175
176 return status;
177}
178
179/// Returns how many bytes remain when the first non-erased byte is found.
181 s32 remaining;
182
183 for (remaining = gFlash->sector.size; remaining != 0; remaining--) {
184 if (*cursor++ != 0xff)
185 break;
186 }
187 return remaining;
188}
189
190/// Converts a nonzero erased-byte remainder into the flash verification error.
192 if (verify(sector) != 0)
193 return 0x8004;
194 return 0;
195}
u16 gFlashNumRemainingBytes
u16 gFlash_Handler3
Credits scroll position in pixels, in the low half of a flash work cell.
void CopyFlashReadRoutineToRam(void *destination)
Copies the byte reader to RAM and installs its Thumb entry point.
Definition flash.c:161
Flash memory: erasing, programming and reading sectors.
The flash chips: sector size and count, and each chip type's routines.
u16(*) FlashWaitProc(u8 timingIndex, volatile u8 *address, u8 expected)
Definition flash_data.h:9
const struct FlashType * gFlash
The hardware's I/O registers and their bits, as pret names them.
#define REG_WAITCNT
Definition io_reg.h:307
s32 _call_via_r3(s32, s32, s32, s32)
s32 RunFlashEraseVerifier(u8 *ptr, s32(*verify)(u8 *))
Converts a nonzero erased-byte remainder into the flash verification error.
Definition sst.c:191
u16 ProgramFlashSectorWithEraseRetry(u16 sector, u8 *source)
Erases and verifies a sector with retries, then programs its bytes.
Definition sst.c:95
u16 EraseFlashSector(u16 sector)
Erases one of sixteen sectors, restoring the cartridge wait setting afterward.
Definition sst.c:39
s32 CountRemainingErasedFlashBytes(u8 *ptr)
Returns how many bytes remain when the first non-erased byte is found.
Definition sst.c:180
u16 ProgramFlashByte(u8 *source, u8 *destination)
Issues a byte-program command and waits for its destination to match.
Definition sst.c:81
u16 EraseFlashChip(void)
Issues the chip-erase command and waits for an erased byte.
Definition sst.c:13
Flash chip type (the 24-byte record pointed to by gFlash).
Definition flash_data.h:20
struct FlashSector sector
Definition flash_data.h:22
u16 wait[2]
Low two bits of REG_WAITCNT.
Definition flash_data.h:23
signed int s32
Definition types.h:14
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11