采用arm-none-eabi-gcc交叉编译工具链 以及使用xmake构建 STM32 RT-Thread nano工程 笔记

xmake构建工程

由于多余的文件目录太多,所以删除了bsp目录

xmake.lua构建文件编写

-- 设置工程名
set_project("stm32_rtt_nano_demo")

-- 设置工程版本
set_version("1.0.0")

add_rules("mode.debug", "mode.release")

-- 自定义工具链
toolchain("arm-none-eabi")
    -- 标记为自定义独立工具链
    set_kind("standalone")
    -- 定义交叉编译工具链地址,根据工具链的实际位置修改
    set_sdkdir("C:\\gcc-arm-none-eabi\\10 2021.10")   
toolchain_end()

target("rtt_thread.elf")
    -- 编译为二进制程序
    set_kind("binary") 
    -- 设置使用的交叉编译工具链
    set_toolchains("arm-none-eabi")  

    -- 设置平台
    set_plat("cross")
    -- 设置架构
    set_arch("m3")

    -- 设置编译生成程序名字,不设置就会使用target("rtt_thread.elf")里面的名字
    --set_filename("rtt_thread.elf")

    add_defines(
        "USE_HAL_DRIVER",  -- 使用HAL库
        "STM32F103xB"  -- 参考 libraries\STM32F1xx_HAL\CMSIS\Device\ST\STM32F1xx\Include\stm32f1xx.h 60行 进行设置   
    )

    -- 添加链接库
    add_links("c", "m");  -- 或者链接选项添加 :-lc -lm -lnosys -lrdimon 
    
    add_cflags(
        "-Og",
        "-mcpu=cortex-m3",
        "-mthumb",
        "-Wall",
        "-fdata-sections",
        "-ffunction-sections",
        "-g3 -gdwarf-2",
        "--specs=nano.specs", 
        {force = true}
    )

    add_asflags(
        "-Og",
        "-mcpu=cortex-m3",
        "-mthumb",
       "-x assembler-with-cpp",
        "-Wall",
        "-fdata-sections", 
        "-ffunction-sections",
        "-g3 -gdwarf-2",
        {force = true}
    )

    add_ldflags(
        "-Og",
        "-mcpu=cortex-m3",
        "-TSTM32F103C8Tx_FLASH.ld",  -- 不同芯片需要修改链接脚本 STM32F103XE_FLASH.ld STM32F103C8Tx_FLASH.ld
        "-Wl,--gc-sections",
        "--specs=nosys.specs",
        "--specs=nano.specs",  -- 减小代码尺寸
        "-u _printf_float",  -- 支持printf打印浮点数
        {force = true}
    )
    
    -- 源文件和头文件路径
    local src_path = {
        "applications",
        "drivers",
        "libraries/STM32F1xx_HAL_Driver/Src",
        "drivers/bsp",
    }
    -- 头文件路径
    local inc_path = {
        "applications",
        "drivers",
        "drivers/bsp",
        "libraries/STM32F1xx_HAL_Driver/Inc",
        "libraries/CMSIS/Device/ST/STM32F1xx/Include",
        "libraries/CMSIS/Include",
        "config",
    }
    -- RT-Thread source files
    local rtt_src = {
        "rt-thread/src",
        "rt-thread/libcpu/arm/cortex-m3",
        "rt-thread/components/finsh",
    }
    -- RT-Thread header files
    local rtt_inc = {
        "rt-thread/include",
        "rt-thread",
        "rt-thread/components/finsh",
        "rt-thread/components/drivers/include/drivers"
    }
    -- RT-Thread 线程调度相关的汇编文件
    add_files("rt-thread/libcpu/arm/cortex-m3/context_gcc.S")

    -- 添加启动文件(根据芯片选择) 
    add_files("startup_stm32f103xb.s");

    for _, dir in ipairs(src_path) do  -- 遍历 src_path
        add_files(dir.."/*.c"); 
    end

     for _, dir in ipairs(rtt_src) do  -- 遍历 rtt_src
        add_files(dir.."/*.c"); 
    end

    -- 添加头文件路径
    for _, inc in ipairs(inc_path) do
        add_includedirs(inc);
    end

    for _, inc in ipairs(rtt_inc) do
        add_includedirs(inc);
    end
   
    if is_mode("debug") then 
        -- add_cflags("-g", "-gdwarf-2")
        add_defines("DEBUG")
    end

    after_build(
        function(target)
        cprint("Compile finished!!!")

        if is_mode("release") then
            print("release finished")
            os.exec("arm-none-eabi-objcopy -O ihex ./build/cross/m3/release/rtt_thread.elf ./build/rtt_thread.hex")
            os.exec("arm-none-eabi-objcopy -O binary ./build/cross/m3/release/rtt_thread.elf ./build/rtt_thread.bin")
        end

        if is_mode("debug") then
            print("debug finished")
            os.exec("arm-none-eabi-objcopy -O ihex ./build/cross/m3/debug/rtt_thread.elf ./build/rtt_thread.hex")
            os.exec("arm-none-eabi-objcopy -O binary ./build/cross/m3/debug/rtt_thread.elf ./build/rtt_thread.bin")
        end

        print("Generate hex and bin files ok!!!")

        print(" ");
        print("********************储存空间占用情况*****************************")
        if is_mode("release") then
            os.exec("arm-none-eabi-size -Ax ./build/cross/m3/release/rtt_thread.elf")
            os.exec("arm-none-eabi-size -Bx ./build/cross/m3/release/rtt_thread.elf")
            os.exec("arm-none-eabi-size -Bd ./build/cross/m3/release/rtt_thread.elf")
        end

        if is_mode("debug") then
            os.exec("arm-none-eabi-size -Ax ./build/cross/m3/debug/rtt_thread.elf")
            os.exec("arm-none-eabi-size -Bx ./build/cross/m3/debug/rtt_thread.elf")
            os.exec("arm-none-eabi-size -Bd ./build/cross/m3/debug/rtt_thread.elf")
        end
        --print("heap-堆, stack-栈, .data-已初始化的变量全局/静态变量, .bss-未初始化的data, .text-代码和常量")
        -- os.run("arm-none-eabi-objdump.exe -D ./build/cross/m3/release/rtt_thread.elf > rtt_thread.s")
        -- os.exec("arm-none-eabi-objdump -h -S ./build/cross/m3/debug/rtt_thread.elf > rtt_thread.list")
    end)

RT-Thread nano 自动初始化段添加

 /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)

    KEEP (*(.init))
    KEEP (*(.fini))
    
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */

           /* section information for finsh shell */
    . = ALIGN(4);
    __fsymtab_start = .;
    KEEP(*(FSymTab))
    __fsymtab_end = .; */
 
    . = ALIGN(4);
    __vsymtab_start = .;
    KEEP(*(VSymTab))
    __vsymtab_end = .; 

    /* section information for initial. */
    . = ALIGN(4);
    __rt_init_start = .;
    KEEP(*(SORT(.rti_fn*)))
    __rt_init_end = .;
    
  } >FLASH

RT-Thread nano在gcc下自动初始化段不能失效,原因是gcc的自定义段需要在链接脚本中添加自定义段

添加的自定义段如下:

         /* section information for finsh shell */
    . = ALIGN(4);
    __fsymtab_start = .;
    KEEP(*(FSymTab))
    __fsymtab_end = .; */
 
    . = ALIGN(4);
    __vsymtab_start = .;
    KEEP(*(VSymTab))
    __vsymtab_end = .; 

    /* section information for initial. */
    . = ALIGN(4);
    __rt_init_start = .;
    KEEP(*(SORT(.rti_fn*)))
    __rt_init_end = .;

如果使用的容量太小的MCU,如64K小容量的,不要开启Finsh组件。

多数情况下也不要shell组件。

给RT-Thread定义的堆内存不要太大,够用就行。否则小容量的单片机RAM只有20K,其他地方定义大数组就会超过RAM大小,程序编译链接失败:

"arm-none-eabi-ld.exe: region `ram' overflowed xxx bytes" 

修改链接地址和重设中断向量

修改链接地址为0x800B000,也是加载地址

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20005000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x400;      /* required amount of heap  */
_Min_Stack_Size = 0x800; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
  RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
  FLASH (rx)      : ORIGIN = 0x800B000, LENGTH = 64K
}
  • FLASH (rx) : ORIGIN = 0x8000000 改 FLASH (rx) : ORIGIN = 0x800B000

根据芯片不同,修改不同头文件
libraries/CMSIS/Device/ST/STM32F1xx/Include/stm32f103xb.h:

#define FLASH_BASE            0x0800B000U /*!< FLASH base address in the alias region */
#define FLASH_BANK1_END       0x0801FFFFU /*!< FLASH END address of bank1 */
#define SRAM_BASE             0x20000000U /*!< SRAM base address in the alias region */
  • FLASH_BASE改为0x0800B000U

常用的xmake编译操作

1、编译

xmake

2、根据xmake配置生成makefile

 xmake project -k makefile

3、切换到debug模式编译

xmake f -m debug   // 切换为debug模式 
xmake    //编译

4、编译且输出警告信息

xmake -w 或 xmake --warning

5、看详细的编译参数信息

xmake -v 或 xmake --verbose

6、编译以及获取出错时xmake的调试栈信息

xmake -v --backtrace

xmake编译需要注意的问题

1、xmake.lua 如果是其他工程拷贝过来的,可以删除.xmake文件夹和build文件夹,或者执行xmake f -c强制清除配置缓存,主要是.xmake缓存了上一个工程的配置信息等,会编译失败

2、修改链接地址后不生效,生成反汇编如果不生效的话,先xmake clean清除上一次编译缓存的obj文件,再执行xmake编译

3、如果前一次编译没有错误,而此次编译出现错误,可以尝试使用xmake f -c清除配置缓存再次进行编译。

代码

https://github.com/guangjieMVP/stm32_m3_rtt_nano_xmake_template

你可能感兴趣的