Ruffian Heng embedded: several methods of redirecting key functions to ram for execution under MCU Xpress IDE

Time:2021-9-16

Hello, I’m ruffian Heng, a serious technical ruffian. What ruffian Heng shared with you today isSeveral methods of redirecting key functions to ram for execution under MCU Xpress IDE

Some time ago, ruffian Heng wrote an articleThree methods of redirecting key functions to ram for execution in IAR development environment, some readers leave a message at the bottom of the article and hope to talk about the method of redirecting functions to ram under the MCU Xpress ide. We know that the implementation of function redirection needs the help of linker in IDE. Although the principle of linker is similar in different ides, the specific link syntax is different. The underlying tool chain of mcuxpresso IDE is arm GCC, so today’s topic is actually related to the syntax and usage of arm GCC linker.

1、 Preparatory work

First, prepare the environment, including the necessary software. The environment of ruffian Heng is as follows:

Then followSDK project import and workspace management mechanism under MCU Xpress IDEOne step import from the SDK package to generate a project (choose the simplest hello_world). After the project is successfully imported, it will be displayed in \ mcuxpressoide_ 11.4.0_ 6224\workspace\evkmimxrt1170_ hello_ world_ demo_ CM7 saw the.Project project file, opened the project under MCUXpresso IDE, and then adjusted the engineering settings Memory in the following order:

Now let’s create a new source file critical_ Code. C is used to sample key functions. Add this source file to the project, critical_ There are only three test functions in the code. C file (they will be called in the main function):

void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

Compile and link the modified project, and then check its mapping file (evkmimxrt1170_hello_world_demo_cm7. Map) to find the critical_ The relevant contents of the code. C file are as follows, which is obviously critical_ All three functions in code. C will be chained to board_ In the flash space (all in the. Text segment, and the total size of the function body itself is 52bytes).

Linker script and memory map
LOAD ./source/critical_code.o
**************************************************************
.text           0x30002000     0x4f30
 .text.critical_func1
                0x300026dc       0x10 ./source/critical_code.o
                0x300026dc                critical_func1
 .text.critical_func2
                0x300026ec       0x10 ./source/critical_code.o
                0x300026ec                critical_func2
 .text.critical_func3
                0x300026fc       0x14 ./source/critical_code.o
                0x300026fc                critical_func3
 .rodata.critical_func1.str1.4
                0x30005ea4        0xd ./source/critical_code.o
 *fill*         0x30005eb1        0x3 ff
 .rodata.critical_func2.str1.4
                0x30005eb4       0x11 ./source/critical_code.o
 *fill*         0x30005ec5        0x3 ff
 .rodata.critical_func3.str1.4
                0x30005ec8       0x11 ./source/critical_code.o
 *fill*         0x30005ed9        0x3 ff

2、 Redirect to ram method

What we have to do now is to put critical_ The functions in the code. C file are redirected to ram for execution. SRAM is specified in the original MCU Xpress ide project link configuration_ DTC_ CM7 space to store the readwrite segment, then we try to redirect the key function to SRAM_ DTC_ CM7 (if it is necessary to change to sram_itc_cm7, sram_oc1 / 2 and other spatial methods are similar).

2.1 __ Ramfunc() modifier function

The first method is to use the header file of MCU Xpress ide_ section_ Macros in macros. H. Use__ Ramfunc (ramaliasname) macro to decorate the function definition. This method is mainly applicable to redirecting a single key function. For example, we use it to modify critical_ Func1() function:

  • Note: __ RAMFUNC () only redirecting the modified function body itself code, and the other function bodies that are invoked in the function are not affected by itself.
#include __RAMFUNC(RAM) void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

Compile and link the modified project, and then check its mapping file (evkmimxrt1170_hello_world_demo_cm7. Map) to find the critical_ The relevant contents of the code. C file are as follows. At this time, critical_ Func1() has been put into the built-in. Ramfunc. $ram segment of MCU Xpress IDE, which is the underlying linker of MCU Xpress IDE, which is specially used to collect functions redirected to ram.

Linker script and memory map

2.2 user defined section specifying function

The second method is to use the information in GNU C__ attribute__ Mechanism, ready to use__ attribute__ ((section (“usersectionname”)) syntax to modify the function definition and put it into the custom program segment. For example, we will be critical_ The func1() function is placed in a custom segment named. Criticalfunc:

__attribute__((section(".criticalFunc"))) void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

Then link the configuration setting interface in the MCU Xpress ideExtra linker script input sectionsBox, specify the custom program segment to the specific ramx:

As like as two peas, you can find the effect of the mapping file (evkmimxrt1170_hello_world_demo_cm7.map). The only difference is that the.Ramfunc.$RAM segment name is built with MCUXpresso IDE, and the.CriticalFunc is only the custom section name.

Linker script and memory map

2.3 for all functions in the source file

The first two redirection methods are applicable to a single key function (if there are multiple key functions, it is OK to add modifications one by one). However, if there are many functions in a source file and we want to redirect all the functions in the source file to ram, is there a more convenient method? Of course!

We will now be critical_ All functions in the code. C file are redirected. First, you need to remove them in the link configuration setting interface of MCU Xpress ideManage linker scriptIf the option is checked, the evkmimxrt1170 will be generated automatically_ hello_ world_ demo_ cm7_ Copy the debug.ld file in the same path and rename itLinker scriptSpecify a new linked file in the path.

Open the linked file evkmimxrt1170_ hello_ world_ demo_ cm7_ Debug_ User.ld, find the main. Text /. Data section execution field respectively, and_ Remove code. O from. Text (note that the original single * (. Text *) statement needs to be deleted) and add. Data.

Compile and link the modified project, and then check its mapping file (evkmimxrt1170_hello_world_demo_cm7. Map) to find the critical_ The relevant contents of the code. C file are as follows. At this time, critical_ Func1 / 2 / 3 () is linked in RAM.

Linker script and memory map
LOAD ./source/critical_code.o
**************************************************************
 *(SORT_BY_ALIGNMENT(EXCLUDE_FILE(*critical_code.o) .text*))
 .rodata.critical_func1.str1.4
                0x30005e8c        0xd ./source/critical_code.o
 *fill*         0x30005e99        0x3 ff
 .rodata.critical_func2.str1.4
                0x30005e9c       0x11 ./source/critical_code.o
 *fill*         0x30005ead        0x3 ff
 .rodata.critical_func3.str1.4
                0x30005eb0       0x11 ./source/critical_code.o
 *fill*         0x30005ec1        0x3 ff
**************************************************************
 .data           0x20000000       0x7c load address 0x30006f18
  *critical_code.o(SORT_BY_ALIGNMENT(.text.*))
 .text.critical_func1
                0x20000038       0x10 ./source/critical_code.o
                0x20000038                critical_func1
 .text.critical_func2
                0x20000048       0x10 ./source/critical_code.o
                0x20000048                critical_func2
 .text.critical_func3
                0x20000058       0x14 ./source/critical_code.o
                0x20000058                critical_func3
 *fill*         0x2000006c        0x4 ff
 .text.critical_func3.__stub
                0x20000070        0x8 linker stubs

By the way, I didn’t want to change the link file manually. I wanted to use the following ide option configuration to put the statement to be added into the automatically generated link file, but the actual measurement failed to achieve the expected effect, because the original * (. Text *) statement in the. Text execution domain still exists. It looks like thisExtra linker script input sectionsBox can only add new sentences into the linked file, lacking the function of deleting sentences.

3、 Start the copy process in the file

The three function redirection methods have been introduced. I wonder if you have ever wondered when and how these key function machine codes were copied from flash to ram? This starts from the project startup file startup_ mimxrt1176_ CM7. C, there are all data / BSS initialization processes in the reset function resetisr():

extern unsigned int __data_section_table;
extern unsigned int __data_section_table_end;
extern unsigned int __bss_section_table;
extern unsigned int __bss_section_table_end;

__attribute__ ((naked, section(".after_vectors.reset")))
void ResetISR(void) {
    // Disable interrupts
    __asm volatile ("cpsid i");
    __asm volatile ("MSR MSP, %0" : : "r" (&_vStackTop) : );

#if defined (__USE_CMSIS)
// If __USE_CMSIS defined, then call CMSIS SystemInit code
    SystemInit();
#endif // (__USE_CMSIS)

    // Copy the data sections from flash to SRAM.
    unsigned int LoadAddr, ExeAddr, SectionLen;
    unsigned int *SectionTableAddr;

    // Load base address of Global Section Table
    SectionTableAddr = &__data_section_table;

    // Copy the data sections from flash to SRAM.
    while (SectionTableAddr < &__data_section_table_end) {
        LoadAddr = *SectionTableAddr++;
        ExeAddr = *SectionTableAddr++;
        SectionLen = *SectionTableAddr++;
        data_init(LoadAddr, ExeAddr, SectionLen);
    }

    // At this point, SectionTableAddr = &__bss_section_table;
    // Zero fill the bss segment
    while (SectionTableAddr < &__bss_section_table_end) {
        ExeAddr = *SectionTableAddr++;
        SectionLen = *SectionTableAddr++;
        bss_init(ExeAddr, SectionLen);
    }

    // Reenable interrupts
    __asm volatile ("cpsie i");

#if defined (__REDLIB__)
    // Call the Redlib library, which in turn calls main()
    __main();
#endif

    while (1);
}

So far, several methods of redirecting key functions to ram under the MCU Xpress ide have been introduced. Where are the applause~~~

Welcome to subscribe

The article will be published to me at the same timeBlog Park home pageCSDN home pageZhihu home pageWeChat official accountOn the platform.

Wechat search“Ruffian scale“Or scan the QR code below to see it for the first time on the mobile phone.