Add support for the WeAct Studio STM32G474 Core Board [Update]
The closest board available is the nucleo_g474re, however, I am not fully familiar with these boards and I may need some help defining the right parameters for the WeAct board.
The board in question is this one from AliExpress.
The provided repo by WeAct is here.
This board does not have an external flash; however, the bare footprint is available for soldering one chip, as is commonly done with these boards.
Thanks in advance
Dear all
I have spent some time* creating my own configuration files. I had some general success after browsing several resources, reading different example files from other boards and I managed to get some configuration working on my board.
*took me ages, tbh
However, I am not sure about the reliability of my implementation. While I can flash code via STLink and do simple tasks I am not fully convinced if I should trust this for starting a big project I have ahead.
This is what I have accomplished so far:
-
Created variant boards inside the folder:
platformio/packages/framework-arduinoststm32/variants/STM32G4xx\G473C(B-C-E)U_G474C(B-C-E)U_G483CEU_G484CEUvariant_weact_minicore_g474ceu.handvariant_weact_minicore_g474ceu.cpp -
Redefine board pins on the .h and .cpp files based on the datasheet from the STM32G474CEU and each pin's function. Here, I took some creative liberties assigning analog, digital and communication pins.
For reference, check the schematic here
variant_weact_minicore_g474ceu.h (partial file only)
/*
*******************************************************************************
* Copyright (c) 2019-2021, STMicroelectronics
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#pragma once
/*----------------------------------------------------------------------------
* STM32 pins number
*----------------------------------------------------------------------------*/
/* P1 connector left side */
#define PB12 0 // SPI2-CSn
#define PB13 1 // SPI2-CLK
#define PB14 2 // SPI2-MISO
#define PB15 3 // SPI2-MOSI
#define PC6 4 // --> BLUE LED
#define PA8 5 // I2C2-SDA
#define PA9 6 // I2C2-SCL
#define PA10 7
#define PA11 8 // USB_DP
#define PA12 9 // USB_DN
#define PA15 10 // SPI1_CSn
#define PC10 11 // UART4-TX
#define PC11 12 // UART4-RX
#define PB3 13 // SPI1/3-SCK
#define PB4 14 // SPI1/3-MISO
#define PB5 15 // SPI1/3MOSI
#define PB6 16 // USART1-TX
#define PB7 17 // USART1-RX
#define PB8 18 // BOOT0 / I2C1-SCL
#define PB9 19 // I2C1-SDA
/* P2 connector right side */
#define PB10 20
#define PB11 PIN_A12 // FLASH-SPI-CSn
#define PB2 PIN_A11
#define PB0 PIN_A10 // FLASH-SPI-MISO
#define PB1 PIN_A9 // FLASH-SPI-MOSI
#define PA7 PIN_A8 // FLASH-WPn
#define PC4 PIN_A7
#define PA5 PIN_A6
#define PA6 PIN_A5 // FLASH-HOLDn
#define PA3 PIN_A4
#define PA4 PIN_A3
#define PA1 PIN_A2
#define PA2 PIN_A1
#define PA0 PIN_A0
#define PC14 34 // RTC-XTAL-IN
#define PC15 35 // RTC-XTAL-OUT
#define PC13 36 // BUTTON
/* Unrouted to connector */
// PA13 SWDIO
// Alternate pins number
(see file in link)
#define NUM_DIGITAL_PINS 36
#define NUM_ANALOG_INPUTS 13
// On-board LED pin number
#define LED_BLUE PC6
#ifndef LED_BUILTIN
#define LED_BUILTIN LED_BLUE
#endif
// On-board user button
#ifndef USER_BTN
#define USER_BTN PC13
#endif
....
...
- Created a new
.jsonboard definition file:weact_minicore_g474ceu.json
{
"build": {
"arduino": {
"variant_h": "variant_weact_minicore_g474ceu.h",
"ldscript":"stm32g474ceu.ld"
},
"core": "stm32",
"cpu": "cortex-m4",
"extra_flags": "-DSTM32G4 -DSTM32G4xx -DSTM32G474xx",
"f_cpu": "170000000L",
"framework_extra_flags": {
"arduino": "-DARDUINO_WeActMiniCoreG474CEU"
},
"mcu": "stm32g474ceu",
"product_line": "STM32G474xx",
"variant": "STM32G4xx/G473C(B-C-E)U_G474C(B-C-E)U_G483CEU_G484CEU"
},
"connectivity": [
"can",
"ethernet"
],
"debug": {
"jlink_device": "STM32G474CEU",
"openocd_target": "stm32g4x",
"svd_path": "STM32G474.svd"
},
"frameworks": [
"arduino",
"cmsis",
"stm32cube"
],
"name": "WeAct Studio Mini Core G474CEU",
"upload": {
"maximum_ram_size": 131072,
"maximum_size": 524288,
"protocol": "stlink",
"protocols": [
"jlink",
"cmsis-dap",
"stlink",
"blackmagic"
]
},
"url": "https://github.com/WeActStudio/WeActStudio.STM32G474CoreBoard/tree/master",
"vendor": "WeAct Studio"
}
- With the help of ChatGPT and after "feeding it" some template ld files, I managed to get a working linker file:
stm32g474ceu.ld. I am totally blank here. I understand very little from this file.
/**
******************************************************************************
* @file LinkerScript.ld
* @brief Linker script for STM32G474CEU MCU
* 512Kbytes FLASH
* 128Kbytes RAM (96KB Main RAM + 32KB CCM RAM)
*
******************************************************************************
*/
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* End of main RAM */
/* Minimum heap and stack sizes */
_Min_Heap_Size = 0x200; /* Minimum heap size */
_Min_Stack_Size = 0x400; /* Minimum stack size */
/* Memory regions */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
RAM_CCM (xrw) : ORIGIN = 0x10000000, LENGTH = 32K
}
/* Sections */
SECTIONS
{
/* Interrupt vector table */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} > FLASH
/* Code and read-only data */
.text :
{
. = ALIGN(4);
*(.text) /* Code sections */
*(.text*) /* Additional code sections */
*(.glue_7) /* ARM to Thumb glue */
*(.glue_7t) /* Thumb to ARM glue */
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
_etext = .; /* End of code */
} > FLASH
/* Read-only data */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* Read-only sections */
*(.rodata*) /* Additional read-only sections */
. = ALIGN(4);
} > FLASH
/* Exception tables */
.ARM.extab (READONLY) :
{
. = ALIGN(4);
*(.ARM.extab*)
. = ALIGN(4);
} > FLASH
.ARM (READONLY) :
{
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} > FLASH
/* Pre-initialization arrays */
.preinit_array (READONLY) :
{
. = ALIGN(4);
__preinit_array_start = .;
KEEP(*(.preinit_array*))
__preinit_array_end = .;
. = ALIGN(4);
} > FLASH
/* Initialization arrays */
.init_array (READONLY) :
{
. = ALIGN(4);
__init_array_start = .;
KEEP(*(.init_array*))
__init_array_end = .;
. = ALIGN(4);
} > FLASH
/* Finalization arrays */
.fini_array (READONLY) :
{
. = ALIGN(4);
__fini_array_start = .;
KEEP(*(.fini_array*))
__fini_array_end = .;
. = ALIGN(4);
} > FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* Create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* Define a global symbol at data end */
} > RAM AT> FLASH
/* Uninitialized data (BSS) */
.bss :
{
. = ALIGN(4);
_sbss = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > RAM
/* CCM RAM for high-speed data */
.ccmram (NOLOAD) :
{
. = ALIGN(4);
_sccmram = .;
*(.ccmram*)
. = ALIGN(4);
_eccmram = .;
} > RAM_CCM
/* Heap and stack section */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE(end = .);
PROVIDE(_end = .);
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM
/* Remove unused sections */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
- Finally, I used all of these along with the following environment configuration in my
platformio.inifile:
[env:WeAct_MiniCore_STM32G474CEU]
platform = ststm32
board = weact_minicore_g474ceu
framework = arduino
; change microcontroller
; board_build.mcu = stm32g474ceu6
;upload protocol
upload_protocol = stlink
; change MCU frequency
board_build.f_cpu = 170000000L
build_flags =
; enable USB serial
-D HSE_VALUE=8000000U
-O3
-D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
-D USBCON
-D USB_MANUFACTURER=“STMicroelectronics”
You can download all files from this link:
http://thainee-disco.quickconnect.to/d/s/11CnRM7asVUfLIGuu10y4sGXjbJFbrid/xrTKo84LWGG4BbftjWMMXqFclRIRL-gH-7LDgYbri3ws
Using these files, I was able to blink an LED, enumerate my board as a COM port upon bootup and read some analog values on ADC0 (assigned to PA0 as A0 to pin). Sort of.
However, I have several concerns regarding my "solution":
- Is my Frankenstein-ish board description well-defined for my device? Keep in mind that I reviewed dozens of online resources, checked multiple datasheets and other boards implementations, like the
nucleo_g474reand the other two WeAct boards from the package container. - The
analogRead()function throws wrong values. For instance, feeding 3.000V to the pin shows 2.67-ish V. Very inaccurate. I feel like there might be some clock/timing issues here. - Will advanced features like UART, SPI and I2C work fine? I will test them soon but some of you might be able to spot something REALLY wrong. While my files seem to work and the code compiles and runs immediately after bootup, honestly, I have no idea what I am doing in most of them and it has been a trial-and-error in many occasions.
I would like to invite the guys from @WeActStudio to chip-in and help with these definitions.
Thank you all once again
🍺