PI Zi Heng embedded: different entry settings in IVT may cause abnormal flight after i.mxrt1xxx series starts app

Time:2020-11-10

Hello, everyone. I’m a ruffian. I’m a real technical ruffian. What ruffian Heng shares with you today isDifferent entry settings in IVT may cause abnormal flight after i.mxrt1xxx series starts app

A question post on the official forum of NXP《RT1015 dev_cdc_vcom_freertos reset entry failed》This is a problem encountered by Qisda, a colleague of ruffian Heng, Miss Kerry, who is very careful and responsible, sorted out the problem and posted it. In the post, a detailed description of the problem and various test results were made. After reading the long post, ruffian Heng’s first guess is that it is related to the app stack setting, which is the reason. So why does the stack setting go wrong? And listen to ruffian Heng’s chat:

1、 Problem description

Let’s first sort out the problems in the post. The customer tested two routines in the official NXP SDK on rt1015-evk. One is a simple hello_ World, the other is the complex dev_ cdc_ vcom_ FreeRTOS, the two routines are inconsistent under the combination of entry values in different IDE and IVT

Test app Entry in IVT Test IDE App running results
hello_world Start address of interrupt vector table/

Reset vector function address
IAR EWARM/


MCUXpresso IDE
normal
dev_cdc_vcom_freertos Start address of interrupt vector table IAR EWARM/


MCUXpresso IDE
normal
dev_cdc_vcom_freertos Reset vector function address IAR EWARM normal
dev_cdc_vcom_freertos Reset vector function address MCUXpresso IDE Abnormal flight

According to the results in the above table, it is very difficult for us to make an effective inference. We can only say that the abnormal result can be reproduced under the specific app, entry value and mcuxpress ide.

2、 A probe into the causes

Since we can’t see the reason for that, let’s do some preparatory work first. Let’s sort out the differences among the three influencing factors (APP, entry value, IDE)

2.1 different link assignment of two apps

Both apps are from the SDK and have been tested in detail by the official authorities, so we don’t doubt that the app itself has abnormal functions. The difference is mainly in link assignment. In the case of IAR, we only look at flexspi_ Nor build. The default heap and stack size allocated in the link file are 1KB

/* Sizes */
if (isdefinedsymbol(__stack_size__)) {
  define symbol __size_cstack__        = __stack_size__;
} else {
  define symbol __size_cstack__        = 0x0400;
}

if (isdefinedsymbol(__heap_size__)) {
  define symbol __size_heap__          = __heap_size__;
} else {
  define symbol __size_heap__          = 0x0400;
}

hello_ Because the world routine is relatively simple, it uses the default stack size directly, and dev_ cdc_ vcom_ The FreeRTOS routine is more complex, and the stack has been adjusted to 8KB.

We also noticed hello_ The world routine puts its RW, Zi, and stack into a 32KB dtcm, while dev_ cdc_ vcom_ FreeRTOS routine put RW and Zi into 64KB ocram, and only put the stack into dtcm

define symbol m_ data_ start             = 0x20000000;

2.2 use of entry value in bootrom

Let’s talk about the entry in IVT, and i.mxrt1xxx series started by ruffian HengBootable image format and loadingSection 3.2 of describes the structure and function of IVT. IVT is the key startup head, which guides bootrom to move app and load execution. The entry member is mainly used for jump execution.

Why can this entry value be either the start address of the vector table or the reset vector_ What about the function address? This depends on how the entry value is used in bootrom. The following function is the final jump function in bootrom:

void jump_to_entry(uint32_t entry)
{
    typedef void (*application_callback_t)(void);
    static application_callback_t s_app_callback;

    pu_irom_mpu_disable();

    __DMB();
    __DSB();
    __ISB();

    // The entry point is the absolute address of the call back function
    if ((uint32_t)entry & 1)
    {
        s_app_callback = (application_callback_t)entry;
    }
    // The entry point is the base address of vector table
    else
    {
        static uint32_t s_stack_pointer;
        // Ensure Core read vector table for destination instead of register
        volatile uint32_t *vector_table = (volatile uint32_t *)entry;

        s_stack_pointer = vector_table[0];
        s_app_callback = (application_callback_t)vector_table[1];

        // Update Stack pointer
        __set_MSP(s_stack_pointer);
        __set_PSP(s_stack_pointer);
    }

    __DSB();
    __ISB();

    // Jump to user application in the end
    s_app_callback();

    // Should never reach here
    __NOP();
    __NOP();
}

Jump from the jump function above_ To_ The implementation of entry() shows that if the entry value is the reset function address (i.e. odd address), then the bootrom will jump to the reset function execution directly; if the entry value is the first address of the interrupt vector table (i.e., even address), bootrom will reset the current SP to the top of the stack specified by app, and then jump to the reset function.

OK, now we know where the different entry values differ in IVT.

2.3 startup process under different IDE

Since two different ides are involved, namely IAR and mcuxpresso IDE, let’s take a look at the startup implementation under these two ides. We know that the code after the main function is ide independent, but startup varies with the compiler.

PI Ziheng takes the routine in sdk2.8.2 package of i.mxrt1010 as an example, and first uses IAR to open dev_ cdc_ vcom_ FreeRTOS routine, find the startup under the project_ Mimxrt1011. S file, see its reset_ Handler implementation:

__vector_table
        DCD     sfe(CSTACK)
        DCD     Reset_Handler

        DCD     NMI_Handler                                   ;NMI Handler
        DCD     HardFault_Handler                             ;Hard Fault Handler
        ; ...
__Vectors_End

        THUMB

        PUBWEAK Reset_Handler
        SECTION .text:CODE:REORDER:NOROOT(2)
Reset_Handler
        CPSID   I               ; Mask interrupts
        LDR     R0, =0xE000ED08
        LDR     R1, =__vector_table
        STR     R1, [R0]
        LDR     R2, [R1]
        MSR     MSP, R2
        LDR     R0, =SystemInit
        BLX     R0
        CPSIE   I               ; Unmask interrupts
        LDR     R0, =__iar_program_start
        BX      R0

IAR version reset_ Handler consists of four steps: reset vtor, reset SP, execute systeminit (close watchdog, close systick, process cache), and execute IAR library function__ iar_ program_ Start (initialize the data / BSS / ramfunc section and jump to main).

Use mcuxpresso ide to open the same dev_ cdc_ vcom_ FreeRTOS routine, find the startup under the project_ For the mimxrt1011. C file, see its resetisr implementation:

extern void _vStackTop(void);

__attribute__ ((used, section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
    // Core Level - CM7
    &_vStackTop,                       // The initial stack pointer
    ResetISR,                          // The reset handler
    NMI_Handler,                       // The NMI handler
    HardFault_Handler,                 // The hard fault handler
    // ...
}; /* End of g_pfnVectors */

__attribute__ ((section(".after_vectors.reset")))
void ResetISR(void) {
    __asm volatile ("cpsid i");

    SystemInit();

    // 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);
    }

    __asm volatile ("cpsie i");

    // Call the Redlib library, which in turn calls main()
    __main();

    while (1);
}

The resetisr of mcuxpresso ide version mainly consists of three steps: execute systeminit (reset vtor, close watchdog, close systick, process cache), initialize data / BSS / ramfunc segment, and jump to main.

After the above comparison, can you see the difference? Compared with the startup of IAR, mcuxpresso ide does not need to reset sp by one step.

2.4 stack errors causing abnormal runaway

With the analysis basis of the previous three sections, we can basically get dev_ cdc_ vcom_ The reason for the FreeRTOS routine to run abnormally is that a stack error has occurred. Why do stack errors occur? This is because there is no SP reset operation in startup under mcuxpresso. Therefore, when the entry in IVT is the reset vector, the stack in bootrom will still be used after bootrom jumps to app. According to the information in the system boot section of the chip reference manual, the stack of bootrom is placed in ocram space (0x20200000 – 0x202057ff), but dev_ cdc_ vcom_ FreeRTOS routine also put the RW and Zi segments into ocram. Therefore, with the application of the stack (function call, local variable definition) and the RW and Zi segment data (global variables) in the app, it is expected that the program will run unknown.

What is the solution to the problem? Of course, the SP reset operation is added to the startup process of mcuxpresso ide to keep it consistent with the IAR startup process.

Wei attribute__  ((section(".after_ vectors.reset ")))

At this point, the different entry settings in IVT may cause abnormal flight after i.mxrt1xxx series starts the app. The experience of analyzing and solving the problem of abnormal running and flying is finished. What’s the applause~~~

Welcome to subscribe

The article will be posted to me at the same timeBlog Garden HomepageCSDN home pageZhihu HomepageWeChat official accountOn the platform.

Wechat search“Ruffian scale embedded“Or scan the QR code below, and you can read it for the first time on your mobile phone.