4 #include "../cpu/cpu.h"
10 #define CPUCLK_IN_KHZ 48000
12 #define IRQ_MASK 0x00000080
13 #define FIQ_MASK 0x00000040
14 #define INTs_MASK (IRQ_MASK | FIQ_MASK)
19 typedef struct flashSectorToAddress_s
21 unsigned long address;
24 flashSectorToAddress_t;
26 static flashSectorToAddress_t flashSectorToAddress [] =
28 { 0x00000000, 4096 }, // 0
29 { 0x00001000, 4096 }, // 1
30 { 0x00002000, 4096 }, // 2
31 { 0x00003000, 4096 }, // 3
32 { 0x00004000, 4096 }, // 4
33 { 0x00005000, 4096 }, // 5
34 { 0x00006000, 4096 }, // 6
35 { 0x00007000, 4096 }, // 7
36 { 0x00008000, 32768 }, // 8
37 { 0x00010000, 32768 }, // 9
38 { 0x00018000, 32768 }, // 10
39 { 0x00020000, 32768 }, // 11
40 { 0x00028000, 32768 }, // 12
41 { 0x00030000, 32768 }, // 13
42 { 0x00038000, 32768 }, // 14
43 { 0x00040000, 32768 }, // 15
44 { 0x00048000, 32768 }, // 16
45 { 0x00050000, 32768 }, // 17
46 { 0x00058000, 32768 }, // 18
47 { 0x00060000, 32768 }, // 19
48 { 0x00068000, 32768 }, // 20
49 { 0x00070000, 32768 }, // 21
50 { 0x00078000, 4096 }, // 22
51 { 0x00079000, 4096 }, // 23
52 { 0x0007a000, 4096 }, // 24
53 { 0x0007b000, 4096 }, // 25
54 { 0x0007c000, 4096 }, // 26
57 typedef struct iapErrnoStr_s
64 static iapErrnoStr_t iapErrnoStr [] =
66 { IAP_RESULT_CMD_SUCCESS, "success" },
67 { IAP_RESULT_INVALID_COMMAND, "invalid command" },
68 { IAP_RESULT_SRC_ADDR_ERROR, "source address error" },
69 { IAP_RESULT_DST_ADDR_ERROR, "destination address error" },
70 { IAP_RESULT_SRC_ADDR_NOT_MAPPED, "source address not mapped" },
71 { IAP_RESULT_DST_ADDR_NOT_MAPPED, "destination address not mapped" },
72 { IAP_RESULT_COUNT_ERROR, "count error" },
73 { IAP_RESULT_INVALID_SECTOR, "invalid sector" },
74 { IAP_RESULT_SECTOR_NOT_BLANK, "sector not blank" },
75 { IAP_RESULT_SECTOR_NOT_PREPARED, "sector not prepared" },
76 { IAP_RESULT_COMPARE_ERROR, "compare error" },
77 { IAP_RESULT_BUSY, "busy" },
78 { IAP_RESULT_PARAM_ERROR, "parameter error" },
79 { IAP_RESULT_ADDR_ERROR, "address error" },
80 { IAP_RESULT_ADDR_NOT_MAPPED, "address not mapped" },
81 { IAP_RESULT_CMD_LOCKED, "command locked" },
82 { IAP_RESULT_INVALID_CODE, "invalid code" },
83 { IAP_RESULT_INVALID_BAUD_RATE, "invalid baud rate" },
84 { IAP_RESULT_ANVALID_STOP_BIT, "invalid stop bit" },
85 { IAP_RESULT_CRP_ENABLED, "CRP enabled" },
86 { IAP_RESULT_X_NOTSAFEREGION, "sector or address not in safe region" },
87 { IAP_RESULT_X_NOSAFEREGIONAVAIL, "no safe sectors available (all of memory used?)" },
93 static unsigned int iapCommands [5];
94 static unsigned int iapResults [2];
95 static int iapErrno = 0;
96 extern unsigned long __end_of_text__;
97 static unsigned int end_of_text = (unsigned int) &__end_of_text__;
110 int iapSectorToAddress (int sectorNumber, unsigned long *address, int *sectorSize)
112 if (sectorNumber >= (int) arrsizeof (flashSectorToAddress))
116 *address = flashSectorToAddress [sectorNumber].address;
118 *sectorSize = flashSectorToAddress [sectorNumber].sizeInBytes;
124 // Convert address to sector, or -1 if address not in flash area
126 int iapAddressToSector (unsigned long address)
130 for (i = 0; i < (int) arrsizeof (flashSectorToAddress); i++)
131 if (address < (flashSectorToAddress [i].address + flashSectorToAddress [i].sizeInBytes))
134 iapErrno = IAP_RESULT_INVALID_SECTOR;
139 // 1 == address in safe region, 0 if not
141 int iapIsSafeAddress (unsigned long address)
146 if ((eotSector = iapAddressToSector (end_of_text)) == -1)
148 if ((addressSector = iapAddressToSector (address)) == -1)
151 if (addressSector <= eotSector)
153 iapErrno = IAP_RESULT_X_NOTSAFEREGION;
161 // 0 == not safe sector, 1 == safe (not in a code sector)
163 int iapIsSafeSector (int sector)
167 if ((eotSector = iapAddressToSector (end_of_text)) == -1)
170 if (sector <= eotSector)
172 iapErrno = IAP_RESULT_X_NOTSAFEREGION;
180 // Returns a safe sector number or -1 if none available
182 int iapFindSafeSector (void)
186 for (i = 0; i < arrsizeof (flashSectorToAddress); i++)
187 if (iapIsSafeSector (i))
190 iapErrno = IAP_RESULT_X_NOSAFEREGIONAVAIL;
195 // 1 == sector is safe, 0 == not safe
197 int iapIsValidSector (int sector)
199 if ((sector < 0) || (sector >= (int) arrsizeof (flashSectorToAddress)))
201 iapErrno = IAP_RESULT_INVALID_SECTOR;
211 int iapGetErrno (void)
216 const char *iapStrerror (int err)
220 for (i = 0; i < arrsizeof (iapErrnoStr); i++)
221 if (iapErrnoStr [i].errno == err)
222 return iapErrnoStr [i].text;
230 static void iapCall (void) __attribute ((naked));
231 static void iapCall (void)
233 register void *pFP0 asm("r0") = iapCommands;
234 register void *pFP1 asm("r1") = iapResults;
236 asm volatile(" bx %[iapLocation]"
238 : "r" (pFP0), "r" (pFP1), [iapLocation] "r" (IAP_LOCATION) );
244 static inline unsigned __get_cpsr (void)
246 unsigned long retval;
248 asm volatile (" mrs %0, cpsr" : "=r" (retval) : /* no inputs */ );
253 static inline void __set_cpsr (unsigned val)
255 asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );
258 static unsigned disableInts (void)
262 _cpsr = __get_cpsr ();
265 __set_cpsr (_cpsr | INTs_MASK);
266 while ((__get_cpsr () ^ INTs_MASK) & INTs_MASK);
271 static unsigned restoreInts (unsigned oldCPSR)
275 _cpsr = __get_cpsr();
278 __set_cpsr ((_cpsr & ~INTs_MASK) | (oldCPSR & INTs_MASK));
279 while ((__get_cpsr () ^ oldCPSR) & INTs_MASK);
287 int iapPrepareSectors (int startingSector, int endingSector)
291 if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
294 iapCommands [0] = IAP_CMD_PREPARE;
295 iapCommands [1] = startingSector;
296 iapCommands [2] = endingSector;
298 cpsr = disableInts ();
304 return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
308 // IAP_CMD_COPYRAMTOFLASH can span multiple sectors (2, at any rate, since bufferLen
309 // must be 256, 512, 1024 or 4096, and the smallest sectors are 4096 bytes). Although
310 // more than 2 sectors can be prepared for writing, it's useless to do so, since
311 // after each IAP_CMD_COPYRAMTOFLASH, the sectors are re-locked.
313 int iapWriteSectors (unsigned int address, unsigned char *buffer, int bufferLen)
317 iapCommands [0] = IAP_CMD_COPYRAMTOFLASH;
318 iapCommands [1] = address;
319 iapCommands [2] = (int) buffer;
320 iapCommands [3] = bufferLen;
321 iapCommands [4] = CPUCLK_IN_KHZ;
323 cpsr = disableInts ();
329 if ((iapErrno = iapResults [0]) != IAP_RESULT_CMD_SUCCESS)
335 int iapFillSectors (int startingSector, int endingSector, int byte)
338 unsigned char buffer [256];
340 if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
343 memset (buffer, byte, sizeof (buffer));
345 for (sector = startingSector; sector <= endingSector; sector++)
348 unsigned long address;
351 if (iapSectorToAddress (sector, &address, §orSize))
354 for (i = 0; i < sectorSize; i += sizeof (buffer))
356 if (iapPrepareSectors (sector, sector) == -1)
358 if (iapWriteSectors (address + i, buffer, sizeof (buffer)) == -1)
360 if (iapCompare (address + i, buffer, sizeof (buffer)) == -1)
368 int iapEraseSectors (int startingSector, int endingSector)
372 if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
375 if (iapPrepareSectors (startingSector, endingSector) == -1)
378 iapCommands [0] = IAP_CMD_ERASE;
379 iapCommands [1] = startingSector;
380 iapCommands [2] = endingSector;
381 iapCommands [3] = CPUCLK_IN_KHZ;
383 cpsr = disableInts ();
389 return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
393 // -1 = error (iapErrno set)
395 // 1 = sector not blank
397 int iapBlankCheckSectors (int startingSector, int endingSector)
401 if (!iapIsValidSector (startingSector) || !iapIsValidSector (endingSector))
404 iapCommands [0] = IAP_CMD_BLANKCHECK;
405 iapCommands [1] = startingSector;
406 iapCommands [2] = endingSector;
408 cpsr = disableInts ();
414 if ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS)
416 if (iapResults [0] == IAP_RESULT_SECTOR_NOT_BLANK)
425 unsigned int iapReadPartID (void)
429 iapCommands [0] = IAP_CMD_READPARTID;
431 cpsr = disableInts ();
437 return iapResults [1];
443 unsigned int iapReadBootCodeVersion (void)
447 iapCommands [0] = IAP_CMD_READBOOTCODEVER;
449 cpsr = disableInts ();
455 return iapResults [1];
461 int iapCompare (unsigned int address, unsigned char *buffer, int bufferLen)
465 iapCommands [0] = IAP_CMD_COMPARE;
466 iapCommands [1] = address;
467 iapCommands [2] = (int) buffer;
468 iapCommands [3] = bufferLen;
470 cpsr = disableInts ();
476 return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
487 portDISABLE_INTERRUPTS ();
489 VIC_IntEnClr = VIC_IntEnClr_MASK;
493 SCB_PLLFEED = SCB_PLLFEED_FEED1;
494 SCB_PLLFEED = SCB_PLLFEED_FEED2;
498 USB_PLLFEED = USB_PLLFEED_FEED1;
499 USB_PLLFEED = USB_PLLFEED_FEED2;
501 for (p = (REG32 *) T1_BASE_ADDR, i = 0; i< 0x74 / 4; i++)
506 SCB_PCONP = 0x000003be;
519 PCB_PINSEL0 = 0x00000000;
520 PCB_PINSEL1 = 0x00000000;
522 GPIO0_IODIR = 0x00004000;
523 GPIO0_IOCLR = 0x00004000;
527 WD_FEED = WD_FEED_FEED1;
528 WD_FEED = WD_FEED_FEED2;
530 iapCommands [0] = IAP_CMD_REINVOKEISP;