@@ -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+
854861FLASHMEM 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
12091233FLASHMEM 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.
0 commit comments