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 *----------------------------------------------------------------------------
12 * Creation : HIi 10/10/2003
13 * Modif : HIi 15/06/2004 : add crc32 to verify the download
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 *----------------------------------------------------------------------------
26 #include "AT91RM9200.h"
27 #include "lib_AT91RM9200.h"
30 #include "dataflash.h"
31 #include "AT91C_MCI_Device.h"
43 #define AT91C_SDRAM_START 0x20000000
44 #define AT91C_BOOT_ADDR 0x21F00000
45 #define AT91C_BOOT_SIZE 128*PAGESIZE
47 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400
49 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000
51 #define AT91C_PLLA_VALUE 0x2026BE04 // crystal= 18.432MHz
52 //#define AT91C_PLLA_VALUE 0x202CBE01 // crystal= 4MHz
56 #define DISP_LINE_LEN 16
58 // Reason for boot failure
59 #define IMAGE_BAD_SIZE 0
60 #define IMAGE_READ_FAILURE 1
61 #define IMAGE_CRC_ERROR 2
66 extern void AT91F_ST_ASM_HANDLER(void);
67 extern void Jump(unsigned int addr
);
69 const char *menu_dataflash
[] = {
94 volatile char XmodemComplete
= 0;
96 unsigned int StTick
= 0;
98 AT91S_RomBoot
const *pAT91
;
100 AT91S_SBuffer sXmBuffer
;
101 AT91S_SvcXmodem svcXmodem
;
102 AT91S_Pipe xmodemPipe
;
104 AT91S_CtlTempo ctlTempo
;
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)
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
)
127 /* stop the Xmodem tempo */
128 svcXmodem
.tempo
.Stop(&(svcXmodem
.tempo
));
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
)
141 AT91PS_SBuffer pSBuffer
= (AT91PS_SBuffer
) xmodemPipe
.pBuffer
->pChild
;
142 AT91PS_USART pUsart
= svcXmodem
.pUsart
;
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
);
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)
159 volatile unsigned int csr
= *AT91C_DBGU_CSR
;
164 if (AT91C_BASE_ST
->ST_SR
& 0x01) {
166 ctlTempo
.CtlTempoTick(&ctlTempo
);
171 error
= AT91F_US_Error((AT91PS_USART
)AT91C_BASE_DBGU
);
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
);
180 else if (csr
& (AT91C_US_TXRDY
| AT91C_US_ENDTX
| AT91C_US_TXEMPTY
|
181 AT91C_US_RXRDY
| AT91C_US_ENDRX
| AT91C_US_TIMEOUT
|
183 if ( !(svcXmodem
.eot
) )
184 svcXmodem
.Handler(&svcXmodem
, csr
);
190 //*-----------------------------------------------------------------------------
191 //* Function Name : AT91F_DisplayMenu()
193 //* Input Parameters :
195 //*-----------------------------------------------------------------------------
196 static int AT91F_DisplayMenu(void)
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
]);
209 //*-----------------------------------------------------------------------------
210 //* Function Name : AsciiToHex()
211 //* Object : ascii to hexa conversion
212 //* Input Parameters :
214 //*-----------------------------------------------------------------------------
215 static unsigned int AsciiToHex(char *s
, unsigned int *val
)
221 if(s
[0] == '0' && ((s
[1] == 'x') || (s
[1] == 'X')))
224 while((n
< 8) && (s
[n
] !=0))
227 if ( (s
[n
] >= '0') && (s
[n
] <='9'))
228 *val
+= (s
[n
] - '0');
230 if ((s
[n
] >= 'a') && (s
[n
] <='f'))
231 *val
+= (s
[n
] - 0x57);
233 if ((s
[n
] >= 'A') && (s
[n
] <='F'))
234 *val
+= (s
[n
] - 0x37);
245 //*-----------------------------------------------------------------------------
246 //* Function Name : AT91F_MemoryDisplay()
247 //* Object : Display the content of the dataflash
248 //* Input Parameters :
250 //*-----------------------------------------------------------------------------
251 static int AT91F_MemoryDisplay(unsigned int addr
, unsigned int length
)
253 unsigned long i
, nbytes
, linebytes
;
255 // unsigned int *uip;
256 // unsigned short *usp;
258 char linebuf
[DISP_LINE_LEN
];
260 // nbytes = length * size;
264 // uip = (unsigned int *)linebuf;
265 // usp = (unsigned short *)linebuf;
266 ucp
= (unsigned char *)linebuf
;
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
);
275 read_dataflash(addr
, linebytes
, linebuf
);
277 for (i
=0; i
<linebytes
; i
++)
280 printf(" %08x", *uip++);
282 printf(" %04x", *usp++);
285 printf(" %02x", *ucp
++);
291 for (i
=0; i
<linebytes
; i
++) {
292 if ((*cp
< 0x20) || (*cp
> 0x7e))
300 } while (nbytes
> 0);
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)
314 AT91PS_PMC pPmc
= AT91C_BASE_PMC
;
315 AT91PS_CKGR pCkgr
= AT91C_BASE_CKGR
;
317 pPmc
->PMC_IDR
= 0xFFFFFFFF;
319 /* -Setup the PLL A */
320 pCkgr
->CKGR_PLLAR
= AT91C_PLLA_VALUE
;
322 while (!(*AT91C_PMC_SR
& AT91C_PMC_LOCKA
));
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
));
332 if (tmp
!= 0x00000202) {
333 pPmc
->PMC_MCKR
= 0x00000202;
334 if ((tmp
& 0x00000003) != 0x00000002)
335 while (!(*AT91C_PMC_SR
& AT91C_PMC_MCKRDY
));
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)
352 /* set the PIOs in input*/
353 /* This disables the UART output, so dont execute for now*/
356 *AT91C_PIOA_ODR
= 0xFFFFFFFF; /* Disables all the output pins */
357 *AT91C_PIOA_PER
= 0xFFFFFFFF; /* Enables the PIO to control all the pins */
360 AT91F_AIC_DisableIt (AT91C_BASE_AIC
, AT91C_ID_SYS
);
361 /* close all peripheral clocks */
364 AT91C_BASE_PMC
->PMC_PCDR
= 0xFFFFFFFC;
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;
371 /* read the AIC_IVR and AIC_FVR */
375 /* write the end of interrupt control register */
376 *AT91C_AIC_EOICR
= 0;
382 static int AT91F_LoadBoot(void)
384 // volatile unsigned int crc1 = 0, crc2 = 0;
385 volatile unsigned int SizeToDownload
= 0x21400;
386 volatile unsigned int AddressToDownload
= AT91C_BOOT_ADDR
;
389 /* Read vector 6 to extract size to load */
390 if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR
, 32,
391 (char *)AddressToDownload
) != AT91C_DATAFLASH_OK
)
393 printf("Bad Code Size\n");
394 return IMAGE_BAD_SIZE
;
396 /* calculate the size to download */
397 SizeToDownload
= *(int *)(AddressToDownload
+ AT91C_OFFSET_VECT6
);
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
)
406 return IMAGE_READ_FAILURE
;
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);
416 /* Restore the value of Vector 6 */
417 *(int *)(AddressToDownload
+ AT91C_OFFSET_VECT6
) =
418 *(int *)(AddressToDownload
+ SizeToDownload
+ 4);
421 printf("DF CRC bad %x != %x\n",crc1
,crc2
);
422 return IMAGE_CRC_ERROR
;
428 static int AT91F_StartBoot(void)
431 if((sts
= AT91F_LoadBoot()) != SUCCESS
) return sts
;
433 // printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n");
434 if (AT91F_ResetRegisters())
437 Jump(AT91C_BOOT_ADDR
);
444 static void AT91F_RepeatedStartBoot(void)
447 for(i
= 0; i
< CRC_RETRIES
; i
++) {
448 if(AT91F_StartBoot() != IMAGE_CRC_ERROR
){
459 #define TRX_MAGIC 0x30524448 /* "HDR0" */
460 #define TRX_VERSION 1
466 unsigned int flag_version
;
467 unsigned int offsets
[3];
470 #define AT91C_MCI_TIMEOUT 1000000
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);
476 int Program_From_MCI(void)
479 unsigned int Max_Read_DataBlock_Length
;
481 int buffer
= AT91C_DOWNLOAD_BASE_ADDRESS
;
482 int bufpos
= AT91C_DOWNLOAD_BASE_ADDRESS
;
484 struct trx_header
*p
;
486 p
= (struct trx_header
*)bufpos
;
488 Max_Read_DataBlock_Length
= MCI_Device
.pMCI_DeviceFeatures
->Max_Read_DataBlock_Length
;
490 AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT
);
492 AT91F_MCI_ReadBlockSwab(&MCI_Device
, block
*Max_Read_DataBlock_Length
, (unsigned int *)bufpos
, Max_Read_DataBlock_Length
);
494 if (p
->magic
!= TRX_MAGIC
) {
495 printf("Inv IMG 0x%08x\n", p
->magic
);
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
);
504 bufpos
+= Max_Read_DataBlock_Length
;
508 i
= dataflash_info
[0].Device
.pages_number
;
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
;
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]);
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]);
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
;
531 //*----------------------------------------------------------------------------
532 //* Function Name : main
533 //* Object : Main function
534 //* Input Parameters : none
535 //* Output Parameters : True
536 //*----------------------------------------------------------------------------
540 AT91PS_Buffer pXmBuffer
;
541 AT91PS_SvcComm pSvcXmodem
;
543 AT91S_SvcTempo svcBootTempo
; // Link to a AT91S_Tempo object
545 volatile unsigned int AddressToDownload
, SizeToDownload
;
546 unsigned int DeviceAddress
= 0;
550 unsigned int crc1
= 0, crc2
= 0;
554 volatile int Nb_Device
= 0;
557 pAT91
= AT91C_ROM_BOOT_ADDRESS
;
567 /* Tempo Initialisation */
568 pAT91
->OpenCtlTempo(&ctlTempo
, (void *) &(pAT91
->SYSTIMER_DESC
));
569 ctlTempo
.CtlTempoStart((void *) &(pAT91
->SYSTIMER_DESC
));
571 // Attach the tempo to a tempo controler
572 ctlTempo
.CtlTempoCreate(&ctlTempo
, &svcBootTempo
);
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
);
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
592 /* Enable ST interrupt */
593 AT91F_AIC_EnableIt(AT91C_BASE_AIC
, AT91C_ID_SYS
);
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
);
606 AddressToDownload
= AT91C_DOWNLOAD_BASE_ADDRESS
;
607 SizeToDownload
= AT91C_DOWNLOAD_MAX_SIZE
;
610 /* try to detect Dataflash */
612 Nb_Device
= AT91F_DataflashInit();
614 mci_present
= AT91F_DisplayMenu();
618 if (Program_From_MCI())
624 AT91F_ReadLine ("Enter: ", message
);
627 /* stop tempo ==> stop autoboot */
628 svcBootTempo
.Stop(&svcBootTempo
);
631 command
= message
[0];
632 for(ix
= 1; (message
[ix
] == ' ') && (ix
< 12); ix
++); // Skip some whitespace
634 if(!AsciiToHex(&message
[ix
], &DeviceAddress
) )
635 DeviceAddress
= 0; // Illegal DeviceAddress
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);
650 // printf("Download Dataflash to [0x%x]\n", DeviceAddress);
652 switch(DeviceAddress
& 0xFF000000)
654 case CFG_DATAFLASH_LOGIC_ADDR_CS0
:
655 if (dataflash_info
[0].id
== 0){
657 AT91F_WaitKeyPressed();
664 case CFG_DATAFLASH_LOGIC_ADDR_CS3
:
665 if (dataflash_info
[1].id
== 0){
667 AT91F_WaitKeyPressed();
695 AT91F_MemoryDisplay(DeviceAddress
, 256);
696 AT91F_ReadLine (NULL
, message
);
697 DeviceAddress
+= 0x100;
699 while(message
[0] == '\0');
705 switch(DeviceAddress
& 0xFF000000)
707 case CFG_DATAFLASH_LOGIC_ADDR_CS0
:
709 case CFG_DATAFLASH_LOGIC_ADDR_CS3
:
717 AT91F_ReadLine ("RDY ERA\nSure?",
719 if(message
[0] == 'Y' || message
[0] == 'y') {
720 erase_dataflash(DeviceAddress
& 0xFF000000);
721 // printf("Erase complete\n\n");
724 // printf("Erase aborted\n");
736 for(i
= 0; i
<= AT91C_DOWNLOAD_MAX_SIZE
; i
++)
737 *(unsigned char *)(AddressToDownload
+ i
) = 0;
739 xmodemPipe
.Read(&xmodemPipe
, (char *)AddressToDownload
,
740 SizeToDownload
, XmodemProtocol
, 0);
741 while(XmodemComplete
!=1);
742 SizeToDownload
= (unsigned int)((svcXmodem
.pData
) -
743 (unsigned int)AddressToDownload
);
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)
749 i
= dataflash_info
[device
].Device
.pages_number
;
752 i
= (SizeToDownload
/ 512)+1 + (NbPage
<< 13) +
753 (dataflash_info
[device
].Device
.pages_size
<< 17); //+4 to add crc32
754 SizeToDownload
= 512 * (i
&0xFF);
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)*/
767 *(int *)(AddressToDownload
+ AT91C_OFFSET_VECT6
) = i
;
768 // printf("\nModification of Arm Vector 6 :%x\n", i);
770 // printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress);
772 pAT91
->CRC32((const unsigned char *)AddressToDownload
, SizeToDownload
, &crc1
);
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);
780 /* write dataflash */
781 write_dataflash (DeviceAddress
, AddressToDownload
, (SizeToDownload
+ 8));
783 /* clear the buffer before read */
784 for(i
=0; i
<= SizeToDownload
; i
++)
785 *(unsigned char *)(AddressToDownload
+ i
) = 0;
787 /* Read dataflash to check the validity of the data */
788 read_dataflash (DeviceAddress
, (SizeToDownload
+ 4), (char *)(AddressToDownload
));
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);
806 AT91F_WaitKeyPressed();