Skip to main content
Explorer II
December 28, 2025
Solved

OpenOCD reset command

  • December 28, 2025
  • 9 replies
  • 252 views

Hello, 

I am using a custom environment for development and debugging for NUCLEIO-STM32F767ZI.

It is based on a custom devcontainer, VSCode and gdb-multiarch. On the server side I have OpenOCD, running on a ubuntu 24.04 PC. This is connected via USB to the board. The Board itself is not changed in any way, maybe I changed jumpers at some point, I would need to check this if this might effect the behavior.

 

The first connection after Powerup works always as expected, the Firmware is flashed and works as expected.

If I rebuild the project or flash the firmware again, the MCU is in some kind of undefined state.

Calls to different HAL functions fail, return Errors. As some return values are not verified within the generated calls, I don´t see the errors immediately, but very late during debugging. Missing interrupts as an example. The code is a simply generated STM32CubeMX project, without any changes. I am using only GPIOs and Systick interrupt so far.

 

I need the right Reset command for OpenOCD BEFORE or AFTER Firmware flashing.

According OpenOCD documentation, this depends on the board and how STLink is wired to the MCU.

 

Does anyone has experience on such a setup and have some tipps for the correct Reset command.

And which type of Reset is used inside STM32CubeIDE? Is there a way to retrieve any Logs from GDBServer and GDB inside STM32CubeIDE? If I try to connect STM32CubeIDE to OpenOCD, it fails with something like: This is not a STM32 Chip.

If I plug the board into my Windows PC, everything works as expected. But I want to use my Ubuntu PC for debugging and Development.

 

I tried to use

monitor reset halt
before Flashing the firmware, The result is as described above
 
 
Manually typing:
monitor reset init

shows also the same, The chip restarts with initialization, but the errors are still there.

 

Inside OpenOCD are also commands like: 

monitor soft_reset_halt

But they are refused by openocd with:

[stm32f7x.cpu] requesting target halt and executing a soft reset

Target stm32f7x.cpu does not support soft_reset_halt

 

I do not have further configuration in OpenOCD beside the delivered scripts for initialization. My openocd startup arguments look like this:

-f /usr/share/openocd/scripts/interface/stlink.cfg -f /usr/share/openocd/scripts/target/stm32f7x.cfg -f /home/<user>/openocd.cfg.

openocd.cfg contains only: bindto 0.0.0.0

 

I know, that there are STM32 Extensions for VSCode, But in the Videos I saw, they used a direct USB connection.

I want OpenOCD to be available on my network. 

 

Thanks in Advance and Best Regards.

Dietrich

    This topic has been closed for replies.
    Best answer by DietWall

    Found it,

    I have been using the wrong linker script.

     

    For some reason, STMCubeMX generated 2 linker scripts: <device>_FLASH.ld and <device>_RAM.ld.

    What I did, was just to copy both linker scripts into my build environment and writing this into my cmake files:

     

    target_link_options(${PROJECT_NAME}
     PUBLIC "-TSTM32F767ZITX_FLASH.ld"
     PUBLIC "-TSTM32F767ZITX_RAM.ld"
     PUBLIC "-Wl,-Map=${PROJECT_NAME}.map" 
     #export map after linking, still required for debugging
    )

    There were some warnings at the beginning of development, because some sections were defined twice. So instead of really taking care of this warning, I just commented the second definition in RAM.ld out.  (I guess gcc takes the second linker script, if 2 are given?)

     

    Because of that, the variable _sidata (I guess an abbreviaton for: Statically Initialized DATA) in the startup_<device>.s file was not properly linked.

    So therefore the underlying array had a length of 0, and no data was copied from FLASH to RAM.

    The linking command from CubeIDE includes only the flash linker script.

     

    My Linux OpenOCD works actually good enough now without any changes. But I am still wondering why it has been working sometimes...

    9 replies

    DietWallAuthor
    Explorer II
    December 28, 2025

    I would also appreciate any type of documentation for the board, stlink or its connection to stm32f7.

    I am still not used to ST documents. But this is not related to the documentatton itself. 

     

    Version information:

    openocd --version
    Open On-Chip Debugger 0.12.0
    Licensed under GNU GPL v2
    For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html

     

    gdb-multiarch --version
    GNU gdb (Debian 13.1-3) 13.1
    Copyright (C) 2023 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    Super User
    December 28, 2025

    Board documentation is on the product page:

    NUCLEO-F767ZI | Product - STMicroelectronics

    In particular, the User Manual and the Schematic are there and are usually helpful.

     

    DietWallAuthor
    Explorer II
    December 28, 2025

    thank you for the reference.

     

    After checking some documentation, I could read out the RCC_CSR Register, verify and see if there is a difference between openocd and STM32CubeIDE. And also if there is a difference between a cold start and a re-flashing procedure in openocd.

     

    Additionally, I think that clock or Systick configurations might also provide some useful information.

    The biggest issue right now is a return HAL_ERROR here:

    https://github.com/STMicroelectronics/stm32f7xx-hal-driver/blob/e1446fa12ffda80ea1016faf349e45b2047fff12/Src/stm32f7xx_hal.c#L236

     

    The return value is not checked in HAL_INIT(), so therefore this condition is not easy to catch yet.

     

    Just a side question:

    What means MSP in STM32F7HAL like in: 

    /* Init the low level hardware */
      HAL_MspInit();
     

    The function is completely empty.

    Super User
    December 28, 2025

    The only reason that should fail is if this gets caught:

    STM32CubeF7/Drivers/CMSIS/Core/Include/core_cm7.h at 4d308aa04f6a5fff988126e5124ffcf597639647 · STMicroelectronics/STM32CubeF7

     

    Which would indicate a serious issue with the project configuration and how it was created. Step through. Is that where it fails?

     

    Try creating a new project in STM32CubeMX and compiling. Does that work? If so, start from there.

    DietWallAuthor
    Explorer II
    December 29, 2025

    you´re right, it fails exactly there.

    ticks has the value of: 392350558

    Ticks calculation depends on this declaration:

     

    uint32_t SystemCoreClock = 16000000;
    And its value at failure is:   1 177 051 676
    The second variable for the calculation: 
    uwTickFreq is at 254

    So I guess the clock initialization is wrong on the second debugging session.

     

    I have still the feeling that the reset sequence is not the right one. It works as long as I am not connected (I can see the LEDs blinking) and on the very first GDB connection. If I disconnect and reconnect again, it starts to fail.

     

    Maybe there is an additional sleep required to settle some of the clocks? Or an additional signal from STLink to reset some clocks circuit?

     

    The generation was based on the Board (Nucleo-STM32F767ZI) in STM32CubeMX and I am pretty sure I did no changes beside of activating USART3. I don´t think there is much to mess up here? The only change inside the generated code was to deactivate USART3 init functions.

    Super User
    December 29, 2025

    Does this error [after warm reset]  occur without debugger, or you state that the debugger causes it?

     

    Super User
    December 29, 2025

    Hi,

    There's a request to provide updated source of the ST branch of OpenOCD:

    https://community.st.com/t5/stm32cubeide-mcus/how-can-i-obtain-the-latest-source-code-for-openocd-that-comes/td-p/862800

    If granted, this should help with debugging STM32s on various platforms.

    What means MSP in STM32F7HAL

    It means "MCU support package" or something like that. There is one "global" HAL_MspInit() and a MspInit for each kind of "peripheral" which is called from specific "peripheral" init functions. It does stuff like pin configuration. This layer should be also enabling "peripheral" instances, set up power and clock sources per instance, but all that got mixed up in the current Cube and HAL library, so don't take it too seriously. Just look at the provided source  - it is what it is.

     

    Super User
    December 29, 2025

    Looks like the debugger isn't set up correctly. Maybe it's not initializing things correctly, maybe it's not flashing correctly. If you can reset the chip and trace through starting at Reset_Handler, might be able to see something. Weigh the benefit of going a non-standard route vs using the VSCode default working debug configuration.

    DietWallAuthor
    Explorer II
    December 29, 2025

    Yes, I´m also thinking that this is the correct approach right now.

    I will try to setup a breakpoint, that halts the execution, whenever this variable changes or observe its value during single stepping.

     

    I don´t know enough yet about the static initialization routines. Which calls in arm-gcc and newlib(-nano) should initialize the correct values in static variables?

     

    And after reading through the messages again, There is an openocd setup integrated into STM32CubeIDE. I created a debug configuration for local USB debugging. It created a full initialization script for me :) 

    It looks like this: (I removed some comments)

     

    source [find interface/stlink-dap.cfg]
    set WORKAREASIZE 0x8000
    transport select "dapdirect_swd"
    set CHIPNAME STM32F767ZITx
    set BOARDNAME NUCLEO-F767ZI
    set ENABLE_LOW_POWER 1
    set STOP_WATCHDOG 1
    set CLOCK_FREQ 8000
    reset_config srst_only srst_nogate connect_assert_srst
    set CONNECT_UNDER_RESET 1
    set CORE_RESET 0
    set AP_NUM 0
    set GDB_PORT 3333

     I can't test it right now, whether this script works locally. But this are the type of commands I was looking for initially.

    That Kudos Button is not big enough. :) @Pavel A. 

    Super User
    December 29, 2025

    The main thing is it needs to start at Reset_Handler. The code will be compiled with the correct calls to initialize things.

    Super User
    December 29, 2025

    Before main() the program executes the (assembly) startup function Reset_Handler that should re-initialize static variables such as SystemCoreClock. It *should* be correct at main() entry. Make sure you arrive at the Reset_Handler.

     

    DietWallAuthor
    Explorer II
    December 29, 2025

    I found little time for debugging. 

    After starting/restarting the debugging session my code lands at the Reset Handler, first instruction is:

    Reset_Handler:
    ldr sp, =_estack /* set stack pointer */

    Reset Handler itself should be just an instruction address, loaded to the Reset Vector. And the ldr instruction is the first one to execute.

    So this should be fine from my understanding.

     

     

    On the other side, the static initialization is definitevely not happening. I introduced some more global integers and they keep their random value from the beginning.

    &SystemCoreClock = 0x20000074

    *&SystemCoreClock = 1177051676

     

    &random_variable = 0x2000006c

    *(&random_variable) = 537079928

    C-Declaration looks like this:

    volatile int random_variable = 1337;
     
    Looking at the startup code. I guess the symbol LoopCopyDataInit (Lines 73-81) is responsible for loading the correct values into the globals. Or provide the addresses to the  __libc_init_array. Which then copies the data from Flash to RAM. 
    __libc_init_array is located inside newlib. 
     
    And one more observation: SystemCoreClock is set to 30MHz after SystemClock_Config(). But inside generated Code it is already used in
    HAL_Init()->HAL_InitTick(TICK_INT_PRIORITY);
    I tried to call HAL_InitTick again after SystemClock_Config(). But the effect was still the same.
     
    What is still confusing to me, is why this initialization sometimes works and sometimes not. This should not change, if I am connected with openocd or not. So maybe there are actually 2 issues to solve.
     
    I will debug the same startup procedure from STM32CubeIDE and see, if there ís something different. And more specifically, when SystemCoreClock is initialized.
     
    And I could load the binary into STM32CubeIDE environment, by doing so, I could identify whether it is a debugger or a linker error.
    DietWallAuthor
    Explorer II
    December 29, 2025

    Ok, after debugging both versions, I can conclude. it is some kind of a compilation/linking error. 

    I will compare all compile/linker flags from my environment to STMCubeIDE in the next days.

     

    The initialization of globals is in fact between Lines 73-81. The values in STMCubeIDEs application are copied in this lines from FLASH to RAM. My application behaves with STMs OpenOCD very similarly to my Linux OpenOCD environment. SystemCoreClock is not initialized at beginning of main.

     

    STMCubeIDEs version is working as expected.

     

     

    DietWallAuthorAnswer
    Explorer II
    December 30, 2025

    Found it,

    I have been using the wrong linker script.

     

    For some reason, STMCubeMX generated 2 linker scripts: <device>_FLASH.ld and <device>_RAM.ld.

    What I did, was just to copy both linker scripts into my build environment and writing this into my cmake files:

     

    target_link_options(${PROJECT_NAME}
     PUBLIC "-TSTM32F767ZITX_FLASH.ld"
     PUBLIC "-TSTM32F767ZITX_RAM.ld"
     PUBLIC "-Wl,-Map=${PROJECT_NAME}.map" 
     #export map after linking, still required for debugging
    )

    There were some warnings at the beginning of development, because some sections were defined twice. So instead of really taking care of this warning, I just commented the second definition in RAM.ld out.  (I guess gcc takes the second linker script, if 2 are given?)

     

    Because of that, the variable _sidata (I guess an abbreviaton for: Statically Initialized DATA) in the startup_<device>.s file was not properly linked.

    So therefore the underlying array had a length of 0, and no data was copied from FLASH to RAM.

    The linking command from CubeIDE includes only the flash linker script.

     

    My Linux OpenOCD works actually good enough now without any changes. But I am still wondering why it has been working sometimes...