| /*---------------------------------------------------------------------------- |
| * 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<linebytes; i++) |
| { |
| /* if (size == 4) |
| printf(" %08x", *uip++); |
| else if (size == 2) |
| printf(" %04x", *usp++); |
| else |
| */ |
| printf(" %02x", *ucp++); |
| // addr += size; |
| addr++; |
| } |
| printf(" "); |
| cp = linebuf; |
| for (i=0; i<linebytes; i++) { |
| if ((*cp < 0x20) || (*cp > 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 |
| } |
| } |
| |