trying /dev/serial/by-id/usb-Parallax_Inc_Propeller_P2-ES_EVAL_P23YOO42-if00-port0 with timeout of 50 ms...
P2 version G found on serial port /dev/serial/by-id/usb-Parallax_Inc_Propeller_P2-ES_EVAL_P23YOO42-if00-port0
Setting load mode to CHIP
Setting clock_mode to 12427f8
Loading fast loader for chip...
Loading Flash_loader_ebh3.binary - 5088 bytes
chksum: 42 OK
Flash_loader_ebh3.binary loaded
Ah, just pushed it over the edge with an unstable binary, due to too high sysclock, in the Flash chip that goes wonky. My tweaked loadp2 can recover it, on second attempt, without having to change the dip switches. Yours tries 50 ms then 500 ms without finding the prop2 and repeated attempts doesn't make progress. Actually, I need to solve why it even takes two attempts with my tweaks too ...
Okay, the problem with mine is because of unflushed garbage in the PC's comport buffers. One of the side effects of the errant binary is it spews garbage down the comport.
My loadp2 actually downloads fine on first attempt because it is operating blindly until the very end and only when it goes to check for the prop2 response of "." does it get confused. This of course has updated the prop2 with the fixed version of the binary so the next attempt is no problem.
I'm guessing your latest loadp2 is suffering the same garbage in the buffers but with the extra checks it is giving up before downloading the binary.
No, 90 ms is too long. Dave would have chosen it to be shorter than the 100 ms timeout but that is actually too close to 100 ms. In colder temperatures RCFAST goes quite a lot faster.
EDIT: Hmm, unless the spec is guaranteed to be longer than 100 ms on the timeout.
Well, on Linux over a 20 metre USB 1.0 active extension cable + hub, testing at various sleeptime's the flushing of spewing data works right down to a 15 ms sleep time on the first method above. Don't need to duplicate Dave's original fixed 90 ms, IMHO.
I tested that. For some reason, presumably to do with serial bits still arriving, it needs to have some milliseconds (15 ms for me) duration between the DTR resetting the prop2 and the buffer being flushed, or it won't clean up enough.
I quite liked the tidiness of moving the settable "sleeptime" into the hwreset() function, providing for both requirements (delay needed for prop2 hard reset response and also this flushing) in one place.
I tested that. For some reason, presumably to do with serial bits still arriving, it needs to have some milliseconds (15 ms for me) duration between the DTR resetting the prop2 and the buffer being flushed, or it won't clean up enough.
That's for the case of P2 user code sending, when reset arrives ?
Maybe that's the hardware uart buffers in action ? What baud rate was that at ?
Another way to mange that, could be to Empty Rx and retry a few times, should unexpected chars appear ?
That should be both HW delays, and HW buffer size tolerant.
Other points :
a) In the UB3 UART Bridge for P2D2, I've bumped the HW buffer to 1536 bytes, so that may store more unwanted chars, if reset during a stream ?
(some FTDI parts have 2K buffers)
I do notice the SiLabs code does this
if (DEVICE_OPEN_f) { // Reset variable state
resetState(); // reset buffer states and init uart, 16b loads into pointers, apply baud..
rxIdleTime = RX_FLUSH_TIME;
} // endif DEVICE_OPEN
So maybe a simple re-apply of the open(), can be used to flush the USB-UART HW buffers ? (Perhaps a call to TCIFLUSH does the same thing ?)
b) Why the double reset pulse ?
On the UB3 I've added a monostable internally, that pulses the reset pin low for 100us on the leading edge of DTR
That's done for a couple of reasons - to make reset exit as fast as possible, and to reduce jitter, should someone's design want multiple-P2 sync's / restarts.
Or if that 90 ms was important for reliable operation on other platforms then an extra step would be in order...
It may be that longer time is also related to various possible or historic Prop reset circuits ?
Reset Pulse exit is going to be rather variable, and will depend on user designs.
Some use differing caps in the edge drive, & even differing edges, and then there is the reset cap on the board itself....
I've also seen reset-devices that stretch a reset pulse, so the SW needs to be somewhat tolerant to longer exit times, but flexible enough to be quick if P2 is quick.
That's one reason I favour the multiple-tries, as those can exit as soon as P2 responds.
Or if that 90 ms was important for reliable operation on other platforms then an extra step would be in order...
It may be that longer time is also related to various possible or historic Prop reset circuits ?
This is not the resetting pulse itself but post reset actions. The 2 ms is for the pulse length.
I'm pretty sure that value of 90 ms was just made as big as Dave thought was possible (100 ms causes problems). Rather than setting at least a middle value like 40 ms.
Or if that 90 ms was important for reliable operation on other platforms then an extra step would be in order...
It may be that longer time is also related to various possible or historic Prop reset circuits ?
This is not the resetting pulse itself but post reset actions. The 2 ms is for the pulse length.
Yes, but the pulse the PC generates, is not always what the processor reset pin sees.
Common is a transistor edge pulser, which has its own time constant, and that can discharge another Cap on the reset pin, giving another time constant.
The reset exit time is the sum of those external and variable delays, plus the time the P2 take internally to exit reset.
Heh, sorry, my bad wording. The flush can be placed anywhere after the 40 ms sleep. Importance of the second DTR reset pulse is to eliminate, from post-reset downloading operations, this added flushing delay.
So first reset is to stop the garbage coming at the PC's comport from the prop2. The second reset is for downloading sequence to start.
The two resets could be combined to a single reset but that would need the "sleeptime" parameter inside hwreset() function.
EDIT: JMG's idea of draining the comport after reset has merit but is obviously a whole other set of API calls to be understood. And will still need some timeout to ensure no late stragglers.
EDIT2: Or you could make these steps explicit in main loadp2.c sequence.
if (need_reset) {
hwreset();
msleep(50);
hwreset();
msleep(sleeptime);
}
If you did that then hwreset() goes back to smallest code
void hwreset(void)
{
int cmd = use_rts_for_reset ? TIOCM_RTS : TIOCM_DTR;
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
msleep(2);
ioctl(hSerial, TIOCMBIC, &cmd); /* clear bit */
msleep(2);
ioctl(hSerial, TIOCMBIS, &cmd); /* assert bit */
tcflush(hSerial, TCIFLUSH);
}
And why do you think two reset pulses are necessary? What benefit would there be to resetting the P2 twice?
I wondered that too... maybe 2 pulses is a legacy of stopping a streaming P2 ?
The Python P2 loader has this code for reset - delay between dtr is optional, but likely makes the Sw more circuit tolerant.
sp.dtr = True # toggle DTR Orig - waveform ===\________/========== ~ Optional delay
# sleep(0.01) # UB3 does not need any delay, as it has a monostable on DTR =\_ This delay seems to apply 10ms ~ 12ms measured
sp.dtr = False
The Python loader does not seem to include a flush, so it would be less tolerant of an active-P2.
Best I think is a single reset pulse, and an early flush to empty the serial buffers.
eg
DTR=True,SmallDelay,DTR=False,SmallDelay,Flush, to cover all polarities of reset HW
then either of
Reset-exit-delay, poll P2
or
repeat of : Smalldelay.ReTry-Poll-P2 - this better covers variations in reset exit delay, but also exits quickly on a fast-RST-circuit p2.
... Importance of the second DTR reset pulse is to eliminate, from post-reset downloading operations, this added flushing delay.
The UART flush should empty any errant chaff, making the two resets redundant ? ( and seems more tolerant of P2 links with large buffers and low baud rates )
Yes, it's for eliminating received garbage. I vaguely remember this issue coming up in the past too. At the time I didn't know what Dave did to fix it. Now I know.
I still don't see why 2 resets are needed. As far as I can see the sequence for restarting the P2 should be:
reset the hardware by pulsing RTS and/or DTR
pause for a short period
flush input to ignore any garbage sent by P2 before reset
start talking to the P2 ROM download code
We need to nail down the exact duration for "pause for a short period" (and perhaps it's variable). But I don't see anything in there that should require a second reset.
Are you saying that tcflush(hSerial, TCIFLUSH) is not working to flush the input, and we need an another reset + delay in its place?
I still don't see why 2 resets are needed. As far as I can see the sequence for restarting the P2 should be:
reset the hardware by pulsing RTS and/or DTR
pause for a short period
flush input to ignore any garbage sent by P2 before reset
start talking to the P2 ROM download code
We need to nail down the exact duration for "pause for a short period" (and perhaps it's variable).
The pause will be variable based on user circuits. ie if someone has an extra inversion, reset can occur on the other' DTR edge, but a short pause should be ok (a few ms),
as the P2 will enter reset very soon after the last edge, no matter how the user wires things.
A delay would be needed before talking to the P2, and I like the looping/retry ping approach, as that also discards garbage, & gives a safety-net, should the flush not work on any systems...
I did check sending a series of PropVer pings, even with no delays, a while back, and that seemed to never generate unexpected chars.
Even tho P2 can exit reset part way thru any string, the smart autobaud Chip has, looks only for '>', so it auto-syncs to that char.
Eric,
Yep, that's the right set of steps. However, the original code had two pauses after the reset. One before the flush and another after the flush. And that's what you've fallen back on. There is nothing wrong with having two reset pulses to hide the delay needed for flushing.
The upper limit is 100 ms when SPI booting is enabled. That runs from RCFAST so I'd like to give it some clearance. Also, I've noticed, on Linux at least, that the milliseconds of sleep tends to run long.
Put all that together and I'd like to hold to 50 ms as target delay for reset to first comms.
I did check sending a series of PropVer pings, even with no delays, a while back, and that seemed to never generate unexpected chars.
The need for flushing is when the prop2 has an errant program in the SPI Flash chip spewing garbage all the time. It's not fun having to go back to the dip switches and disable the Flash chip each time this happens. And, as you've pointed out, some boards maybe not have the option for disabling the boot EEPROM.
I did check sending a series of PropVer pings, even with no delays, a while back, and that seemed to never generate unexpected chars.
The need for flushing is when the prop2 has an errant program in the SPI Flash chip spewing garbage all the time.
Understood, and I agree.
My point was more related to early pings, where the P2 exits reset, in the middle of one of many Prop_Ver strings.
That seems to be tolerated, because Chip's Autobaud is very specific to only trigger on the '>' char
Uh-oh, somewhere along the line we've lost stand-alone terminal mode too. I had to revert to July's edition loadp2 to get it back.
EDIT: I've had a look at it. Best guess is it's an auto-baud issue. The only diff in behaviour is the later loadp2's always send "> Prop_Chk 0 0 0 0 " before starting the terminal. The difference between 2 M and 115 k must be too much once set ... In fact telling loadp2 to open the terminal at 2 Mbaud makes it work.
@evanh, @jmg : the loadp2 discussion has been very productive and useful, but I worry that it may be lost in this thread (which is about fastspin rather than loadp2). So I'm going to open a new thread for loadp2 and we can carry on there, if you don't mind.
Comments
My loadp2 actually downloads fine on first attempt because it is operating blindly until the very end and only when it goes to check for the prop2 response of "." does it get confused. This of course has updated the prop2 with the fixed version of the binary so the next attempt is no problem.
I'm guessing your latest loadp2 is suffering the same garbage in the buffers but with the extra checks it is giving up before downloading the binary.
EDIT: I couldn't work out why Dave had such a long sleep in there either. It was for the flush. It won't need that long but I guess some is needed ...
EDIT: Hmm, unless the spec is guaranteed to be longer than 100 ms on the timeout.
I quite liked the tidiness of moving the settable "sleeptime" into the hwreset() function, providing for both requirements (delay needed for prop2 hard reset response and also this flushing) in one place.
That's for the case of P2 user code sending, when reset arrives ?
Maybe that's the hardware uart buffers in action ? What baud rate was that at ?
Another way to mange that, could be to Empty Rx and retry a few times, should unexpected chars appear ?
That should be both HW delays, and HW buffer size tolerant.
Other points :
a) In the UB3 UART Bridge for P2D2, I've bumped the HW buffer to 1536 bytes, so that may store more unwanted chars, if reset during a stream ?
(some FTDI parts have 2K buffers)
I do notice the SiLabs code does this So maybe a simple re-apply of the open(), can be used to flush the USB-UART HW buffers ? (Perhaps a call to TCIFLUSH does the same thing ?)
b) Why the double reset pulse ?
On the UB3 I've added a monostable internally, that pulses the reset pin low for 100us on the leading edge of DTR
That's done for a couple of reasons - to make reset exit as fast as possible, and to reduce jitter, should someone's design want multiple-P2 sync's / restarts.
It may be that longer time is also related to various possible or historic Prop reset circuits ?
Reset Pulse exit is going to be rather variable, and will depend on user designs.
Some use differing caps in the edge drive, & even differing edges, and then there is the reset cap on the board itself....
I've also seen reset-devices that stretch a reset pulse, so the SW needs to be somewhat tolerant to longer exit times, but flexible enough to be quick if P2 is quick.
That's one reason I favour the multiple-tries, as those can exit as soon as P2 responds.
You've gone back to the bad code. Without putting in an extra reset pulse after the flush, the two sleeps add together making one longer sleep.
Please use this
I'm pretty sure that value of 90 ms was just made as big as Dave thought was possible (100 ms causes problems). Rather than setting at least a middle value like 40 ms.
Common is a transistor edge pulser, which has its own time constant, and that can discharge another Cap on the reset pin, giving another time constant.
The reset exit time is the sum of those external and variable delays, plus the time the P2 take internally to exit reset.
And why do you think two reset pulses are necessary? What benefit would there be to resetting the P2 twice?
So first reset is to stop the garbage coming at the PC's comport from the prop2. The second reset is for downloading sequence to start.
The two resets could be combined to a single reset but that would need the "sleeptime" parameter inside hwreset() function.
EDIT: JMG's idea of draining the comport after reset has merit but is obviously a whole other set of API calls to be understood. And will still need some timeout to ensure no late stragglers.
EDIT2: Or you could make these steps explicit in main loadp2.c sequence.
If you did that then hwreset() goes back to smallest code
The Python P2 loader has this code for reset - delay between dtr is optional, but likely makes the Sw more circuit tolerant.
The Python loader does not seem to include a flush, so it would be less tolerant of an active-P2.
Best I think is a single reset pulse, and an early flush to empty the serial buffers.
eg
DTR=True,SmallDelay,DTR=False,SmallDelay,Flush, to cover all polarities of reset HW
then either of
Reset-exit-delay, poll P2
or
repeat of : Smalldelay.ReTry-Poll-P2 - this better covers variations in reset exit delay, but also exits quickly on a fast-RST-circuit p2.
The UART flush should empty any errant chaff, making the two resets redundant ? ( and seems more tolerant of P2 links with large buffers and low baud rates )
Are you saying that tcflush(hSerial, TCIFLUSH) is not working to flush the input, and we need an another reset + delay in its place?
as the P2 will enter reset very soon after the last edge, no matter how the user wires things.
A delay would be needed before talking to the P2, and I like the looping/retry ping approach, as that also discards garbage, & gives a safety-net, should the flush not work on any systems...
I did check sending a series of PropVer pings, even with no delays, a while back, and that seemed to never generate unexpected chars.
Even tho P2 can exit reset part way thru any string, the smart autobaud Chip has, looks only for '>', so it auto-syncs to that char.
Yep, that's the right set of steps. However, the original code had two pauses after the reset. One before the flush and another after the flush. And that's what you've fallen back on. There is nothing wrong with having two reset pulses to hide the delay needed for flushing.
The upper limit is 100 ms when SPI booting is enabled. That runs from RCFAST so I'd like to give it some clearance. Also, I've noticed, on Linux at least, that the milliseconds of sleep tends to run long.
Put all that together and I'd like to hold to 50 ms as target delay for reset to first comms.
My point was more related to early pings, where the P2 exits reset, in the middle of one of many Prop_Ver strings.
That seems to be tolerated, because Chip's Autobaud is very specific to only trigger on the '>' char
EDIT: I've had a look at it. Best guess is it's an auto-baud issue. The only diff in behaviour is the later loadp2's always send "> Prop_Chk 0 0 0 0 " before starting the terminal. The difference between 2 M and 115 k must be too much once set ... In fact telling loadp2 to open the terminal at 2 Mbaud makes it work.