准备分析
资源工具
着手写程序
start.S中的代码拷贝很重要,Makefile中的链接地址很重要。
- /*
- * $Id: nand_cp.c,v 1.1 2008/11/20 01:08:36 boyko Exp $
- *
- * (C) Copyright 2006 Samsung Electronics
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
- /*
- * You must make sure that all functions in this file are designed
- * to load only U-Boot image.
- *
- * So, DO NOT USE in common read.
- *
- * By scsuh.
- */
- /*
- * Standard NAND flash commands
- */
- #define NAND_CMD_READ0 0
- #define NAND_CMD_READ1 1
- #define NAND_CMD_RNDOUT 5
- #define NAND_CMD_PAGEPROG 0x10
- #define NAND_CMD_READOOB 0x50
- #define NAND_CMD_ERASE1 0x60
- #define NAND_CMD_STATUS 0x70
- #define NAND_CMD_STATUS_MULTI 0x71
- #define NAND_CMD_SEQIN 0x80
- #define NAND_CMD_RNDIN 0x85
- #define NAND_CMD_READID 0x90
- #define NAND_CMD_PARAM 0xec
- #define NAND_CMD_ERASE2 0xd0
- #define NAND_CMD_RESET 0xff
- /* Extended commands for large page devices */
- #define NAND_CMD_READSTART 0x30
- #define NAND_CMD_RNDOUTSTART 0xE0
- #define NAND_CMD_CACHEDPROG 0x15
- #define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
- #define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
- #define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
- //#include <asm/io.h>
- //#include <linux/mtd/nand.h>
- #include "s5pc110.h"
- #define COPY_BL2_SIZE 0x80000
- #define NAND_CONTROL_ENABLE() (NFCONT_REG |= (1 << 0))
- /*
- * address format
- * 17 16 9 8 0
- * --------------------------------------------
- * | block(12bit) | page(5bit) | offset(9bit) |
- * --------------------------------------------
- */
- static int nandll_read_page (uchar *buf, ulong addr, int large_block)
- {
- int i;
- int page_size = 512;
- if (1 == large_block)
- page_size = 2048;
- else if (2 == large_block)
- page_size = 8192;
- NAND_ENABLE_CE();
- NFCMD_REG = NAND_CMD_READ0;
- /* Write Address */
- NFADDR_REG = 0;
- if (large_block)
- NFADDR_REG = 0;
- NFADDR_REG = (addr) & 0xff;
- NFADDR_REG = (addr >> 8) & 0xff;
- NFADDR_REG = (addr >> 16) & 0xff;
- if (large_block)
- NFCMD_REG = NAND_CMD_READSTART;
- NF_TRANSRnB();
- /* for compatibility(2460). u32 cannot be used. by scsuh */
- for(i=0; i < page_size; i++) {
- *buf++ = NFDATA8_REG;
- }
- NAND_DISABLE_CE();
- return 0;
- }
- /*
- * Read data from NAND.
- */
- static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
- {
- uchar *buf = (uchar *)dst_addr;
- int i;
- uint page_shift = 9;
- if (1 == large_block)
- {
- page_shift = 11;
- /* Read pages */
- for (i = (0x6000>>page_shift); i < (size>>page_shift); i++, buf+=(1<<page_shift))
- {
- nandll_read_page(buf, i, large_block);
- }
- }
- else if(2 == large_block)
- {
- page_shift = 12;
- for (i = 0; i < (size>>page_shift); i++, buf+=(1<<(page_shift-1)))
- {
- nandll_read_page(buf, i, large_block);
- }
- }
- return 0;
- }
- int copy_uboot_to_ram_nand (void)
- {
- int large_block = 0;
- int i;
- vu_char id;
- NAND_CONTROL_ENABLE();
- NAND_ENABLE_CE();
- NFCMD_REG = NAND_CMD_READID;
- NFADDR_REG = 0x00;
- /* wait for a while */
- for (i=0; i<200; i++);
- id = NFDATA8_REG;
- id = NFDATA8_REG;
- if (id > 0x80)
- large_block = 1;
- if(id == 0xd5)
- {
- large_block = 2;
- }
- /* read NAND Block.
- * 128KB ->240KB because of U-Boot size increase. by scsuh
- * So, read 0x3c000 bytes not 0x20000(128KB).
- */
- //return nandll_read_blocks(CONFIG_SYS_TEXT_BASE, COPY_BL2_SIZE, large_block);
- return nandll_read_blocks(0xd0024000, 0x4000, large_block);
- }
- void board_init_f_nand(unsigned long bootflag)
- {
- __attribute__((noreturn)) void (*uboot)(void);
- copy_uboot_to_ram_nand();
- /* Jump to U-Boot image */
- uboot = (void *)0xd024010;
- (*uboot)();
- /* Never returns Here */
- }
- @******************************************************************************
- @ File:start.S
- @ 功能:启动代码,设置栈,拷贝16k到0xd0020000处
- @******************************************************************************
- .text
- .global _start
- _start:
- ldr sp, =0xD0037D80 @ 设置栈,以便调用c函数
- adr r0, _start @ 重定位
- @ _start当前所位于的地址:0xd0020010 (前边放有16bit的头信息)
- ldr r1, =_start @ _start的链接地址:0xd0024010
- ldr r2, =0xd0028000 @ 0xd0028000 = 0xd0024000 + 0x4000(16k)
- cmp r0, r1
- beq run_on_dram
- bl nand_asm_init
- bl copy_uboot_to_ram_nand
- run_on_dram:
- ldr pc, =main @ 跳转
- halt:
- b halt
- led_debug:
- ldr R0,=0xE0200280 @ R0设为GPJ2CON寄存器。此寄存器
- @ 用于选择端口J各引脚的功能:
- @ 是输出、是输入、还是其他
- mov R1,#0x00000001
- str R1,[R0] @ 设置GPJ2_0为输出口, 位[10:9]=0b01
- ldr R0,=0xE0200284 @ R0设为GPJ2DAT寄存器。此寄存器
- @ 用于读/写端口GPJ2各引脚的数据
- mov R1,#0x00000000 @ 此值改为0x00000001,
- @ 可让LED1熄灭
- str R1,[R0] @ GPJ2_0输出0,LED1点亮
- mov pc, lr
- /* Setting GPIO for NAND */
- /* This setting is NAND initialze code at booting time in iROM. */
- nand_asm_init:
- /*
- * Nand Interface Init for SMDKC110
- */
- #define ELFIN_GPIO_BASE 0xE0200000
- #define ELFIN_NAND_BASE 0xB0E00000
- #define NFCONF_VAL (7<<12)|(7<<8)|(7<<4)|(0<<3)|(0<<2)|(1<<1)|(0<<0)
- #define NFCONT_VAL (0x1<<23)|(0x1<<22)|(0<<18)|(0<<17)|(0<<16)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0x2<<1)|(1<<0)
- #define MP01CON_OFFSET 0x2E0
- #define MP01PUD_OFFSET 0x2E8
- #define MP03CON_OFFSET 0x320
- #define MP03PUD_OFFSET 0x328
- #define NFCONF_OFFSET 0x00
- #define NFCONT_OFFSET 0x04
- ldr r0, =ELFIN_GPIO_BASE
- ldr r1, [r0, #MP01CON_OFFSET]
- bic r1, r1, #(0xf<<8)
- orr r1, r1, #(0x3<<8)
- str r1, [r0, #MP01CON_OFFSET]
- ldr r1, [r0, #MP01PUD_OFFSET]
- bic r1, r1, #(0x3<<4)
- str r1, [r0, #MP01PUD_OFFSET]
- ldr r1, [r0, #MP03CON_OFFSET]
- bic r1, r1, #0xFFFFFF
- ldr r2, =0x22222222
- orr r1, r1, r2
- str r1, [r0, #MP03CON_OFFSET]
- ldr r1, [r0, #MP03PUD_OFFSET]
- ldr r2, =0x3fff
- bic r1, r1, r2
- str r1, [r0, #MP03PUD_OFFSET]
- ldr r0, =ELFIN_NAND_BASE
- ldr r1, [r0, #NFCONF_OFFSET]
- ldr r2, =0x777F
- bic r1, r1, r2
- ldr r2, =NFCONF_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONF_OFFSET]
- ldr r1, [r0, #NFCONT_OFFSET]
- ldr r2, =0x707C7
- bic r1, r1, r2
- ldr r2, =NFCONT_VAL
- orr r1, r1, r2
- str r1, [r0, #NFCONT_OFFSET]
- ldr r1, [r0, #NFCONF_OFFSET]
- orr r1, r1, #0x70
- orr r1, r1, #0x7700
- str r1, [r0, #NFCONF_OFFSET]
- ldr r1, [r0, #NFCONT_OFFSET]
- orr r1, r1, #0x03
- str r1, [r0, #NFCONT_OFFSET]
- mov pc, lr
- #define GPJ2CON (*(volatile unsigned long *) 0xE0200280)
- #define GPJ2DAT (*(volatile unsigned long *) 0xE0200284)
- // 延时函数
- void delay(unsigned long count)
- {
- volatile unsigned long i = count;
- while (i--)
- ;
- }
- void main() //LED 闪烁
- {
- GPJ2CON = 0x00001111; // 配置引脚
- while(1) // 闪烁
- {
- GPJ2DAT = 0; // LED on
- delay(0x100000);
- GPJ2DAT = 0xf; // LED off
- delay(0x100000);
- }
- }
下载运行
同《
S5PV210的LED应用(一)》
运行调试
一开始以为程序会很难,应该MLC的,这样的NandFlash涉及到了ECC校验,颇为麻烦,但是细想,只实现读操作,会少许简单一些。最后发现读的时候问题并不多。也并不是那么困难。nand_asm_init和nand_cp.c提取于u-boot,并加以移植。