Klipper Firmware Fails to Start on Custom STM32F070 Board

Hello Klipper Community,

I’ve been working on a custom board based on the STM32F070F6P6 microcontroller. I developed my own firmware for it, and everything works as expected: the crystal oscillator starts, pins initialize correctly, all GPIO-s is functional.

However, when I flash the Klipper firmware onto the board, it fails to start entirely. Here are the symptoms:

The crystal oscillator does not start.

Pins that would typically initialize to default states remain unresponsive.

UART communication is completely absent.

It seems like the microcontroller doesn’t even reach the initialization phase. I’ve verified my hardware design and ruled out any issues there since the board works perfectly with my custom firmware.

I’m looking for insights or suggestions on:

Potential configuration issues in the Klipper firmware that could cause this behavior.

Any known compatibility concerns with the STM32F070 series.

Debugging steps to pinpoint what might be going wrong during startup.


Sorry, but you haven’t provided anything to go on - without you providing schematics or your “custom firmware” there’s not much we can say at all.

When you provide your schematics, please make sure to include part numbers; especially for the crystal.

EDIT:

Just thinking more about this.

To maximize the chance that we can figure out what’s wrong, could you provide:

  1. Schematics. In .pdf format would be preferable.
  2. Your custom firmware source. I would be most interested in your initialization code including clocking.
  3. What are the parameters that you are using in make menuconfig
  4. How you Flash the MCU? Are you using DFU or are you loading in a bootloader and, if so, please provide where you got the bootloader.
  5. As part of the previous request, could you tell us whether or not you have STM Link (with STM32 Cube Programmer) or another tool to load your firmware or the Klipper firmware?
    ^ If you can write to your STM32F070’s Flash, what happens if you clear the Flash - you should be in DFU mode. If don’t have a USB connection, then you can program the STM32F070 USART1 TX (PA9) should be in output mode and high.
    ^ I’m asking this because this requires a running clock - and you should be a good way of getting things running.

Thank you for your response! Here are additional details about my setup:

  1. Schematic.pdf
  2. main.txt (main.c)
  3. config.txt (.config)
  4. I am using ST-Link to flash both my firmware and Klipper firmware. I do not use a bootloader.
  5. Of course! I have an ST-Link and use STM32 Cube Programmer for loading both my firmware and Klipper firmware. I have access to the flash and scan erase and write to it without issues.

Currently, it is more important to understand why the firmware does not start.

I have a Blue Pill board where I tested an equivalent Klipper firmware for the STM32F103. Here is what I observe:

UART communication works, and I can see data on the oscilloscope (trigger set for monitoring) and in screen.

The crystal oscillator starts, and its frequency is visible on the oscilloscope.

The LED on PC13 lights up as expected. :slight_smile:

However, on my custom board, the crystal oscillator does not start, and the LEDs do not turn on either. This is currently the primary issue. UART functionality can be addressed later, but for now, simply turning on the LEDs would be a good starting point.

I have tried selecting the internal oscillator for the custom board, but that does not work either.

To provide confidence that the hardware design is correct, I would like to mention that my own firmware works flawlessly. All modes function as expected without any issues.

Let me know if you need further adjustments or clarifications!

config.txt (2.8 KB)
main.txt (11.6 KB)
Schematic.pdf (141.2 KB)

Probably it was right to write this as a response to your message :man_shrugging:

A few comments then I want to dive into what you’re observing in more detail.

Overall, I don’t see any reason why Klipper shouldn’t run although what you’re using is a pretty marginal part. I’m guessing you designed it as a Serial/USB connected controller board for controlling a chamber.

Secondly, you haven’t provided the complete schematics. I would like to see how the heater/fan drivers are wired specifically. I’d also like to know what “MODE” (PA4) is wired to. I also asked for the crystal part number.

Third, you have a somewhat weird circuit connected to PA9/PA10 (USB and USART1 - apparently set up as both). I’m not sure what the pull up on PA10 USART1 RX pin will do here.

Now, when I look at your Klipper configuration, I believe that it is what I see on the make menuconfig - the conventional way of showing what you are doing is to show the screen like:

Are these the parameters that you used?


The most likely cause for your board not starting is that you haven’t flashed the firmware correctly. How are you verifying the start of code in the firmware.bin file? How are you verifying that the firmware has gone in correctly?

It sounds like you have a good idea how to check if the firmware is running, so I would have to question how the code goes in.

To this end, I’ve designed three boards and have only used ST Link to verify that the firmware has gone in correctly, erase the device and set the operational bits. To program the board, I’ve always use DFU Mode - it’s fast, reliable and easy to use.

What I would be interested in hearing is what happens if you erase the device, remove R172 (the pull up on PA10) and plug the board, using the USB C connector into a Linux system and do a lsusb command.

You should get back something like:

Bus 001 Device 005: ID 0483:df11 STMicroelectronics STM Device in DFU Mode

If you do, then you can do a DFU-UTIL load of the Klipper firmware and start working with it once you reset. I would recommend changing your config to use USB rather than serial as that will give you an immediate link to your host.

Let’s see what happens here.

You are quite right, this is the control board for the active thermal camera.

The MODE button in a cycle switches the operating modes when this is used as a standalone device.

PA9/PA10 - this is also correct here! In one case a 1.5Kohm pull-up resistor is needed, in the other case it is not needed, but this is a feature and inconvenience that I decided on consciously. That is, if necessary, I can put a jumper and thus control Pullup DP.

You recreated my settings exactly from the file. I also tried Internal clock and that also did not lead to anything.

Regarding the supposed cause and the start of the firmware.

In order to exclude such errors, I generated two firmware for stm32f103 and stm32f070.

And flashed them from address 0x0800000000 via ST-link and STM32CubeProgrammer.

For verification I erased the chip, checking that all memory is filled correctly

But only stm32f103 starts and the LED on PC13 confirms it. And yes, I also check for a signal from the crystal and only the stm32f103 has one.

I will not argue about the quality of st-link and DFU, but st-link, being an official tool, shows its reliability in other projects and even on the example of stm32f103 everything works perfectly. I should check the DFU too though.

I have removed R172 and put it back in place. This does not lead to anything. And of course I connected my board to Linux, because I just recently got a Windows computer and I can’t be sure that I will do everything right in Windows.

If you do, then you can do a DFU-UTIL load of the Klipper firmware and start working with it once you reset. I would recommend changing your config to use USB rather than serial as that will give you an immediate link to your host.

I would like to understand what I am doing wrong with stm32f070, because I am doing the same actions for both MCUs but only in one case I get the desired result.

If you have any suggestions, what could be wrong with the stm32f070, I will be glad to fulfill your recommendations.

I would be satisfied with one of the three LEDs glowing or the presence of a signal from the crystal, the rest will not cause problems :blush:

I emphasize.
The operation of the hardware has been checked.
All actions for stm32f070 and stm32f103 are similar
The result have is only for stm32f103

Okay, I don’t think you got what I was saying.

Just to be clear:

  1. I don’t see any reason why Klipper won’t run on your board. The device you’ve chosen is marginal for the application (in terms of Flash and pin resources) but I think it should work.
    ^ Having said that you do have a bit of a wonky USB/Serial interface that should work for both. As will be discussed below, I think the USB C connector (with R172 removed) should provide you with a DFU interface.
  2. I meant no disparagement of STM Link/STMCubeProgrammer - I use them all the time.
  3. I have never Flashed an STM32 device using STM Link with Klipper. I’m not confident that loading in the klipper.bin image as is into STM Link and Flashing it into the MCU will work.
    ^ I do not know what tool you used for building your custom firmware nor do I know the parameters and whether or not the generated file is in the same format as klipper.bin.
  4. Where I do have experience is with DFU-UTIL. It’s reliable, fast and easy to use.

In summary, things look good but there’s the unknown as to whether or not using ST Link/STMCubeProgrammer can successfully Flash klipper.bin into an MCU.

I’m going to suggest that you try to attach your board to your Linux system using the USB C connector on the board. I just verified it on one of my Linux systems (Ubuntu 24.04LTS) and will pass along the screenshots of what I got on one of my custom boards.

  1. Create your klipper.bin file. I’m going to recommend that you set it up to run on USB after the build, so that you have another way of checking that it took place correctly. The parameters that you should use are:
  2. Remove R172 from your board.
  3. Apply power to your board, attach STM Link and erase the MCU’s Flash. I did it with one of my boards here:
  4. Remove power, disconnect STM Link.
  5. Connect your board to your Linux system. Based on the schematics, it looks like the board will be powered through the USB C connector.
  6. Do an lsusb on your system and you should see a device with the ID 0483:DF11 - this is the STM DFU USB VID/PID.
  7. Run sudo dfu-util -a 0 -D <location>/klipper.bin --dfuse-address 0x08000000:force:mass-erase:leave -d 0483:df11 where “<location>” is where you have your klipper.bin file.
    You should get something like (you can ignore the last line regarding error on get_status:
    d
  8. Now, when you do an lsusb command, you’ll see that the MCU is now available as an “OpenMoko” device:

That’s it. I should point out that this is the first time I’ve done this - it was theoretical for me up to now but it’s nice to see that you can Flash an MCU using a basic Linux system without any issues.

I would expect that you would be able to do this with your board, from the photographs in the original posting it looks like your USB C connector is quite close to the MCU, so if you haven’t designed it with line impedance in mind, you should be okay.

Just remember to remove R172 before doing this.

I look forward to hearing how this works for you.

@Rula

I agree with Myke. Without a complete schematics there will be just guessing.

1 Like

A new datapoint that I don’t think you’re going to love.

I wanted to see if STM Link/STMCubeProgrammer could be used for loading the Klipper firmware.

So, I took the firmware image that I built in my previous posting and Flashed it into another of my custom MCU boards using STM Link/STMCubeProgrammer. I then connected the board (via USB) to a Raspberry Pi 4B with Klipper installed and…

The Raspberry Pi 4B used a new 64bit OS using Raspberry Pi Imager with Klipper/Moonraker/mainsail installed using KIAUH which also creates a simple printer.cfg. I used KIAUH to do any available system updates.

With Klipper installed, I plugged in my board and checked to see if it was recognized as an “OpenMoko” USB device and then did a ls /dev/serial/by-id to get the Klipper UUID:

I copied this UUID into printer.cfg, did “SAVE & RESTART” and got the result that you see at the top; the board (and MCU) connect to the Klipper host without issues.

So, my trepidation regarding using ST Link/STMCubeProgrammer for loading the Klipper Firmware into an MCU seems to be unwarranted. In STMCubeProgrammer I simply loaded in klipper.bin and uploaded it into the (cleared) MCU.

So, where does this leave you? Honestly, I don’t know.

What I would suggest is:

  1. Share your full schematics with us as well as a photograph of the full board. Maybe there’s something that will jump out at us as being problematic.
  2. Detail the full process you are using to Flash your MCU, including how you built the Klipper image and where you got your copy of Klipper and how you installed it.
  3. Share how you’re checking the MCU to see if it’s working. You mentioned 'scoping the clock (which generally is not recommended) what else have you done? Have you checked the 3V3 power rail? What about devices that are backdriving the MCU?
  4. Try to follow the process I outlined above precisely. I think you should be able to use DFU-UTIL to load your MCU - I highly recommend that you follow my example and use USB communications rather than serial (remember to remove R172). The advantage of the process I outlined previously is that you get indications along with way whether or not things are working as expected.
  5. Look for a development board that uses the EXACT same MCU as you are using. I did a quick look and STM doesn’t have one (theirs uses the STM32F070RBT6 which has more Flash and IO pins) but some other company may.

How many boards do you have? Do they all work the same way?

When you’re reporting your results or providing information, remember that more is better.

I’m looking to hear how things work for you.

This is redundant information, as is the attempt to replace one flashing tool with another. It clearly yields no results and only generates false hypotheses.

The search for truth is the elimination of all false assumptions. I reconsidered my approach and simply tried flashing with Katapult. This allowed me to exclude all peripherals except PA11 and PA12. Of course, I conducted this in parallel on two boards: my own and a BluePill. The result turned out to be identical. On the BluePill, I observe a functioning firmware, while on my board, I don’t even see the oscillator starting up.

So far, based on the results, I can conclude that the issue lies with the linking specifically for the STM32F070, causing some currently unknown error. I draw this conclusion from the fact that my custom firmware, configured in 5 minutes using CubeMX, works perfectly fine. According to Katapult’s documentation, it is based on Klipper files, so this could be a systemic issue. If I can muster the strength and patience, I might go down the path of building with make V=1, but I fear that path could be long.

Of course, it would be easiest to get feedback from someone who has an STM32F070 in operation to definitively confirm that the problem is with my board. However, since no one has responded so far, I suspect this MCU is not commonly used.

Perhaps someone familiar with Klipper’s development, its source code, and the build system could quickly verify this. However, I don’t know who among the developers to invite to this topic who is specifically working in this area.

Mike, I am very grateful for your attempt to help. My tests have so far been unsuccessful, and I’ve ordered a development board based on the STM32F070F6P6 to rule out possible design errors - though I can hardly imagine where one could make a mistake, given that it’s hard to get confused with just three resistors. Nevertheless, I’ll receive the order in two days and will continue my investigation.

Once again, thank you so much for your effort to assist! I will get back in touch and definitely share what the issue was, or we’ll resume the discussion in a few days.

1 Like

Where did you find a development board with the STM32F070F6P6? the only one I found was:

But the designer won’t share his schematic or PCB layout.

The “STM32F070” is not uncommonly used but all the boards that I’ve found that incorporate it have the “STM32F070CBT6” which has 128k Flash and 48 IO pins - I should point out that these run Klipper without any issue. I have never seen a Klipper board running the STM32F070F6P6 and I can’t find one online.


Now, I would like to make a hypothesis that you can test out while you’re waiting for your development board.

My hypothesis is that Klipper builds for the “STM32F070CBT6” under the assumption that all “STM32F070” boards are the same and have the same basic register functions and addresses but the “STM32F070F6P6” actually has different ones.

If I were to make a guess, I’d say that to make your test code you got your firmware development tool here:

https://www.st.com/en/embedded-software/stm32cubef0.html

When I go through the documentation, I see something interesting in terms of the supported products:

Note that there is a different .h file for the “STM32F070x6” and the “STM32F070xB”. I would expect that you created your firmware including STM32F070x6.h (but in the “main.txt” you provided there’s no include statement for the device used or a complete set of source files to confirm).

You can validate this hypothesis by:

  1. Rebuilding your test firmware including “STM32F070xB.h” and Flashing it into your board and seeing if it works. If it doesn’t, which is expected by the hypothesis, then go on to the next step:
  2. Go through the Klipper source, find the file “STM32F070xB.h” or it’s equivalent and replace it with “STM32F070x6.h” or an equivalent, build the new Klipper firmware, load it into your board and see if it works (make sure the resulting file isn’t greater than 32k or it won’t load properly into your device).

If this is the problem then report to the developers (on this site under the “Developers” category), explaining the issue, providing all code and ask that they update Klipper to differentiate between the STM32F070xB and STM32F070x6. Don’t expect an immediate fix, there will probably be questions along with how to present it as a “make” option to users.