文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>[原创]u-boot 里面的环境变量的设置 的问题。 07..

[原创]u-boot 里面的环境变量的设置 的问题。 07..

时间:2009-07-07  来源:bob_zhang2004

http://www.linuxforum.net/forum/showflat.php?Cat=&Board=driver&Number=668357&page=0&view=collapsed&sb=5&o=31&fpart=  
 
bob2004
(old hand)
07-12-19 22:06
请教 u-boot 里面的环境变量的设置 的问题。
编辑  回复 

请教 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\n",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\n",
__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\n", __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\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
SHOW_BOOT_PROGRESS (-1);
#endif

if (sizeof(default_environment) > ENV_SIZE)
{
puts ("*** Error - default environment is too large\n\n");
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

文章选项:      

bob2004
(old hand)
07-12-19 22:06
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 

其实, 我要问的核心问题就是:

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

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

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

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

--------------------
http://KernelChina.cublog.cn

文章选项:      

bob2004
(old hand)
07-12-20 10:19
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 

继续看代码:

在 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

文章选项:      

bob2004
(old hand)
07-12-20 14:26
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 

通过用multi-ICE + realview 调试发现一个奇怪的问题 , 明明c 语言里面是malloc 一次, 结果查看汇编的时候, 就变成了 3次malloc ,

如图:


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


所以我就疯掉了,

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

估计后面device_init() 就是因此挂掉了。

--------------------
http://KernelChina.cublog.cn

文章选项:      

tpu
(old hand)
07-12-20 16:21
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
回复 

但汇编里面BL malloc只有一次啊,说明只调用了一次。C语言的显示混乱是否跟优化有关呢?

--------------------
精益求精!

文章选项:      

bob2004
(old hand)
07-12-20 17:56
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: tpu]
编辑  回复 

你说得有道理, 看来malloc确实被调用了一次,

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


/*
* 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

文章选项:      

bob2004
(old hand)
07-12-20 23:54
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 

找到一篇 env_relocate()实现的文章 , 正在分析:
http://blog.chinaunix.net/u1/47239/showart_375478.html

--------------------
http://KernelChina.cublog.cn

文章选项:      

bob2004
(old hand)
07-12-21 10:38
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 

接着读 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\n",
__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\n", __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\n\n");
#else
puts ("*** Warning - bad CRC, using default environment\n\n");
SHOW_BOOT_PROGRESS (-1);
#endif

if (sizeof(default_environment) > ENV_SIZE)
{
puts ("*** Error - default environment is too large\n\n");
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

文章选项:      

kernelworld
(addict)
07-12-24 00:39
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
回复 

出现这种奇怪的现象,首先看看你的地址配置怎么样,因为这已经涉及到操作内存了,
上次的我出现的问题更怪printf()稍微打印内容多一点CPU就复位了,最后问题就是配置
的地址不正确的。
PS:感觉现在的2.0的U-BOOT.好像是很有问题,上次改了几个BUG,一个就是环境变量的取值问题,
一个就是网卡的PING包问题,不知怎么回事,这还是明显的错误,你的U-BOOT来的门道来得正宗了,
这个要注意了,我下的U-BOOT的明显还一个内地的补丁,我当时记得也是到一个比较正式的网站下的。
刚忙完U-BOOT的移植,好久没有来祭坛了。。。欢迎共同讨论问题

--------------------
诗圣曰:语不惊人死不休
我亦曰:技不动人死不休

编辑者: kernelworld (07-12-24 00:43)

文章选项:      

bob2004
(old hand)
07-12-24 09:59
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: kernelworld]
编辑  回复 

谢谢你的分享 , 确实是地址设定的问题 , 问题已经解决了,
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\n",
__FUNCTION__,__LINE__,
gd->reloc_off,env_ptr);
env_ptr = (env_t *)malloc (CFG_ENV_SIZE);
DEBUGF ("%s[%d] malloced ENV at %p\n", __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

文章选项:      

bob2004
(old hand)
07-12-24 20:33
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 



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


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

文章选项:      

bob2004
(old hand)
07-12-24 21:26
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
编辑  回复 


对下面这段经典的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

文章选项:      

freebsdxjj
(newbie)
07-12-26 17:14
Re: 请教 u-boot 里面的环境变量的设置 的问题。 [re: bob2004]
回复 

我来回答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

--------------------
苟全性命于乱世
时机未到,不求闻达

文章选项:      

  加到“个人收藏夹”   |   打印

平坦模式  树状模式 
前往讨论区 *Linux 社区和文化* -----   社区公告栏   社区服务台   业界新闻与评论   自由软件杂谈   IT 人生   Linux软件快递   翻译作坊   Linux图书与评论   招聘和求职*Linux 桌面与办公自动化* -----   GNU Emacs/XEmacs   Linux 中文环境和中文化   Linux桌面与办公软件   Linux 多媒体与娱乐版   自由之窗Mozilla   笔记本电脑上的Linux*Linux 入门及网络应用* -----   Gentoo   Debian 一族   网络管理技术   Linux 安装与入门   WEB服务器和FTP服务器   域名服务器和邮件服务器   Linux防火墙和代理服务器应用   文件及打印服务器    技术培训与认证*Linux 高级应用* -----   TI专版   Linux内核技术   Linux 嵌入技术   Linux设备驱动程序   Linux 集群技术   LINUX平台数据库   系统和网络安全   CPU 与 编译器   系统计算研究所专栏*Linux 环境下的程序设计* -----   Linux下的GUI软件开发   C/C++编程版   PHP 技 术   Java&jsp技术   Shell编程技术   Perl 编 程   Python 编 程   XML/Web Service 技术*永远的 UNIX* -----   永远的Unix   FreeBSD世界
Contact Us LINUXFORUM.NET
相关阅读 更多 +
排行榜 更多 +
鹰眼IV

鹰眼IV

飞行射击 下载
火柴人史诗射手

火柴人史诗射手

飞行射击 下载
10发子弹安卓版

10发子弹安卓版

飞行射击 下载