Skip to content

Commit b319791

Browse files
committed
Enable interrupt mode of UART tx
Current version of write will never use the interrupt mode transmission, because it fails to check if holding register is empty. This commit fix that, and several (maybe not all) bugs related to interrupt mode serial transmission.
1 parent 10d1056 commit b319791

File tree

3 files changed

+31
-12
lines changed

3 files changed

+31
-12
lines changed

cores/arduino/UARTClass.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ int UARTClass::read( void )
168168

169169
void UARTClass::flush( void )
170170
{
171-
while (_tx_buffer->_iHead != _tx_buffer->_iTail); //wait for transmit data to be sent
171+
while (_tx_buffer->_iHead != *(volatile int*)&(_tx_buffer->_iTail)); //wait for transmit data to be sent
172172
// Wait for transmission to complete
173173
while(!uart_tx_complete(CONFIG_UART_CONSOLE_INDEX));
174174
}
@@ -179,11 +179,11 @@ size_t UARTClass::write( const uint8_t uc_data )
179179
return(0);
180180

181181
// Is the hardware currently busy?
182-
if (_tx_buffer->_iTail != _tx_buffer->_iHead)
182+
if (_tx_buffer->_iTail != _tx_buffer->_iHead || !uart_tx_ready(CONFIG_UART_CONSOLE_INDEX))
183183
{
184184
// If busy we buffer
185185
int l = (_tx_buffer->_iHead + 1) % SERIAL_BUFFER_SIZE;
186-
while (_tx_buffer->_iTail == l)
186+
while (*(volatile int*)&(_tx_buffer->_iTail) == l)
187187
; // Spin locks if we're about to overwrite the buffer. This continues once the data is sent
188188

189189
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
@@ -201,17 +201,22 @@ size_t UARTClass::write( const uint8_t uc_data )
201201

202202
void UARTClass::IrqHandler( void )
203203
{
204-
uint8_t uc_data;
205-
int ret;
206-
ret = uart_poll_in(CONFIG_UART_CONSOLE_INDEX, &uc_data);
207-
208-
while ( ret != -1 ) {
209-
_rx_buffer->store_char(uc_data);
204+
uart_irq_update(CONFIG_UART_CONSOLE_INDEX);
205+
// if irq is Receiver Data Available
206+
if(uart_irq_rx_ready(CONFIG_UART_CONSOLE_INDEX))
207+
{
208+
uint8_t uc_data;
209+
int ret;
210210
ret = uart_poll_in(CONFIG_UART_CONSOLE_INDEX, &uc_data);
211+
212+
while ( ret != -1 ) {
213+
_rx_buffer->store_char(uc_data);
214+
ret = uart_poll_in(CONFIG_UART_CONSOLE_INDEX, &uc_data);
215+
}
211216
}
212217

213-
// Do we need to keep sending data?
214-
if (!uart_irq_tx_ready(CONFIG_UART_CONSOLE_INDEX))
218+
// if irq is Transmitter Holding Register
219+
else if(uart_irq_tx_ready(CONFIG_UART_CONSOLE_INDEX))
215220
{
216221
if (_tx_buffer->_iTail != _tx_buffer->_iHead) {
217222
uart_poll_out(CONFIG_UART_CONSOLE_INDEX, _tx_buffer->_aucBuffer[_tx_buffer->_iTail]);

system/libarc32_arduino101/drivers/ns16550.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ unsigned char uart_poll_out(
340340
)
341341
{
342342
/* wait for transmitter to ready to accept a character */
343-
while ((INBYTE(LSR(which)) & LSR_TEMT) == 0)
343+
while ((INBYTE(LSR(which)) & LSR_THRE) == 0)
344344
;
345345

346346
OUTBYTE(THR(which), outChar);
@@ -640,6 +640,19 @@ uint8_t uart_tx_complete(int which)
640640
return INBYTE(LSR(which)) & LSR_TEMT;
641641
}
642642

643+
/*******************************************************************************
644+
*
645+
* uart_tx_complete - check if tx holding register is empty
646+
*
647+
* RETURNS: zero if register is non-empty,
648+
* non-zero if register is empty (ready to receive new data)
649+
*/
650+
651+
uint8_t uart_tx_ready(int which)
652+
{
653+
return INBYTE(LSR(which)) & LSR_THRE;
654+
}
655+
643656
/*******************************************************************************
644657
*
645658
* uart_loop_enable - enable loopback

system/libarc32_arduino101/drivers/uart.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ int uart_break_check(int port);
9292
void uart_break_send(int port, int delay);
9393
void uart_disable(int port);
9494
uint8_t uart_tx_complete(int which);
95+
uint8_t uart_tx_ready(int which);
9596
void uart_loop_enable(int which);
9697
void uart_loop_disable(int which);
9798

0 commit comments

Comments
 (0)