Skip to content

Commit 96daba1

Browse files
Merge pull request #40 from kfox/fw-transfer-deadlines
Discard what a failed remote transfer still sends, and don't block on flush ...and thank you again!
2 parents 9fec8ff + 54c1f7a commit 96daba1

3 files changed

Lines changed: 35 additions & 21 deletions

File tree

‎Source/Teensy/FileTransfer.ino‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ FLASHMEM bool ReceiveFileData(File& file, uint32_t len, uint32_t& checksum)
115115
SendU16(FailToken);
116116
CmdChannel->printf("Rec %lu of %lu bytes\n", bytenum, len);
117117
file.close();
118+
DiscardCmdInput(len - bytenum, millis(), len - bytenum);
118119
return false;
119120
}
120121
file.write(byteIn = CmdChannel->read());
@@ -209,7 +210,11 @@ FLASHMEM void PostFileCommand()
209210

210211
SendU16(AckToken);
211212

212-
if (!ReceiveFileData(fileStream, fileLength, checksum)) return;
213+
if (!ReceiveFileData(fileStream, fileLength, checksum))
214+
{
215+
sourceFS->remove(FileNamePath); //GetFileStream made it, so a retry finds no "File already exists"
216+
return;
217+
}
213218

214219
SendU16(AckToken);
215220

@@ -628,7 +633,7 @@ FLASHMEM bool SendFileData(File& file, uint32_t len) {
628633

629634
Printf_dbg("[SendFileData] Complete - Sent %lu bytes\n", bytenum);
630635
Printf_dbg("[SendFileData] Flushing output...\n");
631-
CmdChannel->flush();
636+
FlushCmdChannel(CmdChannel);
632637
Printf_dbg("[SendFileData] Flush complete\n");
633638
return true;
634639
}

‎Source/Teensy/SerUSBIO.ino‎

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ FLASHMEM void ServiceSerial(Stream *ThisCmdChannel)
292292
if(StartMicros>MaxMicros) MaxMicros=StartMicros;
293293
if(StartMicros<MinMicros) MinMicros=StartMicros;
294294
CmdChannel->printf("Took %luuS to send %d Regs\n", StartMicros, RegsInPacket);
295-
CmdChannel->flush();
295+
FlushCmdChannel(CmdChannel);
296296
delay(10); //allow scope time to re-arm
297297
}
298298
CmdChannel->printf(" %d packets, %luuS Min to %luuS Max\n", NumPackets, MinMicros, MaxMicros);
@@ -851,6 +851,13 @@ FLASHMEM bool GetUInt(uint32_t *InVal, uint8_t NumBytes)
851851
return true;
852852
}
853853

854+
FLASHMEM void FlushCmdChannel(Stream *Channel)
855+
{
856+
// EthernetClient::flush() and USBSerialBase::flush() wait with no deadline for the peer
857+
// to ACK; the bytes are already queued to go without them.
858+
if (Channel == &Serial) Serial.send_now();
859+
}
860+
854861
FLASHMEM void SendU16(uint16_t SendVal)
855862
{
856863
CmdChannel->write((uint8_t)(SendVal & 0xff));
@@ -984,6 +991,23 @@ FLASHMEM void getFreeITCM()
984991
//CmdChannel->printf( "ITCM DWORD cnt = %u [#bytes=%u] \n", jj, jj*4);
985992
}
986993

994+
// The WriteC64Spans command's deadline for the whole command, not only SerialAvailabeTimeout's per
995+
// byte, which leaves every byte's wait for the peer to spend with the C64 unserved. 2 bytes/mS is
996+
// under every channel's rate, the 115200 baud USB host port included. Bytes is the command's length so far.
997+
FLASHMEM uint32_t SpansCeilingmS(uint32_t Bytes) { return SerialTimoutMillis * 10 + Bytes / 2; }
998+
999+
// Throws away up to Owed bytes a failed sender can still send unprompted, so they are not parsed
1000+
// as commands. Ends early on quiet longer than a TCP retransmit, or 2 S past SpansCeilingmS(Bytes)
1001+
// counted from Began. A caller with no command deadline passes millis() and Owed, so the ceiling
1002+
// runs from the failure; WriteC64Spans passes its command's start and length, so it runs from there.
1003+
FLASHMEM void DiscardCmdInput(uint32_t Owed, uint32_t Began, uint32_t Bytes)
1004+
{
1005+
const uint32_t CeilingmS = SpansCeilingmS(Bytes) + SerialTimoutMillis * 4;
1006+
uint32_t Quiet = millis();
1007+
while (Owed && millis() - Quiet < SerialTimoutMillis * 2 && millis() - Began < CeilingmS)
1008+
if (CmdChannel->available()) { CmdChannel->read(); Owed--; Quiet = millis(); }
1009+
}
1010+
9871011
#ifdef Dbg_SerSD
9881012
// SD card info, then a copy of SdFat's TeensySdioDemo speed test (examples/TeensySdioDemo), then
9891013
// what a MinimalBoot bank swap does (LoadBank in IOH_EasyFlash.c): a seek and one 8K read, timed in uS.
@@ -1209,7 +1233,6 @@ struct DMAStage
12091233
FLASHMEM void WriteC64MemCommand()
12101234
{
12111235
uint32_t DMAAddr, DMALength;
1212-
const uint32_t Began = millis();
12131236

12141237
if (!GetUInt(&DMAAddr, 2))
12151238
{
@@ -1231,7 +1254,7 @@ FLASHMEM void WriteC64MemCommand()
12311254
{
12321255
SendU16(FailToken);
12331256
CmdChannel->printf("No memory to stage %lu bytes\n", DMALength);
1234-
DiscardCmdInput(DMALength, Began, DMALength); // sent unprompted, and not to be read as commands
1257+
DiscardCmdInput(DMALength, millis(), DMALength); // sent unprompted, and not to be read as commands
12351258
return;
12361259
}
12371260

@@ -1241,6 +1264,7 @@ FLASHMEM void WriteC64MemCommand()
12411264
{
12421265
SendU16(FailToken);
12431266
CmdChannel->println("Error receiving data!");
1267+
DiscardCmdInput(DMALength - ByteNum, millis(), DMALength - ByteNum);
12441268
return;
12451269
}
12461270
DMABuf[ByteNum] = CmdChannel->read();
@@ -1272,21 +1296,6 @@ FLASHMEM void WriteC64MemCommand()
12721296
//Serial.printf("DMA Write: addr $%04x:$%04x (%lu Bytes)\n", DMAAddr, DMAAddr+DMALength-1, DMALength);
12731297
}
12741298

1275-
// One deadline for the whole command, not only SerialAvailabeTimeout's per byte, which leaves
1276-
// every byte's wait for the peer to spend with the C64 unserved. 2 bytes/mS is under every
1277-
// channel's rate, the 115200 baud USB host port included. Bytes is the command's length so far.
1278-
FLASHMEM uint32_t SpansCeilingmS(uint32_t Bytes) { return SerialTimoutMillis * 10 + Bytes / 2; }
1279-
1280-
// Throws away up to Owed bytes a failed sender can still send unprompted, so they are not parsed
1281-
// as commands. Ends early on quiet longer than a TCP retransmit, or 2 S past the command's deadline.
1282-
FLASHMEM void DiscardCmdInput(uint32_t Owed, uint32_t Began, uint32_t Bytes)
1283-
{
1284-
const uint32_t CeilingmS = SpansCeilingmS(Bytes) + SerialTimoutMillis * 4;
1285-
uint32_t Quiet = millis();
1286-
while (Owed && millis() - Quiet < SerialTimoutMillis * 2 && millis() - Began < CeilingmS)
1287-
if (CmdChannel->available()) { CmdChannel->read(); Owed--; Quiet = millis(); }
1288-
}
1289-
12901299
// After is what the sender goes on to send without waiting for a reply. On false a FailToken
12911300
// has gone out. Patient waits out a pause under the command's deadline alone, rather than
12921301
// SerialAvailabeTimeout's per byte.

‎Source/Teensy/Teensy.ino‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void loop()
299299
#ifdef DbgIOTraceLog
300300
PrintResetSnapshot();
301301
#endif
302-
CmdChannel->flush();
302+
FlushCmdChannel(CmdChannel);
303303
delay(50);
304304
uint32_t NextInterval = 10000, beginWait = millis();
305305
bool LEDState = true, DefEEPReboot = false;

0 commit comments

Comments
 (0)