uboot源码分析

Uboot代码结构详细分析 1. Bootloader功能分析 Bootloader(如Uboot、Redboot、Blob、vivi等)直接和CPU、外围硬件设备(存储器、网卡、LCD等)打交道,负责初始化硬件设备,以及负责拉起内核:建立内存空间映射图,为内核的启动运行做好一切准备,最后将Linux内核代码加载到RAM中运行。 一般来说,bootload都会提供两种操作模式: 正常启动模式:无需开发者和用户干涉,上电后自动开始运行,完成启动内核的任务; 下载模式(开发者模式):需要用户干预,进入下载模式,使用uboot命令 阅读详情
AI摘要

本文围绕uboot展开,介绍了其出现原因,即作为裸机程序为内核运行提供环境,将硬件初始化和配置从内核分离。还提及了study210开发板S5PV210芯片的启动流程,并对uboot源码进行了分析,包括BL1和BL2部分。

1 前言

1.1 uboot出现的原因

uboot本身是一个裸机程序,uboot出现的目的就是为内核的运行提供环境,内核是不会去进行相关的硬件配置的,因为硬件的种类很多,所以硬件的初始化和配置分出来变成了bootloader,uboot是bootloader的一种。

1.2 uboot主要做哪些工作

1 设置中断向量表
2 设置CPU时钟
3 配置串口
4 配置定时器
5 关闭看门狗
6 初始化DDR
7 记录DDR的大小和物理地址
8 传递机器码

1.3 uboot启动流程

下面是study210开发板 S5PV210芯片的启动流程

1 开发板内置了一块64K的IROM,存放代码的功能主要是初始化SD卡
  和对SD卡的读取,简称BL0,起始地址0x0000_0000,arm架构的
  cpu刚启动就会到这个地址运行读取代码,这是由硬件决定的。
2 开发板内置了一块96k的SRAM,SRAM不用初始化,上电就可以用,
  但是价格比较贵,起始地址: 0xD002_0000
3 BL0读取SD卡的前8k内容到SRAM中的0xD002_0000中,其中前
  16字节为校验头,具体是怎么校验的是由BL0中的算法决定的,真
  正的代码从0xD002_0010开始,简称BL1
4 BL1只是uboot代码的前8k,是uboot的一部分。因为uboot大小为
  几百K,而且SRAM比较贵,DDR又不能上电直接用,所以先使用
  SRAM运行前8k代码初始化DDR。
5 前8k代码不止用于初始化DDR,在九鼎的uboot源码中,BL1进行了
  设置中断向量表,设置CPU为SVC模式,禁用中断,关闭看门狗,
  初始化时钟,初始化串口,设置上电锁存等。
6 DDR初始化完成后,BL1拷贝SD卡49扇区开始的内容到DDR中,49
  扇区存放着完整的uboot,拷贝完成后,BL1跳转到BL2工作,这里
  跳转的DDR地址是0x33e00000,DDR的物理地址范围0x3000_0000~
  0x4fff_ffff共计512M,这个物理地址是可以选择的,这个范围是在
  BL1中设置的。
7 BL2也会执行前8K代码的工作,但是会判断当前PC指针的运行位置,
  当PC指针在DDR中时,会跳过BL1中已经运行过的函数,BL2会进行
  更加细致的硬件设备初始化,并且记录一些必要的硬件参数,把这些
  参数放到0x3000_0100的位置,内核也会从这个位置读取参数,引导
  内核的运行。
8 BL2在初始化完硬件设备后,会拷贝内核镜像到0x30008000这个地址,
  uboot在最后会跳转执行内核时,会传递三个参数,分别使用r0,r1,r2这
  三个寄存器传递,分别是0,机器码,和参数的存储地址。至此,
  uboot的工作全部结束。

2 源码分析

请看注释,下面的代码已经去掉了没有使用到的条件编译

//BL1部分的前16字节,用来存储校验信息,现在只是内容填充,数据的内容不重要
#if defined(CONFIG_EVT1) && !defined(CONFIG_FUSED)
	.word 0x2000
	.word 0x0
	.word 0x0
	.word 0x0
#endif
/*.globl关键字的作用是把变量声明为类似环境变量一样的东西,在整个Makefile编译
过程中,其他的源文件也可以使用这个变量*/
.globl _start
//设置中断向量表
_start: b	reset  //跳转到reset函数,向下找"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

_undefined_instruction:
	.word undefined_instruction
_software_interrupt:
	.word software_interrupt
_prefetch_abort:
	.word prefetch_abort
_data_abort:
	.word data_abort
_not_used:
	.word not_used
_irq:
	.word irq
_fiq:
	.word fiq
_pad:
	.word 0x12345678 /* now 16*4=64 */
.global _end_vect
_end_vect:

	.balignl 16,0xdeadbeef
	/*
 *************************************************************************
 *
 * Startup Code (reset vector)
 *
 * do important init only if we don't start from memory!
 * setup Memory and board specific bits prior to relocation.
 * relocate armboot to ram
 * setup stack
 *
 *************************************************************************
 */
//后面会有ldr pc,_TEXT_BASE的代码,意思是跳转到TEXT_BASE地址去执行代码
_TEXT_BASE:
	.word	TEXT_BASE

/*
 * Below variable is very important because we use MMU in U-Boot.
 * Without it, we cannot run code correctly before MMU is ON.
 * by scsuh.
 */
_TEXT_PHY_BASE:
	.word	CFG_PHY_UBOOT_BASE

.globl _armboot_start
_armboot_start:
	.word _start

/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
	.word __bss_start

.globl _bss_end
_bss_end:
	.word _end
/*
 * the actual reset code
 */
//跳转到这里执行复位代码
reset:
	/*
	 * set the cpu to SVC32 mode and IRQ & FIQ disable
	 */
	@;mrs	r0,cpsr              //@开头的是注释
	@;bic	r0,r0,#0x1f
	@;orr	r0,r0,#0xd3
	@;msr	cpsr,r0
	//失能中断,设置CPU为SVC模式
	msr	cpsr_c, #0xd3		@ I & F disable, Mode: 0x13 - SVC  
/*
 *************************************************************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
         /*
         * we do sys-critical inits only at reboot,
         * not when booting from ram!
         */
cpu_init_crit:
	bl	disable_l2cache //做一些关于缓存的配置,我不懂,老师说和主体无关不用管
	bl	set_l2cache_auxctrl_cycle
	bl	enable_l2cache
	/*
    * Invalidate L1 I/D
     */
     mov	r0, #0                  @ set up for MCR
     mcr	p15, 0, r0, c8, c7, 0   @ invalidate TLBs
     mcr	p15, 0, r0, c7, c5, 0   @ invalidate icache

    /*
     * disable MMU stuff and caches
     */
     mrc	p15, 0, r0, c1, c0, 0
     bic	r0, r0, #0x00002000     @ clear bits 13 (--V-)
     bic	r0, r0, #0x00000007     @ clear bits 2:0 (-CAM)
     orr	r0, r0, #0x00000002     @ set bit 1 (--A-) Align
     orr	r0, r0, #0x00000800     @ set bit 12 (Z---) BTB
     mcr 	p15, 0, r0, c1, c0, 0


    /* Read booting information */
    //0xE000_0004这个寄存器会被自动设置,被设置值和选择的启动介质有关 
     ldr	r0, =PRO_ID_BASE
     ldr	r1, [r0,#OMR_OFFSET]
     bic	r2, r1, #0xffffffc1   //r2中根据启动介质的不同,被设置成不同的值
     /* SD/MMC BOOT */
	cmp     r2, #0xc              //当r2中的值为0xc的时候,执行下一句代码
	/*"moveq"指令用于将一个立即数加载到寄存器中,其中"eq"表示条件码,表示只有
	在上一条指令影	响标志位并且结果为零时才执行该指令。*/
	moveq   r3, #BOOT_MMCSD	      //BOOT_MMCSD=0X3,r3=0x3
	/*
	 * Go setup Memory and board specific bits prior to relocation.
	 */
	//根据芯片手册推荐,设置栈指针到合适的SRAM中的区段,为C代码运行做准备
	ldr	sp, =0xd0036000 /* end of sram dedicated to u-boot */
	sub	sp, sp, #12	/* set stack */
	mov	fp, #0  //这个fp指针不知道是干什么的
	//跳转到C函数执行代码
	bl	lowlevel_init	/* go setup pll,mux,memory */
lowlevel_init:
    //压栈,因为lr寄存器只能保存一个地址,且SVC模式下只有一个lr寄存器,函数跳转必须压栈
	push	{lr}   

	/* check reset status 检查热启动还冷启动,和启动主体关系不大 */
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE+RST_STAT_OFFSET)
	ldr	r1, [r0]
	bic	r1, r1, #0xfff6ffff
	cmp	r1, #0x10000
	beq	wakeup_reset_pre
	cmp	r1, #0x80000
	beq	wakeup_reset_from_didle

	/* IO Retention release 和主要流程关系不大,后面我就不再赘述,有注释就是重要*/
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + OTHERS_OFFSET)	/* 0xE0100000 + 0xE000 */
	ldr	r1, [r0]
	ldr	r2, =IO_RET_REL
	orr	r1, r1, r2
	str	r1, [r0]

	/* Disable Watchdog */
	ldr	r0, =ELFIN_WATCHDOG_BASE	/* 0xE2700000 */
	mov	r1, #0
	str	r1, [r0]

	/* SRAM(2MB) init for SMDKC110 */
	/* GPJ1 SROM_ADDR_16to21 */
	ldr	r0, =ELFIN_GPIO_BASE
	
	ldr	r1, [r0, #GPJ1CON_OFFSET]
	bic	r1, r1, #0xFFFFFF
	ldr	r2, =0x444444
	orr	r1, r1, r2
	str	r1, [r0, #GPJ1CON_OFFSET]

	ldr	r1, [r0, #GPJ1PUD_OFFSET]
	ldr	r2, =0x3ff
	bic	r1, r1, r2
	str	r1, [r0, #GPJ1PUD_OFFSET]

	/* GPJ4 SROM_ADDR_16to21 */
	ldr	r1, [r0, #GPJ4CON_OFFSET]
	bic	r1, r1, #(0xf<<16)
	ldr	r2, =(0x4<<16)
	orr	r1, r1, r2
	str	r1, [r0, #GPJ4CON_OFFSET]

	ldr	r1, [r0, #GPJ4PUD_OFFSET]
	ldr	r2, =(0x3<<8)
	bic	r1, r1, r2
	str	r1, [r0, #GPJ4PUD_OFFSET]


	/* CS0 - 16bit sram, enable nBE, Byte base address */
	ldr	r0, =ELFIN_SROM_BASE	/* 0xE8000000 */
	mov	r1, #0x1
	str	r1, [r0]

	/* PS_HOLD pin(GPH0_0) set to high 上电所存,按下POWER键,板子持续供电*/
	ldr	r0, =(ELFIN_CLOCK_POWER_BASE + PS_HOLD_CONTROL_OFFSET)
	ldr	r1, [r0]
	orr	r1, r1, #0x300	
	orr	r1, r1, #0x1	
	str	r1, [r0]

	/* init system clock 初始化时钟*/
	bl	system_clock_init
	//初始化DDR
	bl	mem_ctrl_asm_init
//汇编语言的执行顺序是流水型,bl执行完函数会跳转回来,然后执行1:
1:
	/* for UART */
	bl	uart_asm_init
	
	bl	tzpc_init
	
	bl	onenandcon_init
	//出栈
	pop	{pc}
/* get ready to call C functions */
//再次设置栈指针,因为DDR已经初始化,且SRAM的栈太小,所以再次设置栈指针
ldr	sp, _TEXT_PHY_BASE	/* setup temp stack pointer */
sub	sp, sp, #12
mov	fp, #0			/* no previous frame, so fp=0 */
/* when we already run in ram, we don't need to relocate U-Boot.
* and actually, memory controller must be configured before U-Boot
 * is running in ram.
 */
 //判断pc寄存器现在运行的地址,如果在SRAM中,进行BL2拷贝到DDR中,否则不进行
ldr	r0, =0xff000fff
bic	r1, pc, r0		/* r0 <- current base addr of code */
ldr	r2, _TEXT_BASE		/* r1 <- original base addr in ram */
bic	r2, r2, r0		/* r0 <- current base addr of code */
//请看英文注释
cmp     r1, r2                  /* compare r0, r1                  */
beq     after_copy		/* r0 == r1 then skip flash copy   */

//注意一下哈,这里我把after_copy函数拷贝过来了,并不是紧挨着的
after_copy:
//使能mmu,设置虚拟地址转换表,这个内容比较难懂,我看不懂虚拟地址是怎么转换的
enable_mmu:
	/* enable domain access */
	ldr	r5, =0x0000ffff
	mcr	p15, 0, r5, c3, c0, 0		@load domain access register

	/* Set the TTB register */
	ldr	r0, _mmu_table_base
	ldr	r1, =CFG_PHY_UBOOT_BASE
	ldr	r2, =0xfff00000
	bic	r0, r0, r2
	orr	r1, r0, r1
	mcr	p15, 0, r1, c2, c0, 0

	/* Enable the MMU */
mmu_on:
	mrc	p15, 0, r0, c1, c0, 0
	orr	r0, r0, #1
	mcr	p15, 0, r0, c1, c0, 0
	nop
	nop
	nop
	nop
//after_copy 结尾处
//再次设置栈指针,这次设置的目的是把栈放置到合适的位置
ldr	sp, =(CFG_UBOOT_BASE + CFG_UBOOT_SIZE - 0x1000)
sub	sp, r0, #12		/* leave 3 words for abort-stack    */
//bss段变量的值设置为0
clear_bss:
	ldr	r0, _bss_start		/* find start of bss segment        */
	ldr	r1, _bss_end		/* stop here                        */
	mov 	r2, #0x00000000		/* clear                            */

clbss_l:
	str	r2, [r0]		/* clear loop...                    */
	add	r0, r0, #4
	cmp	r0, r1
	ble	clbss_l
	/*跳转执行_start_armboot,本人认为啊,上面的代码知道具体干什么就行了,代码
	只是对功能的实现,知道功能,再去实现代码不是一件难事,所以学习要学习思路*/
	ldr	pc, _start_armboot
_start_armboot:
	.word start_armboot

上面是uboot的BL1部分,主要进行了:

1 异常中断向量表的创建
2 关闭看门狗
3 上电锁存
4 DDR初始化
5 系统时钟初始化
6 串口初始化
7 设置栈指针
8 使能MMU,创建内存映射表(老版本uboot并没有使用虚拟地址)

接下来进行BL2源码的解析,注意一下哈,我贴出来的代码都是去掉条件编译的

void start_armboot (void)
{
	init_fnc_t **init_fnc_ptr;
	char *s;
	int mmc_exist = 0;
	ulong gd_base;
	//设置全局变量存储的地址,事实上,你想怎么设置就怎么设置,毕竟DDR随便操作,但是不要出现数据覆盖的情况
	gd_base = CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE - sizeof(gd_t);
	//转成gd_t结构体类型,因为/**/这种注释不能嵌套,所以我使用条件编译的形式进行注释的添加
	#if 0
	typedef	struct	global_data {
	bd_t		*bd;
	unsigned long	flags;
	unsigned long	baudrate;
	unsigned long	have_console;	/* serial_init() was called */
	unsigned long	reloc_off;	/* Relocation Offset */
	unsigned long	env_addr;	/* Address  of Environment struct */
	unsigned long	env_valid;	/* Checksum of Environment valid? */
	unsigned long	fb_base;	/* base address of frame buffer */
	void		**jt;		/* jump table */
	} gd_t;
	#endif
	gd = (gd_t*)gd_base; 
	/* 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));
	//_bss_start和_armboot_start是makefile链接脚本指定的
	monitor_flash_len = _bss_start - _armboot_start;
	//和BL1的硬件初始化不同,这里是存储硬件的相关信息,比如:内存的地址分布、数量和大小
	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
		if ((*init_fnc_ptr)() != 0) {
			hang ();
		}
	}
	//uboot中实现了一个malloc函数,用来申请内存,堆区的大小由宏配置文件的宏定义决定
	//如果没记错的话,这里的堆区应该是900多K。实际上malloc的底层实现原理只是有一个
	//内存管理表,这个表是个数据结构,我好像记得里面存储的是一个个的结构体,记录了每一块
	//内存的起始地址,类型,大小等,free函数就是删除这个结构体
	mem_malloc_init (CFG_UBOOT_BASE + CFG_UBOOT_SIZE - CFG_MALLOC_LEN - CFG_STACK_SIZE);
	//这里进行更细致的SD卡初始化,IROM中只是进行了简单的初始化
	puts ("SD/MMC:  ");
	mmc_exist = mmc_initialize(gd->bd);
	if (mmc_exist != 0)
	{
		puts ("0 MB\n");
	}
	/* initialize environment */
	env_relocate ();  //我没了解,但是老师讲了
	/* IP Address */
	gd->bd->bi_ip_addr = getenv_IPaddr ("ipaddr");	//获取IP地址
	/* MAC Address */
	{
		int i;
		ulong reg;
		char *s, *e;
		char tmp[64];

		i = getenv_r ("ethaddr", tmp, sizeof (tmp));
		s = (i > 0) ? tmp : NULL;

		for (reg = 0; reg < 6; ++reg) {
			gd->bd->bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0;
			if (s)
				s = (*e) ? e + 1 : e;
		}	
	}
		//这个函数里面存储的应该是函数名,然后去执行函数
	    devices_init ();	/* get the devices list going. */
	    jumptable_init ();   //不懂
	    /* enable exceptions */
		enable_interrupts ();
		cs8900_get_enetaddr (gd->bd->bi_enetaddr);  //应该和网卡驱动有关
		/* Initialize from environment 从环境变量配置那里读取信息,并给一些变量赋值*/
		if ((s = getenv ("loadaddr")) != NULL) {
			load_addr = simple_strtoul (s, NULL, 16);
		}
		if ((s = getenv ("bootfile")) != NULL) {
			copy_filename (BootFile, s, sizeof (BootFile));
		}
		/*这后面的知识,我偷懒了,没学,哈哈哈,大概的作用就是为后面向内核传递
		硬件设备的参数做准备*/
		board_late_init ();
		puts ("Net:   ");
		eth_initialize(gd->bd);
		puts("IDE:   ");
		ide_init();
		extern int x210_preboot_init(void);
		x210_preboot_init();
		/* check menukey to update from sd */
		extern void update_all(void);
		if(check_menu_update_from_sd()==0)//update mode
		{
			//按下LEFT按键好像可以使用SD卡向iNand烧录uboot kernel rootfs,使用SD卡快速烧录
			puts ("[LEFT DOWN] update mode\n");
			run_command("fdisk -c 0",0);
			update_all();
		}
		else
			puts ("[LEFT UP] boot mode\n");
	
		/* main_loop() can return to retry autoboot, if so just run it again. */
		for (;;) {
			//进入uboot的类型shell的命令终端窗口,进入后,后自动调用一些设置的命令,比如:bootm 0x30008000;跳转到指定地址执行程序。具体kernel和rootfs的挂载地址我忘记了,这里可能不准确。bootm对应的函数是 do_bootm_linux,请看下一个函数。
			main_loop ();
		}
	
		/* NOTREACHED - no way out of command loop except booting */
}
//bootm调用的函数
void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
		     bootm_headers_t *images)
{
	ulong	initrd_start, initrd_end;
	ulong	ep = 0;
	bd_t	*bd = gd->bd;
	char	*s;
	//机器码,正常来说,每个板子的机器码是唯一的,可以通过查看好像叫type-machines的文件获取
	int	machid = bd->bi_arch_number;
	//定义个执行内核的函数,并进行传参
	void	(*theKernel)(int zero, int arch, uint params);
	int	ret;

#ifdef CONFIG_CMDLINE_TAG
	//获取在BL2开头部分存储的硬件信息,这里是获取自己设置的环境变量
	char *commandline = getenv ("bootargs");
#endif

	/* find kernel entry point */
	if (images->legacy_hdr_valid) {
		//ep:entry point获取内核的程序入口,就行C语言中的main入口
		ep = image_get_ep (&images->legacy_hdr_os_copy);
#if defined(CONFIG_FIT)
	} else if (images->fit_uname_os) {
		ret = fit_image_get_entry (images->fit_hdr_os,
					images->fit_noffset_os, &ep);
		if (ret) {
			puts ("Can't get entry point property!\n");
			goto error;
		}
#endif
	} else {
		puts ("Could not find kernel entry point!\n");
		goto error;
	}
	//跳转到内核的程序入口地址,这里并不是真正的入口地址,而是zImage头部解压代码的入口
	theKernel = (void (*)(int, int, uint))ep;

	s = getenv ("machid");
	if (s) {
		machid = simple_strtoul (s, NULL, 16);
		printf ("Using machid 0x%x from environment\n", machid);
	}
	//不懂
	ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM,
			&initrd_start, &initrd_end);
	if (ret)
		goto error;
	//不懂,有的没注释是因为有英文注释,或者自己不懂
	show_boot_progress (15);

	debug ("## Transferring control to Linux (at address %08lx) ...\n",
	       (ulong) theKernel);
	//内核中取参数时,setup_start_tag会作为开始标志。传参按照tag结构体的形式,内核也会使用这种方式取
	setup_start_tag (bd);
	setup_memory_tags (bd);  //这里重要,会传递几块DDR,起始地址和大小。这些信息在BL2中设置
	setup_commandline_tag (bd, commandline);
	if (initrd_start && initrd_end)
		setup_initrd_tag (bd, initrd_start, initrd_end);
	setup_mtdpartition_tag();
	setup_end_tag (bd);
	printf ("\nStarting kernel ...\n\n");  //uboot最后打印的信息
	cleanup_before_linux ();

	theKernel (0, machid, bd->bi_boot_params); //开始跳转执行kernel
	/* does not return */
	return;
error:
	do_reset (cmdtp, flag, argc, argv);
	return;
}

至此,uboot源码全部分析完毕,上面内容是自己的理解,难免有错误,读者注意辨别。

U-Boot重点源码详解 文件夹就是和具体的板子有关的,打开此文件夹,里面全是不同的板子,毫无疑问正点原子的开发板肯定也在里面(其中imxdownload是烧录文件 u-boot*这些文件是编译产生的。这个文件夹里面的文件都是跟 ARMV7。,只是freescale 后来被。芯片的板子都放到此文件夹中,可以看出有很多架构,比如。文件夹,在里面找到和。的时候需要重点关注的。文件夹里面有个名为“ 阅读详情

相关推荐

Uboot开发与移植笔记(超详细代码讲解)(一)

本文对UBoot源码进行详细讲解,逐一带你从0修改UBoot源码进行移植工作

qq_46037552的博客 1万+

u-boot源码分析

u-boot源码分析

小王的博客 6806

uboot源码分析——start_armboot

Stage2源码分析 start_armboot函数的路径:/lib_arm/board.c   void start_armboot (void) { init_fnc_t **init_fnc_ptr; char *s; #if defined(CONFIG_VFD) || defined(CONFIG_LCD) unsigned long 

Burning Water 2230

嵌入式系统启动流程基础概念、uboot工作流程、kernel启动流程、文件系统特性分析.

本系列课程属于嵌入式系统入门级的课程,适合于想要接触嵌入式系统、对嵌入式系统比较感兴趣、想要了解系统启动流程的同学主要选取了市场上常见的SOC芯片IMX6UL进行数据手册特性分析,介绍了SOC的芯片框架,分析了设备启动的多种方式分析uboot的工作原理、指令集、关键源码,简要分析kernel启动流程,带领大家一起进行内核log分析。

uboot:源码分析-启动第一阶段-lowlevel_init

检查复位状态、IO恢复、关看门狗、开发板供电锁存、时钟初始化、DDR初始化、串口初始化并打印’O’、tzpc初始化、打印’K’。其中值得关注的:关看门狗、开发板供电锁存、时钟初始化、DDR初始化、打印"OK"

qq_43441284的博客 1549

uboot源码分析uboot启动流程,uboot-CMD命令调用关系

uboot的最终目的是引导启动内核加载系统,根据这个线索我们可以首先找到uboot引导内核的main函数,查看系统引导的执行跳转的函数 main_loop。下面对uboot函数的调用关系和主要调用函数进行分析。

u010584870的博客 1581

二、uboot_源码分析

1、第一阶段,硬件相关初始化(arch/arm/cpu/arm920t/start.S)2、第二阶段,c语言程序(lib_arm/board.c)2、第二阶段初始化(c语言)1、第一阶段初始化(汇编)(1)实现读写flash。(4)读取内核,引导内核。一、uboot启动原理。(3)初始化SDRAM。(5)拷贝第二阶段代码。

liutit的博客 919

九.linux开发之uboot移植(九)——uboot源码分析3-uboot启动内核机制

借鉴资料:http://blog.51cto.com/9291927/1792467 有道云笔记分享地址:http://note.youdao.com/noteshare?id=b63e0101293984d08ea7a015ab202893&amp;sub=2C6EFA378FC4444DBC8D24BBFF8074EC 一.uboot和内核到底是什么 1、uboot是一个裸机程序 ...

Mr.Wang的博客 4091

UBOOT启动源码分析

指导链接器如何将输入的目标文件合并成输出文件(通常是可执行文件或库)。这个脚本是用于U-Boot的,所以可能涉及到启动代码和内存布局的安排。对齐要求:向量表基地址(VBAR_ELx)必须 2048 字节对齐,确保硬件能正确计算入口地址。ARMv8 定义了 16 种异常类型,每种类型对应固定的 128 字节偏移。代码地址:arch/arm/cpu/armv8/exceptions.S。代码地址入口i:arch/arm/lib/crt0_64.S。**OUTPUT_FORMAT:**指定输出文件的格式为。

weixin_46053662的博客 606

ST7102驱动移植与调试实战

本文详细介绍了在君正T40平台上移植和调试ST7102 LCD驱动芯片的实战经验。内容涵盖硬件接口配置、时序参数调整、寄存器初始化序列编写及常见问题解决,重点解析了ST7102单芯片集成显示与触控功能的特性,为嵌入式设备显示驱动开发提供实用指南。

k6l7m8n9的博客 1410

svn co --depth和svn up --set-depth 只check out下一层文件 只更新指定文件 只更新下一层的用法

svn的工程可能很大 有时我们只需要部分文件即可 这里介绍几个命令 1.svn co(check out) --depth --depth=empty,files,immediates,infinity 假设某svn结构如下 svn://root/PRO/A_dir/a svn://root/PRO/B_dir/b svn://root/PRO/c_file svn co --depth=emptysvn://root/PRO 此时只会在本地check out出 PRO/的空目录。 sv.

cy413026的博客 1万+

ARM uboot 源码分析6 - uboot如何启动内核

一、uboot 和内核到底是什么 1、uboot 是一个裸机程序 (1) uboot 的本质就是一个复杂点的裸机程序。和我们在 ARM 裸机全集中学习的每一个裸机程序并没有本质区别。 (2) ARM 裸机第十六部分写了个简单的 shell,这东西其实就是个mini 型的 uboot。 2、内核本身也是一个"裸机程序" (1) 操作系统内核本身就是一个裸机程序,和 uboot、和其他裸机程序并没有本质区别。 正是内核运行起来了之后,才有了称为操作系统的环境,操作系统负责管理所有计算机资源。 (2) 区别就

weixin_42109053的博客 2179

航空大数据——项目资源汇总及开源(四)

ADS-B项目开源大礼包

cyc头发还挺多的博客 4980

【一】Uboot-2017.11源码分析启动过程之汇编部分

1 设置中断向量表 CPU在上电后,首先从0x0000 0000地址开始执行程序,uboot编译后,在程序的起始地址处存放了中断向量表,该部分代码为汇编语言写的,代码存储于arch\arm\cpu\armv7目录下的start.S中,如下所示: /*************************************************************************

乘风破浪潮头立,扬帆起航正当时。 1万+

ThingsBoard教程(十九):规则节点概览介绍

在ThingsBoard的CE V2.5.6版本中,一共有这几种类型在每一种类都有包含了多个节点,每一种类型的节点都有不同的颜色表示本篇文章做一个简单的概括,后续的文章会详细讲解每一个种类的节点如何使用,每一个节点的使用。一共有10个,使用黄色表示 过滤器节点用于消息过滤和路由。一共有9个,使用绿色 属性节点用于更新传入消息的元数据。一共三个,使用蓝色 转换节点用于更改传入消息字段,如发起者、消息类型、有效负载和元数据。一共21个,使用红色标识 动作节点根据传入的消息执行各种动作。一共9个,使用黄色表示,

知无涯 1万+

学Simulink--基于机器人与自动化系统的场景实例:六自由度机械臂的逆运动学控制仿真

摘要:本文详细介绍了在Simulink中实现六自由度机械臂逆运动学控制的仿真方法。通过构建包含机械臂模型、路径规划器、逆运动学求解器和控制器等模块的系统,利用MATLAB Robotics工具箱进行建模。文章逐步讲解了从模型创建、轨迹规划、逆运动学求解到控制器设计的完整流程,并提供了性能评估标准。该方法能有效验证逆运动学算法,优化机械臂控制策略,提高操作精度和效率,为机器人自动化系统开发提供实用参考。

xiaoheshang_123的博客 230

uboot源码分析——fastboot命令的源码分析(如何利用fastboot将镜像烧写至iNand)

以下内容源于网络资源的学习与整理,如有侵权请告知删除。

主要记录嵌入式学习与开发过程。 4322

详细分析一下华为自研的MetaERP系统中的合并报表流程与规则

华为MetaERP合并报表系统针对其全球化复杂业务量身定制,采用五层自动化架构:统一数据采集、多币种转换、智能对账协同、规则化抵消处理及多维分析输出。系统核心在于可配置的智能规则引擎,涵盖股权合并范围、内部交易抵消、未实现利润计算等复杂场景,实现多准则并行处理。相比传统软件,该系统深度集成业务数据、支持准实时合并,并通过参数化配置快速适应组织变革,成为华为全球财务管控的"数字神经中枢",在效率、准确性和安全性上具有显著优势。

金牌架构师 673

linux uboot 源码分析,UBoot源码分析1.pdf

UBoot源码分析1• UBoot源码解析(一)主要内容• 分析UBoot是如何引导Linux内核• UBoot源码的一阶段解析BootLoader概念• Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境• 通常,Boot ...

weixin_39922147的博客 336

TVBox源总失效?不如自己搭建一个!告别不稳定!手把手教你自建TVBox源,全网资源尽掌握!

🚀 TVBox源总失效?别慌!手把手教你自建TVBox源,打造一个稳定、海量、无广告的影视宝库!从此告别片荒,尽享丝滑观影体验!

XiaoqiangClub的博客 5446

2023年全国职业院校技能大赛 网络系统管理服务模块 Linux部分讲解

网络系统管理,Linux,服务部署,Chinaskills,2023国赛

weixin_62926639的博客 1547

UBOOT之源码分析(X4412)——代码重定位

参考http://blog.youkuaiyun.com/xieweihua2012/article/details/8474655根据X4412

亚克鸿宇的专栏 709

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Uboot的start.s源码分析

将此标号地址处的内容取出来给pc指针,而这内容恰好是异常处理函数的首地址(预留的空间就是为了放异常处理地址用的,这里_software_interrupt: .word software_interrupt指令中software_interrupt,是一个标号,标号代表的是处理地址,也是跳转的目标地址,该标号在本文件最下边有定义,其他标号类似),这样完成了一次异常处理。_TEXT_BASE并不是ram中的起始地址,只是u-boot放置的首地址,源码中是:0x33f80000。

独舞风 1026

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

uboot启动源码分析

102-109 判断宏CONFIG_NAND_SPL是否定义,如果定义了设置栈地址为CONFIG_SYS_INIT_SP_ADDR,如果定义了CONFIG_SPL_BUILD、CONFIG_SPL_STACK则设置栈地址为CONFIG_SPL_STACK,否则设置栈地址为CONFIG_SYS_INIT_SP_ADDR,目的是为了执行C语言做准备。// 可用sdram的顶端。其中_image_copy_end_ofs是uboot镜像整个大小,见链接脚本文件arch/arm/cpu/u-boot.lds。

tecoes的博客 175
上一篇: misc类驱动编写
下一篇: USB WIFI网卡在S5PV210的移植(1)
金银588
博客等级 码龄7年 1210粉丝 30原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值