Wait 200ms before starting u-boot
[romboot.git] / main.cpp
blob01779fac8144f34c588db5d55793402ee8831b67
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 //*----------------------------------------------------------------------------
14 #include <AT91RM9200.h>
15 #include <lib_AT91RM9200.h>
17 #include "com.h"
18 #include "main.h"
19 #include "dataflash.h"
21 #define AT91C_UBOOT_ADDR 0x21F00000
22 #define AT91C_UBOOT_SIZE 512*1024
23 #define AT91C_UBOOT_DATAFLASH_ADDR 0xC0008400
25 // crystal= 18.432MHz
26 #define AT91C_PLLA_VALUE 0x20263E04 // -> 179.712MHz
27 #define AT91C_PLLA_MCK 0x0000202
29 // crystal= 20.000MHz
30 // #define AT91C_PLLA_VALUE 0x2023BE04 // -> 180MHz
31 // #define AT91C_PLLA_MCK 0x0000202
33 #define DELAY_MAIN_FREQ 1000
34 #define DISP_LINE_LEN 16
36 //* prototypes
37 extern void AT91F_DBGU_Printk(char *);
38 extern "C" void AT91F_ST_ASM_Handler(void);
39 extern "C" void Jump(unsigned int addr);
41 const char *menu_separ = "*----------------------------------------*\n\r";
43 const char *menu_dataflash = {
44 "1: Download Dataflash [addr]\n\r"
45 "2: Read Dataflash [addr]\n\r"
46 "3: Start U-BOOT\n\r"
47 "4: Clear bootloader section in Dataflash\n\r"
50 //* Globales variables
51 char message[40];
52 volatile char XmodemComplete = 0;
53 unsigned int StTick;
55 AT91S_RomBoot const *pAT91;
56 AT91S_SBuffer sXmBuffer;
57 AT91S_SvcXmodem svcXmodem;
58 AT91S_Pipe xmodemPipe;
59 AT91S_CtlTempo ctlTempo;
60 AT91S_SvcTempo svcTempo; // Link to a AT91S_Tempo object
62 void switch_led();
64 //*--------------------------------------------------------------------------------------
65 //* Function Name : GetTickCount()
66 //* Object : Return the number of systimer tick
67 //* Input Parameters :
68 //* Output Parameters :
69 //*--------------------------------------------------------------------------------------
70 unsigned int GetTickCount(void)
72 return StTick;
76 //*--------------------------------------------------------------------------------------
77 //* Function Name : AT91_XmodemComplete()
78 //* Object : Perform the remap and jump to appli in RAM
79 //* Input Parameters :
80 //* Output Parameters :
81 //*--------------------------------------------------------------------------------------
82 void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
84 // stop the Xmodem tempo
85 svcXmodem.tempo.Stop(&(svcXmodem.tempo));
86 XmodemComplete = 1;
90 //*--------------------------------------------------------------------------------------
91 //* Function Name : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
92 //* Object : Xmodem dispatcher
93 //* Input Parameters :
94 //* Output Parameters :
95 //*--------------------------------------------------------------------------------------
96 void XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
98 AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild;
99 AT91PS_USART pUsart = svcXmodem.pUsart;
101 if (pSBuffer->szRdBuffer == 0) {
102 // Start a tempo to wait the Xmodem protocol complete
103 svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);
108 //*-------------------------- Interrupt handlers ----------------------------------------
109 //*--------------------------------------------------------------------------------------
110 //* Function Name : irq1_c_handler()
111 //* Object : C Interrupt handler for Interrutp source 1
112 //* Input Parameters : none
113 //* Output Parameters : none
114 //*--------------------------------------------------------------------------------------
115 extern "C" void AT91F_ST_Handler(void);
117 void AT91F_ST_Handler(void)
119 volatile unsigned int csr = *AT91C_DBGU_CSR;
120 unsigned int error;
122 /* ========== Systimer interrupt ============== */
123 if (AT91C_BASE_ST->ST_SR & 0x01) {
124 StTick++;
125 switch_led();
126 ctlTempo.CtlTempoTick(&ctlTempo);
127 return;
130 error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU);
131 if (csr & error) {
132 // Stop previous Xmodem transmition
133 *(AT91C_DBGU_CR) = AT91C_US_RSTSTA;
134 AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX);
135 AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY);
139 else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY |
140 AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT |
141 AT91C_US_RXBUFF)) {
142 if ( !(svcXmodem.eot) )
143 svcXmodem.Handler(&svcXmodem, csr);
148 //*-----------------------------------------------------------------------------
149 //* Function Name : AT91F_DisplayMenu()
150 //* Object :
151 //* Input Parameters :
152 //* Return value :
153 //*-----------------------------------------------------------------------------
154 void AT91F_DisplayMenu(void)
156 printf("\n\rATMEL LOADER %s %s %s\n\r", AT91C_VERSION, __DATE__, __TIME__);
157 printf(menu_separ);
158 AT91F_DataflashPrintInfo();
159 printf(menu_separ);
160 printf(menu_dataflash);
161 printf(menu_separ);
164 //*-----------------------------------------------------------------------------
165 //* Function Name : AsciiToHex()
166 //* Object : ascii to hexa conversion
167 //* Input Parameters :
168 //* Return value :
169 //*-----------------------------------------------------------------------------
170 unsigned int AsciiToHex(char *s, unsigned int *val)
172 int n;
174 *val=0;
176 if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X')))
177 s+=2;
178 n = 0;
179 while((n < 8) && (s[n] !=0))
181 *val <<= 4;
182 if ( (s[n] >= '0') && (s[n] <='9'))
183 *val += (s[n] - '0');
184 else
185 if ((s[n] >= 'a') && (s[n] <='f'))
186 *val += (s[n] - 0x57);
187 else
188 if ((s[n] >= 'A') && (s[n] <='F'))
189 *val += (s[n] - 0x37);
190 else
191 return 0;
192 n++;
195 return 1;
199 //*-----------------------------------------------------------------------------
200 //* Function Name : AT91F_MemoryDisplay()
201 //* Object : Display the content of the dataflash
202 //* Input Parameters :
203 //* Return value :
204 //*-----------------------------------------------------------------------------
205 int AT91F_MemoryDisplay(unsigned int addr, unsigned int size, unsigned int length)
207 unsigned long i, nbytes, linebytes;
208 char *cp;
209 unsigned int *uip;
210 unsigned short *usp;
211 unsigned char *ucp;
212 char linebuf[DISP_LINE_LEN];
214 nbytes = length * size;
217 uip = (unsigned int *)linebuf;
218 usp = (unsigned short *)linebuf;
219 ucp = (unsigned char *)linebuf;
221 printf("%08x:", addr);
222 linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
224 read_dataflash(addr, (linebytes/size)*size, linebuf);
225 for (i=0; i<linebytes; i+= size)
227 if (size == 4)
228 printf(" %08x", *uip++);
229 else if (size == 2)
230 printf(" %04x", *usp++);
231 else
232 printf(" %02x", *ucp++);
233 addr += size;
235 printf(" ");
236 cp = linebuf;
237 for (i=0; i<linebytes; i++) {
238 if ((*cp < 0x20) || (*cp > 0x7e))
239 printf(".");
240 else
241 printf("%c", *cp);
242 cp++;
244 printf("\n\r");
245 nbytes -= linebytes;
246 } while (nbytes > 0);
247 return 0;
251 //*--------------------------------------------------------------------------------------
252 //* Function Name : AT91F_SetPLL
253 //* Object : Set the PLLA to 180Mhz and Master clock to 60 Mhz
254 //* Input Parameters :
255 //* Output Parameters :
256 //*--------------------------------------------------------------------------------------
257 void AT91F_SetPLL(void)
259 volatile int tmp = 0;
261 AT91PS_PMC pPmc = AT91C_BASE_PMC;
262 AT91PS_CKGR pCkgr = AT91C_BASE_CKGR;
264 pPmc->PMC_IDR = 0xFFFFFFFF;
266 //* -Setup the PLL A
267 pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
269 while(!(pPmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
271 //* - Commuting Master Clock from PLLB to PLLA/3
272 pPmc->PMC_MCKR = AT91C_PLLA_MCK;
276 //*--------------------------------------------------------------------------------------
277 //* Function Name : AT91F_ResetRegisters
278 //* Object : Restore the initial state to registers
279 //* Input Parameters :
280 //* Output Parameters :
281 //*--------------------------------------------------------------------------------------
282 static void AT91F_ResetRegisters(void)
284 volatile int i = 0;
286 //* set the PIOs in input
287 *AT91C_PIOA_ODR = 0xFFFFFFFF; /* Disables all the output pins */
288 *AT91C_PIOA_PER = 0xFFFFFFFF; /* Enables the PIO to control all the pins */
290 AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
292 /* close all peripheral clocks */
293 AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC;
295 //* Disable core interrupts and set supervisor mode
296 __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
298 //* Clear all the interrupts
299 *AT91C_AIC_ICCR = 0xffffffff;
301 /* read the AIC_IVR and AIC_FVR */
302 i = *AT91C_AIC_IVR;
303 i = *AT91C_AIC_FVR;
305 /* write the end of interrupt control register */
306 *AT91C_AIC_EOICR = 0;
308 AT91F_SetPLL();
311 void AT91F_StartUboot(unsigned int dummy, void *pvoid)
313 printf("Load U-BOOT from dataflash[%x] to SDRAM[%x]\n\r", AT91C_UBOOT_DATAFLASH_ADDR, AT91C_UBOOT_ADDR);
314 read_dataflash(AT91C_UBOOT_DATAFLASH_ADDR, AT91C_UBOOT_SIZE, (char *)(AT91C_UBOOT_ADDR));
315 printf("Set PLLA to 180Mhz and Master clock to 60Mhz and start U-BOOT\n\r");
316 //* Reset registers
317 AT91F_ResetRegisters();
318 Jump(AT91C_UBOOT_ADDR);
319 while(1);
322 void turn_led_off()
324 *AT91C_PIOD_ODR = AT91C_PIO_PD6; /* Disables all the output pins */
325 *AT91C_PIOD_PER = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
326 *AT91C_PIOD_OER = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
327 *AT91C_PIOD_SODR = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
330 void turn_led_on()
332 *AT91C_PIOD_ODR = AT91C_PIO_PD6; /* Disables all the output pins */
333 *AT91C_PIOD_PER = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
334 *AT91C_PIOD_OER = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
335 *AT91C_PIOD_CODR = AT91C_PIO_PD6; /* Enables the PIO to control all the pins */
338 #define ILIM0 0
339 #define ILIM1 100
340 #define ILIM2 200
341 int cnt=0;
342 void switch_led()
344 switch ( cnt)
346 case ILIM0 :
348 turn_led_on();
349 cnt++;
350 break;
353 case ILIM1:
355 turn_led_off();
356 cnt++;
357 break;
359 case ILIM2:
361 cnt = ILIM0;
362 break;
364 default:
366 cnt++;
367 break;
373 //*----------------------------------------------------------------------------
374 //* Function Name : main
375 //* Object : Main function
376 //* Input Parameters : none
377 //* Output Parameters : True
378 //*----------------------------------------------------------------------------
379 int main(void)
381 AT91PS_Buffer pXmBuffer;
382 AT91PS_SvcComm pSvcXmodem;
383 AT91S_SvcTempo svcUbootTempo; // Link to a AT91S_Tempo object
385 unsigned int AddressToDownload, SizeToDownload;
386 unsigned int DeviceAddress = 0;
387 volatile int i = 0;
388 char command = 0;
389 unsigned int crc1 = 0, crc2 = 0;
390 volatile int device;
391 int NbPage;
393 stdin = fopen(0, at91_dbgu_getc);
394 stdout = fopen(at91_dbgu_putc, 0);
396 pAT91 = AT91C_ROM_BOOT_ADDRESS;
398 // Tempo Initialisation
399 pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
400 ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));
402 // Attach the tempo to a tempo controler
403 ctlTempo.CtlTempoCreate(&ctlTempo, &svcUbootTempo);
405 // Xmodem Initialisation
406 pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
407 pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
408 pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
410 //* System Timer initialization
411 AT91F_AIC_ConfigureIt (
412 AT91C_BASE_AIC, // AIC base address
413 AT91C_ID_SYS, // System peripheral ID
414 AT91C_AIC_PRIOR_HIGHEST, // Max priority
415 AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive
416 AT91F_ST_ASM_Handler );
417 //* Enable ST interrupt
418 AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
420 // DataFlash on SPI Configuration
421 AT91F_DataflashInit ();
423 // start tempo to start Uboot in a delay of 1 sec if no key pressed
424 svcUbootTempo.Start(&svcUbootTempo, 200, 0, AT91F_StartUboot, (void *)0);
426 printf("press any key to enter bootloader\n\r");
427 getc();
429 // stop tempo
430 svcUbootTempo.Stop(&svcUbootTempo);
432 while(1)
434 while(command == 0)
436 AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS;
437 SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE;
438 DeviceAddress = 0;
440 AT91F_DisplayMenu();
441 message[0] = 0;
442 message[2] = 0;
443 AT91F_ReadLine("Enter: ", message);
445 command = message[0];
446 if(command == '1' || command == '2')
447 if(AsciiToHex(&message[2], &DeviceAddress) == 0)
448 command = 0;
450 switch(command)
452 case '1':
453 printf("Download Dataflash [0x%x]\n\r", DeviceAddress);
455 switch(DeviceAddress & 0xFF000000)
457 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
458 device = 0;
459 break;
461 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
462 device = 1;
463 break;
465 default:
466 command = 0;
467 break;
469 break;
471 case '2':
474 AT91F_MemoryDisplay(DeviceAddress, 4, 64);
475 AT91F_ReadLine ((char *)0, message);
476 DeviceAddress += 0x100;
478 while(message[0] == '\0');
479 command = 0;
480 break;
482 case '3':
483 AT91F_StartUboot(0, (void *)0);
484 command = 0;
485 break;
486 case '4':
488 int *i;
489 for(i = (int *)0x20000000; i < (int *)0x20004000; i++)
490 *i = 0;
492 write_dataflash(0xc0000000, 0x20000000, 0x4000);
493 printf("Bootsection cleared\r\n");
494 command = 0;
495 break;
496 default:
497 command = 0;
498 break;
502 xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload, SizeToDownload, XmodemProtocol, 0);
503 while(XmodemComplete !=1);
504 SizeToDownload = (unsigned int)(svcXmodem.pData) - (unsigned int)AddressToDownload;
506 // Modification of vector 6
507 NbPage = 0;
508 i = dataflash_info[device].Device.pages_number;
509 while(i >>= 1)
510 NbPage++;
511 i = (SizeToDownload / 512) + 1 + (NbPage << 13) + (dataflash_info[device].Device.pages_size << 17);
512 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i;
514 printf("\n\rModification of Arm Vector 6 :%x\n\r", i);
516 printf("\n\rWrite %d bytes in DataFlash [0x%x]\n\r",SizeToDownload, DeviceAddress);
517 crc1 = 0;
518 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1);
520 // write the dataflash
521 write_dataflash (DeviceAddress, AddressToDownload, SizeToDownload);
522 // clear the buffer before read
523 for(i=0; i < SizeToDownload; i++)
524 *(unsigned char *)(AddressToDownload + i) = 0;
526 //* Read dataflash page in TestBuffer
527 read_dataflash (DeviceAddress, SizeToDownload, (char *)(AddressToDownload));
529 printf("Verify Dataflash: ");
530 crc2 = 0;
532 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2);
533 if (crc1 != crc2)
534 printf("Failed\r\n");
535 else
536 printf("OK\r\n");
538 command = 0;
539 XmodemComplete = 0;
540 AT91F_WaitKeyPressed();