v0.1 board believed to be reading Vbat, Pressure, and X/Y/Z correctly now,
[fw/openalt] / iap / iap.c
1 #include "FreeRTOS.h"
2
3 #include <string.h>
4 #include "../cpu/cpu.h"
5 #include "iap.h"
6
7 //
8 //
9 //
10 #define CPUCLK_IN_KHZ 48000
11
12 #define IRQ_MASK  0x00000080
13 #define FIQ_MASK  0x00000040
14 #define INTs_MASK (IRQ_MASK | FIQ_MASK)
15
16 //
17 //
18 //
19 typedef struct flashSectorToAddress_s
20 {
21   unsigned long address;
22   int sizeInBytes;
23 }
24 flashSectorToAddress_t;
25
26 static flashSectorToAddress_t flashSectorToAddress [] = 
27 {
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
55 };
56
57 typedef struct iapErrnoStr_s
58 {
59   int errno;
60   const char *text;
61 }
62 iapErrnoStr_t;
63
64 static iapErrnoStr_t iapErrnoStr [] =
65 {
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?)" },
88 };
89
90 //
91 //
92 //
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__;
98
99
100 //
101 //
102 //
103 void iapInit (void)
104 {
105 }
106
107 //
108 //
109 //
110 int iapSectorToAddress (int sectorNumber, unsigned long *address, int *sectorSize)
111 {
112   if (sectorNumber >= (int) arrsizeof (flashSectorToAddress))
113     return -1;
114
115   if (address)
116     *address = flashSectorToAddress [sectorNumber].address;
117   if (sectorSize)
118     *sectorSize = flashSectorToAddress [sectorNumber].sizeInBytes;
119
120   return 0;
121 }
122
123 //
124 //  Convert address to sector, or -1 if address not in flash area
125 //
126 int iapAddressToSector (unsigned long address)
127 {
128   int i;
129
130   for (i = 0; i < (int) arrsizeof (flashSectorToAddress); i++)
131     if (address < (flashSectorToAddress [i].address + flashSectorToAddress [i].sizeInBytes))
132       return i;
133
134   iapErrno = IAP_RESULT_INVALID_SECTOR;
135   return -1;
136 }
137
138 //
139 //  1 == address in safe region, 0 if not
140 //
141 int iapIsSafeAddress (unsigned long address)
142 {
143   int eotSector;
144   int addressSector;
145
146   if ((eotSector = iapAddressToSector (end_of_text)) == -1)
147     return 0;
148   if ((addressSector = iapAddressToSector (address)) == -1)
149     return 0;
150
151   if (addressSector <= eotSector)
152   {
153     iapErrno = IAP_RESULT_X_NOTSAFEREGION;
154     return 0;
155   }
156
157   return 1;
158 }
159
160 //
161 //  0 == not safe sector, 1 == safe (not in a code sector)
162 //
163 int iapIsSafeSector (int sector)
164 {
165   int eotSector;
166
167   if ((eotSector = iapAddressToSector (end_of_text)) == -1)
168     return 0;
169
170   if (sector <= eotSector)
171   {
172     iapErrno = IAP_RESULT_X_NOTSAFEREGION;
173     return 0;
174   }
175
176   return 1;
177 }
178
179 //
180 //  Returns a safe sector number or -1 if none available
181 //
182 int iapFindSafeSector (void)
183 {
184   unsigned int i;
185
186   for (i = 0; i < arrsizeof (flashSectorToAddress); i++)
187     if (iapIsSafeSector (i))
188       return i;
189
190   iapErrno = IAP_RESULT_X_NOSAFEREGIONAVAIL;
191   return -1;
192 }
193
194 //
195 //  1 == sector is safe, 0 == not safe
196 //
197 int iapIsValidSector (int sector)
198 {
199   if ((sector < 0) || (sector >= (int) arrsizeof (flashSectorToAddress)))
200   {
201     iapErrno = IAP_RESULT_INVALID_SECTOR;
202     return 0;
203   }
204
205   return 1;
206 }
207
208 //
209 //
210 //
211 int iapGetErrno (void)
212 {
213   return iapErrno;
214 }
215
216 const char *iapStrerror (int err)
217 {
218   unsigned int i;
219
220   for (i = 0; i < arrsizeof (iapErrnoStr); i++)
221     if (iapErrnoStr [i].errno == err)
222       return iapErrnoStr [i].text;
223
224   return NULL;
225 }
226
227 //
228 //
229 //
230 static void iapCall (void) __attribute ((naked));
231 static void iapCall (void)
232 {
233   register void *pFP0 asm("r0") = iapCommands;
234   register void *pFP1 asm("r1") = iapResults;
235
236   asm volatile(" bx  %[iapLocation]"
237                :
238                : "r" (pFP0), "r" (pFP1), [iapLocation] "r" (IAP_LOCATION) );
239 }
240
241 //
242 //
243 //
244 static inline unsigned __get_cpsr (void)
245 {
246   unsigned long retval;
247
248   asm volatile (" mrs  %0, cpsr" : "=r" (retval) : /* no inputs */  );
249
250   return retval;
251 }
252
253 static inline void __set_cpsr (unsigned val)
254 {
255   asm volatile (" msr  cpsr, %0" : /* no outputs */ : "r" (val)  );
256 }
257
258 static unsigned disableInts (void)
259 {
260   unsigned _cpsr;
261
262   _cpsr = __get_cpsr ();
263
264   do
265     __set_cpsr (_cpsr | INTs_MASK);
266   while ((__get_cpsr () ^ INTs_MASK) & INTs_MASK);
267
268   return _cpsr;
269 }
270
271 static unsigned restoreInts (unsigned oldCPSR)
272 {
273   unsigned _cpsr;
274
275   _cpsr = __get_cpsr();
276
277   do
278     __set_cpsr ((_cpsr & ~INTs_MASK) | (oldCPSR & INTs_MASK));
279   while ((__get_cpsr () ^ oldCPSR) & INTs_MASK);
280
281   return _cpsr;
282 }
283
284 //
285 //
286 //
287 int iapPrepareSectors (int startingSector, int endingSector)
288 {
289   unsigned int cpsr;
290
291   if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
292     return -1;
293
294   iapCommands [0] = IAP_CMD_PREPARE;
295   iapCommands [1] = startingSector;
296   iapCommands [2] = endingSector;
297
298   cpsr = disableInts ();
299
300   iapCall ();
301
302   restoreInts (cpsr);
303
304   return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
305 }
306
307 //
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.
312 //
313 int iapWriteSectors (unsigned int address, unsigned char *buffer, int bufferLen)
314 {
315   unsigned int cpsr;
316
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;
322
323   cpsr = disableInts ();
324
325   iapCall ();
326
327   restoreInts (cpsr);
328
329   if ((iapErrno = iapResults [0]) != IAP_RESULT_CMD_SUCCESS)
330     return -1;
331
332   return 0;
333 }
334
335 int iapFillSectors (int startingSector, int endingSector, int byte)
336 {
337   int sector;
338   unsigned char buffer [256];
339
340   if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
341     return -1;
342
343   memset (buffer, byte, sizeof (buffer));
344
345   for (sector = startingSector; sector <= endingSector; sector++)
346   {
347     int i;
348     unsigned long address;
349     int sectorSize;
350
351     if (iapSectorToAddress (sector, &address, &sectorSize))
352       return -1;
353
354     for (i = 0; i < sectorSize; i += sizeof (buffer))
355     {
356       if (iapPrepareSectors (sector, sector) == -1)
357         return -1;
358       if (iapWriteSectors (address + i, buffer, sizeof (buffer)) == -1)
359         return -1;
360       if (iapCompare (address + i, buffer, sizeof (buffer)) == -1)
361         return -1;
362     }
363   }
364
365   return 0;
366 }
367
368 int iapEraseSectors (int startingSector, int endingSector)
369 {
370   unsigned int cpsr;
371
372   if (!iapIsSafeSector (startingSector) || !iapIsSafeSector (endingSector))
373     return -1;
374
375   if (iapPrepareSectors (startingSector, endingSector) == -1)
376     return -1;
377
378   iapCommands [0] = IAP_CMD_ERASE;
379   iapCommands [1] = startingSector;
380   iapCommands [2] = endingSector;
381   iapCommands [3] = CPUCLK_IN_KHZ;
382
383   cpsr = disableInts ();
384
385   iapCall ();
386
387   restoreInts (cpsr);
388
389   return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
390 }
391
392 //
393 // -1 = error (iapErrno set)
394 //  0 = sector blank
395 //  1 = sector not blank
396 //
397 int iapBlankCheckSectors (int startingSector, int endingSector)
398 {
399   unsigned int cpsr;
400
401   if (!iapIsValidSector (startingSector) || !iapIsValidSector (endingSector))
402     return -1;
403
404   iapCommands [0] = IAP_CMD_BLANKCHECK;
405   iapCommands [1] = startingSector;
406   iapCommands [2] = endingSector;
407
408   cpsr = disableInts ();
409
410   iapCall ();
411
412   restoreInts (cpsr);
413
414   if ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS)
415     return 0;
416   if (iapResults [0] == IAP_RESULT_SECTOR_NOT_BLANK)
417     return 1;
418
419   return -1;
420 }
421
422 //
423 //
424 //
425 unsigned int iapReadPartID (void)
426 {
427   unsigned int cpsr;
428
429   iapCommands [0] = IAP_CMD_READPARTID;
430
431   cpsr = disableInts ();
432
433   iapCall ();
434
435   restoreInts (cpsr);
436
437   return iapResults [1];
438 }
439
440 //
441 //
442 //
443 unsigned int iapReadBootCodeVersion (void)
444 {
445   unsigned int cpsr;
446
447   iapCommands [0] = IAP_CMD_READBOOTCODEVER;
448
449   cpsr = disableInts ();
450
451   iapCall ();
452
453   restoreInts (cpsr);
454
455   return iapResults [1];
456 }
457
458 //
459 //
460 //
461 int iapCompare (unsigned int address, unsigned char *buffer, int bufferLen)
462 {
463   unsigned int cpsr;
464
465   iapCommands [0] = IAP_CMD_COMPARE;
466   iapCommands [1] = address;
467   iapCommands [2] = (int) buffer;
468   iapCommands [3] = bufferLen;
469
470   cpsr = disableInts ();
471
472   iapCall ();
473
474   restoreInts (cpsr);
475
476   return ((iapErrno = iapResults [0]) == IAP_RESULT_CMD_SUCCESS) ? 0 : -1;
477 }
478
479 //
480 //
481 //
482 void iapISP (void)
483 {
484   int i;
485   REG32 *p;
486
487   portDISABLE_INTERRUPTS ();
488
489   VIC_IntEnClr = VIC_IntEnClr_MASK;
490
491   SCB_PLLCON = 0;
492   SCB_PLLCFG = 0;
493   SCB_PLLFEED = SCB_PLLFEED_FEED1;
494   SCB_PLLFEED = SCB_PLLFEED_FEED2;
495
496   USB_PLLCON = 0; 
497   USB_PLLCFG = 0; 
498   USB_PLLFEED = USB_PLLFEED_FEED1;
499   USB_PLLFEED = USB_PLLFEED_FEED2;
500
501   for (p = (REG32 *) T1_BASE_ADDR, i = 0; i< 0x74 / 4; i++)
502     *p++ = 0;
503
504   T1_IR = 0xff;
505
506   SCB_PCONP = 0x000003be;
507
508   UART0_IER = 0x00; 
509   UART0_LCR = 0x80; 
510   UART0_DLL = 0x01; 
511   UART0_DLM = 0x00;
512   UART0_LCR = 0x00; 
513   UART0_FCR = 0x06; 
514   UART0_FDR = 0x10;
515
516   SCB_MEMMAP = 0;
517   SCB_VPBDIV = 0;
518
519   PCB_PINSEL0 = 0x00000000;
520   PCB_PINSEL1 = 0x00000000;
521   
522   GPIO0_IODIR = 0x00004000;
523   GPIO0_IOCLR = 0x00004000;
524
525   WD_TC = 0x0ffffff; 
526   WD_MOD = 0;
527   WD_FEED = WD_FEED_FEED1;
528   WD_FEED = WD_FEED_FEED2;
529
530   iapCommands [0] = IAP_CMD_REINVOKEISP;
531
532   // disableInts ();
533   // cpuPLLDisable ();
534   // cpuT1Disable ();
535
536   iapCall ();
537 }