Skip to content
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

Add support for the WeAct Studio STM32G474 Core Board [Update] #818

Open
dzalf opened this issue Dec 3, 2024 · 1 comment
Open

Add support for the WeAct Studio STM32G474 Core Board [Update] #818

dzalf opened this issue Dec 3, 2024 · 1 comment

Comments

@dzalf
Copy link

dzalf commented Dec 3, 2024

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

@dzalf dzalf changed the title Add support for the WeAct Studio STM32G474 Core Board Add support for the WeAct Studio STM32G474 Core Board [Update] Dec 5, 2024
@dzalf
Copy link
Author

dzalf commented Dec 5, 2024

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:

  1. Created variant boards inside the folder: platformio/packages/framework-arduinoststm32/variants/STM32G4xx\G473C(B-C-E)U_G474C(B-C-E)U_G483CEU_G484CEU variant_weact_minicore_g474ceu.h and variant_weact_minicore_g474ceu.cpp

  2. 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

image

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

....
...
  1. Created a new .json board 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"
}
  1. 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) }
}

  1. Finally, I used all of these along with the following environment configuration in my platformio.ini file:
[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":

  1. 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_g474re and the other two WeAct boards from the package container.
  2. 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.
  3. 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

🍺

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants