U-BOOT-2009.11在MINI2440上移植探索详情

 

S3C2440与S3C2410的区别:

接口:S3C2440增加了摄像头接口,AC’97音频接口,NAND FLASH有较大的变化,主频更高(405M)S3C32410只有203M,芯片时钟芯片频率控制器有一定的变化,其它都是兼容的

时钟系统和电源管理模块由三个部分组成:时钟控制部分,usb控制部分和电源管理部分组成。

所用的S3C2440A有两个锁相环(PLL)一个提供给FCLK,HCLK,PCLK;另一个提供给USB模块(48MHZ)专用的。

首先是建立属于自己的板子 cd u-boot-2009.11/board/Samsung/

Mkdir mini2440 //这就是我们这次的开发板所在目录

选择和s3c2440最为相近的smdk2410作为参考板,将不同的地方修改为我们需要的。

Cp  -rf smdk2410/* mini2440/

Cd  mini2440

Mv   smdk2410.c mini2440.c  //改为自己的板子文件 比较有成就感

修改mini2440文件夹中的makefile COBJS  :=mini2440.o flash.o

在/include/configs文件夹中以smdk2410.h作为模板 制作我们的开发板需要的头文件

Cp smdk2410.h mini2440.h

include/configs/mini2440.h中,添加这类信息参照已有格式即可

#define CONFIG_S3C2440   1 //很重要

 

修改u-boot-2009.11文件夹中的makefile文件 将交叉编译环境修改为 CROSS_COMPILE ?= arm-linux-gcc

在makefile文件中注册我们的板子芯片照着smdk2410_config的格式进行修改:

Mini2440_config : unconfig

         @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0

在这里需要注意 最好是复制上面已有的格式然后修改 如果自己写的话要注意makefile书写格式第二行第一个@前面是Tab键 这个不能用4个空格代替 否则会编译出错。 Samsung表示的是所建立的mini2440目录在board/samsung文件夹中 如果你将mini2440直接建立在board文件夹中则直接写NULL,这个是告诉编译器mini2440在哪

Arm:cpu的架构

Arm920t:cpu的类型

Mini2440:对应在board目录下建立的开发板项目的目录

Samsung:新开发板目录的上级目录,如果直接在board下建立则为NULL

S3c2440: cpu型号

然后测试编译环境:make mini2440_config

Make

编译完成如果在u-boot-2009.11目录中出现u-boot.bin文件,就成功了一小小步。

 

接下来写段小程序验证一下我们制作的u-boot是否在板子上运行起来了(通过led显示)

通过cpu/arm920t/u-boot.lds文件可以知道程序的入口在start.S文件中的_start处,我们进入到start.S文件中看到

.globl _start
_start: b       start_code    //将程序的执行跳转到start_code

说明程序正在的入口在start_code处;

由于u-boot的移植都是采用这种打补丁的方式进行移植的,这个程序中存在了很多其他板子的程序段在,

bl coloured_LED_init  //此处两行是对AT91RM9200DK开发板上的LED进行初始化的
    bl red_LED_on

因为我们在RAM中调试程序cpusupervivi初始化了故注释掉u-boot中的cpu初始化

/*#ifndef CONFIG_SKIP_LOWLEVEL_INIT  

    bl cpu_init_crit

#endif*/

不是我们需要的注释掉我们自己写我们需要的led显示(任何合适的地方)

#if defined(CONFIG_S3C2440)  //区别与其他开发板,这个CONFIG_S3C2440要添加在include/configs/mini2440.h中,添加这类信息参照已有格式即可

#define CONFIG_S3C2440  1 //很重要

//根据mini2440原理图可知LED分别由S3C2440PB5678口来控制,以下是PB端口寄存器基地址(2440DataSheet得知)
#define GPBCON 0x56000050
#define GPBDAT 0x56000054
#define GPBUP  0x56000058    

    //以下对寄存器的操作参照S3C2440DataSheet进行操作
    ldr r0, =GPBUP
    ldr r1, =0x7FF    //即:二进制11111111111

    str r1, [r0]

    ldr r0, =GPBCON   
    ldr r1, =0x15400 

    str r1, [r0]

    ldr r0, =GPBDAT
    ldr r1, =0x1C0   //这里的等号别忘记了写,本人一时大意忘记了写结果就编译出错。
    str r1, [r0]

#endif

//此段代码使u-boot启动后,点亮开发板上的LED1LED2LED3LED4不亮

如果编译成功的话将u-boot.bin文件下载到开发板中(通过友善之臂提供的supervivi下载到内存中)即可看到现象,又成功了一点点。

胜不骄败不馁继续。。。

在u-boot中添加中添加对s3c2440一些寄存器的支持、添加中断禁止部分和时钟设置部分。因为u-boot启动的stage1主要集中在start.S 中所以我们还是修改这个文件。由《u-boot官方移植教程》可以知道linux内核启动时除了内核映像必须在主存的适当位置,cpu还必须具备一定的条件:

第一步要做的事情就是关闭看门狗(现在的狗狗还认不到主人先关起来免得被咬)u-boot中已经做了关闭的工作我们只需要添加defined(CONFIG_S3C2440)

#if defined(CONFIG_S3C2400)|| defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)
    /* turn off the watchdog */

由于s3c2410中的很多寄存器和s3c2440中的一样节约了很多时间(知道要选择类似模板的原因了吧)如

# define pWTCON     0x53000000
# define INTMSK     0x4A000008    /* Interupt-Controller base addresses */
# define INTSUBMSK  0x4A00001C
# define CLKDIVN    0x4C000014    /* clock divisor register */

禁止中断:

 mov  r1, #0xffffffff
    ldr  r0,=INTMSK
    str  r1,[r0]

# if defined(CONFIG_S3C2410)
    ldr  r1,=0x3ff
    ldr  r0,=INTSUBMSK
    str  r1,[r0]
# endif
# if defined(CONFIG_S3C2440)//添加s3c2440的中断禁止部分
    ldr  r1, =0x7fff        //0111 1111 1111根据2440芯片手册,INTSUBMSK寄存器有15位可用  

//INTSUBMSK寄存器在数据手册中的定义


 从这里可以知道1代表屏蔽其使能;

ldr  r0, =INTSUBMSK
    str  r1, [r0]
# endif

//添加s3c2440的时钟部分

关于s3c2440的时钟和电源管理:微处理器主时钟可以由外部晶振或外部时钟提供,选择后可以生成FCLK,HCLK,PCLK时钟信号,其中FCLK信号提供给IP核使用,HCLK提供给IP核和AHB总线,PCLK提供给APB总线使用。

 

FCLK时钟值可以根据MPLLCON寄存器的值来设置。如FCLK的时钟频率为271.5MHZ,通过数据手册上面的PLL VALUE SELECTION TABLE可以得到MPLLCON=0Xad022

FCLK经过HDIV分频和PDIV分频后得到HCLKPCLK,FCLKHCLKPCLK之间的关系设置CLKDIVN寄存器得到,如FCLK:HCLK:PCLK=8:4:1,则CLKDIVN = 0X5

 

 

# if defined(CONFIG_S3C2440)  

#define MPLLCON   0x4C000004   //系统主频配置寄存器基地址

#define UPLLCON   0x4C000008   //USB时钟频率配置寄存器基地址 
    ldr  r0,=CLKDIVN          //设置分频系数FCLK:HCLK:PCLK = 8:4:1
    mov  r1,#5
    str  r1,[r0]

 

    ldr  r0, =MPLLCON  //设置系统主频为405MHz 

    ldr  r1, =0x7F021  //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分

    str  r1, [r0]

 

    ldr  r0, =UPLLCON  //设置USB时钟频率为48MHz 

    ldr  r1, =0x38022  //这个值参考芯片手册“PLL VALUE SELECTION TABLE”部分

    str  r1, [r0]

# else //其他开发板的时钟部分,这里就不用管了,我们现在是做2440

    /* FCLK:HCLK:PCLK = 1:2:4 */
    /* default FCLK is 120 MHz !*/  

    ldr  r0, =CLKDIVN
    mov  r1, #3
    str  r1, [r0]

# endif
#endif    /* CONFIG_S3C2400 || CONFIG_S3C2410 || CONFIG_S3C2440 */

 

 

 

S3C2440的时钟部分除了在start.S中添加外,还要分别在board/samsung/mini2440/mini2440.c和cpu/arm920t/s3c24x0/speed.c中修改或添加部分代码,如下:

(时钟和电源管理块由三部分组成:时钟控制,USB控制和电源的控制)

board/samsung/mini2440/mini2440.c:

#define FCLK_SPEED 2       //设置默认等于2,即下面红色代码部分有效
#if FCLK_SPEED==0          /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV    0xC3
#define M_PDIV    0x4
#define M_SDIV    0x1
#elif FCLK_SPEED==1        /* Fout = 202.8MHz */
#define M_MDIV    0xA1
#define M_PDIV    0x3
#define M_SDIV    0x1
#elifFCLK_SPEED==2        /* Fout = 405MHz */
#defineM_MDIV    0x7F     //这三个值根据S3C2440芯片手册“PLL VALUE SELECTION TABLE”部分进行设置
#define M_PDIV    0x2
#define M_SDIV    0x1
#endif
#define USB_CLOCK 2        //最开始默认为1不是我们想要的,设置默认等于2,即下面红色代码部分有效
#if USB_CLOCK==0
#define U_M_MDIV    0xA1
#define U_M_PDIV    0x3
#define U_M_SDIV    0x1
#elifUSB_CLOCK==1
#define U_M_MDIV    0x48
#define U_M_PDIV    0x3
#define U_M_SDIV    0x2
#elifUSB_CLOCK==2         /* Fout = 48MHz */
#defineU_M_MDIV    0x38   //这三个值根据S3C2440芯片手册“PLL VALUE SELECTION TABLE”部分进行设置
#define U_M_PDIV    0x2
#define U_M_SDIV    0x2
#endif

cpu/arm920t/s3c24x0/speed.c:

static ulong get_PLLCLK(int pllreg)
{
    S3C24X0_CLOCK_POWER *const clk_power = S3C24X0_GetBase_CLOCK_POWER();
    ulong r, m, p, s;

    if(pllreg == MPLL)
    r = clk_power->MPLLCON;
    elseif(pllreg == UPLL)
    r = clk_power->UPLLCON;
    else
    hang();

    m =((r & 0xFF000)>> 12)+ 8;
    p =((r & 0x003F0)>> 4)+ 2;
    s = r & 0x3;

#if defined(CONFIG_S3C2440)
    if(pllreg == MPLL)
    {   //参考S3C2440芯片手册上的公式:PLL=(2 * m * Fin)/(p * 2s)
        return((CONFIG_SYS_CLK_FREQ * m * 2) / (p << s));
    }
#endif

    return((CONFIG_SYS_CLK_FREQ * m)/(p << s));
}

/* return HCLK frequency */
ulong get_HCLK(void)
{
    S3C24X0_CLOCK_POWER *const clk_power = S3C24X0_GetBase_CLOCK_POWER();

#if defined(CONFIG_S3C2440)
    return(get_FCLK()/4);
#endif

    return((clk_power->CLKDIVN & 0x2)? get_FCLK()/2 : get_FCLK());
}

 

和刚才的比较可以看出时钟部分对u-boot的重要性,时钟频率正确才能保证系统的正常工作。从超级终端我们可以看出来显示信息和我们开发板不同 我们的flash是2M而显示的是512K,原因是我们还没有添加nor flash的支持。

(以上移植参考了千兵卫博士的博客http://www.cnblogs.com/doctorqbw/archive/2011/11/16/2251395.html)

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值