init函数详解
2017-09-05 16:28
363 查看
1.主要功能,红色部分是android特有的一些功能,如fastboot,recovery模式等: * Variety of nand devices for bootup * USB driver to enable upgrading images over usb during development * Keypad driver to enable developers enter ‘fastboot’ mode for image upgrades * Display driver for debugging and splash screen * Enable Android recovery image and image upgrades 2.配置dram内存大小,供linux kernel使用 The memory tags can be customized inlk/target/<target_name>/atags.c 3.fastboot模式,可以自行打开或者关闭 如,在boot中关闭按键或者usb 驱动,都可以达到此目的 相关文件 lk/app/aboot/fastboot.c lk/app/aboot/aboot.c 4.MTD block setting 可以配置各个mtd image 分区在如下 文件中 lk\target\tcc8900_evm\init.c static struct ptentry board_part_list[] 5.打开或者关闭splash screen in the bootloader DISPLAY_SPLASH_SCREEN功能可以来打开关闭 开机时候,boot会从’splash’ MTD分区中读取原始的文件到framebuffer中显示,所以也需要加载display 的驱动 入口函数在 kernel/main.c 中的 kmain(), 以下就来读读这一段 code. void kmain(void) { // get us into some sort of thread context thread_init_early(); // early arch stuff arch_early_init(); // do any super early platform initialization platform_early_init(); // do any super early target initialization target_early_init(); dprintf(INFO, "welcome to lk/n/n"); // deal with any static constructors dprintf(SPEW, "calling constructors/n"); call_constructors(); // bring up the kernel heap dprintf(SPEW, "initializing heap/n"); heap_init(); // initialize the threading system dprintf(SPEW, "initializing threads/n"); thread_init(); // initialize the dpc system dprintf(SPEW, "initializing dpc/n"); dpc_init(); // initialize kernel timers dprintf(SPEW, "initializing timers/n"); timer_init(); #if (!ENABLE_NANDWRITE) // create a thread to complete system initialization dprintf(SPEW, "creating bootstrap completion thread/n"); thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); // enable interrupts exit_critical_section(); // become the idle thread thread_become_idle(); #else bootstrap_nandwrite(); #endif } In include/debug.h: 我们可以看到 dprintf ()的第一个参数是代表 debug level. /* debug levels */ #define CRITICAL 0 #define ALWAYS 0 #define INFO 1 #define SPEW 2 In include/debug.h: view plainprint? #define dprintf(level, x...) do { if ((level) <= DEBUGLEVEL) { _dprintf(x); } } while (0) 所以 dprintf 会依 DEBUGLEVEL 来判断是否输出信息. 来看第一个 call 的函数: thread_init_early, define in thread.c view plainprint? void thread_init_early(void) { int i; /* initialize the run queues */ for (i=0; i < NUM_PRIORITIES; i++) list_initialize(&run_queue[i]); /* initialize the thread list */ list_initialize(&thread_list); /* create a thread to cover the current running state */ thread_t *t = &bootstrap_thread; init_thread_struct(t, "bootstrap"); /* half construct this thread, since we're already running */ t->priority = HIGHEST_PRIORITY; t->state = THREAD_RUNNING; t->saved_critical_section_count = 1; list_add_head(&thread_list, &t->thread_list_node); current_thread = t; } #define NUM_PRIORITIES 32 in include/kernel/thread.h list_initialize() defined in include/list.h: initialized a list view plainprint? static inline void list_initialize(struct list_node *list) { list->prev = list->next = list; } run_queue 是 static struct list_node run_queue[NUM_PRIORITIES] thread_list 是 static struct list_node thread_list 再来要 call 的函数是: arch_early_init() defined in arch/arm/arch.c view plainprint? void arch_early_init(void) { /* turn off the cache */ arch_disable_cache(UCACHE); /* set the vector base to our exception vectors so we dont need to double map at 0 */ #if ARM_CPU_CORTEX_A8 set_vector_base(MEMBASE); #endif #if ARM_WITH_MMU arm_mmu_init(); platform_init_mmu_mappings(); #endif /* turn the cache back on */ arch_enable_cache(UCACHE); #if ARM_WITH_NEON /* enable cp10 and cp11 */ uint32_t val; __asm__ volatile("mrc p15, 0, %0, c1, c0, 2" : "=r" (val)); val |= (3<<22)|(3<<20); __asm__ volatile("mcr p15, 0, %0, c1, c0, 2" :: "r" (val)); /* set enable bit in fpexc */ val = (1<<30); __asm__ volatile("mcr p10, 7, %0, c8, c0, 0" :: "r" (val)); #endif } 现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit, 内存管理单元)提供支持。 CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Address,以下简称VA),而MMU将这个地 址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PA MMU将VA映射到PA是以页(Page)为单位的,32位处理器的页尺寸通常是4KB。例如,MMU可以通过一个映射项将VA的一页 0xb7001000~0xb7001fff映射到PA的一页0x2000~0x2fff,如果CPU执行单元要访问虚拟地址0xb7001008,则实际访问到的物理地 址是0x2008。物理内存中的页称为物理页面或者页帧(Page Frame)。虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页 表(Page Table)来描述的,页表保存在物理内存中,MMU会查找页表来确定一个VA应该映射到什么PA。 操作系统和MMU是这样配合的: 1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中 的什么位置。 2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令 控制MMU去做。 MMU除了做地址转换之外,还提供内存保护机制。各种体系结构都有用户模式(User Mode)和特权模式(Privileged Mode)之分, 操作系统可以在页表中设置每个内存页面的访问权限,有些页面不允许访问,有些页面只有在CPU处于特权模式时才允许访问,有些页面 在用户模式和特权模式都可以访问,访问权限又分为可读、可写和可执行三种。这样设定好之后,当CPU要访问一个VA时,MMU会检查 CPU当前处于用户模式还是特权模式,访问内存的目的是读数据、写数据还是取指令,如果和操作系统设定的页面权限相符,就允许访 问,把它转换成PA,否则不允许访问,产生一个异常(Exception) 常见的 segmentation fault 产生的原因: 用户程序要访问一段 VA, 经 MMU 检查后无权访问, MMU 会产生异常, CPU 从用户模式切换到特权模式, 跳转到内核代码中执行异常服务程序. 内核就会把这个异常解释为 segmentation fault, 将引发异常的程序终止.
相关文章推荐
- Shell公共函数:/etc/init.d/functions详解
- PHP&nbsp;curl_init函数详解
- stm32启动文件详解及SystemInit函数分析
- STM32时钟初始化函数SystemInit()详解【转】
- linux驱动入口函数module_init详解
- ngx_os_init函数详解
- kswapd_init()函数详解
- Go init函数详解
- 004:STM32启动文件详解及SystemInit函数分析(转)
- STM32启动文件详解及SystemInit函数分析(转)
- STM32时钟初始化函数SystemInit()详解
- ngx_crc32_table_init函数详解
- OpenSSL EVP_EncryptInit 函数官方详解
- STM32时钟初始化函数SystemInit()详解[转]
- JDE系统函数详解---JDB_InitBhvr
- php curl_init函数用法实例详解
- linux模块(module_init)、子系统(subsys_initcall)入口函数详解
- 第六章:STM32时钟初始化函数SystemInit()详解
- SQL Server数据库ROW_NUMBER()函数使用详解
- 详解spl_autoload_register()函数