Gain de code
[romboot.git] / main.cpp
blob2b090d15a92670c0f77f99aef24ce5dd9254de54
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 0xC1000000
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 flash [addr]\n\r"
45 "2: Read flash [addr]\n\r"
46 "3: start Uboot\n\r"
47 "4: Clear bootloader in flash\n\r"
48 "5: Erase chip [nb]\n\r"
49 "6: sw flash lock on (flash_nb)\n\r"
50 "7: sw flash lock off (fl_nb)\r\n"
51 "8: lock status register (all)\r\n"
52 "9: lockdown status register (all)\r\n"
53 "a: security register (all)\r\n"
54 "b: clr lock register (fl_nb) all to 0 \r\n"
55 "c: set lock register (fl_nb) all to ff \r\n"
56 "d: Display flash info\r\n"
57 "f: reset hw flash lock\r\n"
58 "g: set hw flash lock\r\n"
61 //* Globales variables
62 char message[40];
63 volatile char XmodemComplete = 0;
64 unsigned int StTick;
66 AT91S_RomBoot const *pAT91;
67 AT91S_SBuffer sXmBuffer;
68 AT91S_SvcXmodem svcXmodem;
69 AT91S_Pipe xmodemPipe;
70 AT91S_CtlTempo ctlTempo;
71 AT91S_SvcTempo svcTempo; // Link to a AT91S_Tempo object
73 void switch_led();
75 //*--------------------------------------------------------------------------------------
76 //* Function Name : GetTickCount()
77 //* Object : Return the number of systimer tick
78 //* Input Parameters :
79 //* Output Parameters :
80 //*--------------------------------------------------------------------------------------
81 unsigned int GetTickCount(void)
83 return StTick;
87 //*--------------------------------------------------------------------------------------
88 //* Function Name : AT91_XmodemComplete()
89 //* Object : Perform the remap and jump to appli in RAM
90 //* Input Parameters :
91 //* Output Parameters :
92 //*--------------------------------------------------------------------------------------
93 void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid)
95 // stop the Xmodem tempo
96 svcXmodem.tempo.Stop(&(svcXmodem.tempo));
97 XmodemComplete = 1;
101 //*--------------------------------------------------------------------------------------
102 //* Function Name : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
103 //* Object : Xmodem dispatcher
104 //* Input Parameters :
105 //* Output Parameters :
106 //*--------------------------------------------------------------------------------------
107 void XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
109 AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild;
110 AT91PS_USART pUsart = svcXmodem.pUsart;
112 if (pSBuffer->szRdBuffer == 0) {
113 // Start a tempo to wait the Xmodem protocol complete
114 svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart);
119 //*-------------------------- Interrupt handlers ----------------------------------------
120 //*--------------------------------------------------------------------------------------
121 //* Function Name : irq1_c_handler()
122 //* Object : C Interrupt handler for Interrutp source 1
123 //* Input Parameters : none
124 //* Output Parameters : none
125 //*--------------------------------------------------------------------------------------
126 extern "C" void AT91F_ST_Handler(void);
128 void AT91F_ST_Handler(void)
130 volatile unsigned int csr = *AT91C_DBGU_CSR;
131 unsigned int error;
133 /* ========== Systimer interrupt ============== */
134 if (AT91C_BASE_ST->ST_SR & 0x01) {
135 StTick++;
136 // switch_led();
137 ctlTempo.CtlTempoTick(&ctlTempo);
138 return;
141 error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU);
142 if (csr & error) {
143 // Stop previous Xmodem transmition
144 *(AT91C_DBGU_CR) = AT91C_US_RSTSTA;
145 AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX);
146 AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY);
150 else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY |
151 AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT |
152 AT91C_US_RXBUFF)) {
153 if ( !(svcXmodem.eot) )
154 svcXmodem.Handler(&svcXmodem, csr);
159 //*-----------------------------------------------------------------------------
160 //* Function Name : AT91F_DisplayMenu()
161 //* Object :
162 //* Input Parameters :
163 //* Return value :
164 //*-----------------------------------------------------------------------------
165 void AT91F_DisplayMenu(void)
167 printf("\n\rATMEL LOADER %s %s %s\n\r", AT91C_VERSION, __DATE__, __TIME__);
168 printf(menu_separ);
169 printf(menu_separ);
170 printf(menu_dataflash);
171 printf(menu_separ);
174 //*-----------------------------------------------------------------------------
175 //* Function Name : AsciiToHex()
176 //* Object : ascii to hexa conversion
177 //* Input Parameters :
178 //* Return value :
179 //*-----------------------------------------------------------------------------
180 unsigned int AsciiToHex(char *s, unsigned int *val)
182 int n;
184 *val=0;
186 if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X')))
187 s+=2;
188 n = 0;
189 while((n < 8) && (s[n] !=0))
191 *val <<= 4;
192 if ( (s[n] >= '0') && (s[n] <='9'))
193 *val += (s[n] - '0');
194 else
195 if ((s[n] >= 'a') && (s[n] <='f'))
196 *val += (s[n] - 0x57);
197 else
198 if ((s[n] >= 'A') && (s[n] <='F'))
199 *val += (s[n] - 0x37);
200 else
201 return 0;
202 n++;
205 return 1;
209 //*-----------------------------------------------------------------------------
210 //* Function Name : AT91F_MemoryDisplay()
211 //* Object : Display the content of the dataflash
212 //* Input Parameters :
213 //* Return value :
214 //*-----------------------------------------------------------------------------
215 int AT91F_MemoryDisplay(unsigned int addr, unsigned int size, unsigned int length)
217 unsigned long i, nbytes, linebytes;
218 char *cp;
219 unsigned int *uip;
220 unsigned short *usp;
221 unsigned char *ucp;
222 char linebuf[DISP_LINE_LEN];
224 nbytes = length * size;
227 uip = (unsigned int *)linebuf;
228 usp = (unsigned short *)linebuf;
229 ucp = (unsigned char *)linebuf;
231 printf("%08x:", addr);
232 linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
234 read_dataflash(addr, (linebytes/size)*size, linebuf);
235 for (i=0; i<linebytes; i+= size)
237 if (size == 4)
238 printf(" %08x", *uip++);
239 else if (size == 2)
240 printf(" %04x", *usp++);
241 else
242 printf(" %02x", *ucp++);
243 addr += size;
245 printf(" ");
246 cp = linebuf;
247 for (i=0; i<linebytes; i++) {
248 if ((*cp < 0x20) || (*cp > 0x7e))
249 printf(".");
250 else
251 printf("%c", *cp);
252 cp++;
254 printf("\n\r");
255 nbytes -= linebytes;
256 } while (nbytes > 0);
257 return 0;
260 #if 0
261 //*-----------------------------------------------------------------------------
262 //* Function Name : AT91F_DramDisplay()
263 //* Object : Display the content of the sdram
264 //* Input Parameters :
265 //* Return value :
266 //*-----------------------------------------------------------------------------
267 int AT91F_SdramDisplay(unsigned int addr, unsigned int size, unsigned int length)
269 unsigned long i, nbytes, linebytes;
270 char *cp;
271 unsigned int *uip;
272 unsigned short *usp;
273 unsigned char *ucp;
275 nbytes = length * size;
278 uip = (unsigned int *)addr;
279 usp = (unsigned short *)addr;
280 ucp = (unsigned char *)addr;
282 printf("%08x:", addr);
283 linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes;
285 for (i=0; i<linebytes; i+= size)
287 if (size == 4)
288 printf(" %08x", *uip++);
289 else if (size == 2)
290 printf(" %04x", *usp++);
291 else
292 printf(" %02x", *ucp++);
293 addr += size;
295 printf(" ");
296 for (i=0; i<linebytes; i++) {
297 if ((*cp < 0x20) || (*cp > 0x7e))
298 printf(".");
299 else
300 printf("%c", *cp);
301 cp++;
303 printf("\n\r");
304 nbytes -= linebytes;
305 } while (nbytes > 0);
306 return 0;
308 #endif
311 //*--------------------------------------------------------------------------------------
312 //* Function Name : AT91F_SetPLL
313 //* Object : Set the PLLA to 180Mhz and Master clock to 60 Mhz
314 //* Input Parameters :
315 //* Output Parameters :
316 //*--------------------------------------------------------------------------------------
317 void AT91F_SetPLL(void)
319 volatile int tmp = 0;
321 AT91PS_PMC pPmc = AT91C_BASE_PMC;
322 AT91PS_CKGR pCkgr = AT91C_BASE_CKGR;
324 pPmc->PMC_IDR = 0xFFFFFFFF;
326 //* -Setup the PLL A
327 pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE;
329 while(!(pPmc->PMC_SR & AT91C_PMC_MCKRDY) && (tmp++ < DELAY_MAIN_FREQ));
331 //* - Commuting Master Clock from PLLB to PLLA/3
332 pPmc->PMC_MCKR = AT91C_PLLA_MCK;
336 //*--------------------------------------------------------------------------------------
337 //* Function Name : AT91F_ResetRegisters
338 //* Object : Restore the initial state to registers
339 //* Input Parameters :
340 //* Output Parameters :
341 //*--------------------------------------------------------------------------------------
342 static void AT91F_ResetRegisters(void)
344 volatile int i = 0;
346 //* set the PIOs in input
347 *AT91C_PIOA_ODR = 0xFFFFFFFF; /* Disables all the output pins */
348 *AT91C_PIOA_PER = 0xFFFFFFFF; /* Enables the PIO to control all the pins */
350 AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS);
352 /* close all peripheral clocks */
353 AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC;
355 //* Disable core interrupts and set supervisor mode
356 __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
358 //* Clear all the interrupts
359 *AT91C_AIC_ICCR = 0xffffffff;
361 /* read the AIC_IVR and AIC_FVR */
362 i = *AT91C_AIC_IVR;
363 i = *AT91C_AIC_FVR;
365 /* write the end of interrupt control register */
366 *AT91C_AIC_EOICR = 0;
368 AT91F_SetPLL();
371 void AT91F_StartUboot(unsigned int dummy, void *pvoid)
373 printf("Load U-BOOT from dataflash[%x] to SDRAM[%x]\n\r", AT91C_UBOOT_DATAFLASH_ADDR, AT91C_UBOOT_ADDR);
374 if (pvoid == 0) {
375 read_dataflash(AT91C_UBOOT_DATAFLASH_ADDR, AT91C_UBOOT_SIZE, (char *)(AT91C_UBOOT_ADDR));
377 else {
378 read_dataflash((unsigned long)pvoid, AT91C_UBOOT_SIZE, (char *)(AT91C_UBOOT_ADDR));
380 printf("Set PLLA to 180Mhz and Master clock to 60Mhz and start U-BOOT\n\r");
381 //* Reset registers
382 AT91F_ResetRegisters();
383 Jump(AT91C_UBOOT_ADDR);
384 while(1);
387 void turn_led_off()
389 *AT91C_PIOD_ODR = AT91C_PIO_PD6; /* Manage PD6 io */
390 *AT91C_PIOD_PER = AT91C_PIO_PD6; /* Enable PD6 PIO */
391 *AT91C_PIOD_OER = AT91C_PIO_PD6; /* Enables PD6 ouput */
392 *AT91C_PIOD_SODR = AT91C_PIO_PD6; /* Set PD6 */
395 void turn_led_on()
397 *AT91C_PIOD_ODR = AT91C_PIO_PD6;
398 *AT91C_PIOD_PER = AT91C_PIO_PD6;
399 *AT91C_PIOD_OER = AT91C_PIO_PD6;
400 *AT91C_PIOD_CODR = AT91C_PIO_PD6;
403 void set_hw_lock(int set)
405 *AT91C_PIOC_ODR = AT91C_PIO_PC15; /* Manage PB15 io */
406 *AT91C_PIOC_PER = AT91C_PIO_PC15; /* Enables PB15 io */
407 *AT91C_PIOC_OER = AT91C_PIO_PC15; /* Enables PB15 ouput */
408 if ( set) {
409 *AT91C_PIOC_SODR = AT91C_PIO_PC15; /* Clear PB 15 */
411 else {
412 *AT91C_PIOC_CODR = AT91C_PIO_PC15; /* Clear PB 15 */
416 #define ILIM0 0
417 #define ILIM1 100
418 #define ILIM2 200
419 int cnt=0;
420 void switch_led()
422 switch ( cnt)
424 case ILIM0 :
426 turn_led_on();
427 cnt++;
428 break;
431 case ILIM1:
433 turn_led_off();
434 cnt++;
435 break;
437 case ILIM2:
439 cnt = ILIM0;
440 break;
442 default:
444 cnt++;
445 break;
451 //*----------------------------------------------------------------------------
452 //* Function Name : main
453 //* Object : Main function
454 //* Input Parameters : none
455 //* Output Parameters : True
456 //*----------------------------------------------------------------------------
458 void flash_lock_reg(void);
459 void flash_unlock_reg(void);
462 int main(void)
464 AT91PS_Buffer pXmBuffer;
465 AT91PS_SvcComm pSvcXmodem;
466 AT91S_SvcTempo svcUbootTempo; // Link to a AT91S_Tempo object
468 unsigned int AddressToDownload, SizeToDownload;
469 unsigned int DeviceAddress = 0;
470 volatile int i = 0;
471 char command = 0;
472 unsigned int crc1 = 0, crc2 = 0;
473 volatile int device;
474 int NbPage;
476 set_hw_lock(0);
478 stdin = fopen(0, at91_dbgu_getc);
479 stdout = fopen(at91_dbgu_putc, 0);
481 pAT91 = AT91C_ROM_BOOT_ADDRESS;
483 // Tempo Initialisation
484 pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));
485 ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));
487 // Attach the tempo to a tempo controler
488 ctlTempo.CtlTempoCreate(&ctlTempo, &svcUbootTempo);
490 // Xmodem Initialisation
491 pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);
492 pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);
493 pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);
495 //* System Timer initialization
496 AT91F_AIC_ConfigureIt (
497 AT91C_BASE_AIC, // AIC base address
498 AT91C_ID_SYS, // System peripheral ID
499 AT91C_AIC_PRIOR_HIGHEST, // Max priority
500 AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive
501 AT91F_ST_ASM_Handler );
502 //* Enable ST interrupt
503 AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);
505 // DataFlash on SPI Configuration
506 AT91F_DataflashInit ();
508 // start tempo to start Uboot in a delay of 1 sec if no key pressed
509 svcUbootTempo.Start(&svcUbootTempo, 2000, 0, AT91F_StartUboot, (void *)0);
512 printf("press any key to enter bootloader\n\r");
513 getc();
515 // stop tempo
516 svcUbootTempo.Stop(&svcUbootTempo);
518 while(1)
520 while(command == 0)
522 AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS;
523 SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE;
524 DeviceAddress = 0;
526 AT91F_DisplayMenu();
527 message[0] = 0;
528 message[2] = 0;
529 AT91F_ReadLine("Enter: ", message);
531 command = message[0];
532 if(command == '1' || command == '2' ||
533 command == '3' ||
534 command == '5' ||
535 command == '6' ||
536 command == '7' ||
537 command == 'b' ||
538 command == 'c' ||
539 command == 'e'
541 if(AsciiToHex(&message[2], &DeviceAddress) == 0)
542 command = 0;
544 switch(command)
546 case '1':
547 printf("Download Dataflash [0x%x]\n\r", DeviceAddress);
549 switch(DeviceAddress & 0xFF000000)
551 case CFG_DATAFLASH_LOGIC_ADDR_CS0:
552 device = 0;
553 break;
555 case CFG_DATAFLASH_LOGIC_ADDR_CS1:
556 device = 1;
557 break;
559 case CFG_DATAFLASH_LOGIC_ADDR_CS2:
560 device = 2;
561 break;
563 case CFG_DATAFLASH_LOGIC_ADDR_CS3:
564 device = 3;
565 break;
567 default:
568 command = 0;
569 break;
571 break;
573 case '2':
576 AT91F_MemoryDisplay(DeviceAddress, 4, 64);
577 AT91F_ReadLine ((char *)0, message);
578 DeviceAddress += 0x100;
580 while(message[0] == '\0');
581 command = 0;
582 break;
584 case '3':
586 AT91F_StartUboot(0, (void *)DeviceAddress);
587 command = 0;
588 break;
591 case '4':
593 int *i;
594 for(i = (int *)0x20000000; i < (int *)0x20004000; i++)
595 *i = 0;
597 write_dataflash(0xc0000000, 0x20000000, 0x4000);
598 printf("Bootsection cleared\r\n");
599 command = 0;
600 break;
602 case '5':
603 erase_dataflash(DeviceAddress);
604 command = 0;
605 break;
607 case '6':
609 flash_enable_lock(DeviceAddress);
610 command = 0;
611 break;
614 case '7':
616 flash_disable_lock(DeviceAddress);
617 command = 0;
618 break;
621 case '8':
623 read_lock_reg(&read_lock_cmd_sector);
624 command = 0;
625 break;
627 case '9':
629 read_lock_reg(&read_lock_cmd_lockdown);
630 command = 0;
631 break;
633 case 'a':
635 read_lock_reg(&read_lock_cmd_security);
636 command = 0;
637 break;
639 case 'b':
641 clr_lock_reg(DeviceAddress);
642 command = 0;
643 break;
645 case 'c':
647 set_lock_reg(DeviceAddress);
648 command = 0;
649 break;
652 case 'd':
654 AT91F_DataflashPrintInfo();
655 command = 0;
656 break;
658 case 'e':
660 AT91F_StartUboot(0, (void *)DeviceAddress);
661 command = 0;
662 break;
665 case 'f':
667 set_hw_lock(0);
668 command = 0;
669 break;
671 case 'g':
673 set_hw_lock(1);
674 command = 0;
675 break;
677 case 'd':
678 default:
679 AT91F_DataflashPrintInfo();
680 command = 0;
681 break;
685 xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload, SizeToDownload, XmodemProtocol, 0);
686 while(XmodemComplete !=1);
687 SizeToDownload = (unsigned int)(svcXmodem.pData) - (unsigned int)AddressToDownload;
689 // Modification of vector 6
690 NbPage = 0;
691 i = dataflash_info[device].Device.pages_number;
692 while(i >>= 1)
693 NbPage++;
694 i = (SizeToDownload / 512) + 1 + (NbPage << 13) + (dataflash_info[device].Device.pages_size << 17);
695 *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i;
697 printf("\n\rModification of Arm Vector 6 :%x\n\r", i);
699 printf("\n\rWrite %d bytes in DataFlash [0x%x]\n\r",SizeToDownload, DeviceAddress);
700 crc1 = 0;
701 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1);
703 // write the dataflash
704 write_dataflash (DeviceAddress, AddressToDownload, SizeToDownload);
705 // clear the buffer before read
706 for(i=0; i < SizeToDownload; i++)
707 *(unsigned char *)(AddressToDownload + i) = 0;
709 //* Read dataflash page in TestBuffer
710 read_dataflash (DeviceAddress, SizeToDownload, (char *)(AddressToDownload));
712 printf("Verify Dataflash: ");
713 crc2 = 0;
715 pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2);
716 if (crc1 != crc2)
717 printf("Failed\r\n");
718 else
719 printf("OK\r\n");
721 command = 0;
722 XmodemComplete = 0;
723 AT91F_WaitKeyPressed();