【AG35源代码分析】01 之 ql-ol-bootloader 源码分析

一、ql-ol-bootloader 源码分析

1.1 ql-ol-bootloader\arch\arm\crt0.S

crt0.S主要作用是:

  1. 初始化中断向量表
  2. 初始化CPU、MMU、Cache等相关配置
  3. 初始 BSS 栈,为运行C 代码创建环境
  4. 跳转进入kmain()开始运行C代码
@ ql-ol-bootloader\arch\arm\crt0.S
.globl _start
_start:
	b	reset
reset:
    …… 做一系列的CPU、Cache、BSS 初始化操作……
	bl		kmain
	b		.

1.2 ql-ol-bootloader\kernel\main.c:kmain()

主要工作如下:

  1. 初始化thread_list,当前线程命令为bootstrap
  2. 初始化mmu,关闭cache,初始化mmu,后再使能cache
  3. 获取platform平台硬件相关版本号等信息,保存在struct board_data board结构体中
  4. 初始化mdm_clocks_9607[]数组中的clock,如Uart5、Uart2、USB、ce1等clock
  5. 初始化通用中断控制器
  6. 初始化scm_call,主要是发送 IS_CALL_AVAIL_CMD 命令检查SCM功能能不能用
  7. 初始化UART调试口
  8. 初始化 heap 堆空间
  9. 生成一个随机数,保存在全局变量__stack_chk_guard中,用作栈顶填充使用
  10. 创建一个dpc 线程,线程中一直死循环等dpc_event event,然后处理 dpc cb函数
  11. 初始kernel timer_tick为10ms
  12. 创建bootstrap2线程,运行bootstrap2()函数
  13. 将当前线程设置为 idle线程,设置优先级为 LOWEST_PRIORITY=0

代码分析如下:

/* called from crt0.S */
void kmain(void) __NO_RETURN __EXTERNALLY_VISIBLE;
void kmain(void){
    
    

	// 初始化thread_list,当前线程命令为bootstrap
	thread_init_early();
    // 关闭cache,初始化mmu后再使能cache
	arch_early_init();  
	==========>   // ql-ol-bootloader\arch\arm\arch.c
		{
    
    
			arch_disable_cache(UCACHE);		/* turn off the cache */
			arm_mmu_init();
			arch_enable_cache(UCACHE);		/* turn the cache back on */
		}
	<==========
	
	platform_early_init();  
	==========>   // ql-ol-bootloader\platform\mdm9607\platform.c	
		void platform_early_init(void)
		{
    
    
			board_init();
				--------->
					// 获取主板SMEM_BOARD_INFO_LOCATION区域的major minor info,
					// 初始化static struct board_data board结构体,如主板、平台、硬件、PMIC相关信息
					platform_detect();	
					target_detect(&board);
					target_baseband_detect(&board);
				<---------
			// 初始化mdm_clocks_9607[]数组中的clock,如Uart5、Uart2、USB、ce1等clock
			platform_clock_init();
			// 初始化通用中断控制器
			qgic_init();
			// 获取时钟频率 timer frequency
			qtimer_init();
			// 初始化scm_call,主要是发送 IS_CALL_AVAIL_CMD 命令检查SCM功能能不能用
			scm_init();
			// 将DDR内存映射到MMU
			board_ddr_detect();
		}
	<==========
	//初始化UART调试口
	target_early_init();    // do any super early target initialization

	dprintf(INFO, "welcome to lk\n\n");
	bs_set_timestamp(BS_BL_START);
	dprintf(SPEW, "calling constructors\n");
	// 依次调用__ctor_list 中的所有初始化函数,调用C++的构造函数,此处忽略
	call_constructors();

	// 初始化 heap 堆空间,bring up the kernel heap
	dprintf(SPEW, "initializing heap\n");
	heap_init();
	// 生成一个随机数,保存在全局变量__stack_chk_guard中,
	// 它的作用为,在调用子函数时,会将__stack_chk_guard值保存在栈顶,
	// 当子函数返回时,再读出这个值,如果相等,则正常返回,如果不相等,则可以判断存在栈溢出,
	// 调用__stack_chk_fail() 直接宕机,由于它是随机生成的随机数,所以相对安全。
	__stack_chk_guard_setup();

	dprintf(SPEW, "initializing threads\n");
	thread_init();	// initialize the threading system

	// 创建一个dpc 线程,线程中一直死循环等dpc_event event,然后处理 dpc cb函数
	// initialize the dpc system
	dprintf(SPEW, "initializing dpc\n");
	dpc_init();
	=========>
		thr = thread_create("dpc", &dpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE);

	// 初始kernel timer_tick为10ms, initialize kernel timers
	dprintf(SPEW, "initializing timers\n");
	timer_init();
	
	// 创建bootstrap2线程,运行bootstrap2()函数
	// create a thread to complete system initialization
	dprintf(SPEW, "creating bootstrap completion thread\n");
	thr = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
	thread_resume(thr);
	// enable interrupts
	exit_critical_section();
	// 将当前线程设置为 idle线程,设置优先级为 LOWEST_PRIORITY=0 , become the idle thread
	thread_become_idle();
}


1.3 ql-ol-bootloader\kernel\main.c:bootstrap2()

static int bootstrap2(void *arg)
{
    
    
	dprintf(SPEW, "top of bootstrap2()\n");

	arch_init();

	// XXX put this somewhere else
#if WITH_LIB_BIO
	bio_init();
#endif
#if WITH_LIB_FS
	fs_init();
#endif

	// initialize the rest of the platform
	dprintf(SPEW, "initializing platform\n");
	platform_init();

	// initialize the target
	dprintf(SPEW, "initializing target\n");
	target_init();

	dprintf(SPEW, "calling apps_init()\n");
	apps_init();

	return 0;
}

猜你喜欢

转载自blog.csdn.net/Ciellee/article/details/129875987