uboot启动第二阶段1
来源:互联网 发布:全球软件行业市场规模 编辑:程序博客网 时间:2024/05/19 18:39
uboot启动第二阶段。在这个阶段中,uboot完成一些复杂的初始化,最终读取内核文件并启动内核。
主要流程:1、为gd gb全局变量分配空间,并初始化
2、初始化列表
3、
4、
一、gd bd全局变量分配空间、初始化
/* 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));monitor_flash_len = _bss_start - _armboot_start;
在内存的映射空间中保留了128B的字节给全局变量,gd bd为全局变量数据,存放一些重要的数据。具体可以查找相关结构体。对分配的空间进行初始化,赋值0.__asm__ __volatile__("": : :"memory");这一条指令告诉编译器,寄存器当前数值发生变化,存放的值无效。
monitor_flash_len存放代码大小
二、初始化列表
其中typedef int (init_fnc_t) (void);表示init_fnc_t 表示返回值为空、参数为空的函数指针。初始化列表对这种类型的函数进行初始化。
init_fnc_t **init_fnc_ptr;for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {if ((*init_fnc_ptr)() != 0) {hang ();}}
typedef int (init_fnc_t) (void);
init_fnc_t *init_sequence[] = {cpu_init,/* basic cpu dependent setup */board_init,/* basic board dependent setup */interrupt_init,/* set up exceptions */env_init,/* initialize environment */init_baudrate,/* initialze baudrate settings */serial_init,/* serial communications setup */console_init_f,/* stage 1 init of console */display_banner,/* say that we are here */#if defined(CONFIG_DISPLAY_CPUINFO)print_cpuinfo,/* display cpu info (and speed) */#endif#if defined(CONFIG_DISPLAY_BOARDINFO)checkboard,/* display board info */#endifdram_init,/* configure available RAM banks */display_dram_config,NULL,};1、int cpu_init (void)
在uboot的第一阶段已经对cpu进行初始化,这里只是一个空函数
int cpu_init (void){/* * setup up stacks if necessary */#ifdef CONFIG_USE_IRQIRQ_STACK_START = _armboot_start - CFG_MALLOC_LEN - CFG_GBL_DATA_SIZE - 4;FIQ_STACK_START = IRQ_STACK_START - CONFIG_STACKSIZE_IRQ;#endifreturn 0;}2、int board_init (void)
board初始化,主要完成GPIO初始化、时钟初始化、并对全局变量中gd中的启动参数与机器类型初始化、开启数据与代码cache。
int board_init (void){ S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER(); S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); /* set up the I/O ports */ gpio->GPACON = 0x007FFFFF; gpio->GPBCON = 0x00044555; gpio->GPBUP = 0x000007FF; gpio->GPCCON = 0xAAAAAAAA; gpio->GPCUP = 0x0000FFFF; gpio->GPDCON = 0xAAAAAAAA; gpio->GPDUP = 0x0000FFFF; gpio->GPECON = 0xAAAAAAAA; gpio->GPEUP = 0x0000FFFF; gpio->GPFCON = 0x000055AA; gpio->GPFUP = 0x000000FF; gpio->GPGCON = 0xFF95FFBA; gpio->GPGUP = 0x0000FFFF; gpio->GPHCON = 0x002AFAAA; gpio->GPHUP = 0x000007FF; /* support both of S3C2410 and S3C2440, by www.100ask.net */ if ((gpio->GSTATUS1 == 0x32410000) || (gpio->GSTATUS1 == 0x32410002)) { /* FCLK:HCLK:PCLK = 1:2:4 */ clk_power->CLKDIVN = S3C2410_CLKDIV; /* change to asynchronous bus mod */ __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */ "orr r1, r1, #0xc0000000\n" /* Asynchronous */ "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */ :::"r1" ); /* to reduce PLL lock time, adjust the LOCKTIME register */ clk_power->LOCKTIME = 0xFFFFFF; /* configure MPLL */ clk_power->MPLLCON = S3C2410_MPLL_200MHZ; /* some delay between MPLL and UPLL */ delay (4000); /* configure UPLL */ clk_power->UPLLCON = S3C2410_UPLL_48MHZ; /* some delay between MPLL and UPLL */ delay (8000); /* arch number of SMDK2410-Board */ gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; } else { /* FCLK:HCLK:PCLK = 1:4:8 */ clk_power->CLKDIVN = S3C2440_CLKDIV; /* change to asynchronous bus mod */ __asm__( "mrc p15, 0, r1, c1, c0, 0\n" /* read ctrl register */ "orr r1, r1, #0xc0000000\n" /* Asynchronous */ "mcr p15, 0, r1, c1, c0, 0\n" /* write ctrl register */ :::"r1" ); /* to reduce PLL lock time, adjust the LOCKTIME register */ clk_power->LOCKTIME = 0xFFFFFF; /* configure MPLL */ clk_power->MPLLCON = S3C2440_MPLL_400MHZ; /* some delay between MPLL and UPLL */ delay (4000); /* configure UPLL */ clk_power->UPLLCON = S3C2440_UPLL_48MHZ; /* some delay between MPLL and UPLL */ delay (8000); /* arch number of SMDK2440-Board */ gd->bd->bi_arch_number = MACH_TYPE_S3C2440; } /* adress of boot parameters */ gd->bd->bi_boot_params = 0x30000100; icache_enable(); dcache_enable(); return 0;}
3、中断初始化,其实没有采用中断。让定时器采用10ms循环计数的方法,对时间进行标记。代码如下,实现过程可以参考datasheet。
int interrupt_init (void){S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();/* use PWM Timer 4 because it has no output *//* prescaler for Timer 4 is 16 */timers->TCFG0 = 0x0f00;if (timer_load_val == 0){/* * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 * (default) and prescaler = 16. Should be 10390 * @33.25MHz and 15625 @ 50 MHz */timer_load_val = get_PCLK()/(2 * 16 * 100);}/* load value for 10 ms timeout */lastdec = timers->TCNTB4 = timer_load_val;/* auto load, manual update of Timer 4 */timers->TCON = (timers->TCON & ~0x0700000) | 0x600000;/* auto load, start Timer 4 */timers->TCON = (timers->TCON & ~0x0700000) | 0x500000;timestamp = 0;return (0);}4、环境变量初始化
在环境变量的文章中有介绍,让gd的环境地址指向有效的环境地址。
int env_init(void){#ifdef CONFIG_OMAP2420H4int flash_probe(void);if(flash_probe() == 0)goto bad_flash;#endifif (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {gd->env_addr = (ulong)&(env_ptr->data);gd->env_valid = 1;return(0);}#ifdef CONFIG_OMAP2420H4bad_flash:#endifgd->env_addr = (ulong)&default_environment[0];gd->env_valid = 0;return (0);}#ifdef CMD_SAVEENV
5、波特率初始化,就是查找波特率的值
如果环境变量中的参数没有波特率参数,采用程序的默认值
static int init_baudrate (void){char tmp[64];/* long enough for environment variables */int i = getenv_r ("baudrate", tmp, sizeof (tmp));gd->bd->bi_baudrate = gd->baudrate = (i > 0)? (int) simple_strtoul (tmp, NULL, 10): CONFIG_BAUDRATE;return (0);}
6串口初始化,串口初始化调用系统的时钟与波特率完成串口的初始化。
在完成串口初始化后,可以调用putc puts getc等相关函数进行输入输出
int serial_init (void){serial_setbrg ();return (0);}
void serial_setbrg (void){S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);int i;unsigned int reg = 0;/* value is calculated so : (int)(PCLK/16./baudrate) -1 */reg = get_PCLK() / (16 * gd->baudrate) - 1;/* FIFO enable, Tx/Rx FIFO clear */uart->UFCON = 0x07;uart->UMCON = 0x0;/* Normal,No parity,1 stop,8 bit */uart->ULCON = 0x3;/* * tx=level,rx=edge,disable timeout int.,enable rx error int., * normal,interrupt or polling */uart->UCON = 0x245;uart->UBRDIV = reg;#ifdef CONFIG_HWFLOWuart->UMCON = 0x1; /* RTS up */#endiffor (i = 0; i < 100; i++);}
7控制台初始化(第一阶段),设置控制台的标志位
int console_init_f (void){gd->have_console = 1;#ifdef CONFIG_SILENT_CONSOLEif (getenv("silent") != NULL)gd->flags |= GD_FLG_SILENT;#endifreturn (0);}
8、 display_banner函数显示uboot的版本信息,在make文件中自动调用编译时间,好方便不用设置
9、 dram_init,display_dram_config。dram初始化,其实已经在uboot的第一阶段进行初始化了。在这里对bd变量中内存存储容量与存储地址进行初始化。显示出来。
阅读全文
0 0
- uboot启动第二阶段1
- uboot启动第二阶段详细分析(1)
- uboot启动第二阶段
- UBoot启动第二阶段
- uboot第二阶段启动过程
- uboot第二阶段启动流程
- Uboot启动的第二阶段
- uboot启动第二阶段2
- uboot启动第二阶段
- uboot - 启动流程分析【第二阶段】
- uboot启动流程webee210启动第二阶段
- uboot 启动流程分析(二) — 第二阶段
- uboot启动第二阶段详细分析(2)
- uboot 启动流程分析(二) — 第二阶段
- uboot——启动第二阶段分析
- uboot启动第二阶段之x-load分析
- UBOOT第二阶段源码分析1
- uboot第二阶段
- Jna
- leetcode 661. Image Smoother
- cscope 使用时打开新的窗口
- No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '***' is theref
- 我来试试
- uboot启动第二阶段1
- java遍历Excel行
- 关于排列组合算法的心得
- 【python】复杂对象的创建过程与转化为json
- jsonp请求实例原生和jquery
- 最详细开发者账号申请流程,不看后悔
- Vue学习笔记一
- 趣味推理题 动动好久没有认真思考的脑袋
- cs231n笔记--到底什么是梯度消散