some bugfixes

This commit is contained in:
Marco Scholl 2024-03-29 22:32:18 +01:00
parent 8388c79f9f
commit cf1b6bc7ac
No known key found for this signature in database
2 changed files with 63 additions and 67 deletions

View File

@ -169,11 +169,9 @@ void __isr __time_critical_func(TpUartDataLinkLayer::processRx)(bool isr)
_rxOverflow = true; _rxOverflow = true;
// verarbeiten daten // verarbeiten daten
uint8_t counter = isr ? 10 : 255; while (_platform.uartAvailable())
while (_platform.uartAvailable() && counter > 0)
{ {
processRxByte(); processRxByte();
counter--;
} }
isrUnlock(); isrUnlock();
@ -190,49 +188,28 @@ void TpUartDataLinkLayer::processRxByte()
if (byte < 0) if (byte < 0)
return; return;
if (_rxState == RX_FRAME) /*
* Wenn ich im RX_INVALID state bin
* und das letzte Byte vor mehr als 2ms verarbeitet wurde (also pause >2ms)
* und keine weiteren Bytes vorliegen,
* dann kann ich den INVALID State verwerfen.
*/
if (_rxState == RX_INVALID && (millis() - _rxLastTime) > 2 && !_platform.uartAvailable())
{ {
processRxFrameByte(byte); println("Reset RX_INVALID");
}
else if ((byte & L_DATA_MASK) == L_DATA_STANDARD_IND || (byte & L_DATA_MASK) == L_DATA_EXTENDED_IND)
{
/*
* Verarbeite ein vorheriges Frame falls noch vorhanden. Das dürfte normal nur im Busmonitor auftreten, weil hier noch auch ein ACK gewartet wird
*/
processRxFrameComplete(); processRxFrameComplete();
_rxState = RX_IDLE;
_rxFrame->addByte(byte);
// Provoziere ungültige Frames für Tests
// if (millis() % 20 == 0)
// _rxFrame->addByte(0x1);
_rxMarker = false;
_rxState = RX_FRAME;
/*
* Hier wird inital ein Ack ohne Addressed gesetzt. Das dient dazu falls noch ein Ack vom vorherigen Frame gesetzt wurde,
* welches aber ggf nicht rechtzeitig verarbeitet (also nach der Übertragung gesendet wurde) sich nicht auf das neue Frame auswirkt.
* Der Zustand kann beliebig oft gesendet werden. Sobald der Moment gekommen ist, dass ein Ack gesendet wird, schaut TPUart im Buffer
* was der letzte Ackstatus war und sendet diesen.
*
* Das darf man natürlich nur wenn ich nicht gerade selber sende, da man eigene Frames nicht ACKt
*/
if (_txState == TX_IDLE)
{
_platform.writeUart(U_ACK_REQ);
}
} }
else if (_rxState == RX_INVALID || _rxOverflow)
if (_rxState == RX_INVALID)
{ {
/* /*
* Sobald ein Frame ungültig verarbeitet wurde oder ein unbekanntest Kommando eintrifft ist wechselt der Zustand in RX_INVALID. * Sobald ein Frame ungültig verarbeitet wurde oder ein unbekanntes Kommando eintrifft, wechselt der Zustand in RX_INVALID.
* Ab jetzt muss ich davon ausgehen, dass einen Übertragungsfehler gegeben hat und die aktuellen Bytes ungültig sind. * Ab jetzt muss ich davon ausgehen, dass einen Übertragungsfehler gegeben hat und die aktuellen Bytes ungültig sind.
* Gleiches gilt auch wenn ein HW Overflow erkannt wurde * Gleiches gilt auch wenn ein HW Overflow erkannt wurde.
* *
* - Dieser Zustand wird aufgehoben wenn ein Frame "vermutlich" erkannt wurde. (if Abfrage über dieser) * - Die Zeit des letzten Frames 3ms vorbei ist (kann aber nicht garantiert werden, wegen möglichem ISR & DMA. Hier sollte es das Problem aber nicht geben)
* - Die Zeit des letzten Frames 3ms vorbei ist (erfolt im loop) * - Wenn der Markermodus aktiv ist und ein U_FRAME_END_IND sauber erkannt wurde. (Wird hier geprüft)
* - Wenn der Markermodus aktiv ist und ein U_FRAME_END_IND sauber erkannt wurde. (passiert hiert)
* *
* Ansonsten macht dieser Abschnitt nichts und verwirrft die ungültigen Bytes * Ansonsten macht dieser Abschnitt nichts und verwirrft die ungültigen Bytes
*/ */
@ -253,11 +230,38 @@ void TpUartDataLinkLayer::processRxByte()
_rxMarker = false; _rxMarker = false;
_rxState = RX_IDLE; _rxState = RX_IDLE;
} }
else }
{ }
// print("RX_INVALID: "); else if (_rxState == RX_FRAME)
// println(byte, HEX); {
} processRxFrameByte(byte);
}
else if ((byte & L_DATA_MASK) == L_DATA_STANDARD_IND || (byte & L_DATA_MASK) == L_DATA_EXTENDED_IND)
{
/*
* Verarbeite ein vorheriges Frame falls noch vorhanden. Das dürfte normal nur im Busmonitor auftreten, weil hier noch auch ein ACK gewartet wird
*/
processRxFrameComplete();
_rxFrame->addByte(byte);
// Provoziere ungültige Frames für Tests
// if (millis() % 20 == 0)
// _rxFrame->addByte(0x1);
_rxMarker = false;
_rxState = RX_FRAME;
/*
* Hier wird inital ein Ack ohne Addressed gesetzt. Das dient dazu falls noch ein Ack vom vorherigen Frame gesetzt wurde,
* welches aber ggf nicht rechtzeitig verarbeitet (also nach der Übertragung gesendet wurde) sich nicht auf das neue Frame auswirkt.
* Der Zustand kann beliebig oft gesendet werden. Sobald der Moment gekommen ist, dass ein Ack gesendet wird, schaut TPUart im Buffer
* was der letzte Ackstatus war und sendet diesen.
*
* Das darf man natürlich nur wenn ich nicht gerade selber sende, da man eigene Frames nicht ACKt
*/
if (_txState == TX_IDLE)
{
_platform.writeUart(U_ACK_REQ);
} }
} }
else else
@ -576,17 +580,17 @@ bool TpUartDataLinkLayer::sendFrame(CemiFrame &cemiFrame)
* Außerdem soll regelmäßig die aktuelle Config bzw der Modus übermittelt werden, so dass nach einem Disconnect, * Außerdem soll regelmäßig die aktuelle Config bzw der Modus übermittelt werden, so dass nach einem Disconnect,
* der TPUart im richtigen Zustand ist. * der TPUart im richtigen Zustand ist.
*/ */
void TpUartDataLinkLayer::requestState() void TpUartDataLinkLayer::requestState(bool force /* = false */)
{ {
if (_rxState != RX_IDLE) if (!force)
return; {
if (!(_rxState == RX_IDLE || _rxState == RX_INVALID))
return;
if (_txState != TX_IDLE) // Nur 1x pro Sekunde
return; if ((millis() - _lastStateRequest) < 1000)
return;
// Nur 1x pro Sekunde }
if ((millis() - _lastStateRequest) < 1000)
return;
// println("requestState"); // println("requestState");
@ -720,7 +724,7 @@ bool TpUartDataLinkLayer::reset()
if (success) if (success)
{ {
_lastStateRequest = 0; // Force _lastStateRequest = 0; // Force
requestState(); requestState(true);
_rxLastTime = millis(); _rxLastTime = millis();
} }
@ -860,6 +864,7 @@ void TpUartDataLinkLayer::loop()
{ {
println("TPUart overflow detected!"); println("TPUart overflow detected!");
_rxOverflow = false; _rxOverflow = false;
_rxState = RX_INVALID;
} }
if (_tpState) if (_tpState)
@ -869,7 +874,7 @@ void TpUartDataLinkLayer::loop()
_tpState = 0; _tpState = 0;
} }
processRx(); // processRx();
#ifdef USE_TP_RX_QUEUE #ifdef USE_TP_RX_QUEUE
processRxQueue(); processRxQueue();
#endif #endif
@ -877,16 +882,6 @@ void TpUartDataLinkLayer::loop()
requestState(); requestState();
processTxQueue(); processTxQueue();
checkConnected(); checkConnected();
/*
* Normal ist alles so gebaut worde, dass anhand der Bytes entschieden wird wann ein Frame "fertig" ist oder nicht.
* Dennoch gibt es Situationen, wo ein Frame nicht geschlossen wurde, weil Bytes verloren geangen sind oder wie beim Busmonitor
* bewusst auf ein Ack gewartet werden muss.
*/
// if (!_platform.uartAvailable() && _rxFrame->size() > 0 && (millis() - _rxLastTime) > 2)
// {
// processRxFrameComplete();
// }
} }
void TpUartDataLinkLayer::rxFrameReceived(TpFrame *tpFrame) void TpUartDataLinkLayer::rxFrameReceived(TpFrame *tpFrame)
@ -1066,7 +1061,8 @@ void TpUartDataLinkLayer::processRxFrame(TpFrame *tpFrame)
printFrame(tpFrame); printFrame(tpFrame);
println(); println();
#endif #endif
rxFrameReceived(tpFrame); if (!(tpFrame->flags() & TP_FRAME_FLAG_ECHO))
rxFrameReceived(tpFrame);
} }
} }

View File

@ -137,7 +137,7 @@ class TpUartDataLinkLayer : public DataLinkLayer
void processRxFrameComplete(); void processRxFrameComplete();
inline void processRxFrame(TpFrame* tpFrame); inline void processRxFrame(TpFrame* tpFrame);
void pushTxFrameQueue(TpFrame* tpFrame); void pushTxFrameQueue(TpFrame* tpFrame);
void requestState(); void requestState(bool force = false);
void requestConfig(); void requestConfig();
inline void processRxFrameByte(uint8_t byte); inline void processRxFrameByte(uint8_t byte);