移植uboot第三步:修改时钟

这个步骤弄死我了,弄了一宿,有很多原因,老是这里那里有问题。
因为是基于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
可以永久取消强制签名,驱动就不会掉了,我也是试试,因为一直掉,设置以后还没重启过,等重启以后看看有没有掉,再来补充

猜你喜欢

转载自blog.csdn.net/ltc844139730/article/details/52171697