链接文件连载 (1)- CACHE / NON-CACHE
CACHE / NON-CACHE
抛出问题
如何在链接过程中,把不同的函数指定放在CACHE 或者是 NON-CACHE呢。
实际代码使用
首先我们定义两个函数。让他们分别放在cache上和non-cache
static uint8 test_value =0;
#pragma section ".in_cache.text" ax
uint8 run_in_cache(void)
{
return test_value++;
}
#pragma section
#pragma section ".in_noncache.text" ax
uint8 run_in_noncache(void)
{
return test_value--;
}
#pragma section
uint8 link_main(void)
{
return run_in_cache() + run_in_noncache();
}
这里一目了然,两个函数,分别放在cache 和 non-cache。那么我们需要在链接文件里面如何实现呢?
这里我们采用的是Hightec编译器来做解释。
从上面的代码
可以看到 两个字段
- .in_cache.text
- .in_noncache.text
那么在链接文件如何体现呢?
链接文件 .ld 或者 .lsl 这里在里面添加一些定义如下
链接文件如何改动
地址定义
PFLASH0_TEST_NC (rx!p): org = 0xA0100000, len = 1k
PFLASH0_TEST (rx!p): org = 0x80100000, len = 1k
使用指令REGION_MIRROR来mirror一下两个地址。实际上在物理空间,这两个地址是一个地址。后面在map文件里也可以看出来。
REGION_MIRROR("PFLASH0_TEST","PFLASH0_TEST_NC")
给地址改个名字,这样看起来方便一点
REGION_ALIAS("FASTCODE",PFLASH0_TEST)
REGION_ALIAS("SLOWCODE",PFLASH0_TEST_NC)
定义代码存放的位置
.fast :
{
*(.in_cache.text)
}>FASTCODE
.slow :
{
*(.in_noncache.text)
}>SLOWCODE
哦,这里恍然大悟,看到了 前面代码里面用#pragma 指定的位置。
好我们编译一下看看结果。
这。。。。有点长。。。。请往后拉这看。
=============================================================================================================================================================================================================================================================================
Start End Size S Name Memory O-Sec I-Sec Input object
=============================================================================================================================================================================================================================================================================
0x80100000 0x8010000f 16 g run_in_cache PFLASH0_TEST .fast .in_cache.text output\objs\asw\Hightec_Link.o
0xa0100010 0xa010001f 16 g run_in_noncache PFLASH0_TEST_NC .slow .in_noncache.text output\objs\asw\Hightec_Link.o
可以看出来两个函数的地址A 与 8.并且 地址是连续的。
这里可能有人会问I-Sec 和 O-Sec是什么意思。
1. O-Sec(Output Section):O-Sec表示目标文件中的输出区段。在编译过程中,源代码被编译成目标文件,而目标文件中的代码和数据会被划分到不同的区段中。O-Sec存储着最终生成的可执行文件或库文件中的代码和数据。
2. I-Sec(Input Section):I-Sec表示目标文件中的输入区段。当将多个目标文件链接起来生成最终的可执行文件或库文件时,链接器会将各个目标文件中的I-Sec合并在一起。I-Sec是链接器在进行链接过程中使用的区段。
总结起来,O-Sec代表目标文件中的输出部分,而I-Sec代表目标文件中的输入部分,在链接过程中会合并多个目标文件的输入部分形成最终的可执行文件或库文件。
最终我们看一下elf文件解析出来的汇编+code
查看结果
下面是链接好了的可执行文件。(elf文件)
static uint8 test_value =0;
#pragma section ".in_cache.text" ax
uint8 run_in_cache(void)
{
return test_value++;
0x80100000 91 00 00 F7 MOVH.A a15,0x7000
0x80100004 39 F2 18 C0 LD.BU d2,[a15]0x318
0x80100008 9A 12 ADD d15,d2,0x1
0x8010000A E9 FF 18 C0 ST.B [a15]0x318,d15
}
0x8010000E 00 90 RET
...
#pragma section
#pragma section ".in_noncache.text" ax
uint8 run_in_noncache(void)
{
return test_value--;
0xA0100010 91 00 00 F7 MOVH.A a15,0x7000
0xA0100014 39 F2 18 C0 LD.BU d2,[a15]0x318
0xA0100018 9A F2 ADD d15,d2,-0x1
0xA010001A E9 FF 18 C0 ST.B [a15]0x318,d15
}
0xA010001E 00 90 RET
...
#pragma section
uint8 link_main(void)
{
return run_in_cache() + run_in_noncache();
0x800138C6 6D 07 9D 63 CALL run_in_cache (0x80100000)
0x800138CA 02 2F MOV d15,d2
0x800138CC ED A8 08 00 CALLA run_in_noncache (0xA0100010)
0x800138D0 42 F2 ADD d2,d15
}
0x800138D2 8F F2 0F 21 AND d2,d2,0xFF
0x800138D6 00 90 RET
这里是未链接的编译好了的汇编 (.o 文件)
static uint8 test_value =0;
#pragma section ".in_cache.text" ax
uint8 run_in_cache(void)
{
return test_value++;
0: 91 00 00 f0 movh.a %a15,0
4: 39 f2 00 00 ld.bu %d2,[%a15]0 <0 <run_in_cache>>
8: 9a 12 add %d15,%d2,1
a: e9 ff 00 00 st.b [%a15]0 <0 <run_in_cache>>,%d15
}
e: 00 90 ret
Disassembly of section .in_noncache.text:
00000000 <run_in_noncache>:
#pragma section
#pragma section ".in_noncache.text" ax
uint8 run_in_noncache(void)
{
return test_value--;
0: 91 00 00 f0 movh.a %a15,0
4: 39 f2 00 00 ld.bu %d2,[%a15]0 <0 <run_in_noncache>>
8: 9a f2 add %d15,%d2,-1
a: e9 ff 00 00 st.b [%a15]0 <0 <run_in_noncache>>,%d15
}
e: 00 90 ret
Disassembly of section .text.link_main:
00000000 <link_main>:
#pragma section
uint8 link_main(void)
{
return run_in_cache() + run_in_noncache();
0: 6d 00 00 00 call 0 <link_main>
4: 02 2f mov %d15,%d2
6: 6d 00 00 00 call 6 <link_main+0x6>
a: 42 f2 add %d2,%d15
}
c: 8f f2 0f 21 and %d2,%d2,255
10: 00 90 ret
对比上面两个汇编。确实 实际的地址调用 和我们前面的设计一致。
这里就完成了 对cache的指定函数存放。
文章转载自公众号:汽车与基础软件