打印

u-boot1.2 for smartarm2200试用版

[复制链接]
2054|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
歪 歪|  楼主 | 2010-9-10 08:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
歪 歪|  楼主 | 2010-9-10 08:53 | 只看该作者
****************************************************
* u-boot(uboot)在EasyARM2200和SmartARM2200上的移植 *
****************************************************
                          ------ 浅谈《ecos增值包》在辅助开发方面的用途
    2007/03/25  asdjf@163.com  www.armecos.com

    现在想学习GNU/Linux的网友越来越多,但是很多人找不到切入点,如何才能利用现有的资源轻松进入呢?如果你手头有EasyARM2200和/或SmartARM2200开发板,那么,下面**介绍的方法或许对你有用......
    --------------------
    | 学习u-boot的好处 |
    --------------------
    好处可多啦:
        (1)学习GNU开发工具链的使用,如:makefile写法、常用shell命令、gcc等;
        (2)学习的副产品---u-boot可以用来引导uCLinux/Linux、WinCE等操作系统;
        (3)学习程序编写,看专家写的程序本身就是一种美的享受;
        (4)借鉴(抄)其中的设备驱动,u-boot支持的CPU和外围硬件很丰富;
        ......
    总之,最好研究一下u-boot,不只是为了得到一个bootloader,更重要的是为学习GNU/Linux打基础。
   
    --------------
    | 初学者难点 |
    --------------
    经常在网上看到类似的提问:cygwin怎么工作不正常?gcc命令为什么找不到?编译怎么一大堆错误?我是不是要装Linux环境?那得花一天时间啊!如何装虚拟机?如何在虚拟机和windows间互传文件?......
    初学者遇到的最大难点是环境搭建。听起来好笑,但很多网友就是由于未能搭建好开发环境或者开发环境出问题,导致迟迟不能迈出第一步,耽误了宝贵的时间。其实最难的是第一步,走过这一步,后面就是一马平川了。
   
    --------------------------
    | 《ecos增值包》解决方案 |
    --------------------------
    开发平台采用“cygwin + gcc for arm + redboot”。
   
    redboot和u-boot一样都是bootloader,支持串口/网口下载、烧录flash、查看内存等功能,利用ecos中已有的redboot来调试u-boot可以避免反复烧写flash,尽管flash可烧写十万次,但在RAM里调试程序仍是好习惯。
   
    GNU开发工具链支持很多种体系架构,没有版权限制,大部分开源软件都是用GNU编译器开发。光盘中提供编译好的GNUTOOLS for ARM,当然,如果你感兴趣,可以自己从源码制作工具(binutils、gcc、gdb等),这样可以自行升级工具版本,《ecos增值包》提供step by step的指导。
   
    cygwin是虚拟机,可以在windows上虚拟类UNIX的shell界面,相当于windows应用程序。使用cygwin的好处是简单方便,只要5-15分钟就可以搭建起环境。大部分人使用的是windows系统,尤其是初学者,纯Linux系统环境并不是最佳选择。如果装VmWare虚拟机,情况会好些,但在windows和虚拟机间交换文件(FTP、Samba等)也不容易。使用cygwin是最简单的方式,用户可以直接在windows下使用UltraEdit、VC6、文件搜索、文件比较等工具,考虑到大多数人的实际情况,采用cygwin开发比较现实。也许有人热衷于纯Linux环境,也许有人对cygwin存有偏见,但绝大部分情况是,cygwin没有问题,而是使用cygwin的人出了差错。其实,cygwin非常可靠易用,从原理上讲,它和纯Linux环境的执行效果是完全一样的。cygwin经常遭人诟病的是其执行效率低,这是事实,但对于编译100多K大小u-boot程序的初学者来说,此速度损失可忽略不计。而且make只会编译受改变影响的相关文件,加上使用已编译的库,即使编译大程序,执行速度也可以接受。
   
    顺便说下,《ecos增值包》可不仅仅只是做这个用途的,这只是它的一个很小的应用。它还提供web server、ftp server、lwip、GUI、TCP/IP、FS、视频监控、税控机、行驶记录仪、自动绣花纺织机、远程监控、通信设备等应用,以后会陆续给出例子。
   
    ------------------
    | u-boot移植规划 |
    ------------------
    u-boot的功能很强大,决定先做以下驱动:
    (1)串口驱动。用于串口下载程序和命令行调试界面;
    (2)Flash驱动。保存参数,存储文件;
    (3)网络驱动。实现TFTP和NFS。
   
    暂时没有实现的是:(主要是因为EasyARM2200上没有这些设备)
    USB host、NAND Flash、PCMCIA(CF)、RTC、reset等。
   
    ------------------
    | u-boot结构分析 |
    ------------------
    从ecos的观点(学习ecos就是好啊,看问题都抽象了^_^),u-boot包含了三个抽象层:
    (1)体系结构抽象层
        EasyARM2200和SmartARM2200使用LPC2210芯片,属于ARM7体系架构,u-boot已经提供了(或抽象了)通用的ARM驱动程序,即lib_arm目录。
    (2)变种抽象层
        很多公司都生产ARM(7)芯片,LPC2210是NXP公司设计的,基于ARM7的变种。其他如s3c44b0、pxa、ixp、arm946等都是不同芯片公司生产的ARM体系的变种。在cpu/目录下,就是各种变种的驱动目录,在此,我们增加cpu/lpc2xxx/目录。主要完成程序搬移、串口驱动、中断处理。
   
    (3)平台抽象层
        很多制造商都使用LPC2210芯片生产设备,EasyARM2200和SmartARM2200是zlg Co.生产的两款不同的硬件平台,虽然都使用LPC2210,但地址分配不同,外围设备不同(“价格差别也很大”)。在board/目录下就是各种不同硬件平台的驱动,在此,我们加入board/easyarm2200或board/smartarm2200目录。主要完成板子上电初始化、TEXT_BASE初始化、链接脚本lds、flash初始化。

    除了这3个目录及文件,还有一些与移植有关:
   
    include/configs/ZLGARM2200.h 这个头文件用于配置开发板平台,如各种参数、地址范围、功能选择等。实际使用时将ZLGARM2200.h换成相应的EasyARM2200.h或SmartARM2200.h
   
    include/configs/asm-arm/arch-lpc2xxx/hardware.h 这个头文件定义开发板的各种寄存器地址宏,操作宏、初始化宏。
   
    Makefile 这个文件里要增加开发板的配置选项,ZLGARM2200_config(实际使用时将ZLGARM2200_config换成相应的EasyARM2200_config或SmartARM2200_config)。还有要把交叉编译前缀“#CROSS_COMPILE = arm-linux-”换成“CROSS_COMPILE = arm-elf-”
   
    还有一些需要改动的文件:
    drivers/rtl8019.h 主要是适应8019的8位数据接口。
   
    为了清晰起见,将要修改的目录文件总结如下:(小技巧:把这些目录或文件做成快捷方式放在桌面上)
    board/easyarm2200/
    cpu/lpc2xxx/
    include/configs/asm-arm/arch-lpc2xxx/hardware.h
    include/configs/EASYARM2200.h
    drivers/rtl8019.h
    Makefile
   
    ------------------------
    | u-boot各部分移植详述 |
    ------------------------
    u-boot不支持LPC2210,所以需要新增加变种和平台抽象层目录board/easyarm2200/和cpu/lpc2xxx/;以及配置文件hardware.h和EASYARM2200.h;同时,有些不适应的文件需要修改,如rtl8019.h和Makefile。
   
    Makefile要修改的是:
---------------------------------------------------------------------------
#CROSS_COMPILE = arm-linux-
CROSS_COMPILE = arm-elf-
   
#########################################################################
## EASYARM2200 Systems
#########################################################################

EASYARM2200_config        :        unconfig
        @$(MKCONFIG) $(@:_config=) arm lpc2xxx EASYARM2200 easyarm2200
   
---------------------------------------------------------------------------

    drivers/rtl8019.h要修改的是:
---------------------------------------------------------------------------
#define                RTL8019_REG_00                        (RTL8019_BASE + 0x00 * 2)
......
---------------------------------------------------------------------------

   include/configs/asm-arm/arch-lpc2xxx/hardware.h
---------------------------------------------------------------------------
// UART

#define LPC2XXX_UART0_BASE        0xE000C000
#define LPC2XXX_UART1_BASE        0xE0010000

#define LPC2XXX_UART_RBR          0x00
#define LPC2XXX_UART_THR          0x00
#define LPC2XXX_UART_IER          0x04
#define LPC2XXX_UART_IIR          0x08
#define LPC2XXX_UART_FCR          0x08
......
---------------------------------------------------------------------------

    include/configs/EASYARM2200.h
---------------------------------------------------------------------------
#define DEBUG 10

#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
                            CFG_CMD_DATE | \
                             CFG_CMD_ELF | \
                             CFG_CMD_NET | \
                             CFG_CMD_ENV | CFG_CMD_FLASH )

/*
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS        1           /* we have 1 banks of DRAM */
#define PHYS_SDRAM_1                0x81000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE        0x00800000 /* 8 MB */

#define PHYS_FLASH_1                0x80000000 /* Flash Bank #1 */
#define PHYS_FLASH_SIZE                0x00200000 /* 2 MB */

#define CFG_FLASH_BASE                PHYS_FLASH_1
......
---------------------------------------------------------------------------

    cpu/lpc2xxx/
---------------------------------------------------------------------------
========
serial.c
========
static int serial_flush_input(void)
static int serial_flush_output(void)
void serial_putc (const char c)
int serial_tstc (void)

void serial_setbrg (void)
{
        unsigned char * base = (unsigned char *)LPC2XXX_UART0_BASE;

        HAL_WRITE_UINT8(base + LPC2XXX_UART_LCR,LPC2XXX_UART_LCR_DLAB);
   
        HAL_WRITE_UINT8(base+LPC2XXX_UART_DLM, SIO_BRDDIV / 256);
        HAL_WRITE_UINT8(base+LPC2XXX_UART_DLL, SIO_BRDDIV % 256);
   
        // 8-1-no parity.
        HAL_WRITE_UINT8(base + LPC2XXX_UART_LCR,
                     LPC2XXX_UART_LCR_8_DBITS | LPC2XXX_UART_LCR_1_SBITS | LPC2XXX_UART_LCR_NO_PARITY);
}
int serial_getc (void)
{
        int rv;
        unsigned int c;
        unsigned char ch;

        for(;;) {
                rv = serial_tstc();

                if(rv > 0){
                        HAL_READ_UINT8(LPC2XXX_UART0_BASE+LPC2XXX_UART_RBR, c);
                        ch = (unsigned char)(c & 0xFF);
                        return ch;
                }
        }
}

=======
start.S
=======
如果从ROM里启动,那么开始部分的reset代码地址为80000030。用arm-elf-objdump -d u-boot > 1.txt得知reset偏址。
.globl _start
_start:       
        ldr        pc, =0x80000030
加载位置TEXT_BASE在easyarm2200中是0x81060000,在smartarm2200中是0x817c0000。

/*************************************************/
/*        interrupt vectors        */
/*************************************************/
real_vectors:
        ldr     pc,.reset                  //0x00
        ldr     pc,.undefined_instruction  //0x04
        ldr     pc,.software_interrupt     //0x08
        ldr     pc,.prefetch_abort         //0x0C
        ldr     pc,.data_abort             //0x10
        ldr     pc,.not_used               //0x14
        ldr     pc,.irq                    //0x18
        ldr     pc,.fiq                    //0x1C

/*************************************************/

.reset:                 .word     reset
.undefined_instruction: .word     undefined_instruction
.software_interrupt:    .word     software_interrupt
.prefetch_abort:        .word     prefetch_abort
.data_abort:            .word     data_abort
.not_used:              .word     not_used
.irq:                   .word     irq
.fiq:                   .word     fiq
......

============
interrupts.c
============
void udelay (unsigned long usec)
int interrupt_init (void)
---------------------------------------------------------------------------

    board/easyarm2200/
---------------------------------------------------------------------------
=====================
EASYARM2200/config.mk
=====================
TEXT_BASE = 0x817C0000
PLATFORM_CPPFLAGS += -Uarm

===========================
EASYARM2200/lowlevel_init.S
===========================
#include <asm/hardware.h>

.globl lowlevel_init
lowlevel_init:

    PLATFORM_SETUP1
   
    mov pc, lr

==============
common/flash.c
==============
static ulong flash_get_size (vu_long *addr, flash_info_t *info)
......
        case (CFG_FLASH_WORD_SIZE)SST_ID_xF1601:
        case (CFG_FLASH_WORD_SIZE)SST_ID_xF160A:
                info->flash_id += FLASH_SST160A;
                info->sector_count = 32;
                info->size = 0x00200000;
                break;                                /* => 2 MB                */
......
---------------------------------------------------------------------------

    ------------------
    | u-boot移植难点 |
    ------------------
    board/easyarm2200/EASYARM2200/config.mk中的TEXT_BASE决定u-boot在RAM中的加载位置,board/easyarm2200/EASYARM2200/u-boot.lds中虽然使用“. = 0x00000000;”,但config.mk中的LDFLAGS标志“LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS)”却将text段指定在了$(TEXT_BASE),所以,最终text段的位置由TEXT_BASE决定。
    cpu/lpc2xxx/start.S中判断程序是否位于指定加载位置,如果不是,就把代码搬移到TEXT_BASE指定位置,注意:“adr r0, _start”是把当前代码位置赋给r0,可不是“mov r0, _start”。
        adr        r0, _start                /* r0 <- current position of code   */
        ldr        r1, _TEXT_BASE                /* test if we run from flash or RAM */
        cmp     r0, r1                  /* don't reloc during debug         */
        beq     copy_vector
        内存搬移
    copy_vector:
   
    cpu/lpc2xxx/start.S中的中断向量表要按照给出的方式定义,否则,中断可能无法长跳转到中断服务子程序,导致uClinux运行不正常(在开中断cli后,跳不到中断服务子程序)。
   
    u-boot的平台配置文件include/configs/EASYARM2200.h需要仔细设置,注意不要引起地址冲突,u-boot自身需要占用一部分flash和内存空间,注意确保这些空间不被使用。
   
    u-boot上电后会自动枚举flash,通过flash ID判断加载适当驱动,u-boot已经支持开发板的flash驱动了,出问题的话主要是没有找到对应ID,加上即可。
   
    8019驱动u-boot也支持,主要是寄存器访问要改。
   
    LPC2210没有cache和SDRAM,简化了移植工作。
   
    ------------------
    | u-boot编译方法 |
    ------------------
cd /u-boot-1.2.0        进入u-boot目录。小技巧:输入cd/u-,然后按TAB键,shell会自动补全路径,很方便。
make clean              清除垃圾,只第一次需要,以后可不用此步骤。有时编译不正确,清一下垃圾就好了。
make EASYARM2200_config 配置EASYARM2200开发板编译环境,生成config.h和指定体系结构、平台、变种、配置文件名等。只第一次需要。
make                    编译
   
    ------------------
    | u-boot使用方法 |
    ------------------
    u-boot功能强大,命令很多,详细使用方法可以在网上查找到,这里只给出一些范例。
    help      帮助命令,可用“?”代替,可以用“help 指令”形式获得更详细说明。
    printenv  打印环境变量
   
    setenv ethaddr 12:34:56:78:9A:BC
    setenv ipaddr 192.168.0.6
    setenv serverip 192.168.0.1     (tftp服务器的地址)
    tftp 81200000 a.bin  把server(IP=环境变量中设置的serverip)中/tftproot/下的a.bin通过TFTP读入到内存0x81200000处。
   
    saveenv  保存环境变量到flash等不挥发的存储设备上。
   
    nfs 32000000 192.168.0.1:aa.txt  把192.168.0.1(LINUX的NFS文件系统)上的NFS文件系统中的aa.txt 读入内存0x32000000处。
   
    ----------------------------------
    | 《ecos增值软件包》辅助开发方法 |
    ----------------------------------
    开发调试u-boot非常困难,因为串口还没有正常工作,如果出现问题,很难调试,而大多数初学者又没有仿真器,所以,这一状况更显严峻。当然不反对使用仿真器,不过使用一根串口线配合redboot也可以做到,调试效率不是很低,没有办法的办法。
   
    每次编译完u-boot,就用redboot下载到内存调试运行:
    lo -b 0x817c0000 -r -m xmodem
    go 0x817c0000
   
    程序可能出错,使用内存打印技术发现问题:
    汇编中内存打印
        ldr r1, =0x81040000
        add r1, r1, #2
        mov r0, #'a'
        strb r0,[r1]
        add r1,r1,#1
        mov r0, #'2'
        strb r0,[r1]
    C程序中内存打印
        unsigned char *yybuf = 0x81030000;

        *(unsigned char *)yybuf++ = 'y';
        *(unsigned char *)yybuf++ = '1';
   
    把这些语句加到合适的地方,出错后,使用:
    du -b 0x81040000 -l 300
    就可以看到打印语句的输出(十六进制和ASCII码显示),通过判断打印语句的情况,就可以了解程序运行情况。
    当然,在使用显存前要先清零:
    mfill -b 0x81040000 -l 300 -p 0
   
    在RAM里调试的好处是不必反复烧写flash,一旦调试正确,就可以固化。
   
    由此可见,有了《ecos增值软件包》辅助开发,u-boot移植再也不是什么难事了,调试手段也够用,cygwin环境很方便,gcc编译器适用于各种体系结构,编译调试u-boot可以为使用Linux打基础,还能借鉴许多现成代码。
   
    使用EasyARM2200和SmartARM2200的初学者现在就可以开始动手玩u-boot了,一般5-15分钟就可以搭建好开发环境,三天之内怎么也能跑起来了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

39

主题

790

帖子

3

粉丝