您的位置:首页 > 其它

请教 u-boot 里面的环境变量的设置 的问题。

2014-04-18 02:00 537 查看
转自: http://www.unixresources.net/linux/clf/driver/archive/00/00/66/83/668357.html
请教 u-boot 里面的环境变量的设置 的问题。

我现在已经把 nor flash的驱动加进去了, 自己写了一小段测试代码,

确实是把一段字符串写进入到nor flash里面去了。

但是saveenv却不行, 仔细一查, 原来好像是 env_relocate()有问题。

首先初始化gd:

我是上仿真器的, 我有4个SRAM , SRAM0(0x30000000) , SRAM1(0x30010000)

,SRAM2(0x30020000) , SRAM3(0x30030000)

我的nor flash的起始地址是 0x10000000 , 大小是 16M ,

127个sector(normal:128k) + 4个parameter sector(每个是32k) ,

我的环境打算放在 第1个快(即 0x10020000) ,

我把TEXT_BASE 设置成了 , SRAM1(0x30010000) ,

SRAM0 (64k)专门放置gd什么的。

/* Pointer is writable since we allocated a register for it */

gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

/* compiler optimization barrier needed for GCC >= 3.4 */

__asm__ __volatile__("": : :"memory");

//	reset_cpu(0);  bob only testing watchdog if works well

memset ((void*)gd, 0, sizeof (gd_t));

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

memset (gd->bd, 0, sizeof (bd_t));


int  env_init(void)

{

if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {

gd->env_addr  = (ulong)&(env_ptr->data);

printf("env_addr=%#08lx
",gd->env_addr);

gd->env_valid = 1;

return(0);

}

gd->env_addr  = (ulong)&default_environment[0];

gd->env_valid = 0;

return (0);

}


而这里 env_ptr 默认是 就是 static env_t *flash_addr = (env_t *)CFG_ENV_ADDR;

即:0x10020000

++++++++++++++++++++++++++++

关键就是 env_relocate()这个函数,

我觉得有问题啊:

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);

输出是这样的:

env_relocate[204] offset = 0x0 , no modify : env_ptr addr=10020000

env_relocate[222] malloced ENV at 00000000

怎么malloc返回的就是 0 呢?

void env_relocate (void)

{

DEBUGF ("%s[%d] offset = 0x%lx  ,  no modify : env_ptr addr=%p
",

__FUNCTION__,__LINE__,gd->reloc_off,env_ptr);

/*

* We must allocate a buffer for the environment

*/

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);

DEBUGF ("%s[%d] malloced ENV at %p
", __FUNCTION__,__LINE__,env_ptr);

/*

* After relocation to RAM, we can always use the "memory" functions

*/

env_get_char = env_get_char_memory;

if (gd->env_valid == 0) {

#if defined(CONFIG_GTH)	|| defined(CFG_ENV_IS_NOWHERE)	/* Environment not changable

*/

puts ("Using default environment

");

#else

puts ("*** Warning - bad CRC, using default environment

");

SHOW_BOOT_PROGRESS (-1);

#endif

if (sizeof(default_environment) > ENV_SIZE)

{

puts ("*** Error - default environment is too large

");

return;

}

memset (env_ptr, 0, sizeof(env_t));

memcpy (env_ptr->data,

default_environment,

sizeof(default_environment));

#ifdef CFG_REDUNDAND_ENVIRONMENT

env_ptr->flags = 0xFF;

#endif

env_crc_update ();

gd->env_valid = 1;

}

else {

env_relocate_spec ();

}

gd->env_addr = (ulong)&(env_ptr->data);

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-19 22:06 Length:408 byte(s)
[Original][Print]
[Top]
其实, 我要问的核心问题就是:

当初始化了 SRAM后, 我要malloc的时候, 返回的地址应该 SRAM的地址才对啊,

假如TEXT_BASE 定义的SDRAM的地址, 那么返回的地址应该就是SDRAM的地址范围才对啊。

返回如果是0 ,肯定就是在nor flash地址范围了, 肯定是错的啊。

不知道大家在移植u-boot的时候 有没有碰到过类似的问题。

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-20 10:19 Length:1,100 byte(s)
[Original][Print]
[Top]
继续看代码:

在 start_armboot() 函数中 ,调用了:

/* armboot_start is defined in the board-specific linker script */

mem_malloc_init (_armboot_start - CFG_MALLOC_LEN); //30006044

/*

* Begin and End of memory area for malloc(), and current "brk"

*/

所以这样看起来, 一旦以后调用malloc 应该获得地址空间就应该是 SRAM的地址啊,

可是我的malloc返回的是 0 , 奇怪了。

static ulong mem_malloc_start = 0;

static ulong mem_malloc_end = 0;

static ulong mem_malloc_brk = 0;

static

void mem_malloc_init (ulong dest_addr)

{

mem_malloc_start = dest_addr;

mem_malloc_end = dest_addr + CFG_MALLOC_LEN;

mem_malloc_brk = mem_malloc_start;

memset ((void *) mem_malloc_start, 0,

mem_malloc_end - mem_malloc_start);

}

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-20 14:26 Length:581 byte(s)
[Original][Print]
[Top]
通过用multi-ICE + realview 调试发现一个奇怪的问题 , 明明c 语言里面是malloc 一次, 结果查看汇编的时候, 就变成了 3次malloc ,

如图:



点击左边的DSM 按钮, 就可以看到汇编:



所以我就疯掉了,

我的内存是有限的, 这么连续三次malloc , 相当于两次leak 啊,

估计后面device_init() 就是因此挂掉了。
----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: tpu Posted:
2007-12-20 16:21 Length:82 byte(s)
[Original][Print]
[Top]
但汇编里面BL malloc只有一次啊,说明只调用了一次。C语言的显示混乱是否跟优化有关呢?
----
精益求精!
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-20 17:56 Length:1,753 byte(s)
[Original][Print]
[Top]
你说得有道理, 看来malloc确实被调用了一次,

接着查一些资料, 查到几篇比较的资料, 比如这个:

href=http://www.cublog.cn/u/26710/showart_402757.html>http://www.cublog.cn/u/26710/sho

wart_402757.html 说得比较好 ,

还有:http://safelab.nku.cn:8080/cgi-bin/topic.cgi?forum=26&topic=64&replynum=

last#bottom

(分析很有深度,让我对u-boot启动后的内存规划比较了解了。

最好的还是下面这个图,太一幕了然了, 以前总是脑子里面没有形成图啊。 :



我想请问的是, 正常的情况(从nor flash启动, SDRAM ok) ,

malloc返回的地址应该是上面图的哪个区域呢?

从 u-boot代码的注释来看:应该是 CFG_MALLOC_LEN 这个区域啊。

/*

* Begin and End of memory area for malloc(), and current "brk"

*/

static ulong mem_malloc_start = 0; static ulong mem_malloc_end = 0; static ulong mem_malloc_brk = 0; static void mem_malloc_init (ulong dest_addr) { mem_malloc_start = dest_addr; mem_malloc_end = dest_addr + CFG_MALLOC_LEN; mem_malloc_brk = mem_malloc_start; memset ((void *) mem_malloc_start, 0, mem_malloc_end - mem_malloc_start); }


大家觉得呢?

我不明白的是, mem_malloc_init () 仅仅是做了上面的动作, malloc怎么就返回

CFG_MALLOC_LEN 地址范围的地址呢? 有详尽分析过 malloc实现的兄弟指点一下啊,

我也仔细再分析一下,分析明白了, 又够一篇经典文章的了。
----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-20 23:54 Length:240 byte(s)
[Original][Print]
[Top]
找到一篇 env_relocate()实现的文章 , 正在分析:

http://blog.chinaunix.net/u1/47239/showart_375478.html

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-21 10:38 Length:2,827 byte(s)
[Original][Print]
[Top]
接着读 env_relocate() 函数: 有两个地方有疑问, 还望研究过的大侠指教:

下面的代码,我删掉了一些无关的部分,

下面的envsize 都是 128k (0x20000)

我的疑问是

1》对于 最开始一句:gd->reloc_off,env_ptr);

这个 gd->reloc 是在哪里赋值的呢? 我用source insight 就没有搜索到arm 平台,

它赋值的情况。

2》从下面的代码看:

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);

就算 malloc成功了, 那就分配了 128k内存

而后面直接就这样了:

memset (env_ptr, 0, sizeof(env_t));

memcpy (env_ptr->data,default_environment,sizeof(default_environment));

我觉得从c语言角度就不对啊, 因为我们并没有对 env_ptr->data 进行malloc分配空间啊。

仅仅给env_ptr分配了128k空间, 就用env_ptr->data 这能行吗?

void env_relocate (void)

{

DEBUGF ("%s[%d] offset = 0x%lx  ,  no modify : env_ptr addr=%p
",

__FUNCTION__,__LINE__,

gd->reloc_off,env_ptr);

/*

* We must allocate a buffer for the environment

*/

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);

DEBUGF ("%s[%d] malloced ENV at %p
", __FUNCTION__,__LINE__,env_ptr);

/*

* After relocation to RAM, we can always use the "memory" functions

*/

env_get_char = env_get_char_memory;

if (gd->env_valid == 0) {

#if defined(CONFIG_GTH)	|| defined(CFG_ENV_IS_NOWHERE)	/* Environment not changable

*/

puts ("Using default environment

");

#else

puts ("*** Warning - bad CRC, using default environment

");

SHOW_BOOT_PROGRESS (-1);

#endif

if (sizeof(default_environment) > ENV_SIZE)

{

puts ("*** Error - default environment is too large

");

return;

}

memset (env_ptr, 0, sizeof(env_t));

memcpy (env_ptr->data,

default_environment,

sizeof(default_environment));

#ifdef CFG_REDUNDAND_ENVIRONMENT

env_ptr->flags = 0xFF;

#endif

env_crc_update ();

gd->env_valid = 1;

}

else {

env_relocate_spec ();

}

gd->env_addr = (ulong)&(env_ptr->data);

#ifdef CONFIG_AMIGAONEG3SE

disable_nvram();

#endif

}

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: kernelworld Posted:
2007-12-24 00:39 Length:552 byte(s)
[Original][Print]
[Top]
出现这种奇怪的现象,首先看看你的地址配置怎么样,因为这已经涉及到操作内存了,

上次的我出现的问题更怪printf()稍微打印内容多一点CPU就复位了,最后问题就是配置

的地址不正确的。

PS:感觉现在的2.0的U-BOOT.好像是很有问题,上次改了几个BUG,一个就是环境变量的取值问题,

一个就是网卡的PING包问题,不知怎么回事,这还是明显的错误,你的U-BOOT来的门道来得正宗了,

这个要注意了,我下的U-BOOT的明显还一个内地的补丁,我当时记得也是到一个比较正式的网站下的。

刚忙完U-BOOT的移植,好久没有来祭坛了。。。欢迎共同讨论问题
----
诗圣曰:语不惊人死不休

我亦曰:技不动人死不休
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-24 09:59 Length:2,244 byte(s)
[Original][Print]
[Top]
谢谢你的分享 , 确实是地址设定的问题 , 问题已经解决了,

malloc 返回 0 , 就是 内存太小了, 导致无法分配更多的内存。

我的memory是这样的:

0x3000 0000 SRAM0 (64k)

0x3001 0000 SRAM1 (64k)

0x3002 0000 SRAM2 (64k)

0x3003 0000 SRAM3 (64k)

.....

0x6000 0000 SDRAM(16MB)

------------------

从上面看的话, SRAM总共才256KB , SDRAM 16MB

而我们是上仿真器的, 因为一开始 代码要下到一个memory 执行,

而此时SDRAM肯定还没有初始化, 因此 ,只好选 SRAM1的地址作为下载地址, SRAM0

存放其他的内容,比如 CFG_MALLOC_LEN , gd ,还有 各种模式的堆栈等。

而在代码中:

void env_relocate (void)

{

DEBUGF ("%s[%d] offset = 0x%lx  ,  no modify : env_ptr addr=%p
",

__FUNCTION__,__LINE__,

gd->reloc_off,env_ptr);

env_ptr = (env_t *)malloc (CFG_ENV_SIZE);

DEBUGF ("%s[%d] malloced ENV at %p
", __FUNCTION__,__LINE__,env_ptr);


而这里 CFG_ENV_SIZE 我定义的是 128k ,( 因为 nor flash的 扇区大小刚好是 128k) ,

而CFG_MALLOC_LEN 我又恰好根据SRAM 大小调整了 ,

include/configs/xx.h

/*------------------------------

* Size of malloc() pool

*-----------------------------*/

#define CFG_MALLOC_LEN	(CFG_ENV_SIZE + 128*1024)	//use for SDRAM(64M)

//#define CFG_MALLOC_LEN	 0xa000	//temp modify to fit for SRAM	--bob


这样的话, malloc 就有可能失败了, 因为SRAM实在太少了。 ]

当以上配置都采用正常值的时候, 直接把 u-boot 烧写到 nor 里面去 执行 , config.mk

里面配置的 TEXT_BASE也改为 SDRAM的相应地址(我是 0x63f80000) , malloc就正常了。

-------------

我总结了一条经验, 仿真器是个好东西, 但是有的时候, 仿真器毕竟不能模仿真实的一切,

所以还要自己调整。

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-24 20:33 Length:2,136 byte(s)
[Original][Print]
[Top]


针对上面的图片, 可以从代码中得到验证:

stack_setup:

ldr	r0, _TEXT_BASE		/* upper 128 KiB: relocated uboot   */

sub	r0, r0, #CFG_MALLOC_LEN	/* malloc area                      */

sub	r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo                        */ 128byte

#ifdef CONFIG_USE_IRQ

sub	r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)

#endif

sub	sp, r0, #12		/* leave 3 words for abort-stack    */


这就和上面的 CFG_MALLOC_LEN 和 GLOBAL_DATA_SIZE 和 irq,FIQ 区域,

第二阶段的代码,做了初始化工作:

/* Pointer is writable since we allocated a register for it */

gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

/* compiler optimization barrier needed for GCC >= 3.4 */

__asm__ __volatile__("": : :"memory");  //内存屏障

memset ((void*)gd, 0, sizeof (gd_t));

gd->bd = (bd_t*)((char*)gd - sizeof(bd_t));

memset (gd->bd, 0, sizeof (bd_t));

//汇编里面分配的 GLOBAL_DATA_SIZE应该是包含 gd和bd的,有128个字节。

monitor_flash_len = _bss_start - _armboot_start;


1, 可是上面图上的 “用户栈区” ,

到底是在哪里分配并初始化的呢?在u-boot代码并没有看到啊?

2, 另外:

/* Pointer is writable since we allocated a register for it */

gd = (gd_t*)(_armboot_start - CFG_MALLOC_LEN - sizeof(gd_t));

/* compiler optimization barrier needed for GCC >= 3.4 */

__asm__ __volatile__("": : :"memory");

上面的 /* Pointer is writable since we allocated a register for it */

什么意思呢?没看明白啊。 (不要翻译哦)

谢谢了。

----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: bob2004 Posted:
2007-12-24 21:26 Length:2,027 byte(s)
[Original][Print]
[Top]
对下面这段经典的relocate的代码, 从细节上(汇编语言角度),我还是有点疑问,

假设 BOARD/SMDK2410/config.mk 里面的 TEXT_BASE 0x63f80000

我们就讨论, u-boot 从nor flash启动的情况:

0,问个汇编的问题, 关于 .word 查了一下, 可是还是没太明白,为什么一定要用word 呢?

比如:

.globl _bss_start

_bss_start:

.word __bss_start

ldr	r2, _armboot_start

ldr	r3, _bss_start

那么 写成这样行吗?

ldr	r3, __bss_start   (这个就是定义在System.map)


1,

relocate:				/* relocate U-Boot to RAM	    */

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


adr 是怎么做到 当从 nor flash启动的时候, 就是 0 , 而debug得时候, 就是0x63f80000

的呢?

2,

ldr	r2, _armboot_start

ldr	r3, _bss_start

sub	r2, r3, r2		/* r2 <- size of armboot            */

add	r2, r0, r2		/* r2 <- source end address         */


当 u-boot已经烧写道nor flash里面的时候,

_start的值是多少呢?

从System.map 来看 _start 是 0x63f80000 ,

而这里又

.globl _start

_start:

b reset

ldr pc, _undefined_instruction

ldr pc, _software_interrupt

ldr pc, _prefetch_abort

ldr pc, _data_abort

ldr pc, _not_used

ldr pc, _irq

ldr pc, _fiq

从这里来看, 从 nor flash 启动的时候, _start的地址应该就是 0 啊, 谁来解释一下啊?

谢谢了。
----
http://KernelChina.cublog.cn
[Original][Print]
[Top]
Subject:Re: 请教 u-boot 里面的环境变量的设置 的问题。

Author: freebsdxjj Posted:
2007-12-26 17:14 Length:750 byte(s)
[Original][Print]
[Top]
我来回答start的问题

System.map 的中的地址有可能是中间过程的地址

start的地址可能是在ld.script中

下面是我的一个ld.script

OUTPUT_ARCH(mips)

ENTRY(entry)

SECTIONS {

. = 0x80300000;

.text : {

*(.text.entry)

*(.text)

*(.rodata)

}

.data : {

*(.data)

}

.bss : {

*(.bss)

}

workspace = .;

}

我的第一个指令位于 entry,从cpu来看的地址是 0x80300000
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: