买了2块mini开发板,一块STM32F407VE
,另一块STM32H743VI
。无他,唯体积小。看到OpenMV
大行其道,开始折腾MicroPython
。
环境: Ubuntu 16.04 x64
开发板: DevEBox STM32H7XX_M Ver:V2.0 SN:1907
STM32H743VI
开发板外观如下(STM32F407VE
板样子都一样)。
1、安装make
和gcc
1 2 3 4 5 6 7 8 9 10 11 sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install make gcc-9 g++-9 sudo add-apt-repository ppa:team-gcc-arm-embedded/ppa sudo apt update sudo apt install gcc-arm-embedded
2、下载micropython
源码
1 2 3 4 5 6 7 cd <SRC_ROOT>git clone https://github.com/micropython/micropython.git cd micropythongit submodule update --init
3、下载开发板的配置代码
1 2 3 4 5 6 7 8 9 10 11 cd <SRC_ROOT>/micropython/ports/stm32/boardsgit clone https://github.com/mcauser/MCUDEV_DEVEBOX_H7XX_M.git
此处编译出错,按照MCUDEV_DEVEBOX_H7XX_M
中的Issues/1
说明,编辑 MCUDEV_DEVEBOX_H7XX_M/mpconfigboard.h
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #define MICROPY_HW_CLK_PLLM (5) #define MICROPY_HW_CLK_PLLN (192) #define MICROPY_HW_CLK_PLLP (2) #define MICROPY_HW_CLK_PLLQ (5) #define MICROPY_HW_CLK_PLLR (2) #define MICROPY_HW_CLK_PLL3M (5) #define MICROPY_HW_CLK_PLL3N (48) #define MICROPY_HW_CLK_PLL3P (2) #define MICROPY_HW_CLK_PLL3Q (5) #define MICROPY_HW_CLK_PLL3R (2)
4、编译
1 2 3 4 5 6 cd <SRC_ROOT>/micropythonmake -C mpy-cross cd ports/stm32make submodules make BOARD=MCUDEV_DEVEBOX_H7XX_M clean make BOARD=MCUDEV_DEVEBOX_H7XX_M
5、烧入开发板
编译完成后,在micropython/ports/stm32
目录下会出现build-MCUDEV_DEVEBOX_H7XX_M
目录,找到固件文件firmware.hex
,使用STM32 ST-LINK Utility
烧入即可。
烧写完成后出现low power
的情况,插入usb
之后会出现windows安装设备等提示,以一个U盘形式出现。
6、使用方法
两种模式,解释器模式和文件模式。前者使用putty
打开串口,与其他解释器一样使用。后者直接修改main.py
文件。IDE
方面,VScode
略显不便,可以采用Thonny
,写完代码可以直接烧入开发板,比较方便。
7、例子
查看当前运行主频:
1 2 3 4 5 6 7 import machinemachine.freq()
首先点个灯:
1 2 3 4 5 import pybtim = pyb.Timer(4 ,freq=2 ) tim.callback(lambda t:pyb.LED(1 ).toggle())
如果用sleep
函数,必须等待其执行完成,或 Ctrl+C
终止执行
1 2 3 4 import time>>> for _ in range (30 ):... pyb.LED(1 ).toggle()... time.sleep(0.5 )
再来一个PWM:
1 2 3 4 5 6 7 import pyb p = pyb.Pin('D12' ) tim = pyb.Timer(4 , freq=1000 ) ch = tim.channel(1 , pyb.Timer.PWM, pin=p) ch.pulse_width_percent(50 )
8、使用板载Flash
vs MCU
内置Flash
上述编译中,使用的是MCU
内置flash
,hex
固件约1.26M
,烧完之后,几乎没啥空间了,考虑折腾板载的外置Flash
。
H7xx
开发板板载一颗W25Q64
的8MByte flash
,F407开发板板载的是W25Q16
的2MByte flash
。前者支持QSPI
,后者不支持。
SPI
协议包括:Standard SPI
、Dual SPI
和Queued SPI
三种协议,分别对应3-wire
, 4-wire
, 6-wire
。
Standard SPI
,有4根信号线,分别为CLK、CS、MOSI和MISO。数据线工作在全双工。
Dual SPI
,只针对SPI Flash而言,不是针对所有SPI外设。对于SPI Flash,全双工并不常用,因此扩展了mosi和miso的用法,让它们工作在半双工,用以加倍数据传输。也就是对于Dual SPI Flash,可以发送一个命令字节进入dual mode,这样mosi变成SIO0(serial io 0),mosi变成SIO1(serial io 1),这样一个时钟周期内就能传输2个bit数据,加倍了数据传输。
类似的,QSPI
也是针对SPI Flash
,Qual SPI Flash
增加了两根I/O线(SIO2,SIO3),目的是一个时钟内传输4个bit
8.1 增加管脚定义
micropython
自带的PYBD_SF
开发板是很好的参考资料,位于ports\stm32\boards\PYBD_SF2
可参考ports/stm32/boards/PYBD_SF2
中相关内容
也可参考 MCUDEV_DEVEBOX_F407VET6
中相关内容
打开MCUDEV_DEVEBOX_H7XX_M/mpconfigboard.h
,增加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) #if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE #define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) #define MICROPY_HW_SPIFLASH_SIZE_BITS (64 * 1024 * 1024) #define MICROPY_HW_QSPIFLASH_SIZE_BITS_LOG2 (26) #define MICROPY_HW_QSPIFLASH_CS (pin_B6) #define MICROPY_HW_QSPIFLASH_SCK (pin_B2) #define MICROPY_HW_QSPIFLASH_IO0 (pin_D11) #define MICROPY_HW_QSPIFLASH_IO1 (pin_D12) #define MICROPY_HW_QSPIFLASH_IO2 (pin_E2) #define MICROPY_HW_QSPIFLASH_IO3 (pin_D13) #define MICROPY_BOARD_EARLY_INIT Mcudev_Devebox_H743VI_board_early_init void Mcudev_Devebox_H743VI_board_early_init (void ) ;extern const struct _mp_spiflash_config_t spiflash_config ;extern struct _spi_bdev_t spi_bdev ;#define MICROPY_HW_BDEV_IOCTL(op, arg) ( \ (op) == BDEV_IOCTL_NUM_BLOCKS ? (MICROPY_HW_SPIFLASH_SIZE_BITS / 8 / FLASH_BLOCK_SIZE) : \ (op) == BDEV_IOCTL_INIT ? spi_bdev_ioctl(&spi_bdev, (op), (uint32_t)&spiflash_config) : \ spi_bdev_ioctl(&spi_bdev, (op), (arg)) \ ) #define MICROPY_HW_BDEV_READBLOCKS(dest, bl, n) spi_bdev_readblocks(&spi_bdev, (dest), (bl), (n)) #define MICROPY_HW_BDEV_WRITEBLOCKS(src, bl, n) spi_bdev_writeblocks(&spi_bdev, (src), (bl), (n)) #endif
8.2 补全QSPI
实现函数
增加bdev.c
和board_init.c
文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include "storage.h" #if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE STATIC const mp_soft_qspi_obj_t qspi_bus = { .cs = MICROPY_HW_QSPIFLASH_CS, .clk = MICROPY_HW_QSPIFLASH_SCK, .io0 = MICROPY_HW_QSPIFLASH_IO0, .io1 = MICROPY_HW_QSPIFLASH_IO1, .io2 = MICROPY_HW_QSPIFLASH_IO2, .io3 = MICROPY_HW_QSPIFLASH_IO3, }; STATIC mp_spiflash_cache_t spi_bdev_cache; const mp_spiflash_config_t spiflash_config = { .bus_kind = MP_SPIFLASH_BUS_QSPI, .bus.u_qspi.data = (void *)&qspi_bus, .bus.u_qspi.proto = &mp_soft_qspi_proto, #if MICROPY_HW_SPIFLASH_ENABLE_CACHE .cache = &spi_bdev_cache, #endif }; spi_bdev_t spi_bdev;#endif
1 2 3 4 5 6 7 8 9 10 11 12 #include "py/mphal.h" void Mcudev_Devebox_H743VI_board_early_init (void ) {#include "py/mphal.h" void Mcudev_Devebox_H743VI_board_early_init (void ) { }
8.3 补全管脚定义
打开MCUDEV_DEVEBOX_H7XX_M/pins.csv
,增加如下内容
1 2 3 4 5 6 QSPIFLASH_CS,PB6 QSPIFLASH_SCK,PB2 QSPIFLASH_IO0,PD11 QSPIFLASH_IO1,PD12 QSPIFLASH_IO2,PE2 QSPIFLASH_IO3,PD13
8.4 编译
可根据情况,选取是否使用SPI Flash
,修改宏定义后,重新编译即可。
1 2 3 #define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)
9、 Mini F407VE
板
F407VE
板已经自带了bdev.c
和board_init.c
,只是缺少一个开启cache
的宏,可以参考PYBD_SF2
在bdev.c
中分开加,也可以参考STM32L476DISC
在mpconfigboard.h
中一次性加入。
另外需要注意的是,F407VE
板使用的是标准SPI
,可以直接copySTM32L476DISC
内容,只是需要增加一个开启关闭使用外部Flash
的宏,最后注意SPI
低电平有效,需要预先将管脚位置低。
最后放上patch
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 board_init.c | 3 ++- mpconfigboard.h | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) @@ -3,5 +3,6 @@ void Mcudev_Devebox_F407VE_board_early_init(void) { // set SPI flash CS pin high mp_hal_pin_output(pin_A15); - mp_hal_pin_write(pin_A15, 1); + // mp_hal_pin_write(pin_A15, 1); + mp_hal_pin_write(pin_A15, 0); } @@ -1,10 +1,6 @@ #define MICROPY_HW_BOARD_NAME "MCUDEV DEVEBOX STM32F407VE" #define MICROPY_HW_MCU_NAME "STM32F407VE" -#define MICROPY_HW_FLASH_FS_LABEL "DEVEBOXF407VE" - -// 1 = use internal flash (512 KByte) -// 0 = use onboard SPI flash (2 MByte) Winbond W25Q16 -#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1) +#define MICROPY_HW_FLASH_FS_LABEL "MiniF407VE" #define MICROPY_HW_HAS_SWITCH (1) // has 1 button KEY0 #define MICROPY_HW_HAS_FLASH (1) @@ -15,9 +11,9 @@ #define MICROPY_HW_ENABLE_SDCARD (0) // it has a sd scard, but i am not sure what the detect pin is, yet // HSE is 8MHz -#define MICROPY_HW_CLK_PLLM (8) // divide external clock by this to get 1MHz -#define MICROPY_HW_CLK_PLLN (336) // PLL clock in MHz -#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) // divide PLL clock by this to get core clock +#define MICROPY_HW_CLK_PLLM (4) // divide external clock by this to get 1MHz +#define MICROPY_HW_CLK_PLLN (168) // PLL clock in MHz +#define MICROPY_HW_CLK_PLLP (2) // divide PLL clock by this to get core clock #define MICROPY_HW_CLK_PLLQ (7) // divide core clock by this to get 48MHz // The board has a 32kHz crystal for the RTC @@ -106,9 +102,16 @@ #define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) #define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) +// 1 = use internal flash (512 KByte) +// 0 = use onboard SPI flash (2 MByte) Winbond W25Q16 +#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0) + // If using onboard SPI flash #if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE +// fix "error: unknown type name 'mp_spiflash_cache_t'" +#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1) + // Winbond W25Q16 SPI Flash = 16 Mbit (2 MByte) #define MICROPY_HW_SPIFLASH_SIZE_BITS (16 * 1024 * 1024) #define MICROPY_HW_SPIFLASH_CS (pin_A15)
参考
https://blog.csdn.net/liaoze22/article/details/106708796
https://blog.csdn.net/wangguchao/article/details/105593303