/*---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support - ROUSSET - *---------------------------------------------------------------------------- * The software is delivered "AS IS" without warranty or condition of any * kind, either express, implied or statutory. This includes without * limitation any warranty or condition with respect to merchantability or * fitness for any particular purpose, or against the infringements of * intellectual property rights of others. *---------------------------------------------------------------------------- * File Name : main.c * Object : * Creation : HIi 10/10/2003 * Modif : HIi 15/06/2004 : add crc32 to verify the download * from dataflash * : HIi 21/09/2004 : Set first PLLA to 180Mhz and MCK to * 60Mhz to speed up dataflash boot (15Mhz) * : MLC 12/04/2005 : Modify SetPLL() to avoid errata * : USA 30/12/2005 : Change to page Size 1056 * Change startaddress to C0008400 * Change SPI Speed to ~4 Mhz * Add retry on CRC Error *---------------------------------------------------------------------------- */ #include "config.h" #include "stdio.h" #include "AT91RM9200.h" #include "lib_AT91RM9200.h" #include "com.h" #include "main.h" #include "dataflash.h" #include "AT91C_MCI_Device.h" #define DEBUGOUT #define XMODEM #define MEMDISP #ifdef PAGESZ_1056 #define PAGESIZE 1056 #else #define PAGESIZE 1024 #endif #define AT91C_SDRAM_START 0x20000000 #define AT91C_BOOT_ADDR 0x21F00000 #define AT91C_BOOT_SIZE 128*PAGESIZE #ifdef PAGESZ_1056 #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400 #else #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000 #endif #define AT91C_PLLA_VALUE 0x237A3E5A // crystal= 18.432MHz - fixes BRG error at 115kbps //#define AT91C_PLLA_VALUE 0x2026BE04 // crystal= 18.432MHz //#define AT91C_PLLA_VALUE 0x202CBE01 // crystal= 4MHz #define DISP_LINE_LEN 16 // Reason for boot failure #define IMAGE_BAD_SIZE 0 #define IMAGE_READ_FAILURE 1 #define IMAGE_CRC_ERROR 2 #define IMAGE_ERROR 3 #define SUCCESS -1 /* prototypes*/ extern void AT91F_ST_ASM_HANDLER(void); extern void Jump(unsigned int addr); const char *menu_dataflash[] = { #ifdef XMODEM "1: P DFboot\n", "2: P U-Boot\n", #endif "3: P SDCard\n", #ifdef PAGESZ_1056 "4: R UBOOT\n", #else "4: R UBOOT\n", #endif #ifdef XMODEM "5: P DF [addr]\n", #endif "6: RD DF [addr]\n", "7: E DF\n" }; #ifdef XMODEM #define MAXMENU 7 #else #define MAXMENU 4 #endif char message[20]; #ifdef XMODEM volatile char XmodemComplete = 0; #endif unsigned int StTick = 0; AT91S_RomBoot const *pAT91; #ifdef XMODEM AT91S_SBuffer sXmBuffer; AT91S_SvcXmodem svcXmodem; AT91S_Pipe xmodemPipe; #endif AT91S_CtlTempo ctlTempo; //*-------------------------------------------------------------------------------------- //* Function Name : GetTickCount() //* Object : Return the number of systimer tick //* Input Parameters : //* Output Parameters : //*-------------------------------------------------------------------------------------- unsigned int GetTickCount(void) { return StTick; } #ifdef XMODEM //*-------------------------------------------------------------------------------------- //* Function Name : AT91_XmodemComplete() //* Object : Perform the remap and jump to appli in RAM //* Input Parameters : //* Output Parameters : //*-------------------------------------------------------------------------------------- static void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid) { /* stop the Xmodem tempo */ svcXmodem.tempo.Stop(&(svcXmodem.tempo)); XmodemComplete = 1; } //*-------------------------------------------------------------------------------------- //* Function Name : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid) //* Object : Xmodem dispatcher //* Input Parameters : //* Output Parameters : //*-------------------------------------------------------------------------------------- static void XmodemProtocol(AT91S_PipeStatus status, void *pVoid) { AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild; AT91PS_USART pUsart = svcXmodem.pUsart; if (pSBuffer->szRdBuffer == 0) { /* Start a tempo to wait the Xmodem protocol complete */ svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart); } } #endif //*-------------------------------------------------------------------------------------- //* Function Name : irq1_c_handler() //* Object : C Interrupt handler for Interrutp source 1 //* Input Parameters : none //* Output Parameters : none //*-------------------------------------------------------------------------------------- void AT91F_ST_HANDLER(void) { volatile unsigned int csr = *AT91C_DBGU_CSR; #ifdef XMODEM unsigned int error; #endif if (AT91C_BASE_ST->ST_SR & 0x01) { StTick++; ctlTempo.CtlTempoTick(&ctlTempo); return; } #ifdef XMODEM error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU); if (csr & error) { /* Stop previous Xmodem transmition*/ *(AT91C_DBGU_CR) = AT91C_US_RSTSTA; AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX); AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY); } else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY | AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT | AT91C_US_RXBUFF)) { if ( !(svcXmodem.eot) ) svcXmodem.Handler(&svcXmodem, csr); } #endif } //*----------------------------------------------------------------------------- //* Function Name : AT91F_DisplayMenu() //* Object : //* Input Parameters : //* Return value : //*----------------------------------------------------------------------------- static int AT91F_DisplayMenu(void) { int i, mci_present = 0; printf("\nDF LOADER %s %s %s\n",AT91C_VERSION,__DATE__,__TIME__); AT91F_DataflashPrintInfo(); mci_present = AT91F_MCI_Init(); for(i = 0; i < MAXMENU; i++) { puts(menu_dataflash[i]); } return mci_present; } //*----------------------------------------------------------------------------- //* Function Name : AsciiToHex() //* Object : ascii to hexa conversion //* Input Parameters : //* Return value : //*----------------------------------------------------------------------------- static unsigned int AsciiToHex(char *s, unsigned int *val) { int n; *val=0; if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X'))) s+=2; n = 0; while((n < 8) && (s[n] !=0)) { *val <<= 4; if ( (s[n] >= '0') && (s[n] <='9')) *val += (s[n] - '0'); else if ((s[n] >= 'a') && (s[n] <='f')) *val += (s[n] - 0x57); else if ((s[n] >= 'A') && (s[n] <='F')) *val += (s[n] - 0x37); else return 0; n++; } return 1; } #ifdef MEMDISP //*----------------------------------------------------------------------------- //* Function Name : AT91F_MemoryDisplay() //* Object : Display the content of the dataflash //* Input Parameters : //* Return value : //*----------------------------------------------------------------------------- static int AT91F_MemoryDisplay(unsigned int addr, unsigned int length) { unsigned long i, nbytes, linebytes; char *cp; // unsigned int *uip; // unsigned short *usp; unsigned char *ucp; char linebuf[DISP_LINE_LEN]; // nbytes = length * size; nbytes = length; do { // uip = (unsigned int *)linebuf; // usp = (unsigned short *)linebuf; ucp = (unsigned char *)linebuf; printf("%08x:", addr); linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; if((addr & 0xF0000000) == 0x20000000) { for(i = 0; i < linebytes; i ++) { linebuf[i] = *(char *)(addr+i); } } else { read_dataflash(addr, linebytes, linebuf); } for (i=0; i 0x7e)) printf("."); else printf("%c", *cp); cp++; } printf("\n"); nbytes -= linebytes; } while (nbytes > 0); return 0; } #endif //*-------------------------------------------------------------------------------------- //* Function Name : AT91F_SetPLL //* Object : Set the PLLA to 180Mhz and Master clock to 60 Mhz //* Input Parameters : //* Output Parameters : //*-------------------------------------------------------------------------------------- static unsigned int AT91F_SetPLL(void) { AT91_REG tmp; AT91PS_PMC pPmc = AT91C_BASE_PMC; AT91PS_CKGR pCkgr = AT91C_BASE_CKGR; pPmc->PMC_IDR = 0xFFFFFFFF; /* -Setup the PLL A */ pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE; while (!(*AT91C_PMC_SR & AT91C_PMC_LOCKA)); /* - Switch Master Clock from PLLB to PLLA/3 */ tmp = pPmc->PMC_MCKR; /* See Atmel Errata #27 and #28 */ if (tmp & 0x0000001C) { tmp = (tmp & ~0x0000001C); pPmc->PMC_MCKR = tmp; while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)); } if (tmp != 0x00000202) { pPmc->PMC_MCKR = 0x00000202; if ((tmp & 0x00000003) != 0x00000002) while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)); } return 1; } //*-------------------------------------------------------------------------------------- //* Function Name : AT91F_ResetRegisters //* Object : Restore the initial state to registers //* Input Parameters : //* Output Parameters : //*-------------------------------------------------------------------------------------- static unsigned int AT91F_ResetRegisters(void) { volatile int i = 0; /* set the PIOs in input*/ /* This disables the UART output, so dont execute for now*/ #ifndef DEBUGOUT *AT91C_PIOA_ODR = 0xFFFFFFFF; /* Disables all the output pins */ *AT91C_PIOA_PER = 0xFFFFFFFF; /* Enables the PIO to control all the pins */ #endif AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS); /* close all peripheral clocks */ #ifndef DEBUGOUT AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC; #endif /* Disable core interrupts and set supervisor mode */ __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40) /* Clear all the interrupts */ *AT91C_AIC_ICCR = 0xffffffff; /* read the AIC_IVR and AIC_FVR */ i = *AT91C_AIC_IVR; i = *AT91C_AIC_FVR; /* write the end of interrupt control register */ *AT91C_AIC_EOICR = 0; return 1; } static int AT91F_LoadBoot(void) { // volatile unsigned int crc1 = 0, crc2 = 0; volatile unsigned int SizeToDownload = 0x21400; volatile unsigned int AddressToDownload = AT91C_BOOT_ADDR; #if 0 /* Read vector 6 to extract size to load */ if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, 32, (char *)AddressToDownload) != AT91C_DATAFLASH_OK) { printf("Bad Code Size\n"); return IMAGE_BAD_SIZE; } /* calculate the size to download */ SizeToDownload = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6); #endif // printf("\nLoad UBOOT from dataflash[%x] to SDRAM[%x]\n", // AT91C_BOOT_DATAFLASH_ADDR, AT91C_BOOT_ADDR); if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, SizeToDownload + 8, (char *)AddressToDownload) != AT91C_DATAFLASH_OK) { printf("F DF RD\n"); return IMAGE_READ_FAILURE; } #if 0 pAT91->CRC32((const unsigned char *)AT91C_BOOT_ADDR, (unsigned int)SizeToDownload , (unsigned int *)&crc2); crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) + (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) + (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) + (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24); /* Restore the value of Vector 6 */ *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = *(int *)(AddressToDownload + SizeToDownload + 4); if (crc1 != crc2) { printf("DF CRC bad %x != %x\n",crc1,crc2); return IMAGE_CRC_ERROR; } #endif return SUCCESS; } static int AT91F_StartBoot(void) { int sts; if((sts = AT91F_LoadBoot()) != SUCCESS) return sts; // printf("\n"); // printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n"); if (AT91F_ResetRegisters()) { printf("Jump"); Jump(AT91C_BOOT_ADDR); // LED_blink(0); } return IMAGE_ERROR; } #if 0 static void AT91F_RepeatedStartBoot(void) { int i; for(i = 0; i < CRC_RETRIES; i++) { if(AT91F_StartBoot() != IMAGE_CRC_ERROR){ // LED_blink(1); return; } } return; } #endif #define TRUE 1 #define FALSE 0 #define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_VERSION 1 struct trx_header { unsigned int magic; unsigned int len; unsigned int crc32; unsigned int flag_version; unsigned int offsets[3]; }; #define AT91C_MCI_TIMEOUT 1000000 extern AT91S_MciDevice MCI_Device; extern void AT91F_MCIDeviceWaitReady(unsigned int); extern int AT91F_MCI_ReadBlockSwab(AT91PS_MciDevice, int, unsigned int *, int); int Program_From_MCI(void) { int i; unsigned int Max_Read_DataBlock_Length; int block = 0; int buffer = AT91C_DOWNLOAD_BASE_ADDRESS; int bufpos = AT91C_DOWNLOAD_BASE_ADDRESS; int NbPage = 0; struct trx_header *p; p = (struct trx_header *)bufpos; Max_Read_DataBlock_Length = MCI_Device.pMCI_DeviceFeatures->Max_Read_DataBlock_Length; AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length); if (p->magic != TRX_MAGIC) { printf("Inv IMG 0x%08x\n", p->magic); return FALSE; } printf("RDSD"); AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC8 | AT91C_PIO_PC14; for (i=0; i<(p->len/512); i++) { AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length); block++; bufpos += Max_Read_DataBlock_Length; } NbPage = 0; i = dataflash_info[0].Device.pages_number; while(i >>= 1) NbPage++; i = ((p->offsets[1] - p->offsets[0])/ 512) + 1 + (NbPage << 13) + (dataflash_info[0].Device.pages_size << 17); *(int *)(buffer + p->offsets[0] + AT91C_OFFSET_VECT6) = i; printf(" WDFB"); AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC14; AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8; write_dataflash(0xc0000000, buffer + p->offsets[0], p->offsets[1] - p->offsets[0]); printf(" WUB"); AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15; AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8 | AT91C_PIO_PC14; write_dataflash(0xc0008000, buffer + p->offsets[1], p->offsets[2] - p->offsets[1]); printf(" WKRFS"); AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC15; AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC14; write_dataflash(0xc0042000, buffer + p->offsets[2], p->len - p->offsets[2]); AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC14; AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC15; return TRUE; } //*---------------------------------------------------------------------------- //* Function Name : main //* Object : Main function //* Input Parameters : none //* Output Parameters : True //*---------------------------------------------------------------------------- int main(void) { #ifdef XMODEM AT91PS_Buffer pXmBuffer; AT91PS_SvcComm pSvcXmodem; #endif AT91S_SvcTempo svcBootTempo; // Link to a AT91S_Tempo object unsigned int ix; volatile unsigned int AddressToDownload, SizeToDownload; unsigned int DeviceAddress = 0; char command = 0; #ifdef XMODEM volatile int i = 0; unsigned int crc1 = 0, crc2 = 0; volatile int device; int NbPage; #endif volatile int Nb_Device = 0; int mci_present = 0; pAT91 = AT91C_ROM_BOOT_ADDRESS; if (!AT91F_SetPLL()) { printf("F SetPLL"); while(1); } at91_init_uarts(); /* Tempo Initialisation */ pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC)); ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC)); // Attach the tempo to a tempo controler ctlTempo.CtlTempoCreate(&ctlTempo, &svcBootTempo); // LED_init(); // LED_blink(2); #ifdef XMODEM /* Xmodem Initialisation */ pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer); pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo); pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer); #endif /* System Timer initialization */ AT91F_AIC_ConfigureIt( AT91C_BASE_AIC, // AIC base address AT91C_ID_SYS, // System peripheral ID AT91C_AIC_PRIOR_HIGHEST, // Max priority AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive AT91F_ST_ASM_HANDLER ); /* Enable ST interrupt */ AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); #ifndef PRODTEST /* Start tempo to start Boot in a delay of * AT91C_DELAY_TO_BOOT sec if no key pressed */ svcBootTempo.Start(&svcBootTempo, AT91C_DELAY_TO_BOOT, 0, AT91F_StartBoot, NULL); #endif while(1) { while(command == 0) { AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS; SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE; DeviceAddress = 0; /* try to detect Dataflash */ if (!Nb_Device) Nb_Device = AT91F_DataflashInit(); mci_present = AT91F_DisplayMenu(); #ifdef PRODTEST if (mci_present) { if (Program_From_MCI()) AT91F_StartBoot(); } #endif message[0] = 0; AT91F_ReadLine ("Enter: ", message); #ifndef PRODTEST /* stop tempo ==> stop autoboot */ svcBootTempo.Stop(&svcBootTempo); #endif command = message[0]; for(ix = 1; (message[ix] == ' ') && (ix < 12); ix++); // Skip some whitespace if(!AsciiToHex(&message[ix], &DeviceAddress) ) DeviceAddress = 0; // Illegal DeviceAddress switch(command) { #ifdef XMODEM case '1': case '2': case '5': if(command == '1') { DeviceAddress = 0xC0000000; // printf("Download DataflashBoot.bin to [0x%x]\n", DeviceAddress); } else if(command == '2') { DeviceAddress = AT91C_BOOT_DATAFLASH_ADDR; // printf("Download u-boot.bin to [0x%x]\n", DeviceAddress); } else { // printf("Download Dataflash to [0x%x]\n", DeviceAddress); } switch(DeviceAddress & 0xFF000000) { case CFG_DATAFLASH_LOGIC_ADDR_CS0: if (dataflash_info[0].id == 0){ printf("No DF"); AT91F_WaitKeyPressed(); command = 0; } device = 0; break; case CFG_DATAFLASH_LOGIC_ADDR_CS3: if (dataflash_info[1].id == 0){ printf("No DF"); AT91F_WaitKeyPressed(); command = 0; } device = 1; break; default: command = 0; break; } break; #endif case '3': if (mci_present) Program_From_MCI(); command = 0; break; case '4': AT91F_StartBoot(); command = 0; break; #ifdef MEMDISP case '6': do { AT91F_MemoryDisplay(DeviceAddress, 256); AT91F_ReadLine (NULL, message); DeviceAddress += 0x100; } while(message[0] == '\0'); command = 0; break; #endif case '7': switch(DeviceAddress & 0xFF000000) { case CFG_DATAFLASH_LOGIC_ADDR_CS0: break; case CFG_DATAFLASH_LOGIC_ADDR_CS3: break; default: command = 0; break; } if (command != 0) { AT91F_ReadLine ("RDY ERA\nSure?", message); if(message[0] == 'Y' || message[0] == 'y') { erase_dataflash(DeviceAddress & 0xFF000000); // printf("Erase complete\n\n"); } // else // printf("Erase aborted\n"); } command = 0; break; default: command = 0; break; } } #ifdef XMODEM for(i = 0; i <= AT91C_DOWNLOAD_MAX_SIZE; i++) *(unsigned char *)(AddressToDownload + i) = 0; xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload, SizeToDownload, XmodemProtocol, 0); while(XmodemComplete !=1); SizeToDownload = (unsigned int)((svcXmodem.pData) - (unsigned int)AddressToDownload); /* Modification of vector 6 */ if ((DeviceAddress == CFG_DATAFLASH_LOGIC_ADDR_CS0)) { // Vector 6 must be compliant to the BootRom description (ref Datasheet) NbPage = 0; i = dataflash_info[device].Device.pages_number; while(i >>= 1) NbPage++; i = (SizeToDownload / 512)+1 + (NbPage << 13) + (dataflash_info[device].Device.pages_size << 17); //+4 to add crc32 SizeToDownload = 512 * (i &0xFF); } else { /* Save the contents of vector 6 ==> will be restored * at boot time (AT91F_StartBoot) */ *(int *)(AddressToDownload + SizeToDownload + 4) = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6); /* Modify Vector 6 to contain the size of the * file to copy (Dataflash -> SDRAM)*/ i = SizeToDownload; } *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i; // printf("\nModification of Arm Vector 6 :%x\n", i); // printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress); crc1 = 0; pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1); /* Add the crc32 at the end of the code */ *(char *)(AddressToDownload + SizeToDownload) = (char)(crc1 & 0x000000FF); *(char *)(AddressToDownload + SizeToDownload + 1) = (char)((crc1 & 0x0000FF00) >> 8); *(char *)(AddressToDownload + SizeToDownload + 2) = (char)((crc1 & 0x00FF0000) >> 16); *(char *)(AddressToDownload + SizeToDownload + 3) = (char)((crc1 & 0xFF000000) >> 24); /* write dataflash */ write_dataflash (DeviceAddress, AddressToDownload, (SizeToDownload + 8)); /* clear the buffer before read */ for(i=0; i <= SizeToDownload; i++) *(unsigned char *)(AddressToDownload + i) = 0; /* Read dataflash to check the validity of the data */ read_dataflash (DeviceAddress, (SizeToDownload + 4), (char *)(AddressToDownload)); printf("VFY: "); crc2 = 0; pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2); crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) + (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) + (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) + (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24); if (crc1 != crc2) printf("ERR"); else printf("OK"); command = 0; XmodemComplete = 0; AT91F_WaitKeyPressed(); #endif } }