bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理

bootloader功能介绍

初始化开发板上主要硬件(时钟,内存,硬盘),

把操作系统从硬盘拷贝到内存,然后让cpu跳转到内存中执行操作系统。

boot阶段

1.关闭影响CPU正常执行的外设

-关闭看门狗(watch dog)   WTCON 0xE2700000

-关闭中断 CPSR I和F位设置为1,关闭,不响应任何中断。

2.初始化时钟

-倍频到1Ghz,为外设分频

*串口驱动

3.初始化内存控制器,DDRAM

-验证内存,往里面写一个值,然后再读出来

4.初始化硬盘,nand Flash

-nand flash 读驱动(从nand往外读数据)

loader阶段

1.从硬盘指定的地址加载kernel到内存指定的地址。

2.跳转到内存kernel所在的地址,执行

附加功能:

实现bootloader中shell(命令解释器)

附加功能:

实现bootloader中shell(命令解释器)

uboot中支持的命令, 

help

loadb 下载程序, kermit 协议

go 0X21000000;

例如:在uboot中直接控制蜂鸣器

mm 0xe02000a0 0x1(控制寄存器)

mm 0xe02000a4 0x1(数据寄存器)

常用调试手段:

1.led点灯大法

2.串口调试,uart_getchar,uart_putchar,进一步实现stdio.h

时钟初始化设置

pll 锁相环,
倍频

串口工作原理

串口工作核心图

#define ULCON0 *((volatile unsigned int *)0XE2900000)

volatile 关键字,防止编译器做优化,每次读取寄存器的值,都是重新读取寄存器。

//start.s
	AREA start_main,CODE, READONLY
	ENTRY
	IMPORT uart_test
START
	B uart_test

	END
//uart.c
#define ULCON0 *((volatile unsigned int *)0XE2900000)
#define UCON0 *((volatile unsigned int *)0XE2900004)
#define UTRSTAT0 *((volatile unsigned int *)0XE2900010)
#define UTXH0 *((volatile unsigned int *)0XE2900020)
#define URXH0 *((volatile unsigned int *)0XE2900024)
#define UBRDIV0 *((volatile unsigned int *)0XE2900028)
#define UDIVSLOT0 *((volatile unsigned int *)0XE290002C)
#define GPACON0 *((volatile unsigned int *)0XE0200000)
void uart_init(void)
{
	//串口管脚设置成功能态
	GPACON0 = 0x22;
	//设置8  N  1
	ULCON0 = 0X3;
	//设置轮询工作模式
	UCON0 = 0X5;
	//设置波特率
	UBRDIV0 = 34;
	UDIVSLOT0 = 0XDDDD;

}
char uart_getchar(void)
{
	char ch;
	//如果有数据到达,状态寄存器第0位置1
	//判断状态位是否为1,决定读接收缓冲寄存器,读到的值作为函数的返回值
	while (!(UTRSTAT0 & 0x1))
		;
	ch = URXH0;
	return ch;
}
void uart_putchar(char ch)
{
	//如果状态寄存器第1为置1,表示发送单元为空,可以发送数据
	//把ch赋值到发送缓冲寄存器里,状态寄存器第1为置0, 自动发送,当发送完毕
	while (!(UTRSTAT0 & 0X2))
		;
	UTXH0 = ch;
}
void uart_test(void)
{
	char ch;

	uart_init();
	uart_putchar('a');
	uart_putchar('b');
	uart_putchar('c');
	//串口回显功能
	while (1)
	{
		ch = uart_getchar();
		uart_putchar(ch);
	}
}

内存工作原理

--------------------------------------------------

NandFlash工作原理

内存是总线设备,nandflash属于非总线设备。

没有地址线, 只有数据线。

内存:总线数据, nandflash:非总线设备。

命令、地址、数据复用端口。

忙闲位。

裸板操作NandFlash的示例代码:

#define NFCONF (*(volatile unsigned int *)0xB0E00000)
#define NFCONT (*(volatile unsigned int *)0xB0E00004)
#define NFCMMD (*(volatile unsigned int *)0xB0E00008)
#define NFADDR (*(volatile unsigned int *)0xB0E0000C)
#define NFDATA (*(volatile unsigned int *)0xB0E00010)
#define NFSTAT (*(volatile unsigned int *)0xB0E00028)

#define MP0_3CON (*(volatile unsigned int *)0xE0200320)

#define PAGE_SIZE	2048

void nand_init(void)
{
	//[15:12]TACLS = 1->(1) 1/133Mhz = 7.5ns
	//[11:8] TWRPH0 = 1->(1+7) 7.5ns*2 = 15ns
	//[7:4] TWRPH1 = 1->(1+1) 7.5ms *2 = 15ns
	NFCONF |= 1<<2 | 1<< 8 | 1<< 4;
	//AdrCycle [1]1=5 address cycle
	NFCONF |= 1<<1;
	//MODE [0] NAND Flash controller operating node
	// 0=disable nand flash controller
	// *1 = enable nand flash controller
	NFCONT |= 1<<0;
	//Reg_nCE0 [1] nandflash memort nRCS[0] signal control
	// *0 = force nRCS[0] to low (enable chip select)
	// 1 = force nRCS[0] to high(disable chip select)
	NFCONT &= ~(1<<1);
	//GPIO functional mux setting
	// 0010 = NF_xxx
	MP0_3CON = 0X22222222;
	return ;
}

void nand_read_id(char id[])
{
	int i;
	//write read_id cmd 90th
	NFCMMD = 0X90;
	//write address 00h
	NFADDR = 0x00;
	for(i=0; i<5; i++)
	{
		id[i] = NFDATA;
	}
	return ;
}

void nand_read_page(int addr, char buf[])
{
	int i;
	char tmp;
	//write read_page cmd 00h
	NFCMMD = 0X00;
	//write 5 address
	NFADDR = (addr >> 0) & 0xFF;
	NFADDR = (addr >> 8) & 0x7;
	NFADDR = (addr >> 11) & 0xFF;
	NFADDR = (addr >> 19) & 0xFF;
	NFADDR = (addr >> 27) & 0x1;
	//write read_page cmd 30h
	NFCMMD = 0X30;
	//wait for R/nB -->ready
	while( (NFSTAT &(1<<0))==0 )
		;
	//read data 2048 bytes
	for(i=0; i<PAGE_SIZE; i++)
	{
		buf[i] = NFDATA;
	}
	for (i=0; i<64; i++)
	{
		tmp = NFDATA;
	}
	return ;

}

void nand_read(int nand_addr, char *sdram_addr, int size)
{
	int pages = (size -1)/PAGE_SIZE + 1;
	int i;

	for (i=0; i<pages; i++)
	{
		nand_read_page(nand_addr + i*PAGE_SIZE, sdram_addr + i*PAGE_SIZE);
	}

}

uboot中操作NandFlash的示例代码:

//s3c2440_nand.c

#include <common.h>

#if 0
#define DEBUGN printf
#else
#define DEBUGN(x,args ...){}
#endif
#include <nand.h>
#include <asm/arch/s3c24x0_cpu.h>
#include <asm/arch/s3c2410.h>
#include <asm/io.h>

#define __REGb(x) (*(volatile unsigned char *)(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 NFMECCD0         __REGi(NF_BASE + 0x14)
#define NFMECCD1         __REGi(NF_BASE + 0x18)
#define NFSECCD          __REGi(NF_BASE + 0x1C)
#define NFSTAT           __REGb(NF_BASE + 0x20)
#define NFSTAT0          __REGi(NF_BASE + 0x24)
#define NFSTAT1          __REGi(NF_BASE + 0x28)
#define NFMECC0          __REGi(NF_BASE + 0x2C)
#define NFMECC1          __REGi(NF_BASE + 0x30)
#define NFSECC           __REGi(NF_BASE + 0x34)
#define NFSBLK           __REGi(NF_BASE + 0x38)
#define NFEBLK           __REGi(NF_BASE + 0x3C)

#define S3C2440_NFCONT_nCE (1<<1)
#define S3C2440_ADDR_NALE 0x08
#define S3C2440_ADDR_NCLE 0x0c

#ifdef CONFIG_NAND_SPL

/* in the early stage of NAND flash booting, printf() is not available */
#define printf(fmt, args...)

static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
{
	int i;
	struct nand_chip *this = mtd->priv;

	for (i = 0; i < len; i++)
		buf[i] = readb(this->IO_ADDR_R);
}
#endif

ulong  IO_ADDR_W = NF_BASE;
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
    struct nand_chip *chip = mtd->priv;
	DEBUGN("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);
	if (ctrl & NAND_CTRL_CHANGE) {
		IO_ADDR_W = NF_BASE;
		if (!(ctrl & NAND_CLE))
				IO_ADDR_W |= S3C2440_ADDR_NCLE;
		if (!(ctrl & NAND_ALE))
				IO_ADDR_W |= S3C2440_ADDR_NALE;

       if (ctrl & NAND_NCE)
			NFCONT &= ~ S3C2440_NFCONT_nCE;
       else
			NFCONT |= S3C2440_NFCONT_nCE;
    }
	if (cmd != NAND_CMD_NONE)
                writeb(cmd, (void *)IO_ADDR_W);
}

static int s3c2440_dev_ready(struct mtd_info *mtd)
{
	DEBUGN("dev_ready\n");
	return(NFSTAT & 0x01);
}

#ifdef CONFIG_S3C2410_NAND_HWECC
void s3c2410_nand_enable_hwecc(struct mtd_info *mtd, int mode)
{
	struct s3c2410_nand *nand = s3c2410_get_base_nand();
	debugX(1, "s3c2410_nand_enable_hwecc(%p, %d)\n", mtd, mode);
	writel(readl(&nand->NFCONF) | S3C2410_NFCONF_INITECC, &nand->NFCONF);
}

static int s3c2410_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
				      u_char *ecc_code)
{
	struct s3c2410_nand *nand = s3c2410_get_base_nand();
	ecc_code[0] = readb(&nand->NFECC);
	ecc_code[1] = readb(&nand->NFECC + 1);
	ecc_code[2] = readb(&nand->NFECC + 2);
	debugX(1, "s3c2410_nand_calculate_hwecc(%p,): 0x%02x 0x%02x 0x%02x\n",
	       mtd , ecc_code[0], ecc_code[1], ecc_code[2]);

	return 0;
}

static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
				     u_char *read_ecc, u_char *calc_ecc)
{
	if (read_ecc[0] == calc_ecc[0] &&
	    read_ecc[1] == calc_ecc[1] &&
	    read_ecc[2] == calc_ecc[2])
		return 0;

	printf("s3c2410_nand_correct_data: not implemented\n");
	return -1;
}
#endif

int board_nand_init(struct nand_chip *nand)
{
	u_int32_t cfg;
	u_int8_t tacls, twrph0, twrph1;
	struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();

	DEBUGN("board_nand_init()\n");

	writel(readl(&clk_power->CLKCON) | (1 << 4), &clk_power->CLKCON);

	/* initialize hardware */
	twrph0 = 4;
	twrph1 =2;
	tacls = 0;

	cfg = ((tacls<<12)|(twrph0<<8)|(twrph1<<4));
	NFCONF=cfg;
	cfg = ((1<<6)|(1<<4)|(0<<1)|(1<<0));
	NFCONT=cfg;
	/* initialize nand_chip data structure */
	nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)0x4e000010;

	/* read_buf and write_buf are default */
	/* read_byte and write_byte are default */

	/* hwcontrol always must be implemented */
	nand->cmd_ctrl = s3c2440_hwcontrol;
	nand->dev_ready = s3c2440_dev_ready;
	nand->ecc.mode = NAND_ECC_SOFT;

	DEBUGN("end of nand_init\n");

	return 0;
}
时间: 2025-01-01 01:20:20

bootloader功能介绍/时钟初始化设置/串口工作原理/内存工作原理/NandFlash工作原理的相关文章

带你走近AngularJS - 基本功能介绍

带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------------------------------------------------------------------------------------------ AngularJS是Google推出的一款Web应用开发框架.它提供了一系列兼容性良好并且可扩展的服务,包括数据绑定.DOM操作.M

Visio2007新功能介绍

  Visio2007新功能介绍           提示:使用现有的数据,你可以生成许多种类的 Visio 标准图表,包括组织结构图.日程表.日历和甘特图.然而,本文讨论的新数据功能和增强的数据功能仅在 Office Visio Professional 2007 中提供,而在 Office Visio Standard 2007 中没有提供. Visio2007 快速入门 使用 Office Visio 2007 中新的"入门"窗口,便可找到所需的模板. 更简单的模板类别现在,由于

在uclinux下,如何设置串口才能发at指令

问题描述 在uclinux下,如何设置串口才能发at指令 在uclinux下,如何设置串口才能发at指令? 最近上手了一个新的项目,由于代码之前已经实现在tos平台下通过串口发at指令,现在在uclinux平台下也须实现该功能,但是目前只能通过该串口看到系统启动时的调试信息,不能通过该口发送at指令. 我目前已经做的工作是:关闭该串口的控制台功能,使之成为普通串口.但是我通过关闭宏来实现该功能后,发现该串口出现的调试信息停在了start kernel这里,而且也还不能发at指令. 所以目前我有两

在uclinux下,如何设置串口才能发at指令?

问题描述 在uclinux下,如何设置串口才能发at指令? 最近上手了一个新的项目,由于代码之前已经实现在tos平台下通过串口发at指令,现在在uclinux平台下也须实现该功能,但是目前只能通过该串口看到系统启动时的调试信息,不能通过该口发送at指令. 我目前已经做的工作是:关闭该串口的控制台功能,使之成为普通串口.但是我通过关闭宏来实现该功能后,发现该串口出现的调试信息停在了start kernel这里,而且也还不能发at指令. 所以目前我有两个疑问:1.系统究竟有没起来?还是关闭了控制台功

时间子系统10_hpet时钟初始化

// 时钟mult :mult/2^shift = ns/cyc // 参考:http://www.bluezd.info/archives/reg_clock_event_device_1 // x86平台初始化 // 注:arch/x86/kernel/x86_init.c 1.1 struct x86_init_ops x86_init __initdata = { ... //时钟初始化 .timers = { .setup_percpu_clockev = setup_boot_API

胡进勤:精密空调组网群控功能介绍

本文讲的是胡进勤:精密空调组网群控功能介绍 [IT168 资讯]由中国通信企业协会增值服务委员会主办,中国通信企业协会通信网络运维专业委员会与中国联通国家数据中心协办,中国IDC产业联盟网和C114中国通信网联合承办的"2010中国绿色数据中心发展与实践高峰论坛"将于9月16日在北京新世纪日航饭店隆重召开.It168 记者带来实时的精彩报道. 图:艾默生网络能源有限公司 空调技术专家胡进勤(大会直播专题) 演讲人简介: 胡进勤,艾默生网络能源技术专家.浙江大学制冷与低温研究所制冷专业硕

阿里云湖北区域服务提供商:阿里云CDN功能介绍

阿里云湖北区域服务提供商官方唯一指定武汉捷讯技术.关于阿里云CDN功能介绍如下: 阿里云CDN(内容分发网络)全称是AlibabaCloudContentDeliveryNetwork,建立并覆盖在承载网之上.由分布在不同区域的边缘节点服务器群组成的分布式网络,替代传统以WEBServer为中心的数据传输模式.将源内容发布到边缘节点,配合精准的调度系统:将用户的请求分配至最适合他的节点,使用户可以以最快的速度取得他所需的内容,有效解决Internet网络拥塞状况,提高用户访问的响应速度.使用CD

windows 2008服务器安装与初始化设置图解

软件下载什么的我就不介绍了,大家自己准备吧. 安装开始:1.用安装光盘引导启动安装 由于主板厂商的不同,我们无法确定您的设定方式与我们完全相同,所以本部分请使用者自行参考主板说明书的"BIOS配置设定 开始,会让你选择安装语言,选择适合自己的时间和货币显示种类及键盘和输入方式. ,这里,,我就没抓到图,,嘿嘿,,不好意思.. 点击"现在安装".. 咦?你看到这里是不是说奇怪,,怎么没有要求你输入:产品密钥??嘿嘿..8告诉你! 因为本来就不用输入WINDOWS 2008的产品

Fiddler抓包使用教程-基本功能介绍

转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/72932886 本文出自[赵彦军的博客] Fiddler 基本页面 会话列表功能介绍 标识符 含义 # Fiddler为Session生成的ID Result 响应状态码 Protocol 该Session使用的协议(HTTP/HTTPS/FTP) Host 接收请求的服务器的主机名和端口号 URL 请求URL的路径.文件和查询字符串 Body 响应体中包含的字节数 Caching