The peripherals it needs
Field-oriented control does not need a fast processor nearly as much as it needs the right peripherals. The whole loop is a few hundred floating-point operations — the hard part is that they must happen at a precise instant relative to the switching, on currents sampled at another precise instant, with the result reaching the bridge coherently on all three phases. Almost all of that is done by hardware you configure once and then leave alone.
This page is the shopping list, and the reasons. The concrete numbers and the failures come from one rig — an NXP MCX-N947 driving a Teknic M-2311P through an FRDM-MC-LVPMSM inverter at 24 V — because a specific board that actually ran is more useful than a generic table. Those are measured or datasheet numbers from that hardware, not outputs of this site’s model.
1. A PWM unit with complementary outputs and hardware deadtime
Three submodules, six outputs, centre-aligned.
Complementary means you write one duty per phase and the peripheral generates the inverted signal for the low-side device itself. That matters for more than convenience: the deadtime between the two edges must be inserted by hardware. Software cannot be trusted to hold off a turn-on by hundreds of nanoseconds while an interrupt might land in between, and a leg with both devices on is a short circuit across the DC link.
Centre-aligned rather than edge-aligned, because it is what puts the null vector symmetrically at the start and end of every period — which is what the bridge page shows, and what makes the sampling window in §3 exist at all.
Synchronising the three submodules to one timebase is not optional either. The three carriers must be exactly in phase, or the voltage vector the bridge applies is not the one the modulator computed.
The reload rule, which will bite you
The duty registers are double buffered. A write lands in a holding register and transfers to the active one only at a reload event. That is the mechanism that guarantees all three phases change together on a period boundary rather than mid-pulse — you cannot produce a torque glitch by being slow between two register writes.
The converse is the part that costs a day: while a reload is pending, further writes to the value registers do not take effect. A duty update therefore has exactly one correct shape, and it is not obvious from the register map:
clear any pending reload (CLDOK)
write the three duties (VAL2/VAL3 × 3)
arm the transfer (LDOK)
Here is what that rule does when two pieces of code both write duties in the same interrupt. The figure runs the actual latch model — which write landed, which the hardware discarded, and what the bridge ended up switching on:
The second writer is not overwriting the first. It is being ignored — silently, with no error anywhere — because the first writer armed a transfer and the value registers are locked until that transfer completes. And whether it is ignored depends on where the counter happened to be, which is not a property of either piece of code.
On the rig above, that was exactly the defect. A library began writing duties after the vendor stack in the same interrupt; the vendor driver sets the latch bit at the end of its own write, so the second writer found the registers locked by the first writer’s pending reload. The duty-write winner was effectively random, and the symptom was intermittently impossible physics. Only after clearing the pending reload first did the measured q-axis voltage at 800 rpm (3.2 V) agree with what back-EMF says it must be.
On the bench The obvious lesson is “always clear the pending reload first”, and that is the smaller half of it. Clearing is necessary; it is not sufficient. Put three writers in a period, each of them perfectly disciplined, and the model still produces three different answers — because whichever write happens to precede the boundary is the one that gets carried through.
The rule underneath the story is therefore about counting, not about instructions: exactly one piece of code may own the duty registers. Two writers in the same period is not a race you can win by ordering them carefully, because the hardware, not your code, decides which write survives.
2. Fault inputs wired straight to the outputs
The PWM unit should be able to force its outputs to a safe state from a hardware input, with no CPU involvement — typically from an analogue comparator watching a current shunt.
That is the whole argument for putting over-current protection here rather than in the ISR. At 16 kHz the software path’s worst case is 62.5 µs of a current that is already past its limit, plus the reload that follows it. For a shorted leg that is a long time.
On the rig, the comparator feeding that path is mis-calibrated: it silently chopped the PWM above 2.4 A on a 7.7 A motor. The mapping was therefore cleared deliberately and protection carried in software instead. That is a real downgrade and it is written down as one — the point of naming it here is that “we turned off the hardware protection” is a decision that must survive in documentation, not a comment in a driver.
3. An ADC the PWM can trigger
Not an ADC you read from a timer interrupt. One that the modulator triggers directly.
Low-side shunt measurement only works during the null vector, when all three low-side devices are on and the phase currents are actually flowing through the shunts. Because the pulse is centred on the middle of the period, its complement — that null window — is centred on the period boundary. So the window is not an interval inside the period at all; it straddles the edge between two of them, which is why the conversion is triggered at the counter underflow rather than anywhere that sounds more natural:
The chain that follows is worth getting in the right order:
- the PWM’s own compare event triggers conversion,
- conversion-complete raises the control interrupt.
So the control law never runs on stale currents, and never runs before the samples it needs exist. Everything on the sensing page about where to place the sampling instant assumes this hardware path.
You need enough channels to take two phase currents plus the DC-bus voltage. Two currents are sufficient — the third follows from Kirchhoff — though which two you use is not arbitrary when duties get extreme, and the figure above shows why: the phase with the largest duty is the one whose window closes first.
On the bench One converter serving the whole drive means the three phases are not sampled simultaneously. One trigger starts a chained sequence — phase a, phase b, phase c, then the bus — and a FIFO watermark interrupt fires once all four are present. That interrupt is the control interrupt.
The skew between the first and last conversion is the price of a single converter, and it is tolerable for a specific reason rather than by hope: inside the null window the machine is freewheeling through the low-side devices, so the phase currents decay only slowly across it. Move the sampling instant out of that window and the same skew stops being harmless.
4. A quadrature decoder, if you have an encoder
A counter that decodes A/B in hardware and captures the index pulse. Decoding quadrature in software works at low speed and then quietly stops working: at 2000 pulses per revolution and 3000 rpm, the edges arrive about every 2.5 µs.
Even in a sensorless drive, an encoder input earns its place on the bench as a witness. On the rig, a sensorless startup once reported a healthy RUN state at 435 electrical rad/s while the shaft stood still — the observer had locked onto a phantom. The frozen encoder count was the only thing on the board that disagreed.
5. A debug path you can read at speed
Not a peripheral of the control loop, but the difference between engineering and guessing. On this rig the serial console’s host-to-target direction was dead — a physical break that no amount of firmware could fix — so every measurement in the report behind this page was taken by reading and writing target memory over SWD while the motor ran.
That turned out to be a better tool than the console would have been, and it is worth designing for deliberately: keep the drive’s state in a small number of known globals, and a debug probe becomes an oscilloscope for your control law.
What it costs, on a real part
| Quantity | Value on this rig |
|---|---|
| Core | Cortex-M33 at 150 MHz |
| PWM period | 62.5 µs (16 kHz) |
| Control ISR | ≈ 12 µs, so about 19% of the period |
| Transport delay | ≈ one period, sample to applied vector |
| Encoder | 2000 ppr, quadrature |
The delay in the third row is not a defect of this board — it is the structural consequence of the reload rule in §1. Duties computed from a sample are latched at the following boundary, so the applied vector lags the measurement by about one period. That is the number the timing page turns into a phase-margin budget, and it is why the ISR being 12 µs rather than 30 µs matters far less than you would expect.
What to take away
- Complementary outputs with hardware deadtime, centre-aligned, on one synchronised timebase. Software cannot be trusted with the interlock.
- The duty registers are double buffered, and a pending transfer locks them. One writer, always — the count is what makes it deterministic, not the discipline of each writer.
- Trigger conversions from the modulator, at the boundary, and let conversion-complete raise the control interrupt.
- Put over-current protection in the comparator, not the ISR. A cycle versus a period is the entire difference.
- A quadrature decoder and a debug probe both earn their place, and in a sensorless drive the encoder earns it as a witness rather than as a sensor.