首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MCUxpresso imr位置无关代码导致空闲rtos任务激活出现严重故障。

MCUxpresso imr位置无关代码导致空闲rtos任务激活出现严重故障。
EN

Stack Overflow用户
提问于 2022-04-26 15:06:46
回答 1查看 113关注 0票数 1

我有一个开发板(imx 1024)来自于nxp,我编写了一个使用MCUxpresso的软件(nxp的IDE)。对于我的项目,我被要求介绍位置独立代码(PIC),长话短说,这将节省我们在空中安装固件更新时的几秒钟停机时间。

我首先创建了一个新的标准项目,以便弄脏我的手,更好地理解PIC是如何工作的。因此,在对链接器脚本进行了一些更改(将.got部分放在闪存中的某个位置,并将其定义为SRAM (VMA))并对启动代码进行一些修改之后,我终于开始了第一步的工作:我可以在我的mcu上运行编译为“位置独立代码”的代码。

显然,我还没有把它移到“任何”地点。但作为第一步,我很高兴。

我的下一步是,输入一些响应硬件中断的代码。我不知道为什么,但我觉得这可能很棘手。或者,也许我也想看到它起作用。对我来说不幸的是,它失败了。太难了。

简要阐述:

  1. 因此,我有一个项目,它在我的开发板上切换一个引脚,它可以切换一个led。对于像我这样简单的人来说,很容易得到反馈。这个很管用。还没给人留下深刻印象。
  2. 接下来,我用-fPIC编译了相同的项目,并使其工作起来。
  3. 接下来,我引入freertos,创建一个简单的任务,为我做“闪烁”,然后进入睡眠状态。同样,在没有使用-fPIC进行编译的情况下启动。这个也能用。再一次,不给人印象深刻,简单的小步。

闪烁以供参考的任务。

代码语言:javascript
复制
static void main_task(void *params)
{
    while (1)
    {
        GPIO1->DR ^= (1<<24);
        vTaskDelay(100);
    }
}
  1. 接下来,让我们再做一次freertos测试,但是现在用-fPIC进行编译。一旦FreeRTOS试图启动其调度程序,程序就会在mem错误上崩溃。

现在,我尝试了很多事情,想弄清楚这件事,一条线索,一个模糊的原因,但我什么也没得到。将.got部分从ITC移到ITC,不要将其移动到sram,而是将其保存在闪存中(因为我还没有在闪存中移动代码)。似乎没有什么能改变这种行为。一旦我用-fPIC编译了freertos测试项目,它就会在任务调度程序启动时崩溃。

潜入一些细节

作为参考,链接器脚本修改:

代码语言:javascript
复制
 .got : ALIGN(4)
{
    __global_offset_table_flash_start__ = LOADADDR(.got) ;
    __global_offset_table_itc_start__ = ADDR(.got) ;
    *(.got* .got.*)
    __global_offset_table_flash_end__ = . ;
} >SRAM_DTC AT>PROGRAM_FLASH

附带注意:这是复制到SRAM_DTC (/aka是数据的优化内存,ITC是指令的优化内存(/aka函数)。我认为 .got部分包含指向数据的指针,.got.plt包含共享库的函数(我不使用共享库,因此没有.got.plt部分)。我在ITC和DTC中都尝试了.got部分。两者都以同样的方式失败。对我来说,将.got存储在DTC中是最有意义的。所以,我坚持这样做,直到我知道这些假设中的一些是错误的。

也可供参考,调整部分的ResetHandler。在启动代码中,我设置了用于PIC的r9寄存器。我还将.got部分复制到SRAM_DTC

代码语言:javascript
复制
// Ignore the volatile stuff, it makes debugging easier, if I don't, 
// I see 'optimized out' in mcuxpresso which is making my life harder
// other than that, it serves no functional purpose
// volatile is casted away with const_cast<...>

volatile extern unsigned int __global_offset_table_flash_start__;
volatile extern unsigned int __global_offset_table_itc_start__;
volatile extern unsigned int __global_offset_table_flash_end__;

volatile unsigned int size;
unsigned int index;

unsigned int *global_offset_table_flash;
unsigned int *global_offset_table_itc;
unsigned int *global_offset_table_end_itc;
unsigned int global_offset_table_size;


__attribute__ ((naked, section(".after_vectors.reset")))
void ResetISR(void) 
{
    // Disable interrupts
    __asm volatile ("cpsid i");
    // Setup r9 used for PIC, and let it point to the location in flash first
    __asm volatile ("LDR r9, = __global_offset_table_flash_start__");
    // Set the stack pointer, AFTER we setup r9
    __asm volatile ("MSR MSP, %0" : : "r" (&_vStackTop) : );

    //
    // Copy global offset table to ram
    //
    global_offset_table_flash = const_cast<unsigned int*>(&__global_offset_table_flash_start__);
    global_offset_table_itc = const_cast<unsigned int*>(&__global_offset_table_itc_start__);
    global_offset_table_end_itc = const_cast<unsigned int*>(&__global_offset_table_flash_end__);

    size =
        reinterpret_cast<unsigned int>(&__global_offset_table_flash_end__) -
        reinterpret_cast<unsigned int>(&__global_offset_table_itc_start__);
    global_offset_table_size = static_cast<unsigned int>(&__global_offset_table_flash_end__ - &__global_offset_table_itc_start__);

    for (index = 0u; index < size/sizeof(unsigned int); ++index)
    {
        global_offset_table_itc[index] = global_offset_table_flash[index];
    }

    __asm volatile ("LDR r9, = __global_offset_table_itc_start__");

    // ... rest of startup code, initializes VTOR and some other nxp generated stuff
    // ... before it jumps to main()

我知道真正的男人会在集会上这样做。我还没有足够的男子汉来参加简单的集会。我还可以想象,核心程序集人员可能不太熟悉这个c++。我很有信心,这段代码可以做它声称要做的事情。我一步一步地完成了这个过程。.got section通过uint32被uint32复制,并以SRAM结束。

跳转到主后就完成了。执行的代码很少。我配置我的LED引脚,创建一个包含大量堆栈的freertos任务,并启动调度程序。

代码语言:javascript
复制
static void main_task(void *params);

int main(void) {

    /* Init board hardware. */
    BOARD_ConfigMPU();
    BOARD_InitBootPins();
    BOARD_InitBootClocks();
    BOARD_InitBootPeripherals();
#ifndef BOARD_INIT_DEBUG_CONSOLE_PERIPHERAL
    /* Init FSL debug console. */
    BOARD_InitDebugConsole();
#endif

    gpio_pin_config_t USER_LED_config = {
        .direction = kGPIO_DigitalOutput,
        .outputLogic = 0U,
        .interruptMode = kGPIO_NoIntmode
    };
    /* Initialize GPIO functionality on GPIO_AD_B1_08 (pin 82) */
    GPIO_PinInit(GPIO1, 24U, &USER_LED_config);


    xTaskCreate(
        main_task,
        "main",
        2000,
        nullptr,
        2,
        nullptr );

    vTaskStartScheduler();


    return 0 ;
}

启动调度程序时,代码会在mem错误上立即崩溃。

有没有人有过职位独立代码的经验,并认识到这种行为?有小费吗?有什么好的建议可以排除吗?

我可以分享任何与代码相关的信息。这只是在mcuxpresso中创建的一个标准的新c++项目。如果这有帮助的话,我甚至可以在github上分享整个项目。

非常感谢帮助/指针/提示!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-30 13:43:01

freertos社区的帮助下,我解决了这个问题。

最后,我所要做的就是修改freertos端口,在那里初始化堆栈以恢复创建的堆栈上的r9。

代码语言:javascript
复制
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
                                 TaskFunction_t pxCode,
                                 void * pvParameters )
{
    /* Simulate the stack frame as it would be created by a context switch
     * interrupt. */

    /* Offset added to account for the way the MCU uses the stack on entry/exit
     * of interrupts, and to ensure alignment. */
    pxTopOfStack--;

    *pxTopOfStack = portINITIAL_XPSR;                                    /* xPSR */
    pxTopOfStack--;
    *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
    pxTopOfStack--;
    *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS;             /* LR */

    /* Save code space by skipping register initialisation. */
    pxTopOfStack -= 5;                            /* R12, R3, R2 and R1. */
    *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */

    /* A save method is being used that requires each task to maintain its
     * own exec return value. */
    pxTopOfStack--;
    *pxTopOfStack = portINITIAL_EXC_RETURN;

    pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
    
    // 
    // I added this part, as suggested by freertos members
    // 

    // Patched freertos for supporting -fpic: Set the task's initial R9 value
    __asm ("MOV %[result], R9"
        : [result] "=r" (pxTopOfStack[9-4])
      );


    return pxTopOfStack;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72016315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档