公告

大中华汽车电子生态圈社区并入开发者社区- 更多资讯点击此

Tip / 登入 to post questions, reply, level up, and achieve exciting badges. Know more

cross mob

AURIX TC3XX MCAL中Link文件解析以及代码变量定位方法详解

AURIX TC3XX MCAL中Link文件解析以及代码变量定位方法详解

Quanqiu
Employee
Employee
First like received 100 comments on blog 50 comments on blog

1.        Tasking Link文件解析:

1.1 DSRAM中的数据存放:

 

在Aurix 2G中(以TC387为例),每个CPU都有自己的PSRAM (又称PSPR)和DSRAM (又称DSPR),它们都是RAM,只不过PSRAM是挂在指令总线上,而DSRAM是挂在数据总线上,因此如果在PSRAM运行代码,DSRAM存放数据,可以达到0 cycle等待。但是PSRAM上也是可能存放数据的,只不过效率低一点。

DSRAM的起始地址如下:

CPU0 DSRAM

   

0x70000000

   

CPU1 DSRAM

   

0x60000000

   

CPU2 DSRAM

   

0x50000000

   

CPU3 DSRAM

   

0x40000000

   

 

在MCAL的Tasking link文件中,对于数据的存放如下图所示:

 

 

 

 

 

 

CSA:

CSA是用来在函数调用或者进出中断时用来保存通用寄存器的区域,具体可到英飞凌官网(www.infineon.com)下载“AURIX? TC3xx Architecture“用户手册。它的大小由LCF_CSAx_SIZE决定。

ISTACK:

在中断服务程序中使用的栈,它的大小由LCF_ISTACKx_SIZE决定

 

USTACK:

在用户程序中使用的栈,它的大小由LCF_USTACKx_SIZE决定

Heap:

程序中使用的堆,它的大小由LCF_HEAP_SIZE决定

Predefine Data/Data:

Data区域是用来存放带初始化值的全局变量,在link文件中,这个区域有两种类型,预先定义的区域和默认区域,

预先定义的Data区域,例如.data.Ifx_Ssw_Tc1和.data.Cpu1_Main[CQQ(ASGS1] .*, 在cpu1_main.c中如果定义了一个带初始化值的变量,则它会放在DSRAM1中的.data.Cpu1_Main.*段中

 

group (ordered, attributes=rw, run_addr=mem:dsramx)

        {

          select ".data.Ifx_Ssw_Tcx.*";

          select ".data.Cpux_Main.*";

          …

}

 

   

 

而如果在一个其他.c文件(例如demo.c)中定义了一个带初始化值的变量,则它会放在DSRAM0中data区域(即默认区域),这个由Link文件中下面语句决定:

 

 

#    if LCF_DEFAULT_HOST == LCF_CPU0

    group (ordered, contiguous, align = 4, attributes=rw, run_addr = mem:dsram0)

#    endif

    {

      group data(attributes=rw)

      {

        select ".data.*";

        select ".data.farDsprInit.cpu0.32bit";

        select ".data.farDsprInit.cpu0.16bit";

        select ".data.farDsprInit.cpu0.8bit";

      }

      …

}

 

   

 

Predefine BSS/BSS:

BSS区域是用来存放没有初始值的全局变量,在link文件中,这个区域有两种类型,预先定义的区域和默认区域,

预先定义的BSS区域,例如.bss.Ifx_Ssw_Tc1和.bss.Cpu1_Main.*, 在cpu1_main.c中如果定义了一个带初始化值的变量,则它会放在DSRAM1中的.bss.Cpu1_Main.*段中

 

group (ordered, attributes=rw, run_addr=mem:dsramx)

        {

          select ".bss.Ifx_Ssw_Tcx.*";

          select ".bss.Cpux_Main.*";

          …

}

 

   

 

而如果在一个其他.c文件(例如demo.c)中定义了一个不带初始化值的变量,则它会放在DSRAM0中BSS区域(即默认区域),这由Link文件中下面语句决定:

 

 

#    if LCF_DEFAULT_HOST == LCF_CPU0

    group (ordered, contiguous, align = 4, attributes=rw, run_addr = mem:dsram0)

#    endif

    {

      group bss(attributes=rw)

      {

        select ".bss.*";

        select ".bss.farDsprClearOnInit.cpu0.32bit";

        select ".bss.farDsprClearOnInit.cpu0.16bit";

        select ".bss.farDsprClearOnInit.cpu0.8bit";

      }      

 …

}

 

   

 


 

 

 

1.2 PFlash中的代码存放

TC3xx的Flash是以3MB或者1MB作为一个Bank,不用Cache的地址从0xA0000000开始,用Cache的地址从0x80000000开始。

 

在MCAL的Link文件中,常量和代码的存放如下图所示:

 

 

Predefined text/text:

Text段用来存放代码,它分为两种:一种是预先定义好的text段,另外一种默认的text段。

预先定义好的text段,例如.text.Cpu1_Main.*, 在Cpu1_Main.c中的代码会放在这个段内。

 

group (ordered, align = 4, run_addr=mem:pflsx)

        {

          select ".text.Ifx_Ssw_Tcx.*";

          select ".text.Cpux_Main.*";

          select ".text.text_cpux*";

          select "*Code.Cpux";

          select "*Code.Fast.Cpux";

        }

 

   

 

但是如果是其他.c文件(例如demo.c),则会放在默认的text段中,这个是由Link文件中下面语句决定的:

 

 

#    if LCF_DEFAULT_HOST == LCF_CPU0

    group (ordered, run_addr=mem:pfls0)

#    endif

    {

      select ".text.*";

      select ".text.fast.pfls.cpu0";

      select ".text.slow.pfls.cpu0";

      select ".text.5ms.pfls.cpu0";

      select ".text.10ms.pfls.cpu0";

      select ".text.callout.pfls.cpu0";

      }

 

   

 

Predefined rodata/rodata:

rodata段用来存放代码,它分为两种:一种是预先定义好的rodata段,另外一种默认的rodata段。

预先定义好的rodata段,例如.rodata.Cpu1_Main.*, 在Cpu1_Main.c中的常量会放在这个段内。

 

group (ordered, align = 4, run_addr=mem:pflsx)

      {

        select ".rodata.Ifx_Ssw_Tcx.*";

        select ".rodata.Cpux_Main.*";

}

 

   

 

但是如果是其他.c文件(例如demo.c),则会放在默认的rodata段中,这个是由Link文件中下面语句决定的:

 

#    if LCF_DEFAULT_HOST == LCF_CPU0

    group (ordered, align = 4, run_addr=mem:pfls0)

#    endif

    {

      select ".rodata.*";

      select ".rodata.farConst.cpu0.32bit";

      select ".rodata.farConst.cpu0.16bit";

      select ".rodata.farConst.cpu0.8bit";

    }

    }

 

   

 

1.3 (d)LMU

LMU分为各个CPU私有的dLMU和共用的LMU两部分,在MCAL中的Link文件中只是定义了LMU的几个段,在工程中并没有用到这个区域,关于怎么把变量放到LMU中,请看第2.2和2.3章。

 

 

1.4 PSRAM

每个CPU都有自己的PSRAM区域,这个区域可以运行程序,也可以存放数据,在Link中只是定义了几个段,在工程中并没有用到这个区域,关于怎么在这个区域运行程序,请看第2.4章。

 

1.5 UCB

UCB是配置MCU参数的一块区域,关于怎么在程序中配置UCB区域,请看第2.7章。

 


 

 

2.        代码和变量定位

2.1   把变量放在DSRAM

2.1.1 把变量放在固定位置:

如果需要把变量放在固定位置,则需要在Link文件中,首先定义一个data段,从0x7001000开始,一个bss段,从0x70004000开始。

 

/*Far Data / Far Const Sections, selectable with   patterns and user defined sections*/

  section_layout :vtc:linear

  {

    /*Far Data Sections, selectable with patterns and   user defined sections*/

    group

    {

        …

     

        group (ordered, attributes=rw, run_addr=0x70001000)

        {

          select ".bss.user_test_bss";

        }

       

        group (ordered, attributes=rw, run_addr=0x70004000)

        {

          select ".data.user_test_data";

        }

}

}

 

   

 

在程序中定义如下,则run_cnt1和run_cnt2, 则run_cnt1就会放在0x70001000, run_cnt2放在0x70004000

 

 

#pragma   section farbss "user_test_bss"

volatile uint32 run_cnt1;

#pragma   section farbss restore

 

#pragma   section fardata "user_test_data"

volatile uint32 run_cnt2 =   0x1234;

#pragma section fardata restore

 

   

 

 

 

编译后,查看map文件,可以发现定义的变量放在预期的位置。

 

2.1.2 把变量放在其它DSRAM

默认的全局变量都是放在DSRAM0中,如果需要使用其他DSRAM,则可以把变量放在Link文件已经定义好一些段中:

 

/* Initialized Data */

          select "*InitData.Cpux.8bit";

          select "*InitData.Cpux.16bit";

          select "*InitData.Cpux.32bit";

   

          /* UnInitialized Data */

          select "*ClearedData.Cpux.8bit";

          select "*ClearedData.Cpux.16bit";

          select "*ClearedData.Cpux.32bit";

 

   

 

例如,如果想把变量放在DSRAM1中,则在程序中可以这么写:

 

#pragma   section farbss "ClearedData.Cpu1.32bit"

volatile uint32 run_cnt1_dsram1;

#pragma   section farbss restore

 

#pragma   section fardata "InitData.Cpu1.32bit"

volatile uint32   run_cnt2_dsram1 = 0x1234;

#pragma section fardata restore

 

   

 

查看map,发现变量放在PSRAM1的预期:

 

2.2   把变量放在DLMU

在Link文件已经定义了各个CPU所属的DLMU的段,如下:

 

 

group (ordered, attributes=rw, run_addr = mem:cpux_dlmu)

        {

          select ".data.*.lmudata_cpux";

          select ".bss.*.lmubss_cpux";

        }      

 

   

 

如果想把变量放在DLMU2中,则可以如下面这样写:

 

 

#pragma   section farbss "test.lmubss_cpu2"

volatile uint32 run_cnt1_dlmu2;

#pragma   section farbss restore

 

#pragma   section fardata "test.lmudata_cpu2"

volatile uint32   run_cnt2_dlmu2 = 0x1234;

#pragma section fardata restore

 

   

 

查看map文件,发现这两个变量已经放在DLMU2中:

 


 

 

 

2.3   把变量放在LMU

在Link文件已经定义了LMU的段,如下:

 

group (ordered, attributes=rw, run_addr=mem:lmuram/cached)

        {

          select ".data.*.lmu_data";

          select ".bss.*.lmu_bss";

}

 

group (ordered, attributes=rw, run_addr = mem:lmuram/not_cached)

        {

          /* Initialized Data */

          select "*InitData.LmuNC.8bit";

          select "*InitData.LmuNC.16bit";

          select "*InitData.LmuNC.32bit";

     

          /* UnInitialized Data */

          select "*ClearedData.LmuNC.8bit";

          select "*ClearedData.LmuNC.16bit";

          select "*ClearedData.LmuNC.32bit";

   

        }

 

   

 

如果想把变量放在LMU (不用CACHE)中,则可以如下面这样写:

 

#pragma   section farbss "ClearedData.LmuNC.32bit"

volatile uint32 run_cnt1_lmu;

#pragma   section farbss restore

 

#pragma   section fardata "InitData.LmuNC.32bit"

volatile uint32 run_cnt2_lmu   = 0x1234;

#pragma section fardata restore

 

   

 

查看map文件,发现变量已经放在LMU区域:

 

2.4   把程序放在PSRAM中运行

有时候需要把程序放到RAM去运行,例如在擦写Flash的时候,这个时候可以直接把代码放在 ”FLSLOADERRAMCODE” 段,也可以自己在PSRAM中再定义一个段,如下所示:

 

 

section_layout   :vtc:linear

    {

        group   MY_RAM_CODE (ordered, attributes=rwx, copy, run_addr=mem:psram0)

        {

           select ".text.my_ram_code";

        }

    }

 

   

 

在程序中定义如下, 这样RunTest()这个函数就会在PSRAM0中去运行:

 

#pragma   section code "my_ram_code"

void RunTest(void)

{

    run_cnt1++;

    run_cnt2++;

    run_cnt1_dsram1++;

    run_cnt2_dsram1++;

    run_cnt1_dlmu2++;

    run_cnt2_dlmu2++;

    run_cnt1_lmu++;

    run_cnt2_lmu++;

}

#pragma section code restore

 

   

 

查看map文件,可以看到RunTest()放在PSRAM0中:

 

 

2.5   把程序放在PFLASH中指定位置

如果需要把程序放在指定位置执行,则可以在Link文件中首先定义一个程序段,例如把程序放在0x80041000开始的地址,则可以如下定义:

 

/* user define code section */

      group  user_test_code (ordered, run_addr=0x80041000)        

{

        select "(.text.user_test_code*)";

      }

 

   

 

在程序中定义如下,则AddTest()就会放在0x80041000地址:

 

 

#pragma   section code "user_test_code"

uint32 AddTest(uint32 a, uint32 b)

{

    uint32 c = a+b;

    return c;

}

#pragma section code restore

 

   

 

查看map文件,发现AddTest()已经放在预期位置。

 

2.6   把常量放在PFLASH中指定位置

如果需要把常量放在指定位置,则可以在Link文件中首先定义一个常量段,例如把常量放在0x80040000开始的地址,则可以如下定义:

 

/* user define const section */

group  user_test_const (ordered, run_addr=0x80040000) 

      {

        select ".rodata.user_test_const" ;

      }

 

   

在程序中定义如下,则user_test_const就会放在0x80040000地址:

 

#pragma   section farrom "user_test_const"

volatile const uint32 user_test_const[4]   = {0x12345678, 0x87654321, 0xAABBCCDD, 0xFFEEDDCC};

#pragma section farrom restore

 

   

 

查看map文件,发现user_test_const已经放在预期位置.

 

2.7   用数组设置UCB区域

操作UCB可以使用调试器,但是一般在工厂烧录时,需要把程序和UCB一起烧录进去,这个时候就需要把UCB的数据放在程序中。下面以使能HSM为例介绍在程序中设置UCB的流程。

首先需要在Link文件中定义需要操作UCB段,例如使能HSM,需要操作UCB_HSMCOTP0_ORIG

 

/*Fixed memory Allocations for HSM Configuration*/

    group (ordered)

    {

        group  hsmxcotp0_orig (run_addr=mem:ucb[0x2800])

        {

           select ".rodata.hsmcotp0_orig";

        }

    }

 

   

 

在程序定义如下,则把编译后hex中的UCB部分烧录进去,MCU的HSM功能就能激活(具体请查看芯片用户手册“AURIX? TC3xx User Manual “

 

 

#pragma   section farrom "hsmcotp0_orig"

const Ifx_HsmCotp_Config hsmcotp0_orig =

{

     0x00000000, /* sf_proconusr, offset: 0x000 */

     0x00000001, /* boot_sector, bit[7:0]: SEL0, bit[15:8]: SEL1,   bit[23:16]: SEL2, bit[31:24]: SEL3 */

     0x00000000, /* hsm_exclusive0, offset: 0x008 */

     0x00000000, /* hsm_exclusive1, offset: 0x00C */

    0x00000000, /* hsm_otp0, offset: 0x010*/

     0x00000000, /* hsm_otp1, offset: 0x014 */

     0x00000001, /* sp_proconhsmcfg, bit0: HSM boot enable, offset:   0x018 */

     {

           0x00000000,   /* 0x01C, Reserved */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x020: Reserved (0x020 - 0x02F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x030: Reserved (0x030 - 0x03F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x040: Reserved (0x040 - 0x04F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x050: Reserved (0x050 - 0x05F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x060: Reserved (0x060 - 0x06F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x070: Reserved (0x070 - 0x07F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x080: Reserved (0x080 - 0x08F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x090: Reserved (0x090 - 0x09F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x0A0: Reserved (0x0A0 - 0x0AF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x0B0: Reserved (0x0B0 - 0x0BF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x0C0: Reserved (0x0C0 - 0x0CF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x0D0: Reserved (0x0D0 - 0x0DF) */

           0x00000000, 0x00000000,   0x00000000, 0x00000000, /**< rief 0x0E0: Reserved (0x0E0 - 0x0EF) */

           0x00000000, 0x00000000, 0x00000000, 0x00000000, /**< rief 0x0F0: Reserved (0x0F0 - 0x0FF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x100: Reserved (0x100 - 0x100) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x110: Reserved (0x110 - 0x01F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x120: Reserved (0x120 - 0x02F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x130: Reserved (0x130 - 0x03F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x140: Reserved (0x140 - 0x04F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x150: Reserved (0x150 - 0x05F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x160: Reserved (0x160 - 0x06F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x170: Reserved (0x170 - 0x07F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x180: Reserved (0x180 - 0x08F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x190: Reserved (0x190 - 0x09F) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x1A0: Reserved (0x1A0 - 0x0AF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x1B0: Reserved (0x1B0 - 0x0BF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x1C0: Reserved (0x1C0 - 0x0CF) */

           0x00000000,   0x00000000, 0x00000000, 0x00000000, /**<   rief 0x1D0: Reserved (0x1D0 - 0x0DF) */

           0x00000000, 0x00000000,   0x00000000, 0x00000000, /**< rief 0x1E0: Reserved (0x1E0 - 0x0EF) */

     },

     0x43211234,    /**<   rief 0x1F0: .confirmation: 32-bit CODE, (always same)*/

     {

           0x00000000,   /* 0x004, Reserved */

           0x00000000,   /* 0x008, Reserved */

           0x00000000,   /* 0x00C, Reserved */

     }

};

 

   

 

查看map文件,发现HSM UCB区域部分已经有了数据:

 

需要确保Flash中已经下载了HSM代码,再激活HSM,否则芯片将被锁死,因此为了安全,附带的例程中这部分HSM的配置是被注释掉的。

 

摘要:本文长达5000字,适合专业级商用开发项目、业余爱好者,入门者,建议收藏。内容包括:

1. AURIX? TC3xx通过Mcal进行底层开发时,TASKING Link文件解析以及代码变量定位方法;

2. AURIX? 开发套件大全。

 [CQQ(ASGS1]要标黄吗


0 点赞
4333 次查看
6 评论