Skip to content

Commit 07f4de2

Browse files
sgbihuSidLeung
authored andcommitted
Jira 842 UART improvement, PR 266, broke BLE interface.
Root causes: 1. The uart_fifo_fill doesn't check the FIFO's length and failed to send out all data. 2. Check the FIFO status register before write data in FIFO. 3. Ring buffer pointer variables are not volatile and polling mechanism failed to examine the actual pointer value being update by foreground task. File changes: 1. RingBuffer.h: Make pointer as volatile. 2. UARTClass.cpp: Added checking of FIFO size for data Tx. 3. ns16550.c: Added routines to h/w status register checking.
1 parent 6d22f3d commit 07f4de2

File tree

3 files changed

+43
-21
lines changed

3 files changed

+43
-21
lines changed

cores/arduino/RingBuffer.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ class RingBuffer
3030
{
3131
public:
3232
uint8_t *_aucBuffer;
33-
int _iHead ;
34-
int _iTail ;
35-
bool _buffer_overflow ;
33+
volatile int _iHead ;
34+
volatile int _iTail ;
35+
volatile bool _buffer_overflow ;
3636

3737
RingBuffer( void ) ;
3838
void store_char( uint8_t c ) ;

cores/arduino/UARTClass.cpp

+21-14
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 != (_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
}
@@ -183,8 +183,7 @@ size_t UARTClass::write( const uint8_t uc_data )
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 (_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,21 +200,29 @@ 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+
if(uart_irq_tx_ready(CONFIG_UART_CONSOLE_INDEX))
215219
{
216-
if (_tx_buffer->_iTail != _tx_buffer->_iHead) {
217-
uart_poll_out(CONFIG_UART_CONSOLE_INDEX, _tx_buffer->_aucBuffer[_tx_buffer->_iTail]);
218-
_tx_buffer->_iTail = (unsigned int)(_tx_buffer->_iTail + 1) % UART_BUFFER_SIZE;
220+
if(_tx_buffer->_iTail != _tx_buffer->_iHead)
221+
{
222+
int end = (_tx_buffer->_iTail < _tx_buffer->_iHead) ? _tx_buffer->_iHead : UART_BUFFER_SIZE;
223+
int l = min(end - _tx_buffer->_iTail, UART_FIFO_SIZE);
224+
l = uart_fifo_fill(CONFIG_UART_CONSOLE_INDEX, _tx_buffer->_aucBuffer+_tx_buffer->_iTail, l);
225+
_tx_buffer->_iTail = (_tx_buffer->_iTail+l)%UART_BUFFER_SIZE;
219226
}
220227
else
221228
{

system/libarc32_arduino101/drivers/ns16550.c

+19-4
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);
@@ -352,6 +352,8 @@ unsigned char uart_poll_out(
352352
*
353353
* uart_fifo_fill - fill FIFO with data
354354
*
355+
* It is up to the caller to make sure that FIFO capcity is not exceeded
356+
*
355357
* RETURNS: number of bytes sent
356358
*/
357359

@@ -362,8 +364,9 @@ int uart_fifo_fill(int which, /* UART on which to send */
362364
{
363365
int i;
364366

365-
for (i = 0; i < size && (INBYTE(LSR(which)) &
366-
LSR_BOTH_EMPTY) != 0; i++) {
367+
for (i = 0; i < size && (INBYTE(LSR(which)) &
368+
LSR_BOTH_EMPTY) != 0; i++)
369+
{
367370
OUTBYTE(THR(which), txData[i]);
368371
}
369372
return i;
@@ -622,7 +625,6 @@ void uart_int_connect(int which, /* UART to which to connect */
622625
)
623626
{
624627
interrupt_connect((unsigned int)uart[which].irq, isr);
625-
interrupt_priority_set ((int)uart[which].irq, uart[which].intPri);
626628
interrupt_enable((unsigned int)uart[which].irq);
627629
/* set the Host Processor Interrupt Routing Mask */
628630
SOC_UNMASK_INTERRUPTS(INT_UART_0_MASK + (which * UART_REG_ADDR_INTERVAL));
@@ -641,6 +643,19 @@ uint8_t uart_tx_complete(int which)
641643
return INBYTE(LSR(which)) & LSR_TEMT;
642644
}
643645

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

0 commit comments

Comments
 (0)