f2747e3f3ff8244770b149758ee155a3d7cd8204
[librecmc/librecmc.git] / target / linux / at91-2.6 / image / dfboot / src / main.c
1 /*----------------------------------------------------------------------------
2  *         ATMEL Microcontroller Software Support  -  ROUSSET  -
3  *----------------------------------------------------------------------------
4  * The software is delivered "AS IS" without warranty or condition of any
5  * kind, either express, implied or statutory. This includes without
6  * limitation any warranty or condition with respect to merchantability or
7  * fitness for any particular purpose, or against the infringements of
8  * intellectual property rights of others.
9  *----------------------------------------------------------------------------
10  * File Name            : main.c
11  * Object               : 
12  * Creation             : HIi   10/10/2003
13  * Modif                : HIi   15/06/2004 :    add crc32 to verify the download
14  *                                              from dataflash
15  *                      : HIi   21/09/2004 :    Set first PLLA to 180Mhz and MCK to
16  *                                              60Mhz to speed up dataflash boot (15Mhz)
17  *                      : MLC   12/04/2005 :    Modify SetPLL() to avoid errata
18  *                      : USA   30/12/2005 :    Change to page Size 1056
19  *                                              Change startaddress to C0008400
20  *                                              Change SPI Speed to ~4 Mhz
21  *                                              Add retry on CRC Error
22  *----------------------------------------------------------------------------
23  */
24 #include "config.h"
25 #include "stdio.h"
26 #include "AT91RM9200.h"
27 #include "lib_AT91RM9200.h"
28 #include "com.h"
29 #include "main.h"
30 #include "dataflash.h"
31 #include "AT91C_MCI_Device.h"
32
33 #define DEBUGOUT
34 #define XMODEM
35 #define MEMDISP
36
37 #ifdef  PAGESZ_1056
38 #define PAGESIZE        1056
39 #else
40 #define PAGESIZE        1024
41 #endif
42
43 #define AT91C_SDRAM_START 0x20000000
44 #define AT91C_BOOT_ADDR 0x21F00000
45 #define AT91C_BOOT_SIZE 128*PAGESIZE
46 #ifdef  PAGESZ_1056
47 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400
48 #else
49 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000
50 #endif
51 #define AT91C_PLLA_VALUE 0x2026BE04     // crystal= 18.432MHz
52 //#define AT91C_PLLA_VALUE 0x202CBE01   // crystal= 4MHz
53
54
55
56 #define DISP_LINE_LEN 16
57
58 // Reason for boot failure
59 #define IMAGE_BAD_SIZE                  0
60 #define IMAGE_READ_FAILURE      1
61 #define IMAGE_CRC_ERROR         2
62 #define IMAGE_ERROR                     3
63 #define SUCCESS                         -1
64
65 /* prototypes*/
66 extern void AT91F_ST_ASM_HANDLER(void);
67 extern void Jump(unsigned int addr);
68
69 const char *menu_dataflash[] = {
70 #ifdef XMODEM
71         "1: P DFboot\n",
72         "2: P U-Boot\n",
73 #endif
74         "3: P SDCard\n",
75 #ifdef  PAGESZ_1056
76         "4: R UBOOT\n",
77 #else
78         "4: R UBOOT\n",
79 #endif
80 #ifdef XMODEM
81         "5: P DF [addr]\n",
82 #endif
83         "6: RD DF [addr]\n",
84         "7: E DF\n"
85 };
86 #ifdef XMODEM
87 #define MAXMENU 7
88 #else
89 #define MAXMENU 4
90 #endif
91
92 char message[20];
93 #ifdef XMODEM
94 volatile char XmodemComplete = 0;
95 #endif
96 unsigned int StTick = 0;
97
98 AT91S_RomBoot const *pAT91;
99 #ifdef XMODEM
100 AT91S_SBuffer sXmBuffer;
101 AT91S_SvcXmodem svcXmodem;
102 AT91S_Pipe xmodemPipe;
103 #endif
104 AT91S_CtlTempo ctlTempo;
105
106
107 //*--------------------------------------------------------------------------------------
108 //* Function Name       : GetTickCount()
109 //* Object              : Return the number of systimer tick 
110 //* Input Parameters    :
111 //* Output Parameters   :
112 //*--------------------------------------------------------------------------------------
113 unsigned int GetTickCount(void)
114 {
115         return StTick;
116 }
117
118 #ifdef XMODEM
119 //*--------------------------------------------------------------------------------------
120 //* Function Name       : AT91_XmodemComplete()
121 //* Object              : Perform the remap and jump to appli in RAM
122 //* Input Parameters    :
123 //* Output Parameters   :
124 //*--------------------------------------------------------------------------------------
125 static void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
126 {
127         /* stop the Xmodem tempo */
128         svcXmodem.tempo.Stop(&(svcXmodem.tempo));
129         XmodemComplete = 1;
130 }
131
132
133 //*--------------------------------------------------------------------------------------
134 //* Function Name       : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
135 //* Object              : Xmodem dispatcher
136 //* Input Parameters    :
137 //* Output Parameters   :
138 //*--------------------------------------------------------------------------------------
139 static void XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
140 {
141         AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild;
142         AT91PS_USART   pUsart     = svcXmodem.pUsart;
143                         
144         if (pSBuffer->szRdBuffer == 0) {
145                 /* Start a tempo to wait the Xmodem protocol complete */
146                 svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);                                                          
147         }
148 }
149 #endif
150
151 //*--------------------------------------------------------------------------------------
152 //* Function Name       : irq1_c_handler()
153 //* Object              : C Interrupt handler for Interrutp source 1
154 //* Input Parameters    : none
155 //* Output Parameters   : none
156 //*--------------------------------------------------------------------------------------
157 void AT91F_ST_HANDLER(void)
158 {
159         volatile unsigned int csr = *AT91C_DBGU_CSR;
160 #ifdef XMODEM
161         unsigned int error;
162 #endif
163         
164         if (AT91C_BASE_ST->ST_SR & 0x01) {
165                 StTick++;
166                 ctlTempo.CtlTempoTick(&ctlTempo);
167                 return;
168         }
169
170 #ifdef XMODEM
171         error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU);
172         if (csr & error) {
173                 /* Stop previous Xmodem transmition*/
174                 *(AT91C_DBGU_CR) = AT91C_US_RSTSTA;
175                 AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX);
176                 AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY);
177
178         }
179         
180         else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY | 
181                         AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT | 
182                         AT91C_US_RXBUFF)) {
183                 if ( !(svcXmodem.eot) )
184                         svcXmodem.Handler(&svcXmodem, csr);
185         }
186 #endif
187 }
188
189
190 //*-----------------------------------------------------------------------------
191 //* Function Name       : AT91F_DisplayMenu()
192 //* Object              : 
193 //* Input Parameters    : 
194 //* Return value                : 
195 //*-----------------------------------------------------------------------------
196 static int AT91F_DisplayMenu(void)
197 {
198         int i, mci_present = 0;
199         printf("\nDF LOADER %s %s %s\n",AT91C_VERSION,__DATE__,__TIME__);
200         AT91F_DataflashPrintInfo();
201         mci_present = AT91F_MCI_Init();
202         for(i = 0; i < MAXMENU; i++) {
203                 puts(menu_dataflash[i]);
204         }
205         return mci_present;
206 }       
207
208
209 //*-----------------------------------------------------------------------------
210 //* Function Name       : AsciiToHex()
211 //* Object              : ascii to hexa conversion
212 //* Input Parameters    : 
213 //* Return value                : 
214 //*-----------------------------------------------------------------------------
215 static unsigned int AsciiToHex(char *s, unsigned int *val)
216 {
217         int n;
218
219         *val=0;
220         
221         if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X')))
222                 s+=2;
223         n = 0;  
224         while((n < 8) && (s[n] !=0))
225         {
226                 *val <<= 4;
227                 if ( (s[n] >= '0') && (s[n] <='9'))
228                         *val += (s[n] - '0');
229                 else    
230                         if ((s[n] >= 'a') && (s[n] <='f'))
231                                 *val += (s[n] - 0x57);
232                         else
233                                 if ((s[n] >= 'A') && (s[n] <='F'))
234                                         *val += (s[n] - 0x37);
235                         else
236                                 return 0;
237                 n++;
238         }
239
240         return 1;                               
241 }
242
243
244 #ifdef MEMDISP
245 //*-----------------------------------------------------------------------------
246 //* Function Name       : AT91F_MemoryDisplay()
247 //* Object              : Display the content of the dataflash
248 //* Input Parameters    : 
249 //* Return value                : 
250 //*-----------------------------------------------------------------------------
251 static int AT91F_MemoryDisplay(unsigned int addr, unsigned int length)
252 {
253         unsigned long   i, nbytes, linebytes;
254         char    *cp;
255 //      unsigned int    *uip;
256 //      unsigned short  *usp;
257         unsigned char   *ucp;
258         char linebuf[DISP_LINE_LEN];
259
260 //      nbytes = length * size;
261         nbytes = length;
262         do
263         {
264 //              uip = (unsigned int *)linebuf;
265 //              usp = (unsigned short *)linebuf;
266                 ucp = (unsigned char *)linebuf;
267                 
268                 printf("%08x:", addr);
269                 linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
270                 if((addr & 0xF0000000) == 0x20000000) {
271                         for(i = 0; i < linebytes; i ++) {
272                                 linebuf[i] =  *(char *)(addr+i);
273                         }
274                 } else {
275                         read_dataflash(addr, linebytes, linebuf);
276                 }
277                 for (i=0; i<linebytes; i++)
278                 {
279 /*                      if (size == 4) 
280                                 printf(" %08x", *uip++);
281                         else if (size == 2)
282                                 printf(" %04x", *usp++);
283                         else
284 */
285                                 printf(" %02x", *ucp++);
286 //                      addr += size;
287                         addr++;
288                 }
289                 printf("    ");
290                 cp = linebuf;
291                 for (i=0; i<linebytes; i++) {
292                         if ((*cp < 0x20) || (*cp > 0x7e))
293                                 printf(".");
294                         else
295                                 printf("%c", *cp);
296                         cp++;
297                 }
298                 printf("\n");
299                 nbytes -= linebytes;
300         } while (nbytes > 0);
301         return 0;
302 }
303 #endif
304
305 //*--------------------------------------------------------------------------------------
306 //* Function Name       : AT91F_SetPLL
307 //* Object              : Set the PLLA to 180Mhz and Master clock to 60 Mhz
308 //* Input Parameters    :
309 //* Output Parameters   :
310 //*--------------------------------------------------------------------------------------
311 static unsigned int AT91F_SetPLL(void)
312 {
313         AT91_REG tmp;
314         AT91PS_PMC pPmc = AT91C_BASE_PMC;
315         AT91PS_CKGR pCkgr = AT91C_BASE_CKGR;
316
317         pPmc->PMC_IDR = 0xFFFFFFFF;
318
319         /* -Setup the PLL A */
320         pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
321
322         while (!(*AT91C_PMC_SR & AT91C_PMC_LOCKA));
323         
324         /* - Switch Master Clock from PLLB to PLLA/3 */
325         tmp = pPmc->PMC_MCKR;
326         /* See Atmel Errata #27 and #28 */
327         if (tmp & 0x0000001C) {
328                 tmp = (tmp & ~0x0000001C);
329                 pPmc->PMC_MCKR = tmp;
330                 while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
331         }
332         if (tmp != 0x00000202) {
333                 pPmc->PMC_MCKR = 0x00000202;
334                 if ((tmp & 0x00000003) != 0x00000002)
335                         while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY));
336         }
337
338         return 1;       
339 }
340
341
342 //*--------------------------------------------------------------------------------------
343 //* Function Name       : AT91F_ResetRegisters
344 //* Object              : Restore the initial state to registers
345 //* Input Parameters    :
346 //* Output Parameters   :
347 //*--------------------------------------------------------------------------------------
348 static unsigned int AT91F_ResetRegisters(void)
349 {
350         volatile int i = 0;
351
352         /* set the PIOs in input*/
353         /* This disables the UART output, so dont execute for now*/
354
355 #ifndef DEBUGOUT
356         *AT91C_PIOA_ODR = 0xFFFFFFFF;   /* Disables all the output pins */
357         *AT91C_PIOA_PER = 0xFFFFFFFF;   /* Enables the PIO to control all the pins */
358 #endif
359
360         AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
361         /* close all peripheral clocks */
362
363 #ifndef DEBUGOUT
364         AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC;
365 #endif
366         /* Disable core interrupts and set supervisor mode */
367         __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
368         /* Clear all the interrupts */
369         *AT91C_AIC_ICCR = 0xffffffff;
370
371         /* read the AIC_IVR and AIC_FVR */
372         i = *AT91C_AIC_IVR;
373         i = *AT91C_AIC_FVR;
374
375         /* write the end of interrupt control register */
376         *AT91C_AIC_EOICR        = 0;
377
378         return 1;
379 }
380
381
382 static int AT91F_LoadBoot(void)
383 {
384 //      volatile unsigned int crc1 = 0, crc2 = 0;
385         volatile unsigned int SizeToDownload = 0x21400;
386         volatile unsigned int AddressToDownload = AT91C_BOOT_ADDR;
387
388 #if 0
389         /* Read vector 6 to extract size to load */     
390         if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, 32,
391                            (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
392         {
393                 printf("Bad Code Size\n");
394                 return IMAGE_BAD_SIZE;
395         }
396         /* calculate the size to download */
397         SizeToDownload = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
398 #endif
399         
400 //      printf("\nLoad UBOOT from dataflash[%x] to SDRAM[%x]\n",
401 //             AT91C_BOOT_DATAFLASH_ADDR, AT91C_BOOT_ADDR);
402         if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, SizeToDownload + 8,
403                            (char *)AddressToDownload) != AT91C_DATAFLASH_OK)
404         {
405                 printf("F DF RD\n");
406                 return IMAGE_READ_FAILURE;
407         }
408 #if 0
409         pAT91->CRC32((const unsigned char *)AT91C_BOOT_ADDR,
410                      (unsigned int)SizeToDownload , (unsigned int *)&crc2);
411         crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) +
412                (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
413                (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
414                (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
415
416         /* Restore the value of Vector 6 */
417         *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) =
418                 *(int *)(AddressToDownload + SizeToDownload + 4);
419         
420         if (crc1 != crc2) {
421                 printf("DF CRC bad %x != %x\n",crc1,crc2);
422                 return  IMAGE_CRC_ERROR;
423         }
424 #endif
425         return SUCCESS;
426 }
427
428 static int AT91F_StartBoot(void)
429 {
430         int     sts;
431         if((sts = AT91F_LoadBoot()) != SUCCESS) return sts;
432 //      printf("\n");
433 //      printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n");
434         if (AT91F_ResetRegisters())
435         {
436                 printf("Jump");
437                 Jump(AT91C_BOOT_ADDR);
438 //              LED_blink(0);
439         }
440         return  IMAGE_ERROR;
441 }
442
443 #if 0
444 static void     AT91F_RepeatedStartBoot(void)
445 {
446         int     i;
447         for(i = 0; i < CRC_RETRIES; i++) {
448                 if(AT91F_StartBoot() != IMAGE_CRC_ERROR){
449 //                      LED_blink(1);
450                         return;
451                 }
452         }
453         return;
454 }
455 #endif
456
457 #define TRUE 1
458 #define FALSE 0
459 #define TRX_MAGIC 0x30524448  /* "HDR0" */
460 #define TRX_VERSION 1
461
462 struct trx_header {
463         unsigned int magic;
464         unsigned int len;
465         unsigned int crc32;
466         unsigned int flag_version;
467         unsigned int offsets[3];
468 };
469
470 #define AT91C_MCI_TIMEOUT 1000000
471
472 extern AT91S_MciDevice MCI_Device;
473 extern void AT91F_MCIDeviceWaitReady(unsigned int);
474 extern int AT91F_MCI_ReadBlockSwab(AT91PS_MciDevice, int, unsigned int *, int);
475
476 int Program_From_MCI(void)
477 {
478   int i;
479   unsigned int Max_Read_DataBlock_Length;
480   int block = 0;
481   int buffer = AT91C_DOWNLOAD_BASE_ADDRESS;
482   int bufpos = AT91C_DOWNLOAD_BASE_ADDRESS;
483   int NbPage = 0;
484   struct trx_header *p;
485
486         p = (struct trx_header *)bufpos;
487
488         Max_Read_DataBlock_Length = MCI_Device.pMCI_DeviceFeatures->Max_Read_DataBlock_Length;
489
490         AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT);
491
492   AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
493
494   if (p->magic != TRX_MAGIC) {
495                 printf("Inv IMG 0x%08x\n", p->magic);
496                 return FALSE;
497                 }
498
499         printf("RDSD");
500         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC8 | AT91C_PIO_PC14;
501         for (i=0; i<(p->len/512); i++) {
502                 AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length);
503                 block++;
504                 bufpos += Max_Read_DataBlock_Length;
505                 }
506
507         NbPage = 0;
508         i = dataflash_info[0].Device.pages_number;
509         while(i >>= 1)
510                 NbPage++;
511         i = ((p->offsets[1] - p->offsets[0])/ 512) + 1 + (NbPage << 13) + (dataflash_info[0].Device.pages_size << 17);
512         *(int *)(buffer + p->offsets[0] + AT91C_OFFSET_VECT6) = i;
513
514         printf(" WDFB");
515         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC14;
516         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8;
517         write_dataflash(0xc0000000, buffer + p->offsets[0], p->offsets[1] - p->offsets[0]);
518         printf(" WUB");
519         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
520         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
521         write_dataflash(0xc0008000, buffer + p->offsets[1], p->offsets[2] - p->offsets[1]);
522         printf(" WKRFS");
523         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC15;
524         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC14;
525         write_dataflash(0xc0042000, buffer + p->offsets[2], p->len - p->offsets[2]);
526         AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC14;
527         AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC15;
528         return TRUE;
529 }
530
531 //*----------------------------------------------------------------------------
532 //* Function Name       : main
533 //* Object              : Main function
534 //* Input Parameters    : none
535 //* Output Parameters   : True
536 //*----------------------------------------------------------------------------
537 int main(void)
538 {
539 #ifdef XMODEM
540         AT91PS_Buffer           pXmBuffer;
541         AT91PS_SvcComm          pSvcXmodem;
542 #endif
543         AT91S_SvcTempo          svcBootTempo;    // Link to a AT91S_Tempo object
544         unsigned int            ix;
545         volatile unsigned int AddressToDownload, SizeToDownload;        
546         unsigned int DeviceAddress = 0;
547         char command = 0;
548 #ifdef XMODEM
549         volatile int i = 0;     
550         unsigned int crc1 = 0, crc2 = 0;
551         volatile int device;
552         int NbPage;
553 #endif
554         volatile int Nb_Device = 0;
555         int mci_present = 0;
556
557         pAT91 = AT91C_ROM_BOOT_ADDRESS;
558
559         if (!AT91F_SetPLL())
560         {
561                 printf("F SetPLL");
562                 while(1);
563         }
564
565         at91_init_uarts();
566
567         /* Tempo Initialisation */
568         pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
569         ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));
570         
571         // Attach the tempo to a tempo controler
572         ctlTempo.CtlTempoCreate(&ctlTempo, &svcBootTempo);
573 //      LED_init();
574 //      LED_blink(2);
575
576 #ifdef XMODEM
577         /* Xmodem Initialisation */
578         pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
579         pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem,
580                      (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
581         pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
582 #endif
583
584         /* System Timer initialization */
585         AT91F_AIC_ConfigureIt(
586                 AT91C_BASE_AIC,                        // AIC base address
587                 AT91C_ID_SYS,                          // System peripheral ID
588                 AT91C_AIC_PRIOR_HIGHEST,               // Max priority
589                 AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive
590                 AT91F_ST_ASM_HANDLER
591         );
592         /* Enable ST interrupt */
593         AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
594
595 #ifndef PRODTEST
596         /* Start tempo to start Boot in a delay of
597          * AT91C_DELAY_TO_BOOT sec if no key pressed */
598         svcBootTempo.Start(&svcBootTempo, AT91C_DELAY_TO_BOOT,
599                            0, AT91F_StartBoot, NULL);
600 #endif
601
602         while(1)
603         {
604                 while(command == 0)
605                 {
606                         AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS;
607                         SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE;
608                         DeviceAddress = 0;
609                         
610                         /* try to detect Dataflash */
611                         if (!Nb_Device)
612                                 Nb_Device = AT91F_DataflashInit();                              
613                                                         
614                         mci_present = AT91F_DisplayMenu();
615
616 #ifdef PRODTEST
617                         if (mci_present) {
618                                 if (Program_From_MCI())
619                                         AT91F_StartBoot();
620                         }
621 #endif
622
623                         message[0] = 0;
624                         AT91F_ReadLine ("Enter: ", message);
625
626 #ifndef PRODTEST
627                         /* stop tempo ==> stop autoboot */
628                         svcBootTempo.Stop(&svcBootTempo);
629 #endif
630
631                         command = message[0];
632                         for(ix = 1; (message[ix] == ' ') && (ix < 12); ix++);   // Skip some whitespace
633                                 
634                         if(!AsciiToHex(&message[ix], &DeviceAddress) )
635                                 DeviceAddress = 0;                      // Illegal DeviceAddress
636                                 
637                         switch(command)
638                         {
639 #ifdef XMODEM
640                                 case '1':
641                                 case '2':
642                                 case '5':
643                                         if(command == '1') {
644                                                 DeviceAddress = 0xC0000000;
645 //                                              printf("Download DataflashBoot.bin to [0x%x]\n", DeviceAddress);
646                                         } else if(command == '2') {
647                                                 DeviceAddress = AT91C_BOOT_DATAFLASH_ADDR;
648 //                                              printf("Download u-boot.bin to [0x%x]\n", DeviceAddress);
649                                         } else {
650 //                                              printf("Download Dataflash to [0x%x]\n", DeviceAddress);
651                                         }
652                                         switch(DeviceAddress & 0xFF000000)
653                                         {
654                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
655                                                         if (dataflash_info[0].id == 0){
656                                                                 printf("No DF");
657                                                                 AT91F_WaitKeyPressed();
658                                                                 command = 0;
659                                                         }
660
661                                                         device = 0;
662                                                 break;
663                                         
664                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
665                                                         if (dataflash_info[1].id == 0){
666                                                                 printf("No DF");
667                                                                 AT91F_WaitKeyPressed();
668                                                                 command = 0;
669                                                         }
670                                                         device = 1;
671                                                 break;
672                                         
673                                                 default:
674                                                         command = 0;
675                                                 break;
676                                         }
677                                 break;
678 #endif
679
680                                 case '3':
681                                         if (mci_present)
682                                                 Program_From_MCI();
683                                         command = 0;
684                                         break;
685
686                                 case '4':
687                                         AT91F_StartBoot();
688                                         command = 0;
689                                 break;
690
691 #ifdef MEMDISP
692                                 case '6':
693                                         do 
694                                         {
695                                                 AT91F_MemoryDisplay(DeviceAddress, 256);
696                                                 AT91F_ReadLine (NULL, message);
697                                                 DeviceAddress += 0x100;
698                                         }
699                                         while(message[0] == '\0');
700                                         command = 0;
701                                 break;
702 #endif
703
704                                 case '7':
705                                         switch(DeviceAddress & 0xFF000000)
706                                         {
707                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
708                                                         break;
709                                                 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
710                                                         break;
711                                                 default:
712                                                         command = 0;
713                                                         break;
714                                         }
715
716                                         if (command != 0) {
717                                                 AT91F_ReadLine ("RDY ERA\nSure?",
718                                                                 message);
719                                                 if(message[0] == 'Y' || message[0] == 'y') {
720                                                         erase_dataflash(DeviceAddress & 0xFF000000);
721 //                                                      printf("Erase complete\n\n");
722                                                 }
723 //                                              else
724 //                                                      printf("Erase aborted\n");
725                                         }
726                                         command = 0;
727
728                                 break;
729
730                                 default:
731                                         command = 0;
732                                 break;
733                         }
734                 }
735 #ifdef XMODEM
736                 for(i = 0; i <= AT91C_DOWNLOAD_MAX_SIZE; i++)
737                         *(unsigned char *)(AddressToDownload + i) = 0;
738         
739                 xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload,
740                                 SizeToDownload, XmodemProtocol, 0);     
741                 while(XmodemComplete !=1);
742                 SizeToDownload = (unsigned int)((svcXmodem.pData) -
743                                  (unsigned int)AddressToDownload);
744
745                 /* Modification of vector 6 */
746                 if ((DeviceAddress == CFG_DATAFLASH_LOGIC_ADDR_CS0)) {
747                         // Vector 6 must be compliant to the BootRom description (ref Datasheet)
748                         NbPage = 0;
749                 i = dataflash_info[device].Device.pages_number;
750                 while(i >>= 1)
751                         NbPage++;
752                         i = (SizeToDownload / 512)+1 + (NbPage << 13) +
753                             (dataflash_info[device].Device.pages_size << 17); //+4 to add crc32
754                     SizeToDownload = 512 * (i &0xFF);
755                 }       
756                 else
757                 {
758                         /* Save the contents of vector 6 ==> will be restored 
759                          * at boot time (AT91F_StartBoot) */
760                         *(int *)(AddressToDownload + SizeToDownload + 4) =
761                                 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6);
762                         /* Modify Vector 6 to contain the size of the
763                          * file to copy (Dataflash -> SDRAM)*/
764                         i = SizeToDownload;     
765                 }               
766
767                 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i;
768 //              printf("\nModification of Arm Vector 6 :%x\n", i);
769                             
770 //              printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress);
771                 crc1 = 0;
772                 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1);
773
774                 /* Add the crc32 at the end of the code */
775                 *(char *)(AddressToDownload + SizeToDownload)     = (char)(crc1 & 0x000000FF);
776                 *(char *)(AddressToDownload + SizeToDownload + 1) = (char)((crc1 & 0x0000FF00) >> 8);
777                 *(char *)(AddressToDownload + SizeToDownload + 2) = (char)((crc1 & 0x00FF0000) >> 16);
778                 *(char *)(AddressToDownload + SizeToDownload + 3) = (char)((crc1 & 0xFF000000) >> 24);
779
780                 /* write dataflash */
781                 write_dataflash (DeviceAddress, AddressToDownload, (SizeToDownload + 8));
782
783                 /* clear the buffer before read */
784                 for(i=0; i <= SizeToDownload; i++)
785                         *(unsigned char *)(AddressToDownload + i) = 0;
786                                         
787                 /* Read dataflash to check the validity of the data */
788                 read_dataflash (DeviceAddress, (SizeToDownload + 4), (char *)(AddressToDownload));
789
790                 printf("VFY: ");        
791                 crc2 = 0;
792                                 
793                 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2);
794                 crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload))          +
795                            (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) +
796                            (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) +
797                            (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24);
798
799                 if (crc1 != crc2)
800                         printf("ERR");
801                 else
802                         printf("OK");
803                         
804                 command = 0;
805                 XmodemComplete = 0;
806                 AT91F_WaitKeyPressed();
807 #endif
808         }
809 }
810