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
12 //* Creation : HIi 10/10/2003
13 //*----------------------------------------------------------------------------
14 #include <AT91RM9200.h>
15 #include <lib_AT91RM9200.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
26 #define AT91C_PLLA_VALUE 0x20263E04 // -> 179.712MHz
27 #define AT91C_PLLA_MCK 0x0000202
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
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"
47 "4: Clear bootloader section in Dataflash\n\r"
48 "5: Read Dram [addr]\n\r"
49 "6: Lock the flash\n\r"
50 "7: Unlock the flash\r\n"
51 "8: Read the lock register status of the flash\r\n"
54 //* Globales variables
56 volatile char XmodemComplete
= 0;
59 AT91S_RomBoot
const *pAT91
;
60 AT91S_SBuffer sXmBuffer
;
61 AT91S_SvcXmodem svcXmodem
;
62 AT91S_Pipe xmodemPipe
;
63 AT91S_CtlTempo ctlTempo
;
64 AT91S_SvcTempo svcTempo
; // Link to a AT91S_Tempo object
68 //*--------------------------------------------------------------------------------------
69 //* Function Name : GetTickCount()
70 //* Object : Return the number of systimer tick
71 //* Input Parameters :
72 //* Output Parameters :
73 //*--------------------------------------------------------------------------------------
74 unsigned int GetTickCount(void)
80 //*--------------------------------------------------------------------------------------
81 //* Function Name : AT91_XmodemComplete()
82 //* Object : Perform the remap and jump to appli in RAM
83 //* Input Parameters :
84 //* Output Parameters :
85 //*--------------------------------------------------------------------------------------
86 void AT91_XmodemComplete(AT91S_PipeStatus status
, void *pVoid
)
88 // stop the Xmodem tempo
89 svcXmodem
.tempo
.Stop(&(svcXmodem
.tempo
));
94 //*--------------------------------------------------------------------------------------
95 //* Function Name : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid)
96 //* Object : Xmodem dispatcher
97 //* Input Parameters :
98 //* Output Parameters :
99 //*--------------------------------------------------------------------------------------
100 void XmodemProtocol(AT91S_PipeStatus status
, void *pVoid
)
102 AT91PS_SBuffer pSBuffer
= (AT91PS_SBuffer
) xmodemPipe
.pBuffer
->pChild
;
103 AT91PS_USART pUsart
= svcXmodem
.pUsart
;
105 if (pSBuffer
->szRdBuffer
== 0) {
106 // Start a tempo to wait the Xmodem protocol complete
107 svcXmodem
.tempo
.Start(&(svcXmodem
.tempo
), 10, 0, AT91_XmodemComplete
, pUsart
);
112 //*-------------------------- Interrupt handlers ----------------------------------------
113 //*--------------------------------------------------------------------------------------
114 //* Function Name : irq1_c_handler()
115 //* Object : C Interrupt handler for Interrutp source 1
116 //* Input Parameters : none
117 //* Output Parameters : none
118 //*--------------------------------------------------------------------------------------
119 extern "C" void AT91F_ST_Handler(void);
121 void AT91F_ST_Handler(void)
123 volatile unsigned int csr
= *AT91C_DBGU_CSR
;
126 /* ========== Systimer interrupt ============== */
127 if (AT91C_BASE_ST
->ST_SR
& 0x01) {
130 ctlTempo
.CtlTempoTick(&ctlTempo
);
134 error
= AT91F_US_Error((AT91PS_USART
)AT91C_BASE_DBGU
);
136 // Stop previous Xmodem transmition
137 *(AT91C_DBGU_CR
) = AT91C_US_RSTSTA
;
138 AT91F_US_DisableIt((AT91PS_USART
)AT91C_BASE_DBGU
, AT91C_US_ENDRX
);
139 AT91F_US_EnableIt((AT91PS_USART
)AT91C_BASE_DBGU
, AT91C_US_RXRDY
);
143 else if (csr
& (AT91C_US_TXRDY
| AT91C_US_ENDTX
| AT91C_US_TXEMPTY
|
144 AT91C_US_RXRDY
| AT91C_US_ENDRX
| AT91C_US_TIMEOUT
|
146 if ( !(svcXmodem
.eot
) )
147 svcXmodem
.Handler(&svcXmodem
, csr
);
152 //*-----------------------------------------------------------------------------
153 //* Function Name : AT91F_DisplayMenu()
155 //* Input Parameters :
157 //*-----------------------------------------------------------------------------
158 void AT91F_DisplayMenu(void)
160 printf("\n\rATMEL LOADER %s %s %s\n\r", AT91C_VERSION
, __DATE__
, __TIME__
);
162 AT91F_DataflashPrintInfo();
164 printf(menu_dataflash
);
168 //*-----------------------------------------------------------------------------
169 //* Function Name : AsciiToHex()
170 //* Object : ascii to hexa conversion
171 //* Input Parameters :
173 //*-----------------------------------------------------------------------------
174 unsigned int AsciiToHex(char *s
, unsigned int *val
)
180 if(s
[0] == '0' && ((s
[1] == 'x') || (s
[1] == 'X')))
183 while((n
< 8) && (s
[n
] !=0))
186 if ( (s
[n
] >= '0') && (s
[n
] <='9'))
187 *val
+= (s
[n
] - '0');
189 if ((s
[n
] >= 'a') && (s
[n
] <='f'))
190 *val
+= (s
[n
] - 0x57);
192 if ((s
[n
] >= 'A') && (s
[n
] <='F'))
193 *val
+= (s
[n
] - 0x37);
203 //*-----------------------------------------------------------------------------
204 //* Function Name : AT91F_MemoryDisplay()
205 //* Object : Display the content of the dataflash
206 //* Input Parameters :
208 //*-----------------------------------------------------------------------------
209 int AT91F_MemoryDisplay(unsigned int addr
, unsigned int size
, unsigned int length
)
211 unsigned long i
, nbytes
, linebytes
;
216 char linebuf
[DISP_LINE_LEN
];
218 nbytes
= length
* size
;
221 uip
= (unsigned int *)linebuf
;
222 usp
= (unsigned short *)linebuf
;
223 ucp
= (unsigned char *)linebuf
;
225 printf("%08x:", addr
);
226 linebytes
= (nbytes
> DISP_LINE_LEN
)?DISP_LINE_LEN
:nbytes
;
228 read_dataflash(addr
, (linebytes
/size
)*size
, linebuf
);
229 for (i
=0; i
<linebytes
; i
+= size
)
232 printf(" %08x", *uip
++);
234 printf(" %04x", *usp
++);
236 printf(" %02x", *ucp
++);
241 for (i
=0; i
<linebytes
; i
++) {
242 if ((*cp
< 0x20) || (*cp
> 0x7e))
250 } while (nbytes
> 0);
254 //*-----------------------------------------------------------------------------
255 //* Function Name : AT91F_DramDisplay()
256 //* Object : Display the content of the sdram
257 //* Input Parameters :
259 //*-----------------------------------------------------------------------------
260 int AT91F_SdramDisplay(unsigned int addr
, unsigned int size
, unsigned int length
)
262 unsigned long i
, nbytes
, linebytes
;
268 nbytes
= length
* size
;
271 uip
= (unsigned int *)addr
;
272 usp
= (unsigned short *)addr
;
273 ucp
= (unsigned char *)addr
;
275 printf("%08x:", addr
);
276 linebytes
= (nbytes
> DISP_LINE_LEN
)?DISP_LINE_LEN
:nbytes
;
278 for (i
=0; i
<linebytes
; i
+= size
)
281 printf(" %08x", *uip
++);
283 printf(" %04x", *usp
++);
285 printf(" %02x", *ucp
++);
289 for (i
=0; i
<linebytes
; i
++) {
290 if ((*cp
< 0x20) || (*cp
> 0x7e))
298 } while (nbytes
> 0);
303 //*--------------------------------------------------------------------------------------
304 //* Function Name : AT91F_SetPLL
305 //* Object : Set the PLLA to 180Mhz and Master clock to 60 Mhz
306 //* Input Parameters :
307 //* Output Parameters :
308 //*--------------------------------------------------------------------------------------
309 void AT91F_SetPLL(void)
311 volatile int tmp
= 0;
313 AT91PS_PMC pPmc
= AT91C_BASE_PMC
;
314 AT91PS_CKGR pCkgr
= AT91C_BASE_CKGR
;
316 pPmc
->PMC_IDR
= 0xFFFFFFFF;
319 pCkgr
->CKGR_PLLAR
= AT91C_PLLA_VALUE
;
321 while(!(pPmc
->PMC_SR
& AT91C_PMC_MCKRDY
) && (tmp
++ < DELAY_MAIN_FREQ
));
323 //* - Commuting Master Clock from PLLB to PLLA/3
324 pPmc
->PMC_MCKR
= AT91C_PLLA_MCK
;
328 //*--------------------------------------------------------------------------------------
329 //* Function Name : AT91F_ResetRegisters
330 //* Object : Restore the initial state to registers
331 //* Input Parameters :
332 //* Output Parameters :
333 //*--------------------------------------------------------------------------------------
334 static void AT91F_ResetRegisters(void)
338 //* set the PIOs in input
339 *AT91C_PIOA_ODR
= 0xFFFFFFFF; /* Disables all the output pins */
340 *AT91C_PIOA_PER
= 0xFFFFFFFF; /* Enables the PIO to control all the pins */
342 AT91F_AIC_DisableIt (AT91C_BASE_AIC
, AT91C_ID_SYS
);
344 /* close all peripheral clocks */
345 AT91C_BASE_PMC
->PMC_PCDR
= 0xFFFFFFFC;
347 //* Disable core interrupts and set supervisor mode
348 __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40)
350 //* Clear all the interrupts
351 *AT91C_AIC_ICCR
= 0xffffffff;
353 /* read the AIC_IVR and AIC_FVR */
357 /* write the end of interrupt control register */
358 *AT91C_AIC_EOICR
= 0;
363 void AT91F_StartUboot(unsigned int dummy
, void *pvoid
)
365 printf("Load U-BOOT from dataflash[%x] to SDRAM[%x]\n\r", AT91C_UBOOT_DATAFLASH_ADDR
, AT91C_UBOOT_ADDR
);
366 read_dataflash(AT91C_UBOOT_DATAFLASH_ADDR
, AT91C_UBOOT_SIZE
, (char *)(AT91C_UBOOT_ADDR
));
367 printf("Set PLLA to 180Mhz and Master clock to 60Mhz and start U-BOOT\n\r");
369 AT91F_ResetRegisters();
370 Jump(AT91C_UBOOT_ADDR
);
376 *AT91C_PIOD_ODR
= AT91C_PIO_PD6
; /* Disables all the output pins */
377 *AT91C_PIOD_PER
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
378 *AT91C_PIOD_OER
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
379 *AT91C_PIOD_SODR
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
384 *AT91C_PIOD_ODR
= AT91C_PIO_PD6
; /* Disables all the output pins */
385 *AT91C_PIOD_PER
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
386 *AT91C_PIOD_OER
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
387 *AT91C_PIOD_CODR
= AT91C_PIO_PD6
; /* Enables the PIO to control all the pins */
424 AT91S_DataflashDesc desc
;
426 unsigned char read_lock_cmd
[4]=
431 void clear_desc( AT91S_DataflashDesc
*d
)
442 d
->DataFlash_state
= 0;
456 unsigned char rx
[33];
460 desc
.tx_cmd_pt
= read_lock_cmd
;
462 desc
.tx_cmd_size
= 4;
463 desc
.rx_cmd_size
= 4;
464 desc
.tx_data_size
= 32;
465 desc
.rx_data_size
= 32;
466 desc
.tx_data_pt
= rx
;
467 desc
.rx_data_pt
= rx
;
469 AT91F_SpiWrite(&desc
);
470 printf("Lock status = \r\n");
471 for ( i
= 0 ; i
< 16 ; i
++ )
473 printf("0x%02x:",rx
[i
]);
475 for ( i
= 16 ; i
< 32 ; i
++ )
477 printf("0x%02x:",rx
[i
]);
481 unsigned char clear_lock_cmd
[4]=
486 void clear_lock_reg()
489 unsigned char rx
[33];
490 for ( i
= 0 ; i
< 32 ; i
++)
497 desc
.tx_cmd_pt
= clear_lock_cmd
;
499 desc
.tx_cmd_size
= 4;
500 desc
.rx_cmd_size
= 4;
501 AT91F_SpiWrite(&desc
);
505 unsigned char lock_unlock_cmd
[4]=
510 unsigned char enable_lock_unlock_cmd
[4]=
515 unsigned char disable_lock_unlock_cmd
[4]=
519 void flash_lock_reg()
521 unsigned char rxf
[4];
522 unsigned char rx
[33];
529 desc
.tx_cmd_pt
= enable_lock_unlock_cmd
;
530 desc
.rx_cmd_pt
= rxf
;
531 desc
.tx_cmd_size
= 4;
532 desc
.rx_cmd_size
= 4;
534 AT91F_SpiWrite(&desc
);
537 for ( i
= 0 ; i
< 32 ; i
++)
541 desc
.tx_cmd_pt
= lock_unlock_cmd
;
542 desc
.rx_cmd_pt
= rxf
;
543 desc
.tx_cmd_size
= 4;
544 desc
.rx_cmd_size
= 4;
545 desc
.tx_data_size
= 32;
546 desc
.rx_data_size
= 32;
547 desc
.tx_data_pt
= rx
;
548 desc
.rx_data_pt
= rx
;
550 AT91F_SpiWrite(&desc
);
555 void flash_unlock_reg()
558 unsigned char rxf
[4];
559 unsigned char rx
[33];
563 for ( i
= 0 ; i
< 32 ; i
++)
568 desc
.tx_cmd_pt
= lock_unlock_cmd
;
569 desc
.rx_cmd_pt
= rxf
;
570 desc
.tx_cmd_size
= 4;
571 desc
.rx_cmd_size
= 4;
572 desc
.tx_data_size
= 32;
573 desc
.rx_data_size
= 32;
574 desc
.tx_data_pt
= rx
;
575 desc
.rx_data_pt
= rx
;
577 AT91F_SpiWrite(&desc
);
581 desc
.tx_cmd_pt
= disable_lock_unlock_cmd
;
582 desc
.rx_cmd_pt
= rxf
;
583 desc
.tx_cmd_size
= 4;
584 desc
.rx_cmd_size
= 4;
586 AT91F_SpiWrite(&desc
);
590 //*----------------------------------------------------------------------------
591 //* Function Name : main
592 //* Object : Main function
593 //* Input Parameters : none
594 //* Output Parameters : True
595 //*----------------------------------------------------------------------------
598 AT91PS_Buffer pXmBuffer
;
599 AT91PS_SvcComm pSvcXmodem
;
600 AT91S_SvcTempo svcUbootTempo
; // Link to a AT91S_Tempo object
602 unsigned int AddressToDownload
, SizeToDownload
;
603 unsigned int DeviceAddress
= 0;
606 unsigned int crc1
= 0, crc2
= 0;
610 stdin
= fopen(0, at91_dbgu_getc
);
611 stdout
= fopen(at91_dbgu_putc
, 0);
613 pAT91
= AT91C_ROM_BOOT_ADDRESS
;
615 // Tempo Initialisation
616 pAT91
->OpenCtlTempo(&ctlTempo
, (void *) &(pAT91
->SYSTIMER_DESC
));
617 ctlTempo
.CtlTempoStart((void *) &(pAT91
->SYSTIMER_DESC
));
619 // Attach the tempo to a tempo controler
620 ctlTempo
.CtlTempoCreate(&ctlTempo
, &svcUbootTempo
);
622 // Xmodem Initialisation
623 pXmBuffer
= pAT91
->OpenSBuffer(&sXmBuffer
);
624 pSvcXmodem
= pAT91
->OpenSvcXmodem(&svcXmodem
, (AT91PS_USART
)AT91C_BASE_DBGU
, &ctlTempo
);
625 pAT91
->OpenPipe(&xmodemPipe
, pSvcXmodem
, pXmBuffer
);
627 //* System Timer initialization
628 AT91F_AIC_ConfigureIt (
629 AT91C_BASE_AIC
, // AIC base address
630 AT91C_ID_SYS
, // System peripheral ID
631 AT91C_AIC_PRIOR_HIGHEST
, // Max priority
632 AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
, // Level sensitive
633 AT91F_ST_ASM_Handler
);
634 //* Enable ST interrupt
635 AT91F_AIC_EnableIt(AT91C_BASE_AIC
, AT91C_ID_SYS
);
637 // DataFlash on SPI Configuration
638 AT91F_DataflashInit ();
640 // start tempo to start Uboot in a delay of 1 sec if no key pressed
641 svcUbootTempo
.Start(&svcUbootTempo
, 200, 0, AT91F_StartUboot
, (void *)0);
643 printf("press any key to enter bootloader\n\r");
647 svcUbootTempo
.Stop(&svcUbootTempo
);
653 AddressToDownload
= AT91C_DOWNLOAD_BASE_ADDRESS
;
654 SizeToDownload
= AT91C_DOWNLOAD_MAX_SIZE
;
660 AT91F_ReadLine("Enter: ", message
);
662 command
= message
[0];
663 if(command
== '1' || command
== '2' || command
== '5' )
664 if(AsciiToHex(&message
[2], &DeviceAddress
) == 0)
670 printf("Download Dataflash [0x%x]\n\r", DeviceAddress
);
672 switch(DeviceAddress
& 0xFF000000)
674 case CFG_DATAFLASH_LOGIC_ADDR_CS0
:
678 case CFG_DATAFLASH_LOGIC_ADDR_CS3
:
691 AT91F_MemoryDisplay(DeviceAddress
, 4, 64);
692 AT91F_ReadLine ((char *)0, message
);
693 DeviceAddress
+= 0x100;
695 while(message
[0] == '\0');
700 AT91F_StartUboot(0, (void *)0);
706 for(i
= (int *)0x20000000; i
< (int *)0x20004000; i
++)
709 write_dataflash(0xc0000000, 0x20000000, 0x4000);
710 printf("Bootsection cleared\r\n");
716 AT91F_SdramDisplay(DeviceAddress
, 4, 64);
717 AT91F_ReadLine ((char *)0, message
);
718 DeviceAddress
+= 0x100;
720 while(message
[0] == '\0');
754 xmodemPipe
.Read(&xmodemPipe
, (char *)AddressToDownload
, SizeToDownload
, XmodemProtocol
, 0);
755 while(XmodemComplete
!=1);
756 SizeToDownload
= (unsigned int)(svcXmodem
.pData
) - (unsigned int)AddressToDownload
;
758 // Modification of vector 6
760 i
= dataflash_info
[device
].Device
.pages_number
;
763 i
= (SizeToDownload
/ 512) + 1 + (NbPage
<< 13) + (dataflash_info
[device
].Device
.pages_size
<< 17);
764 *(int *)(AddressToDownload
+ AT91C_OFFSET_VECT6
) = i
;
766 printf("\n\rModification of Arm Vector 6 :%x\n\r", i
);
768 printf("\n\rWrite %d bytes in DataFlash [0x%x]\n\r",SizeToDownload
, DeviceAddress
);
770 pAT91
->CRC32((const unsigned char *)AddressToDownload
, SizeToDownload
, &crc1
);
772 // write the dataflash
773 write_dataflash (DeviceAddress
, AddressToDownload
, SizeToDownload
);
774 // clear the buffer before read
775 for(i
=0; i
< SizeToDownload
; i
++)
776 *(unsigned char *)(AddressToDownload
+ i
) = 0;
778 //* Read dataflash page in TestBuffer
779 read_dataflash (DeviceAddress
, SizeToDownload
, (char *)(AddressToDownload
));
781 printf("Verify Dataflash: ");
784 pAT91
->CRC32((const unsigned char *)AddressToDownload
, SizeToDownload
, &crc2
);
786 printf("Failed\r\n");
792 AT91F_WaitKeyPressed();