linux 下 VSCODE 使用CMake编译STM32程序
项目在做什么
- 本项目是为了研究MCU在linux下开发而做的
--build 存放cmake编译生成的文件
--cmake 存放cmake编译时会用到的文件,比如工具链检查、编译选项等
--prj windows下kei工程的工程文件
--src 源码
- 本项目中大量的CMakeLists.txt的写法参考了LoRa-Node
目前项目已经初步能够运行了
使用的组件
- VSCODE -> 程序员使用的文本编辑器
- cmake -> 组织编译逻辑
- arm-none-eabi --> 编译,生成elf,bin,hex
- JLinkGDBServer -> GDB 服务器
- cortex-debug -> 用来调试程序
我的环境
jk@jk:~$ sudo lsb_release -a
[sudo] jk 的密码:
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.2 LTS
Release: 18.04
Codename: bionic
至此,需要的组件就罗列清除了,下面来讲下怎么安装
组件安装
VSCODE
官网瞎下载安装即可,每什么可讲的,记得安装最新版
CMake(需要>3.6)
jk@jk:~$ cmake -version
cmake version 3.10.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
安装方法:
- Ubuntu 16.04/ Linux Mint 18: Since the official repository version is too old, one can use e.g. PPA
- Linux Arch:
pacman -S cmake
arm-none-eabi
- GNU ARM-Toolchain
- GNU/Linux:
- Ubuntu 16.04/ Linux Mint 18: Since the official repository version is too old, one can use e.g. PPA
- Ubuntu 18.04: the toolchain has been updated but there is a bug with
libnewlibcausing the linker to fail.sudo apt install gcc-arm-none-eabi - Linux Arch:
pacman -S arm-none-eabi-gcc arm-none-eabi-newlib
JLinkGDBServer
jk@jk:~$ JLinkGDBServer -version
SEGGER J-Link GDB Server V6.48b Command Line Version
JLinkARM.dll V6.48b (DLL compiled Aug 2 2019 10:20:19)
去官网下载:JLinkGDBServer
我下载的是deb格式,使用dpkg -i安装即可
cortex-debug
VSCODE 里面搜索cortex-debug 安装即可
至此,安装就完成了
思路
首先,我们来看main函数
/**
* Main application entry point.
*/
int main( void )
{
board_init();
uart1.rx_complete_callback = uartCallback;
while(1)
{
HAL_UART_SendBytes((uint8_t*)"hello world\r\n",sizeof("hello world\r\n"));
DelayMs(5000);
}
}
这个程序就是将硬件初始化,然后5s打印一次"Hello World\r\n"
也就是说这个程序主要分为三个部分:
- main
- 驱动
- MCU HAL 库
我们来看一下源码结构,也可以得出结论
jk@jk:~/programe/stm32-linux-cmake$ tree -d -L 2 src
src
├── apps
└── boards
├── driver
└── stm32
其中:
apps中存放的就是main.c文件
boards中存放的是硬件部分
boards.driver存放的是硬件的驱动
boards.stm32中存放的就是stm32的HAL库的代码
所以,我的思路是:
- app/boards.driver/boards.stm32这三部分分别生成三个target,最后由这三个target生成exe
实现
AS WE KNOWN
编译需要指定.c文件,编译.c文件时由于多函数跨文件调用是通过头文件进行的,所以需要找寻头文件,当头文件找不到时就无法调用指定函数
将.c文件添加到指定target的方法,我这里用了两种,两种方式都可以达到一样的效果
一个个添加
list(APPEND ${PROJECT_NAME}_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/main.c"
)
添加指定文件夹下的所有c文件
file(GLOB ${PROJECT_NAME}_SOURCES "${CMAKE_CURRENT_LIST_DIR}/*.c")
将头文件路径添加倒target路径,是通过cmake的target_include_directories()方法,其中,我们可以通过${CMAKE_CURRENT_SOURCE_DIR},直接添加目录,但有时候,我们需要添加别的target的头文件,此时可以用表达式去获取target的头文件,比如
1. $<TARGET_PROPERTY:drivers,INTERFACE_INCLUDE_DIRECTORIES>
通过这个表达式可以获取到在drivers这个target中添加的头文件
CMake的用法还有很多,太灵活了,我这写的也只是冰山一角,后面还要继续努力
干活
编译程序
在项目的根目录建立CMakeLists.txt,将apps,boards.driver,boards.stm32三个subdirectory分别导入,并在这三个文件夹中写好分别的CMakeLists.txt
我们分别将三个target命名为
- app -->project(app)
- drivers -->project(drivers)
- stm32l051 -->project(stm32l051)
并在其中添加好各自target的.c文件和头文件,具体见源码
ok之后,CMake文件就编写完了
我们需要执行
- mkdir build
- cd build
- cmake -DCMAKE_TOOLCHAIN_FILE="cmake/toolchain-arm-none-eabi.cmake" ..
PS:
- 在根目录生成build文件夹,这是为了方便我们管理,后续如果要删除编译的产物,直接删除build文件夹即可,也可以防止编译的产物污染代码
- Makefile生成成功提示如下:
jk@jk:~/programe/stm32-linux-cmake$ ./configure
-- The C compiler identification is GNU 8.3.1
-- The CXX compiler identification is GNU 8.3.1
-- Check for working C compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc
-- Check for working C compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-g++
-- Check for working CXX compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-g++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
Linker script: /home/jk/programe/stm32-linux-cmake/src/boards/stm32/cmsis/arm-gcc/stm32l051xx_flash.ld
-- The ASM compiler identification is GNU
-- Found assembler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jk/programe/stm32-linux-cmake/build
执行make,编译程序
jk@jk:~/programe/stm32-linux-cmake/build$ make
Scanning dependencies of target app
[ 3%] Building C object src/apps/CMakeFiles/app.dir/main.c.obj
[ 3%] Built target app
Scanning dependencies of target stm32l051
[ 6%] Building ASM object src/boards/stm32/CMakeFiles/stm32l051.dir/cmsis/arm-gcc/startup_stm32l051xx.s.obj
[ 9%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/cmsis/system_stm32l0xx.c.obj
[ 12%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal.c.obj
[ 16%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc.c.obj
[ 19%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc_ex.c.obj
[ 22%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_cortex.c.obj
[ 25%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_dma.c.obj
[ 29%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash.c.obj
[ 32%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex.c.obj
[ 35%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_gpio.c.obj
[ 38%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c.c.obj
[ 41%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr.c.obj
[ 45%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr_ex.c.obj
[ 48%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc.c.obj
[ 51%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc_ex.c.obj
[ 54%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc.c.obj
[ 58%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc_ex.c.obj
[ 61%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_spi.c.obj
[ 64%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c.obj
[ 67%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart_ex.c.obj
[ 67%] Built target stm32l051
Scanning dependencies of target drivers
[ 70%] Building C object src/boards/driver/CMakeFiles/drivers.dir/board.c.obj
[ 74%] Building C object src/boards/driver/CMakeFiles/drivers.dir/delay.c.obj
[ 77%] Building C object src/boards/driver/CMakeFiles/drivers.dir/gpio-board.c.obj
[ 80%] Building C object src/boards/driver/CMakeFiles/drivers.dir/gpio.c.obj
[ 83%] Building C object src/boards/driver/CMakeFiles/drivers.dir/key_board.c.obj
[ 87%] Building C object src/boards/driver/CMakeFiles/drivers.dir/led_board.c.obj
[ 90%] Building C object src/boards/driver/CMakeFiles/drivers.dir/stm32l0xx_hal_msp.c.obj
[ 93%] Building C object src/boards/driver/CMakeFiles/drivers.dir/stm32l0xx_it.c.obj
[ 96%] Building C object src/boards/driver/CMakeFiles/drivers.dir/uart_board.c.obj
[ 96%] Built target drivers
Scanning dependencies of target arm_minisys
[100%] Linking C executable arm_minisys
text data bss dec hex filename
14988 12 400 15400 3c28 arm_minisys
[100%] Built target arm_minisys
Scanning dependencies of target arm_minisys.hex
[100%] Built target arm_minisys.hex
Scanning dependencies of target arm_minisys.bin
[100%] Built target arm_minisys.bin
至此,程序编译完成
配置VSCODE
- 配置launch.json (应以调试)
- 配置c_cpp_properties.json(用于编写,阅读代码)
此处我使用的是JLinkGDBServer,是因为之前使用openocd进行调试时总是出现问题,而用JLinkGDBServer则没发现什么问题
launch.json
不讲了,自己看配置文件吧
c_cpp_properties.json
之前没有仔细配置时,总是在代码编辑器的右边出现红色的错误提示,很是难受,配完之后,这些错误提示都消失了,就舒服了。
下面我讲一下其中重的部分:
includePath,这个下面一定要靶所有的头文件的路径都包含进去,不然找不到头文件,就会出现波浪线的错误提示了,可以使用**的用法,来将目录下的所有文件都导入
"includePath": [
"${workspaceFolder}/src/**",
"/home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/arm-none-eabi/include/**"
],
defines,需要把程序中使用的宏添加到此处,否则编辑器对预编译宏做的代码开关也是没法正确识别,例如:
"defines": [
"STM32L051xx",
"USE_HAL_DRIVER"
],
compilerPath,这个填写正确的gcc路径,否则也是有奇奇怪怪的错误
最后的注意事项
- 当CMake config/generate失败的时候,可以尝试将build文件夹删除,重新进行,可能会成功
- 因为此处我是通过传递工具链文件的方式来传递工具链给CMake的,指令有些长,且难记,为了方便,我将指令做成了config文件,在${ROOT}下有个config文件,这样,后面只要执行./config就可以生成Makefile文件了
- 代码结构要清晰,要尽量接耦,否则CMakeLists.txt文件编写时会互相调用,显得不整洁
感谢大家,有问题欢迎大家指正
linux 下 VSCODE 使用CMake编译STM32程序的更多相关文章
- Linux下通过源码编译安装程序
本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...
- Linux下通过源码编译安装程序(configure/make/make install的作用,然后在/etc/profile文件里修改PATH环境变量)
一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件:就是通常我们见到的lib目录下的文件 配置文件:这个不必多说,都知道 帮助文档:通常是我们在 ...
- [转]Caffe在Linux下的安装,编译,实验
Caffe在Linux下的安装,编译,实验 原文地址:http://www.cnblogs.com/evansyang/p/6150118.html 第一部分:Caffe 简介 caffe是有伯克利 ...
- Linux下简单的取点阵字模程序
源:Linux下简单的取点阵字模程序 Linux操作系统下进行简单的图形开发,经常会用到取字模的软件,但是Linux并没有像Windows下的小工具可用,我们也并不希望为了取字模而频繁地切换操作系统. ...
- Linux下使用Eclipse开发Hadoop应用程序
在前面一篇文章中介绍了如果在完全分布式的环境下搭建Hadoop0.20.2,现在就再利用这个环境完成开发. 首先用hadoop这个用户登录linux系统(hadoop用户在前面一篇文章中创建的),然后 ...
- Linux下librdkafka客户端的编译运行
Linux下librdkafka客户端的编译运行 librdkafka是一个开源的Kafka客户端C/C++实现,提供了Kafka生产者.消费者接口. 由于项目需要,我要将Kafka生产者接口封装起来 ...
- 【转】在嵌入式Linux和PC机Linux下使用popen函数时,程序运行结果有差异。
下面程序演示了在嵌入式Linux和PC机Linux下使用popen函数时,程序的运行结果是有差异的. 两个程序 atest.c 和 btest.c,atest 检查是否有 btest 进程运行,如果没 ...
- linux下,一个运行中的程序,究竟占用了多少内存
linux下,一个运行中的程序,究竟占用了多少内存 1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中 VSZ(或VSS)列 表示,程序占用 ...
- Linux下FFmpeg的安装编译过程【转】
本文转载自:http://www.linuxidc.com/Linux/2013-06/85628.htm 详细说下在Linux下FFmpeg的安装编译过程.参考 Ubuntu 10.04安装编译FF ...
随机推荐
- 软件测试必须掌握的linux命令大全
测试工程师的四大基础技能:数据库.linux.网络协议.测试工具,不管是刚入门还是已经工作多年,这几个方向都是要掌握的.今天我们再讲一下测试工程师必须要掌握的linux命令. 测试工程师需要掌握lin ...
- 个人永久性免费-Excel催化剂功能第104波-批量选择多种类型的图形对象
在Excel的日常操作过程中,选择绝对是一个高频的操作,之前开发过一些快速选择单元格区域的辅助功能,除了单元格区域,Excel强大之处在于,类似PhotoShop那般可以存放多种图形,并且有图层先后顺 ...
- cron 表达式的格式 了解
cron 表达式的格式 Quartz cron 表达式的格式十分类似于 UNIX cron 格式,但还是有少许明显的区别.区别之一就是 Quartz 的格式向下支持到秒级别的计划,而 UNIX cro ...
- C#3.0新增功能06 对象和集合初始值设定项
连载目录 [已更新最新开发文章,点击查看详细] 使用 C# 可以在单条语句中实例化对象或集合并执行成员分配. 对象初始值设定项 使用对象初始值设定项,你可以在创建对象时向对象的任何可访问字段或属 ...
- 从后端到前端之Vue(三)小结以及一颗真实的大树
上一篇写了一下tab,下面整理一下用过的知识点,本想按照官网的文档,整理一下可以更清晰,结果也许是我的方法不对吧,总之更模糊了. 按照官网文档的顺序整理到了表单输入绑定之前,因为之前大致也就只涉及到这 ...
- PHP--数据库访问(增、删、改、查)
练习通过数据库查询一个表,操作这个表的增.删.改.查的功能! 一.主页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...
- 配置 IDEA 远程连接应用服务器
当调试 Web 应用时,经常需要使用 ide 远程连接,来进行 debug 调试.使用 Springboot 内置服务器和使用 Tomcat 服务器是常见的应用部署方式,可以用不同的配置方式来启动远程 ...
- 2019前端面试系列——Vue面试题
Vue 双向绑定原理 mvvm 双向绑定,采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter.getter,在数 ...
- Keil uVision4 ——如何新建一个项目
一.打开Keil4软件,点击Project,再点击New μVision Projrct. 二.新建一个文件夹,并在里面输入这个项目的名字. 三.点击Intel,根据实际情况选择,这里选择的是80/8 ...
- hdoj 4715 Difference Between Primes 素数筛选+二分查找
#include <string.h> #include <stdio.h> const int maxn = 1000006; bool vis[1000006]; int ...