程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)

Mini2440之uboot移植之实践单板添加(一)

一、u-boot移植概述

1.1 移植不同的硬件层次

我们要向不同的硬件平台上移植u-boot,我们必须明确不同硬件平台之间的差别。而硬件的差别体现在多个层面上。比如说我们使用的Mini2440开发板,采用的SOC芯片是三星公司的S3C2440,该SOC使用的内核(CPU)是ARM公司设计的ARM920T。ARM920T属于ARM9系列,ARM920T系列内核基于ARMv4架构。

这里以S3C2440为例,我们从芯片手册截取到这款芯片的内部结构图,可以看到S3C2440主要由ARM920核+片内外设组成。

ARM920T里面的又些一下功能单元组成:

  • JTAG:一种调试或者测试芯片的接口,可以通过JTAG接口访问CPU的内部寄存器和挂在总线上的设备,如Flash、RAM等,我们不必过多关注。
  • ARM9TMDI:它才是真正运行程序的。
  • 指令、数据MMU:包括两个C13一起处理内存地址映射的。
  • 指令、数据Cache:包括写回PATAG RAM、写缓冲,一起完成高速缓存的功能。
  • CP15:这里是用于控制MMU和Cache的,还可以控制别的器件,不同的系统配置下是不同的。

从一种硬件平台向另一种硬件平台移植时,需要知道两者之间在哪个硬件层次上开始有区别:

  • 同一种SOC,不同的开发板:那么区别可能就只存在于板载外设,需要修改或添加一些驱动;
  • 同一种内核,不同的SOC,不同的开发板:比如TI基于ARM920T做的SOC和三星基于ARM920T做的SOC,以及更下游厂商做的不同开发板,那么除了板载外设的不同,移植时还要根据不同SOC之间的差别做修改;
  • 同一种架构,不同的内核,不同的SOC,不同的开发板:比如Cortex-A53的板子和Cortex-A57的板子,那么移植的时候,板载外设、SOC、内核相关的程序都可能要修改;
  • 不同的架构,不同的内核,不同的SOC,不同的开发板:比如ARM9的板子和cortex-A8的板子(同出于ARM,架构还有一定的相似性),更有甚者ARM架构的板子和MIPS架构的板子,那么移植的工作量就非常大了,基本上,除了u-boot的硬件无关的程序,所有硬件相关的程序都要修改,修改的程度视两者的差异大小而定;

一般越是上游的厂商面对的不同点越多,而下游的厂商在上游厂商移植的基础上进行,比如ARM提供ARMv4架构以及ARM920T内核相关的程序:

  • 三星再此基础上为其推出的SMDK2410做移植,就只需要提供SOC层面和开发板层面的程序;
  • 下游厂商使用S3C2440做产品,就可以在三星提供的SMDK2410的基础上做一些修改以支持自己的板子;

1.2 u-boot流程图绘制

我们在前面的几篇博客中,我们以smdk2410为例,对u-boot源码进行了分析。那么我们试着将我们前几节介绍的内容连起来。绘制一个u-boot启动流程图:

 

二、u-boot移植步骤

既然我们想要移植u-boot,那么我们首先需要明白u-boot的启动流程。u-boot移植大概可以分为以下几个步骤:

  • 内核级配置和初始化;
  • SOC级别的配置与初始化;
  • board_init_f;
  • u-boot重定位;
  • board_init_r;
  • 启动内核或者处理用户命令;

2.1 内核级配置和初始化

这个主要就是在start.S文件里面那些汇编代码,主要包括:

  • 开启SVC模式,关闭fiq,irq中断;
  • 关闭看门狗
  • 屏蔽所有中断;
  • 设置系统时钟;
  • 执行cpu_init_crit函数;
    • 关闭关闭MMU和cache;
    • lowlevel_init函数;

这部分是和内核息息相关的代码,这部分根据内核的不同,配置略有区别。

2.2 SOC级别的配置与初始化

这部分的内容是比较多的,而且可以说贯穿整个u-boot,但基本上必要的都集中在lowlevel_init,其它的就取决于你是否要在u-boot阶段使用某些硬件资源了。

2.3 board_init_f

这个阶段主要是对u-boot之后重定位进行内存的规划,虽然执行的子函数多,但都不复杂。移植内容少。

2.4 u-boot重定位

这部分代码基本不需要改。

2.5 board_init_r

这个阶段干的事主要就是准备终端,初始化需要用到的硬件资源,如果使用新的驱动模型的话,还要像kernel一样将硬件进行抽象。这个根据自己的需求,用了什么就要改什么。

2.6 启动内核或者处理用户命令

u-boot最大的使命就是启动内核,所以这部分也是核心的内容。board_init_r最后会调用run_main_loop进入一个循环,要么就是直接去启动内核,要么就是进入终端处理用户命令和用户交互。也可以说不用改,差不多已经是纯软件干的事了。

三、添加单板

我们在移植u-boot到Mini2440开发板时,通常会在SMDK2410基础上进行修改,这是三星推出的开发板,使用的是S3C2410这款SOC。其实很多芯片厂商在推出新款SOC的时候,都会推出基于此SOC的开发板,以帮助用户使用该SOC设计产品,从而达到推广该SOC的目的。而三星在推出SMDK2410的时候,也向u-boot官方提供了相应的移植程序,这正是我们移植的重要参照。

S3C2410和S3C2440都是基于ARM920T内核的,由于u-boot-2016.0目前只支持支持S3C2410,所以我们可以直接将S3C2410的单板相关文件都复制为S3C2440的。

3.在board中创建单板目录(board/samsung/smdk2440)

cd board/samsung/
cp smdk2410 -r smdk2440

进入smdk2440路径:

修改文件Kconfig:

复制代码
if TARGET_SMDK2440

config SYS_BOARD
        default "smdk2440"

config SYS_VENDOR
        default "samsung"

config SYS_SOC
        default "s3c24x0"

config SYS_CONFIG_NAME
        default "smdk2440"

endif
复制代码

修改MAINTAINERS文件:

SMDK2440 BOARD
M:      David Müller <d.mueller@elsoft.ch>
S:      Maintained
F:      board/samsung/smdk2440/
F:      include/configs/smdk2440.h
F:      configs/smdk2440_defconfig

从这里可以看到,后面我们还需要创建include/configs/smdk2440.h、configs/smdk2440_defconfig。

修改Makefile文件:

复制代码
#
# (C) Copyright 2000-2006
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# SPDX-License-Identifier:      GPL-2.0+
#

obj-y   := smdk2440.o
obj-y   += lowlevel_init.o
复制代码

smdk2410.c改名为smdk2440.c

mv smdk2410.c smdk2440.c

3.2 创建单板相关头文件(include/configs/smdk2440.h)

同样,我们将include/configs/目录下的smdk2410.h文件复制为smdk2440.h:

cd include/configs
cp smdk2410.h smdk2440.h

这个文件很重要,这里主要用来配置编译u-boot时是否启用某些功能,比如网卡,LCD等,如果定义了,那么将会编译相关模块的代码。

修改smdk2440.h中字符串2410->2440:

#define CONFIG_S3C2440          /* specifically a SAMSUNG S3C2440 SoC */
#define CONFIG_SMDK2440         /* on a SAMSUNG SMDK2440 Board */
复制代码
/*
 * NAND configuration
 */
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2440
#define CONFIG_SYS_S3C2440_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_SYS_NAND_BASE            0x4E000000
#endif
复制代码

3.3 创建defconfig文件

在执行make smdk2440_defconfig,依赖于configs/smdk2440_defconfig文件,所以我们也将smdk2410_defconfig复制过来:

cd configs
cp smdk2410_defconfig smdk2440_defconfig

修改smdk2440_defconfig:

复制代码
CONFIG_ARM=y
CONFIG_TARGET_SMDK2440=y
CONFIG_HUSH_PARSER=y
CONFIG_SYS_PROMPT="SMDK2440 # "
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_CMD_CACHE=y
CONFIG_CMD_EXT2=y
CONFIG_CMD_FAT=y
复制代码

3.4 修改arch/arm/Kconfig文件

vim arch/arm/Kconfig

添加以下内容:

config TARGET_SMDK2440
    bool "Support smdk2440"
    select CPU_ARM920T

source "board/samsung/smdk2440/Kconfig"

3.5 尝试配置并编译

在做完上述步骤的时候,我们就完成了S3C2440单板的添加,虽然都是复制S3C2410的,但我们只要在S3C2410的配置文件基础上进行修改即可。

make smdk2440_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux- V=1

第一步可以编译成功,第二步会编译失败,主要是因为我们在include/configs/smdk2440.h中配置了NAND,但是我们没有移植相关代码。

四、 内核级配置和初始化(arch/arm/cpu/arm920t/start.S)

我们首先来分析arch/arm/cpu/arm920t/start.S文件,看看有没有需要修改的地方。

我们需要修改的第一处就是时钟系统设置。初始化系统时钟 FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz 。

复制代码
#ifdef CONFIG_S3C24X0
        /* turn off the watchdog */

# if defined(CONFIG_S3C2400)
#  define pWTCON        0x15300000
#  define INTMSK        0x14400008      /* Interrupt-Controller base addresses */
#  define CLKDIVN       0x14800014      /* clock divisor register */
#else
#  define pWTCON        0x53000000
#  define INTMSK        0x4A000008      /* Interrupt-Controller base addresses */
#  define INTSUBMSK     0x4A00001C
/*  初始化系统时钟 FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz  */
#  define LOCKTIME      0x4c000000
#  define MPLLCON       0x4c000004
#  define UPLLCON       0x4c000008
#  define CLKDIVN       0x4c000014
#  define M_MDIV        92       /* Fin=12M  UPLL=400M  */
#  define M_PDIV        1
#  define M_SDIV        1
#  define U_MDIV        56        /* Fin=12M  UPLL=48M  */
#  define U_PDIV        2
#  define U_SDIV        2
#  define DIVN_UPLL     0         /* FCLK:HCLK:PCLK=1:4:8 */
#  define HDIVN         2
#  define PDIVN         1
# endif

        ldr     r0, =pWTCON
        mov     r1, #0x0
        str     r1, [r0]

        /*
         * mask all IRQs by setting all bits in the INTMR - default
         */
        mov     r1, #0xffffffff
        ldr     r0, =INTMSK
        str     r1, [r0]
# if defined(CONFIG_S3C2410)
        ldr     r1, =0x3ff
        ldr     r0, =INTSUBMSK
        str     r1, [r0]
# endif

        /* 设置Lock Time  */
        ldr     r0, =LOCKTIME
        ldr     r1, =0xffffffff
        str     r1, [r0]

        /* 设置分频系数 */
        ldr     r0, =CLKDIVN
        ldr     r1, =((DIVN_UPLL<<3) | HDIVN <<1 | PDIVN)
        str     r1, [r0]

        /* CPU改为异步总线模式 */
        mrc      p15,0,r1,c1,c0,0
        orr      r1, r1,#0xC0000000
        mcr      p15,0,r1,c1,c0,0

        /* 设置UPLL */
        ldr      r0, =UPLLCON
        ldr      r1, =((U_MDIV<<12) | (U_PDIV<<4) | U_SDIV)
        str      r1, [r0]

        nop
        nop
        nop
        nop
        nop
        nop
        nop

        /* 设置MPLL */
        ldr     r0, =MPLLCON
        ldr     r1, =((M_MDIV << 12) | (M_PDIV << 4) | M_SDIV)
        str     r1, [r0]

#endif  /* CONFIG_S3C24X0 */
复制代码

五、SOC级别的配置与初始化(board/samsung/smdk2440/lowlevel_init.S)

在lowlevel_init.S文件中主要包含初始化SDRAM的代码。SDRAM的初始化取决于我们外接的SDRAM芯片

以Mini2440开发板为例:将两片32MB,16位宽SDRAM内存(型号HY57V561620FTP)焊接在Bank6,并联形成64M,32位内存。因此这里我们主要关注Bandk6相关的配置。

我们将源代码中的配置和Mini2440裸机开发之存储器控制器中的代码做个对比,我们需要修改以下几处:

#define REFCNT            1269     /* period=7.8125us, HCLK=60Mhz, (2048+1-7.8125*100) */

更改BANKSIZE为0xB1:

复制代码
SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0xB1
    .word 0x30
    .word 0x30
复制代码

 六、 board_init_f

既然在start.S中已经进行时钟频率设置了,那在board_init_f中就没必要进行时钟频率设置了。

其中board_early_init_f这个函数定义在board/samsung/smdk2440/smdk2440.c,在里面进行时钟频率设置,所以我们需要修改这个函数中的内容,去掉时钟频率设置。

将board_early_init_f函数修改如下:

复制代码
int board_early_init_f(void)
{
        struct s3c24x0_clock_power * const clk_power =
                                        s3c24x0_get_base_clock_power();
        struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();

        /* 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);

        /* some delay between MPLL and UPLL */
//      pll_delay(4000);

        /* configure UPLL */
//      writel((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV,
//             &clk_power->upllcon);

        /* some delay between MPLL and UPLL */
//      pll_delay(8000);

        /* set up the I/O ports */
        writel(0x007FFFFF, &gpio->gpacon);
        writel(0x00044555, &gpio->gpbcon);
        writel(0x000007FF, &gpio->gpbup);
        writel(0xAAAAAAAA, &gpio->gpccon);
        writel(0x0000FFFF, &gpio->gpcup);
        writel(0xAAAAAAAA, &gpio->gpdcon);
        writel(0x0000FFFF, &gpio->gpdup);
        writel(0xAAAAAAAA, &gpio->gpecon);
        writel(0x0000FFFF, &gpio->gpeup);
        writel(0x000055AA, &gpio->gpfcon);
        writel(0x000000FF, &gpio->gpfup);
        writel(0xFF95FFBA, &gpio->gpgcon);
        writel(0x0000FFFF, &gpio->gpgup);
        writel(0x002AFAAA, &gpio->gphcon);
        writel(0x000007FF, &gpio->gphup);

        return 0;
}
复制代码

串口初始化函数serial_init在初始化串口0的时候,会利用get_PCLK方法(位于arch/arm/cpu/arm920t/s3c24x0/speed.c)获取PCLK时钟频率,然后计算波特率,根据实际情况判断是否需要修改该方法。

复制代码
/* return HCLK frequency */
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
}

/* return PCLK frequency */
ulong get_PCLK(void)
{
        struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();

        return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK();
}
复制代码

七、u-boot重定位

 这一块代码我们不做修改。

八、 board_init_r

亲爱的读者和支持者们,自动博客加入了打赏功能,陆陆续续收到了各位老铁的打赏。在此,我想由衷地感谢每一位对我们博客的支持和打赏。你们的慷慨与支持,是我们前行的动力与源泉。

日期姓名金额
2023-09-06*源19
2023-09-11*朝科88
2023-09-21*号5
2023-09-16*真60
2023-10-26*通9.9
2023-11-04*慎0.66
2023-11-24*恩0.01
2023-12-30I*B1
2024-01-28*兴20
2024-02-01QYing20
2024-02-11*督6
2024-02-18一*x1
2024-02-20c*l18.88
2024-01-01*I5
2024-04-08*程150
2024-04-18*超20
2024-04-26.*V30
2024-05-08D*W5
2024-05-29*辉20
2024-05-30*雄10
2024-06-08*:10
2024-06-23小狮子666
2024-06-28*s6.66
2024-06-29*炼1
2024-06-30*!1
2024-07-08*方20
2024-07-18A*16.66
2024-07-31*北12
2024-08-13*基1
2024-08-23n*s2
2024-09-02*源50
2024-09-04*J2
2024-09-06*强8.8
2024-09-09*波1
2024-09-10*口1
2024-09-10*波1
2024-09-12*波10
2024-09-18*明1.68
2024-09-26B*h10
2024-09-3010
2024-10-02M*i1
2024-10-14*朋10
2024-10-22*海10
2024-10-23*南10
2024-10-26*节6.66
2024-10-27*o5
2024-10-28W*F6.66
2024-10-29R*n6.66
2024-11-02*球6
2024-11-021*鑫6.66
2024-11-25*沙5
2024-11-29C*n2.88
posted @   大奥特曼打小怪兽  阅读(1403)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
如果有任何技术小问题,欢迎大家交流沟通,共同进步

公告 & 打赏

>>

欢迎打赏支持我 ^_^

最新公告

程序项目代做,有需求私信(小程序、网站、爬虫、电路板设计、驱动、应用程序开发、毕设疑难问题处理等)。

了解更多

点击右上角即可分享
微信分享提示