Skip to content

Commit 28d2a75

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 c353f4c commit 28d2a75

File tree

3 files changed

+31
-13
lines changed

3 files changed

+31
-13
lines changed

cores/arduino/UARTClass.cpp

Lines changed: 16 additions & 12 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,12 +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) % UART_BUFFER_SIZE;
186-
while (_tx_buffer->_iTail == l)
187-
; // Spin locks if we're about to overwrite the buffer. This continues once the data is sent
186+
while (*(volatile int*)&(_tx_buffer->_iTail) == l); // Spin locks if we're about to overwrite the buffer. This continues once the data is sent
188187

189188
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
190189
_tx_buffer->_iHead = l;
@@ -201,17 +200,22 @@ size_t UARTClass::write( const uint8_t uc_data )
201200

202201
void UARTClass::IrqHandler( void )
203202
{
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);
203+
uart_irq_update(CONFIG_UART_CONSOLE_INDEX);
204+
// if irq is Receiver Data Available
205+
if(uart_irq_rx_ready(CONFIG_UART_CONSOLE_INDEX))
206+
{
207+
uint8_t uc_data;
208+
int ret;
210209
ret = uart_poll_in(CONFIG_UART_CONSOLE_INDEX, &uc_data);
210+
211+
while ( ret != -1 ) {
212+
_rx_buffer->store_char(uc_data);
213+
ret = uart_poll_in(CONFIG_UART_CONSOLE_INDEX, &uc_data);
214+
}
211215
}
212216

213-
// Do we need to keep sending data?
214-
if (!uart_irq_tx_ready(CONFIG_UART_CONSOLE_INDEX))
217+
// if irq is Transmitter Holding Register
218+
else if(uart_irq_tx_ready(CONFIG_UART_CONSOLE_INDEX))
215219
{
216220
if (_tx_buffer->_iTail != _tx_buffer->_iHead) {
217221
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)