移植uboot第三步:修改时钟

写在前面:

我的博客已迁移至自建服务器:博客传送门,CSDN博客暂时停止,如有机器学习方面的兴趣,欢迎来看一看。

此外目前我在gitHub上准备一些李航的《统计学习方法》的实现算法,目标将书内算法全部手打实现,欢迎参观并打星。GitHib传送门

正文

这个步骤弄死我了,弄了一宿,有很多原因,老是这里那里有问题。
因为是基于s3c2410改的boot,2410和2440在使用上区别不大,所以暂时修改不大。
**1.**还是从start.S依次往下看。
**a.**设置管理模式的代码都没有条件编译,肯定差不多,跳过。
**b.**关闭看门狗的条件编译是CONFIG_S3C24X0,都一样的,跳过
**c.*设置分频,这里需要改,2410和2440有区别。(先做个标记)
d.CPU相关的初始化:
cpu_init_crit
Icache和Dcache的设置,估计也差不多,反正先没管,有问题再说
最后调用了C函数lowlevel_init,
lowlevel_init:
发现是设置内存的,里面有一堆宏定义,想知道值到底是多少挺麻烦的,可能2410和2440的有不一样(做个标记,如果出问题了再来改)
e.设置堆栈调用了C函数
board_init_f
这个函数里面就是各种板载资源的初始化,第二步里写过,里面有一个init_sequence结构体,里面有很多的初始化函数,板载资源应该差不多,也不改了。但是里面有一个函数
board_early_init_f
这是设置时钟的,这里有些问题,之前分频结束,但是时钟还没设置,分频以后直接去初始化了内存,之后再设置时钟,这样子设置内存的时候有关时间的参数设置的就不对了。比如说设置内存的时候有一个寄存器值#define REFCNT 1113 /
period=15.6us, HCLK=60Mhz, (2048+1-15.6*60) */它是基于HCLK=60M的时候,没设置时钟的时候肯定达不到这个频率,就有问题了(做个标记)

**2.**先把分频改了,然后时钟设置放到board_early_init_f前头
解决:找到了之前写的400M时钟设置的代码,把之前start.S里的分频删了,添加自己写的分频和时钟设置,同时打开了ICache,ICache是为了速度快一点,不加也可以。

/* 设置时钟 */
	ldr 	r0, 	= 0x4c000014
	mov r1,	#0x05			//FCLK:HCLK:PCLK=1:4:8
	str 	r1, 	[r0]

	mrc	p15, 0, r1, c1, c0, 0        /* 读出控制寄存器 */ 
	orr	r1, r1, #0xc0000000          /* 设置为“asynchronous bus mode” */
	mcr	p15, 0, r1, c1, c0, 0        /* 写入控制寄存器 */

#define 	S3C2440_MPLL_400MHZ     ((0x5c<<12)|(0x01<<4)|(0x01))

	/*  MPLLCON = S3C2440_MPLL_200MHZ; */
	ldr 	r0, 	=0x4c000004
	ldr 	r1, 	=S3C2440_MPLL_400MHZ
	str 	r1, 	[r0]

	/* 启动ICACHE */
	mrc	 p15, 0, r0, c1, c0, 0
	orr	r0,	r0,	#(1<<12)
	mcr	 p15, 0, r0, c1, c0, 0

最后还要把它原先的时钟设置的地方注释掉

board_early_init_f
/* to reduce PLL lock time, adjust the LOCKTIME register */
	//writel(0xFFFFFF, &clk_power->locktime);

	/* configure MPLL */
	//writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV,
	 //      &clk_power->mpllcon);

3.修改后的文件拖进linux里编译,编译成功,下载到板子里测试。
这里有一个便捷的方式测试,我是用oflash下载的,uboot充其量就是个裸机程序,也没法NFS什么的(我当时这么认为)。编译出来的bin524K左右,下进去很慢。后来看了韦东山老师的视频,发现可以先下载好用的boot,我用的是韦东山老师的,200+K,下载的时间是一半,下进去以后再通过dnw下载,速度快很多。
详细:
a.启动uboot,按空格取消倒数,进入下载模式。
b.输入usb 1 30000000命令,usb表示通过usb下载,1表示一直等待文件传入(猜测0的话在等待期间还可以输入别的命令做别的事),30000000表示下载到该地址。
c.PC端打开dnw,USB Port->Transmit,选择bin,确定。
d.板子收到文件以后,protect off all,这是取消nor的写保护,因为一会要把文件写入到nor。
e.earse 0 7ffff,擦除nor,0表示起始地址,7ffff表示结束地址,我的bin算524k,十六进制7ffff,这个结束地址根据bin的实际大小来写,可以写大一点。
f.cp.b 30000000 0 7ffff。把代码段拷贝进30000000这个地址,以这个为首地址,写到末地址,也就是到7ffff。
g.重启板子。
备注:一开始很疑惑,我原先好用的boot存在nor,我下载自己的boot的时候,先下载到内存,然后烧到nor,那我原先的boot怎么办,老家都没了还怎么运行。后来觉得自己傻逼了,之前自己还一直记得程序最开始就会把nor里面的代码copy到SDRAM,早就搬家了,但是重启以后的话,原先的boot就会彻底消失了。我真是太傻逼了,还想了好久。

测试结果:输出了乱码。
分析:要不就是时钟有问题,要不就是串口波特率的问题,这个都不知道两年单片机白写了,我都对不起郭天祥韦东山。

4:我觉得时钟没问题,那就是串口有问题

void board_init_f(ulong bootflag)
for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) 
serial_init
//找到串口初始化了,再进去看一看
int serial_init(void)
{
	return serial_init_dev(UART_NR);
}

是个函数调用,再进去看
static int serial_init_dev(const int dev_index)
这个函数里面有很多东西,看不懂,有点懵逼了,反正是串口初始化,各种参数的设置。感觉这种为了多种平台而写的东西,都会用好多宏定义,绕来绕去的很麻烦。韦东山直接反汇编去看值了,我不会汇编,跟着他的视频看能看懂,自己看就看不懂了。

不管怎么样,这个函数里我找到了这个函数_serial_setbrg(dev_index);,应该是波特率设置,如果不是的话我真的要一个一个看下去了。
这个函数里也就调了一个_PCLK(),它又调了get_HCLK(),其他地方就是算数,给的都是常量,感觉没什么问题,就一直往里走
void _serial_setbrg(const int dev_index)
reg = get_PCLK() / (16 * gd->baudrate) - 1;
get_PCLK()
get_HCLK();

找到了问题,函数里是条件编译#ifdef CONFIG_S3C2440,这个并没有被定义,也就是说函数一直在运行return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK();这句话,很明显这是2410的串口初始化,所以把这个宏定义定义了就好了。

ulong get_HCLK(void)
{
	struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
#ifdef CONFIG_S3C2440
	switch (readl(&clk_power->clkdivn) & 0x6) {
	default:
	case 0:
		return get_FCLK();
	case 2:
		return get_FCLK() / 2;
	case 4:
		return (readl(&clk_power->camdivn) & (1 << 9)) ?
			get_FCLK() / 8 : get_FCLK() / 4;
	case 6:
		return (readl(&clk_power->camdivn) & (1 << 8)) ?
			get_FCLK() / 6 : get_FCLK() / 3;
	}
#else
	return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK();
#endif
}

找到smdk2440.h,把下面这句话注释掉

``#define CONFIG_S3C2410 /* specifically a SAMSUNG S3C2410 SoC */

自己添加一个#define CONFIG_S3C2440,重新编译,结果说和s3c2410_nand.c的72行冲突了
72行:writel(readl(&nand->nfconf) & ~S3C2410_NFCONF_nFCE,
找到了nand结构体 struct s3c2410_nand *nand = s3c2410_get_base_nand();
又去看了s3c2410_nand ,结果如下

#ifdef CONFIG_S3C2410
/* NAND FLASH (see S3C2410 manual chapter 6) */
struct s3c2410_nand {
	u32	nfconf;
	u32	nfcmd;
	u32	nfaddr;
	u32	nfdata;
	u32	nfstat;
	u32	nfecc;
};
#endif

这里就明白了,这个结构体是条件编译,我把这个注释掉了,结构体就没了,程序出错。我现在只想让串口打印点东西,所以打算不要这个函数。

5.找到了s3c2410_nand.c所在地的Makefile,我打算直接不让这个文件编译了,试试呗。
61行:COBJS-$(CONFIG_NAND_S3C2410) += s3c2410_nand.o
说明这个文件被编译是由宏定义CONFIG_NAND_S3C2410决定的,我去取消宏定义就好了,在smdk2440.h里找到了它的宏定义

/*
 * NAND configuration
 */
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE	1
#define CONFIG_SYS_NAND_BASE		0x4E000000
#endif

打算把#define CONFIG_NAND_S3C2410这句话屏了,后来看韦东山更牛逼,想把NAND整个屏了,这些也都是条件编译,可以看到是由CONFIG_CMD_NAND决定的,所以

#ifdef CONFIG_CMD_NAND,这句话直接屏蔽了

再次编译,没有错误

6.下载到板子上,运行

U-Boot 2012.04.01 (Aug 10 2016 - 03:15:13)

CPUID: 32440001
FCLK:      400 MHz
HCLK:      100 MHz
PCLK:       50 MHz
DRAM:  64 MiB
WARNING: Caches not enabled
Flash: *** failed ***
### ERROR ### Please RESET the board ###

程序死了,至少串口输出了。

后记:dnw的驱动网上可以百度,我是win10的,dnw因为没有签名,所以安装不上,百度win10取消强制签名,可以安装,但是实践发现取消强制签名只有第一次重启有效,重启开机驱动会问号。
选择永久取消强制签名,右键开始->命令提示符(管理员),输入
bcdedit.exe /set nointegritychecks on
可以永久取消强制签名,驱动就不会掉了,我也是试试,因为一直掉,设置以后还没重启过,等重启以后看看有没有掉,再来补充

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值