stm32开发新方式-platformio

platformio,这个强大的嵌入式开发平台当然也提供了stm32的支持,本文尝试在platformio开发平台上开发stm32。

如果您不喜欢使用CLI(命令行)的stm32开发方式,可以阅读文章stm32开发新方式——platformio的IDE,也许你会得到惊喜!

测试环境:

  1. macOS
  2. stm32f103c8t6最小系统板
  3. st-link v2

新建pio工程

  • 创建工程文件夹并进入:

    mkdir test && cd test
    
  • 查找自己适合的板子

    pio boards
    

    会看到以下结果,十里这里选择genericSTM32F103C8,这里执行这个命令,主要是查找对应自己最小系统板的board ID:

    ...
    disco_l152rb          STM32L152RBT6  32Mhz     128kB   16kB   ST STM32LDISCOVERY
    disco_f100rb          STM32F100RBT6  24Mhz     128kB   8kB    ST STM32VLDISCOVERY
    genericSTM32F103C8    STM32F103C8    72Mhz     64kB    20kB   STM32F103C8 (20k RAM. 64k Flash)
    genericSTM32F103CB    STM32F103CB    72Mhz     128kB   20kB   STM32F103CB (20k RAM. 128k Flash)
    genericSTM32F103R8    STM32F103R8    72Mhz     64kB    20kB   STM32F103R8 (20k RAM. 64k Flash)
    genericSTM32F103RB    STM32F103RB    72Mhz     128kB   20kB   STM32F103RB (20k RAM. 128k Flash)
    genericSTM32F103RC    STM32F103RC    72Mhz     256kB   48kB   STM32F103RC (48k RAM. 256k Flash)
    genericSTM32F103RE    STM32F103RE    72Mhz     512kB   64kB   STM32F103RE (64k RAM. 512k Flash)
    ...
    
  • 初始化工程,以vim作为IDE:

    pio init --ide vim -b genericSTM32F103C8
    
  • 新建Makefile,添加以下内容(这里注意缩进问题):

    all:
      platformio -f -c vim run
    upload:
      platformio -f -c vim run --target upload
    clean:
      platformio -f -c vim run --target clean
    program:
      platformio -f -c vim run --target program
    uploadfs:
      platformio -f -c vim run --target uploadfs
    update:
      platformio -f -c vim update
    
  • 配置platformio.ini文件 因为我们这里使用stlink v2,所以需要将程序上传方式定为stlink,默认生成的工程使用arduino框架,这是玩过Arduino的网友的福音,不是吗?只需添加一行指定程序上传方式,最终内容如下:

    [env:genericSTM32F103C8]
    platform = ststm32
    board = genericSTM32F103C8
    framework = arduino
    upload_protocol = stlink
    

upload_protocol = stlink 可以省略。

添加代码

添加点灯代码,十里的最小系统板上LED对应于管脚PB0,所以在src目录下添加main.cpp的内容如下:

#include <Arduino.h>

void setup() {
    pinMode(PB0, OUTPUT);
}

void loop() {
    digitalWrite(PB0, HIGH);
    delay(500);
    digitalWrite(PB0, LOW);
    delay(500);
}

编译一下,编译的时候会下载stm32平台开发需要的编译工具和相关框架,你能做的就是waiting…:

$ test make all
platformio -f -c vim run
[Wed Nov  8 09:42:57 2017] Processing genericSTM32F103C8 
(upload_protocol: stlink; platform: ststm32; board: genericSTM32F103C8; framework: arduino)
--------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
Collected 27 compatible libraries
Looking for dependencies...
No dependencies
Linking .pioenvs/genericSTM32F103C8/firmware.elf
Calculating size .pioenvs/genericSTM32F103C8/firmware.elf
text	   data	    bss	    dec	    hex	filename
6484	   1936	    312	   8732	   221c	.pioenvs/genericSTM32F103C8/firmware.elf
================================ [SUCCESS] Took 1.55 seconds =====================================

上传程序

因为前面已经配置了程序上传方式为stlink,所以将stlink连接最小系统板和mac就可以执行上传了,这里也会下载相应的下载工具,waiting … :

$ make upload

正常的话就会看到命令行窗口打印上传过程的信息。但也可能会遇到下面类似的问题:

$ test make upload
platformio -f -c vim run --target upload
[Wed Nov  8 09:50:10 2017] Processing genericSTM32F103C8 
(upload_protocol: stlink; platform: ststm32; board: genericSTM32F103C8; framework: arduino)
------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
Collected 27 compatible libraries
Looking for dependencies...
No dependencies
Linking .pioenvs/genericSTM32F103C8/firmware.elf
Checking program size
text	   data	    bss	    dec	    hex	filename
6484	   1936	    312	   8732	   221c	.pioenvs/genericSTM32F103C8/firmware.elf
Uploading .pioenvs/genericSTM32F103C8/firmware.bin
2017-11-08T09:50:11 INFO src/common.c: Loading device parameters....
2017-11-08T09:50:11 WARN src/common.c: unknown chip id! 0xe0042000
st-flash 1.3.1
*** [upload] Error 255
====================================== [ERROR] Took 1.53 seconds ======================================
make: *** [upload] Error 1

有一个临时的解决方法,将板上的BOOT0VDD短接,复位一下最小系统板,会进入boot模式,此时执行make upload,程序会同时烧写在flash和内存上,一旦复位内存上的程序会消失,如果BOOT0还是接VDD的话还会进入boot模式,此时程序已经没了,但是flash 中仍然存在,所以只需将BOOT0短接GND再复位一下,板子就从flash启动了,所以最终程序调试方法为:

调试程序:BOOT0短接VDD,每次上传程序先复位板子,然后执行make upload;不进行调试的话,先以调试程序的方式上传程序,然后短接BOOT0GND,复位一下板子,板子会从flash启动运行固化的程序。

上述问题本来不该出现,后来发现原来是我的usb hub有问题,我直接将stlink v2连接到macbook上是没有上述问题的。

调试程序

MCU开发过程中有可能会遇到比较棘手的问题,所以硬件调试是少不了的。如果是第一次建立这个stm的PIO工程,在上面编译过程中就会下载stm32单片机开发需要的编译工具和调试工具。

调试配置

免费版的PIO有所限制,不支持stm32硬件调试,但我们可以自己进行简单配置,搭建硬件调试的快捷方式:

  1. 添加必要的编译选项

    platformio.ini 文件中添加以下内容:

    build_flags = 
        -g
    

    添加这个参数项,是为了编译生成调试需要的符号项,比如变量名、函数名等。

  2. 添加调试相关的Make快捷命令

    Makefile 中添加以下代码:

    debug:
        arm-none-eabi-gdb .pioenvs/genericSTM32F103C8/firmware.elf
    
    server:
        openocd -f interface/stlink.cfg -f target/stm32f1x.cfg > .dblog
    
    • server 命令:用于开启 openocd 调试服务,指明了使用 stlink 调试 stm32f1x 系列芯片^[系统环境变量中已添加openocd的路径(export PATH="/Users/5km/.platformio/packages/tool-openocd/bin:$PATH"),调用 openocd 的时候会先从其相对路径下查找指定的配置文件,所以这里可以使用配置文件的相对路径,比如interface/stlink.cfg。关于openocd的使用参考OpenOCD User’s Guide。];
    • debug 命令:用于开启gdb进行调试,指明了 .pioenvs/genericSTM32F103C8/firmware.elf 为可执行调试文件^[这里调用了 arm-none-eabi-gdb 这个是 arm 芯片的交叉编译链工具集中的调试命令,这里直接调用,是因为工具集路径已经添加到环境变量中了];
  3. 添加gdb初始化文件

    工程根目录下添加文件 .gdbinit,内容如下:

    target extended-remote localhost:3333
    monitor reset halt
    load
    break main
    continue
    

    上述内容,会在开启调试命令后执行,首先连接本地已经开始的 openocd 调试服务,复位待调试硬件,加载可执行文件(这里是elf文件),然后在程序入口 main函数 处打断点,最后执行程序到 main 函数。

调试操作

完成上述配置后就可以进行调试了。

  1. 开启调试服务

    $  make server
    ~/.platformio/packages/tool-openocd/bin/openocd -f ~/.platformio/packages/tool-openocd/scripts/interface/stlink.cfg -f ~/.platformio/packages/tool-openocd/scripts/target/stm32f1x.cfg > .dblog
    GNU MCU Eclipse 64-bits Open On-Chip Debugger 0.10.0+dev-00392-gbe9ef0b0 (2018-01-12-16:51)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
    Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
    adapter speed: 1000 kHz
    adapter_nsrst_delay: 100
    none separate
    Info : Listening on port 6666 for tcl connections
    Info : Listening on port 4444 for telnet connections
    Info : Unable to match requested speed 1000 kHz, using 950 kHz
    Info : Unable to match requested speed 1000 kHz, using 950 kHz
    Info : clock speed 950 kHz
    Info : STLINK v2 JTAG v18 API v2 SWIM v4 VID 0x0483 PID 0x3748
    Info : using stlink api v2
    Info : Target voltage: 3.241188
    Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints
    Info : Listening on port 3333 for gdb connections
    ...
    
  2. 启动调试

    $  make debug
    arm-none-eabi-gdb .pioenvs/genericSTM32F103C8/firmware.elf
    GNU gdb (GNU Tools for Arm Embedded Processors 7-2017-q4-major) 8.0.50.20171128-git
    Copyright (C) 2017 Free Software Foundation, Inc.
    ...
    ...
    ...
    Reading symbols from .pioenvs/genericSTM32F103C8/firmware.elf...done.
    0x00000000 in ?? ()
    target halted due to debug-request, current mode: Thread
    xPSR: 0x01000000 pc: 0x08000fb8 msp: 0x20005000
    Loading section .text, size 0x39e4 lma 0x8000000
    Loading section .ARM.exidx, size 0x8 lma 0x80039e8
    Loading section .data, size 0x938 lma 0x80039f0
    Loading section .rodata, size 0x4fc lma 0x8004328
    Start address 0x8000fb8, load size 18464
    Transfer rate: 16 KB/sec, 4616 bytes/write.
    Breakpoint 1 at 0x8002c22: file /Users/5km/.platformio/packages/framework-arduinoststm32/STM32F1/cores/maple/main.cpp, line 38.
    ---Type <return> to continue, or q <return> to quit---
    (gdb) 
    
  3. 进行gdb调试

    下面就可以使用 gdb 命令对程序进行调试了:打断点,单步,执行等等,相关gdb跳是命令这里就不讲解了,可以阅读 GDB 命令速查 了解。