• U-BOOT 移植到友善之臂mini2440


    U-BOOT 移植到友善之臂mini2440

    开发环境:ubuntu 10.10
    编译器:友善之臂mini2440光盘自带arm-linux-gcc 4.4.3

    一. 在denx官网下载源码,我所用版本号为u-boot-2010.03。               
    二. 主机编译环境为友善之臂提供的arm-linux-gcc.所參考板子为smdk2410。
    三. 启动第一阶段移植过程

    1.首先測试编译环境,由于arm-linux-gcc,已经增加了PATH环境变量,在lib_arm文件夹下的config.mk 定义了CRPSS_COMPILE 为arm-linux-,而主文件夹下的Makefile包括这个文件,所以交叉编译工具连就已经确定了。无需再改。
    $cd  u-boot-mini2440
    $make smdk2410_config
    $make
    编译通过,说明编译环境没有问题。
    2.建立mini2440配置以及文件
     (1)进入顶层文件夹Makefile,找到:
    smdk2410_config :       unconfig
         @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0
    复制并改动成:
    mini2440_config :       unconfig
         @$(MKCONFIG) $(@:_config=) arm arm920t mini2440 samsung s3c24x0
    注意:@前面是tab键,否则编译配置的时候出错。
                这条命令实际是运行顶层文件夹下的 mkconfig,后面的都是參数

     (2)进入/board/samsung,将smdk2410文件夹,复制成为mini2440.这个是我们的开发板的文件夹。进入mini2440文件夹,改动smdk2410.c为mini2440.c。改动Makefile:

    COBJS   := mini2440.o flash.o

     (3)进入/include/configs,将smdk2410.h,复制成为mini2440.h,这个是我们的配置文件。
    这样我们的开发板的文件就都有了,可是内容都是smdk2410开发板的。
    编译測试
    make clean
    make mini2440_config
    make
    编译通过说明没有问题。
    3. start.S的改动(1)
    @       bl      coloured_LED_init
    @       bl      red_LED_on
    这个mini2440没有彩色灯,所以要凝视掉
    # if defined(CONFIG_S3C2440)
            ldr     r1, =0x3fff
            ldr     r0, =INTSUBMSK
            str     r1, [r0]
    # endif
    由于子中断2440有15个,所以要改一下。
    # if defined(CONFIG_S3C2440)
    #define MPLLCON 0x4c000004
    #define UPLLCON 0x4c000008
            /* FCLK:HCLK:PCLK = 1:2:4 */
            /* default FCLK is 405 MHz ! */
            ldr     r0, =CLKDIVN
            mov     r1, #5
            str     r1, [r0]
            ldr r0, =MPLLCON
            ldr r1, =(0x7f<<12)|(0x02<<4)|(0x01)
            str r1, [r0]
            ldr r0, =UPLLCON
            ldr r1, =(0x38<<12)|(0x02<<4)|(0x02)
            str r1, [r0]
    # else
            /* FCLK:HCLK:PCLK = 1:2:4 */
            /* default FCLK is 120 MHz ! */
            ldr     r0, =CLKDIVN
            mov     r1, #3
            str     r1, [r0]
    #endif  /* CONFIG_S3C2440 */
    以上是S3C2440时钟初始化的代码,能够看出2410和2440时钟初始化还是区别非常大的。
    4.  初始化时钟后,紧接着就是cpu内部初始化。这个函数cpu_init_crit无需改动,可是里面调用的lowlevel_init函数必须改动,由于是初始化内存的代码,每一个开发板的内存都不同,所以lowlevel_init.S在/board/samsung/mini2440文件夹里。
     #define Trp                     0x2     /* 2clk */
     #define REFCNT                  1012   
    

    5. 加入检查代码位置以及推断启动方式的代码

    /*********** CHECK_CODE_POSITION ************/
            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     stack_setup
    /***************** CHECK_CODE_POSITION ****/
    /***************** CHECK_BOOT_FLASH *******/
    #define rBWSCON 0x48000000
            mov     r0, #rBWSCON 
            ldr     r0, [r0]
            bic     r0, r0, #0xfffffff5  /* BWSCON[2:1] is controled by OM[1:0] */
            cmp     r0, #0    /* when OM[1:0] is 00,BSWCON[2:1]=00, nand flash boot */
    
    
            bne     relocate             /* norflash boot */
    /*****************CHECK_BOOT_FLASH*************************/
    检查启动代码位置,是通过比較当前的代码位置和TEXT_BASE之间是否同样来推断的
    而推断启动方式是通过检查BWSCON[2:1]来推断的,详细实现见start.S的分析

    6.加入Nandflash启动代码

    #define LENGTH_UBOOT 0x60000
    #define NAND_CTL_BASE 0x4E000000
    #ifdef CONFIG_S3C2440
    /* Offset */
    #define oNFCONF 0x00
    #define oNFCONT 0x04
    #define oNFCMD 0x08
    #define oNFSTAT 0x20
    	@ reset NAND
    	mov	r1, #NAND_CTL_BASE
    	ldr	r2, =( (7<<12)|(7<<8)|(7<<4)|(0<<0) )
    	str	r2, [r1, #oNFCONF]
    	ldr	r2, [r1, #oNFCONF]
    	ldr	r2, =( (1<<4)|(0<<1)|(1<<0) )	@ Active low CE Control 
    	str	r2, [r1, #oNFCONT]
    	ldr	r2, [r1, #oNFCONT]
    	ldr	r2, =(0x6)	@ RnB Clear
    	str	r2, [r1, #oNFSTAT]
    	ldr	r2, [r1, #oNFSTAT]
    	mov	r2, #0xff	@ RESET command
    	strb	r2, [r1, #oNFCMD]
    	mov	r3, #0	@ wait
    nand1: 
    	add	r3, r3, #0x1
    	cmp	r3, #0xa
    	blt	nand1
    nand2:
    	ldr	r2, [r1, #oNFSTAT]	@ wait ready
    	tst	r2, #0x4
    	beq	nand2
    	ldr	r2, [r1, #oNFCONT]
    	orr	r2, r2, #0x2	@ Flash Memory Chip Disable
    	str	r2, [r1, #oNFCONT]
    	@ get read to call C functions (for nand_read())
    	ldr	sp, DW_STACK_START	@ setup stack pointer
    	mov	fp, #0	@ no previous frame, so fp=0
    	@ copy U-Boot to RAM
    	ldr	r0, =TEXT_BASE
    	mov	r1, #0x0
    	mov	r2, #LENGTH_UBOOT
    	bl	nand_read_ll
    	tst	r0, #0x0
    	beq	ok_nand_read
    bad_nand_read:
    loop2:
    	b	loop2	@ infinite loop
    ok_nand_read:
    	@ verify
    	mov	r0, #0
    	ldr	r1, =TEXT_BASE
    	mov	r2, #0x400	@ 4 bytes * 1024 = 4K-bytes
    go_next:
    	ldr	r3, [r0], #4
    	ldr	r4, [r1], #4
    	teq	r3, r4
    	bne	notmatch
    	subs	r2, r2, #4
    	beq	stack_setup
    	bne	go_next
    notmatch:
    loop3:
    	b	loop3	@ infinite loop
    #endif

    nand_read_ll 这个函数是nand_read.c里面的,这个文件应该在板级文件夹里,加入这个文件到/board/samsung/mini2440里面。而且改动Makefile,使得编译进代码

    COBJS   := mini2440.o flash.o nand_read.o

    到此第一阶段的代码改动完成。由于要測试编译是否通过,而代码中有CONFIG_S3C2440配置,所以要改动mini2440.h。
    7 编译排错:
    (1).发现DW_STACK_START未定义,这个是进入C语言初始话栈的时候用到的,加上定义。
    #define STACK_BASE 0x33f00000
    #define STACK_SIZE 0x10000
            .align  2
    DW_STACK_START: .word   STACK_BASE+STACK_SIZE-4
    (2)发现include/asm/arch/s3c24x0_cpu.h错误,里面定义了CONFIG_S3C2410包括了s3c2410.h,由于我们定义的是CONFIG_S3C2440所以没有包括头文件,所以改一下,将s3c2410.h复制为s3c2440.h。
    (3)  发现s3c2440.h未定义CONFIG_S3C2440,将当中有关CONFIG_S3C2410 的预处理选项都换成CONFIG_S3C2410||CONFIG_S3C2440,这样代码才可以编译进来。
    8 加上led灯显示程序。
    #  if defined(CONFIG_MINI2440_LED)
    #define rGPBCON 0x56000010
    #define rGPBDATA 0x56000014
    #define rGPBUP 0x56000018
            ldr r0, =rGPBCON
            ldr r1, =(0x01<<10)|(0x01<<12)|(0x01<<14)|(0x01<<16)
            str r1, [r0]
            ldr r0, =rGPBUP
            ldr r1, =0x7fff
            str r1, [r0]
            ldr r0, =rGPBDATA
            ldr r1, =(0x1<<5)|(0x0<<6)|(0x1<<7)|(0x0<<8)
            str r1, [r0]
    #endif
    9 改动u-boot.lds 中的链接顺序,由于lowlevel_init.S,和nand_read.c都须要在前4K代码中,改动为
                    cpu/arm920t/start.o     (.text)
                    board/samsung/mini2440/lowlevel_init.o
                    board/samsung/mini2440/nand_read.o
    配置mini2440.h,加入CONFIG_MINI2440_LED宏定义,又一次编译,下载到板子上,假设LED灯,第一个和第三个亮了,其它是灭的。说明程序第一阶段正确运行了。kermit(串口终端)出现乱码,说明串口驱动还没有移植,是正常现象。
    四. 启动第二阶段移植过程
    1.串口初始化改动
            串口实现基本上不用改动什么,串口初始化函数是serial_init,在/drivers/serial/serial_s3c24x0.c中,由于串口要初始化波特率,须要get_PCLK()这个函数,而这个函数在/cpu/arm920t/speed.c里面,2410与2440实现是不同的,所以须要改动这个函数。改动完了,又一次编译出现错误,CAMDIVN未定义,由于2410里面没有这个寄存器,在s3c24x0.h中增加定义就能够了。然后下载到板子上,串口就会出现正常的终端显示。可是非常多命令用不了。由于是其它的驱动没有移植。
    2. LCD终端移植
    參考代码的LCD驱动是通过VFD方式实现的,可是分析一下代码感觉其编程方式让人非常不爽,看了一下LCD实现的方式,更加贴近自己的风格。所以果断转向LCD方式实现LCD终端。
    (1)首先在mini2440.h中加入宏定义
    #define CONFIG_LCD
    #define LCD_VIDEO_ADDR	0x33d00000
    (2)加入2440寄存器
    2410和2440寄存器是一样的,所以仅仅须要添加CONFIG_S3C2440就能够了。
    (3)加入底层LCD驱动代码lcd.c

    将lcd.c复制到/board/samsung/mini2440里面,说明是底层驱动。这个文件是依据參考代码改动而成。

    #include <common.h>
    #include <netdev.h>
    #include <asm/arch/s3c24x0_cpu.h>
    #include <video_fb.h>
    #include <lcd.h>
    #include <asm/io.h>
    
    #if defined(CONFIG_CMD_NAND)
    #include <linux/mtd/nand.h>
    #endif
    
    DECLARE_GLOBAL_DATA_PTR;
    
    #define MVAL		(0)
    #define MVAL_USED 	(0)		//0=each frame   1=rate by MVAL
    #define INVVDEN		(1)		//0=normal       1=inverted
    #define BSWP		(0)		//Byte swap control
    #define HWSWP		(1)		//Half word swap control
    
    
    //TFT 240320
    #define LCD_XSIZE_TFT_240320 	(240)	
    #define LCD_YSIZE_TFT_240320 	(320)
    #define LCD_MEM_SIZE		240*320*16
    
    //TFT240320
    #define HOZVAL_TFT_240320	(LCD_XSIZE_TFT_240320-1)
    #define LINEVAL_TFT_240320	(LCD_YSIZE_TFT_240320-1)
    
    //Timing parameter for NEC3.5"
    #define VBPD_240320		(3)		
    #define VFPD_240320		(10)
    #define VSPW_240320		(1)
    
    #define HBPD_240320		(5)
    #define HFPD_240320		(2)
    #define HSPW_240320_NEC		(36)  //Adjust the horizontal displacement of the screen :tekkamanninja@163.com
    #define HSPW_240320_TD		(23)  //64MB nand mini2440 is 36 ,128MB is 23
    				      //+ : -->    - : <--
    #define CLKVAL_TFT_240320	(3) 	
    //FCLK=101.25MHz,HCLK=50.625MHz,VCLK=6.33MHz
    
    #ifdef CONFIG_LCD 
    
    vidinfo_t panel_info = {
    	LCD_XSIZE_TFT_240320, 
    	LCD_YSIZE_TFT_240320,
    	LCD_BPP
    };
    int lcd_line_length;
    int lcd_color_fg;
    int lcd_color_bg;
    
    void *lcd_base;				/* Start of framebuffer memory	*/
    void *lcd_console_address;		/* Start of console buffer	*/
    
    short console_col;
    short console_row;
    void lcd_ctrl_init (void *lcd_base)
    {
    	struct s3c24x0_lcd * const lcd	 = s3c24x0_get_base_lcd(); 
    	struct s3c2410_nand * const nand = s3c2410_get_base_nand();
    
            /*  select LCM type by env variable */ 
    	 
    	/* Configuration for GTA01 LCM on QT2410 */ 
    	lcd->LCDCON1 = 0x00000378; /* CLKVAL=4, BPPMODE=16bpp, TFT, ENVID=0 */ 
    	lcd->LCDCON2 = (VBPD_240320<<24)|(LINEVAL_TFT_240320<<14)|(VFPD_240320<<6)|(VSPW_240320); 
    	lcd->LCDCON3 = (HBPD_240320<<19)|(HOZVAL_TFT_240320<<8)|(HFPD_240320); 
    
    	if ( (nand->NFCONF) & 0x08 )	{ 
    	lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_TD);
    	}
    	else	{
    	  lcd->LCDCON4 = (MVAL<<8)|(HSPW_240320_NEC);
    	}
    	
    	lcd->LCDCON5 = 0x00000f09; 
    	lcd->LPCSEL  = 0x00000000; 
    	printf("Video: ");
    	printf ("TongBao 240*320 LCD 16bit 565 mode
    ");
    	/* Init LCD base address */
    	writel((((ulong)lcd_base) >> 1), &lcd->LCDSADDR1); 
    	writel((((readl(&lcd->LCDSADDR1))&0x1fffff) + (LCD_XSIZE_TFT_240320+0) * LCD_YSIZE_TFT_240320), &lcd->LCDSADDR2); 
    	writel((LCD_XSIZE_TFT_240320 & 0x7ff), &lcd->LCDSADDR3); 
     
             /* Clear video memory */
            memset((void *)lcd_base, 0, LCD_MEM_SIZE);
     
             /* Enable  Display  */
    	writel((readl(&lcd->LCDCON1) | 0x01), & lcd->LCDCON1); /* ENVID = 1 */
    
    }
    void lcd_enable (void)
    {
    }

    详细实现见u-boot lcd 分析

    (4)定义颜色位数
    由于/common/lcd.c中的默认的颜色是8位的,而统宝的是16位的。所以在mini440.h中定义
    #define LCD_BPP                 LCD_COLOR16
    (5)又一次编译
    make clean
    make mini2440_config
    make
    能够看到终端提示符到LCD上了,可是字是白的,背景是黑的。
    在mini2440.h中定义#define CONFIG_SYS_WHITE_ON_BLACK       1 
    就会反白了。这样才够帅。由于默认是LCD终端提示符,这个是由于注冊设备顺序的缘故,在/common/stdio.c stdio_init函数中,将drv_lcd_init ()放到serial_stdio_init ()后面就能够了。然后又一次编译下载。就会默认串口终端了,能够通过输入 setenv stdout lcd 进行切换。
    (6)加入logo.
    在mini2440.h,定义CONFIG_LCD_LOGO。又一次编译就会出现denx 的开机logo假设还觉的不够帅,加入自己的logo。改动方法,/tools/Makefile
    ifeq ($(LOGO_BMP),)
    LOGO_BMP= logos/ayst.bmp
    endif
    然后将ayst.bmp复制到/tools/logos里面,注意bmp图像是有要求的,宽度要是四的倍数,还得是16位的。仅仅有这样才干正确的显示。
    3. Nandflash驱动移植
    (1)改动底层驱动代码
    改动/drivers/mtd/nand/s3c2410_nand.c
    (2)加入配置
    在mini2440.h中加入Nandflash的配置
    #define	CONFIG_CMD_NAND	1
    /*--------------------------------------------------------------------------------------------
     * NAND flash settings
     */
    #if defined(CONFIG_CMD_NAND)
    #define CONFIG_NAND_S3C2410
    #define CONFIG_SYS_NAND_BASE 0x4E000000 
    #define CONFIG_SYS_MAX_NAND_DEVICE      1       
    #define SECTORSIZE 512
    #define SECTORSIZE_2K 2048
    #define NAND_SECTOR_SIZE SECTORSIZE
    #define NAND_SECTOR_SIZE_2K SECTORSIZE_2K
    #define NAND_BLOCK_MASK 511
    #define NAND_BLOCK_MASK_2K 2047
    #define NAND_MAX_CHIPS 1
    #define CONFIG_MTD_NAND_VERIFY_WRITE 
    #define CONFIG_SYS_64BIT_VSPRINTF               /* needed for nand_util.c */
    #endif  /* CONFIG_CMD_NAND */
    (3)加入2440 nandflash寄存器
    在/include/asm-arm/arch-s3c24x0/s3c24x0.h 中
    #if defined (CONFIG_S3C2440)
    /* NAND FLASH (see S3C2440 manual chapter 6) */
    struct s3c2410_nand {
            u32     NFCONF;
            u32     NFCONT;
            u32     NFCMD;
            u32     NFADDR;
            u32     NFDATA;
            u32     NFMECCD0;
            u32     NFMECCD1;
            u32     NFSECCD;
            u32     NFSTAT;
            u32     NFESTAT0;
            u32     NFESTAT1;
            u32     NFMECC0;
            u32     NFMECC1;
            u32     NFSECC;
            u32     NFSBLK;
            u32     NFEBLK;
    };
    #endif
    4. 网络驱动的移植
    (1)改动网卡初始化代码
    在mini2440.c中加入
    #ifdef CONFIG_DRIVER_DM9000
            rc = dm9000_initialize(bis);
    #endif
    (2)加入配置
    在mini244.h中加入
    #define  CONFIG_CMD_PING	1
    #define CONFIG_NET_MULTI                1
    #define CONFIG_NET_RETRY_COUNT          20
    #define CONFIG_DRIVER_DM9000            1
    #define CONFIG_DM9000_BASE              0x20000300
    #define DM9000_IO                       CONFIG_DM9000_BASE
    #define DM9000_DATA                     (CONFIG_DM9000_BASE+4)
    #define CONFIG_DM9000_USE_16BIT         1
    #define CONFIG_DM9000_NO_SROM           1
    #undef CONFIG_DM9000_DEBUG
    (3)dm9000x.c的改动
    364行
    if (i == 1000) {
    	printf("could not establish link
    ");
    	return 0;
    	break;
    }
    (4)nfs代码的改动
    33行
    #define NFS_TIMEOUT (10*2000UL)
    5 默认环境变量改动
    /*-----------------------------------------------------------------------------------------------------
     *Environment variables setting
     */
    #define CONFIG_BOOTDELAY        5
    #define CONFIG_BOOTARGS         "noinitrd root=/dev/nfs rw nfsroot=192.168.1.111:/home/sun/study/nfsshare/rootfs_qtopia_qt4 ip=192.168.1.230:192.168.1.1::255.255.255.0 console=ttySAC0,115200 init=/linuxrc mem=64M"
    #define CONFIG_ETHADDR          08:08:11:18:12:27
    #define CONFIG_NETMASK          255.255.255.0
    #define CONFIG_IPADDR           192.168.1.230
    #define CONFIG_SERVERIP         192.168.1.111
    #define CONFIG_GATEWAYIP        192.168.1.1
    #define CONFIG_OVERWRITE_ETHADDR_ONCE
    #define CONFIG_BOOTCOMMAND      "tftp 0x30008000 zImage;bootm"
    #if defined(CONFIG_CMD_KGDB)
    #define CONFIG_KGDB_BAUDRATE    115200          /* speed to run kgdb serial port */
    /* what's this ? it's not used anywhere */
    #define CONFIG_KGDB_SER_INDEX   1               /* which serial port to use */
    #endif
    /* timeout values are in ticks */
    #define CONFIG_SYS_FLASH_ERASE_TOUT	(5*CONFIG_SYS_HZ) /* Timeout for Flash Erase */
    #define CONFIG_SYS_FLASH_WRITE_TOUT	(5*CONFIG_SYS_HZ) /* Timeout for Flash Write */
    #define	CONFIG_ENV_IS_IN_NAND	1
    #define CONFIG_ENV_OFFSET		0x40000	/* Total Size of Environment Sector */
    #define CONFIG_ENV_SIZE 0x20000              /*size of environment */

    这个是所处的存储介质,默认的Flash,这里是NandFlash
    /*-----------------------------------------------------------------------------------------------------
     * linux kernel tags
     * This is important for starting kernel
     */
    #define CONFIG_SETUP_MEMORY_TAGS
    #define CONFIG_INITRD_TAG
    #define CONFIG_CMDLINE_TAG
    
    
    #define CONFIG_SYS_HUSH_PARSER
    #define CONFIG_SYS_PROMPT_HUSH_PS2   "> "
    #define CONFIG_CMDLINE_EDITING
    #define CONFIG_AUTO_COMPLETE
    这个标记列表配置对内核启动十分重要,没有就不会启动内核
    五。总结

    本次移植參考tekkamaninja对友善之臂mini2440的移植代码。好多地方都是照搬其代码。由于没有时间的缘故,对一些代码的实现还是不是非常了解。可是对u-boot的主要的软件架构有了一定的了解。自己独创的地方就是推断启动方式上,还有lcd驱动的移植。前一个是參考裸机程序的启动代码写的,后一个全然依照自己对代码的理解移植而成。还是比較成功的。u-boot软件分层结构给了我深刻的印象。还有Makefile的结构也对我非常有启示。这个第一个接触的开源项目。以后还会经经常使用到。

    移植的源代码下载在我的csdn下载资源里http://download.csdn.net/detail/YAOZHENGUO2006/3585685

  • 相关阅读:
    P1536 村村通 题解
    P1551 亲戚题解
    P1185 绘制二叉树 题解
    P3884 [JLOI2009]二叉树问题
    P1087 [NOIP2004 普及组] FBI 树
    P1305 新二叉树题解
    P1229 遍历问题
    P1030 [NOIP2001 普及组] 求先序排列题解
    P1827 [USACO3.4]美国血统 American Heritage 题解
    深度优先搜索dfs 讲解教程
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3805795.html
Copyright © 2020-2023  润新知