当前位置: 首页 > news >正文

ARM+LINUX移植攻略(九)U-boot-2009.08移植TE2440II开发板--支持Nandflash启动

哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处

http://blog.csdn.net/woshixingaaa/archive/2011/02/17/6192146.aspx

nandflash启动最关键的部分是rellocated,即代码重定位。s3c2440数据手册有这么一段,所以代码重定位是由nandflash控制器自动完成的,而不是一些人说的由CPU完成的。

include/configs/TE2440II.h中添加nandflash控制器的定义:

/*

* NAND flash setting

*/

#if defined(CONFIG_CMD_NAND)

#define CONFIG_SYS_NAND_BASE 0x4e000000

#define CONFIG_SYS_MAX_NAND_DEVICE 1

#define CONFIG_MTD_NAND_VERIFY_WRITE 1

#define NAND_SAMSUNG_LP_OPTIONS 1 //大页要添加这个

#define CONFIG_NAND_S3C2440 1

#define CONFIG_S3C2440_NAND_BOOT 1

#define NAND_CTL_BASE 0x4E000000

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFADDR 0x0c

#define oNFDATA 0x10

#define oNFCMD 0x08

#define oNFSTAT 0x20

#define oNFECC 0x2c

#endif

/*

* Command line configuration.

*/

下添加

#define CONFIG_CMD_NAND

修改环境变量那部分

//#undef CONFIG_ENV_IS_IN_FLASH 1

#define CONFIG_ENV_IS_IN_NAND 1

其次,修改cpu/arm920t/start.S这个文件,使u-bootNand Flash启动

为了让他自动识别是从norflash还是从nandflash启动添加,BWSCON的第21为即OM1OM0。为00时是从nandflash启动,其他为从norflash启动,判断OM1OM0,就可以让uboot自动识别启动方式。

#define BWSCON 0x48000000

ldr r0, =BWSCON

ldr r1,[r0]

ands r1, r1, #0x6

beq nand_boot

nor_boot:

#ifndef CONFIG_SKIP_RELOCATE_UBOOT

添加nandflash的启动代码,核心是relocated部分。首先设置nandflash控制器,然后将nandflash中从0开始的uboot复制到SDRAM中的TEXT_BASE处,TEXT_BASEconfig.mk中定义,值为0x33f80000。复制好后,比较nandflashSDRAM中的数据,如果前4K相同,表示搬移成功。下面的汇编代码注意ATPC标准规定r0~r3,用于参数传递和返回值。

/********************************************************/

//#define CONFIG_S3C2440_NAND_BOOT 1

nand_boot:

#define CONFIG_S3C2440_NAND_BOOT 1

#define NAND_CTL_BASE 0x4E000000

/* Offset */

#define oNFCONF 0x00

#define oNFCONT 0x04

#define oNFCMD 0x08

#define oNFSTAT 0x20

#define LENGTH_UBOOT 0x40000

@ reset NAND

mov r1, #NAND_CTL_BASE

ldr r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )

str r2, [r1, #oNFCONF]

ldr r2, [r1, #oNFCONF]

ldr r2, =((1<<4)|(0<<1)|(1<<0) ) @ Active low CE Control

str r2, [r1, #oNFCONT]

ldr r2, [r1, #oNFCONT]

ldr r2, =(0x6) @ RnB Clear

str r2, [r1, #oNFSTAT]

ldr r2, [r1, #oNFSTAT]

mov r2, #0xff @ RESET command

strb r2, [r1, #oNFCMD]

mov r3, #0 @ wait

nand1:

add r3, r3, #0x1

cmp r3, #0xa

blt nand1

nand2:

ldr r2, [r1, #oNFSTAT] @ wait ready

tst r2, #0x4

beq nand2

ldr r2, [r1, #oNFCONT]

orr r2, r2, #0x2 @ Flash Memory Chip Disable

str r2, [r1, #oNFCONT]

@ get read to call C functions (for nand_read())

ldr sp, DW_STACK_START @ setup stack pointer

mov fp, #0 @ no previous frame, so fp=0

@ copy U-Boot to RAM

ldr r0, =TEXT_BASE //传递给C代码的第一个参数:u-bootRAM中的起始地址

mov r1, #0x0 //传递给C代码的第二个参数:Nand Flash的起始地址

mov r2, #LENGTH_UBOOT //传递给C代码的第三个参数:u-boot的长度大小

/**********************************************************/

/************************************************************/

bl nand_read_ll

tst r0, #0x0

beq ok_nand_read

bad_nand_read:

loop2:

b loop2 @ infinite loop

ok_nand_read:

@ verify

mov r0, #0

ldr r1, =TEXT_BASE

mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes

go_next:

ldr r3, [r0], #4

ldr r4, [r1], #4

teq r3, r4

bne notmatch

subs r2, r2, #4

beq stack_setup

bne go_next

notmatch:

loop3:

b loop3 @ infinite loop

#endif

/* Set up the stack */

stack_setup:

ldr r0, _TEXT_BASE /* upper 128 KiB: relocated uboot */

sub r0, r0, #CONFIG_SYS_MALLOC_LEN /* malloc area */

sub r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo */

#ifdef CONFIG_USE_IRQ

sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

sub sp, r0, #12 /* leave 3 words for abort-stack */

clear_bss:

ldr r0, _bss_start /* find start of bss segment */

ldr r1, _bss_end /* stop here */

mov r2, #0x00000000 /* clear */

clbss_l:str r2, [r0] /* clear loop... */

add r0, r0, #4

cmp r0, r1

ble clbss_l

ldr pc, _start_armboot

_start_armboot: .word start_armboot

#define STACK_BASE 0x33ff8000

#define STACK_SIZE 0x10000

.align 2

DW_STACK_START: .word STACK_BASE+STACK_SIZE-4

board/samsung/TE2440II/目录下添加nand_read.c文件,内容如下,在K9F2G08datasheet中有这么一段


所以地址由5个周期传完。前两个周期用来寻页内地址。后三个周期是页间寻址。1device=2048block=2048*64page=2048*64*(2k+64)Bytes

#include <config.h>

#include <linux/mtd/nand.h>

#define __REGb(x) (*(volatile unsigned char *)(x))

#define __REGw(x) (*(volatile unsigned short *)(x))

#define __REGi(x) (*(volatile unsigned int *)(x))

#define NF_BASE 0x4e000000

#define NFCONF __REGi(NF_BASE + 0x0)

#define NFCONT __REGi(NF_BASE + 0x4)

#define NFCMD __REGb(NF_BASE + 0x8)

#define NFADDR __REGb(NF_BASE + 0xc)

#define NFDATA __REGb(NF_BASE + 0x10)

#define NFDATA16 __REGw(NF_BASE + 0x10)

#define NFSTAT __REGb(NF_BASE + 0x20)

#define NFSTAT_BUSY (1 << 2)

#define nand_select() (NFCONT &= ~(1 << 1))

#define nand_deselect() (NFCONT |= (1 << 1))

#define nand_clear_RnB() (NFSTAT |= NFSTAT_BUSY)

static inline void nand_wait(void)

{

int i;

while (!(NFSTAT & NFSTAT_BUSY))

for (i=0; i<10; i++);

}

/* configuration for 2440 with 2048byte sized flash */

#define NAND_5_ADDR_CYCLE

#define NAND_PAGE_SIZE 2048

#define BAD_BLOCK_OFFSET NAND_PAGE_SIZE

#define NAND_BLOCK_MASK (NAND_PAGE_SIZE - 1)

#define NAND_BLOCK_SIZE (NAND_PAGE_SIZE * 64)

static int nand_read_page_ll(unsigned char *buf, unsigned long addr)

{

unsigned int i, page_num;

nand_clear_RnB();

NFCMD = NAND_CMD_READ0;

page_num = addr >> 11; /* addr / 2048 */

/* Write Address */

NFADDR = 0;

NFADDR = 0;

NFADDR = page_num & 0xff;

NFADDR = (page_num >> 8) & 0xff;

NFADDR = (page_num >> 16) & 0xff;

NFCMD = NAND_CMD_READSTART;

nand_wait();

相关文章:

  • 深入分析ConcurrentHashMap
  • 从Jetty、Tomcat和Mina中提炼NIO构架网络服务器的经典模式(三)
  • 《大数据时代》读后小结
  • 一个实际的Lisp项目开发心得
  • js判断当前页面在移动设备还是在PC端中打开
  • 元宵,你团圆了吗
  • 获取本机IP
  • Windows Phone 7 不温不火学习之【DeepZoom 详细使用方法】
  • 集合框架遍历方式之——for-each循环
  • ArcGIS API for Android 案例教程 6
  • 类的单列模式
  • Lisp的特性 (评论发不出,只好写一篇新的)
  • 数据图表插件Echarts(一)
  • 一只布谷鸟,两只火鸡,三匹赛马,移动竞赛的改变
  • 2016年 前端学习网站
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 【Under-the-hood-ReactJS-Part0】React源码解读
  • AHK 中 = 和 == 等比较运算符的用法
  • Apache的80端口被占用以及访问时报错403
  • Django 博客开发教程 8 - 博客文章详情页
  • github指令
  • HomeBrew常规使用教程
  • HTTP--网络协议分层,http历史(二)
  • JavaScript的使用你知道几种?(上)
  • laravel 用artisan创建自己的模板
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • swift基础之_对象 实例方法 对象方法。
  • 测试开发系类之接口自动化测试
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 回顾2016
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 深入 Nginx 之配置篇
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 数据结构java版之冒泡排序及优化
  • 我的业余项目总结
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 06-01 点餐小程序前台界面搭建
  • ​低代码平台的核心价值与优势
  • !!【OpenCV学习】计算两幅图像的重叠区域
  • #if 1...#endif
  • #pragma 指令
  • (27)4.8 习题课
  • (3)STL算法之搜索
  • (C语言)共用体union的用法举例
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (草履虫都可以看懂的)PyQt子窗口向主窗口传递参数,主窗口接收子窗口信号、参数。
  • (推荐)叮当——中文语音对话机器人
  • (转)利用ant在Mac 下自动化打包签名Android程序
  • (转)重识new
  • ***php进行支付宝开发中return_url和notify_url的区别分析
  • ***详解账号泄露:全球约1亿用户已泄露
  • .bat批处理(九):替换带有等号=的字符串的子串