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