BOOTLOADER
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
nand.c
Go to the documentation of this file.
1 /*
2  support 512/page NAND Flash only
3 */
4 #include <string.h>
5 
6 #include "def.h"
7 #include "2440addr.h"
8 #include "2440lib.h"
9 #include "2440slib.h"
10 #include "Nand.h"
11 
12 //suppport boot params
13 #define GLOBAL_PARAMS
14 #include "bootpara.h"
15 
16 #define puts Uart_Printf
17 #define printf Uart_Printf
18 #define getch Uart_Getch
19 #define putch Uart_SendByte
20 
21 #define EnNandFlash() (rNFCONT |= 1)
22 #define DsNandFlash() (rNFCONT &= ~1)
23 #define NFChipEn() (rNFCONT &= ~(1<<1))
24 #define NFChipDs() (rNFCONT |= (1<<1))
25 #define InitEcc() (rNFCONT |= (1<<4))
26 #define MEccUnlock() (rNFCONT &= ~(1<<5))
27 #define MEccLock() (rNFCONT |= (1<<5))
28 #define SEccUnlock() (rNFCONT &= ~(1<<6))
29 #define SEccLock() (rNFCONT |= (1<<6))
30 
31 #define WrNFDat8(dat) (rNFDATA8 = (dat))
32 #define WrNFDat32(dat) (rNFDATA = (dat))
33 #define RdNFDat8() (rNFDATA8) //byte access
34 #define RdNFDat32() (rNFDATA) //word access
35 
36 #define WrNFCmd(cmd) (rNFCMD = (cmd))
37 #define WrNFAddr(addr) (rNFADDR = (addr))
38 #define WrNFDat(dat) WrNFDat8(dat)
39 #define RdNFDat() RdNFDat8() //for 8 bit nand flash, use byte access
40 
41 #define RdNFMEcc() (rNFMECC0) //for 8 bit nand flash, only use NFMECC0
42 #define RdNFSEcc() (rNFSECC) //for 8 bit nand flash, only use low 16 bits
43 
44 #define RdNFStat() (rNFSTAT)
45 #define NFIsBusy() (!(rNFSTAT&1))
46 #define NFIsReady() (rNFSTAT&1)
47 
48 //#define WIAT_BUSY_HARD 1
49 //#define ER_BAD_BLK_TEST
50 //#define WR_BAD_BLK_TEST
51 
52 #define READCMD0 0
53 #define READCMD1 1
54 #define READCMD2 0x50
55 #define ERASECMD0 0x60
56 #define ERASECMD1 0xd0
57 #define PROGCMD0 0x80
58 #define PROGCMD1 0x10
59 #define QUERYCMD 0x70
60 #define RdIDCMD 0x90
61 
62 static U16 NandAddr;
63 
64 // HCLK=100Mhz
65 #define TACLS 1//7 // 1-clk(0ns)
66 #define TWRPH0 4//7 // 3-clk(25ns)
67 #define TWRPH1 1//7 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
68 
69 static void InitNandCfg(void)
70 {
71 
72  rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
73 
74  rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
75 
76 }
77 
78 #ifdef WIAT_BUSY_HARD
79 #define WaitNFBusy() while(NFIsBusy())
80 #else
81 static U32 WaitNFBusy(void) // R/B 未接好?
82 {
83  U8 stat;
84 
86  do {
87  stat = RdNFDat();
88  //printf("%x\n", stat);
89  }while(!(stat&0x40));
91  return stat&1;
92 }
93 #endif
94 
95 static U32 ReadChipId(void)
96 {
97  U32 id;
98 
99  NFChipEn();
100  WrNFCmd(RdIDCMD);
101  WrNFAddr(0);
102  while(NFIsBusy());
103  id = RdNFDat()<<8;
104  id |= RdNFDat();
105  NFChipDs();
106 
107  return id;
108 }
109 
110 static U16 ReadStatus(void)
111 {
112  U16 stat;
113 
114  NFChipEn();
115  WrNFCmd(QUERYCMD);
116  stat = RdNFDat();
117  NFChipDs();
118 
119  return stat;
120 }
121 
122 static U32 EraseBlock(U32 addr)
123 {
124  U8 stat;
125 
126  addr &= ~0x1f;
127 
128  NFChipEn();
129  WrNFCmd(ERASECMD0);
130  WrNFAddr(addr);
131  WrNFAddr(addr>>8);
132  if(NandAddr)
133  WrNFAddr(addr>>16);
134  WrNFCmd(ERASECMD1);
135  stat = WaitNFBusy();
136  NFChipDs();
137 
138 #ifdef ER_BAD_BLK_TEST
139  if(!((addr+0xe0)&0xff)) stat = 1; //just for test bad block
140 #endif
141 
142  putch('.');
143  //printf("Erase block 0x%x %s\n", addr, stat?"fail":"ok");
144 
145  return stat;
146 }
147 
148 //addr = page address
149 static void ReadPage(U32 addr, U8 *buf)
150 {
151  U16 i;
152 
153  NFChipEn();
154  WrNFCmd(READCMD0);
155  WrNFAddr(0);
156  WrNFAddr(addr);
157  WrNFAddr(addr>>8);
158  if(NandAddr)
159  WrNFAddr(addr>>16);
160  InitEcc();
161  WaitNFBusy();
162  for(i=0; i<512; i++)
163  buf[i] = RdNFDat();
164  NFChipDs();
165 }
166 
167 static U32 WritePage(U32 addr, U8 *buf)
168 {
169  U32 i, mecc;
170  U8 stat, tmp[7];
171 
172 
173  NFChipEn();
174  WrNFCmd(PROGCMD0);
175  WrNFAddr(0);
176  WrNFAddr(addr);
177  WrNFAddr(addr>>8);
178  if(NandAddr)
179  WrNFAddr(addr>>16);
180  InitEcc(); //reset mecc and secc
181  MEccUnlock();
182  for(i=0; i<512; i++)
183  WrNFDat(buf[i]);
184  MEccLock();
185 
186  mecc = RdNFMEcc();
187 
188  tmp[0] = mecc&0xff;
189  tmp[1] = (mecc>>8)&0xff;
190  tmp[2] = (mecc>>16)&0xff;
191  tmp[3] = (mecc>>24)&0xff;
192  tmp[5] = 0xff; //mark good block
193 
194  SEccUnlock();
195  WrNFDat(tmp[0]);
196  WrNFDat(tmp[1]);
197  WrNFDat(tmp[2]);
198  WrNFDat(tmp[3]);
199  SEccLock();
200  WrNFDat(tmp[4]);
201  WrNFDat(tmp[5]);
202 
203  WrNFCmd(PROGCMD1);
204  stat = WaitNFBusy();
205  NFChipDs();
206 
207 #ifdef WR_BAD_BLK_TEST
208  if((addr&0xff)==0x17) stat = 1; //just for test bad block
209 #endif
210 
211  if(stat)
212  printf("Write nand flash 0x%x fail\n", addr);
213  else {
214  U8 RdDat[512];
215 
216  ReadPage(addr, RdDat);
217  for(i=0; i<512; i++)
218  if(RdDat[i]!=buf[i]) {
219  printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
220  stat = 1;
221  break;
222  }
223  }
224 
225  return stat;
226 }
227 
228 static void MarkBadBlk(U32 addr)
229 {
230  addr &= ~0x1f;
231 
232  NFChipEn();
233 
234  WrNFCmd(READCMD2); //point to area c
235 
236  WrNFCmd(PROGCMD0);
237  WrNFAddr(4); //mark offset 4,5,6,7
238  WrNFAddr(addr);
239  WrNFAddr(addr>>8);
240  if(NandAddr)
241  WrNFAddr(addr>>16);
242  WrNFDat(0); //mark with 0
243  WrNFDat(0);
244  WrNFDat(0); //mark with 0
245  WrNFDat(0);
246  WrNFCmd(PROGCMD1);
247  WaitNFBusy(); //needn't check return status
248 
249  WrNFCmd(READCMD0); //point to area a
250 
251  NFChipDs();
252 }
253 
254 static int CheckBadBlk(U32 addr)
255 {
256  U8 dat;
257 
258  addr &= ~0x1f;
259 
260  NFChipEn();
261 
262  WrNFCmd(READCMD2); //point to area c
263  WrNFAddr(5); //mark offset 4,5,6,7
264  WrNFAddr(addr);
265  WrNFAddr(addr>>8);
266  if(NandAddr)
267  WrNFAddr(addr>>16);
268  WaitNFBusy();
269  dat = RdNFDat();
270 
271  WrNFCmd(READCMD0); //point to area a
272 
273  NFChipDs();
274 
275  return (dat!=0xff);
276 }
277 
278 /************************************************************/
279 struct Partition{
282  char *name;
283 };
284 
285 static struct Partition NandPart[] = {
286  {0, 0x00030000, "boot"}, //256K
287  {0x00030000, 0x001d0000, "kernel"},
288  {0x00200000, 0x01e00000, "rootfs"}, //30M
289  {0x02000000, 0x02000000, "ext-fs1"}, //32M
290  {0, 0 , 0}
291 };
292 
293 static U32 StartPage, BlockCnt;
294 extern U32 downloadAddress;
295 extern U32 downloadFileSize;
296 
297 
298 static int NandSelPart(char *info)
299 {
300  U16 i, max_sel;
301  struct Partition *ptr = NandPart;
302 
303  printf("Please select which region to %s : Esc to abort\n", info);
304 
305  for(i=0; ptr->size!=0; i++, ptr++)
306  printf("%d : offset 0x%-8x, size 0x%-8x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
307 
308  max_sel = i;
309 
310  while(1) {
311  i = getch();
312  if(i==0x1b)
313  return -1;
314  if((i>='0')&&(i<(max_sel+'0'))) {
315  i -= '0';
316  StartPage = NandPart[i].offset>>9;
317  BlockCnt = NandPart[i].size>>14;
318  return i;
319  }
320  }
321 }
322 
323 static void WrFileToNF(void)
324 {
325  int nf_part, i ,size, skip_blks;
326  U32 ram_addr;
327 
328  nf_part = NandSelPart("write");
329  if(nf_part<0)
330  return;
331 
332  if(downloadFileSize>NandPart[nf_part].size) {
333  puts("Download file size is more large than selected partition size!!!\n");
334 // return;
335  }
336 
337  printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d\n", StartPage, downloadAddress, downloadFileSize);
338  puts("Are you sure? [y/n]\n");
339  while(1) {
340  char c = getch();
341  if((c=='y')||(c=='Y'))
342  break;
343  if((c=='n')||(c=='N'))
344  return;
345  }
346 
347  skip_blks = 0;
348  ram_addr = downloadAddress;
349  size = downloadFileSize;
350  for(i=0; size>0; ) {
351  if(!(i&0x1f)) {
352  if(EraseBlock(i+StartPage)) {
353  NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
354  if(downloadFileSize>NandPart[nf_part].size) {
355  puts("Program nand flash fail\n");
356  return;
357  }
358  MarkBadBlk(i+StartPage);
359  skip_blks++;
360  i += 32;
361  continue;
362  }
363  }
364  if(WritePage(i+StartPage, (U8 *)ram_addr)) {
365  ram_addr -= (i&0x1f)<<9;
366  size += (i&0x1f)<<9;
367  i &= ~0x1f;
368  NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
369  if(downloadFileSize>NandPart[nf_part].size) {
370  puts("Program nand flash fail\n");
371  return;
372  }
373  MarkBadBlk(i+StartPage);
374  skip_blks++;
375  i += 32;
376  continue;
377  }
378  ram_addr += 512;
379  size -= 512;
380  i++;
381  }
382 
383  puts("Program nand flash partition success\n");
384  if(skip_blks)
385  printf("Skiped %d bad block(s)\n", skip_blks);
386 }
387 
388 #define LINUX_PAGE_SHIFT 12
389 #define LINUX_PAGE_SIZE (1<<LINUX_PAGE_SHIFT)
390 #define COMMAND_LINE_SIZE 1024
391 
392 struct param_struct {
393  union {
394  struct {
395  unsigned long page_size; /* 0 */
396  unsigned long nr_pages; /* 4 */
397  unsigned long ramdisk_size; /* 8 */
398  unsigned long flags; /* 12 */
399 #define FLAG_READONLY 1
400 #define FLAG_RDLOAD 4
401 #define FLAG_RDPROMPT 8
402  unsigned long rootdev; /* 16 */
403  unsigned long video_num_cols; /* 20 */
404  unsigned long video_num_rows; /* 24 */
405  unsigned long video_x; /* 28 */
406  unsigned long video_y; /* 32 */
407  unsigned long memc_control_reg; /* 36 */
408  unsigned char sounddefault; /* 40 */
409  unsigned char adfsdrives; /* 41 */
410  unsigned char bytes_per_char_h; /* 42 */
411  unsigned char bytes_per_char_v; /* 43 */
412  unsigned long pages_in_bank[4]; /* 44 */
413  unsigned long pages_in_vram; /* 60 */
414  unsigned long initrd_start; /* 64 */
415  unsigned long initrd_size; /* 68 */
416  unsigned long rd_start; /* 72 */
417  unsigned long system_rev; /* 76 */
418  unsigned long system_serial_low; /* 80 */
419  unsigned long system_serial_high; /* 84 */
420  unsigned long mem_fclk_21285; /* 88 */
421  } s;
422  char unused[256];
423  } u1;
424  union {
425  char paths[8][128];
426  struct {
427  unsigned long magic;
428  char n[1024 - sizeof(unsigned long)];
429  } s;
430  } u2;
432 };
433 
434 extern void call_linux(U32 a0, U32 a1, U32 a2);
435 
436 /*************************************************************/
437 static __inline void cpu_arm920_cache_clean_invalidate_all(void)
438 {
439  __asm{
440  mov r1, #0
441  mov r1, #7 << 5 /* 8 segments */
442 cache_clean_loop1:
443  orr r3, r1, #63UL << 26 /* 64 entries */
444 cache_clean_loop2:
445  mcr p15, 0, r3, c7, c14, 2 /* clean & invalidate D index */
446  subs r3, r3, #1 << 26
447  bcs cache_clean_loop2 /* entries 64 to 0 */
448  subs r1, r1, #1 << 5
449  bcs cache_clean_loop1 /* segments 7 to 0 */
450  mcr p15, 0, r1, c7, c5, 0 /* invalidate I cache */
451  mcr p15, 0, r1, c7, c10, 4 /* drain WB */
452  }
453 }
455 {
456  cpu_arm920_cache_clean_invalidate_all();
457 }
458 
459 static __inline void cpu_arm920_tlb_invalidate_all(void)
460 {
461  __asm{
462  mov r0, #0
463  mcr p15, 0, r0, c7, c10, 4 /* drain WB */
464  mcr p15, 0, r0, c8, c7, 0 /* invalidate I & D TLBs */
465  }
466 }
467 
468 void tlb_invalidate(void)
469 {
470  cpu_arm920_tlb_invalidate_all();
471 }
472 
473 void disable_irq(void);
474 
475 void call_linux(U32 a0, U32 a1, U32 a2)
476 {
477  void (*goto_start)(U32, U32);
478 
480 
482  tlb_invalidate();
483 
484  __asm{
485 // mov r0, a0//%0
486 // mov r1, a1//%1
487 // mov r2, a2//%2
488  mov ip, #0
489  mcr p15, 0, ip, c13, c0, 0 /* zero PID */
490  mcr p15, 0, ip, c7, c7, 0 /* invalidate I,D caches */
491  mcr p15, 0, ip, c7, c10, 4 /* drain write buffer */
492  mcr p15, 0, ip, c8, c7, 0 /* invalidate I,D TLBs */
493  mrc p15, 0, ip, c1, c0, 0 /* get control register */
494  bic ip, ip, #0x0001 /* disable MMU */
495  mcr p15, 0, ip, c1, c0, 0 /* write control register */
496  //mov pc, r2
497  //nop
498  //nop
499  /* no outpus */
500  //: "r" (a0), "r" (a1), "r" (a2)
501  }
502 // SetClockDivider(1, 1);
503 // SetSysFclk(FCLK_200M); //start kernel, use 200M
504  //SET_IF();
505  goto_start = (void (*)(U32, U32))a2;
506  (*goto_start)(a0, a1);
507 }
508 
509 extern int sprintf(char * /*s*/, const char * /*format*/, ...);
510 
511 static void LoadRun(void)
512 {
513  U32 i, ram_addr, buf = 0x30245bd0;
514  struct param_struct *params = (struct param_struct *)0x30000100;
515  int size;
516 
517  char *boot_params = "root=/dev/mtdblock2 init=/linuxrc load_ramdisk=0 console=ttySAC1,115200 mem=65536K devfs=mount display=shp480";
518 
519  StartPage = NandPart[1].offset>>9;
520  size = NandPart[1].size;
521  ram_addr = buf;
522 
523  for(i=0; size>0; ) {
524  if(!(i&0x1f)) {
525  if(CheckBadBlk(i+StartPage)) {
526  printf("Skipped bad block at 0x%x\n", i+StartPage);
527  i += 32;
528  size -= 32<<9;
529  continue;
530  }
531  }
532  ReadPage((i+StartPage), (U8 *)ram_addr);
533  i++;
534  size -= 512;
535  ram_addr += 512;
536  }
537  DsNandFlash();
538 
539  for(i=0; i<(sizeof(struct param_struct)>>2); i++)
540  ((U32 *)params)[i] = 0;
541  params->u1.s.page_size = LINUX_PAGE_SIZE;
542  params->u1.s.nr_pages = (0x04000000 >> LINUX_PAGE_SHIFT);
543  for(i=0; boot_params[i]; i++)
544  params->commandline[i] = boot_params[i];
545 
546  puts("Set boot params = ");
547  puts(boot_params);
548  putch('\n');
549  call_linux(0, 362, buf);
550  //call_linux(0, boot_params.machine.val, buf);
551 }
552 
553 /************************************************************/
554 static int have_nandflash;
555 static void InitNandFlash(int info)
556 {
557  U32 i;
558 
559  InitNandCfg();
560  i = ReadChipId();
561  if(info)
562  printf("Read chip id = %x\n", i);
563  if((i==0x9873)||(i==0xec75))
564  NandAddr = 0;
565  else if(i==0xec76)
566  NandAddr = 1;
567  else {
568  if(info)
569  puts("Chip id error!!!\n");
570  have_nandflash = 0;
571  return;
572  }
573  have_nandflash = 1;
574  if(info)
575  printf("Nand flash status = %x\n", ReadStatus());
576 }
577 
578 void NandErase(void)
579 {
580  int i, err = 0;
581 
582  InitNandFlash(1);
583  if(!have_nandflash)
584  return;
585 
586  i = NandSelPart("erase");
587  if(i<0)
588  return;
589 
590  printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartPage, BlockCnt);
591  while(1) {
592  char c;
593 
594  c = getch();
595  if((c=='y')||(c=='Y'))
596  break;
597  if((c=='n')||(c=='N'))
598  return;
599  }
600 
601  for(i=0; BlockCnt; BlockCnt--, i+=32) {
602  if(EraseBlock(i+StartPage)) {
603  err ++;
604  puts("Press any key to continue...\n");
605  getch();
606  }
607  }
608 
609  DsNandFlash(); //disable nand flash interface
610  puts("Erase Nand partition completed ");
611  if(err)
612  printf("with %d bad block(s)\n", err);
613  else
614  puts("success\n");
615 }
616 
617 void NandWrite(void)
618 {
619  InitNandFlash(1);
620  if(!have_nandflash)
621  return;
622  WrFileToNF();
623  DsNandFlash(); //disable nand flash interface
624 }
625 
626 extern MemoryTest(void);
627 int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);
628 
629 static void LoadRunWince(void)
630 {
631  U32 i, ram_addr, buf = boot_params.initrd_addr.val;
632  int size;
633  MemoryTest();
634  printf("Load Kernel...\n");
635 
636  if(boot_params.osstor.val) //load program from NOR or NAND FLASH
637  memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x00fe0000);
638  else {
639  StartPage = NandPart[boot_params.start.val].offset>>9; //part 2,3...
640  size = boot_params.initrd_len.val;//NandPart[boot_params.root_sel.val].size;
641  ram_addr = buf;
642 
643  for(i=0; size>0; ) {
644  if(!(i&0x1f)) {
645  if(CheckBadBlk(i+StartPage)) {
646  printf("Skipped bad block at 0x%x\n", i+StartPage);
647  i += 32;
648  //size -= 32<<9;
649  continue;
650  }
651  }
652  ReadPage((i+StartPage), (U8 *)ram_addr);
653  i++;
654  size -= 512;
655  ram_addr += 512;
656  }
657  }
658 
659  printf("run 0x%08x...\n", boot_params.run_addr.val);
660  //RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
661  call_linux(0, 0, boot_params.run_addr.val);
662 }
663 
664 void NandLoadRun(void)
665 {
666  InitNandFlash(1);
667  //if(!have_nandflash)
668  // return;
669  //if(boot_params.start.val<2) //linux
670  LoadRun();
671  //LoadRunWince();
672 }
673 
674 /*
675 void TestNandFlash(void)
676 {
677  InitNandFlash();
678 
679  while(1)
680  {
681  U8 key = '2';
682 
683  puts("\nNand flash operations, press ESC to exit\n");
684  puts("1.Write nand flash with download file\n");
685  puts("2.Load progam from nand flash and run\n");
686  puts("3.Erase nand flash partition\n");
687  puts("4.Test nand flash erase, write, read\n");
688 
689  key = getch();
690 
691  if(key==0x1b)
692  goto TestNandExit;
693  else if(key=='1')
694  WrFileToNF();
695  else if(key=='2')
696  LoadRun();
697  else if(key=='3')
698  NandErase();
699  else if(key=='4')
700  TestFunc();
701  }
702 TestNandExit:
703  DsNandFlash(); //disable nand flash interface
704 }*/
705 
706 #include "norflash.h"
707 #define NOR_PARAMS_OFFSET 0x1c000
708 
709 int search_params(void)
710 {
711  U32 page, page_cnt;
712  U8 dat[528];
713  BootParams *pBP = (BootParams *)dat;
714  int ret=-1;
715 
716  InitNandFlash(0); //don't show info in InitNandFlash!
717  if(have_nandflash) {
718  page = NandPart[0].offset>>9;
719  page_cnt = NandPart[0].size>>9;
720 
721  //search from the last page
722  while(page_cnt--) {
723  ReadPage(page+page_cnt, dat);
724  if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) {
725  ret = 0;
726  break;
727  }
728  }
729  } else {
730  memcpy(dat, (void *)(NOR_PARAMS_OFFSET), 512); //now mmu is not set, so use original address
731  if(!strncmp(boot_params.start.flags, pBP->start.flags, 10))
732  ret = 0;
733  }
734 
735  DsNandFlash();
736 
737  if(!ret) {
738  ParamItem *pPIS = &pBP->start, *pPID = &boot_params.start;
739 
740  for(; pPID<=&boot_params.user_params; pPIS++, pPID++)
741  if(!strncmp(pPID->flags, pPIS->flags, sizeof(pPID->flags)))
742  pPID->val = pPIS->val;
743  strncpy(boot_params.string, pPIS->flags, boot_params.user_params.val+1);
744 
745  if(boot_params.user_params.val!=strlen(pPID->flags)) {
746  memset(boot_params.string, 0, sizeof(boot_params.string));
747  boot_params.user_params.val = 0;
748  }
749  } else {
750  //printf("Fail to find boot params! Use Default parameters.\n");
751  //don't printf anything before serial initialized!
752  }
753 
754  return ret;
755 }
756 
757 //保存在最后两个block,应确保程序(包括出现坏块时)不会覆盖到最后两块
758 int save_params(void)
759 {
760  U32 page, page_cnt;
761  U8 dat[0x20000];
762  int ret = 0;
763 
764  InitNandFlash(1);
765  have_nandflash=1;
766  if(have_nandflash) {
767  memset(dat, 0, sizeof(boot_params));
768  memcpy(dat, &boot_params, sizeof(boot_params));
769 
770  page = (NandPart[1].offset>>9)-64;
771 
772  for(page_cnt=0; page_cnt<64; page_cnt++) {
773  if(!(page_cnt%32))
774  EraseBlock(page);
775  if(!WritePage(page+page_cnt, dat))
776  break;
777  }
778  if(page_cnt>=64)
779  ret = -1;
780  printf("Save boot params %s.\n", ret?"fail":"success");
781  } else {
782  memcpy(dat, (void *)0x04000000, NOR_PARAMS_OFFSET);
783  memcpy(dat+NOR_PARAMS_OFFSET, &boot_params, sizeof(boot_params));
784  ProgNorFlash(0, (U32)dat, sizeof(dat)); //28F128
785  }
786 
787  DsNandFlash();
788 
789  return ret;
790 }
791 
792 int set_params(void)
793 {
794  int i, key, chg=0;
795  int lcd_type;
796  char *string;
797  ParamItem *pPID;
798 
799  printf("\nConfig parameters\n");
800 
801  do {
802  pPID = &boot_params.start;
803  for(i=0; pPID<=&boot_params.user_params; pPID++, i++)
804  printf("[%d] : %s%-8s is 0x%08x (%d)\n",
805  i, (i>9)?"":" ", pPID->flags, pPID->val, pPID->val);
806  printf("[%d] : Exit\n", i);
807  if(boot_params.user_params.val)
808  printf("User parameters is : \"%s\"\n", boot_params.string);
809 
810  printf("\nplease select item:");
811  key = Uart_GetIntNum();
812  if(key>=0&&key<i) {
813  chg = 1;
814  printf("please enter value:");
815  i = key;
816  if((&boot_params.start + i)==&boot_params.user_params) {
817  //确保输入的字节数不超过127!
818  printf("\n");
819  printf("1: display 240x320\n");
820  printf("2: display 320x240\n");
821  printf("3: display 480x272\n");
822  printf("4: display 640x480\n");
823 
824  lcd_type = Uart_GetIntNum();
825 
826  switch(lcd_type)
827  {
828  case 1:
829  string = "display=shp240";
830  strncpy(boot_params.string, string,strlen(string)+1);
831  strncpy(boot_params.string, string,strlen(string)+1);
832 
833  break;
834  case 2:
835  string = "display=shp320";
836  strncpy(boot_params.string, string,strlen(string)+1);
837  boot_params.user_params.val = strlen(string);
838  break;
839  case 3:
840  string = "display=shp480";
841  strncpy(boot_params.string, string,strlen(string)+1);
842  boot_params.user_params.val = strlen(string);
843  break;
844  case 4:
845  string = "display=shp640";
846  strncpy(boot_params.string, string,strlen(string)+1);
847  boot_params.user_params.val = strlen(string);
848  break;
849  default:
850  break;
851  }
852  //strncpy(boot_params.string, cmd, strlen(cmd)+1);
853  //boot_params.user_params.val = strlen(string);
854  }
855 #if 0
856  if((&boot_params.start + i)==&boot_params.user_params) {
857  //确保输入的字节数不超过127!
858  char cmd[128];
859  memset(cmd, 0, sizeof(cmd));
860  Uart_GetString(cmd);
861  strncpy(boot_params.string, cmd, strlen(cmd)+1);
862  boot_params.user_params.val = strlen(cmd);
863  }
864 
865  else if(&boot_params.start + i) == &boot_params.lcd)
866  {
867  printf("1. lcd 240x320\n");
868  printf("2. lcd 320x240\n");
869  printf("3. lcd 480x272\n");
870  printf("4. lcd 640x480\n");
871  lcd_type = Uart_GetIntNum();
872 
873  switch(lcd_type)
874  {
875  case 1:
876  string = "display=shp240";
877  break;
878  case 2:
879  string = "display=shp320";
880  break;
881  case 3:
882  string = "display=shp480";
883  break;
884  case 4:
885  string = "display=shp640";
886  break;
887  default:
888  string = "display=shp240";
889  break;
890  }
891  strncpy(boot_params.string, string,strlen(string)+1);
892 
893  boot_params.lcd.val= lcd_type;
894  }
895 #endif
896  else
897  {
898  key = Uart_GetIntNum();
899  (&boot_params.start + i)->val = key;
900  }
901  } else
902  break;
903  } while(1);
904 
905  if(chg) {
906  printf("Do you want to save parameters? press y or Y for save.\n");
907  key = getch();
908  if(key=='y'||key=='Y')
909  save_params();
910  }
911 
912  return 0;
913 }
914