Skip to content

STM32H723VET6 (BTT Octopus Max EZ) USB CDC runtime clock issue / descriptor failure using HSI48 across Arduino and STM32Cube HAL frameworks #2998

Description

@s-zhikharev-tech

Hello team,

I am working with a BigTreeTech Octopus Max EZ v1.0 board featuring an STM32H723VET6 MCU. The board design completely lacks an external HSE crystal oscillator for the USB peripheral and relies entirely on the internal HSI48 oscillator.

We are encountering a critical runtime issue where the USB CDC (Virtual COM Port) stack fails to properly enumerate on Windows OS after a successful firmware upload, across multiple frameworks (Arduino and pure STM32Cube HAL). We have gathered comprehensive hardware feedback through different flashing methods and configurations.

Detailed Test History & Hardware Behavior:

1. Zadig Patch, PlatformIO Upload, and Runtime Silence:

  • Step A (DFU Mode): I force the board into Bootloader mode manually (holding BOOT and cycling RESET). The PC emits a connection sound and the board successfully enumerates via Zadig software as STM32 BOOTLOADER (DFU mode, USB ID 0483:df11).
  • Step B (Driver Fix): Inside Zadig, I successfully patched/reinstalled the required WinUSB/libusb driver to enable a stable connection for the upload tool.
  • Step C (Successful Upload): I switch over to PlatformIO. The firmware compiles perfectly and uploads directly via the dfu-util tool, outputting a 100% stable green [SUCCESS] log in the terminal.
  • The Issue (Runtime State): Right after the successful upload, if I press the hard RESET button on the board or completely unplug and replug the USB cable to switch to runtime mode, the patched DFU link disconnects as expected, but the runtime firmware remains completely silent. Windows OS triggers zero connection sounds, and the USB port acts completely dead during runtime.

2. Flashing via MicroSD Slot:

  • Copying the compiled firmware.bin to a MicroSD card (formatted to FAT32 via an older Android device to ensure standard parameters) and booting the board yields zero activity. The status LEDs do not signal any flashing routine, and the USB line remains completely silent upon runtime boot.

3. Flashing via USB-A (Host) Port with a USB Flash Drive:

  • When we copy firmware.bin to a standard USB Flash Drive and plug it directly into the onboard USB-A (Host) port, the hardware bootloader successfully starts reading the drive.
  • The Exact Behavior: The activity LED on the USB Flash Drive itself starts blinking rapidly, proving that the board's hardware host controller is actively reading the filesystem. Immediately during this reading sequence, Windows OS triggers a plug-in system sound but instantly throws a "USB Device Not Recognized" error window (USB_DEVICE_DESCRIPTOR_FAILURE).
  • Crucial Clarification: This descriptor error only appears while the flash drive is physically inside the USB-A host port. If the flash drive is removed and the board is power-cycled via the USB link, the runtime environment drops back into absolute silence with no OS feedback at all.

Every Configuration & Framework Iteration Attempted:

We tried to approach this problem from high-level libraries down to bare-metal registers, switching frameworks to isolate the bug.

Approach A: Arduino Framework (With Clock Interception)

We attempted to force-enable the internal HSI48 clock source inside setup() before initializing the Serial object.

platformio.ini:

[env:btt_octopus_max_ez]
platform = ststm32
framework = arduino
board = nucleo_h743zi
board_build.mcu = stm32h723vet6
board_build.f_cpu = 550000000L
build_flags = 
    -D HAL_PCD_MODULE_ENABLED
    -D USBCON
    -D USBD_USE_CDC

main.cpp Source:

#include <Arduino.h>

void setup() {
  delay(100); 
  RCC->CR |= RCC_CR_HSI48ON; 
  while (!(RCC->CR & RCC_CR_HSI48RDY)) { __asm("nop"); }
  RCC->D2CCIP2R |= RCC_D2CCIP2R_USBSEL_1; 

  Serial.begin(115200);
}
void loop() {
  Serial.println("Device Ready");
  delay(1000);
}

Result: Success on upload, but absolute silence on reset (unless USB drive is left plugged in, triggering USB_DEVICE_DESCRIPTOR_FAILURE).

Approach B: Bare-Metal Registers (Pure CMSIS)

To completely bypass any potential Arduino framework USB initialization bugs, we dropped the framework and wrote low-level register clock mapping. We manually routed HSI48 to the USB peripheral clock mux, enabled the RCC_AHB1ENR_USB1OTGHSEN bus, and toggled the physical PB15 data lines to simulate hardware connection.
Result: Firmware compiles and uploads fine via DFU, but the internal peripheral clock fails to match the host PC timing loops without an external crystal, causing a completely unrecognized/dead state.

Approach C: Official STM32Cube HAL Framework (The Factory Engine)

We switched the PlatformIO project over to framework = stm32cube to use the standard HAL_PCD_Init() driver stack provided directly by STMicroelectronics.

main.cpp (HAL Implementation):

#include "stm32h7xx_hal.h"

PCD_HandleTypeDef hpcd_USB_OTG_FS;

void SystemClock_Config(void) {
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
    RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
    PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
    HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    __HAL_RCC_USB1_OTG_HS_CLK_ENABLE();

    hpcd_USB_OTG_FS.Instance = USB1_OTG_HS;
    hpcd_USB_OTG_FS.Init.dev_endpoints = 9;
    hpcd_USB_OTG_FS.Init.speed = PCD_SPEED_FULL;
    hpcd_USB_OTG_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
    
    HAL_PCD_Init(&hpcd_USB_OTG_FS);
    HAL_PCD_Start(&hpcd_USB_OTG_FS);

    while (1) {}
}

Result: Compiles flawlessly with the STMicroelectronics HAL drivers, flashes over DFU Protocol, but runtime execution still yields absolute silence on the host OS.

It appears the STMicroelectronics framework core fails to stabilize or properly trim the internal HSI48 clock routing for strict USB descriptor handshakes on the STM32H723 when no external HSE crystal is detected on boot.

Could you please provide the correct low-level initialization routine, clock synchronization patches, or framework configuration flags required to establish a stable runtime USB CDC connection on this target?

Thank you in advance!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions