Skip to content

Commit 8a842ef

Browse files
committed
cores: Replace HardwareSerial.cpp with master version.
Signed-off-by: Frederikwag <[email protected]>
1 parent 85185d9 commit 8a842ef

File tree

1 file changed

+64
-17
lines changed

1 file changed

+64
-17
lines changed

cores/HardwareSerial.cpp

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ HardwareSerial::HardwareSerial(XMC_UART_t *xmc_uart_config,
3232
RingBuffer *tx_buffer) {
3333
_XMC_UART_config = xmc_uart_config;
3434
_rx_buffer = rx_buffer;
35-
_tx_buffer = tx_buffer; // TODO: replaced by TBUF (hardware register), can be actually removed
35+
_tx_buffer = tx_buffer;
3636
}
3737

3838
// Public Methods //////////////////////////////////////////////////////////////
@@ -119,12 +119,10 @@ int HardwareSerial::available(void) {
119119
}
120120

121121
int HardwareSerial::availableForWrite(void) {
122-
int available = XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel);
123-
if (available == XMC_USIC_CH_TBUF_STATUS_IDLE) {
124-
return 0;
125-
} else {
126-
return 1;
127-
} // TODO: should return bytes avaliable to write! need to enable txFIFO in the future
122+
int tail = _tx_buffer->_iTail; // Snapshot index affected by irq
123+
if (_tx_buffer->_iHead >= tail)
124+
return SERIAL_BUFFER_SIZE - 1 - _tx_buffer->_iHead + tail;
125+
return tail - _tx_buffer->_iHead - 1;
128126
}
129127

130128
int HardwareSerial::peek(void) {
@@ -146,19 +144,59 @@ int HardwareSerial::read(void) {
146144
}
147145

148146
void HardwareSerial::flush(void) {
147+
while (_tx_buffer->_iHead != _tx_buffer->_iTail)
148+
; // wait for transmit data to be sent
149+
149150
while (XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) ==
150151
XMC_USIC_CH_TBUF_STATUS_BUSY)
151152
;
152153
}
153154

154155
size_t HardwareSerial::write(const uint8_t uc_data) {
155-
// Is the hardware currently busy?
156-
157-
// Make sure TX interrupt is enabled
158-
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
159-
// Bypass buffering and send character directly
160-
XMC_UART_CH_Transmit(_XMC_UART_config->channel, uc_data);
161-
156+
// Is the hardware currently busy?
157+
#if defined(SERIAL_USE_U1C1)
158+
if (_tx_buffer->_iTail != _tx_buffer->_iHead)
159+
#else
160+
if ((XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) ==
161+
XMC_USIC_CH_TBUF_STATUS_BUSY) ||
162+
(_tx_buffer->_iTail != _tx_buffer->_iHead))
163+
#endif
164+
{
165+
// If busy we buffer
166+
int nextWrite = _tx_buffer->_iHead + 1;
167+
if (nextWrite >= SERIAL_BUFFER_SIZE)
168+
nextWrite = 0;
169+
170+
// This should always be false but in case transmission is completed before buffer, we need
171+
// to reenable IRQ
172+
if (XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) !=
173+
XMC_USIC_CH_TBUF_STATUS_BUSY) {
174+
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
175+
XMC_UART_CH_Transmit(_XMC_UART_config->channel,
176+
_tx_buffer->_aucBuffer[_tx_buffer->_iTail]);
177+
_tx_buffer->_iTail++;
178+
if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
179+
_tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
180+
// Size calculate the correct index value
181+
}
182+
183+
unsigned long startTime = millis();
184+
while (_tx_buffer->_iTail == nextWrite) {
185+
if (millis() - startTime > 1000) {
186+
return 0; // Spin locks if we're about to overwrite the buffer. This continues once
187+
// the data is
188+
// sent
189+
}
190+
}
191+
192+
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
193+
_tx_buffer->_iHead = nextWrite;
194+
} else {
195+
// Make sure TX interrupt is enabled
196+
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
197+
// Bypass buffering and send character directly
198+
XMC_UART_CH_Transmit(_XMC_UART_config->channel, uc_data);
199+
}
162200
return 1;
163201
}
164202

@@ -182,11 +220,20 @@ void HardwareSerial::IrqHandler(void) {
182220
XMC_UART_CH_ClearStatusFlag(_XMC_UART_config->channel,
183221
XMC_UART_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION);
184222

185-
// Mask off transmit interrupt so we don't get it any more
186-
XMC_UART_CH_DisableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
223+
if (_tx_buffer->_iTail != _tx_buffer->_iHead) {
224+
XMC_UART_CH_Transmit(_XMC_UART_config->channel,
225+
_tx_buffer->_aucBuffer[_tx_buffer->_iTail]);
226+
_tx_buffer->_iTail++;
227+
if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
228+
_tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
229+
// Size calculate the correct index value
230+
} else {
231+
// Mask off transmit interrupt so we don't get it any more
232+
XMC_UART_CH_DisableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
233+
}
187234
}
188235
}
189236

190237
//****************************************************************************
191238
// END OF FILE
192-
//****************************************************************************
239+
//****************************************************************************

0 commit comments

Comments
 (0)