DarkPill使用非8MHz晶振

title

DarkPill开发板github项目地址

预备知识

RM0008 - STM32F10x参考手册-中文

STM32的启动模式

RM0008:P33

boot-mode

DarkPill的BOOT0,BOOT1,Reset

DarkPill的BOOT0默认下拉,按下开关为高电平,BOOT1为串100K悬空(悬空是低电平),Reset默认上拉,按下开关复位

STM32的刷机方式

三种最常用的:

串口芯片刷机

RM0008: P60

“The values on the BOOT pins are lated on the 4th rising edge of SYSCLK after a reset(复位后,BOOT0引脚和nBOOT1位上的值在SYSCLK的第4个上升沿被锁存)”

STM32用CH340下载程序的方法

SWD刷机

SWD接口直接连接Cortex-M3内核,无需复位操作,直接接上ST-LINK烧录

DFU刷机

DFU的两种编程模式

外部高速晶振(HSE)与USB总线时钟

P1:

f103_datasheet_page1

P12:

HSE_PLL_USBCLK

stm32f103支持晶振频率的范围为4-16Mhz的任意整数,要使USBCLK正常工作在48MHz,必须要使能HSE(外部高速时钟)和PLL,根据时钟树的顺序,可以得出下表,可见只要主频SYSCLK一样USB时钟频率就一样,72MHz主频下使用不同晶振只需修改PLL倍数(PLLMUL)

HSE频率(MHz) PLLMUL SYCLK(MHz) 2xPLLCLK USB预分频器 USB时钟频率(MHz)
8 x9 72 144 /3 48
12 x6 72 144 /3 48
16 x4 72 144 /3 48

STM32的时钟树.pdf

RCC时钟配置实践

DFU的两种编程模式

关键词: ISP模式,IAP模式,自举驱动程序

“对于STM32F1系列,只有互联型子系列STM32 F105/STM32F107支持通过DFU方式实现ISP编程, 所谓ISP模式就是指MCU芯片出厂时内部已集成了DFU相关自举驱动代码,利用它并借助USB接口即可将用户应用程序下载进芯片。而其它STM32F1芯片即使带USB模块,若想利用DFU方式编程就只能自行编写DFU自举驱动,即通过IAP模式实现用户程序的下载或升级...” 👉 原文轻戳

在Aduino IDE下使用

Arduino_STM32

github地址

按照wiki里的Installation步骤(下载安装开发板包,安装Due开发板以间接安装g++工具链)

arduino环境支持的三种常见的烧录方式已经在DarkPill的README.md中演示

我们来说说使用stm32duino-bootloader实现USB-C烧录F103:

STM32duino-bootloader

github地址

作者是罗杰·克拉克(澳洲),他将maple-bootloader改良,让更多的F103开发板能以IAP模式实现DFU烧录程序,这么好的东西DarkPill是不是可以直接用呢?但经过测试发现,他老人家仓库里编译的二进制文件仅适用于板载8MHz晶振的F103,而我的目前DarkPill板载是3225 12Mhz晶振(大真空3225 8Mhz晶振刚下单,逃)

烧录stm32duino-bootloader

连接
ch340/FT232 stm32f103
RX PA9
TX PA10
GND GND
烧录

烧录的STM32duino-bootloader与3225晶振频率的对应表:

HSE bin
8MHz generic_boot20_pc13.binor generic_boot20_pc13_8MHz.bin
12MHz generic_boot20_pc13_12MHz.bin
16MHz generic_boot20_pc13_16MHz.bin

以上bootloader文件在DarkPill github仓库的“STM32duino-bootloader for DarkPill”文件夹里,如何编译请看解决stm32duino-bootloader晶振频率不匹配

将正确的bootloader复制到arduino-1.8.10\hardware\Arduino_STM32\tools\win的目录下,在这个目录有stm32flash.exe烧写工具,我们接下来要使用它

在目录栏直接输入cmd 回车唤出黑白命令框

20200814010947

执行stm32flash.exe -w generic_boot20_pc13.bin -v -g 0x0 COM23

注:上方命令最后的COM后的数字取决于你串口烧录器的端口号

使用CH340正常烧录:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
D:\arduino-1.8.10\hardware\Arduino_STM32\tools\win>stm32flash.exe -w generic_boot20_pc13.bin -v -g 0x0 COM23
stm32flash 0.4

http://stm32flash.googlecode.com/

Using Parser : Raw BINARY
Interface serial_w32: 57600 8E1
Version : 0x22
Option 1 : 0x00
Option 2 : 0x00
Device ID : 0x0410 (Medium-density)
- RAM : 20KiB (512b reserved by bootloader)
- Flash : 128KiB (sector size: 4x1024)
- Option RAM : 16b
- System RAM : 2KiB
Write to memory
Erasing memory
Wrote and verified address 0x080056fc (100.00%) Done.

Starting execution at address 0x08000000... done.

烧录后,需要按一次reset,会执行stm32duino-bootloader自带的例程:PC13的LED飞速闪烁几下

打开设备和管理器,可以看到Maple DFU:

20200814010947

但它还没有被win10识别为COM端口,所以还要安装驱动程序,到arduino-1.8.10\hardware\Arduino_STM32\drivers\win目录下,以管理员身份先后运行install_drivers.bat和install_STM_COM_drivers.bat批处理程序,等待驱动安装,提示如下:

install_drivers.bat install_STM_COM_drivers.bat
install_drivers.bat install_STM_COM_drivers.bat

之后,你发现安装完成后STM32F103还是没有被识别为COM号,所以请继续:

打开arduino ide,选择一个基础例程程序,在COM为灰色的情况下上传,ide会自动识别Maple DFU

20200814230533

然后下次就能正常识别为COM了

20200814011155

若晶振频率不匹配

Arduino IDE默认的Generic STM32FC series的Crystal默认是8Mhz,如果Darkpill的HSE为12MHz或16MHz,那么Blink程序闪烁速度会比8Mhz快,串口波特率也同理(会收不到信息或者乱码),所以,需要修改开发包里的HSE或者PLL的值

那么,我们开始找吧!

在Arduino_STM32\STM32F1\core\maple下的boards.h文件里有以下两行代码:

20200810210153

即:

1
2
#define CLOCK_SPEED_MHZ		CYCLES_PER_MICROSECOND
#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL)

那么我们在boards.h文件文件包含的头文件里找找CYCLES_PER_MICROSECOND这个宏

1
2
3
#include <libmaple/libmaple_types.h>
#include <wirish_types.h>
#include <board/board.h>

找了一圈,锁定了board.h文件(注意与boards.h不同),board.h文件有很多个,找到在开发板管理器里选用的gerneric_stmf103c的board.h打开:

board.h__generic_stm32f103c

打开后,文件里有以下一行代码:

20200810210123

可见CYCLES_PER_MICROSECOND由F_CPU定义,我们再去找F_CPU,然鹅,board.h没有包含头文件,我们到其根目录去找找:

在Arduino_STM32、STM32F1\variants\generic_stm32f103c\wirish的boards_setup.cpp里找到了处理F_CPU的宏,可见50到64行代码是根据预设的F_CPU的值来定义PLL倍频值,与常见的先定义倍频再定义主频相反😳

boards_setup.cpp

那么在到他包含的头文件里找。。。。

算了看看这个issue:F_CPU在什么时候定义?,这个issue也不是,它是Arduino_Core_STM32的F_CPU

我们直接到STM32duino的仓库找吧,下面是F1和F4的,在一个txt文件里定义,估计是脚本程序运行的,知识的盲区😳

buildf_cpu(1)

buildf_cpu(2)

既然这样,直接把72MHz PLL的倍频改为12MHz下的倍数不就行了😢

还是打开STM32F1\variants\generic_stm32f103c\wirish的boards_setup.cpp文件,修改为6即可:

boards.h_change_PLL

测试5秒的Blink程序修改前后对比,修改后正常了,串口也正常了

在Keil MDK环境下使用

下载最新版的MDK5.31

下载对应stm32系列的MDK5 Software Packs

MDK5.29,5.30,5.31和各种软件包镜像下载(2020-07-03)

配置MDK工程模板

教程:正点原子手把手教你学STM32:第10集

配置过程中与视频中正点原子战舰的区别

STM32:LD、MD、HD 的区别

DarlPill使用F103C8T6,战舰使用F103ZET6,工程模板仅仅芯片闪存MD与HD的区别,有以下两处:

启动文件

F103C8T6使用startup_stm32f10x_md.s F103ZET6使用startup_stm32f10x_hd.s

全局宏定义

Option for target的C/C++栏里的preprocesor symbols的define:

F103C8T6使用STM32F10X_MD,USE_STDPERIPH_DRIVER F103ZET6使用STM32F10X_HD,USE_STDPERIPH_DRIVER

首次编译问题

按照原子哥的教程配置好工程模板后,编译,最前面前几句报错:

1
2
3
../CORE/core_cm3.c(445): error: non-ASM statement in naked function is not supported
uint32_t result=0;
。。。。。。(后面还有一长串错误不用看了)

问题解决:

20200811222427

修改后,再次编译没问题了:"..\OBJ\Temp.axf" - 0 Error(s), 0 Warning(s).✅

编译视频最后的原子哥的闪烁程序,用FlyMCU上传,第0~5部步骤如下:

20200811231112

上图第5步后,FLyMCU会显示开始连接,这时,按住boot0不放,按一次Reset,FlyMCU会上传,测试OK(我用D1 mini的CH340上传的)

如果没有在OBJ目录找到编译生成的hex文件,看看视频里勾选生成hex那步是不是忘了

晶振及倍频修改

STM32系列修改外部晶振以及代码的修改

解决stm32duino-bootloader晶振频率不匹配

折腾了好久,发现烧录了maple mini bootloader的stm32win10就是不识别设备,估计是外部晶振的频率是12Mhz造成的,几经辗转,看到了STM32duino的社区里帖子STM32F103上将时钟设置为72Mhz,这位使用F103的老外用16Mhz的晶振代替8MHz的晶振,然后使用maple mini的bootloader USB就是发现不了F103, 伯恩特» 2018年10月5日星期五上午11:39的回答截取了maple mini 定义USB总线时钟频率的一段代码,可以知道由PLL倍频器的值定义:

20200813153820

那么他的USB不识别肯定由于16MHz晶振导致USB的时钟不在协议频率范围里了,巧了,在该帖的最下面发现了STM32duino-bootloader的作者罗杰·克拉克的回答,看来USB频率不对实锤了:

20200813151751

那么,现在我们有用的信息是,maple mini bootloader的代码中定义了USB的驱动,根据PLL的值与外部晶振的频率定义了USB的时钟,我用12MHz的晶振导致USB时钟的速度比8MHz快1.5倍,我们可以列出下表:

开发板 CPU频率(MHz) 晶振频率(MHz) USB时钟频率(MHz) PLL倍频 USB时钟频率为晶振的多少倍?
BluePill(正确) 72 8 48 9 6
DarkPill(错误) 108 12 72 9 6
DarkPill(正确) 72 12 48 6 4

拓展阅读:USB时钟为什么是48MHz?

重新编译stm32duino-bootloader

先把STM32duino-bootloader的整个git仓库下载下来,解压

你会发现这个stm32工程使用Makfile管理编译,别怕,我们先Win10下搭建STM32开发环境,将make和gnu_arm嵌入式工具链装好,能在PowerShell中唤出版本信息即可:

20200813225042

然后请粗略了解一下Linux 下 Make 命令如何工作的?中的“规则“概念

在PowerShell里进入解压的STM32duino-bootloader的目录,先来个make命令,看看报什么错20200813230029

看来是抛出了config.h里的#error

在config.h里加一句黄色框内的

config

,再次编译,执行

  • make clean
  • make

OK不报错了,但是build文件夹里bin文件是0KB咋回事?

20200813230232

打开Makefile看看,因为make后不带参数默认执行make all,然而我们发现Makefile里的all规则默认啥也不执行:

20200814234901

所以我们要执行

  • make clean
  • make generic-pc13

实例如下:

20200814005959

Ok,build文件夹里的maple_boot.bin大小正常了:

20200814010030

那么,接下来,修改USBCLK的频率,在github里搜索整个仓库,发现上文伯恩特提到的setuoCLK()在hardware.c里定义:

20200814233519

打开harware.c,发现作者还很贴心:

20200813235456

若HSE为12MHz,我们直接在 #elif defined TARGET_GENERIC_F103_PC13下加一句#define XTAL12M即可,若为16MHz,则加#define XTAL16M

config_add

最后执行

  • make clean
  • make generic-pc13

完工!

参考:

在LINUX下如何开始一个STM32工程

使用CMake构建STM32工程

探索Keil基于makefile的STM32编译方法

STM32F103C8T6 使用DFU