I will add a gate driver. I originally had this with a single MOSFET but doing more research led me to believe that parallel would be more appropriate.
MOSFETs tend to parallel quite fine, but a single part is still better if you can find a suitable one, and you definitely will at this power level no problem.
I selected the 470 resistors to try to keep MCU pin current low.
Average gate drive current is still the same - just peak current is lower. The tradeoff of this is slow switching. And A LOT of power will be dissipated in the MOSFETs when they are in partially conducting state. This is the problem, you don't want that. You want as fast switching as possible. Although slow switching helps reduce parasitic voltage ringing and emissions, but the compromise in power dissipation is dire. But if you do even half-decent job, layout parasitics ring in range of tens of MHz; switching times longer than 1µs (~1MHz) have absolutely no benefit. Therefore start with low values of R.
I am confused by this. I thought I had placed the shunt for high-side switching by placing it between the load (which attaches across OUT_A) and the FETs.
You are confused because you miss the fundamental fact that the diode is one of the two switches; surely self-controlled yes being a diode, but still a switch. The key point in motor controller (or buck converter, basically the same thing) is to offer path for the current all the time; either one of the two switches is always conducting (in continuous conduction mode, that is). If you want to sense the high side, then you need to move the shunt resistor between Vsupply and diode. I don't think there is ever a reason to measure between the diode and MOSFET; the three options are ground side, power side and load side (in series with output). Power side sensing would come with two variations, before the supply bypass capacitors and after the capacitors.
Measuring at the load (i.e., connect shunt between the switch node and the output terminal) has the benefit you measure load current correctly all the time, when either of the two switches (MOSFET or diode) is in conduction. If you measure at high side (after capacitors) or low side, you only measure when power is flowing from input, i.e., that is during MOSFET on-time, so you have to synchronize the ADC to sample during on-time, and if you want average motor current, you need to make some assumptions (e.g., motor always runs in CCM, and you get overestimated value at very slow speeds / light loads when it runs in DCM.)
Measuring before the input caps gives you average current, but slow reaction to overcurrent events, I would not recommend doing this. You sometimes see this, but then this is coupled with some secondary integrated protective current sensing stuff which is more quick.
I'd say, go for low-side sensing.
it would actually probably be easier from a layout perspective for me to shift to low-side sensing, so not at all opposed to that.
Additionally to layout benefits, you can use current sense amplifiers with crappy common mode rejection ratings. Load side sensing is most challenging as the common mode voltage (voltage seen by both input pins) vary at huge edge rates between 0V and 12V, and this will couple into the output more or less. Supply side sensing is easier since both input pins are close to 12V all the time. But being close to GND all the time is even easier for the IC.
Route the current sense signal not only to ADC, but also to analog comparator. This way you can trigger an interrupt very quickly
Interesting. I'm using an ATTiny48 MCU for this
Even this rudimentary thing has an ADC which can be triggered using the internal PWM timer (see ADCSRB.ADTS). Usually the best bet is to configure the PWM in up/down-counting mode, don't remember what it was called in AVR terminology but I think it's there, so that the ADC triggering can be center-aligned to the on-time. Being centered to on-time, you avoid short transients during switching, and assuming the motor runs in continuous conduction, the current at exactly half of the on-time happens to be same as average motor current, no math needed.
This synchronized ADC thing is just maybe barely enough to protect the MOSFETs and provide pulse-by-pulse current limiting, but IIRC there was no problem routing the same current sense signal to the analog comparator input, and it can act faster. You need to generate a reference (comparison) level for it but that's only two resistors.
...but it requires a bit of search for an optimum MOSFET.
This has been the hardest part for me so far. I ended up paying a lot (likely too much it sounds like) attention to the Safe Operating Area graphs and deciding I MUST find a MOSFET where my projected load (12V, 20A, 1ms) is within the "safe" range.
You are looking at wrong spec (or going to do the wrong thing). The idea in PWM controller is to minimize the partially conducting state to as short as possible, so that it stops mattering. Most MOSFETs on the market are designed for switching applications, anyway.
For example, if you do f_sw=1kHz*, and decide to spend 0.5% of the time switching on and 0.5% switching off, then the rise/fall times are 5µs. Now look at the SOA again and you see what I mean. And 5µs is still trivial from layout parasitics perspective, good EMI won't be a problem. At short enough times, SOA curves just reduce to those same numbers elsewhere in the datasheet.
*) I'd recommend a bit more than that, though, say 5-10kHz for less vibration and less current ripple
What you want is: Vds_max at least 1.5x to 2.5x of your supply voltage, depending on how confident you are from your layout, snubbing, unexpected transients etc. 30V works here. Then given low enough f_sw and fast enough switching, you can start by ignoring switching losses and only look at conduction loss:
Choose Rds_on low enough so that power dissipation is not a problem; calculate die temperature:
Tj = Tambient + P_dissipation * RthJ-A, where,
P_dissipation = Rds_on * Imotor^2 (at 100% duty cycle)
RthjJ-A, for an SMD part, a direct datasheet value for a given heatsinking layout, say 40 K/W with a square inch of copper fill and a modest sized SMD part, or maybe 20K/W with rows of vias going into bottom layer as well.
Choose such that Tj is well below maximum rating, like 100 degC, in worst case ambient temperature. Then, you need to divide this calculated Rds_on by approx. 1.6 because the fact that front-page rating for Rds_on is at Tj=25degC, but you would be operating it at said 100degC - see Fig.10 on your IRF540 datasheet for example. And NOW you have parameters to search for: Vds_max and max Rds_on.
Lower Rds_on is better of course, but no point in going excessively low - being excessively good on one parameter is going to sacrifice others, i.e. increase Qg_tot and price. Speaking of which, we are not going to use Qg_tot here in any calculation, but being the only remaining main parameter, you can sort the search results and pick something in the lower half of the Qg_tot range available at your distributor. If excessive, the gate driver will have to spend more current to drive the gate, you have to pick bigger gate driver. Not a real problem at your power level though, just ignore the few biggest and you'll be fine. On the other hand, if you plan to drive from the IO pin, limiting your gate drive to some 5V 50mA or so, then Qg_tot becomes a key parameter. A 12V 1A gate driver - not a problem!
We ignored switching loss here but if you choose say f_sw=5kHz and t_rise = t_fall = 0.5% switching period = 1µs, that's not going to be too big. While calculating Rds_on related loss (conduction loss) is trivial like shown above, exact calculations of switching loss are more complex and hand-wavy simpler calculations are... more hand-wavy. The really simple first-order approximation, assuming motor current is constant and switching voltage waveform is a straight line between 0V and supply voltage, is that if you spend 1% of time switching, you would be dissipating 1% * 6V * 20A = 1.2W. Which is actually quite a lot. 1% is too long!