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();