Skip to content

Commit 2fedb00

Browse files
committed
Switch all of the transmit interrupt code to UARTClass. Also, turn USARTClass into a stub because it did nothing differently from the UART code anyway. Now all serial ports use transmit interrupts.
1 parent bb341c6 commit 2fedb00

File tree

5 files changed

+66
-146
lines changed

5 files changed

+66
-146
lines changed

hardware/arduino/sam/cores/arduino/UARTClass.cpp

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323

2424
// Constructors ////////////////////////////////////////////////////////////////
2525

26-
UARTClass::UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer )
26+
UARTClass::UARTClass( Uart *pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer *pRx_buffer, RingBuffer *pTx_buffer )
2727
{
2828
_rx_buffer = pRx_buffer ;
29+
_tx_buffer = pTx_buffer;
2930

3031
_pUart=pUart ;
3132
_dwIrq=dwIrq ;
@@ -34,7 +35,14 @@ UARTClass::UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* p
3435

3536
// Public Methods //////////////////////////////////////////////////////////////
3637

38+
39+
3740
void UARTClass::begin( const uint32_t dwBaudRate )
41+
{
42+
begin( dwBaudRate, UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL );
43+
}
44+
45+
void UARTClass::begin( const uint32_t dwBaudRate, const uint32_t config )
3846
{
3947
// Configure PMC
4048
pmc_enable_periph_clk( _dwId ) ;
@@ -46,7 +54,7 @@ void UARTClass::begin( const uint32_t dwBaudRate )
4654
_pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS ;
4755

4856
// Configure mode
49-
_pUart->UART_MR = UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL ;
57+
_pUart->UART_MR = config ;
5058

5159
// Configure baudrate (asynchronous, no oversampling)
5260
_pUart->UART_BRGR = (SystemCoreClock / dwBaudRate) >> 4 ;
@@ -58,6 +66,10 @@ void UARTClass::begin( const uint32_t dwBaudRate )
5866
// Enable UART interrupt in NVIC
5967
NVIC_EnableIRQ(_dwIrq);
6068

69+
//make sure both ring buffers are initialized back to empty.
70+
_rx_buffer->_iHead = _rx_buffer->_iTail = 0;
71+
_tx_buffer->_iHead = _tx_buffer->_iTail = 0;
72+
6173
// Enable receiver and transmitter
6274
_pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ;
6375
}
@@ -67,6 +79,8 @@ void UARTClass::end( void )
6779
// clear any received data
6880
_rx_buffer->_iHead = _rx_buffer->_iTail ;
6981

82+
while (_tx_buffer->_iHead != _tx_buffer->_iTail); //wait for transmit data to be sent
83+
7084
// Disable UART interrupt in NVIC
7185
NVIC_DisableIRQ( _dwIrq ) ;
7286

@@ -81,6 +95,14 @@ int UARTClass::available( void )
8195
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
8296
}
8397

98+
int UARTClass::availableForWrite(void)
99+
{
100+
int head = _tx_buffer->_iHead;
101+
int tail = _tx_buffer->_iTail;
102+
if (head >= tail) return SERIAL_BUFFER_SIZE - 1 - head + tail;
103+
return tail - head - 1;
104+
}
105+
84106
int UARTClass::peek( void )
85107
{
86108
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
@@ -109,12 +131,21 @@ void UARTClass::flush( void )
109131

110132
size_t UARTClass::write( const uint8_t uc_data )
111133
{
112-
// Check if the transmitter is ready
113-
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
114-
;
134+
if ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) //is the hardware currently busy?
135+
{
136+
//if busy we buffer
137+
unsigned int l = (_tx_buffer->_iHead + 1) % SERIAL_BUFFER_SIZE;
138+
while (_tx_buffer->_iTail == l); //spin locks if we're about to overwrite the buffer. This continues once the data is sent
115139

116-
// Send character
117-
_pUart->UART_THR = uc_data;
140+
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
141+
_tx_buffer->_iHead = l;
142+
_pUart->UART_IER = UART_IER_TXRDY; //make sure TX interrupt is enabled
143+
}
144+
else
145+
{
146+
// Send character
147+
_pUart->UART_THR = uc_data ;
148+
}
118149
return 1;
119150
}
120151

@@ -126,6 +157,19 @@ void UARTClass::IrqHandler( void )
126157
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
127158
_rx_buffer->store_char(_pUart->UART_RHR);
128159

160+
//Do we need to keep sending data?
161+
if ((status & UART_SR_TXRDY) == UART_SR_TXRDY)
162+
{
163+
if (_tx_buffer->_iTail != _tx_buffer->_iHead) { //just in case
164+
_pUart->UART_THR = _tx_buffer->_aucBuffer[_tx_buffer->_iTail];
165+
_tx_buffer->_iTail = (unsigned int)(_tx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE;
166+
}
167+
else
168+
{
169+
_pUart->UART_IDR = UART_IDR_TXRDY; //mask off transmit interrupt so we don't get it anymore
170+
}
171+
}
172+
129173
// Acknowledge errors
130174
if ((status & UART_SR_OVRE) == UART_SR_OVRE ||
131175
(status & UART_SR_FRAME) == UART_SR_FRAME)

hardware/arduino/sam/cores/arduino/UARTClass.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,21 @@ class UARTClass : public HardwareSerial
2929
{
3030
protected:
3131
RingBuffer *_rx_buffer ;
32+
RingBuffer *_tx_buffer;
3233

3334
protected:
3435
Uart* _pUart ;
3536
IRQn_Type _dwIrq ;
3637
uint32_t _dwId ;
3738

3839
public:
39-
UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer ) ;
40+
UARTClass( Uart* pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, RingBuffer* pTx_buffer) ;
4041

4142
void begin( const uint32_t dwBaudRate ) ;
43+
void begin( const uint32_t dwBaudRate , const uint32_t config ) ;
4244
void end( void ) ;
4345
int available( void ) ;
46+
int availableForWrite(void);
4447
int peek( void ) ;
4548
int read( void ) ;
4649
void flush( void ) ;

hardware/arduino/sam/cores/arduino/USARTClass.cpp

Lines changed: 7 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,10 @@
2323

2424
// Constructors ////////////////////////////////////////////////////////////////
2525

26-
USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, RingBuffer* pTx_buffer )
26+
USARTClass::USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, RingBuffer* pTx_buffer ) : UARTClass((Uart*)pUsart, dwIrq, dwId, pRx_buffer, pTx_buffer)
2727
{
28-
_rx_buffer = pRx_buffer;
29-
_tx_buffer = pTx_buffer;
3028

31-
_pUsart=pUsart ;
32-
_dwIrq=dwIrq ;
33-
_dwId=dwId ;
29+
_pUsart=pUsart ; //In case anyone needs USART specific functionality in the future
3430
}
3531

3632
// Public Methods //////////////////////////////////////////////////////////////
@@ -42,140 +38,26 @@ void USARTClass::begin( const uint32_t dwBaudRate )
4238

4339
void USARTClass::begin( const uint32_t dwBaudRate, const uint32_t config )
4440
{
45-
// Configure PMC
46-
pmc_enable_periph_clk( _dwId ) ;
47-
48-
// Disable PDC channel
49-
_pUsart->US_PTCR = US_PTCR_RXTDIS | US_PTCR_TXTDIS ;
50-
51-
// Reset and disable receiver and transmitter
52-
_pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS ;
53-
54-
// Configure mode
55-
_pUsart->US_MR = config;
56-
57-
58-
// Configure baudrate, asynchronous no oversampling
59-
_pUsart->US_BRGR = (SystemCoreClock / dwBaudRate) / 16 ;
60-
61-
// Configure interrupts
62-
_pUsart->US_IDR = 0xFFFFFFFF;
63-
_pUsart->US_IER = US_IER_RXRDY | US_IER_OVRE | US_IER_FRAME;
64-
65-
// Enable UART interrupt in NVIC
66-
NVIC_EnableIRQ( _dwIrq ) ;
67-
68-
//make sure both ring buffers are initialized back to empty.
69-
_rx_buffer->_iHead = _rx_buffer->_iTail = 0;
70-
_tx_buffer->_iHead = _tx_buffer->_iTail = 0;
71-
72-
// Enable receiver and transmitter
73-
_pUsart->US_CR = US_CR_RXEN | US_CR_TXEN ;
41+
UARTClass::begin(dwBaudRate, config);
7442
}
7543

7644
void USARTClass::end( void )
7745
{
78-
// clear any received data
79-
_rx_buffer->_iHead = _rx_buffer->_iTail ;
80-
81-
while (_tx_buffer->_iHead != _tx_buffer->_iTail); //wait for transmit data to be sent
82-
83-
// Disable UART interrupt in NVIC
84-
NVIC_DisableIRQ( _dwIrq ) ;
85-
86-
// Wait for any outstanding data to be sent
87-
flush();
88-
89-
pmc_disable_periph_clk( _dwId ) ;
90-
}
91-
92-
int USARTClass::available( void )
93-
{
94-
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
95-
}
96-
97-
int USARTClass::availableForWrite(void)
98-
{
99-
int head = _tx_buffer->_iHead;
100-
int tail = _tx_buffer->_iTail;
101-
if (head >= tail) return SERIAL_BUFFER_SIZE - 1 - head + tail;
102-
return tail - head - 1;
103-
}
104-
105-
int USARTClass::peek( void )
106-
{
107-
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
108-
return -1 ;
109-
110-
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
111-
}
112-
113-
int USARTClass::read( void )
114-
{
115-
// if the head isn't ahead of the tail, we don't have any characters
116-
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
117-
return -1 ;
118-
119-
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
120-
_rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ;
121-
return uc ;
46+
UARTClass::end();
12247
}
12348

12449
void USARTClass::flush( void )
12550
{
126-
// Wait for transmission to complete
127-
while ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY)
128-
;
51+
UARTClass::flush();
12952
}
13053

13154
size_t USARTClass::write( const uint8_t uc_data )
13255
{
133-
if ((_pUsart->US_CSR & US_CSR_TXRDY) != US_CSR_TXRDY) //is the hardware currently busy?
134-
{
135-
//if busy we buffer
136-
unsigned int l = (_tx_buffer->_iHead + 1) % SERIAL_BUFFER_SIZE;
137-
while (_tx_buffer->_iTail == l); //spin locks if we're about to overwrite the buffer. This continues once the data is sent
138-
139-
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
140-
_tx_buffer->_iHead = l;
141-
_pUsart->US_IER = US_IER_TXRDY; //make sure TX interrupt is enabled
142-
}
143-
else
144-
{
145-
// Send character
146-
_pUsart->US_THR = uc_data ;
147-
}
148-
return 1;
56+
return UARTClass::write(uc_data);
14957
}
15058

15159
void USARTClass::IrqHandler( void )
15260
{
153-
uint32_t status = _pUsart->US_CSR;
154-
155-
// Did we receive data ?
156-
if ((status & US_CSR_RXRDY) == US_CSR_RXRDY)
157-
{
158-
_rx_buffer->store_char(_pUsart->US_RHR);
159-
}
160-
//Do we need to keep sending data?
161-
if ((status & US_CSR_TXRDY) == US_CSR_TXRDY)
162-
{
163-
if (_tx_buffer->_iTail != _tx_buffer->_iHead) { //just in case
164-
_pUsart->US_THR = _tx_buffer->_aucBuffer[_tx_buffer->_iTail];
165-
_tx_buffer->_iTail = (unsigned int)(_tx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE;
166-
}
167-
else
168-
{
169-
_pUsart->US_IDR = US_IDR_TXRDY; //mask off transmit interrupt so we don't get it anymore
170-
}
171-
}
172-
173-
// Acknowledge errors
174-
if ((status & US_CSR_OVRE) == US_CSR_OVRE ||
175-
(status & US_CSR_FRAME) == US_CSR_FRAME)
176-
{
177-
// TODO: error reporting outside ISR
178-
_pUsart->US_CR |= US_CR_RSTSTA;
179-
}
61+
UARTClass::IrqHandler();
18062
}
18163

hardware/arduino/sam/cores/arduino/USARTClass.h

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
#ifndef _USART_CLASS_
2020
#define _USART_CLASS_
2121

22-
#include "HardwareSerial.h"
22+
#include "UARTClass.h"
2323
#include "RingBuffer.h"
2424

2525
// Includes Atmel CMSIS
@@ -56,27 +56,17 @@
5656
#define SERIAL_7O2 (US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK | US_MR_CHRL_7_BIT | US_MR_PAR_ODD | US_MR_NBSTOP_2_BIT | US_MR_CHMODE_NORMAL)
5757
#define SERIAL_8O2 (US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK | US_MR_CHRL_8_BIT | US_MR_PAR_ODD | US_MR_NBSTOP_2_BIT | US_MR_CHMODE_NORMAL)
5858

59-
class USARTClass : public HardwareSerial
59+
class USARTClass : public UARTClass
6060
{
61-
protected:
62-
RingBuffer *_rx_buffer;
63-
RingBuffer *_tx_buffer;
64-
6561
protected:
6662
Usart* _pUsart ;
67-
IRQn_Type _dwIrq ;
68-
uint32_t _dwId ;
6963

7064
public:
7165
USARTClass( Usart* pUsart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer* pRx_buffer, RingBuffer* pTx_buffer ) ;
7266

7367
void begin( const uint32_t dwBaudRate ) ;
7468
void begin( const uint32_t dwBaudRate , const uint32_t config ) ;
7569
void end( void ) ;
76-
int available( void ) ;
77-
int availableForWrite(void);
78-
int peek( void ) ;
79-
int read( void ) ;
8070
void flush( void ) ;
8171
size_t write( const uint8_t c ) ;
8272

hardware/arduino/sam/variants/arduino_due_x/variant.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,9 @@ extern const PinDescription g_APinDescription[]=
299299
* UART objects
300300
*/
301301
RingBuffer rx_buffer1;
302+
RingBuffer tx_buffer1;
302303

303-
UARTClass Serial(UART, UART_IRQn, ID_UART, &rx_buffer1);
304+
UARTClass Serial(UART, UART_IRQn, ID_UART, &rx_buffer1, &tx_buffer1);
304305
void serialEvent() __attribute__((weak));
305306
void serialEvent() { }
306307

0 commit comments

Comments
 (0)