链接文件连载 (1)- CACHE / NON-CACHE

无聊逛51
发布于 2023-11-13 11:42
浏览
0收藏

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。那么我们需要在链接文件里面如何实现呢?

链接文件连载 (1)- 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的指定函数存放。


文章转载自公众号:汽车与基础软件


分类
标签
已于2023-11-13 11:42:54修改
收藏
回复
举报
回复
    相关推荐