1 uclinux的内存布局
在uclinux启动时,有一段空间利用的提示:
Memory map:
text
= 0x00001000-0x000b0db0
init
= 0x000b1000-0x000bd23c
data
= 0x000bf1b8-0x000e5588
stack
= 0x000c0000-0x000c2000
bss
= 0x000e5590-0x000f14d8
available = 0x000f14d8-0x03500000
rootfs
= 0x03500000-0x03f00000
DMA Zone = 0x03f00000-0x04000000
其中text代表这段空间中存储的是uclinux内核的代码;init中存放的也是uclinux内核的代码,但是这一段空间在内核启动完成后是可以回收的,即它可以供内核重新分配;DATA段是 uClinux 未被初始化的数据空间;BSS段是 uClinux初始化的数据空间,它的初始化操作将在head.s中完成。此外从0到text开始的这一段空间也会被初始化为0。
2 VDSP中的空间分配
uclinux的空间定位是由链接器完成的,由arch/blackfin/kernel/vmlinux.lds.s控制完成。而VDSP的空间定位则是由ldf文件完成的,而ldf文件的语法与vmlinux.lds.s相似。我们所要做的就是将vmlinux.lds.s中的相关定义转移到ldf文件中。
1、定义一块uclinux使用的内存空间:
MEM_SDRAM_UCLINUX
{ TYPE(RAM) START(0x00010000) END(0x001fffff) WIDTH(8) } 在这里,空间的结束使用了一个较大的数值,实际上在uclinux内核中会从代码实际结束的地方开始管理存储空间。
2、将uclinux内核的入口函数写入到0xFFA00000,即a核的启动地址。
RESOLVE(__start, 0xFFA00000)
KEEP(__start,_main)
VDSP默认的入口是start,在*_basiccrt.s中实现。经过这样处理后,A核就将从head.s中的__start开始,而B核仍将从*_basiccrt.s中的start开始执行。
3、移植.text段的内容。
// uclinux的代码部分
uclinux_text
{
INPUT_SECTION_ALIGN(4)
__stext__ = .;
__stext = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.text))
INPUT_SECTION_ALIGN(8)
__sched_text_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.sched.text))
__sched_text_end = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.text.lock))
INPUT_SECTION_ALIGN(16)
___start___ex_table = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ex_table))
___stop___ex_table = .;
// 原先放在L1_Code中的内容
INPUT_SECTION_ALIGN(4)
__CORE = 0;
INPUT_SECTIONS($OBJECTS_CORE_A(L1_code) $LIBRARIES_CORE_A(L1_code))
INPUT_SECTIONS($OBJECTS_CORE_A(VDK_ISR_code) $LIBRARIES_CORE_A(VDK_ISR_code))
INPUT_SECTIONS($OBJECTS_CORE_A(cplb) $LIBRARIES_CORE_A(cplb))
INPUT_SECTIONS($OBJECTS_CORE_A(cplb_code) $LIBRARIES_CORE_A(cplb_code))
INPUT_SECTIONS($OBJECTS_CORE_A(noncache_code) $LIBRARIES_CORE_A(noncache_code))
INPUT_SECTIONS($OBJS_LIBS_INTERNAL_CORE_A(program))
INPUT_SECTIONS($OBJS_LIBS_NOT_EXTERNAL_CORE_A(program))
INPUT_SECTIONS($OBJECTS_CORE_A(program) $LIBRARIES_CORE_A(program))
// SDRAM Bank0的内容
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS($LIBRARIES_SML3_CM(sdram_data_bank0))
INPUT_SECTIONS($LIBRARIES_SML3_CM(sdram_bank0))
INPUT_SECTIONS($LIBRARIES_SML3_CM(data1))
INPUT_SECTIONS($LIBRARIES_SML3_CM(voldata))
INPUT_SECTIONS($LIBRARIES_SML3_CM(constdata))
// SDRAM Bank1的内容
INPUT_SECTION_ALIGN(4)
INPUT_SECTIONS($LIBRARIES_SML3_CM(sdram0))
INPUT_SECTIONS($LIBRARIES_SML3_CM(sdram_data_bank1))
INPUT_SECTIONS($LIBRARIES_SML3_CM(sdram_bank1))
INPUT_SECTIONS($LIBRARIES_SML3_CM(program))
INPUT_SECTIONS($LIBRARIES_SML3_CM(noncache_code))
// uclinux代码
INPUT_SECTIONS($LIBRARIES_SML3_CM(program))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.rodata))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.rodata.*))
INPUT_SECTIONS($LIBRARIES_SML3_CM(__vermagic)) // Kernel version magic
INPUT_SECTIONS($LIBRARIES_SML3_CM(.rodata1))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.fixup))
// Kernel symbol table: Normal symbols
INPUT_SECTION_ALIGN(4)
___start___ksymtab = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab))
___stop___ksymtab = .;
// Kernel symbol table: GPL-only symbols
___start___ksymtab_gpl = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab_gpl))
___stop___ksymtab_gpl = .;
// Kernel symbol table: Normal unused symbols
___start___ksymtab_unused = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab_unused))
___stop___ksymtab_unused = .;
// Kernel symbol table: GPL-only unused symbols
___start___ksymtab_unused_gpl = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab_unused_gpl))
___stop___ksymtab_unused_gpl = .;
// Kernel symbol table: GPL-future symbols
___start___ksymtab_gpl_future = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab_gpl_future))
___stop___ksymtab_gpl_future = .;
// Kernel symbol table: Normal symbols
___start___kcrctab = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__kcrctab))
___stop___kcrctab = .;
// Kernel symbol table: GPL-only symbols
___start___kcrctab_gpl = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__kcrctab_gpl))
___stop___kcrctab_gpl = .;
// Kernel symbol table: GPL-future symbols
___start___kcrctab_gpl_future = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__kcrctab_gpl_future))
___stop___kcrctab_gpl_future = .;
// Kernel symbol table: strings
INPUT_SECTIONS($LIBRARIES_SML3_CM(__ksymtab_strings))
INPUT_SECTION_ALIGN(4)
__etext = .;
} > MEM_SDRAM_UCLINUX
在这里,除了uclinux的代码外,还插入了VDSP库的代码,因为我们希望尽可能使用VDSP提供的库函数。中间还有一部分代码和数据段混合在一起了,以后再进行细调。
还有一个特殊的符号__stext__,这个符号原来是放在head.s中的,表示uclinux内核第一行代码的起始位置,因为我们将第一行代码写到了0xffa00000,因此在head.s中的符号取消,转而在ldf文件中进行定义。
4、移植.init段定义。
// 初始化代码部分,可回收
uclinux_init
{
INPUT_SECTION_ALIGN(4096)
___init_begin = .;
__sinittext = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.init.text))
__einittext = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.init.data))
INPUT_SECTION_ALIGN(16)
___setup_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.init.setup))
___setup_end = .;
___start___param = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(__param))
___stop___param = .;
___initcall_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall1.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall2.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall3.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall4.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall5.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall6.init))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.initcall7.init))
___initcall_end = .;
___con_initcall_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.con_initcall.init))
___con_initcall_end = .;
___security_initcall_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.security_initcall.init))
___security_initcall_end = .;
INPUT_SECTION_ALIGN(4)
___initramfs_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.init.ramfs))
___initramfs_end = .;
INPUT_SECTION_ALIGN(4)
___init_end = .;
} > MEM_SDRAM_UCLINUX
5、移植的.text.l1,即需要放在L1中的部分。
uclinux_text_l1
{
INPUT_SECTION_ALIGN(4)
__l1_lma_start = .;
__stext_l1 = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.l1.text))
INPUT_SECTION_ALIGN(4)
__etext_l1 = .;
} > MEM_A_L1_CODE
6、移植.data.l1数据段。
uclinux_data_l1
{
INPUT_SECTION_ALIGN(4)
__sdata_l1 = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.l1.data))
INPUT_SECTIONS(corea.dlb(data1))
__edata_l1 = .;
INPUT_SECTION_ALIGN(4)
__sbss_l1 = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.l1.bss))
INPUT_SECTION_ALIGN(4)
__ebss_l1 = .;
} > MEM_A_L1_DATA_A
7、移植.data.b.l1。
uclinux_data_b_l1
{
INPUT_SECTION_ALIGN(4)
__sdata_b_l1 = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.l1.data.B))
__edata_b_l1 = .;
INPUT_SECTION_ALIGN(4)
__sbss_b_l1 = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.l1.bss.B))
INPUT_SECTION_ALIGN(4)
__ebss_b_l1 = .;
} > MEM_A_L1_DATA_B
8、移植数据段。
// 数据段
uclinux_data
{
INPUT_SECTION_ALIGN(0x2000)
__sdata = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.data.init_task))
INPUT_SECTIONS($LIBRARIES_SML3_CM(.data))
// 原先放在DATA_A的内容
INPUT_SECTION_ALIGN(4)
___l1_data_cache_a = 0;
INPUT_SECTIONS($OBJECTS_CORE_A(L1_data_a) $LIBRARIES_CORE_A(L1_data_a))
INPUT_SECTIONS($OBJECTS_CORE_A{DualCoreMem("CoreA")}(cplb_data) $LIBRARIES_CORE_A{DualCoreMem("CoreA")}(cplb_data))
INPUT_SECTIONS($OBJECTS_CORE_A(cplb_data) $LIBRARIES_CORE_A(cplb_data))
INPUT_SECTIONS($OBJECTS_CORE_A(voldata) $LIBRARIES_CORE_A(voldata))
INPUT_SECTIONS($OBJECTS_CORE_A(constdata) $LIBRARIES_CORE_A(constdata))
INPUT_SECTIONS($OBJS_LIBS_INTERNAL_CORE_A(data1))
INPUT_SECTIONS($OBJS_LIBS_NOT_EXTERNAL_CORE_A(data1))
INPUT_SECTIONS($OBJECTS_CORE_A(data1) $LIBRARIES_CORE_A(data1))
INPUT_SECTIONS($OBJECTS_CORE_A(.edt) $LIBRARIES_CORE_A(.edt))
INPUT_SECTIONS($OBJECTS_CORE_A(.cht) $LIBRARIES_CORE_A(.cht))
// 原先放在data_b的内容
INPUT_SECTION_ALIGN(4)
___l1_data_cache_b = 0;
INPUT_SECTIONS($OBJECTS_CORE_A(ctor) $LIBRARIES_CORE_A(ctor))
INPUT_SECTIONS($OBJECTS_CORE_A(ctorl) $LIBRARIES_CORE_A(ctorl))
INPUT_SECTIONS($OBJECTS_CORE_A(vtbl) $LIBRARIES_CORE_A(vtbl))
INPUT_SECTIONS($OBJECTS_CORE_A(.gdt) $LIBRARIES_CORE_A(.gdt))
INPUT_SECTIONS($OBJECTS_CORE_A(.gdtl) $LIBRARIES_CORE_A(.gdtl))
INPUT_SECTIONS($OBJECTS_CORE_A(.frt) $LIBRARIES_CORE_A(.frt))
INPUT_SECTIONS($OBJECTS_CORE_A(.rtti) $LIBRARIES_CORE_A(.rtti))
INPUT_SECTIONS($OBJECTS_CORE_A(.edt) $LIBRARIES_CORE_A(.edt))
INPUT_SECTIONS($OBJECTS_CORE_A(.cht) $LIBRARIES_CORE_A(.cht))
INPUT_SECTIONS($OBJS_LIBS_INTERNAL_CORE_A(data1))
INPUT_SECTIONS($OBJS_LIBS_NOT_EXTERNAL_CORE_A(data1))
INPUT_SECTIONS($OBJECTS_CORE_A(data1) $LIBRARIES_CORE_A(data1))
INPUT_SECTIONS($OBJECTS_CORE_A{DualCoreMem("CoreA")}(cplb_data) $LIBRARIES_CORE_A{DualCoreMem("CoreA")}(cplb_data))
INPUT_SECTIONS($OBJECTS_CORE_A(cplb_data) $LIBRARIES_CORE_A(cplb_data))
INPUT_SECTIONS($OBJECTS_CORE_A(voldata) $LIBRARIES_CORE_A(voldata))
INPUT_SECTIONS($OBJECTS_CORE_A(constdata) $LIBRARIES_CORE_A(constdata))
_jiffies = _jiffies_64;
INPUT_SECTION_ALIGN(4)
__edata = .;
} > MEM_SDRAM_UCLINUX
在这里插入了VDSP库中的数据段。
9、移植bss段。
// bss段
uclinux_bss
{
INPUT_SECTION_ALIGN(4)
___bss_start = .;
INPUT_SECTIONS($LIBRARIES_SML3_CM(.bss))
INPUT_SECTIONS($LIBRARIES_SML3_CM(COMMON))
INPUT_SECTION_ALIGN(4)
___bss_stop = .;
__end = . ;
} > MEM_SDRAM_UCLINUX