Reset
Up to Devices and Hardware
Having already tired of having to unplug the USB cable to reset the board, I've figured out how to connect a reset button (through the JTAG port). It should have been obvious, but I had to figure it out anyway.
I'm working on my own custom firmware, which means I can handle reset however I want. Well, sort of. I want to have the reset line handled in hardware, and that works, except for one thing. I'm booting via SAM-BA/sam7, which does not drop the USB pullup because it cannot know which pin it is on or how it is connected (the result being that the host doesn't know that the device has reset, so it's a bit confused). So what I've done is to catch the reset pin in an interrupt (once I'm running my code) and drop the USB pullup there. And that works. Unfortunately, that does me no good if my firmware crashes with interrupts disabled. So what I really want is to ditch the interrupt thing and go back to doing it in hardware.
For that scheme to actually work, my firmware has to enable the pullup by disabling the PA11 output driver (letting R20 do the lifting), rather than by driving PA11 high (which would prevent NRST from being able to pull the base down).
So, am I on the right track? I'd rather find out otherwise now, rather than by risking damage to my hardware. Hence the sanity check. This mod involves no cutting of traces, but it does involve tack-soldering to two vias (or component legs) which I have already located on the controller board.
This is only really an issue because I'm booting through sam7, which I realize is not how most people do it. Once my firmware is to the point where I can boot directly into it, I can take care of dropping and raising the USB pullup myself in precisely the way that sam7 does not. But I still will probably have to return to this mode periodically for testing new firmware prior to flashing it. I want to reduce wear on the FLASH and the NVM bits (which have a stated endurance of only 100 erase/write cycles) by testing code in RAM.
Hi Lou,
We've taken a look at your proposal and we think the logic seems fine.
I'm a little rusty with how everything works in there, but here goes.
I guess the main issue is where the voltage at the base of Q1 ends up in the one tricky case you identify: when PA11 is being driven high. When SAMBA is running, PA11 will be taken high via a weak pullup, so this case is OK, your 4.7K should pull the Base of Q1 low no problem. During our startup we drive PA11 low until we get our USB house in order. This is fine too, USB is disabled. When we're done initializing, we drive it high. This is the worst case for your proposal. PA11's ON transistor fighting your 4.7K to ground. Where does the base voltage end up?
I'd be pretty comfortable soldering some wires on the board and trying it out, however, the good news is that there's a very simple fix that you can apply to the codebase now (and we'll apply for the next release).
In USB-CDC.c, the function vInitUSBInterface( ) you'll find at the end (approximately line 846)
AT91C_BASE_PIOA->PIO_SODR = AT91C_PIO_PA11;
This is where the line is turned on. If instead we just disable the line, it will float high thanks to R20 and will offer no resistance to your NRST modification.
AT91C_BASE_PIOA->PIO_ODR = AT91C_PIO_PA11;
Any subsequent disabling of the USB hardware will turn the output on again (vDetachUSBInterface) so this fix doesn't mess that up.
I hope I haven't missed anything, I am a little rusty as I mentioned. Your
carefully thought-out post really helped me get up to speed. Thanks!
D.
Thank you for looking at my proposal. I am pleased that you liked how I thought it out. I put way too much thought into these things, and it's nice to know it's appreciated.
I think that case (PA11 driven high when NRST gets driven low) is handled pretty well by the proposal, assuming it is ok if the USB pullup doesn't get disabled in that case. PA11 can drive 8ma indefinitely. In terms of your question, the base voltage would be pretty much the same voltage as PA11 in that situation. The port pin is much stronger than the 4.7K resistor.
If you wanted to, you could leave the SODR part the way it is (or not) and initialize the port pin to use MD mode (PIO_MDER). That would basically make it open-drain. It would offer marginally more protection against anybody accidentally setting the pin high.
However...
You bring to mind an interesting point about port pins having their pullups enabled upon reset (the state that you allude to in SAM-BA). A fact which I had inconveniently forgotten about.
I need to take that into account in my math. The port pin pullups may be too strong for this to work. I, too, thought the pullups were weak, but judging from the figures given for I[PULLUP] in the datasheet, it is not encouraging. 600uA doesn't sound like much until you consider it's 0.6ma. My 4.7K resistor could never get that down to 0.6V. This appears to be a showstopper.
There seems to be no way to get around having to make a more extensive hardware modification, which would surely require cutting traces.
So far, the best solution I've come up with is to replace Q1 with something like this: http://www.fairchildsemi.com/pf/NC/NC7S08.html
That particular part is rated for a maximum of 12.5ma, so it ought to be able to drive 2.2ma (3.3v through 1.5K). Q1 could be retained as a voltage-follower, but the chip ought to be able to handle it. Reworking that onto the existing board would be a royal pain, though. As would sourcing small quantities of the part.
Short of that, it might work to put a diode between PA11 and R20 and another between NRST and R20. Because of the diode voltage drop (and the fact that CMOS low levels aren't necessarily 0V), though, the pullup might not get fully shut off. I suppose Schottky diodes are an option. The few tenths of a volt difference could mean the difference between the pullup being fully off and being pulled up to 0.7V.
Either of those two modifications wouldn't require any firmware changes. Of course, the one you mentioned wouldn't hurt either of them, either.

