Skip to content

Commit

Permalink
fixes some problems with txqueue
Browse files Browse the repository at this point in the history
  • Loading branch information
traxanos committed Apr 8, 2024
1 parent e65afeb commit 1754e53
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 22 deletions.
89 changes: 68 additions & 21 deletions src/knx/tpuart_data_link_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,7 @@ void TpUartDataLinkLayer::processRxByte()
if (_txState == TX_FRAME)
{
const bool success = ((byte ^ L_DATA_CON_MASK) >> 7);
uint8_t *cemiData = _txFrame->cemiData();
CemiFrame cemiFrame(cemiData, _txFrame->cemiSize());
dataConReceived(cemiFrame, success);
free(cemiData);
delete _txFrame;
_txFrame = nullptr;
_txState = TX_IDLE;
processTxFrameComplete(success);
}
else
{
Expand Down Expand Up @@ -436,7 +430,7 @@ void TpUartDataLinkLayer::processRxFrameByte(uint8_t byte)
if (availableInRxQueue() < (_rxFrame->size() + 3))
{
// Nur wenn ich nicht selber sende
if (_txState == RX_IDLE)
if (_txState == TX_IDLE)
{
_platform.writeUart(U_ACK_REQ | U_ACK_REQ_ADRESSED | U_ACK_REQ_BUSY);
}
Expand Down Expand Up @@ -529,6 +523,30 @@ void TpUartDataLinkLayer::processRxFrameComplete()
_rxFrame->reset();
}

void TpUartDataLinkLayer::clearTxFrame()
{
if (_txFrame != nullptr)
{
delete _txFrame;
_txFrame = nullptr;
}
}

void TpUartDataLinkLayer::clearTxFrameQueue()
{
}

void TpUartDataLinkLayer::processTxFrameComplete(bool success)
{
uint8_t *cemiData = _txFrame->cemiData();
CemiFrame cemiFrame(cemiData, _txFrame->cemiSize());
dataConReceived(cemiFrame, success);
free(cemiData);
clearTxFrame();
_txProcessdFrameCounter++;
_txState = TX_IDLE;
}

/*
* Steckt das zu sendende Frame in eine Queue, da der TpUart vielleicht gerade noch nicht sende bereit ist.
*/
Expand All @@ -545,6 +563,14 @@ void TpUartDataLinkLayer::pushTxFrameQueue(TpFrame *tpFrame)
_txFrameQueue.back->next = entry;
_txFrameQueue.back = entry;
}

if (_txQueueCount > 10)
{
print("_txQueueCount:");
print(_txQueueCount);
}
_txQueueCount++;
_txFrameCounter++;
}

void TpUartDataLinkLayer::setRepetitions(uint8_t nack, uint8_t busy)
Expand Down Expand Up @@ -685,17 +711,15 @@ bool TpUartDataLinkLayer::reset()
_rxInvalidFrameCounter = 0;
_rxInvalidFrameCounter = 0;
_rxUnkownControlCounter = 0;
if (_txFrame != nullptr)
{
_txFrame = nullptr;
delete _txFrame;
}

clearTxFrame();
clearTxFrameQueue();

if (_rxFrame != nullptr)
{
_rxFrame->reset();
}
_rxState = RX_IDLE;
_txState = TX_IDLE;
_connected = false;
_stopped = false;
_monitoring = false;
Expand Down Expand Up @@ -786,17 +810,24 @@ bool TpUartDataLinkLayer::enabled() const
return _initialized && _connected;
}

/*
* Wenn ein TxFrame gesendet wurde, wird eine Bestätigung für den Versand erwartet.
* Kam es aber zu einem ungültigen Frame oder Busdisconnect, bleibt die Bestätigung aus und der STack hängt im TX_FRAME fest.
* Daher muss nach einer kurzen Wartezeit das Warten beendet werden.
*/
void TpUartDataLinkLayer::clearOutdatedTxFrame()
{
if (_txState == TX_FRAME && (millis() - _txLastTime) > 1000)
processTxFrameComplete(false);
}

/*
* Hier werden die ausgehenden Frames aus der Warteschlange genomnmen und versendet.
* Das passiert immer nur einzelnd, da nach jedem Frame, gewartet werden muss bis das Frame wieder reingekommen ist und das L_DATA_CON rein kommt.
*
*/
void TpUartDataLinkLayer::processTxQueue()
{
// Diese Abfrage ist vorsorglich. Eigentlich sollte auch schon parallel gestartet werden können.
if (_rxState != RX_IDLE)
return;

if (_txState != TX_IDLE)
return;

Expand All @@ -810,9 +841,9 @@ void TpUartDataLinkLayer::processTxQueue()
_txFrameQueue.back = nullptr;
}

// free old frame
if (_txFrame != nullptr)
delete _txFrame;
_txQueueCount--;

clearTxFrame();

// use frame from queue and delete queue entry
_txFrame = entry->frame;
Expand Down Expand Up @@ -892,6 +923,7 @@ void TpUartDataLinkLayer::loop()
#endif

requestState();
clearOutdatedTxFrame();
processTxQueue();
checkConnected();
}
Expand Down Expand Up @@ -1015,6 +1047,21 @@ uint32_t TpUartDataLinkLayer::getRxUnknownControlCounter()
return _rxUnkownControlCounter;
}

/*
* Liefert die Anzahl der zusendenden Frames
*/
uint32_t TpUartDataLinkLayer::getTxFrameCounter()
{
return _txFrameCounter;
}
/*
* Liefert die Anzahl der versendeten Frames
*/
uint32_t TpUartDataLinkLayer::getTxProcessedFrameCounter()
{
return _txProcessdFrameCounter;
}

bool TpUartDataLinkLayer::isConnected()
{
return _connected;
Expand Down
10 changes: 9 additions & 1 deletion src/knx/tpuart_data_link_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class TpUartDataLinkLayer : public DataLinkLayer
uint32_t getRxProcessdFrameCounter();
uint32_t getRxIgnoredFrameCounter();
uint32_t getRxUnknownControlCounter();
uint32_t getTxFrameCounter();
uint32_t getTxProcessedFrameCounter();
uint8_t getMode();

private:
Expand Down Expand Up @@ -95,19 +97,21 @@ class TpUartDataLinkLayer : public DataLinkLayer
volatile bool _busy = false;
volatile bool _initialized = false;

volatile uint32_t _stateTime = 0;
volatile uint8_t _rxState = 0;
volatile uint8_t _txState = 0;
volatile uint32_t _rxProcessdFrameCounter = 0;
volatile uint32_t _rxInvalidFrameCounter = 0;
volatile uint32_t _rxIgnoredFrameCounter = 0;
volatile uint32_t _rxUnkownControlCounter = 0;
volatile uint32_t _txFrameCounter = 0;
volatile uint32_t _txProcessdFrameCounter = 0;
volatile bool _rxMarker = false;
volatile bool _rxOverflow = false;
volatile uint8_t _tpState = 0x0;
volatile uint32_t _txLastTime = 0;
volatile uint32_t _rxLastTime = 0;
volatile bool _forceAck = false;
uint8_t _txQueueCount = 0;

inline bool markerMode();

Expand All @@ -134,6 +138,7 @@ class TpUartDataLinkLayer : public DataLinkLayer
void checkConnected();
void processRxByte();
void processTxQueue();
void clearTxFrameQueue();
void processRxFrameComplete();
inline void processRxFrame(TpFrame* tpFrame);
void pushTxFrameQueue(TpFrame* tpFrame);
Expand All @@ -159,6 +164,9 @@ class TpUartDataLinkLayer : public DataLinkLayer
inline void isrUnlock();
inline void clearUartBuffer();
inline void connected(bool state = true);
void clearTxFrame();
void clearOutdatedTxFrame();
void processTxFrameComplete(bool success);

ITpUartCallBacks& _cb;
DataLinkLayerCallbacks* _dllcb;
Expand Down

0 comments on commit 1754e53

Please sign in to comment.