Let’s take a look at the PCB design!

The overview of the PCB is shown above. On the left is the USB connector, and on the right is the RF interface through an SMA connector. On the top and bottom of the board are P2 and P3, which break out the STM32 MCU’s pins, allowing this board to be used as a development board, or for other projects that need USB, RF or both.
There is a vertical white line running through the board, a little off center. This is the cut line. The board is meant to be used as a whole, as a USB dongle, but if the board is cut along that line, then the right side of the board can be used as an RF module. The pins on P2 and P3 expose the SPI interface and power pins of the module, allowing an external MCU, like an Arduino, to control the RF interface.
The PCB is a four layer board. The top is where all the components are, and most of the routing. Layer 2 is a ground plane, layer 3 is the power plane, and the bottom layer is used for some routing, and as a ground plane. I used JLCPCB as the PCB fabricator, and they require a minimum of 4 layers for controlled impedance, so I went with that. 4 layers also allows the circuit board to be very compact, which is useful since a dongle needs to comfortably fit in USB ports.




Let’s look at the key PCB design areas.
USB

While most of the signals on the board are straight forward, USB needs special attention for two reasons: it is differential and needs controlled impedance.
The differential nature of USB requires that the D- and D+ trace lengths be close to each other. In the picture above, you can see that one trace travels in a large arc (D-), while the other travels in a small arc (D+). This causes one of the differential signals to travel a shorter path, causing D+ and D- to be out of sync. To combat this, the shorter signal has a zig-zag path built in to it, called an accordion. This forces the shorter path to become longer, making both differential signals travel the same length.
USB specifications state that the differential impedance of USB is 90 Ω. I used JLCPCB’s stack up information and Saturn PCB design software to determine what trace widths and spacing is required to achieve this. On JLCPCB’s website, they say the prepreg between the top layer and my ground plane is 0.2 mm thick, and has a dielectric constant of 4.6. Plugging this into my design software gives 10 mil wide differential traces, 7 mils apart:

Frankly, controlled impedance and length matching probably aren’t necessary for this project. The traces are very short, so any issues due to out of spec impedance and different lengths of differential signals will be negligible. However, it’s good practice for larger, more complex boards, and it never hurts to be careful.
Couple more things. There are two resistors in series with the D- and D+ signals. Normally, these should be as close to the MCU pads as possible. However, I’m fairly certain the MCU has these resistors internally, and the resistors on the PCB are redundant, so their position isn’t very critical. I put them there just in case I need them. Secondly, there is ESD protection, right near the USB connector. This component should be as close to the USB connector as possible; the rational is that if an ESD event occurs, the protection that’s right near the connector will handle it, preventing the ESD from getting far into the board. If the ESD protection was near the center of the board, for example, then the ESD pulse would go through half the board and potentially damage things; by having the protection right at the connector, ESD is handled immediately.
Clock



The RF transceiver requires a 16 MHz crystal. The crystal requires two load capacitors and a biasing resistor.
The top layer shows a guard ring around the crystal and the passive components. The guard ring prevents leakage current, that is small amounts of current flowing from copper to copper through the FR4, from getting in or out of the sensitive clock circuitry.
Additionally, the ground planes for the clock circuitry, on the layer 2 and on the bottom, are separated from the rest of the PCB. This ensures that any return currents and nasty transients that occur during oscillation do not impact the rest of the board. Conversely, the separation ensures that any return currents and nasty transients that occur on the rest of the board do not affect the crystal oscillator. Despite the separation, the ground planes must connect to the rest of the circuit’s ground at some point, so there is a small trace connecting the two ground pours on layer 2.
A really helpful document about crystal layouts is ST’s AN2867.
RF

The RF traces are in four segments: unbalanced (left), balanced (middle-left), balanced + amplified (middle-right), and filtered (right). For all four segments, the traces should be kept as short as possible.
The unbalanced segment is composed of two traces. Like USB, the two signals should be of equal length. Since we’re operating at 2.4 GHz, making sure they’re the same length is very, VERY important. The other segments are fairly straight forward; just connect pads together with as short a trace as possible.
Two things to note. Firstly, I typically use 45 degree bends in my traces, but for RF I decided to use smooth corners. I read that RF signals have problems at 45 or 90 degree bends, and a smooth corner is better. This may be an old wive’s tale, but I think it looks cool (very scientific) and helps distinguish RF traces from regular traces. Secondly, like USB, RF traces require controlled impedance. After the balun, the RF traces need 50 Ω impedance. Rather than using the Saturn PCB design software again, I consulted JLCPCB’s online tool:

As you can see, to get a 50 Ω impedance trace, the trace needs to be 11.55 mil thick. I didn’t do this for the USB differential traces because I didn’t notice this tool could do differential traces too, but fortunately the results are nearly identical. If you have a choice between a PCB vendor tool, and a generic PCB tool, you should go with the vendor’s tool.

One last thing to note about RF. When a signal is present on a trace, we generally think of the signal as being confined to the copper. For example, when you drive a logic high on a piece of copper, the logic high doesn’t permeate beyond the boundaries of the copper. However, this becomes less and less true as the frequency of the signal increases. Even SPI clock signals, which are in the megahertz range, can start affecting signal traces that come too close to them. For RF, this is a much more prominent issue. RF signals can impact electronics that aren’t even on the same PCB through EMI emission. In this case, emission is good, since we’re trying to transmit an RF signal. But what we don’t want is uncontrolled, or unintentional emission. We want the RF to be emitted by the antenna only, and nowhere else.
To prevent the RF traces from emitting RF signals (besides through the antenna), we need to button up the edge of the PCB where the RF signals are active. You can think of it like a wall or a dam: the RF traces will emit EMI, and they’ll try to leave the PCB, but the shielding will keep them in. In order for the shielding to be effective, the vias should be placed at most one twentieth of the wavelength we’re trying to keep in apart. In this case, we’re using 2.4 GHz signal, which has a wavelength of 3E8/2.4E9 = 0.125 m, which is about 5 inches. One twentieth of 5 inches is 250 mils, so the vias must be placed closer together than that.
Conclusion
I’ve placed an order for the PCB and the BOM, and they’ll be here in a couple of weeks. When they arrive, let’s take a look at programming the MCU!