This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F280033: 对于具备二次Bootloader的项目,如何将库文件分配到指定扇区

Part Number: TMS320F280033
Other Parts Discussed in Thread: SFRA

现在开发的280033项目Flash分配如下图:

Bank0

Sector 15

App1

24K * 16 bit

48KBytes

Bank1

Sector 7

App2

24K * 16 bit

48KBytes

Sector 14

Sector 6

Sector 13

Sector 5

Sector 12

Sector 4

Sector 11

Sector 3

Sector 10

Sector 2

Sector 9

Boot,16KBytes

Sector 1

Algorithm Library

算法库

Sector 8

Sector 0

程序上电时从Boot区运行,若App2区域内存在有效代码,则擦除App1区域并将App2区域代码复制到App1区域,然后擦除App2区域,跳转到App1运行。

程序(boot或App1)运行时,若遇到升级Boot程序命令则直接升级Boot区,若遇到升级App程序命令则,将收到的程序代码写入App2区域后重启。

现在有如下需求:

将App用到的Ti提供的一些库文件(包括但不限于FlashAPI,SFRA、DCL)固定存放到算法库区域(Bank1:Sector0~Bank1~Sector2),

一方面boot和app共用的FlashAPI代码只需要在FLASH中存储一份,可缩减代码空间

另一方面,可以节省App1和App2的占用空间,尽量为app逻辑代码提供空间

现在包括2个程序:Boot程序,App程序,

请问,对于上表提到的算法库,是否可以新建一个CCS工程,仅提供算法区(Bank1:Sector0~Bank1~Sector2)相关库文件的加载功能?

如果不行,有没有好的建议能帮忙解决上述的需求呢?

  • MEMORY
    {
       BEGIN            : origin = 0x00080000, length = 0x00000002
       BOOT_RSVD        : origin = 0x00000002, length = 0x00000126
    
       RAMM0            : origin = 0x00000128, length = 0x000002D8
       RAMM1            : origin = 0x00000400, length = 0x000003F8
       // RAMM1_RSVD       : origin = 0x000007F8, length = 0x00000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
    
       // RAMLS0           : origin = 0x00008000, length = 0x00000800
       // RAMLS1           : origin = 0x00008800, length = 0x00000800
       // RAMLS2           : origin = 0x00009000, length = 0x00000800
       // RAMLS3           : origin = 0x00009800, length = 0x00000800
       // RAMLS4           : origin = 0x0000A000, length = 0x00000800
       // RAMLS5           : origin = 0x0000A800, length = 0x00000800
    
       // RAMLS6           : origin = 0x0000B000, length = 0x00000800
       // RAMLS7           : origin = 0x0000B800, length = 0x00000800
    
       // RAMGS0           : origin = 0x0000C000, length = 0x00001000
       // RAMGS1           : origin = 0x0000D000, length = 0x00001000
       // RAMGS2           : origin = 0x0000E000, length = 0x00001000
       // RAMGS3           : origin = 0x0000F000, length = 0x00000FF8
       // // RAMGS3_RSVD      : origin = 0x0000FFF8, length = 0x00000008 /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
    
       RAML_Data        : origin = 0x00008000, length = 0x00002000
       RAML_Prog        : origin = 0x0000A000, length = 0x00002000
       RAMG_All         : origin = 0x0000C000, length = 0x00003FF8
    
       BOOTROM          : origin = 0x003F8000, length = 0x00007FC0
       SECURE_ROM       : origin = 0x003F2000, length = 0x00006000
    
       RESET            : origin = 0x003FFFC0, length = 0x00000002
       /* Flash sectors */
       /* BANK 0 */
       BEGIN_BOOT        : origin = 0x088000, length = 0x000008 ,fill = 0xFFFF/* codestart         */
       BOOT_STARTFLAG    : origin = 0x088008, length = 0x000010	,fill = 0xFFFF/* bootloader flag   */
       BOOT_VERSION      : origin = 0x088018, length = 0x000008	,fill = 0xFFFF/* bootloader version*/
       BOOT_FLASH        : origin = 0x088020, length = 0x001FD0	,fill = 0xFFFF/* bootloader code   */
       BOOT_DATETIME     : origin = 0x089FF0, length = 0x000008	,fill = 0xFFFF/* bootloader compile datetime   */
       BOOT_FINISHFLAG   : origin = 0x089FF8, length = 0x000008	,fill = 0xFFFF/* bootloader finish flag   */
    
       APP1_BEGIN        : origin = 0x08A000, length = 0x000008 //,fill = 0xFFFF/* codestart         */
       APP1_STARTFLAG    : origin = 0x08A008, length = 0x000010	//,fill = 0xFFFF/* app1 flag   */
       APP1_VERSION      : origin = 0x08A018, length = 0x000008	//,fill = 0xFFFF/* app1 version*/
       APP1_FLASH        : origin = 0x08A020, length = 0x005FD0	//,fill = 0xFFFF/* app1 code */
       APP1_DATETIME     : origin = 0x08FFF0, length = 0x000008	//,fill = 0xFFFF/* app1 compile datetime */
       APP1_FINISHFLAG   : origin = 0x08FFF8, length = 0x000008	//,fill = 0xFFFF/* app1 finish flag   */
       /* BANK 1 */
       APP_ALGORITHM     : origin = 0x090000, length = 0x002000 //,fill = 0xFFFF/* share algorithm code      */
       APP2_BEGIN        : origin = 0x092000, length = 0x000008 //,fill = 0xFFFF/* codestart         */
       APP2_STARTFLAG    : origin = 0x092008, length = 0x000010	//,fill = 0xFFFF/* app2 flag   */
       APP2_VERSION      : origin = 0x092018, length = 0x000008	//,fill = 0xFFFF/* app2 version*/
       APP2_FLASH        : origin = 0x092020, length = 0x005FD0	//,fill = 0xFFFF/* app2 code */
       APP2_DATETIME     : origin = 0x097FF0, length = 0x000008	//,fill = 0xFFFF/* app2 compile datetime */
       APP2_FINISHFLAG   : origin = 0x097FF8, length = 0x000008	//,fill = 0xFFFF/* app2 finish flag   */
    
    // FLASH_BANK0_SEC15_RSVD     : origin = 0x0AFFF0, length = 0x000010  /* Reserve and do not use for code as per the errata advisory "Memory: Prefetching Beyond Valid Memory" */
    
    }
    
    
    
    SECTIONS
    {
       codestart        : > BEGIN_BOOT, ALIGN(8)
       .text            : > BOOT_FLASH, ALIGN(8)
       .cinit           : > BOOT_FLASH, ALIGN(8)
       .switch          : > BOOT_FLASH, ALIGN(8)
       .reset           : > RESET,                  TYPE = DSECT /* not used, */
    
       .stack           : > RAMM0 | RAMM1
    
       .init_array      : > BOOT_FLASH,  ALIGN(8)
       .bss             : > RAMG_All
       .bss:output      : > RAMG_All
       .bss:cio         : > RAMG_All
       .data            : > RAMG_All
       .sysmem          : > RAMG_All
       .const           : > BOOT_FLASH,  ALIGN(8)
    
       //  /*  Allocate IQ math areas: */
       // IQmath           : > FLASH_BANK0_SEC1, ALIGN(8)
       // IQmathTables     : > FLASH_BANK0_SEC2, ALIGN(8)
    
       // flashApi       :{ -l FAPI_F28003x.lib } > APP_ALGORITHM
         GROUP
       {
           .TI.ramfunc
           {
    //           -l sfra_f64_tmu_eabi.lib
           }
           ramfuncs
           isrcodefuncs
          dclfuncs
       } LOAD = BOOT_FLASH,
             RUN = RAML_Prog,
             LOAD_START(RamfuncsLoadStart),
             LOAD_SIZE(RamfuncsLoadSize),
             LOAD_END(RamfuncsLoadEnd),
             RUN_START(RamfuncsRunStart),
             RUN_SIZE(RamfuncsRunSize),
             RUN_END(RamfuncsRunEnd),
             ALIGN(8)
    
         GROUP
       {
           algorithmfuncs
           {
    //           -l sfra_f64_tmu_eabi.lib
             -l FAPI_F28003x_EABI_v1.58.10.lib
    //         -l rts2800_fpu32_eabi.lib
           }
       } LOAD = APP_ALGORITHM,
             RUN = RAML_Prog,
             LOAD_START(LibfuncsLoadStart),
             LOAD_SIZE(LibfuncsLoadSize),
             LOAD_END(LibfuncsLoadEnd),
             RUN_START(LibfuncsRunStart),
             RUN_SIZE(LibfuncsRunSize),
             RUN_END(LibfuncsRunEnd),
             ALIGN(8)
    
       // SFRA_F32_Data    : > RAMG_All, ALIGN = 64
       // SFRA_Data		  : > RAMG_All, ALIGN = 64
    
       // FPUmathTables    : > APP1_FLASH
    
       boot_startflag    : > BOOT_STARTFLAG,     ALIGN(8)
       boot_version      : > BOOT_VERSION,       ALIGN(8)
       boot_datetime     : > BOOT_DATETIME,      ALIGN(8)
       boot_finishflag   : > BOOT_FINISHFLAG,    ALIGN(8)
    
       app1_startflag    : > APP1_STARTFLAG,     ALIGN(8)
       app1_version      : > APP1_VERSION,       ALIGN(8)
       app1_datetime     : > APP1_DATETIME,      ALIGN(8)
       app1_finishflag   : > APP1_FINISHFLAG,    ALIGN(8)
    
       app2_startflag    : > APP2_STARTFLAG,     ALIGN(8)
       app2_version      : > APP2_VERSION,       ALIGN(8)
       app2_datetime     : > APP2_DATETIME,      ALIGN(8)
       app2_finishflag   : > APP2_FINISHFLAG,    ALIGN(8)
    
    }
    /*
    //===========================================================================
    // End of file.
    //===========================================================================
    */

    当前Boot程序项目利用上面的CMD文件,可以将FAPI_F28003x_EABI_v1.58.10.lib放在指定位置,内存分配如下图所示:

    现在有2个问题:

    第一、如果尝试将rts2800_fpu32_eabi.lib也放入APP_ALGORITHM区域,编译不通过,有如下错误及警告:

    warning #10278-D: LOAD placement specified for section ".text:decompress:none:rts2800_fpu32_eabi.lib<copy_decompress_none.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section ".text:rts2800_fpu32_eabi.lib<memcpy.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section "__TI___TI_zero_init_specialization:rts2800_fpu32_eabi.lib<copy_zero_init.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section ".text:decompress:ZI:__TI_zero_init_nomemset:rts2800_fpu32_eabi.lib<copy_zero_init.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section ".text:decompress:ZI:rts2800_fpu32_eabi.lib<copy_zero_init.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section ".text:rts2800_fpu32_eabi.lib<memset.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    warning #10278-D: LOAD placement specified for section ".text:decompress:lzss:rts2800_fpu32_eabi.lib<copy_decompress_lzss.c.obj>". This section contains decompression routines required for linker generated copy tables and C/C++ auto-initialization. Must ensure that this section is copied to run address before the C/C++ boot code is executed or is placed with single allocation specifier (ex. "> MEMORY").
    
    undefined first referenced
    symbol in file
    --------- ----------------
    __TI_SYSMEM_SIZE C:/ti/ccs1110/ccs/tools/compiler/ti-cgt-c2000_22.6.0.LTS/lib/rts2800_fpu32_eabi.lib<memory.c.obj>
    请问如何处理?

    第二、Boot项目已经将FAPI_F28003x_EABI_v1.58.10.lib放在指定扇区,App项目中如何调用此扇区中的函数呢?似乎需要另外的包含函数地址的lib文件才可以。但是如何生成这个symbols_lib文件呢?

  • 我咨询相关工程师后回复你

  • 好的。

    之前用28002x的时候,因为Flash API已经嵌入在Boot ROM中,所以大大节省了代码占用Flash空间。

    但是现在28003x,只提供软件Flash API,所以不得不考虑压缩代码尺寸了。

  • 阅读文档 ZHCABQ0后受到启发,待我这边测试后有结果了再来更新。

  • 当前的情况:

    1.可以将Boot项目已经将FAPI_F28003x_EABI_v1.58.10.lib放在指定扇区

    2.根据文档 ZHCABQ0 和  ZHCABP6,可以生成SymbolLibrary.lib(仅包含函数名及其地址)

    3.可以在App项目中引用SymbolLibrary.lib,并调用调用函数

    现在的问题是,不能将lib中的函数Copy到RAM运行

    在App项目中使用CODE_SECTION指定Flash_API位置,在CMD中指定对应Section,在main中memcpy拷贝代码,结果发现调用的函数仍然运行于Flash中。

    以下示例完全参考ZHCABP6 文档,基于F28002x:

    其中F28002x_Project1定义函数test,存放位置如下(位于文件CPU1_RAM\F28002x_Project1_linkInfo.xml)

          <logical_group id="lg-10" display="no" color="cyan">
             <name>Project1_Function</name>
             <load_address>0x8e0f8</load_address>
             <run_address>0x8e0f8</run_address>
             <size>0x8</size>
             <contents>
                <object_component_ref idref="oc-d8"/>
             </contents>
          </logical_group>

    利用Strawberry和cgxml工具生成的F28002x_Project1_out_test_tmp.asm文件内容如下:

    asm文件仅定义了函数名及其位置

    ; This file is *auto-generated*. Do not edit. Mods risk being overwritten 
    ; Assembly file : F28002x_Project1_out_test_tmp.asm
    
    	 .global	test
    test	 .set	0x8e0f8

    F28002x_Project2项目调用test函数,可以正常运行。

    尝试将test函数copy到RAM运行一直不成功。

    以下是一种尝试:

    CMD文件:

       .TI.apifunc : LOAD = FLASH_BANK0_SEC1415,
                      RUN = RAMLS7,
                      LOAD_START(ApifuncsLoadStart),
                      LOAD_SIZE(ApifuncsLoadSize),
                      LOAD_END(ApifuncsLoadEnd),
                      RUN_START(ApifuncsRunStart),
                      RUN_SIZE(ApifuncsRunSize),
                      RUN_END(ApifuncsRunEnd),
                      ALIGN(8)

    main.c文件

    #include "driverlib.h"
    #include "device.h"
    #include "test.h"
    
    extern uint16_t ApifuncsLoadStart;
    extern uint16_t ApifuncsLoadEnd;
    extern uint16_t ApifuncsRunStart;
    
    
    void MemCopy(uint16_t *SourceAddr, uint16_t* SourceEndAddr, uint16_t* DestAddr);
    
    
    #pragma CODE_SECTION(test, ".TI.apifunc");
    
    int R_Test1,R_Test2,R_Test3;
    
    void main(void)
    {
        // ApifuncsLoadStart   = (uint16_t*)0x0008E002;
        // ApifuncsLoadEnd     = (uint16_t*)0x0008E100;
        // ApifuncsRunStart    = (uint16_t*)0x0000B800;
    
        MemCopy(&ApifuncsLoadStart, &ApifuncsLoadEnd, &ApifuncsRunStart);
    
        R_Test1 = 123;
        R_Test2 = 456;
    
        for(;;)
        {
            R_Test3 = test(R_Test1,R_Test2);
        }
    }
    
    void MemCopy(uint16_t *SourceAddr, uint16_t* SourceEndAddr, uint16_t* DestAddr)
    {
        while(SourceAddr < SourceEndAddr)
        {
           *DestAddr++ = *SourceAddr++;
        }
        return;
    }
    

    Debug的时候,MemCopy的参数都指向RAM区

    调用test函数时,PC仍位于Flash中:

    请问怎样配置CMD文件才能将test函数拷贝到RAM运行?

  • 好的感谢分享!我也和相关的工程师跟进一下

  • 根据这篇帖子的说法,不能将ROM中的Flash API代码拷贝到RAM运行

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/402181/copy-flash-api-from-rom-to-ram

    但是这很令人费解

    BOOT ROM中的SCI Boot等代码也会擦写FLASH,请问ROM中的这些代码擦写FLASH的时候也会将FLASH API拷贝到RAM中运行吗?

    再者,我之前F280025项目的bootloader项目中使用F28002xCPU1_BootROM_Symbols.lib库来调用ROM中的Flash API,也能对Flash进行擦写编程,只是在线debug的时候会出现异常。

    这里重新读了FLASH_API使用手册:

    里边提到,只要在执行FLASH擦除/编程的过程中只要不对这块(Bank)正在擦除/编程的FALSH进行读数/取指操作,就不会有问题。只要满足这个条件,即便在擦除/编程的过程中,遇到中断也没关系。

    具体可参考

    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1206817/tms320f280049-flash-api-user-application-from-ram

  • 刚刚查看了BoootRom中SCI_Boot代码

    //
    // SCI_Boot - This module is the main SCI boot routine.
    //            It will load code via the SCI-A port.
    //
    //            It will return a entry point address back
    //            to the system initialization routine which in turn calls
    //            the ExitBoot routine.
    //
    uint32_t SCI_Boot(uint32_t bootMode)
    {
        uint32_t entryAddress;
        uint16_t byteData;
    
        //
        // CPU1 Patch/Escape Point 13
        //
        entryAddress = CPU1BROM_TI_OTP_ESCAPE_POINT_13;
        if((entryAddress != 0xFFFFFFFFUL) &&
           (entryAddress != 0x00000000UL))
        {
            //
            // If OTP is programmed, then call OTP patch function
            //
            ((void (*)(void))entryAddress)();
        }
    
        //
        // Check if SCI is enabled on device or not
        //
       if(SysCtl_isPeripheralPresent(SYSCTL_PERIPH_PRESENT_SCIA) == false)
        {
            return(FLASH_ENTRY_POINT);
        }
    
        //
        // Assign GetWordData to the SCI-A version of the
        // function. GetWordData is a pointer to a function.
        //
        GetWordData = SCIA_GetWordData;
    
        //
        // Initialize the SCI-A port for communications
        // with the host.
        //
    
        //
        // Enable the SCI-A clocks
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_SCIA);
        SysCtl_setLowSpeedClock(SYSCTL_LSPCLK_PRESCALE_4);
    
        EALLOW;
        HWREGH(SCIA_BASE + SCI_O_FFTX) = SCI_FFTX_SCIRST;
    
        //
        // 1 stop bit, No parity, 8-bit character
        // No loopback
        //
        HWREGH(SCIA_BASE + SCI_O_CCR) = (SCI_CONFIG_WLEN_8 | SCI_CONFIG_STOP_ONE);
        SCI_setParityMode(SCIA_BASE,SCI_CONFIG_PAR_NONE);
    
        //
        // Enable TX, RX, Use internal SCICLK
        //
        HWREGH(SCIA_BASE + SCI_O_CTL1) = (SCI_CTL1_TXENA | SCI_CTL1_RXENA);
    
        //
        // Disable RxErr, Sleep, TX Wake,
        // Disable Rx Interrupt, Tx Interrupt
        //
        HWREGB(SCIA_BASE + SCI_O_CTL2) = 0x0U;
    
        //
        // Relinquish SCI-A from reset and enable TX/RX
        //
        SCI_enableModule(SCIA_BASE);
    
        EDIS;
    
        //
        // GPIO INIT
        //
        SCIBOOT_configure_gpio(bootMode);
    
        //
        // CPU1 Patch/Escape Point 13
        //
        entryAddress = CPU1BROM_TI_OTP_ESCAPE_POINT_13;
        if((entryAddress != 0xFFFFFFFFUL) &&
           (entryAddress != 0x00000000UL))
        {
            //
            // If OTP is programmed, then call OTP patch function
            //
            ((void (*)(void))entryAddress)();
        }
    
        //
        // Perform autobaud lock with the host.
        // Note that if autobaud never occurs
        // the program will hang in this routine as there
        // is no timeout mechanism included.
        //
        SCI_lockAutobaud(SCIA_BASE);
    
        //
        // Read data
        //
        byteData = SCI_readCharBlockingNonFIFO(SCIA_BASE);
    
        //
        // Configure TX pin after autobaud lock
        // (Performed here to allow SCI to double as wait boot)
        //
        GPIO_setPadConfig(SCI_gpioTx,GPIO_PIN_TYPE_PULLUP);
        GPIO_setPinConfig(SCI_gpioTxPinConfig);
    
        //
        // Write data to request key
        //
        SCI_writeCharNonBlocking(SCIA_BASE,byteData);
    
        //
        // If the KeyValue was invalid, abort the load
        // and return the flash entry point.
        //
        if(SCIA_GetWordData() != BROM_EIGHT_BIT_HEADER)
        {
            return FLASH_ENTRY_POINT;
        }
    
        ReadReservedFn();
    
        entryAddress = GetLongData();
    
        CopyData();
    
        return entryAddress;
    }

    CopyData函数代码

    uint16fptr GetWordData; // GetWordData is a pointer to the function that
                            // interfaces to the peripheral. Each loader assigns
                            // this pointer to it's particular GetWordData function.
    
    //
    // CopyData - This routine copies multiple blocks of data from the host
    //            to the specified RAM locations.  There is no error
    //            checking on any of the destination addresses.
    //            That is because it is assumed all addresses and block size
    //            values are correct.
    //
    //            Multiple blocks of data are copied until a block
    //            size of 00 00 is encountered.
    //
    void CopyData(void)
    {
        struct HEADER {
            uint32_t DestAddr;        
            uint16_t BlockSize;
        } BlockHeader;
    
        uint16_t wordData;
        uint16_t i;
    
        //
        // Get the size in words of the first block
        //
        BlockHeader.BlockSize = (*GetWordData)();
    
        //
        // While the block size is > 0 copy the data
        // to the DestAddr.  There is no error checking
        // as it is assumed the DestAddr is a valid
        // memory location
        //
        while(BlockHeader.BlockSize != (uint16_t)0x0000U)
        {
            BlockHeader.DestAddr = GetLongData();
    
            for(i = 1; i <= BlockHeader.BlockSize; i++)
            {
                wordData = (*GetWordData)();
                *(uint16_t *)BlockHeader.DestAddr = wordData;
                BlockHeader.DestAddr+=1U;
            }
    
            //
            // Get the size of the next block
            //
            BlockHeader.BlockSize = (*GetWordData)();
        }
    
        return;
    }

    可以看到,CopyData中并没有调用FLASH API,而是直接往指针处地址写值:

    *(uint16_t *)BlockHeader.DestAddr = wordData;

    也没有看到任何地方擦除Flash的代码

    CopyData函数顶端的注释说,此函数将接收的数据块拷贝到RAM中,而实际上通过SCI_Boot下载程序时,上位机发送下来的地址都是位于FLASH空间,而不是RAM空间。

    bootrom中可以直接这样写FLASH吗?

  • bootrom版的FLASH API是直接操作FLASH的,无需搬运到RAM中。

    对于有bootrom FLASH API的器件,bootrom FLASH API 与 在代码中调用、执行时搬运到RAM的RAM版FLASH API lib之间是有取舍的,

    bootrom版:不占用代码空间,但是运行速度慢;

    RAM版:占用代码空间,但是搬运到RAM中执行速度快;并且只能搬运到RAM中运行;代码在执行时,不能对同一bank的其它sector进行操作。

  • 非常感谢。

    关于在Project2中调用Project1中放置于指定位置的函数,不能运行于RAM的问题

    目前临时的解决办法如下:

    以Project1和Project2为例

    在Project1中,将test放置在指定FLASH位置,并装载到指定RAM中运行

    MEMORY
    {
       BEGIN           	: origin = 0x08D000, length = 0x000002
       BOOT_RSVD		: origin = 0x00000002, length = 0x00000126
       RAMM0           	: origin = 0x00000128, length = 0x000002D8
       RAMM1            : origin = 0x00000400, length = 0x000003F8     /* on-chip RAM block M1 */
    
       RAMLS7           : origin = 0x0000B800, length = 0x00000800
       RAMGS0           : origin = 0x0000C000, length = 0x000007F8
    
       BOOTROM          : origin = 0x003F0000, length = 0x00008000
       BOOTROM_EXT      : origin = 0x003F8000, length = 0x00007FC0
       RESET            : origin = 0x003FFFC0, length = 0x00000002
    
       FLASH_BANK0_SEC13   : origin = 0x08D002, length = 0x000FFE	/* on-chip Flash */
       FLASH_BANK0_SEC1415 : origin = 0x08E000, length = 0x002000	/* on-chip Flash */
    }
    
    
    SECTIONS
    {
       codestart        : > BEGIN, ALIGN(8)
       .text            : > FLASH_BANK0_SEC13,   ALIGN(8)
       .cinit           : > FLASH_BANK0_SEC13,  ALIGN(8)
       .switch          : > FLASH_BANK0_SEC13,  ALIGN(8)
       .reset           : > RESET,                  TYPE = DSECT /* not used, */
    
       .stack           : > RAMM1
    
       .init_array      : > FLASH_BANK0_SEC13,  ALIGN(8)
       .bss             : > RAMLS7
       .bss:output      : > RAMLS7
       .bss:cio         : > RAMLS7
       .const           : > FLASH_BANK0_SEC13,  ALIGN(8)
       .data            : > RAMLS7
       .sysmem          : > RAMLS7
    
    
       Project1_Function
          {
             -l test.obj(.text)
          }
           load =  FLASH_BANK0_SEC1415,
           run  = RAMGS0,
           table(BINIT),
           ALIGN(8)
       .binit         : > FLASH_BANK0_SEC1415
    }
    
    

    其中table(BINIT)可以省去在main中调用memcpy的代码。

    Project1的linkinfo.xml中,test的地址(load和run)以及尺寸如下

          <object_component id="oc-d9">
             <name>.text:test</name>
             <load_address>0x8e000</load_address>
             <run_address>0xc000</run_address>
             <size>0x8</size>
             <input_file_ref idref="fl-6"/>
          </object_component>

    生成仅包含函数名和地址的F28002x_FlashAPI_SymbolLibrary.lib,该lib文件中仅包含1个test.obj

    其中 F28002x_Project1_out_test_tmp.asm 文件内容如下:

    从上图可知,F28002x_FlashAPI_SymbolLibrary.lib文件中将test函数定位到0xc000,即RAMGS0所在的RAM区域

    F28002x_FlashAPI_SymbolLibrary.lib文件加入Project2中。

    在Project2中,手动指定memcpy的地址和范围,将

    0x08E000(FLASH_BANK0_SEC1415)的代码拷贝到0x0000C000(RAMGS0)的位置。

    #include "driverlib.h"
    #include "device.h"
    #include "test.h"
    
    uint16_t* ApifuncsLoadStart;
    uint16_t* ApifuncsLoadEnd;
    uint16_t* ApifuncsRunStart;
    
    
    void MemCopy(uint16_t *SourceAddr, uint16_t* SourceEndAddr, uint16_t* DestAddr);
    
    
    #pragma CODE_SECTION(test, ".TI.apifunc");
    
    int R_Test1,R_Test2,R_Test3;
    
    void main(void)
    {
        ApifuncsLoadStart   = (uint16_t*)0x0008E000;
        ApifuncsLoadEnd     = (uint16_t*)0x0008E100;
        ApifuncsRunStart    = (uint16_t*)0x0000C000;
    
        MemCopy(ApifuncsLoadStart, ApifuncsLoadEnd, ApifuncsRunStart);
    
        R_Test1 = 123;
        R_Test2 = 456;
    
        for(;;)
        {
            R_Test3 = test(R_Test1,R_Test2);
        }
    }
    
    void MemCopy(uint16_t *SourceAddr, uint16_t* SourceEndAddr, uint16_t* DestAddr)
    {
        while(SourceAddr < SourceEndAddr)
        {
           *DestAddr++ = *SourceAddr++;
        }
        return;
    }

    以上可以实现Project2项目在RAM中运行Project1项目共享的函数test。

    但是这个过程过于繁琐,期望能有更好的实现方案

  • 好的,我需要一些时间来看一下