在ARM裸机引导程序上启用C ++异常

时间:2018-12-12 21:00:55

标签: c++ exception arm bootloader

出于学习目的,我试图在ARM MCU(STM32F407ZE)上获得完整的C ++支持。我正在努力使异常起作用,因此提出了这个问题:

如何在裸机ARM引导加载程序上获取C ++异常?

扩展一下问题:
我知道一个异常,例如退出一个函数,需要展开堆栈。退出函数是开箱即用的事实,但是异常处理却不行,这让我认为编译器正在添加退出函数的展开功能,但不能对异常执行此操作。

因此,子问题1是:此前提正确吗?我真的需要实现/集成展开库以进行异常处理吗?

根据我对展开的肤浅理解,堆栈中有一个框架,展开“正义”需要在其每个对象上调用析构函数,最后跳转到给定的catch

子问题2:展开库如何执行此任务?使用什么策略? (扩展到适合SO答案的范围)

在我的搜索中,我发现了许多有关解散的解释,但很少有如何使它起作用的解释。最接近的是:

GCC arm-none-eabi (Codesourcery) and C++ Exceptions


项目

1)第一步(但有一些困难)是使MCU通电并通过JTAG进行通信。

  

这仅仅是上下文信息,请不要仅因为这张图片而将问题标记为脱题。而是跳到步骤2。

我知道有可用的测试板,但这是一个学习项目,目的是更好地了解幕后的所有“魔术”。因此,我得到了一个芯片插座,一个面包板,并设置了最小的上电电路:

enter image description here

注意:JTAG是通过树莓派的GPIO执行的。
注意2:我正在使用OpenOCD与芯片进行通信。

2)第二步,是制作一个最小的软件来使黄色LED闪烁。
使用arm-none-eabi-g ++作为编译器和链接器,C ++代码很简单,但是我对链接器脚本的理解仍然有些模糊。

3)启用异常处理(尚不可用)。

为此目标,请参考以下有用信息:

但是,对于简单的异常处理而言似乎过于复杂,在开始实现/集成展开库之前,我想确定我会朝着正确的方向发展。
我希望避免在两周内出现问题:“哦,顺便说一句,您只需要向编译器添加此“ -xx”选项即可使用”

main.cpp

auto reset_handler() noexcept ->void;
auto main() -> int;

int global_variable_test=50;

extern "C"
{

        #include "stm32f4xx.h"
        #include "stm32f4xx_rcc.h"
        #include "stm32f4xx_gpio.h"



        void assert_failed(uint8_t* file, uint32_t line){}
        void hardFaultHandler( unsigned int * hardFaultArgs);

        // vector table
        #define SRAM_SIZE 128*1024
        #define SRAM_END        (SRAM_BASE + SRAM_SIZE)
        unsigned long *vector_table[] __attribute__((section(".vector_table"))) =
        {
                (unsigned long *)SRAM_END,   // initial stack pointer 
                (unsigned long *)reset_handler,        // main as Reset_Handler
        };
}


auto reset_handler() noexcept -> void
{
        // Setup execution

        // Call the main function
        int ret = main();

        // never finish
        while(true);
}


class A
{
public:
        int b;

        auto cppFunc()-> void
        {
                throw (int)4;
        }
};

auto main() -> int
{
        // Initializing led GPIO
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
        GPIO_InitTypeDef GPIO_InitDef;

        GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
        GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
        GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_InitDef.GPIO_Speed = GPIO_Speed_100MHz;
        GPIO_Init(GPIOG, &GPIO_InitDef);

        // Testing normal blinking
        int loopNum = 500000;
        for (int i=0; i<5; ++i)
        {
                loopNum = 100000;
                GPIO_SetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14);
                for (int i = 0; i < loopNum; i++) continue; //active waiting!

                loopNum = 800000;
                GPIO_ResetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14);
                for (int i=0; i<loopNum; i++) continue; //active waiting!
        }

        // Try exceptions handling
        try
        {
                A a;
                a.cppFunc();
        }
        catch(...){}


        return 0;
}

Makefile

CPP_C = arm-none-eabi-g++
C_C = arm-none-eabi-g++
LD = arm-none-eabi-g++
COPY = arm-none-eabi-objcopy

LKR_SCRIPT = -Tstm32_minimal.ld

INCLUDE = -I. -I./stm32f4xx/CMSIS/Device/ST/STM32F4xx/Include -I./stm32f4xx/CMSIS/Include -I./stm32f4xx/STM32F4xx_StdPeriph_Driver/inc -I./stm32f4xx/Utilities/STM32_EVAL/STM3240_41_G_EVAL -I./stm32f4xx/Utilities/STM32_EVAL/Common
C_FLAGS  = -c -fexceptions -fno-common -O0 -g -mcpu=cortex-m4 -mthumb -DSTM32F40XX -DUSE_FULL_ASSERT -DUSE_STDPERIPH_DRIVER $(INCLUDE)
CPP_FLAGS  = -std=c++11 -c $(C_FLAGS)
LFLAGS  = -specs=nosys.specs -nostartfiles -nostdlib $(LKR_SCRIPT)
CPFLAGS = -Obinary

all: main.bin

main.o: main.cpp
        $(CPP_C) $(CPP_FLAGS) -o main.o main.cpp

stm32f4xx_gpio.o: stm32f4xx_gpio.c
        $(C_C) $(C_FLAGS) -o stm32f4xx_gpio.o stm32f4xx_gpio.c

stm32f4xx_rcc.o: stm32f4xx_rcc.c
        $(C_C) $(C_FLAGS) -o stm32f4xx_rcc.o stm32f4xx_rcc.c

main.elf: main.o stm32f4xx_gpio.o stm32f4xx_rcc.o
        $(LD) $(LFLAGS) -o main.elf main.o stm32f4xx_gpio.o stm32f4xx_rcc.o

main.bin: main.elf
        $(COPY) $(CPFLAGS) main.elf main.bin

clean:
        rm -rf *.o *.elf *.bin

write:
        ./write_bin.sh main.elf

链接描述文件:stm32_minimal.ld

/* memory layout for an STM32F407 */
MEMORY
{
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 512K
    SRAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 128K
}

/* output sections */
SECTIONS
{
    /* program code into FLASH */
    .text :
    {
        *(.vector_table)    /* Vector table */
        *(.text)            /* Program code */
        *(.data)
        /**(.eh_frame)*/
    } >FLASH

    .ARM.exidx :            /* Required for unwinding the stack? */
    {
        __exidx_start = .;
        * (.ARM.exidx* .gnu.linkonce.armexidx.*)
        __exidx_end   = .;
    } > FLASH

    PROVIDE ( end = . );

}

0 个答案:

没有答案