b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 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 | * Modif : HIi 15/06/2004 : add crc32 to verify the download |
| 14 | * from dataflash |
| 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 | *---------------------------------------------------------------------------- |
| 23 | */ |
| 24 | #include "config.h" |
| 25 | #include "stdio.h" |
| 26 | #include "AT91RM9200.h" |
| 27 | #include "lib_AT91RM9200.h" |
| 28 | #include "com.h" |
| 29 | #include "main.h" |
| 30 | #include "dataflash.h" |
| 31 | #include "AT91C_MCI_Device.h" |
| 32 | |
| 33 | #define DEBUGOUT |
| 34 | #define XMODEM |
| 35 | #define MEMDISP |
| 36 | |
| 37 | #ifdef PAGESZ_1056 |
| 38 | #define PAGESIZE 1056 |
| 39 | #else |
| 40 | #define PAGESIZE 1024 |
| 41 | #endif |
| 42 | |
| 43 | #define AT91C_SDRAM_START 0x20000000 |
| 44 | #define AT91C_BOOT_ADDR 0x21F00000 |
| 45 | #define AT91C_BOOT_SIZE 128*PAGESIZE |
| 46 | #ifdef PAGESZ_1056 |
| 47 | #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008400 |
| 48 | #else |
| 49 | #define AT91C_BOOT_DATAFLASH_ADDR 0xC0008000 |
| 50 | #endif |
| 51 | #define AT91C_PLLA_VALUE 0x237A3E5A // crystal= 18.432MHz - fixes BRG error at 115kbps |
| 52 | //#define AT91C_PLLA_VALUE 0x2026BE04 // crystal= 18.432MHz |
| 53 | //#define AT91C_PLLA_VALUE 0x202CBE01 // crystal= 4MHz |
| 54 | |
| 55 | |
| 56 | |
| 57 | #define DISP_LINE_LEN 16 |
| 58 | |
| 59 | // Reason for boot failure |
| 60 | #define IMAGE_BAD_SIZE 0 |
| 61 | #define IMAGE_READ_FAILURE 1 |
| 62 | #define IMAGE_CRC_ERROR 2 |
| 63 | #define IMAGE_ERROR 3 |
| 64 | #define SUCCESS -1 |
| 65 | |
| 66 | /* prototypes*/ |
| 67 | extern void AT91F_ST_ASM_HANDLER(void); |
| 68 | extern void Jump(unsigned int addr); |
| 69 | |
| 70 | const char *menu_dataflash[] = { |
| 71 | #ifdef XMODEM |
| 72 | "1: P DFboot\n", |
| 73 | "2: P U-Boot\n", |
| 74 | #endif |
| 75 | "3: P SDCard\n", |
| 76 | #ifdef PAGESZ_1056 |
| 77 | "4: R UBOOT\n", |
| 78 | #else |
| 79 | "4: R UBOOT\n", |
| 80 | #endif |
| 81 | #ifdef XMODEM |
| 82 | "5: P DF [addr]\n", |
| 83 | #endif |
| 84 | "6: RD DF [addr]\n", |
| 85 | "7: E DF\n" |
| 86 | }; |
| 87 | #ifdef XMODEM |
| 88 | #define MAXMENU 7 |
| 89 | #else |
| 90 | #define MAXMENU 4 |
| 91 | #endif |
| 92 | |
| 93 | char message[20]; |
| 94 | #ifdef XMODEM |
| 95 | volatile char XmodemComplete = 0; |
| 96 | #endif |
| 97 | unsigned int StTick = 0; |
| 98 | |
| 99 | AT91S_RomBoot const *pAT91; |
| 100 | #ifdef XMODEM |
| 101 | AT91S_SBuffer sXmBuffer; |
| 102 | AT91S_SvcXmodem svcXmodem; |
| 103 | AT91S_Pipe xmodemPipe; |
| 104 | #endif |
| 105 | AT91S_CtlTempo ctlTempo; |
| 106 | |
| 107 | |
| 108 | //*-------------------------------------------------------------------------------------- |
| 109 | //* Function Name : GetTickCount() |
| 110 | //* Object : Return the number of systimer tick |
| 111 | //* Input Parameters : |
| 112 | //* Output Parameters : |
| 113 | //*-------------------------------------------------------------------------------------- |
| 114 | unsigned int GetTickCount(void) |
| 115 | { |
| 116 | return StTick; |
| 117 | } |
| 118 | |
| 119 | #ifdef XMODEM |
| 120 | //*-------------------------------------------------------------------------------------- |
| 121 | //* Function Name : AT91_XmodemComplete() |
| 122 | //* Object : Perform the remap and jump to appli in RAM |
| 123 | //* Input Parameters : |
| 124 | //* Output Parameters : |
| 125 | //*-------------------------------------------------------------------------------------- |
| 126 | static void AT91_XmodemComplete(AT91S_PipeStatus status, void *pVoid) |
| 127 | { |
| 128 | /* stop the Xmodem tempo */ |
| 129 | svcXmodem.tempo.Stop(&(svcXmodem.tempo)); |
| 130 | XmodemComplete = 1; |
| 131 | } |
| 132 | |
| 133 | |
| 134 | //*-------------------------------------------------------------------------------------- |
| 135 | //* Function Name : AT91F_XmodemProtocol(AT91S_PipeStatus status, void *pVoid) |
| 136 | //* Object : Xmodem dispatcher |
| 137 | //* Input Parameters : |
| 138 | //* Output Parameters : |
| 139 | //*-------------------------------------------------------------------------------------- |
| 140 | static void XmodemProtocol(AT91S_PipeStatus status, void *pVoid) |
| 141 | { |
| 142 | AT91PS_SBuffer pSBuffer = (AT91PS_SBuffer) xmodemPipe.pBuffer->pChild; |
| 143 | AT91PS_USART pUsart = svcXmodem.pUsart; |
| 144 | |
| 145 | if (pSBuffer->szRdBuffer == 0) { |
| 146 | /* Start a tempo to wait the Xmodem protocol complete */ |
| 147 | svcXmodem.tempo.Start(&(svcXmodem.tempo), 10, 0, AT91_XmodemComplete, pUsart); |
| 148 | } |
| 149 | } |
| 150 | #endif |
| 151 | |
| 152 | //*-------------------------------------------------------------------------------------- |
| 153 | //* Function Name : irq1_c_handler() |
| 154 | //* Object : C Interrupt handler for Interrutp source 1 |
| 155 | //* Input Parameters : none |
| 156 | //* Output Parameters : none |
| 157 | //*-------------------------------------------------------------------------------------- |
| 158 | void AT91F_ST_HANDLER(void) |
| 159 | { |
| 160 | volatile unsigned int csr = *AT91C_DBGU_CSR; |
| 161 | #ifdef XMODEM |
| 162 | unsigned int error; |
| 163 | #endif |
| 164 | |
| 165 | if (AT91C_BASE_ST->ST_SR & 0x01) { |
| 166 | StTick++; |
| 167 | ctlTempo.CtlTempoTick(&ctlTempo); |
| 168 | return; |
| 169 | } |
| 170 | |
| 171 | #ifdef XMODEM |
| 172 | error = AT91F_US_Error((AT91PS_USART)AT91C_BASE_DBGU); |
| 173 | if (csr & error) { |
| 174 | /* Stop previous Xmodem transmition*/ |
| 175 | *(AT91C_DBGU_CR) = AT91C_US_RSTSTA; |
| 176 | AT91F_US_DisableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_ENDRX); |
| 177 | AT91F_US_EnableIt((AT91PS_USART)AT91C_BASE_DBGU, AT91C_US_RXRDY); |
| 178 | |
| 179 | } |
| 180 | |
| 181 | else if (csr & (AT91C_US_TXRDY | AT91C_US_ENDTX | AT91C_US_TXEMPTY | |
| 182 | AT91C_US_RXRDY | AT91C_US_ENDRX | AT91C_US_TIMEOUT | |
| 183 | AT91C_US_RXBUFF)) { |
| 184 | if ( !(svcXmodem.eot) ) |
| 185 | svcXmodem.Handler(&svcXmodem, csr); |
| 186 | } |
| 187 | #endif |
| 188 | } |
| 189 | |
| 190 | |
| 191 | //*----------------------------------------------------------------------------- |
| 192 | //* Function Name : AT91F_DisplayMenu() |
| 193 | //* Object : |
| 194 | //* Input Parameters : |
| 195 | //* Return value : |
| 196 | //*----------------------------------------------------------------------------- |
| 197 | static int AT91F_DisplayMenu(void) |
| 198 | { |
| 199 | int i, mci_present = 0; |
| 200 | printf("\nDF LOADER %s %s %s\n",AT91C_VERSION,__DATE__,__TIME__); |
| 201 | AT91F_DataflashPrintInfo(); |
| 202 | mci_present = AT91F_MCI_Init(); |
| 203 | for(i = 0; i < MAXMENU; i++) { |
| 204 | puts(menu_dataflash[i]); |
| 205 | } |
| 206 | return mci_present; |
| 207 | } |
| 208 | |
| 209 | |
| 210 | //*----------------------------------------------------------------------------- |
| 211 | //* Function Name : AsciiToHex() |
| 212 | //* Object : ascii to hexa conversion |
| 213 | //* Input Parameters : |
| 214 | //* Return value : |
| 215 | //*----------------------------------------------------------------------------- |
| 216 | static unsigned int AsciiToHex(char *s, unsigned int *val) |
| 217 | { |
| 218 | int n; |
| 219 | |
| 220 | *val=0; |
| 221 | |
| 222 | if(s[0] == '0' && ((s[1] == 'x') || (s[1] == 'X'))) |
| 223 | s+=2; |
| 224 | n = 0; |
| 225 | while((n < 8) && (s[n] !=0)) |
| 226 | { |
| 227 | *val <<= 4; |
| 228 | if ( (s[n] >= '0') && (s[n] <='9')) |
| 229 | *val += (s[n] - '0'); |
| 230 | else |
| 231 | if ((s[n] >= 'a') && (s[n] <='f')) |
| 232 | *val += (s[n] - 0x57); |
| 233 | else |
| 234 | if ((s[n] >= 'A') && (s[n] <='F')) |
| 235 | *val += (s[n] - 0x37); |
| 236 | else |
| 237 | return 0; |
| 238 | n++; |
| 239 | } |
| 240 | |
| 241 | return 1; |
| 242 | } |
| 243 | |
| 244 | |
| 245 | #ifdef MEMDISP |
| 246 | //*----------------------------------------------------------------------------- |
| 247 | //* Function Name : AT91F_MemoryDisplay() |
| 248 | //* Object : Display the content of the dataflash |
| 249 | //* Input Parameters : |
| 250 | //* Return value : |
| 251 | //*----------------------------------------------------------------------------- |
| 252 | static int AT91F_MemoryDisplay(unsigned int addr, unsigned int length) |
| 253 | { |
| 254 | unsigned long i, nbytes, linebytes; |
| 255 | char *cp; |
| 256 | // unsigned int *uip; |
| 257 | // unsigned short *usp; |
| 258 | unsigned char *ucp; |
| 259 | char linebuf[DISP_LINE_LEN]; |
| 260 | |
| 261 | // nbytes = length * size; |
| 262 | nbytes = length; |
| 263 | do |
| 264 | { |
| 265 | // uip = (unsigned int *)linebuf; |
| 266 | // usp = (unsigned short *)linebuf; |
| 267 | ucp = (unsigned char *)linebuf; |
| 268 | |
| 269 | printf("%08x:", addr); |
| 270 | linebytes = (nbytes > DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; |
| 271 | if((addr & 0xF0000000) == 0x20000000) { |
| 272 | for(i = 0; i < linebytes; i ++) { |
| 273 | linebuf[i] = *(char *)(addr+i); |
| 274 | } |
| 275 | } else { |
| 276 | read_dataflash(addr, linebytes, linebuf); |
| 277 | } |
| 278 | for (i=0; i<linebytes; i++) |
| 279 | { |
| 280 | /* if (size == 4) |
| 281 | printf(" %08x", *uip++); |
| 282 | else if (size == 2) |
| 283 | printf(" %04x", *usp++); |
| 284 | else |
| 285 | */ |
| 286 | printf(" %02x", *ucp++); |
| 287 | // addr += size; |
| 288 | addr++; |
| 289 | } |
| 290 | printf(" "); |
| 291 | cp = linebuf; |
| 292 | for (i=0; i<linebytes; i++) { |
| 293 | if ((*cp < 0x20) || (*cp > 0x7e)) |
| 294 | printf("."); |
| 295 | else |
| 296 | printf("%c", *cp); |
| 297 | cp++; |
| 298 | } |
| 299 | printf("\n"); |
| 300 | nbytes -= linebytes; |
| 301 | } while (nbytes > 0); |
| 302 | return 0; |
| 303 | } |
| 304 | #endif |
| 305 | |
| 306 | //*-------------------------------------------------------------------------------------- |
| 307 | //* Function Name : AT91F_SetPLL |
| 308 | //* Object : Set the PLLA to 180Mhz and Master clock to 60 Mhz |
| 309 | //* Input Parameters : |
| 310 | //* Output Parameters : |
| 311 | //*-------------------------------------------------------------------------------------- |
| 312 | static unsigned int AT91F_SetPLL(void) |
| 313 | { |
| 314 | AT91_REG tmp; |
| 315 | AT91PS_PMC pPmc = AT91C_BASE_PMC; |
| 316 | AT91PS_CKGR pCkgr = AT91C_BASE_CKGR; |
| 317 | |
| 318 | pPmc->PMC_IDR = 0xFFFFFFFF; |
| 319 | |
| 320 | /* -Setup the PLL A */ |
| 321 | pCkgr->CKGR_PLLAR = AT91C_PLLA_VALUE; |
| 322 | |
| 323 | while (!(*AT91C_PMC_SR & AT91C_PMC_LOCKA)); |
| 324 | |
| 325 | /* - Switch Master Clock from PLLB to PLLA/3 */ |
| 326 | tmp = pPmc->PMC_MCKR; |
| 327 | /* See Atmel Errata #27 and #28 */ |
| 328 | if (tmp & 0x0000001C) { |
| 329 | tmp = (tmp & ~0x0000001C); |
| 330 | pPmc->PMC_MCKR = tmp; |
| 331 | while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)); |
| 332 | } |
| 333 | if (tmp != 0x00000202) { |
| 334 | pPmc->PMC_MCKR = 0x00000202; |
| 335 | if ((tmp & 0x00000003) != 0x00000002) |
| 336 | while (!(*AT91C_PMC_SR & AT91C_PMC_MCKRDY)); |
| 337 | } |
| 338 | |
| 339 | return 1; |
| 340 | } |
| 341 | |
| 342 | |
| 343 | //*-------------------------------------------------------------------------------------- |
| 344 | //* Function Name : AT91F_ResetRegisters |
| 345 | //* Object : Restore the initial state to registers |
| 346 | //* Input Parameters : |
| 347 | //* Output Parameters : |
| 348 | //*-------------------------------------------------------------------------------------- |
| 349 | static unsigned int AT91F_ResetRegisters(void) |
| 350 | { |
| 351 | volatile int i = 0; |
| 352 | |
| 353 | /* set the PIOs in input*/ |
| 354 | /* This disables the UART output, so dont execute for now*/ |
| 355 | |
| 356 | #ifndef DEBUGOUT |
| 357 | *AT91C_PIOA_ODR = 0xFFFFFFFF; /* Disables all the output pins */ |
| 358 | *AT91C_PIOA_PER = 0xFFFFFFFF; /* Enables the PIO to control all the pins */ |
| 359 | #endif |
| 360 | |
| 361 | AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_SYS); |
| 362 | /* close all peripheral clocks */ |
| 363 | |
| 364 | #ifndef DEBUGOUT |
| 365 | AT91C_BASE_PMC->PMC_PCDR = 0xFFFFFFFC; |
| 366 | #endif |
| 367 | /* Disable core interrupts and set supervisor mode */ |
| 368 | __asm__ ("msr CPSR_c, #0xDF"); //* ARM_MODE_SYS(0x1F) | I_BIT(0x80) | F_BIT(0x40) |
| 369 | /* Clear all the interrupts */ |
| 370 | *AT91C_AIC_ICCR = 0xffffffff; |
| 371 | |
| 372 | /* read the AIC_IVR and AIC_FVR */ |
| 373 | i = *AT91C_AIC_IVR; |
| 374 | i = *AT91C_AIC_FVR; |
| 375 | |
| 376 | /* write the end of interrupt control register */ |
| 377 | *AT91C_AIC_EOICR = 0; |
| 378 | |
| 379 | return 1; |
| 380 | } |
| 381 | |
| 382 | |
| 383 | static int AT91F_LoadBoot(void) |
| 384 | { |
| 385 | // volatile unsigned int crc1 = 0, crc2 = 0; |
| 386 | volatile unsigned int SizeToDownload = 0x21400; |
| 387 | volatile unsigned int AddressToDownload = AT91C_BOOT_ADDR; |
| 388 | |
| 389 | #if 0 |
| 390 | /* Read vector 6 to extract size to load */ |
| 391 | if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, 32, |
| 392 | (char *)AddressToDownload) != AT91C_DATAFLASH_OK) |
| 393 | { |
| 394 | printf("Bad Code Size\n"); |
| 395 | return IMAGE_BAD_SIZE; |
| 396 | } |
| 397 | /* calculate the size to download */ |
| 398 | SizeToDownload = *(int *)(AddressToDownload + AT91C_OFFSET_VECT6); |
| 399 | #endif |
| 400 | |
| 401 | // printf("\nLoad UBOOT from dataflash[%x] to SDRAM[%x]\n", |
| 402 | // AT91C_BOOT_DATAFLASH_ADDR, AT91C_BOOT_ADDR); |
| 403 | if (read_dataflash(AT91C_BOOT_DATAFLASH_ADDR, SizeToDownload + 8, |
| 404 | (char *)AddressToDownload) != AT91C_DATAFLASH_OK) |
| 405 | { |
| 406 | printf("F DF RD\n"); |
| 407 | return IMAGE_READ_FAILURE; |
| 408 | } |
| 409 | #if 0 |
| 410 | pAT91->CRC32((const unsigned char *)AT91C_BOOT_ADDR, |
| 411 | (unsigned int)SizeToDownload , (unsigned int *)&crc2); |
| 412 | crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) + |
| 413 | (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) + |
| 414 | (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) + |
| 415 | (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24); |
| 416 | |
| 417 | /* Restore the value of Vector 6 */ |
| 418 | *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = |
| 419 | *(int *)(AddressToDownload + SizeToDownload + 4); |
| 420 | |
| 421 | if (crc1 != crc2) { |
| 422 | printf("DF CRC bad %x != %x\n",crc1,crc2); |
| 423 | return IMAGE_CRC_ERROR; |
| 424 | } |
| 425 | #endif |
| 426 | return SUCCESS; |
| 427 | } |
| 428 | |
| 429 | static int AT91F_StartBoot(void) |
| 430 | { |
| 431 | int sts; |
| 432 | if((sts = AT91F_LoadBoot()) != SUCCESS) return sts; |
| 433 | // printf("\n"); |
| 434 | // printf("PLLA[180MHz], MCK[60Mhz] ==> Start UBOOT\n"); |
| 435 | if (AT91F_ResetRegisters()) |
| 436 | { |
| 437 | printf("Jump"); |
| 438 | Jump(AT91C_BOOT_ADDR); |
| 439 | // LED_blink(0); |
| 440 | } |
| 441 | return IMAGE_ERROR; |
| 442 | } |
| 443 | |
| 444 | #if 0 |
| 445 | static void AT91F_RepeatedStartBoot(void) |
| 446 | { |
| 447 | int i; |
| 448 | for(i = 0; i < CRC_RETRIES; i++) { |
| 449 | if(AT91F_StartBoot() != IMAGE_CRC_ERROR){ |
| 450 | // LED_blink(1); |
| 451 | return; |
| 452 | } |
| 453 | } |
| 454 | return; |
| 455 | } |
| 456 | #endif |
| 457 | |
| 458 | #define TRUE 1 |
| 459 | #define FALSE 0 |
| 460 | #define TRX_MAGIC 0x30524448 /* "HDR0" */ |
| 461 | #define TRX_VERSION 1 |
| 462 | |
| 463 | struct trx_header { |
| 464 | unsigned int magic; |
| 465 | unsigned int len; |
| 466 | unsigned int crc32; |
| 467 | unsigned int flag_version; |
| 468 | unsigned int offsets[3]; |
| 469 | }; |
| 470 | |
| 471 | #define AT91C_MCI_TIMEOUT 1000000 |
| 472 | |
| 473 | extern AT91S_MciDevice MCI_Device; |
| 474 | extern void AT91F_MCIDeviceWaitReady(unsigned int); |
| 475 | extern int AT91F_MCI_ReadBlockSwab(AT91PS_MciDevice, int, unsigned int *, int); |
| 476 | |
| 477 | int Program_From_MCI(void) |
| 478 | { |
| 479 | int i; |
| 480 | unsigned int Max_Read_DataBlock_Length; |
| 481 | int block = 0; |
| 482 | int buffer = AT91C_DOWNLOAD_BASE_ADDRESS; |
| 483 | int bufpos = AT91C_DOWNLOAD_BASE_ADDRESS; |
| 484 | int NbPage = 0; |
| 485 | struct trx_header *p; |
| 486 | |
| 487 | p = (struct trx_header *)bufpos; |
| 488 | |
| 489 | Max_Read_DataBlock_Length = MCI_Device.pMCI_DeviceFeatures->Max_Read_DataBlock_Length; |
| 490 | |
| 491 | AT91F_MCIDeviceWaitReady(AT91C_MCI_TIMEOUT); |
| 492 | |
| 493 | AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length); |
| 494 | |
| 495 | if (p->magic != TRX_MAGIC) { |
| 496 | printf("Inv IMG 0x%08x\n", p->magic); |
| 497 | return FALSE; |
| 498 | } |
| 499 | |
| 500 | printf("RDSD"); |
| 501 | AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC8 | AT91C_PIO_PC14; |
| 502 | for (i=0; i<(p->len/512); i++) { |
| 503 | AT91F_MCI_ReadBlockSwab(&MCI_Device, block*Max_Read_DataBlock_Length, (unsigned int *)bufpos, Max_Read_DataBlock_Length); |
| 504 | block++; |
| 505 | bufpos += Max_Read_DataBlock_Length; |
| 506 | } |
| 507 | |
| 508 | NbPage = 0; |
| 509 | i = dataflash_info[0].Device.pages_number; |
| 510 | while(i >>= 1) |
| 511 | NbPage++; |
| 512 | i = ((p->offsets[1] - p->offsets[0])/ 512) + 1 + (NbPage << 13) + (dataflash_info[0].Device.pages_size << 17); |
| 513 | *(int *)(buffer + p->offsets[0] + AT91C_OFFSET_VECT6) = i; |
| 514 | |
| 515 | printf(" WDFB"); |
| 516 | AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15 | AT91C_PIO_PC14; |
| 517 | AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8; |
| 518 | write_dataflash(0xc0000000, buffer + p->offsets[0], p->offsets[1] - p->offsets[0]); |
| 519 | printf(" WUB"); |
| 520 | AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC7 | AT91C_PIO_PC15; |
| 521 | AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC8 | AT91C_PIO_PC14; |
| 522 | write_dataflash(0xc0008000, buffer + p->offsets[1], p->offsets[2] - p->offsets[1]); |
| 523 | printf(" WKRFS"); |
| 524 | AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC15; |
| 525 | AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC14; |
| 526 | write_dataflash(0xc0042000, buffer + p->offsets[2], p->len - p->offsets[2]); |
| 527 | AT91C_BASE_PIOC->PIO_CODR = AT91C_PIO_PC8 | AT91C_PIO_PC14; |
| 528 | AT91C_BASE_PIOC->PIO_SODR = AT91C_PIO_PC7 | AT91C_PIO_PC15; |
| 529 | return TRUE; |
| 530 | } |
| 531 | |
| 532 | //*---------------------------------------------------------------------------- |
| 533 | //* Function Name : main |
| 534 | //* Object : Main function |
| 535 | //* Input Parameters : none |
| 536 | //* Output Parameters : True |
| 537 | //*---------------------------------------------------------------------------- |
| 538 | int main(void) |
| 539 | { |
| 540 | #ifdef XMODEM |
| 541 | AT91PS_Buffer pXmBuffer; |
| 542 | AT91PS_SvcComm pSvcXmodem; |
| 543 | #endif |
| 544 | AT91S_SvcTempo svcBootTempo; // Link to a AT91S_Tempo object |
| 545 | unsigned int ix; |
| 546 | volatile unsigned int AddressToDownload, SizeToDownload; |
| 547 | unsigned int DeviceAddress = 0; |
| 548 | char command = 0; |
| 549 | #ifdef XMODEM |
| 550 | volatile int i = 0; |
| 551 | unsigned int crc1 = 0, crc2 = 0; |
| 552 | volatile int device; |
| 553 | int NbPage; |
| 554 | #endif |
| 555 | volatile int Nb_Device = 0; |
| 556 | int mci_present = 0; |
| 557 | |
| 558 | pAT91 = AT91C_ROM_BOOT_ADDRESS; |
| 559 | |
| 560 | if (!AT91F_SetPLL()) |
| 561 | { |
| 562 | printf("F SetPLL"); |
| 563 | while(1); |
| 564 | } |
| 565 | |
| 566 | at91_init_uarts(); |
| 567 | |
| 568 | /* Tempo Initialisation */ |
| 569 | pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC)); |
| 570 | ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC)); |
| 571 | |
| 572 | // Attach the tempo to a tempo controler |
| 573 | ctlTempo.CtlTempoCreate(&ctlTempo, &svcBootTempo); |
| 574 | // LED_init(); |
| 575 | // LED_blink(2); |
| 576 | |
| 577 | #ifdef XMODEM |
| 578 | /* Xmodem Initialisation */ |
| 579 | pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer); |
| 580 | pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, |
| 581 | (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo); |
| 582 | pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer); |
| 583 | #endif |
| 584 | |
| 585 | /* System Timer initialization */ |
| 586 | AT91F_AIC_ConfigureIt( |
| 587 | AT91C_BASE_AIC, // AIC base address |
| 588 | AT91C_ID_SYS, // System peripheral ID |
| 589 | AT91C_AIC_PRIOR_HIGHEST, // Max priority |
| 590 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, // Level sensitive |
| 591 | AT91F_ST_ASM_HANDLER |
| 592 | ); |
| 593 | /* Enable ST interrupt */ |
| 594 | AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); |
| 595 | |
| 596 | #ifndef PRODTEST |
| 597 | /* Start tempo to start Boot in a delay of |
| 598 | * AT91C_DELAY_TO_BOOT sec if no key pressed */ |
| 599 | svcBootTempo.Start(&svcBootTempo, AT91C_DELAY_TO_BOOT, |
| 600 | 0, AT91F_StartBoot, NULL); |
| 601 | #endif |
| 602 | |
| 603 | while(1) |
| 604 | { |
| 605 | while(command == 0) |
| 606 | { |
| 607 | AddressToDownload = AT91C_DOWNLOAD_BASE_ADDRESS; |
| 608 | SizeToDownload = AT91C_DOWNLOAD_MAX_SIZE; |
| 609 | DeviceAddress = 0; |
| 610 | |
| 611 | /* try to detect Dataflash */ |
| 612 | if (!Nb_Device) |
| 613 | Nb_Device = AT91F_DataflashInit(); |
| 614 | |
| 615 | mci_present = AT91F_DisplayMenu(); |
| 616 | |
| 617 | #ifdef PRODTEST |
| 618 | if (mci_present) { |
| 619 | if (Program_From_MCI()) |
| 620 | AT91F_StartBoot(); |
| 621 | } |
| 622 | #endif |
| 623 | |
| 624 | message[0] = 0; |
| 625 | AT91F_ReadLine ("Enter: ", message); |
| 626 | |
| 627 | #ifndef PRODTEST |
| 628 | /* stop tempo ==> stop autoboot */ |
| 629 | svcBootTempo.Stop(&svcBootTempo); |
| 630 | #endif |
| 631 | |
| 632 | command = message[0]; |
| 633 | for(ix = 1; (message[ix] == ' ') && (ix < 12); ix++); // Skip some whitespace |
| 634 | |
| 635 | if(!AsciiToHex(&message[ix], &DeviceAddress) ) |
| 636 | DeviceAddress = 0; // Illegal DeviceAddress |
| 637 | |
| 638 | switch(command) |
| 639 | { |
| 640 | #ifdef XMODEM |
| 641 | case '1': |
| 642 | case '2': |
| 643 | case '5': |
| 644 | if(command == '1') { |
| 645 | DeviceAddress = 0xC0000000; |
| 646 | // printf("Download DataflashBoot.bin to [0x%x]\n", DeviceAddress); |
| 647 | } else if(command == '2') { |
| 648 | DeviceAddress = AT91C_BOOT_DATAFLASH_ADDR; |
| 649 | // printf("Download u-boot.bin to [0x%x]\n", DeviceAddress); |
| 650 | } else { |
| 651 | // printf("Download Dataflash to [0x%x]\n", DeviceAddress); |
| 652 | } |
| 653 | switch(DeviceAddress & 0xFF000000) |
| 654 | { |
| 655 | case CFG_DATAFLASH_LOGIC_ADDR_CS0: |
| 656 | if (dataflash_info[0].id == 0){ |
| 657 | printf("No DF"); |
| 658 | AT91F_WaitKeyPressed(); |
| 659 | command = 0; |
| 660 | } |
| 661 | |
| 662 | device = 0; |
| 663 | break; |
| 664 | |
| 665 | case CFG_DATAFLASH_LOGIC_ADDR_CS3: |
| 666 | if (dataflash_info[1].id == 0){ |
| 667 | printf("No DF"); |
| 668 | AT91F_WaitKeyPressed(); |
| 669 | command = 0; |
| 670 | } |
| 671 | device = 1; |
| 672 | break; |
| 673 | |
| 674 | default: |
| 675 | command = 0; |
| 676 | break; |
| 677 | } |
| 678 | break; |
| 679 | #endif |
| 680 | |
| 681 | case '3': |
| 682 | if (mci_present) |
| 683 | Program_From_MCI(); |
| 684 | command = 0; |
| 685 | break; |
| 686 | |
| 687 | case '4': |
| 688 | AT91F_StartBoot(); |
| 689 | command = 0; |
| 690 | break; |
| 691 | |
| 692 | #ifdef MEMDISP |
| 693 | case '6': |
| 694 | do |
| 695 | { |
| 696 | AT91F_MemoryDisplay(DeviceAddress, 256); |
| 697 | AT91F_ReadLine (NULL, message); |
| 698 | DeviceAddress += 0x100; |
| 699 | } |
| 700 | while(message[0] == '\0'); |
| 701 | command = 0; |
| 702 | break; |
| 703 | #endif |
| 704 | |
| 705 | case '7': |
| 706 | switch(DeviceAddress & 0xFF000000) |
| 707 | { |
| 708 | case CFG_DATAFLASH_LOGIC_ADDR_CS0: |
| 709 | break; |
| 710 | case CFG_DATAFLASH_LOGIC_ADDR_CS3: |
| 711 | break; |
| 712 | default: |
| 713 | command = 0; |
| 714 | break; |
| 715 | } |
| 716 | |
| 717 | if (command != 0) { |
| 718 | AT91F_ReadLine ("RDY ERA\nSure?", |
| 719 | message); |
| 720 | if(message[0] == 'Y' || message[0] == 'y') { |
| 721 | erase_dataflash(DeviceAddress & 0xFF000000); |
| 722 | // printf("Erase complete\n\n"); |
| 723 | } |
| 724 | // else |
| 725 | // printf("Erase aborted\n"); |
| 726 | } |
| 727 | command = 0; |
| 728 | |
| 729 | break; |
| 730 | |
| 731 | default: |
| 732 | command = 0; |
| 733 | break; |
| 734 | } |
| 735 | } |
| 736 | #ifdef XMODEM |
| 737 | for(i = 0; i <= AT91C_DOWNLOAD_MAX_SIZE; i++) |
| 738 | *(unsigned char *)(AddressToDownload + i) = 0; |
| 739 | |
| 740 | xmodemPipe.Read(&xmodemPipe, (char *)AddressToDownload, |
| 741 | SizeToDownload, XmodemProtocol, 0); |
| 742 | while(XmodemComplete !=1); |
| 743 | SizeToDownload = (unsigned int)((svcXmodem.pData) - |
| 744 | (unsigned int)AddressToDownload); |
| 745 | |
| 746 | /* Modification of vector 6 */ |
| 747 | if ((DeviceAddress == CFG_DATAFLASH_LOGIC_ADDR_CS0)) { |
| 748 | // Vector 6 must be compliant to the BootRom description (ref Datasheet) |
| 749 | NbPage = 0; |
| 750 | i = dataflash_info[device].Device.pages_number; |
| 751 | while(i >>= 1) |
| 752 | NbPage++; |
| 753 | i = (SizeToDownload / 512)+1 + (NbPage << 13) + |
| 754 | (dataflash_info[device].Device.pages_size << 17); //+4 to add crc32 |
| 755 | SizeToDownload = 512 * (i &0xFF); |
| 756 | } |
| 757 | else |
| 758 | { |
| 759 | /* Save the contents of vector 6 ==> will be restored |
| 760 | * at boot time (AT91F_StartBoot) */ |
| 761 | *(int *)(AddressToDownload + SizeToDownload + 4) = |
| 762 | *(int *)(AddressToDownload + AT91C_OFFSET_VECT6); |
| 763 | /* Modify Vector 6 to contain the size of the |
| 764 | * file to copy (Dataflash -> SDRAM)*/ |
| 765 | i = SizeToDownload; |
| 766 | } |
| 767 | |
| 768 | *(int *)(AddressToDownload + AT91C_OFFSET_VECT6) = i; |
| 769 | // printf("\nModification of Arm Vector 6 :%x\n", i); |
| 770 | |
| 771 | // printf("\nWrite %d bytes in DataFlash [0x%x]\n",SizeToDownload, DeviceAddress); |
| 772 | crc1 = 0; |
| 773 | pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc1); |
| 774 | |
| 775 | /* Add the crc32 at the end of the code */ |
| 776 | *(char *)(AddressToDownload + SizeToDownload) = (char)(crc1 & 0x000000FF); |
| 777 | *(char *)(AddressToDownload + SizeToDownload + 1) = (char)((crc1 & 0x0000FF00) >> 8); |
| 778 | *(char *)(AddressToDownload + SizeToDownload + 2) = (char)((crc1 & 0x00FF0000) >> 16); |
| 779 | *(char *)(AddressToDownload + SizeToDownload + 3) = (char)((crc1 & 0xFF000000) >> 24); |
| 780 | |
| 781 | /* write dataflash */ |
| 782 | write_dataflash (DeviceAddress, AddressToDownload, (SizeToDownload + 8)); |
| 783 | |
| 784 | /* clear the buffer before read */ |
| 785 | for(i=0; i <= SizeToDownload; i++) |
| 786 | *(unsigned char *)(AddressToDownload + i) = 0; |
| 787 | |
| 788 | /* Read dataflash to check the validity of the data */ |
| 789 | read_dataflash (DeviceAddress, (SizeToDownload + 4), (char *)(AddressToDownload)); |
| 790 | |
| 791 | printf("VFY: "); |
| 792 | crc2 = 0; |
| 793 | |
| 794 | pAT91->CRC32((const unsigned char *)AddressToDownload, SizeToDownload , &crc2); |
| 795 | crc1 = (int)(*(char *)(AddressToDownload + SizeToDownload)) + |
| 796 | (int)(*(char *)(AddressToDownload + SizeToDownload + 1) << 8) + |
| 797 | (int)(*(char *)(AddressToDownload + SizeToDownload + 2) << 16) + |
| 798 | (int)(*(char *)(AddressToDownload + SizeToDownload + 3) << 24); |
| 799 | |
| 800 | if (crc1 != crc2) |
| 801 | printf("ERR"); |
| 802 | else |
| 803 | printf("OK"); |
| 804 | |
| 805 | command = 0; |
| 806 | XmodemComplete = 0; |
| 807 | AT91F_WaitKeyPressed(); |
| 808 | #endif |
| 809 | } |
| 810 | } |
| 811 | |