bootloader---14.nand flash 读取bootloader

 一、 TQ2440上的nand flash是K9F2G08U0B


1.1 Page Block Device三者的关系(见datasheet P6)

1Page = (2k+64)Bytes

1Block = 64*Pages = 64*(2K+64)Byte=(128K+4k)Byte

1Device = 2048*Blocks = 2048*(64*Pages)Bytes

1.2 nand flash初始化

对于K9F2G08U0A的初始化,几乎所有的帖子都说:需要TACLS+TWRPH0+TWRPH1>=46ns, (其中TACLS = tCLS(12)+tALS(12)  TWRPH0 = tWP(12)  TWRPH1 = tCLH(5)+tALH(5)),所以TACLS =0,TWRPH0=3,TWRPH1=0, TACLS +TWRPH0+TWRPH1=50ns,满足要求。

但是修改nand flash的初始化配置:将TACLS=0;TWRPH0=1;TWRPH1=0; 也是正常的。但是TACLS=0;TWRPH0=0;TWRPH1=1;就不正常了。这三者需要满足的关系十分不解,还望高手指教。

1.3 读取数据时地址的发送

从K9F2G08X0B 电路图中可以看出:

        

NCON = 1 ; // 1: Advance NAND flash(1KWords/2KBytes page size, 4/5 address cycle)

GPG13 = 1 ; // 1: Page=2KBytes(NCON = 1)

GPG14 = 1 ;  // 1: 5 address cycle(NCON = 1)

GPG15 = 0 ;  // 0: 8-bit bus width

从上述硬件连接中可以看出,需要5个时钟周期才发送一个完整的地址。

上图中column address(A0-A11 12位) Row Address(A12-A28 17位)

column address:

    即页内的地址(0-2112) 1Page=(2k+64)Bytes,所以需要12位,但实际上不访问后面64个字节的,所以只需要11位即可

Row Address:

    页地址,一共有2048*64=0x20000个页,需要17位指定。

二、代码

root@ubuntu:~/myboot# tree

.├── main.c├── Makefile├── nand.c├── sdram.c├── start.S└── u-boot.lds

2.1 start.S

点击(此处)折叠或打开

  1. .text
  2. .global _start
  3. _start:
  4. _TEXT_BASE:
  5.     .word 0x33d80000

  6. .globl _armboot_start
  7. _armboot_start:
  8.     .word _start

  9.     ldr r0, =0x53000000    
  10.     mov r1, #0x0
  11.     str r1, [r0]

  12. #define COCKTIME    0x4C000000    
  13. #define MPLLCON        0x4C000004
  14. #define UPLLCON        0x4C000008
  15. #define CLKCON        0x4C00000C
  16. #define CLKSLOW        0x4C000010
  17. #define CLKDIVN     0x4C000014
  18. #define CAMDIVN     0x4C000018
  19.     /*FCLK:HCLK:PCLK=1:4:8*/
  20.     ldr r0, =CLKDIVN
  21.     mov r1, #0x05
  22.     str r1, [r0]

  23.     mrc p15, 0, r0, c1, c0, 0
  24.     orr r0, r0, #0xc0000000
  25.     mcr p15, 0, r0, c1, c0,0

  26.     /*MPLL=(2*m*Fin)/(P*(1<<s)), m="(MDIV+8)," p="PDIV+2" s="SDIV*/
  27.     ldr r0, =MPLLCON
  28.     ldr r1, =((0x5C<<12)|(0x01<<4)|(0x01))
  29.     str r1, [r0]
  30.     
  31.     ldr r0, =0x10000
  32. 1:
  33.     sub r0, r0, #1
  34.     bne 1b

  35.     /*UPLL=(m*Fin)/(P*(1<<s)), m="(MDIV+8)," p="(PDIV+2)," s="SDIV*/
  36.     ldr r0, =UPLLCON
  37.     ldr r1, =((0x10<<12)|(0x01<<4)|(0x01))
  38.     str r1, [r0]

  39.     ldr r0, =0x10000
  40. 1:
  41.     sub r0, r0, #1
  42.     bne 1b

  43.     ldr sp, =1024*4
  44.     bl init_sdram

  45.     /*设置栈指向内存地址 (0x33d80000+128k)*/
  46.     ldr sp, =0x33dA0000

  47.     /*dest=0x33d80000 src=0x0 size=16k*/
  48.     bl nand_init ;初始化nand flash
  49.     ldr r0, =0x33d80000
  50.     mov r1, #0x0
  51.     ldr r2, =1024*16
  52.     bl nand_read_page ;将nand flash上的boot读到内存0x33d80000处,大小为16k
  53.     
  54.     ldr pc, _main ;跳转到内存中的main中执行
  55. loop:
  56.     b loop
  57. _main: .word main
2.2 nand.c


点击(此处)折叠或打开

  1. #define NFCONF          (*(volatile unsigned int *) 0x4E000000)
  2. #define NFCONT          (*(volatile unsigned int *) 0x4E000004)
  3. #define NFCMMD          (*(volatile unsigned int *) 0x4E000008)
  4. #define NFADDR          (*(volatile unsigned int *) 0x4E00000C)
  5. #define NFDATA          (*(volatile unsigned char *) 0x4E000010) //注意:类型char
  6. #define NFMECCD0      (*(volatile unsigned int *) 0x4E000014)
  7. #define NFMECCD1      (*(volatile unsigned int *) 0x4E000018)
  8. #define NFSECCD      (*(volatile unsigned int *) 0x4E00001C)
  9. #define NFSTAT          (*(volatile unsigned int *) 0x4E000020)
  10. #define NFESTAT0      (*(volatile unsigned int *) 0x4E000024)
  11. #define NFESTAT1      (*(volatile unsigned int *) 0x4E000028)
  12. #define NFMECC0      (*(volatile unsigned int *) 0x4E00002C)
  13. #define NFMECC1      (*(volatile unsigned int *) 0x4E000030)
  14. #define NFMECC          (*(volatile unsigned int *) 0x4E000034)
  15. #define NFSBLK          (*(volatile unsigned int *) 0x4E000038)
  16. #define NFEBLK          (*(volatile unsigned int *) 0x4E00003C)

  17. /*nand command */
  18. #define NAND_CMD_RESET     0xFF

  19. #define NAND_PAGE_SIZE    2048
  20. #define NAND_PAGE_MASK    (NAND_PAGE_SIZE-1)

  21. static void nand_chip_select(void)
  22. {
  23.     int i;
  24.     NFCONT &= ~(1<<1);
  25.     for(i=0; i<10; i++);
  26. }

  27. static void nand_chip_deselect(void)
  28. {
  29.     NFCONT |= (1<<1);
  30. }

  31. static void nand_write_cmd(unsigned char cmd)
  32. {
  33.     NFCMMD = cmd;
  34. }

  35. static void nand_write_addr(unsigned int addr)
  36. {
  37.     int col, page;
  38.     int i;
  39.     col = addr & NAND_PAGE_MASK;
  40.     page = addr / NAND_PAGE_SIZE;
  41.     
  42.     NFADDR = col & 0xff;            /* Column Address A0~A7 */
  43.     for(i=0; i<10; i++);        
  44.     NFADDR = (col >> 8) & 0x0f;        /* Column Address A8~A11 */
  45.     for(i=0; i<10; i++);
  46.     NFADDR = page & 0xff;            /* Row Address A12~A19 */
  47.     for(i=0; i<10; i++);
  48.     NFADDR = (page >> 8) & 0xff;    /* Row Address A20~A27 */
  49.     for(i=0; i<10; i++);
  50.     NFADDR = (page >> 16) & 0x03;    /* Row Address A28~A29 */
  51.     for(i=0; i<10; i++);
  52. }

  53. static void nand_wait_idle(void)
  54. {
  55.     while( !(NFSTAT & 0x01))
  56.         ;
  57. }

  58. static void nand_reset(void)
  59. {
  60.     nand_chip_select();
  61.     nand_write_cmd(NAND_CMD_RESET);
  62.     nand_wait_idle();
  63.     nand_chip_deselect();
  64. }

  65. static unsigned char nand_read_byte(void)
  66. {
  67.     return (NFDATA&0xFF);
  68. }

  69. void nand_init(void)
  70. {
  71. #define TACLS    0x0
  72. #define TWRPH0     0x03
  73. #define TWRPH1     0x0
  74.     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
  75.     NFCONT = (0x01<<4)|(0x01<<1)|(0x01<<0);
  76.     nand_reset(); //初次使用时要先复位一下
  77. }

  78. /*调用这个函数时要保证size是按页对齐的*/
  79. void nand_read_page(unsigned char * dest_addr, unsigned long src_addr, unsigned int size)
  80. {
  81.     int i,j;

  82.     NFCONT &= ~(1<<1);
  83.     for(i=0; i<10; i++);
  84.     for(i=0; i<size (nand_page_size);="" i++)="" <="" li="" style="word-wrap: break-word;">
  85.     {
  86.         nand_write_cmd(0x00);
  87.         nand_write_addr(src_addr+i*NAND_PAGE_SIZE);
  88.         nand_write_cmd(0x30);
  89.         nand_wait_idle();
  90.         //read one block
  91.         for(j=0; j<nand_page_size; j++)="" <="" li="" style="word-wrap: break-word;">
  92.         {
  93.             *dest_addr = nand_read_byte();
  94.             dest_addr ++;
  95.         }
  96.     }
  97.     nand_chip_deselect();
  98. }
对于nand flash的 NFDATA 寄存器定义时要特别注意,是char而不是int。

2.3 main.c


点击(此处)折叠或打开

  1. #define GPBCON (*(volatile unsigned int *) 0x56000010)
  2. #define GPBDAT (*(volatile unsigned int *) 0x56000014)

  3. static inline void delay (unsigned long loops)
  4. {
  5.     __asm__ volatile ("1:\n"
  6.             "subs %0, %1, #1\n"
  7.             "bne 1b":"=r" (loops):"0" (loops));
  8. }

  9. /* led流水灯 */
  10. void main(void)
  11. {
  12.     int i = 1;
  13.     GPBCON = 0x15400;

  14.     while(1)
  15.     {
  16.         GPBDAT = 0x7FF&(~i<<5);
  17.         i *= 2;
  18.         if(16==i)
  19.             i = 1;
  20.         delay(400000);
  21.     }
  22.     return ;
  23. }
2.4 sdram.c 没有改动
2.5 Makefile中OBJS :=  start.o sdram.o nand.o main.o

 myboot_nand.rar   (使用时要将后缀名改为 .tar.gz)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值