0.环境搭建过程中遇到的问题
1.解决THE FOLLOWING PACKAGES HAVE UNMET DEPENDENCIES问题!!!
终于搭建完成开发环境:
2.执行编译指令报错
Ubuntu下手动安装clang:
apt-get install clang
进入《Configuring_ubuntu.sh》文件搜索clang,发现如下代码,这是该脚本不支持ubuntu16的意思么?
似乎是…
经过实测需要使用ubuntu18.04
1.启动流程分析
reset_vector_up.s
1.关中断;设置CPU为SVC32模式;
/*
* disable interrupts (FIQ and IRQ), also set the cpu to SVC32 mode,
* except if in HYP mode already
*/
mrs r0, cpsr
and r1, r0, #0x1f @ mask mode bits
teq r1, #0x1a @ test for HYP mode
bicne r0, r0, #0x1f @ clear all mode bits
orrne r0, r0, #0x13 @ set SVC mode
orr r0, r0, #0xc0 @ disable FIQ and IRQ
msr cpsr,r0
2.禁止I-cache;
/*
* If I-cache is enabled invalidate it
*/
mcr p15, 0, r0, c7, c5, 0 @ invalidate icache
mcr p15, 0, r0, c7, c10, 4 @ DSB
mcr p15, 0, r0, c7, c5, 4 @ ISB
3.重定位(把程序复制到运行地址);
/* r11: delta of physical address and virtual address */
adr r11, pa_va_offset //把变量pa_va_offset的地址给r11
ldr r0, [r11] //把变量r11存储的变量作为地址,指向的数据给r0
sub r11, r11, r0 //计算地址偏差
/* if we need to relocate to proper location or not */
adr r4, __exception_handlers /* r4: base of load address */
/*__exception_handlers就是异常向量表的首地址,也就是整个程序运行的首地址*/
ldr r5, =SYS_MEM_BASE /* r5: base of physical address*/
/* 处理器内部DDR的物理空间起始地址 */
subs r12, r4, r5 /* r12: delta of load address and physical address */
beq reloc_img_to_bottom_done /* if we load image at the bottom of physical address */
/* 若当前的运行地址和物理地址一致,则跳转到下面的函数,无需进行进行搬运 ,即重定位*/
3.1.搬运分支
/* we need to relocate image at the bottom of physical address */
ldr r7, =__exception_handlers /* r7: base of linked address (or vm address) */
/* r7=实际程序代码段的首地址 */
ldr r6, =__bss_start /* r6: end of linked address (or vm address) */
/* r6=实际程序代码段的末地址 */
sub r6, r7 /* r6: delta of linked address (or vm address) */
/* r6=实际程序代码段的长度 */
add r6, r4 /* r6: end of load address */
/* r6=实际程序代码段的末地址 */
/* 循环搬运 */
reloc_img_to_bottom_loop:
ldr r7, [r4], #4
str r7, [r5], #4
cmp r4, r6
bne reloc_img_to_bottom_loop
sub pc, r12
nop
sub r11, r11, r12 /* r11: eventual address offset */
3.2.无需搬运分支
ldr r4, =g_firstPageTable /* r4: physical address of translation table and clear it */
/* r4=页表的物理地址起始地址 */
add r4, r4, r11
bl page_table_clear /* 页表空间清零 */
4.LINE175:设置页表(虚拟地址转换为物理地址),代码如下
PAGE_TABLE_SET SYS_MEM_BASE, UNCACHED_VMM_BASE, UNCACHED_VMM_SIZE, MMU_INITIAL_MAP_STRONGLY_ORDERED
#ifdef LOSCFG_PLATFORM_IMX6ULL
PAGE_TABLE_SET DDR_RAMFS_ADDR, DDR_RAMFS_VBASE, DDR_RAMFS_SIZE, MMU_INITIAL_MAP_DEVICE
PAGE_TABLE_SET LCD_FB_BASE, LCD_FB_VBASE, LCD_FB_SIZE, MMU_INITIAL_MAP_DEVICE
#endif
PAGE_TABLE_SET SYS_MEM_BASE, KERNEL_VMM_BASE, KERNEL_VMM_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_DEVICE_BASE, PERIPH_DEVICE_SIZE, MMU_INITIAL_MAP_DEVICE
PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_CACHED_BASE, PERIPH_CACHED_SIZE, MMU_DESCRIPTOR_KERNEL_L1_PTE_FLAGS
PAGE_TABLE_SET PERIPH_PMM_BASE, PERIPH_UNCACHED_BASE, PERIPH_UNCACHED_SIZE, MMU_INITIAL_MAP_STRONGLY_ORDERED
其中,PAGE_TABLE_SET
为宏定义,其定义在reset_vector_up.s
为:
/* param0 is physical address, 物理地址
param1 virtual address, 虚拟地址
param2 is sizes, 大小
param3 is flag 标志
*/
.macro PAGE_TABLE_SET param0, param1, param2, param3
ldr r6, =\param0
ldr r7, =\param1
ldr r8, =\param2
ldr r10, =\param3
bl page_table_build
.endm
在MMU启动之前,CPU发出的地址可以直接到达设备,之后则需要经过MMU再发给设备(关于页表和MMU的具体值是参见《嵌入式Linux应用开发完全手册_韦东山全系列视频文档全集V2.4》P639)
bl mmu_setup /* set up the mmu */
5.多核心CPU的处理方式
/* get cpuid and keep it in r11 */
mrc p15, 0, r11, c0, c0, 5
and r11, r11, #MPIDR_CPUID_MASK
/* 判断当前的core是否为核0,若为核0则初始化堆栈,若不是则跳过 */
cmp r11, #0
bne excstatck_loop_done
excstatck_loop:
/* clear out the interrupt and exception stack and set magic num to check the overflow */
ldr r0, =__undef_stack
ldr r1, =__exc_stack_top
bl stack_init
STACK_MAGIC_SET __undef_stack, #OS_EXC_UNDEF_STACK_SIZE, OS_STACK_MAGIC_WORD
STACK_MAGIC_SET __abt_stack, #OS_EXC_ABT_STACK_SIZE, OS_STACK_MAGIC_WORD
STACK_MAGIC_SET __irq_stack, #OS_EXC_IRQ_STACK_SIZE, OS_STACK_MAGIC_WORD
STACK_MAGIC_SET __fiq_stack, #OS_EXC_FIQ_STACK_SIZE, OS_STACK_MAGIC_WORD
STACK_MAGIC_SET __svc_stack, #OS_EXC_SVC_STACK_SIZE, OS_STACK_MAGIC_WORD
STACK_MAGIC_SET __exc_stack, #OS_EXC_STACK_SIZE, OS_STACK_MAGIC_WORD
excstatck_loop_done:
6.设置堆栈
/* set svc stack, every cpu has OS_EXC_SVC_STACK_SIZE stack */
ldr r0, =__svc_stack_top
mov r2, #OS_EXC_SVC_STACK_SIZE
mul r2, r2, r11
sub r0, r0, r2
mov sp, r0
7.设置FPU+NEON
/* enable fpu+neon */
MRC p15, 0, r0, c1, c1, 2
ORR r0, r0, #0xC00
BIC r0, r0, #0xC000
MCR p15, 0, r0, c1, c1, 2
LDR r0, =(0xF << 20)
MCR p15, 0, r0, c1, c0, 2
MOV r3, #0x40000000
VMSR FPEXC, r3
LDR r0, =__exception_handlers
MCR p15, 0, r0, c12, c0, 0
cmp r11, #0
bne cpu_start
8.跳转到main函数
bl main
9.跳转到main函数-路径\kernel\liteos_a\platform
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
{
UINT32 uwRet = LOS_OK;
OsSetMainTask();
OsCurrTaskSet(OsGetMainTask());
/* set smp system counter freq */
#if (LOSCFG_KERNEL_SMP == YES)
#ifndef LOSCFG_TEE_ENABLE
HalClockFreqWrite(OS_SYS_CLOCK);
#endif
#endif
/* system and chip info */
OsSystemInfo();
PRINT_RELEASE("\nmain core booting up...\n");
uwRet = OsMain();
if (uwRet != LOS_OK) {
return LOS_NOK;
}
#if (LOSCFG_KERNEL_SMP == YES)
PRINT_RELEASE("releasing %u secondary cores\n", LOSCFG_KERNEL_SMP_CORE_NUM - 1);
release_secondary_cores();
#endif
CPU_MAP_SET(0, OsHwIDGet());
OsStart();
while (1) {
__asm volatile("wfi");
}
}
7.跳转到uwRet = OsMain();
函数
(1)串口初始化;uart_init();
(2)操作系统任务初始化;ret = OsTaskInit();
(3)操作系统内存初始化;ret = OsSysMemInit();
…