UBOOT之board.c分析(二)

/******初始化malloc空间,将其清零*******/
mem_malloc_init (_armboot_start - CONFIG_SYS_MALLOC_LEN,CONFIG_SYS_MALLOC_LEN);


/******打印nand信息*******/
#if defined(CONFIG_CMD_NAND)
puts ("NAND:  ");
nand_init();                          //初始化nandflash
#endif

以上两句代码执行完毕后,便打印出nand信息,如:NAND:  1024 MB

nand_init函数在drivers/mtd/nand/nand.c中
void nand_init(void)
{
int i;
unsigned int size = 0;
/*******下面这个循环用于确定出nandflash的大小*********/
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) {
nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);
size += nand_info[i].size / 1024;
if (nand_curr_device == -1)
nand_curr_device = i;
}
printf("%u MiB\n", size / 1024);             //打印出nand的大小

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
/*
 * Select the chip in the board/cpu specific driver
 */
board_nand_select_device(nand_info[nand_curr_device].priv, nand_curr_device);
#endif
}
CONFIG_SYS_MAX_NAND_DEVICE在include/config/相应的头文件中定义,用于定义板子上用了几块nandflash:
#define CONFIG_SYS_MAX_NAND_DEVICE 1
nand_info是一个结构体数组,数组中的每个元素代表一个难道的信息,如nand_info[0]代表第一块nandflash的信息,依次类推。
而这个结构体中则包含了一个nand的所有信息,包括块大小,每块的oob数据及oob字节数还有要对这个nand进行操作的一系列函数指针等,这个结构体在include/linux/mtd/mtd.h中定义,因为这个结构体信息太多,所以不详细列出:
struct mtd_info {
······
}
typedef struct mtd_info nand_info_t;

/*************重定位环境变量***************/

env_relocate ();         //这个函数的作用是实现对环境变量的重定位,从nand中将环境变量搬移到DDR2中

env_relocate函数在commo/env_common.c中定义,加黑部分是真正要执行的代码
void env_relocate (void)
{
#ifdef ENV_IS_EMBEDDED
            ········
#else
env_ptr = (env_t *)malloc (CONFIG_ENV_SIZE);        //为环境变量申请一段空间
DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr);
#endif

if (gd->env_valid == 0) {
#if defined(CONFIG_GTH) || defined(CONFIG_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 (-60);
#endif
set_default_env();
}
else {
env_relocate_spec ();                                    //调用真正的重定位代码
}
gd->env_addr = (ulong)&(env_ptr->data);        //将重定位后的环境变量的地址赋给gd->env_addr
}

nv_relocate_spec函数开始实现对环境变量的重定位,这个函数在common/env_nand中定义:
void env_relocate_spec (void)
{
#if !defined(ENV_IS_EMBEDDED)
int ret;

ret = readenv(CONFIG_ENV_OFFSET, (u_char *) env_ptr);     //读取nand中保存的环境变量的值,并将其存放到env_ptr指向的
if (ret)                                                                                                  //地址中,完成环境变量从nand到DDR2的搬移
return use_default();                                                                 //根据返回值确定是否读取失败,如果失败则使用默认的环境变量

if (crc32(0, env_ptr->data, ENV_SIZE) != env_ptr->crc)         //进行CRC效验,确定环境变量是否有效
return use_default();                                                             //如果无效则使用默认的环境变量
#endif /* ! ENV_IS_EMBEDDED */
}

上面的代码很清楚的表明了env_relocate_spec的意图 ,调用readenv将环境变量从nand的CFG_ENV_OFFSET 处读出,环境变量的大小为 CFG_ENV_SIZE ,注意 CFG_ENV_OFFSET CFG_ENV_SIZE 要和 Nand Flash  的块/页边界对齐。读出数据后再调用crc32 对env_ptr->data 进行校验并与保存在 env_ptr->crc 的校验码对比,看数据是否出错。从这里也可以看出在系统第一次启动时Nand Flash 里面没有存储任何环境变量,crc校验肯定回出错,当我们保存环境变量后,接下来再启动板子u-boot就不会再报crc32出错了。

代码中相关宏的作用:
ENV_IS_EMBEDDED :         环境变量是否存在于 u-boot 的 text 段中
CFG_ENV_SIZE :                   环境变量的大小
CFG_ENV_IS_IN_NAND :    环境变量是否存放在Nand Flash 中
CFG_ENV_OFFSET :            环境变量在 Nand Flash 中的偏移地址

如果CRC效验出错,说明nand中的环境变量无效,所以就会使用默认的环境变量,默认的环境变量在数组default_environment中,这个数组定义在common/env_common.c中。这时会调用函数use_default()

这个函数在common/env_nand中:

static void use_default()
{
puts ("*** Warning - bad CRC or NAND, using default environment\n\n");
set_default_env();
}

set_default_env 函数定义在common/env_common.c:
void set_default_env(void)
{
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 CONFIG_SYS_REDUNDAND_ENVIRONMENT
env_ptr->flags = 0xFF;
#endif
env_crc_update ();                                                     //进行CRC效验
gd->env_valid = 1;                                                     //设置环境变量为有效
}

/**********************初始化多串口*********************************/

#ifdef CONFIG_SERIAL_MULTI
serial_initialize();            
#endif

serial_initialize函数在common/seria.c中定义:
void serial_initialize (void)
{
#if defined(CONFIG_S5PC1XX)
serial_register(&s5pc1xx_serial0_device);         //这个函数做的主要操作就是将每个串口的私有结构体插入到链表中
        serial_register(&s5pc1xx_serial1_device);
serial_register(&s5pc1xx_serial2_device);
serial_register(&s5pc1xx_serial3_device);
#endif
serial_assign (default_serial_console ()->name);     //将先前在default_serial_console 函数中返回的默认使用的串口结构体的
                                                                                                 //指针赋给当前串口结构体指针 serial_current 
}
serial_register  函数在common/seria.c中定义:
int serial_register (struct serial_device *dev)
{
dev->next = serial_devices;             //这两句代码就是插入链表的操作,
serial_devices = dev;

return 0;
}
serial_assign 函数在common/seria.c中定义:
int serial_assign (char *name)
{
struct serial_device *s;

for (s = serial_devices; s; s = s->next) {             //根据传进来的串口名字,设置当前串口serial_current 结构体的指针
if (strcmp (s->name, name) == 0) {
serial_current = s;
return 0;
}
}
return 1;
}

在common/seria.c定义了serial_devicesserial_current 变量:
static struct serial_device *serial_devices = NULL;
static struct serial_device *serial_current = NULL;




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值