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

博主在移植U-Boot过程中遇到环境变量设置问题,详细记录了从nor flash启动时环境变量加载失败的过程,最终发现是因为SRAM空间不足导致malloc失败。

转自: 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);

  

----
[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的时候 有没有碰到过类似的问题。

----
[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);

}

----
[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() 就是因此挂掉了。
----
[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实现的兄弟指点一下啊,
我也仔细再分析一下,分析明白了, 又够一篇经典文章的了。
----
[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
----
[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

}

----
[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就正常了。


-------------
我总结了一条经验, 仿真器是个好东西, 但是有的时候, 仿真器毕竟不能模仿真实的一切,
所以还要自己调整。
----
[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 */
什么意思呢?没看明白啊。 (不要翻译哦)

谢谢了。
----
[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 啊, 谁来解释一下啊?

谢谢了。
 
----
[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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值