项目在做什么

项目地址

  1. 本项目是为了研究MCU在linux下开发而做的
  1. --build 存放cmake编译生成的文件
  2. --cmake 存放cmake编译时会用到的文件,比如工具链检查、编译选项等
  3. --prj windowskei工程的工程文件
  4. --src 源码
  1. 本项目中大量的CMakeLists.txt的写法参考了LoRa-Node

目前项目已经初步能够运行了

使用的组件

  1. VSCODE -> 程序员使用的文本编辑器
  2. cmake -> 组织编译逻辑
  3. arm-none-eabi --> 编译,生成elf,bin,hex
  4. JLinkGDBServer -> GDB 服务器
  5. cortex-debug -> 用来调试程序

我的环境

  1. jk@jk:~$ sudo lsb_release -a
  2. [sudo] jk 的密码:
  3. No LSB modules are available.
  4. Distributor ID: Ubuntu
  5. Description: Ubuntu 18.04.2 LTS
  6. Release: 18.04
  7. Codename: bionic

至此,需要的组件就罗列清除了,下面来讲下怎么安装

组件安装

VSCODE

官网瞎下载安装即可,每什么可讲的,记得安装最新版

CMake(需要>3.6)

  1. jk@jk:~$ cmake -version
  2. cmake version 3.10.2
  3. 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 libnewlib causing the linker to fail. sudo apt install gcc-arm-none-eabi
    • Linux Arch: pacman -S arm-none-eabi-gcc arm-none-eabi-newlib

JLinkGDBServer

  1. jk@jk:~$ JLinkGDBServer -version
  2. SEGGER J-Link GDB Server V6.48b Command Line Version
  3. JLinkARM.dll V6.48b (DLL compiled Aug 2 2019 10:20:19)

去官网下载:JLinkGDBServer

我下载的是deb格式,使用dpkg -i安装即可

cortex-debug

VSCODE 里面搜索cortex-debug 安装即可

至此,安装就完成了

思路

首先,我们来看main函数

  1. /**
  2. * Main application entry point.
  3. */
  4. int main( void )
  5. {
  6. board_init();
  7. uart1.rx_complete_callback = uartCallback;
  8. while(1)
  9. {
  10. HAL_UART_SendBytes((uint8_t*)"hello world\r\n",sizeof("hello world\r\n"));
  11. DelayMs(5000);
  12. }
  13. }

这个程序就是将硬件初始化,然后5s打印一次"Hello World\r\n"

也就是说这个程序主要分为三个部分:

  • main
  • 驱动
  • MCU HAL 库

我们来看一下源码结构,也可以得出结论

  1. jk@jk:~/programe/stm32-linux-cmake$ tree -d -L 2 src
  2. src
  3. ├── apps
  4. └── boards
  5. ├── driver
  6. └── stm32

其中:

  • apps中存放的就是main.c文件

  • boards中存放的是硬件部分

    • boards.driver存放的是硬件的驱动

    • boards.stm32中存放的就是stm32的HAL库的代码

所以,我的思路是:

  • app/boards.driver/boards.stm32这三部分分别生成三个target,最后由这三个target生成exe

实现

AS WE KNOWN

  1. 编译需要指定.c文件,编译.c文件时由于多函数跨文件调用是通过头文件进行的,所以需要找寻头文件,当头文件找不到时就无法调用指定函数

  2. 将.c文件添加到指定target的方法,我这里用了两种,两种方式都可以达到一样的效果

    1. 一个个添加

      1. list(APPEND ${PROJECT_NAME}_SOURCES
      2. "${CMAKE_CURRENT_SOURCE_DIR}/main.c"
      3. )
    2. 添加指定文件夹下的所有c文件

      1. file(GLOB ${PROJECT_NAME}_SOURCES "${CMAKE_CURRENT_LIST_DIR}/*.c")
  3. 将头文件路径添加倒target路径,是通过cmake的target_include_directories()方法,其中,我们可以通过${CMAKE_CURRENT_SOURCE_DIR},直接添加目录,但有时候,我们需要添加别的target的头文件,此时可以用表达式去获取target的头文件,比如

    1. 1. $<TARGET_PROPERTY:drivers,INTERFACE_INCLUDE_DIRECTORIES>

    通过这个表达式可以获取到在drivers这个target中添加的头文件

  4. CMake的用法还有很多,太灵活了,我这写的也只是冰山一角,后面还要继续努力

干活

编译程序

  1. 在项目的根目录建立CMakeLists.txt,将apps,boards.driver,boards.stm32三个subdirectory分别导入,并在这三个文件夹中写好分别的CMakeLists.txt

  2. 我们分别将三个target命名为

    • app -->project(app)
    • drivers -->project(drivers)
    • stm32l051 -->project(stm32l051)
  3. 并在其中添加好各自target的.c文件和头文件,具体见源码

  4. ok之后,CMake文件就编写完了

  5. 我们需要执行

    • mkdir build
    • cd build
    • cmake -DCMAKE_TOOLCHAIN_FILE="cmake/toolchain-arm-none-eabi.cmake" ..

    PS:

    • 在根目录生成build文件夹,这是为了方便我们管理,后续如果要删除编译的产物,直接删除build文件夹即可,也可以防止编译的产物污染代码
    • Makefile生成成功提示如下:
    1. jk@jk:~/programe/stm32-linux-cmake$ ./configure
    2. -- The C compiler identification is GNU 8.3.1
    3. -- The CXX compiler identification is GNU 8.3.1
    4. -- Check for working C compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc
    5. -- Check for working C compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc -- works
    6. -- Detecting C compiler ABI info
    7. -- Detecting C compiler ABI info - done
    8. -- Detecting C compile features
    9. -- Detecting C compile features - done
    10. -- Check for working CXX compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-g++
    11. -- Check for working CXX compiler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-g++ -- works
    12. -- Detecting CXX compiler ABI info
    13. -- Detecting CXX compiler ABI info - done
    14. -- Detecting CXX compile features
    15. -- Detecting CXX compile features - done
    16. Linker script: /home/jk/programe/stm32-linux-cmake/src/boards/stm32/cmsis/arm-gcc/stm32l051xx_flash.ld
    17. -- The ASM compiler identification is GNU
    18. -- Found assembler: /home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/bin/arm-none-eabi-gcc
    19. -- Configuring done
    20. -- Generating done
    21. -- Build files have been written to: /home/jk/programe/stm32-linux-cmake/build
  6. 执行make,编译程序

    1. jk@jk:~/programe/stm32-linux-cmake/build$ make
    2. Scanning dependencies of target app
    3. [ 3%] Building C object src/apps/CMakeFiles/app.dir/main.c.obj
    4. [ 3%] Built target app
    5. Scanning dependencies of target stm32l051
    6. [ 6%] Building ASM object src/boards/stm32/CMakeFiles/stm32l051.dir/cmsis/arm-gcc/startup_stm32l051xx.s.obj
    7. [ 9%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/cmsis/system_stm32l0xx.c.obj
    8. [ 12%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal.c.obj
    9. [ 16%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc.c.obj
    10. [ 19%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_adc_ex.c.obj
    11. [ 22%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_cortex.c.obj
    12. [ 25%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_dma.c.obj
    13. [ 29%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash.c.obj
    14. [ 32%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_flash_ex.c.obj
    15. [ 35%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_gpio.c.obj
    16. [ 38%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_i2c.c.obj
    17. [ 41%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr.c.obj
    18. [ 45%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_pwr_ex.c.obj
    19. [ 48%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc.c.obj
    20. [ 51%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rcc_ex.c.obj
    21. [ 54%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc.c.obj
    22. [ 58%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_rtc_ex.c.obj
    23. [ 61%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_spi.c.obj
    24. [ 64%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart.c.obj
    25. [ 67%] Building C object src/boards/stm32/CMakeFiles/stm32l051.dir/mcu/stm32/STM32L0xx_HAL_Driver/Src/stm32l0xx_hal_uart_ex.c.obj
    26. [ 67%] Built target stm32l051
    27. Scanning dependencies of target drivers
    28. [ 70%] Building C object src/boards/driver/CMakeFiles/drivers.dir/board.c.obj
    29. [ 74%] Building C object src/boards/driver/CMakeFiles/drivers.dir/delay.c.obj
    30. [ 77%] Building C object src/boards/driver/CMakeFiles/drivers.dir/gpio-board.c.obj
    31. [ 80%] Building C object src/boards/driver/CMakeFiles/drivers.dir/gpio.c.obj
    32. [ 83%] Building C object src/boards/driver/CMakeFiles/drivers.dir/key_board.c.obj
    33. [ 87%] Building C object src/boards/driver/CMakeFiles/drivers.dir/led_board.c.obj
    34. [ 90%] Building C object src/boards/driver/CMakeFiles/drivers.dir/stm32l0xx_hal_msp.c.obj
    35. [ 93%] Building C object src/boards/driver/CMakeFiles/drivers.dir/stm32l0xx_it.c.obj
    36. [ 96%] Building C object src/boards/driver/CMakeFiles/drivers.dir/uart_board.c.obj
    37. [ 96%] Built target drivers
    38. Scanning dependencies of target arm_minisys
    39. [100%] Linking C executable arm_minisys
    40. text data bss dec hex filename
    41. 14988 12 400 15400 3c28 arm_minisys
    42. [100%] Built target arm_minisys
    43. Scanning dependencies of target arm_minisys.hex
    44. [100%] Built target arm_minisys.hex
    45. Scanning dependencies of target arm_minisys.bin
    46. [100%] Built target arm_minisys.bin
  7. 至此,程序编译完成

配置VSCODE

  • 配置launch.json (应以调试)
  • 配置c_cpp_properties.json(用于编写,阅读代码)

此处我使用的是JLinkGDBServer,是因为之前使用openocd进行调试时总是出现问题,而用JLinkGDBServer则没发现什么问题

launch.json

不讲了,自己看配置文件吧

c_cpp_properties.json

之前没有仔细配置时,总是在代码编辑器的右边出现红色的错误提示,很是难受,配完之后,这些错误提示都消失了,就舒服了。

下面我讲一下其中重的部分:

  1. includePath,这个下面一定要靶所有的头文件的路径都包含进去,不然找不到头文件,就会出现波浪线的错误提示了,可以使用**的用法,来将目录下的所有文件都导入

    1. "includePath": [
    2. "${workspaceFolder}/src/**",
    3. "/home/jk/cross-tool/gcc-arm-none-eabi-8-2019-q3-update/arm-none-eabi/include/**"
    4. ],
  2. defines,需要把程序中使用的宏添加到此处,否则编辑器对预编译宏做的代码开关也是没法正确识别,例如:

    1. "defines": [
    2. "STM32L051xx",
    3. "USE_HAL_DRIVER"
    4. ],
  3. compilerPath,这个填写正确的gcc路径,否则也是有奇奇怪怪的错误

最后的注意事项

  1. 当CMake config/generate失败的时候,可以尝试将build文件夹删除,重新进行,可能会成功
  2. 因为此处我是通过传递工具链文件的方式来传递工具链给CMake的,指令有些长,且难记,为了方便,我将指令做成了config文件,在${ROOT}下有个config文件,这样,后面只要执行./config就可以生成Makefile文件了
  3. 代码结构要清晰,要尽量接耦,否则CMakeLists.txt文件编写时会互相调用,显得不整洁

感谢大家,有问题欢迎大家指正

linux 下 VSCODE 使用CMake编译STM32程序的更多相关文章

  1. Linux下通过源码编译安装程序

    本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...

  2. Linux下通过源码编译安装程序(configure/make/make install的作用,然后在/etc/profile文件里修改PATH环境变量)

    一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件:就是通常我们见到的lib目录下的文件 配置文件:这个不必多说,都知道 帮助文档:通常是我们在 ...

  3. [转]Caffe在Linux下的安装,编译,实验

    Caffe在Linux下的安装,编译,实验  原文地址:http://www.cnblogs.com/evansyang/p/6150118.html 第一部分:Caffe 简介 caffe是有伯克利 ...

  4. Linux下简单的取点阵字模程序

    源:Linux下简单的取点阵字模程序 Linux操作系统下进行简单的图形开发,经常会用到取字模的软件,但是Linux并没有像Windows下的小工具可用,我们也并不希望为了取字模而频繁地切换操作系统. ...

  5. Linux下使用Eclipse开发Hadoop应用程序

    在前面一篇文章中介绍了如果在完全分布式的环境下搭建Hadoop0.20.2,现在就再利用这个环境完成开发. 首先用hadoop这个用户登录linux系统(hadoop用户在前面一篇文章中创建的),然后 ...

  6. Linux下librdkafka客户端的编译运行

    Linux下librdkafka客户端的编译运行 librdkafka是一个开源的Kafka客户端C/C++实现,提供了Kafka生产者.消费者接口. 由于项目需要,我要将Kafka生产者接口封装起来 ...

  7. 【转】在嵌入式Linux和PC机Linux下使用popen函数时,程序运行结果有差异。

    下面程序演示了在嵌入式Linux和PC机Linux下使用popen函数时,程序的运行结果是有差异的. 两个程序 atest.c 和 btest.c,atest 检查是否有 btest 进程运行,如果没 ...

  8. linux下,一个运行中的程序,究竟占用了多少内存

    linux下,一个运行中的程序,究竟占用了多少内存 1. 在linux下,查看一个运行中的程序, 占用了多少内存, 一般的命令有 (1). ps aux: 其中  VSZ(或VSS)列 表示,程序占用 ...

  9. Linux下FFmpeg的安装编译过程【转】

    本文转载自:http://www.linuxidc.com/Linux/2013-06/85628.htm 详细说下在Linux下FFmpeg的安装编译过程.参考 Ubuntu 10.04安装编译FF ...

随机推荐

  1. HiLoGenerator生成id

    using System.Linq; namespace Product.Host { public class HiLoGenerator { ; ; ; private object Sequen ...

  2. 正则与sed,grep,awk三剑客

    系统登录顺序: /etc/profile /etc/profile.d/a.sh (a.sh自己建的) /root/.bash_profile /root/.bashrc /etc/bashrc /b ...

  3. IntelliJ IDEA 2019.2最新解读:性能更好,体验更优,细节处理更完美!

    idea 2019.2 准备 idea 2019.2正式版是在2019年7月24号发布的,本篇文章,我将根据官方博客以及自己的理解来进行说明,总体就是:性能更好,体验更优,细节处理更完美! 支持jdk ...

  4. python输出九九乘法表

    1.脚本如下 (1)倒三角格式的,注意行前的空格 for i in range(1,10):     for j in range(i,10):          print("%d*%d= ...

  5. css清除select默认的样式

    select在firefox与chrome的显示是不一样的,我们一般选择通过css清除掉css的默认样式,然后再增添自定义的样式来解决,css我们一般用这么几行代码来清除默认样式: 1 select ...

  6. 搭建PowerDNS+LAP+NFS+MySQL主从半节点同步实现LAMP架构

    实验环境:(共7台机器) PowerDNS: 192.168.99.110    两台LAP: 192.168.99.120 和 192.168.99.130 NFS服务器:192.168.99.14 ...

  7. 【iOS】代码片段库

    若在某个 Objective-C 的实现文件中输入 init,Xcode 会自动列出一系列备选项,如图所示: Xcode 自动加入的这段代码源自代码片段库(code snippet library), ...

  8. Android Studio 蓝牙开发实例——基于Android 6.0

    因项目需要做一个Android 的蓝牙app来通过手机蓝牙传输数据以及控制飞行器,在此,我对这段时间里写的蓝牙app的代码进行知识梳理和出现错误的总结. 该应用的Compile Sdk Version ...

  9. 以太坊RLPx传输协议

    本文主要内容翻译自:The RLPx Transport Protocol,其中添加了一些个人的理解,由于密码学水平有限,不正确之处望指正.另外原文可能已经更新,最新内容请直接阅读原文. 本文档定义了 ...

  10. Linux基础文件权限

    一.基本权限 文件权限设置: 可以赋于某个用户或组 能够以何种方式 访问某个文件 权限对象:属主: u属组: g其他人: o 基本权限类型:读:r 4写:w 2执行: x 1 rwx rw- r-- ...