Uboot_移植_记录_/*嵌入式学习*/

本文档详细记录了U-Boot在ARM11开发板OK6410上的移植过程,包括环境搭建、配置文件修改、启动脚本调整等关键步骤。适合初学者学习及参考。

菜鸟的技术博客

今天完成了通用Uboot 移植于ARM开发板的修改 和 移植工作。我的操作环境是VMware 虚拟机 Ubuntu 10.10。ARM11开发板OK6410。 与其说是自己完成的,还不如说我是借鉴,照搬,套用,挪动...........等等等........呵呵!网上这类帖子挺多的,博友可以借鉴百度文库“我的arm_linux移植笔记.pdf”等等优秀好文。我这里就仅仅总结一下自己的学习过程,以便帮助后来者,并方便自己以后查询。

虽然网络上的资源挺多的,当对一个菜鸟来说,编译起来那漫天的报错还是挺让人头疼的,如有你能找到别人已经做好了的ARM_Uboot,用他们的源码借鉴起来,就能让你学习的更快一些了,我自己就是借鉴飞凌OK6410的源码学习的。好了不罗嗦了,借鉴别人的博文来总结自己的学习过程,开始总结如下。

第一:下载通用u-boot源码。

ftp://ftp.denx.de/pub/u-boot/ 最好下载和你找到的ARM_u-boot 是一个版本的,这样你不会被一些版本上的差别所误导,下载完成后,解压Uboot,我的解压目录是Uboot1.1.6 ,我将它成为我们工作的根目录。

第二:修改Makefile

在根目录下: vim Makefile 然后瞎改交叉编译器环境变量,我修改的是 CROSS_COMPILE ?= /usr/local/arm/4.2.2-eabi/usr/bin/arm-linux- 在OK6410中实在endif 以后创建的该项,我也是按照这个操作的:

第三:建立smdk6410_config 的编译选项,这个也就是你自己指定的ARM版子选项。在当前Makefile中 修改如下:先vim 命令查找:/smdk6410。修改为

smdk6410_config : uconfig

@$(MKCONFIG) $(@:_config=) arm s3c64xx smdk6410 samsung s3c6410

在这里:

arm : 为CPU的架构(ARCH)

s3c64xx : 为CPU的类型(CPU), 其对应于 cpu/s3c64xx 子目录

smdk6410 : 开发板的型号(BOARD) 它对应了 ./board/samsung/smdk6410

samsung : 开发者、或者经销商(vender)

s3c6410 : 片上系统(SOC)

我自己认为:能够充分的理解这一项是很有必要的,尤其是 s3c64xx 和 smdk6410 这两项,因为i额这里是你的开发板的Uboot 入口,在cpu/s3c64xx 和 ./board/samsung/smdk6410 下都是一些很重要的文件。

第四:创建这些依赖性文件。在根目录下执行命令

$cd board

$mkdir samsung/smdk6410

到这里就要拷贝一下板子的.c 依赖文件,网上很多资料是ARM9的 所以资料有点不一样,我拷贝的是三星

smdk6410.c 到我的板载目录./board/samsung/smdk610 下,并且名称也为smdk6410.c 这里不用担心自己

板子是OK6410,而文件名有差别,因为这里是可以通用,并能拿来移植的。

第五:在include/configs/ 中建立配置文件

和上一步的解决办法类似,直接cp smdk6410.h 就行,如果你的configs里面已经有了这一选项,就不用了。

第六:测试编译能否成功

$ make smdk6410_config 如果出现: Configuring for smdk6410 board... 就证明编译正确

第七: 修改 ./cpu/samsung/smdk6410/start.S

这个函数是smdk6410系列的共有启动的汇编代码,UBOOT 执行的第一个程序, 这里我把飞凌这里的start.S 直接copy下来了,可以剩了去修改,但还是需要去学习一下这里的原理,下面是网友有关于ARM9 在start.S 中的修改的主体。 一起来学习一下。

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

(0)修改寄存器地址定义

(1)修改中断禁止部分

(2)修改时钟设置(2440 的主频可达 533MHz,但是我设到 533MHz 时系统很不稳定


(3)将从 Flash 启动改成从 NAND Flash 启动。(特别注意:这和 2410 的程序有不同,不可混用!!!
是拷贝 vivi 的代码。)
将以下 U-Boot 的重定向语句段:
这段代码将uboot搬运到ram中,这个是没有存放在nand的情况,下面咱们来看一下不在nand启动和在nand
启动时此处的区别。
#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */nor中的起始地址给了r0
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */ram中的uboot代码的起始地址(这里
关于uboot搬运这块在内存地址的部分,分了很多段,每一段空间具有不同功能,这是你理解uboot必须掌
握的,非常关键,解释后续会提到些)
cmp r0, r1 /* don't reloc during debug */比较两个地址是否相同,不同则进行下面的搬
运工作


beq stack_setup
在这里你会发现搬运了全部uboot,有的uboot把uboot的c部分搬运到内存_TEXT_BASE里面所放的
地址处。
ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */ _bss_start-_armboot_start= armboot 因为
_armboot_end的结束位置就是bss区的开始位置所以能计算出uboot代码的大小
add r2, r0, r2 /* r2 <- source end address */
以下就是把整个代码搬运到_TEXT_BASE里面所放的地址处,记住是内存地址,哈哈!!
copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */

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

更详细的过程可以查看百度文库里的这篇文章

第八:在./board/samsung/smdk6410/ 加入NAND Flash 杜函数文件,copy vivi中nand_read.c 文件到此文件夹即可:

第九:修改board/samsung/smdk6410/Makefile 文件

OBJS := smdk6410.o nand_read.o flash.o

第十: 修改 include/configs/smdk6410.h 文件,这是ARM9的做法,我没有这样做,这里仅参考,实际情况可能不就是这样了,ARM9 板子添加

/********************************************************************************************************************************/*
* Nandflash Boot
*/
#define CONFIG_S3C2440_NAND_BOOT 1 这处告诉从 nand 启动
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
//#define UBOOT_RAM_BASE 0x33f80000
/* NAND Flash Controller */
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
/* Offset */
#define oNFCONF 0x00
#define oNFCONT 0x04
#define oNFCMD 0x08
#define oNFADDR 0x0c
#define oNFDATA 0x10
#define oNFSTAT 0x20
#define oNFECC 0x2c
/* GPIO */
#define GPIO_CTL_BASE 0x56000000
#define oGPIO_B 0x10
#define oGPIO_CON 0x0 /* R/W, Configures the pins of the port */
#define oGPIO_DAT 0x4 /* R/W, Data register for port */
#define oGPIO_UP 0x8 /* R/W, Pull-up disable register */
#endif /* __CONFIG_H */
*****************************************************************************************************************************/

第十一: 修改./board/samsung/smdk6410/lowlevel_init.S 文件

第十二:修改./board/samsung/smdk6410/smdk6410.c

因为不同的板子对应的GPIO等硬件并不相同,所以没有一定硬件对硬件有一定的把握这里可能不是很好修改,我这里仅仅是用飞凌的Uboot 里面的这个文件。如果你用的是通用Uboot的话可能需要自己修改一下。

更详细的过程可以查看百度文库里的“我的“arm_linux移植笔记.pdf”这篇文章

第十三: 为了实现NAND Flash 的读写 ,再次修改 ./include/configs/smdk6410.h


到这里我并没有把所有的步骤都罗列出来,因为我没有真正的操作过后面的内容,而仅仅是借用了别人的Uboot源码。看来要正真的给一块刚刚出厂的开发板写一个Uboot是一个繁杂,涉猎很广的工作。路还有这么长,认真学习,加油!


/* * (C) Copyright 2000 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * SPDX-License-Identifier: GPL-2.0+ */ /* #define DEBUG */ #include <common.h> #include <autoboot.h> #include <cli.h> #include <version.h> #include <SsRecovery.h> #if defined(CONFIG_XZ) && defined(FACTORY_BOOT_COMPILE) #include <xz/xz.h> #include <xz/xz_config.h> #include <xz/xz_lzma2.h> #include <xz/xz_stream.h> #endif #ifdef FACTORY_BOOT_COMPILE #define BG_GREEN_FONT_WHITE "\033[42;37m" #define COLOR_NONE "\033[0m" #endif DECLARE_GLOBAL_DATA_PTR; /* * Board-specific Platform code can reimplement show_boot_progress () if needed */ __weak void show_boot_progress(int val) {} static void modem_init(void) { #ifdef CONFIG_MODEM_SUPPORT debug("DEBUG: main_loop: gd->do_mdm_init=%lu\n", gd->do_mdm_init); if (gd->do_mdm_init) { char *str = getenv("mdm_cmd"); setenv("preboot", str); /* set or delete definition */ mdm_init(); /* wait for modem connection */ } #endif /* CONFIG_MODEM_SUPPORT */ } static void run_preboot_environment_command(void) { #ifdef CONFIG_PREBOOT char *p; p = getenv("preboot"); if (p != NULL) { # ifdef CONFIG_AUTOBOOT_KEYED int prev = disable_ctrlc(1); /* disable Control C checking */ # endif run_command_list(p, -1, 0); # ifdef CONFIG_AUTOBOOT_KEYED disable_ctrlc(prev); /* restore Control C checking */ # endif } #endif /* CONFIG_PREBOOT */ } #if defined(FACTORY_BOOT_COMPILE) && defined(FACTORY_BOOT_ONLY) /* 当只使用factory_boot时,要将main_loop()中uboot的引导功能编进factory_boot */ #undef FACTORY_BOOT_COMPILE #define U_BOOT_COMPILE #endif /* We come here after U-Boot is initialised and ready to process commands */ void main_loop(void) { #if defined(U_BOOT_COMPILE) || defined(DBG_U_BOOT_COMPILE) const char *s; #endif int ret = 0; bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop"); #ifndef CONFIG_SYS_GENERIC_BOARD puts("Warning: Your board does not use generic board. Please read\n"); puts("doc/README.generic-board and take action. Boards not\n"); puts("upgraded by the late 2014 may break or be removed.\n"); #endif #if defined(CONFIG_TP_SERIAL_FORBIDDEN) && defined(U_BOOT_COMPILE) printf("SERIAL FORBIDDEN!\n"); u16 *p; p = 0x1f203d4c; *p = 0x3010; #endif modem_init(); #ifdef CONFIG_VERSION_VARIABLE setenv("ver", version_string); /* set version variable */ #endif /* CONFIG_VERSION_VARIABLE */ cli_init(); run_preboot_environment_command(); #ifdef CONFIG_AUTO_UPGRADE_SD run_command("sdupgrade", 0); #endif #ifdef CONFIG_SSTAR_AUTORUN_DSTAR run_command("sdstar", 0); #endif #if defined(CONFIG_UPDATE_TFTP) update_tftp(0UL); #endif /* CONFIG_UPDATE_TFTP */ #if defined(CONFIG_CMD_DFU) extern int update_dfu(void); update_dfu(); #endif /* CONFIG_CMD_DFU */ #ifdef CONFIG_MS_EMMC_RECOVERY RecoveryCheck(); #endif #if defined(U_BOOT_COMPILE) || defined(DBG_U_BOOT_COMPILE) s = bootdelay_process(); if (cli_process_fdt(&s)) cli_secure_boot_cmd(s); #ifdef CONFIG_TP_TAPO_SPMINIOS ret = validateFirmwareWithRecover(); if (!ret) { setenv("bootargs", CONFIG_SP_BOOTARGS); } else { setenv("bootargs", CONFIG_SPMINIOS_BOOTARGS); } #endif #ifdef CONFIG_TAPO_NAND_UPGRADE ret = validateFirmwareWithUpgrade(); #endif autoboot_command(s); #endif #ifdef FACTORY_BOOT_COMPILE bootdelay_process(); if (disable_boot()) { printf(BG_GREEN_FONT_WHITE"abort, init eth"COLOR_NONE"...\n"); run_command_list("estart", -1, 0); goto loop; } #ifdef CONFIG_TAPO_NAND_UPGRADE ret = processUboot(); #endif { printf("Firmware check pass!\n"); /* CONFIG_LOADADDR is 0x21000000, the addr for load normal boot image if ISP_IN_FLASH, normal boot image is stored in 0x40000 of flash; or it is stored in 0x30000 of flash. */ //ssc377, not use CONFIG_MS_SPINAND #ifdef CONFIG_MS_NAND_ONEBIN #ifdef BOOTLOADER_OFFSET char cmd_buf[257] = {0}; snprintf(cmd_buf, 256, "nand read.e 0x21000000 0x%0x 0x40000", BOOTLOADER_OFFSET); run_command_list(cmd_buf, -1, 0); #else run_command_list("nand read.e 0x21000000 0x600000 0x40000", -1, 0); #endif #else #ifdef ISP_IN_FLASH printf("IMG_RADIO_LEN defined, RADIO_LEN = 0x%0x\n", RADIO_LEN); char cmd_buf[128] = {0}; snprintf(cmd_buf, 512, "sf probe 0;sf read 0x21000000 0x%0x 0x%0x", BOOTLOADER_OFFSET, BOOTLOADER_LEN); run_command_list(cmd_buf, -1, 0); #else run_command_list("sf probe 0;sf read 0x21000000 0x30000 0x10000", -1, 0); #endif #endif struct xz_buf b; struct xz_dec *s; xz_crc32_init(); /* * Support up to 64 MiB dictionary. The actually needed memory * is allocated once the headers have been parsed. */ s = xz_dec_init(XZ_SINGLE, 16 * 1024); if (s == NULL) { printf("xz_dec_init ERROR!!\n"); } b.in = (unsigned char *)(CONFIG_LOADADDR + NORMAL_BOOT_IMAGE_OFFSET); // ignore 40 bytes image header b.in_pos = 0; b.in_size = NORMAL_BOOT_IMAGE_SIZE; b.out = (unsigned char *)(NORMAL_BOOT_LOADADDR); b.out_pos = 0; b.out_size = NORMAL_BOOT_MAX_SIZE; printf("XZ params: in_addr 0x%x, in_size 0x%x, out_addr 0x%x, out_size 0x%x\n", (unsigned int)b.in, (unsigned int)b.in_size, (unsigned int)b.out, (unsigned int)b.out_size); ret = xz_dec_run(s, &b); printf("XZ: uncompress ret %d, size = %d\n", ret, b.out_size); xz_dec_end(s); /*?a??ì?×aubootuboot???ˉòì3£?êìa£??óé?cache2ù×÷£??′ê1cache?′?aò2??ó°?ì*/ flush_dcache_all(); invalidate_icache_all(); /* NORMAL_BOOT_LOADADDR is 0x220A0000, the addr for running normal boot*/ char run_buf[128] = {0}; snprintf(run_buf, 128, "go 0x%0x", (unsigned char *)NORMAL_BOOT_LOADADDR); run_command(run_buf, 0); } loop: #endif cli_loop(); }
最新发布
10-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值