Custom STM32 Boards From Scratch! | The Complete Guide to Creating Custom STM32 PCBs

A Quick Preview

This is a fully custom made STM32-based PCB (Printed Circuit Board). Being completely custom, it has an advantage over commercial DevKits in that you can customize its shape and application. (In addition to being able to any extra sensors, functions, etc.)

For this article, instead of a typical project, I will show you everything you need to start designing these cool, custom boards for yourself to power many of your own new and exciting projects. I will also show you when STM32 is a good pick over other MCUs (Microcontroller Units) such as ESP32 or Arduino to give you a good understanding of the pros and cons between them.


If you're interested in designing custom ESP32 boards, I wrote a whole separate tutorial on them here.


In this project, I'll build the STM32H573 for its high performance, sizable memory, compact size, and competitive price point. It's a great do-all chip!


The board will feature:

  • Compact 35x35mm size
  • RGB, power, and blink LEDs
  • USB-C power and upload
  • SWD debugging pins
  • BOOT and RST (reset) buttons
  • Power, GND, and the most usable GPIOs broken out
  • HSE and LSE external oscillator
  • ESD protection
Custom STM32 RGB Light Show
RGB LED light show

Let's begin! 

Real quick, I also want to announce that RoboticWorx has officially launched a product! This is the PolyCast5 multi-tool remote. You can check it out here if interested!



Why STM32?

In my experience, STM32s excel over typical microcontrollers do to two major factors:

  • Volume
  • Support

By volume, I'm referring to the fact that there are literally THOUSANDS of different types and variants of STM32s. A simple search on Digikey can confirm this.

This matters because it means that there will almost always be a STM32 that perfectly matches the exact requirements and specifications of the project you want to create. This also helps because it means if you ever want to build a product to go into production, you won't be spending more on other peripherals, etc. that you don't need. (I'll go over the types of STM32 and how to pick them later.)

Lots of customizability.^

The second major factor (environment) that I mentioned earlier, refers to the sheer number of STM32 projects professionally developed or otherwise. This is especially important in picking the ideal MCU (Microcontroller Unit) because it means that STMicroelectronics (the company behind STM32) has great documentation on their products and tools for developing them. 

Maybe the best example of this is their STM32CubeIDE development environment. I've used ESP-IDF (the ESP32 version) for a while now (tutorial here), and was really impressed when trying out CubeIDE because they used a user interface to configure pins and peripherals that would auto-generate the necessary code over you having to write it yourself. This just made basic set-up (configuring I2C, etc.) super easy. CubeIDE can also run many different operating systems such as my favorite FreeRTOS (thread-based OS) which is pretty cool too.


The example code I used for the RGB LED demo can be found here.

But learning to use CubeIDE deserves a tutorial of its own (check back later). Let's keep moving for now!

If you enjoy my work, please consider becoming a free or Plus subscriber! It helps me keep everything open source and is a great way to stay in the loop.



Why Not STM32?

STM32 is pretty awesome, but it's true that it's not ideal for every project. Currently, my two go-to microcontrollers are STM32 and ESP32, and I've yet to encounter a project that one of them couldn't excel at. Here's how I like to pick between them:

STM32+NRF refers to an STM32 paired with a dedicated transmit/receive IC such as the NRF series of chips.

Of course, this is not always the case, but it's a pretty good outline to how I pick and holds true most of the time. ESP32 has great capabilities but is pretty power-hungry. An equivalent STM32 costs a bit more than an ESP32, but has better power consumption characteristics and can offer more specific functionalities. There's always some give-and-take.

This is with an ESP32 module, there is a smaller ESP32 SoC (System-on-a-Chip) inside it that you can use directly if desired. This is also not to-scale!

I've given a lot of attention to ESP32 and STM32, but what about you Arduino (ATmega) users out there! Here's the deal:


Arduino is a fantastic way to introduce yourself to embedded systems (designing and making circuit boards) but it's a beginner device and falls heavily in comparison to these above.

This isn't a perfect chart (many options for GPIO reconfiguration, external RAMs, etc.) but is a basic general-purpose outline.

The Arduino R4 is a solid upgrade from the UNO, but still can't match the capabilities of most STM32s or ESP32s. There also just aren't very many types of Arduinos, which heavily damage your options when looking to build a project.

The R4 even includes an ESP32-S3!

BUT, even with all of this said, if you haven't done projects like this before, I highly recommend doing a few with an Arduino first. Diving right in can be overwhelming and just lead to confusion and frustration. Arduino has a great project community that can help you and I would highly recommend first learning off Arduino projects before moving on to custom PCBs. (This article will still be here!)



Picking an STM32

As I mentioned before, there are a lot of STM32 choices! This is a good problem to have, but it can be confusing knowing which one is best for your project. Here are the general guidelines:

Image from ST.com

I'd probably just pick an ESP32 over any of the wireless versions (though I'm sure they'd work fine) so I'll skip over those.


To expand on this image, a big part of picking STM32s that isn't mentioned so much is when it was released and how you can use that to save money and gain performance.


For example, an STM32F446 costs $8.85 and includes a 180MHz max clock speed and 512KB of flash memory. These are decent stats, but I could instead get a STM32H573 for 45 cents cheaper, which instead has a 250MHz max clock speed and 2MB of flash memory. That's almost x4 the memory, has faster processing, and is cheaper! 

Okay, so what happened?


This is because the F446 was released in February 2016 and the H573 was released in March 2023. But now the newer chip is cheaper, which doesn't seemingly make much sense. This works because just being that something is newer, doesn't necessarily mean it costs more to make. Newer technologies make manufacturing harder things (like more flash) easier, which can help bring the price down. Also being a newer chip, a lower price will attract people to develop new products with the better technology, to help move out the older versions (F4) to make room for the new (H5).

The point of me saying all of this is to get you to pick newer STM32s! You'll save money and get better performance out of it. With this out of the way, we can get back to the chart.

  • For low power wearables/applications, the STM32U series is great.
    • These come in many flavors, such as the STM32U5 which is a high performance ultra-low-power STM32 or the STM32U0 which is smaller but also cheaper.
    • The STM32L series is also okay, but is older than the U series, so pick accordingly!
  • For general purpose stuff (basic applications), the STM32C series is a solid choice. 
    • Being released in January 2023, it's decently new (at the time of writing this) and offers some nice characteristics.
    • It's also a very cheap IC, and can be a great option for developing mass products.
  • For high performance (one of my favorites) the STM32H5 is awesome! 
    • It's a pretty new series having been released in March 2023, and offers some really cool functionalities and advanced security options such as TrustZone.
  • For really high performance (image processing, etc.) the STM32H7 is dominant.
    • It can offer max clock speeds around 550MHz which is pretty crazy.
    • It's a bit older than the rest, but you're paying for it in performance.

Of course, these aren't strict guidelines and would recommend you look through a variety of different STM32s to pick the best one for your application. They also may not be the newest/optimal choice in the future, so always be sure to check ST's official page and recommendations. Here is also a nice Wikipedia page with some release dates and info.


Now let's move on to building the actual STM32H573!

These projects take a while to get out. If you would like to support my work in creating these free tutorials, please consider becoming a free or Plus subscriber!



The Schematic

After picking your STM32 of choice (in my case, the STM32H573), I always begin by opening up the datasheet. This is also a great place to make sure your pick satisfies your project requirements, as you can normally find some summarized details on the front page and in the "Description" section. 

STM32H573 datasheet - front page.

After that, you get a ton of information. But we don't necessarily need to know all of it to start using the MCU and building the PCB.


The most basic first step that needs to be accomplished to get this bad boy running is ensuring adequate power supply. For this, go to the "Electrical characteristics" section in the datasheet and scroll to the power supply scheme.

You may notice there are two different schemes, one for SMPS (Switch Mode Power Supply) and one for LDO (Low Dropout Regulator). For this example I'll chose LDO for simplicity, but just know that SMPS is also a good option if you'd like a slightly higher efficiency.


This looks like a lot of stuff, but it's really not so complex. Basically, all this is doing is showing us which decoupling capacitors need to be placed where for stable operation. So I'll just copy the recommendations into my KiCad project. (KiCad is a free and super awesome software for developing PCBs. You can check it out here).


I also want to note that ST has a lot of application notes that you can check out for additional recommendations and guidelines should you ever need extra resources.

Ideally, the "+3V3" shouldn't intercept the wire above it, but it makes no practical difference here except looking ugly.

Great! Next we can check out the crystal oscillator.


If you've installed KiCad but have no idea how I put the STM32H573 symbol in there, I downloaded it off Ultra Librarian. Ultra Librarian and SnapEDA are great resources to import external PCB symbols and footprints that aren't included in the default KiCad library.


To find the crystal oscillator info, just go to the section titled "Typical application with an 8MHz crystal."

An 8MHz crystal is typically the default used by most STM32s, although technically you could pick a crystal anywhere from 4-50MHz. Now, you might be wondering what this is or why it's needed. All this does is provide a reference signal (periodic high-to-low oscillation done at a set frequency) for the STM32 to base its internal operations off of. Most STM32s also come with an internal oscillator that could be used, but it's not as precise as an external one and basically is just worse. For example, certain peripherals such as USB require a very specific clock frequency to meet protocol specifications which couldn't so easily be done with the internal oscillator.


For this project, I just picked the ECS-80-18-23B-JTN-TR as the crystal since it has decent tolerances (±20ppm) in a pretty compact size and was rated for 8MHz.

Something else to know is that crystals typically need load capacitors to ensure stable, reliable oscillations. Their values can be calculated by the following formula:

Where C_load is the rated load capacitance of the crystal and C_stray is the stray capacitance of the PCB trace and pins. Sometimes there is a mentioned stray capacitance by the STM32 datasheet but I don't see one in this case for the STM32H573. However, it is always best to check.


If you want, you can also add an LSE (Low Speed External clock) which is typically 32.768kHz and used for accurate timekeeping with the RTC (Real-Time Clock) and low-power operation. You can calculate the load capacitors for this the same way if you choose to add it.

Before breaking out any pins for the STM32, it's useful to identify which pins you will actually need for your project. Unlike ESP32s which have a GPIO matrix to allow any GPIO to be used for any specific function (given they aren't mapped internally), STM32 pins are more specific. For example, if you need to use SPI, you'll need to break out the SPI capable pins. For this project, since nothing specific was needed, I just enabled a bunch of random peripherals then broke those out so the PCB can be flexible. 

The peripherals I enabled to see what pins did what.

This said, however, STM32s are still somewhat flexible in that multiple pins can be used for the same purpose. An example of this would be that on this chip series PA5 and PB3 can be used as SPI1_SCK, etc. On CubeIDE, this can be seen by holding CTRL then clicking the given pin if you're interested. If you don't want to mess with CubeIDE (which is also fine), you can also just look through the pinout on the datasheet to figure out which does which.

Datasheet
CubeIDE

While we're on the topic of pins, I also want to point out STM32 debugging. This is different than you may have experienced using a ESP32 over USB, since you need to use specific debug pins (and a debugger but more on that later). My personal favorite debug method is SWD (serial wire debug) with "Trace Asynchronous Sw". With this enabled, you get the SWO (serial wire output) pin which allows printing to the terminal (via printf) which is super useful for logging the internal state of things. I couldn't figure this out for a long time when I was first starting with using STM32s, but it is super useful; highly recommend! I hope you may enjoy the fruits of my extended troubleshooting.


So all-in-all to debug, you'll have SWO, SWDIO, and SWCLK, pins with an optional NRST pin, plus power and GND. Then when the time comes, you would connect these pins to your debugger of choice then connect that to your computer via whichever cable it uses.

  • SWCLK - Serial Wire Clock
  • SWDIO - Serial Wire Data Input/Output
  • SWO - Serial Wire Output
Serial Wire Debug (SWD) pins.

To finish up, we can simply connect up the BOOT0 and NRST pins. On most STM32s, BOOT mode ("upload code only" mode) is activated when the BOOT0 pin is high, so it's important to add a pull-down resistor to ensure it's low by default so the flashed program can run. It's the opposite for the NRST pin, in which the STM32 is disabled (reset) when the pin is low, so that one needs a pull-up resistor instead for a default high state. We can also connect these pins to tactile switches (buttons) on the PCB so we can activate whichever when we need to.  

It's also a good idea to add a small capacitor to smooth out any button bouncing, since as you may imagine, it would be unideal to be rapidly resetting/booting the STM32 on every press.

Button bounce example.

Another quick tip I'd like to add which I've learned from my own projects is to add a "blink" LED when prototyping. This LED's only job is to blink (which you tell it to with your code) which sounds useless but it actually super useful. When it blinks you know that the code is actually running (didn't get stuck anywhere, which actually happens quite a bit), as well as that the STM32 actually listened to you. This negates any potential problems in setting up, in which maybe the code didn't compile right/was configured wrong and led to weird behavior. 

Blink LED
Blink LED

With that, you can just add a standard USB connector and voltage regular and be done! You can also of course add additional components should they be needed like a battery charger, sensor, etc., but here I'm only focusing on the bare-bones STM32. 

ESD protection is also added here and is recommended (USBLC6).
Generic voltage regulator (5V->3.3V).

As seen above, a power LED is also highly recommended when prototyping so you know if your PCB is getting power. It is also great for identifying short circuits, which can be very useful when first powering up the board. (In the case of shorting, no current will flow through the LED and it will be off. An easy tell if you just plugged it in.)

Here is the full schematic for your reference: 

KiCanvas Embed

A downloadable PDF version can be found here.



Layout

Before getting started, I also just want to point out that ST usually supplies numerous application notes with additional guidelines and suggestions for developing with their products. I would recommend always checking them out when working with something new. Here is the one for the STM32H573 MCU on this board.


Now that we have the schematic finished, we can move to PCB layout which is how the actual PCB will be designed. First things first, we should open the PCB in board editor and import the design.

After that, we should go to File > Board Setup > Physical Stackup, and select 4 copper layers. With PCBs being pretty cheap nowadays, there's really not much point doing 2-layer PCBs since you'll miss out on a free ground and power plane for minimal cost.

While setting up, I also like to go to Edit > Text and Graphic Properties, and then format all reference designators to 0.8 height and width and 0.15 thickness. This is the typical minimum for most PCB manufacturers without having to pay extra. To clean up the layout, I'll also usually hide component values since they're not really needed for layout.

Much better! We can also create some predefined sizes now in File > Board Setup > Pre-defined Sizes. This way, we can have some default sizes to select from when routing. I usually try not to go below what I have here, since the smaller the trace/via, the more expensive the PCB will be to manufacture. The bigger traces you see here are useful for routing power, etc. when space allows.

From there we can go ahead and create an outline for the board (select 'Edge Cuts' layer). If you have any mechanical constraints, make sure that the PCB is of proper size. Since this is just a general purpose board for me, I'll just do a rough-hack of a reasonable size per the number of components, 35x35mm.

Now you can start placing the larger components to see how everything might be able to fit together. At this stage, my design looks something like this, with the few main components roughly placed to adjust later.

This also works to give you an idea of if everything will be able to actually fit on the PCB. It looks like I probably will be able to, so I know I can continue.


Now we can start placing the rest. It's best to start with the other main components and their respective capacitors, since capacitor placement does matter in that a given capacitor for a pin should be as close to that pin as possible for decoupling. You should switch back and forth between the schematic to see which capacitor goes where, then do your best to place it as close as you can to whatever it is connected to. After doing that for a while, your PCB might look something like this with only main components and capacitors placed.


I should also point out that the crystal oscillators should be as close as possible to their respective pins as well since you want to try to reduce stray capacitance.

Feel free to move things around too if you find a more optimal way to do it. You may notice that I placed power supply things like USB → regulator close to each other. This is a good idea since they feed directly into each other on the schematic (5V from USB gets regulated to 3.3V) which makes the connections easier and gives the PCB some flow. You should try to do things like this whenever possible to help yourself with routing and good design practices.


Once that looks decent with the location critical components placed (capacitors, main flow, etc.) we can move on to the resistors and other stuff. These matter less, but it is still good practice to place them as close as possible to whatever they are connected to, since it will make routing easier when we do that next (connecting everything with traces).

Great! Now we can move to the next step, which is routing all the various connections.



Routing

A key element here is the copper layers. There are many different ways to do this but I will usually use this stackup:

  1. Top layer - Signal traces
  2. In1 layer - Ground plane
  3. In2 layer - Power traces with ground fill
  4. Bottom layer - Signal traces

This means that all my signal traces (various connections) will be on the top and bottom layer (but mostly top) and there will be a solid ground plane on layer 2 for all the components to be able to access as well as 3.3V on layer 3 for similar purposes. The ground plane also acts as good isolation from the main signal layer and the rest of the board which is important since it also gives all the signals something to couple to. I also like to fill any open areas on the signal layers with ground pour as a good design practice since it helps prevent warping during manufacturing due to copper imbalance. So let's go ahead and create those planes! ("Add filled zone")

NOTE: Here I use a solid 3.3V plane for layer 3 for convenience, but you would typically only do power traces on layer 3 then fill the rest of layer 3 with ground!

If you press "B" now the zones will fill which is fine if you want to check it out. You can press CTRL+B to unfill them after. It may appear that the top, In1, and bottom layer all become ground planes now, but the amount of ground pour on the top and bottom will be significantly less when we're done routing.


To start, I like to do the most important traces. This is typically the USB D+/- differential pair and the crystal oscillators. After that, I like to connect up the capacitors then power supply with GPIOs last. So, because the USB traces are a differential pair, they needed to be routed together so they can cancel out noise EMI-wise. Maybe something like this: 

It's also highly likely you end up moving a lot of traces around as more get routed, so don't worry too much about making any one trace perfect. I can do the same now for the crystal oscillator traces (though they aren't a differential pair).

You may notice that I used a thicker trace for connecting the load capacitors, which is a good design practice when possible since a thicker trace decreases resistance. The difference isn't a lot so it's okay not too, but is good if you can. You may also notice my bottom LSE crystal is a bit stretched out. If after designing you notice this increased stray capacitance causes an issue then you can always resize the load capacitors we calculated earlier.


For connecting the capacitors, it is best to connect it directly to whichever pin from the power plane rather than simply to the power plane. These capacitors are used specifically to decouple the pin they're connected to and should be routed as so. Here's an example below:

This is what an ideal capacitor connection should look like. You'll notice I used a thicker trace where I could and connected it directly from plane (the via), to the capacitor, to the pin. You should do this everywhere possible. 


If you want to think ahead, you can also break out the grounding vias wherever something is to be grounded. Like the power plane, this via will connect the given pad directly down into the plane for a clean connection. This doesn't have to be done everywhere since the copper fill will ground most of everything, but this is good design practice since everywhere there is a via there will be a shorter grounding path to the plane which results in better ground connections. This is especially important for IC (integrated circuit) ground pins.

I also want to point out to look for some sensible routing tips that maybe aren't as obvious. For example, the voltage regulator is powering all the components with its 3.3V output, right? So, when breaking that 3.3V into the power plane, it would be good practice to use a few vias instead of just one so that the resistance gets lowered and the output has an easier time entering the power plane and getting pulled in all those directions to all the capacitors, etc. Another good example would be to spread out traces whenever possible (decrease crosstalk) and increase the width of traces that carry the most power since resistance would matter the most for those (they connect to everything) and they could potentially heat up (depending on load). It's useful to think through when routing like this so you can ask yourself, "Is there a better way to do this?" 

After repeating for a bit your PCB may look something like so.

With the crucial traces done, you can now switch to a smaller trace width (0.2/0.25mm) and route the rest. (Though thicker is technically still better if you can.) This will be the GPIOs, various resistors, etc. After some time you'll probably have something like below.

Cool! After this, you should go around and add extra ground vias wherever there is copper fill. This creates better coupling between the layers as well as provides additional ground paths all around the board. (This results in better grounding.)

As a useful tip, you can do some cleaning up by going to Tools > Add Teardrops > OK, as well as Tools > Remove Unused Pads > Scope: Vias > Action: Remove unused layers. Teardrops decrease resistance by creating copper to ease in and out of existing traces, pads, etc. Then removing unused vias allow the ground plane to grow between the spaces between existing vias for better grounding.

Almost done! The final check is to run a DRC (Design Rules Check) to check for problems. You will likely get a lot of "Errors" but not all errors are problems. For example, maybe you get a thermal relief error, but it's for a small capacitor or something that doesn't really need good thermal relief. In cases like this, you can ignore them, but it's important to look through all the errors to ensure nothing breaks your design or manufacturability (e.g. < 0.2mm clearance).

When everything looks good, you can slap on some text with maybe the board version or date. This can be helpful if it's part of a large project you're developing that would need many revisions.

With that, you can go ahead and export the manufacturing files. File > Fabrication Outputs > Gerbers. Then click Plot > Generate Drill File > Generate Map File.

With that, open up your file manager or equivalent, and select all the files you just generated and compress them into a .zip file. We can now send them off to our manufacturer of choice!



Building the Board

With that done, we can get the boards manufactured!

  • The Gerber/fabrication file for the board can be found here.
  • The editable STEP and KiCad PCB files are available here to plus subscribers. Want to become a plus subscriber? It’s only $5 and I would really appreciate your support!
  • The part list (BOM) with designators can be found here with the CPL available here if needed.
    • As always, I know that it can seem like a pain to have to order parts, but it’s really not so bad as almost all the parts you order from one project get reused. Think about how much you’ll learn with some hands-on experience!

If you’re interested in learning more about embedded systems (PCB design/development), check out Robert Feranec and Phil’s Lab on YouTube. They’re great designers and I’ve learned a lot from them.


To actually produce the PCB, we'll need to go through a manufacturer. For this, I used PCBWay!

I've never had to question their quality and they also offer many other services such as CNC machining, 3D-printing, and PCB assembly. They also feature nine different solder mask colors to choose from and three different silkscreens, which is great for customization. (I even believe they have multicolor solder masks now!) I chose mine to be blue, as I like the color and it offers a slim solder mask clearance, but you can feel free to choose yours to be whichever color you’d like!

Since I designed with KiCad, I didn't even have to leave my design software to check out, thanks to their convenient plug-in! If not though, you can always just go to PCBWay.com, click on quick-order PCB, and upload the Gerber file for the board. Or alternatively, just go here which I have saved in my favorites bar. I recommend clicking the stencil option at checkout to make hand assembly easier! 

Everything else you can leave as the default, unless you have any specific adjustments you want to make. (Lead-free surface finish, remove product number, etc.)

When I got the boards about a week or so later, they looked great!

Now we can go ahead and assemble them. Step 1 is to tape the board down on a flat surface, tape the stencil over it, then spread some solder paste over it. This is arguably the most important step, so feel free to try a few times to get it right. When you're done, the paste should be well enough applied such that the paste layer is pretty much perfectly over every pad so it's hard to tell that paste is even there.

Afterwards, we can take out the reference sheet (designators on the BOM) and start placing the components. I know that the designators are a bit tight and might be hard to read, so I also made a designator sheet with them more clearly marked for your reference, which can be found here. Simply download the PDF then zoom in to see the clearly marked resistors and capacitors.

Placing components...
All SMDs (Surface-Mount Devices) are placed!

Once everything has been placed, carefully place it on a hotplate (or similar) to melt the solder and solidify the components.

Then, carefully take it off such that nothing slides anywhere and let it cool down. After, you can do a quick visual inspection to make sure no pins bridged together while the solder was melting. This can happen commonly for packages like this where the pins are really close to each other. If you notice any, don't worry. You can use some desoldering wick to remove the bridge.

Since you'll need access to the SWD pins for code upload and debugging, I'd also recommend soldering on some pin headers.

That's it!



BOM

This is the custom STM32 Bill of Materials!


I’ll put everything that you need to have here so that you don’t have to go scrolling around looking for the links I sprinkled throughout the article.

Disclosure: These are affiliate links. I get a portion of product sales at no extra cost to you.



Thanks so much for reading! I hope this was a helpful and informative article. If you decide to do the build, please feel free to leave any questions in the comments below. If not, I hope you were still able to enjoy reading and learn something new!


Have constructive criticism or a suggestion for a future project? I’m always looking to improve my work. Leave it in the comments! Until next time.


Be sure to follow me on Instagram! If you want to learn more cool stuff, I also highly recommend Branch Education and Kurzgesagt on YouTube. :)


If you feel this read was worth at least $5, please consider becoming a plus subscriber. I don’t use ads, so I rely on your support to keep going. This is a quick read for you, but I’ve been working on this for months! You will also receive the following benefits.

Back to blog

Leave a comment

Please note, comments need to be approved before they are published.