一、 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)
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
点击(此处)折叠或打开
- .text
- .global _start
- _start:
- _TEXT_BASE:
- .word 0x33d80000
-
- .globl _armboot_start
- _armboot_start:
- .word _start
-
- ldr r0, =0x53000000
- mov r1, #0x0
- str r1, [r0]
-
- #define COCKTIME 0x4C000000
- #define MPLLCON 0x4C000004
- #define UPLLCON 0x4C000008
- #define CLKCON 0x4C00000C
- #define CLKSLOW 0x4C000010
- #define CLKDIVN 0x4C000014
- #define CAMDIVN 0x4C000018
- /*FCLK:HCLK:PCLK=1:4:8*/
- ldr r0, =CLKDIVN
- mov r1, #0x05
- str r1, [r0]
-
- mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, #0xc0000000
- mcr p15, 0, r0, c1, c0,0
-
- /*MPLL=(2*m*Fin)/(P*(1<<s)), m="(MDIV+8)," p="PDIV+2" s="SDIV*/
- ldr r0, =MPLLCON
- ldr r1, =((0x5C<<12)|(0x01<<4)|(0x01))
- str r1, [r0]
-
- ldr r0, =0x10000
- 1:
- sub r0, r0, #1
- bne 1b
- /*UPLL=(m*Fin)/(P*(1<<s)), m="(MDIV+8)," p="(PDIV+2)," s="SDIV*/
- ldr r0, =UPLLCON
- ldr r1, =((0x10<<12)|(0x01<<4)|(0x01))
- str r1, [r0]
- ldr r0, =0x10000
- 1:
- sub r0, r0, #1
- bne 1b
-
- ldr sp, =1024*4
- bl init_sdram
-
- /*设置栈指向内存地址 (0x33d80000+128k)*/
- ldr sp, =0x33dA0000
-
- /*dest=0x33d80000 src=0x0 size=16k*/
- bl nand_init ;初始化nand flash
- ldr r0, =0x33d80000
- mov r1, #0x0
- ldr r2, =1024*16
- bl nand_read_page ;将nand flash上的boot读到内存0x33d80000处,大小为16k
-
- ldr pc, _main ;跳转到内存中的main中执行
- loop:
- b loop
- _main: .word main
点击(此处)折叠或打开
- #define NFCONF (*(volatile unsigned int *) 0x4E000000)
- #define NFCONT (*(volatile unsigned int *) 0x4E000004)
- #define NFCMMD (*(volatile unsigned int *) 0x4E000008)
- #define NFADDR (*(volatile unsigned int *) 0x4E00000C)
- #define NFDATA (*(volatile unsigned char *) 0x4E000010) //注意:类型char
- #define NFMECCD0 (*(volatile unsigned int *) 0x4E000014)
- #define NFMECCD1 (*(volatile unsigned int *) 0x4E000018)
- #define NFSECCD (*(volatile unsigned int *) 0x4E00001C)
- #define NFSTAT (*(volatile unsigned int *) 0x4E000020)
- #define NFESTAT0 (*(volatile unsigned int *) 0x4E000024)
- #define NFESTAT1 (*(volatile unsigned int *) 0x4E000028)
- #define NFMECC0 (*(volatile unsigned int *) 0x4E00002C)
- #define NFMECC1 (*(volatile unsigned int *) 0x4E000030)
- #define NFMECC (*(volatile unsigned int *) 0x4E000034)
- #define NFSBLK (*(volatile unsigned int *) 0x4E000038)
- #define NFEBLK (*(volatile unsigned int *) 0x4E00003C)
-
- /*nand command */
- #define NAND_CMD_RESET 0xFF
-
- #define NAND_PAGE_SIZE 2048
- #define NAND_PAGE_MASK (NAND_PAGE_SIZE-1)
-
- static void nand_chip_select(void)
- {
- int i;
- NFCONT &= ~(1<<1);
- for(i=0; i<10; i++);
- }
-
- static void nand_chip_deselect(void)
- {
- NFCONT |= (1<<1);
- }
-
- static void nand_write_cmd(unsigned char cmd)
- {
- NFCMMD = cmd;
- }
-
- static void nand_write_addr(unsigned int addr)
- {
- int col, page;
- int i;
- col = addr & NAND_PAGE_MASK;
- page = addr / NAND_PAGE_SIZE;
-
- NFADDR = col & 0xff; /* Column Address A0~A7 */
- for(i=0; i<10; i++);
- NFADDR = (col >> 8) & 0x0f; /* Column Address A8~A11 */
- for(i=0; i<10; i++);
- NFADDR = page & 0xff; /* Row Address A12~A19 */
- for(i=0; i<10; i++);
- NFADDR = (page >> 8) & 0xff; /* Row Address A20~A27 */
- for(i=0; i<10; i++);
- NFADDR = (page >> 16) & 0x03; /* Row Address A28~A29 */
- for(i=0; i<10; i++);
- }
-
- static void nand_wait_idle(void)
- {
- while( !(NFSTAT & 0x01))
- ;
- }
-
- static void nand_reset(void)
- {
- nand_chip_select();
- nand_write_cmd(NAND_CMD_RESET);
- nand_wait_idle();
- nand_chip_deselect();
- }
-
- static unsigned char nand_read_byte(void)
- {
- return (NFDATA&0xFF);
- }
-
- void nand_init(void)
- {
- #define TACLS 0x0
- #define TWRPH0 0x03
- #define TWRPH1 0x0
- NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
- NFCONT = (0x01<<4)|(0x01<<1)|(0x01<<0);
- nand_reset(); //初次使用时要先复位一下
- }
-
- /*调用这个函数时要保证size是按页对齐的*/
- void nand_read_page(unsigned char * dest_addr, unsigned long src_addr, unsigned int size)
- {
- int i,j;
-
- NFCONT &= ~(1<<1);
- for(i=0; i<10; i++);
- for(i=0; i<size (nand_page_size);="" i++)="" <="" li="" style="word-wrap: break-word;">
- {
- nand_write_cmd(0x00);
- nand_write_addr(src_addr+i*NAND_PAGE_SIZE);
- nand_write_cmd(0x30);
- nand_wait_idle();
- //read one block
- for(j=0; j<nand_page_size; j++)="" <="" li="" style="word-wrap: break-word;">
- {
- *dest_addr = nand_read_byte();
- dest_addr ++;
- }
- }
- nand_chip_deselect();
- }
点击(此处)折叠或打开
- #define GPBCON (*(volatile unsigned int *) 0x56000010)
- #define GPBDAT (*(volatile unsigned int *) 0x56000014)
-
- static inline void delay (unsigned long loops)
- {
- __asm__ volatile ("1:\n"
- "subs %0, %1, #1\n"
- "bne 1b":"=r" (loops):"0" (loops));
- }
-
- /* led流水灯 */
- void main(void)
- {
- int i = 1;
- GPBCON = 0x15400;
-
- while(1)
- {
- GPBDAT = 0x7FF&(~i<<5);
- i *= 2;
- if(16==i)
- i = 1;
- delay(400000);
- }
- return ;
- }