1、 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,
2、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 #define d
3、printf(level, x.) do if (level) <= DEBUGLEVEL) _dprintf(x); while (0) 所以 dprintf 会依 DEBUGLEVEL 来判断是否输出信息.来看第一个 call 的函数: thread_init_early, define in thread.cvoid thread_init_early(void) int i; /* initialize the run queues */ for (i=0; i & NUM_PRIORITIES; i+) list_initialize(&run_queuei); /* init
4、ialize 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 were already running */ t->priority = HIGHEST_PRIORITY; t-&state = THREAD_RUNNING
5、;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.hlist_initialize() defined in include/list.h: initialized a liststatic inline void list_initialize(struct list_node *list) list-&prev = list-&n
6、ext = list;run_queue 是 static struct list_node run_queueNUM_PRIORITIESthread_list 是 static struct list_node thread_list再来要 call 的函数是: arch_early_init() defined in arch/arm/arch.cvoid arch_early_init(void) /* turn off the cache */ arch_disable_cache(UCACHE); /* set the vector base to our exception ve
7、ctors 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(m
8、rc p15, 0, %0, c1, c0, 2 : =r (val); val |= (3&22)|(3&20);mcr p15, 0, %0, c1, c0, 2:r /* set enable bit in fpexc */ val = (1&30);mcr p10, 7, %0, c8, c0, 0现代操作系统普遍采用虚拟内存管理(Virtual Memory Management)机制,这需要处理器中的MMU(Memory Management Unit,内存管理单元)提供支持。CPU执行单元发出的内存地址将被MMU截获,从CPU到MMU的地址称为虚拟地址(Virtual Addre
9、ss,以下简称VA),而MMU将这个地址翻译成另一个地址发到CPU芯片的外部地址引脚上,也就是将VA映射成PAMMU将VA映射到PA是以页(Page)为单位的,32位处理器的页尺寸通常是4KB。例如,MMU可以通过一个映射项将VA的一页0xb70010000xb7001fff映射到PA的一页0x20000x2fff,如果CPU执行单元要访问虚拟地址0xb7001008,则实际访问到的物理地址是0x2008。物理内存中的页称为物理页面或者页帧(Page Frame)。虚拟内存的哪个页面映射到物理内存的哪个页帧是通过页表(Page Table)来描述的,页表保存在物理内存中,MMU会查找页表来确定
10、一个VA应该映射到什么PA。操作系统和MMU是这样配合的:1. 操作系统在初始化或分配、释放内存时会执行一些指令在物理内存中填写页表,然后用指令设置MMU,告诉MMU页表在物理内存中 的什么位置。2. 设置好之后,CPU每次执行访问内存的指令都会自动引发MMU做查表和地址转换操作,地址转换操作由硬件自动完成,不需要用指令 控制MMU去做。MMU除了做地址转换之外,还提供内存保护机制。各种体系结构都有用户模式(User Mode)和特权模式(Privileged Mode)之分,操作系统可以在页表中设置每个内存页面的访问权限,有些页面不允许访问,有些页面只有在CPU处于特权模式时才允许访问,有些
11、页面在用户模式和特权模式都可以访问,访问权限又分为可读、可写和可执行三种。这样设定好之后,当CPU要访问一个VA时,MMU会检查CPU当前处于用户模式还是特权模式,访问内存的目的是读数据、写数据还是取指令,如果和操作系统设定的页面权限相符,就允许访问,把它转换成PA,否则不允许访问,产生一个异常(Exception)常见的 segmentation fault 产生的原因:用户程序要访问一段 VA, 经 MMU 检查后无权访问, MMU 会产生异常, CPU 从用户模式切换到特权模式, 跳转到内核代码中执行异常服务程序.内核就会把这个异常解释为 segmentation fault, 将引发异
12、常的程序终止.简单的讲一下 NEON: NEON technology can accelerate multimedia and signal processing algorithms such as video encode/decode,2D/3D graphics, gaming, audio and speech processing, image processing, telephony, and sound synthesis.platform_early_init() defined in platform/&your-platform&/platform.cvoid pl
13、atform_early_init(void) uart_init(); platform_init_interrupts(); platform_init_timer();uart_init.c defined in platform/&/uart.c 所有用到的变数,也都定义在 uart.cvoid uart_init(void) uwr(0x0A, UART_CR); /* disable TX and RX */ uwr(0x30, UART_CR); /* reset error status */ uwr(0x10, UART_CR); /* reset receiver */ u
14、wr(0x20, UART_CR); /* reset transmitter */ #if PLATFORM_QSD8K /* TCXO */ uwr(0x06, UART_MREG); uwr(0xF1, UART_NREG); uwr(0x0F, UART_DREG); uwr(0x1A, UART_MNDREG); #else /* TCXO/4 */ uwr(0xC0, UART_MREG); uwr(0xAF, UART_NREG); uwr(0x80, UART_DREG); uwr(0x19, UART_MNDREG); #endif uwr(0x10, UART_CR); /
15、* reset RX */ uwr(0x20, UART_CR); /* reset TX */ uwr(0x30, UART_CR); /* reset error status */ uwr(0x40, UART_CR); /* reset RX break */ uwr(0x70, UART_CR); /* rest? */ uwr(0xD0, UART_CR); /* reset */ uwr(0x7BF, UART_IPR); /* stale timeout = 630 * bitrate */ uwr(0, UART_IMR); uwr(115, UART_RFWR); /* R
16、X watermark = 58 * 2 - 1 */ uwr(10, UART_TFWR); /* TX watermark */ uwr(0, UART_RFWR); uwr(UART_CSR_115200, UART_CSR); uwr(0, UART_IRDA); uwr(0x1E, UART_HCR); / uwr(0x7F4, UART_MR1); /* RFS/ CTS/ 500chr RFR */ uwr(16, UART_MR1); uwr(0x34, UART_MR2); /* 8N1 */ uwr(0x05, UART_CR); /* enable TX & RX */
17、uart_ready = 1;platform_init_interrupts: defined in platform/msm8x60/interrupts.cvoid platform_init_interrupts(void) platform_gic_dist_init(); platform_gic_cpu_init();GIC 指的是 Generic Interrupt Controller. The gic-cpu and gic-dist are two subcomponents of GIC.Devices are wired to the git-dist which i
18、s in charge of distributing interrupts to the gic-cpu (per cpu IRQ IF).platform_init_timer(): defined in platform/&/timer.cvoid platform_init_timer(void) writel(0, DGT_ENABLE);DGT: Digital Game Timer: presents the countdowns of two players, it is also called chess timer or chess clock.target_early_i
19、nit(): defined in target/init.c/* * default implementations of these routines, if the target code * chooses not to implement. */ _WEAK void target_early_init(void) _WEAK void target_init(void) call_constructors() is defined in kernel/main.c:static void call_constructors(void) void *ctor; ctor = &_ct
20、or_list; while(ctor != &_ctor_end) void (*func)(void); func = (void (*)()*ctor; func(); ctor+; heap_init is defined in lib/heap/heap.c:void heap_init(void) LTRACE_ENTRY; / set the heap range theheap.base = (void *)HEAP_START; theheap.len = HEAP_LEN; LTRACEF(base %p size %zd bytes/n, theheap.base, th
21、eheap.len); / initialize the free list list_initialize(&theheap.free_list); / create an initial free chunk heap_insert_free_chunk(heap_create_free_chunk(theheap.base, theheap.len); / dump heap info / heap_dump(); / dprintf(INFO, running heap tests/n / heap_test();thread_init is defined in kernel/thr
22、ead.c but nothing coded, 先记下.void thread_init(void) dpc_init() is defined in kernel/dpc.c:void dpc_init(void) event_init(&dpc_event, false, 0);dpcdpc_thread_routine, NULL, DPC_PRIORITY, DEFAULT_STACK_SIZE);dpc 为 Delayed Procedure Call 延迟过程调用的缩写.timer_init() is defined in kernel/timer.c:void timer_in
23、it(void) list_initialize(&timer_queue); /* register for a periodic timer tick */ platform_set_periodic_timer(timer_tick, NULL, 10); /* 10ms */ 执行 thread_resume 或是 bootstrap_nandwrite#if (! #endif In kermel/main.c:static int bootstrap2(void *arg) dprintf(SPEW, top of bootstrap2()/n arch_init(); / ini
24、tialize 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; #if (ENABLE_NANDWRITE) void bootstrap_nandwrite(void) dprintf(SPEW, calling nandwrite_init()/n nandwrite_init(); #endif continue to see apps_init(): app/app.c:void apps_init(void)#include &app.h& #include
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1