Alchemy
Loading...
Searching...
No Matches

flash.c

Go to the documentation of this file.
4#include "types.h"
5
6typedef u8 (*FlashByteRead)(u8 *address);
7
8/// Enters flash ID mode, waits for the chip and reads its device and
9/// manufacturer IDs.
11 struct {
12 u8 buffer[64];
13 u16 delay;
14 } locals;
15 FlashByteRead readByte;
16 s32 result;
17
18 CopyFlashReadRoutineToRam(locals.buffer);
19 readByte = (FlashByteRead)(locals.buffer + 1);
20
21 // Unlock the chip and enter its manufacturer/device identification mode.
22 *(volatile u8 *)0x0e005555 = 0xaa;
23 *(volatile u8 *)0x0e002aaa = 0x55;
24 *(volatile u8 *)0x0e005555 = 0x90;
25
26 {
27 volatile u16 *delay = &locals.delay;
28
29 *delay = 20000;
30 while (*delay != 0)
31 *delay = *delay - 1;
32 }
33
34 // The high byte identifies the device; the low byte identifies its maker.
35 result = (u16)readByte((u8 *)0x0e000001) << 8;
36 result |= readByte((u8 *)0x0e000000);
37
38 *(volatile u8 *)0x0e005555 = 0xaa;
39 *(volatile u8 *)0x0e002aaa = 0x55;
40 *(volatile u8 *)0x0e005555 = 0xf0;
41
42 {
43 volatile u16 *delay = &locals.delay;
44
45 *delay = 20000;
46 while (*delay != 0)
47 *delay = *delay - 1;
48 }
49 return result;
50}
51
52extern const struct FlashSetupInfo *const gFlash_Chips[];
54extern u32 gFlash_Handler0;
55extern u32 gFlash_Handler1;
57extern u16 *gFlash_Handler4;
58
59/// Selects matching chip handlers, falling back to the final table entry when
60/// unknown.
62 u16 missing;
63 u16 id;
64 const struct FlashSetupInfo *const *chip;
65
66 REG_WAITCNT = (REG_WAITCNT & ~3) | 3;
67 id = ReadFlashId();
68 chip = gFlash_Chips;
69 missing = 1;
70 while (((u8 *)&(*chip)->type.id)[0] != 0) {
71 if (id == (*chip)->type.id) {
72 missing = 0;
73 break;
74 }
75 chip++;
76 }
77 // Install the selected record, including the fallback when no ID matched.
78 gFlash_Handler0 = (*chip)->handlers[0];
79 gFlash_Handler1 = (*chip)->handlers[1];
80 gEraseFlashSector = (*chip)->handlers[2];
81 gFlash_Handler3 = (*chip)->wait;
82 gFlash_Handler4 = (*chip)->maxTime;
83 gFlash = &(*chip)->type;
84 return missing;
85}
86
87extern volatile u16 gFlashTimerCount;
89extern u8 gFlashTimerNum;
90extern u16 *gFlashTimerReg;
91
92/// Counts down the active flash timeout and marks its expiration.
93void FlashTimerIntr(void) {
94 if (gFlashTimerCount != 0) {
95 s32 ticksRemaining = gFlashTimerCount;
96
97 ticksRemaining -= 1;
98 gFlashTimerCount = ticksRemaining;
99 if (((u32)ticksRemaining << 16) == 0) {
101 }
102 }
103}
104
105/// Selects a hardware timer and returns its timeout interrupt callback.
106s32 SetFlashTimerIntr(u8 timerIndex, void (**callback)(void)) {
107 if (timerIndex > 3)
108 return 1;
109 gFlashTimerNum = timerIndex;
110 // Each timer's counter, REG_TMnCNT_L, is 4 bytes after the one before
112 *callback = FlashTimerIntr;
113 return 0;
114}
115
116extern u16 gFlashSavedIme;
117
118/// Starts the selected operation timeout, saving the interrupt-enable state.
119void StartFlashTimer(u8 timingIndex) {
120 u16 *timing = (u16 *)((u8 *)gFlash_Handler4 + timingIndex * 6);
121 u16 *timerRegister;
122
124 REG_IME = 0;
125 REG_IE |= 8 << gFlashTimerNum;
126 REG_IME = 1;
128 gFlashTimerCount = *timing;
129 timing++;
130 timerRegister = gFlashTimerReg;
131 *timerRegister = *timing;
132 timerRegister++;
133 gFlashTimerReg = timerRegister;
134 *timerRegister = timing[1];
135 timerRegister--;
136 gFlashTimerReg = timerRegister;
137}
138
139/// Stops the flash timer and restores the saved interrupt-enable state.
140void StopFlashTimer(void) {
141 u16 **savedTimerAddress = &gFlashTimerReg;
142 u16 *timerRegister = *savedTimerAddress;
143
144 *timerRegister = 0;
145 timerRegister++;
146 *savedTimerAddress = timerRegister;
147 *timerRegister = 0;
148 timerRegister--;
149 *savedTimerAddress = timerRegister;
150
151 REG_IME = 0;
152 REG_IE &= ~(u16)(8 << gFlashTimerNum);
154}
155
156/// Reads one byte; copied into RAM so the cartridge can be polled during a
157/// write.
158u8 ReadFlashByte(u8 *source) { return *source; }
159
160/// Copies the byte reader to RAM and installs its Thumb entry point.
161void CopyFlashReadRoutineToRam(void *destination) {
162 u16 *destinationCode = destination;
163 u16 *sourceCode;
164 u16 halfwordsRemaining;
165
166 gFlashReadRoutine = (u8 (*)(u8 *))((s32)destinationCode + 1);
167 sourceCode = (u16 *)ReadFlashByte;
168 sourceCode = (u16 *)((s32)sourceCode ^ 1);
169 halfwordsRemaining =
171 while (halfwordsRemaining != 0) {
172 *destinationCode++ = *sourceCode++;
173 halfwordsRemaining--;
174 }
175}
176
177void StartFlashTimer(u8 index);
178
179/// Polls for the expected byte until success or timeout, returning an operation
180/// error.
181u16 WaitForFlashWrite(u8 timingIndex, volatile u8 *address, u8 expected) {
182 u16 result = 0;
183
184 StartFlashTimer(timingIndex);
185 while ((u8)gFlashReadRoutine((u8 *)address) != expected) {
186 if (gFlashTimeoutFlag) {
187 // Allow a final successful read at the timeout boundary.
188 if ((u8)gFlashReadRoutine((u8 *)address) == expected)
189 break;
190 if (gFlash->id == 0x1cc2)
191 *(volatile u8 *)0x0e005555 = 0xf0;
192 result = timingIndex | 0xc000;
193 break;
194 }
195 }
197 return result;
198}
199
200/// Copies flash bytes into RAM; this routine executes from a RAM copy.
201void ReadFlashCore(const u8 *source, u8 *destination, u32 size) {
202 u32 remaining = size - 1;
203
204 if (size != 0) {
205 do {
206 *destination++ = *source++;
207 } while (remaining-- != 0);
208 }
209}
210
211typedef void (*FlashReadCore)(const u8 *source, u8 *destination, u32 size);
212
213/// Copies the RAM reader and reads a range using the standard sector geometry.
214void ReadFlash(u16 sector, u32 offset, u8 *destination, s32 size) {
215 u16 code[64];
216 u16 *sourceCode;
217 u16 *destinationCode;
218 u16 halfwordsRemaining;
219 FlashReadCore core;
220
221 REG_WAITCNT = (REG_WAITCNT & 0xfffc) | 3;
222 sourceCode = (u16 *)ReadFlashCore;
223 sourceCode = (u16 *)((u32)sourceCode ^ 1);
224 destinationCode = code;
225 halfwordsRemaining = ((u32)ReadFlash - (u32)ReadFlashCore) / 2;
226 while (halfwordsRemaining != 0) {
227 *destinationCode++ = *sourceCode++;
228 halfwordsRemaining--;
229 }
230 core = (FlashReadCore)((u8 *)code + 1);
231 core((u8 *)0x0e000000 + (sector << gFlash_ChipUnknown.type.sector.shift) +
232 offset,
233 destination, size);
234}
235
236/// Returns the first differing byte in the right buffer, or NULL when all bytes
237/// match.
238u8 *VerifyFlashCore(u8 *left, u8 *right, u16 size) {
239 u16 index = size - 1;
240
241 while (index != 0xFFFF) {
242 u8 rightByte = *right;
243 u8 leftByte = *left;
244
245 left++;
246 right++;
247 if (rightByte != leftByte) {
248 return right - 1;
249 }
250 index--;
251 }
252 return 0;
253}
254
255typedef u8 *(*FlashVerifyCore)(u8 *source, u8 *flash, u16 size);
256
257/// Copies the verifier to RAM and compares a standard flash sector with source
258/// data.
259s32 Flash_VerifySector(u16 sector, s32 source) {
260 u16 code[128];
261 u16 *sourceCode;
262 u16 *destinationCode;
263 u16 halfwordsRemaining;
264 FlashVerifyCore core;
265
266 REG_WAITCNT = (REG_WAITCNT & 0xfffc) | 3;
267 sourceCode = (u16 *)VerifyFlashCore;
268 sourceCode = (u16 *)((u32)sourceCode ^ 1);
269 destinationCode = code;
270 halfwordsRemaining = ((u32)Flash_VerifySector - (u32)VerifyFlashCore) / 2;
271 while (halfwordsRemaining != 0) {
272 *destinationCode++ = *sourceCode++;
273 halfwordsRemaining--;
274 }
275 core = (FlashVerifyCore)((u8 *)code + 1);
276 return (s32)core((u8 *)source,
277 (u8 *)0x0e000000 +
280}
u16 gFlash_Handler3
Credits scroll position in pixels, in the low half of a flash work cell.
void StopFlashTimer(void)
Stops the flash timer and restores the saved interrupt-enable state.
Definition flash.c:140
u16 WaitForFlashWrite(u8 timingIndex, volatile u8 *address, u8 expected)
Polls for the expected byte until success or timeout, returning an operation error.
Definition flash.c:181
u8 * VerifyFlashCore(u8 *left, u8 *right, u16 size)
Returns the first differing byte in the right buffer, or NULL when all bytes match.
Definition flash.c:238
s32 ReadFlashId(void)
Enters flash ID mode, waits for the chip and reads its device and manufacturer IDs.
Definition flash.c:10
void(*) FlashReadCore(const u8 *source, u8 *destination, u32 size)
Definition flash.c:211
u16 gFlashSavedIme
s32 SetFlashTimerIntr(u8 timerIndex, void(**callback)(void))
Selects a hardware timer and returns its timeout interrupt callback.
Definition flash.c:106
u32 gEraseFlashSector
u32 gFlash_Handler1
u8 gFlashTimerNum
u16 * gFlash_Handler4
void FlashTimerIntr(void)
Counts down the active flash timeout and marks its expiration.
Definition flash.c:93
void ReadFlash(u16 sector, u32 offset, u8 *destination, s32 size)
Copies the RAM reader and reads a range using the standard sector geometry.
Definition flash.c:214
void CopyFlashReadRoutineToRam(void *destination)
Copies the byte reader to RAM and installs its Thumb entry point.
Definition flash.c:161
void StartFlashTimer(u8 timingIndex)
Starts the selected operation timeout, saving the interrupt-enable state.
Definition flash.c:119
s32 Flash_VerifySector(u16 sector, s32 source)
Copies the verifier to RAM and compares a standard flash sector with source data.
Definition flash.c:259
void ReadFlashCore(const u8 *source, u8 *destination, u32 size)
Copies flash bytes into RAM; this routine executes from a RAM copy.
Definition flash.c:201
u8 ReadFlashByte(u8 *source)
Reads one byte; copied into RAM so the cartridge can be polled during a write.
Definition flash.c:158
s32 IdentifyFlash(void)
Selects matching chip handlers, falling back to the final table entry when unknown.
Definition flash.c:61
u8 gFlashTimeoutFlag
volatile u16 gFlashTimerCount
u32 gFlash_Handler0
u8 *(*) FlashVerifyCore(u8 *source, u8 *flash, u16 size)
Definition flash.c:255
const struct FlashSetupInfo *const gFlash_Chips[]
u16 * gFlashTimerReg
u8(*) FlashByteRead(u8 *address)
Definition flash.c:6
Flash memory: erasing, programming and reading sectors.
u8(*) gFlashReadRoutine(u8 *source)
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
const struct FlashSetupInfo gFlash_ChipUnknown
The hardware's I/O registers and their bits, as pret names them.
#define REG_TM0CNT_L
Definition io_reg.h:298
#define REG_WAITCNT
Definition io_reg.h:307
#define REG_IE
Definition io_reg.h:305
#define REG_IME
Definition io_reg.h:308
Settings for each flash chip model (44 bytes), in flash_setup's field order from flashset....
Definition flash_data.h:29
struct FlashType type
Definition flash_data.h:33
struct FlashSector sector
Definition flash_data.h:22
The integer types, TRUE, UNUSED and the fixed-address macros.
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11