xmake-io/xmake下载:
https://github.com/xmake-io/xmake/releases/tag/v2.6.9
arm-none-eabi-gcc 下载:
Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer
https://developer.arm.com/downloads/-/gnu-rm
安装都是一路next下去就可以了。
安装记得勾选添加到环境变量。
xmake入门,构建项目原来可以如此简单
https://zhuanlan.zhihu.com/p/35051214
xmake新增智能代码扫描编译模式,无需手写任何make文件
https://tboox.org/cn/2017/01/07/build-without-makefile/
对比MDK开发STM32:
(汇编.s)
,没有启动文件无法设置栈跳转到C语言世界散列文件(.sct)
,在GNU那里这种叫链接文件(.ld)
或链接脚本
如何得到链接文件和启动文件:
share\gcc-arm-none-eabi\samples
下有链接文件和启动文件的模板Toolchain / IDE的方式为Makefile
,生成的工程就带有启动文件和链接文件为了方便选择STM32CubeMx 的方式生成工程,还可以方便参照生成的makefile来设置编译链接选项
。
-- 设置工程名
set_project("stm32-xmake")
-- 设置工程版本
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")
--set_bindir("C:\\Program Files (x86)\\GNU Arm Embedded Toolchain\\10 2021.10\\bin")
toolchain_end()
target("demo")
-- 编译为二进制程序
set_kind("binary")
-- 设置使用的交叉编译工具链
set_toolchains("arm-none-eabi")
-- 设置平台
set_plat("cross")
-- 设置架构
set_arch("m3")
set_filename("demo.elf")
add_defines(
"USE_HAL_DRIVER",
"STM32F103xE"
)
-- 添加链接库
add_links("c", "m", "nosys", "rdimon");
-- 添加启动文件
add_files("startup_stm32f103xe.s");
-- 源文件和头文件路径
local src_path = {
"./Core/",
"./Drivers/STM32F1xx_HAL_Driver/",
}
-- 特殊头文件目录,不方便递归遍历的
local inc_path = {
"Drivers/CMSIS/Include",
"Drivers/CMSIS/Device/ST/STM32F1xx/Include"
}
-- 排除的文件,不参与编译 模板文件可以直接删除
remove_files("./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_timebase_tim_template.c")
remove_files("./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_timebase_rtc_alarm_template.c")
remove_files("./Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_msp_template.c")
-- 添加启动文件
add_files("startup_stm32f103xe.s");
for _, index in ipairs(src_path) do -- 遍历 src_path
for _, dir in ipairs(os.dirs(index.."/**")) do -- 递归搜索子目录
add_files(dir.."/*.c");
add_includedirs(dir);
end
end
-- 添加头文件路径
for _, inc in ipairs(inc_path) do
add_includedirs(inc);
end
if is_mode("debug") then
add_cflags("-g", "-gdwarf-2")
end
add_cflags(
"-Og",
"-mcpu=cortex-m3",
"-mthumb",
"-Wall",
"-fdata-sections",
"-ffunction-sections",
"-g -gdwarf-2",
{force = true}
)
add_asflags(
"-Og",
"-mcpu=cortex-m3",
"-mthumb",
"-x assembler-with-cpp",
"-Wall",
"-fdata-sections",
"-ffunction-sections",
"-g -gdwarf-2",
{force = true}
)
add_ldflags(
"-Og",
"-mcpu=cortex-m3",
"-TSTM32F103ZETx_FLASH.ld",
"-Wl,--gc-sections",
"--specs=nosys.specs",
"-u _printf_float",
{force = true}
)
after_build(
function(target)
cprint("Compile finished!!!")
cprint("Next, generate HEX and bin files.")
os.exec("arm-none-eabi-objcopy -O ihex ./build/cross/m3/release/demo.elf ./build/demo.hex")
os.exec("arm-none-eabi-objcopy -O binary ./build/cross/m3/release/demo.elf ./build/demo.bin")
print("Generate hex and bin files ok!!!")
print(" ");
print("********************储存空间占用情况*****************************")
os.exec("arm-none-eabi-size -Ax ./build/cross/m3/release/demo.elf")
os.exec("arm-none-eabi-size -Bx ./build/cross/m3/release/demo.elf")
os.exec("arm-none-eabi-size -Bd ./build/cross/m3/release/demo.elf")
--print("heap-堆, stack-栈, .data-已初始化的变量全局/静态变量, .bss-未初始化的data, .text-代码和常量")
--os.run("arm-none-eabi-objdump -D ./build/cross/m3/release/demo.elf > demo.s")
end)
arm-none-eabi-gcc 报错 undefined reference to `_exit’解决方案_Pz_mstr的博客-CSDN博客
https://blog.csdn.net/qq_35544379/article/details/104805295
工具链已经设置到环境变量测试已经生效,但在Vscode上的终端还是无法生效的解决办法:
windows 修改环境变量后在 vscode 的终端不生效的解决方法 | 码农家园
https://www.codenong.com/jsf9a5c0fed195/
stm32-xmake: 使用xmake来编译cubemx生成的项目
https://gitee.com/luodeb/stm32-xmake
GNU(gcc-arm-none-eabi)编译stm32代码,重定向printf问题_一个逍遥怪的博客-CSDN博客_gcc printf 重定向
https://blog.csdn.net/qq_42704360/article/details/102853340
-- 设置工程名
set_project("stm32-xmake")
-- 设置工程版本
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("LED_DRV.elf")
-- 编译为二进制程序
set_kind("binary")
-- 设置使用的交叉编译工具链
set_toolchains("arm-none-eabi")
-- 设置平台 表示交叉编译程序
set_plat("cross")
-- 设置架构
set_arch("m3")
add_defines(
"USE_STDPERIPH_DRIVER", -- 表示使用标准库
"STM32F10X_MD" -- 中容量 根据芯片容量选择
)
-- 添加链接库
add_links("c", "m", "nosys", "rdimon"); -- 链接选项添加 :-lc -lm -lnosys -lrdimon
-- 添加启动文件
add_files("startup_stm32f10x_md.s");
add_cflags(
"-Og",
"-mcpu=cortex-m3",
"-mthumb",
"-Wall",
"-fdata-sections",
"-ffunction-sections",
"-g -gdwarf-2",
{force = true}
)
add_asflags(
"-Og",
"-mcpu=cortex-m3",
"-mthumb",
-- "-x assembler-with-cpp",
"-Wall",
"-fdata-sections",
"-ffunction-sections",
"-g -gdwarf-2",
{force = true}
)
add_ldflags(
"-Og",
"-mcpu=cortex-m3",
"-TSTM32F103C8Tx_FLASH.ld", -- 不同芯片需要修改链接脚本
"-Wl,--gc-sections",
"--specs=nosys.specs",
"-u _printf_float",
{force = true}
)
-- 源文件和头文件路径
local src_path = {
"USER/",
"Common/src",
"./MqEvent/",
"Lib/Fwlib",
"Lib/Fwlib/src",
"./Lib/CMSIS/",
"USER/app/src",
"USER/bsp/src"
}
-- 头文件路径
local inc_path = {
"./MqEvent/",
"./Lib/CMSIS/",
"Lib/Fwlib/inc",
"Common/inc",
"USER/app/inc",
"USER/bsp/inc"
}
-- 排除的文件,不参与编译
remove_files("Common\\src\\meanFilter.c")
remove_files("USER\\bsp\\src\\VirtualCOM.c")
for _, dir in ipairs(src_path) do -- 遍历 src_path
add_files(dir.."/*.c");
end
-- 添加头文件路径
for _, inc in ipairs(inc_path) do
add_includedirs(inc);
end
if is_mode("debug") then
add_cflags("-g", "-gdwarf-2")
end
after_build(
function(target)
cprint("Compile finished!!!")
cprint("Next, generate hex and bin files.")
os.exec("arm-none-eabi-objcopy -O ihex ./build/cross/m3/release/LED_DRV.elf ./build/LED_DRV.hex")
os.exec("arm-none-eabi-objcopy -O binary ./build/cross/m3/release/LED_DRV.elf ./build/LED_DRV.bin")
print("Generate hex and bin files ok!!!")
print(" ");
print("********************储存空间占用情况*****************************")
os.exec("arm-none-eabi-size -Ax ./build/cross/m3/release/LED_DRV.elf")
os.exec("arm-none-eabi-size -Bx ./build/cross/m3/release/LED_DRV.elf")
os.exec("arm-none-eabi-size -Bd ./build/cross/m3/release/LED_DRV.elf")
--print("heap-堆, stack-栈, .data-已初始化的变量全局/静态变量, .bss-未初始化的data, .text-代码和常量")
-- os.run("arm-none-eabi-objdump.exe -D ./build/cross/m3/release/LED_DRV.elf > LED_DRV.s")
end)
在终端中切换到工程根目录执行xmake
编译,如果使用的是Vscode,可以在编辑器内就可以打开终端,默认就是根路径;如果使用的编辑器无此功能,则可以打开powershell或bash等shell终端编译。
使用Vscode内打开终端编译,在window下实际上打开的也是powershell:
如果是想单独打开powershell编译,一个实用技巧就是在当前目录路径输入powershell回车就会打开一个powershell终端并且已经切换到工程根路径。
如果xmake.lua是拷贝另一个工程,编译此工程可能会还是编译上一个工程的程序,这样可能会出问题,这时候可以执行xmake -P .
,表示强制使用当前目录下的xmake.lua
编译工程。
startup_stm32f10x_md.s
从标准库标准库固件包中获取,也可以用STM32CubeMx生成的。
STM32F103C8Tx_FLASH.ld
链接脚本使用STM32CubeMx生成的,也可以从标准库固件包中获取。
Vscode添加源码头文件路径的技巧:对文件目录树的文件或目录右键选择复制相对路径,就可以快速添加目录。
1、解决内联汇编错误
C:\Users\opto\AppData\Local\Temp\cc3sKKIq.s:619: Error: registers may not be the same -- `strexb r0,r0,[r1]'
C:\Users\opto\AppData\Local\Temp\cc3sKKIq.s:650: Error: registers may not be the same -- `strexh r0,r0,[r1]'
stack traceback:
参考HAL库头文件Drivers\CMSIS\Core_A\Include\cmsis_gcc.h
, 对core_cm3.c
做以下修改:
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
//__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
__ASM volatile ("strexb %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
//__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
__ASM volatile ("strexh %0, %2, %1" : "=&r" (result), "=Q" (*addr) : "r" ((uint32_t)value) );
return(result);
}
2、解决 sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk’ 等问题
error: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-sbrkr.o): in function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-writer.o): in function `_write_r':
writer.c:(.text._write_r+0x14): undefined reference to `_write'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-closer.o): in function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-fstatr.o): in function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-isattyr.o): in function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-lseekr.o): in function `_lseek_r':
lseekr.c:(.text._lseek_r+0x14): undefined reference to `_lseek'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-readr.o): in function `_read_r':
readr.c:(.text._read_r+0x14): undefined reference to `_read'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-abort.o): in function `abort':
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-signalr.o): in function `_kill_r':
signalr.c:(.text._kill_r+0xe): undefined reference to `_kill'
c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/ld.exe: c:/gcc-arm-none-eabi/10 2021.10/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/lib/thumb/v7-m/nofp\libc.a(lib_a-signalr.o): in function `_getpid_r':
signalr.c:(.text._getpid_r+0x0): undefined reference to `_getpid'
collect2.exe: error: ld returned 1 exit status
--specs=nosys.specs
Lib\CMSIS\system_stm32f10x.c
:128 #define VECT_TAB_OFFSET 0xB000 /*!< Vector Table base offset field.
264 #ifdef VECT_TAB_SRAM
265 SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
266 #else
267 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
268 #endif
VECT_TAB_OFFSET
从0x0修改为0xB000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0xB000)
; 设置修改链接地址也就是修改链接文件
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x800B000, LENGTH = 64K
}
0x8000000
改为0x800B000
修改了地址后要执行xmake clean
清除先前地址编译的obj文件,因为当前obj文件是未修改前的地址生成的obj,直接执行xmake地址还是原来的地址,所以要先清除后再执行xmake
编译。
然后可以通过生成反汇编文件
查看程序链接地址修改是否正常
反汇编:
Disassembly of section .isr_vector:
0800b000 <.isr_vector>:
800b000: 20005000 andcs r5, r0, r0
800b004: 0800c541 stmdaeq r0, {r0, r6, r8, sl, lr, pc}
800b008: 0800d4d1 stmdaeq r0, {r0, r4, r6, r7, sl, ip, lr, pc}
800b00c: 0800d4d3 stmdaeq r0, {r0, r1, r4, r6, r7, sl, ip, lr, pc}
可以看到中断向量地址已经从0800b000
开始,说明设置成功。
1、重定向printf
usart_printf.c:
#include "stm32f1xx_hal.h"
#include "usart.h"
int _write(int fd, char *buf, int size)
{
for (int i = 0; i < size; i++)
{
while ((USART1->SR & 0X40) == 0); /* wait finised */
USART1->DR = (uint8_t)buf[i]; /* send data */
}
return size;
}
2、自己编写printf
void myprintf(const char *format, ...)
{
char str[256] = {0};
va_list v_args;
va_start(v_args, format);
(void)vsnprintf((char *)&str[0],
(size_t ) sizeof(str),
(char const *) format,
v_args);
va_end(v_args);
usart1Write((char *)str, strlen(str));
}
重定向串口发现bin程序尺寸已经涨了58KB,后经过搜索解决:
--specs=nano.specs
,编译器会使用newlib_nano
库, newlib_nano
应该是类似MDK micro Lib的一个东西,编译完bin文件尺寸已经降到40KB。除了构建APP工程,还构建了Bootloader工程,测试从Bootloader程序跳转到APP程序都没问题。
使用arm-none-eabi-gcc的缺点: