Skip to content

stm32/WEACT_F411_BLACKPILL: Add WeAct F411 'blackpill' board. #15646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions ports/stm32/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -640,15 +640,15 @@ $(BUILD)/%_$(BOARD).c $(HEADER_BUILD)/%.h $(HEADER_BUILD)/%_af_const.h $(HEADER_
--output-source $(GEN_PINS_SRC) --output-header $(GEN_PINS_HDR) \
--output-af-const $(GEN_PINS_AF_CONST) --output-af-defs $(GEN_PINS_AF_DEFS)

powerctrl.c: $(GEN_PLLFREQTABLE_HDR)
$(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD)
$(BUILD)/powerctrl.o: $(GEN_PLLFREQTABLE_HDR)
$(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD)/qstr.i.last
$(ECHO) "GEN $@"
$(Q)$(PYTHON) $(PLLVALUES) -c -m $(CMSIS_MCU_LOWER) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@
$(Q)$(PYTHON) $(PLLVALUES) -c -m $(CMSIS_MCU_LOWER) file:$(HEADER_BUILD)/qstr.i.last > $@

$(TOP)/extmod/machine_i2s.c: $(GEN_PLLI2STABLE_HDR)
$(GEN_PLLI2STABLE_HDR): $(PLLI2SVALUES) | $(HEADER_BUILD)
$(BUILD)/extmod/machine_i2s.o: $(GEN_PLLI2STABLE_HDR)
$(GEN_PLLI2STABLE_HDR): $(PLLI2SVALUES) | $(HEADER_BUILD)/qstr.i.last
$(ECHO) "GEN $@"
$(Q)$(PYTHON) $(PLLI2SVALUES) -c -m $(CMSIS_MCU_LOWER) hse:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h pllm:$(BOARD_DIR)/mpconfigboard.h > $@
$(Q)$(PYTHON) $(PLLI2SVALUES) -c -m $(CMSIS_MCU_LOWER) file:$(HEADER_BUILD)/qstr.i.last > $@

$(BUILD)/modstm.o: $(GEN_STMCONST_HDR)
$(HEADER_BUILD)/modstm_const.h: $(CMSIS_MCU_HDR) make-stmconst.py | $(HEADER_BUILD)
Expand Down
55 changes: 55 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
WeAct F411 'blackpill'
======================

The WeAct F411 blackpill board comes in a number of versions and variants.
All have a footprint for a SPI flash chip on the back, though the board is
often sold without any flash chip loaded.

At the time of writing (Sep 2024) v3.1 is the current version.
This version is sold with both 25Mhz HSE crystal (same as previous versions) and also
with a 8Mhz crystal. The end user should be careful to confirm which variant is
purchased and/or read the markings on the crystal to know which variant build to load.

The previous v2.0 boards had changed the MCU pinout for the spi flash chip so requires
soft-spi support enabled in the variant settings, unlike v3.1 or v1.3 which is
compatible with the hardware spi peripheral.

The original v1.3 boards did not include a user switch on the top, it only has
"BOOT0" and "NRST" switches to load bootloader and reset the board respectively.

For more information see: https://github.com/WeActStudio/WeActStudio.MiniSTM32F4x1

Note: The pins used by features like spiflash and USB are also broken out to the
gpio headers on the sides of the board.
If these peripherals / features are enabled then these external pins must be avoided to ensure
there are no conflicts. [pins.csv](pins.csv) should be consulted to check all pins assigned
to alternate functions on the board.

Customising the build
---------------------

After purchasing a board without any spiflash chip loaded the user can solder on
their own of any desired size. Most brands of spiflash in SO8 pinout are compatible
however some do have a slightly different protocol so may not work out of the box
with micropython. Brand compatibility is outide the scope of this doc.

Once a custom spiflash chip has been loaded onto the board micropython should
be built with the flash size specified. After doing so the spiflash chip will
be used for the FAT/LFS main filesystem.

Examples:

For a v3.1 / 25Mhz (default version) board with 16MiB flash chip loaded:
``` bash
make -C ports/stm32 BOARD=WEACT_F411_BLACKPILL SPI_FLASH_SIZE_MB=16
```

For a v3.1 / 8Mhz board with 4MiB flash chip loaded:
``` bash
make -C ports/stm32 BOARD=WEACT_F411_BLACKPILL BOARD_VARIANT=V31_XTAL_8M SPI_FLASH_SIZE_MB=4
```

For a v1.3 board with 2MiB flash chip loaded and XTAL manually replaced with 8Mhz:
``` bash
make -C ports/stm32 BOARD=WEACT_F411_BLACKPILL BOARD_VARIANT=V13 SPI_FLASH_SIZE_MB=2 XTAL_FREQ_MHZ=8
```
45 changes: 45 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/bdev.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#include "storage.h"
#include "spi.h"
#include "py/mpconfig.h"

#if !MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE

#if WEACT_F411_V20
// External SPI flash uses SPI interface, but not on all HW spi pins.
static const mp_soft_spi_obj_t spi_bus = {
.delay_half = MICROPY_HW_SOFTSPI_MIN_DELAY,
.polarity = 0,
.phase = 0,
.sck = MICROPY_HW_SPIFLASH_SCK,
.mosi = MICROPY_HW_SPIFLASH_MOSI,
.miso = MICROPY_HW_SPIFLASH_MISO,
};

#else // WEACT_F411_V1.3 or WEACT_F411_V3.1
static const spi_proto_cfg_t spi_bus = {
.spi = &spi_obj[0], // SPI1
.baudrate = 25000000,
.polarity = 0,
.phase = 0,
.bits = 8,
.firstbit = SPI_FIRSTBIT_MSB,
};
#endif

#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
static mp_spiflash_cache_t spi_bdev_cache;
#endif

const mp_spiflash_config_t spiflash_config = {
.bus_kind = MP_SPIFLASH_BUS_SPI,
.bus.u_spi.cs = MICROPY_HW_SPIFLASH_CS,
.bus.u_spi.data = (void *)&spi_bus,
.bus.u_spi.proto = &spi_proto,
#if MICROPY_HW_SPIFLASH_ENABLE_CACHE
.cache = &spi_bdev_cache,
#endif
};

spi_bdev_t spi_bdev;

#endif
22 changes: 22 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/board.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"deploy": [
"../PYBV10/deploy.md"
],
"docs": "",
"features": [],
"images": [
"WEACTV20_F411.jpg"
],
"mcu": "stm32f411",
"product": "WeAct F411 'blackpill'. Default variant is v3.1 with no SPI Flash.",
"thumbnail": "",
"url": "https://github.com/WeActStudio/WeActStudio.MiniSTM32F4x1",
"variants": {
"V13": "v1.3 board with no SPI Flash",
"V13_FLASH_4M": "v1.3 board with 4MB SPI Flash",
"V20_FLASH_4M": "v2.0 board with 4MB SPI Flash",
"V31_FLASH_8M": "v3.1 board with 8MB SPI Flash",
"V31_XTAL_8M": "v3.1 board with 8MHz crystal"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, this 8MHz crystal version doesn't have SPI flash?

How do people distinguish v3.1 with the different crystals?

Copy link

@davefes davefes Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can only suggest the way nspsck does here:
https://github.com/nspsck/STM32F411CEU6_BlackPill_Micropython/blob/main/README.md

For 8MHz crystal and 16MB spi flash:

make -j BOARD=WEACTF411CE BOARD_VARIANT=VARIANTS CRYSTAL_FREQ=8 SPI_FLASH_SIZE=16

For 25MHz crystal and 16MB spi flash, you have to leave CRYSTAL_FREQ out:

make -j BOARD=WEACTF411CE BOARD_VARIANT=VARIANTS SPI_FLASH_SIZE=16

maybe ignore BOARD_VARIANT depending on how Andrew builds these variants.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So far there is only one variant with 8MHz xtal ... no external flash.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To build a variant with this PR use:

make BOARD=WEACT_F411_BLACKPILL BOARD_VARIANT=V31_XTAL_8M

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do I need to re-load any of the build files since 203a2a9?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably need to re-pull this PR. But some of the comments here need addressing before it will build correctly for all variants.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I'll wait.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be clear, this 8MHz crystal version doesn't have SPI flash?

According to the store pages: No. But the footprint for the flash chip is present, so people could add a flash chip. But then they have to adapt the build files and build the firmware themselves.

How do people distinguish v3.1 with the different crystals?

They have to look at the crystal.

I re-ordered a 8MHz crystal board and will get it next week. Then I can check whether the configuration works. ATM it does not look right, since MICROPY_HW_CLK_PLLM is defined unconditionally as 25 for all boards. But maybe that definition is not effective.

},
"vendor": "WeAct Studio"
}
112 changes: 112 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/mpconfigboard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// based off the following two repositories:
// * https://github.com/mcauser/WEACT_F411CEU6
// * https://github.com/YXZhu/micropython

#define MICROPY_HW_BOARD_NAME "WEACT_F411_BLACKPILL"
#define MICROPY_HW_MCU_NAME "STM32F411CE"
#define MICROPY_HW_FLASH_FS_LABEL "WEACT_F411_BLACKPILL"

// some users having issues with FLASH_LATENCY_2, so set to 3
// from https://forum.micropython.org/viewtopic.php?t=7154
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_3

#define MICROPY_HW_HAS_FLASH (1)
#define MICROPY_HW_ENABLE_RTC (1)
#define MICROPY_HW_ENABLE_USB (1)
#define MICROPY_HW_USB_FS (1)

// Switch
#if WEACT_F411_V13
#define MICROPY_HW_HAS_SWITCH (0)
#else
#define MICROPY_HW_HAS_SWITCH (1)
#define MICROPY_HW_USRSW_PIN (pyb_pin_SW)
#define MICROPY_HW_USRSW_PULL (GPIO_PULLUP)
#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_FALLING)
#define MICROPY_HW_USRSW_PRESSED (0)
#endif

// LEDs
#define MICROPY_HW_LED1 (pyb_pin_LED_BLUE)
#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin))
#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin))

// RTC
#define MICROPY_HW_RTC_USE_LSE (1)
#define MICROPY_HW_RTC_USE_US (0)
#define MICROPY_HW_RTC_USE_CALOUT (1)

// Set PLLM same as HSE in MHZ.
#define MICROPY_HW_CLK_PLLM (MICROPY_HW_HSE_SPEED_MHZ)
// Configure PLL for final CPU freq of 96MHz
#define MICROPY_HW_CLK_PLLN (192)
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2)
#define MICROPY_HW_CLK_PLLQ (4)

// UART config
#define MICROPY_HW_UART1_TX (pin_A9)
#define MICROPY_HW_UART1_RX (pin_A10)

#define MICROPY_HW_UART2_TX (pin_A2)
#define MICROPY_HW_UART2_RX (pin_A3)

#define MICROPY_HW_UART_REPL (PYB_UART_1)
#define MICROPY_HW_UART_REPL_BAUD (115200)

// I2C bus
#define MICROPY_HW_I2C1_SCL (pin_B6)
#define MICROPY_HW_I2C1_SDA (pin_B7)
#define MICROPY_HW_I2C2_SCL (pin_B10)
#define MICROPY_HW_I2C2_SDA (pin_B9)
#define MICROPY_HW_I2C3_SCL (pin_A8)
#define MICROPY_HW_I2C3_SDA (pin_B8)

// SPI bus
// SPI 1 is generally used for the SPI flash if enabled below.
#define MICROPY_HW_SPI1_NSS (pin_A4)
#define MICROPY_HW_SPI1_SCK (pin_A5)
#define MICROPY_HW_SPI1_MISO (pin_A6)
#define MICROPY_HW_SPI1_MOSI (pin_A7)

#define MICROPY_HW_SPI2_NSS (pin_B12)
#define MICROPY_HW_SPI2_SCK (pin_B13)
#define MICROPY_HW_SPI2_MISO (pin_B14)
#define MICROPY_HW_SPI2_MOSI (pin_B15)

// SPI 3 is not accessible if SPI flash module is used on V2.0 (PB4 conflict)
#define MICROPY_HW_SPI3_NSS (pin_A15)
#define MICROPY_HW_SPI3_SCK (pin_B3)
#define MICROPY_HW_SPI3_MISO (pin_B4)
#define MICROPY_HW_SPI3_MOSI (pin_B5)

// External SPI Flash configuration

#if !MICROPY_HW_SPIFLASH_SIZE_BYTES
// Use internal filesystem if spiflash not enabled.
#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (1)

#else
// Disable internal filesystem to use spiflash.
#define MICROPY_HW_ENABLE_INTERNAL_FLASH_STORAGE (0)

// SPI flash pins
#define MICROPY_HW_SPIFLASH_CS (pyb_pin_FLASH_CS)
#define MICROPY_HW_SPIFLASH_SCK (pyb_pin_FLASH_SCK)
#define MICROPY_HW_SPIFLASH_MOSI (pyb_pin_FLASH_MOSI)
#if WEACT_F411_V13
#define MICROPY_HW_SPIFLASH_MISO (pyb_pin_FLASH_MISO_V13)
#elif WEACT_F411_V20
#define MICROPY_HW_SPIFLASH_MISO (pyb_pin_FLASH_MISO_V20)
#else
#define MICROPY_HW_SPIFLASH_MISO (pyb_pin_FLASH_MISO_V31)
#endif

extern const struct _mp_spiflash_config_t spiflash_config;
extern struct _spi_bdev_t spi_bdev;
#define MICROPY_HW_SPIFLASH_ENABLE_CACHE (1)
#define MICROPY_HW_BDEV_SPIFLASH (&spi_bdev)
#define MICROPY_HW_BDEV_SPIFLASH_CONFIG (&spiflash_config)
#define MICROPY_HW_BDEV_SPIFLASH_SIZE_BYTES (MICROPY_HW_SPIFLASH_SIZE_BITS / 8)
#define MICROPY_HW_BDEV_SPIFLASH_EXTENDED (&spi_bdev) // for extended block protocol
#define MICROPY_HW_SPIFLASH_SIZE_BITS (MICROPY_HW_SPIFLASH_SIZE_BYTES * 8)
#endif
38 changes: 38 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/mpconfigboard.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
MCU_SERIES = f4
CMSIS_MCU = STM32F411xE
AF_FILE = boards/stm32f411_af.csv
LD_FILES = boards/stm32f411.ld boards/common_ifs.ld
TEXT0_ADDR = 0x08000000
TEXT1_ADDR = 0x08020000

MICROPY_VFS_LFS2 = 1

# Settings for version, spi flash and HSE xtal.
# These are used in variant configs and/or on make command line.
# If provided on make command line the build folder name will be updated to match
# When set in variant they're included after this file so the following ifdef blocks are ignored.

ifdef BOARD_VERSION
BUILD := $(BUILD)_V$(BOARD_VERSION)
endif

ifdef SPI_FLASH_SIZE_MB
BUILD := $(BUILD)_FLASH_$(SPI_FLASH_SIZE_MB)M
endif

ifdef XTAL_FREQ_MHZ
BUILD := $(BUILD)_XTAL_$(XTAL_FREQ_MHZ)M
endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this and the above bit that changes BUILD are needed? The variant name is appended automatically to the board name when doing the build.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the makefile ordering this isn't used / run when a variant is configured - this is just for when one of these settings is passed on the make command line. I thought this would be most helpful for people manually configuring the FLASH size from command line, it will put the flash size in the build folder name.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could I suggest a warning in the README.md to not use A4, A5, A6 or A7 on the 8MB variant. I was vaguely aware that those pins were used for the SPI flash, but did not appreciate the consequences of "accidentally" using them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a note to the readme that's a good suggestion; it's not immediately obvious that the pins needed for "on-board" functions are also exposed to the end user.


# Blackpill v3.1 board by default
BOARD_VERSION ?= 31

# No flash chip in default build - use internal flash
SPI_FLASH_SIZE_MB ?= 0

# 25Mhz HSE crystal by default.
XTAL_FREQ_MHZ ?= 25

CFLAGS += -DWEACT_F411_V$(BOARD_VERSION)=1
CFLAGS += -DMICROPY_HW_SPIFLASH_SIZE_BYTES="($(SPI_FLASH_SIZE_MB) * 1024 * 1024)"
CFLAGS += -DMICROPY_HW_HSE_SPEED_MHZ="($(XTAL_FREQ_MHZ))"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BOARD_VERSION = 13
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOARD_VERSION = 13
SPI_FLASH_SIZE_MB = 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOARD_VERSION = 20
SPI_FLASH_SIZE_MB = 4
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOARD_VERSION = 31
SPI_FLASH_SIZE_MB = 8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BOARD_VERSION = 31
XTAL_FREQ_MHZ = 8
45 changes: 45 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/pins.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
,PA0
,PA1
,PA2
,PA3
,PA4
,PA5
,PA6
,PA7
,PA8
,PA9
,PA10
,PA11
,PA12
,PA15
,PB0
,PB1
,PB2
,PB3
,PB4
,PB5
,PB6
,PB7
,PB8
,PB9
,PB10
,PB12
,PB13
,PB14
,PB15
,PC14
,PC15
LED_BLUE,PC13
SW,PA0
-SWDIO,PA13
-SWCLK,PA14
-OSC32_IN,PH0
-OSC32_OUT,PH1
-USB_DM,PA11
-USB_DP,PA12
-FLASH_CS,PA4
-FLASH_SCK,PA5
-FLASH_MOSI,PA7
-FLASH_MISO_V13,PA6
-FLASH_MISO_V20,PB4
-FLASH_MISO_V31,PA6
19 changes: 19 additions & 0 deletions ports/stm32/boards/WEACT_F411_BLACKPILL/stm32f4xx_hal_conf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* This file is part of the MicroPython project, http://micropython.org/
* The MIT License (MIT)
* Copyright (c) 2024 Andrew Leech
*/
#ifndef MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H
#define MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H

#include "boards/stm32f4xx_hal_conf_base.h"

// Oscillator values in Hz
#define HSE_VALUE (MICROPY_HW_HSE_SPEED_MHZ * 1000000)
#define LSE_VALUE (32768)
#define EXTERNAL_CLOCK_VALUE (12288000)

// Oscillator timeouts in ms
#define HSE_STARTUP_TIMEOUT (100)
#define LSE_STARTUP_TIMEOUT (5000)

#endif // MICROPY_INCLUDED_STM32F4XX_HAL_CONF_H
Loading
Loading