23
23
24
24
// Constructors ////////////////////////////////////////////////////////////////
25
25
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 )
27
27
{
28
- _rx_buffer = pRx_buffer ;
28
+ _rx_buffer = pRx_buffer;
29
+ _tx_buffer = pTx_buffer;
29
30
30
- _pUart=pUart ;
31
- _dwIrq=dwIrq ;
32
- _dwId=dwId ;
31
+ _pUart=pUart;
32
+ _dwIrq=dwIrq;
33
+ _dwId=dwId;
33
34
}
34
35
35
36
// Public Methods //////////////////////////////////////////////////////////////
36
37
37
38
void UARTClass::begin ( const uint32_t dwBaudRate )
39
+ {
40
+ begin ( dwBaudRate, UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL );
41
+ }
42
+
43
+ void UARTClass::begin ( const uint32_t dwBaudRate, const uint32_t config )
38
44
{
39
45
// Configure PMC
40
- pmc_enable_periph_clk ( _dwId ) ;
46
+ pmc_enable_periph_clk ( _dwId );
41
47
42
48
// Disable PDC channel
43
- _pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS ;
49
+ _pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
44
50
45
51
// Reset and disable receiver and transmitter
46
- _pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS ;
52
+ _pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
47
53
48
54
// Configure mode
49
- _pUart->UART_MR = UART_MR_PAR_NO | UART_MR_CHMODE_NORMAL ;
55
+ _pUart->UART_MR = config ;
50
56
51
57
// Configure baudrate (asynchronous, no oversampling)
52
- _pUart->UART_BRGR = (SystemCoreClock / dwBaudRate) >> 4 ;
58
+ _pUart->UART_BRGR = (SystemCoreClock / dwBaudRate) >> 4 ;
53
59
54
60
// Configure interrupts
55
61
_pUart->UART_IDR = 0xFFFFFFFF ;
@@ -58,79 +64,128 @@ void UARTClass::begin( const uint32_t dwBaudRate )
58
64
// Enable UART interrupt in NVIC
59
65
NVIC_EnableIRQ (_dwIrq);
60
66
67
+ // Make sure both ring buffers are initialized back to empty.
68
+ _rx_buffer->_iHead = _rx_buffer->_iTail = 0 ;
69
+ _tx_buffer->_iHead = _tx_buffer->_iTail = 0 ;
70
+
61
71
// Enable receiver and transmitter
62
- _pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ;
72
+ _pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
63
73
}
64
74
65
75
void UARTClass::end ( void )
66
76
{
67
- // clear any received data
68
- _rx_buffer->_iHead = _rx_buffer->_iTail ;
69
-
70
- // Disable UART interrupt in NVIC
71
- NVIC_DisableIRQ ( _dwIrq ) ;
77
+ // Clear any received data
78
+ _rx_buffer->_iHead = _rx_buffer->_iTail ;
72
79
73
80
// Wait for any outstanding data to be sent
74
81
flush ();
75
82
76
- pmc_disable_periph_clk ( _dwId ) ;
83
+ // Disable UART interrupt in NVIC
84
+ NVIC_DisableIRQ ( _dwIrq );
85
+
86
+ pmc_disable_periph_clk ( _dwId );
87
+ }
88
+
89
+ void UARTClass::setInterruptPriority (uint32_t priority)
90
+ {
91
+ NVIC_SetPriority (_dwIrq, priority & 0x0F );
92
+ }
93
+
94
+ uint32_t UARTClass::getInterruptPriority ()
95
+ {
96
+ return NVIC_GetPriority (_dwIrq);
77
97
}
78
98
79
99
int UARTClass::available ( void )
80
100
{
81
- return (uint32_t )(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail ) % SERIAL_BUFFER_SIZE ;
101
+ return (uint32_t )(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail ) % SERIAL_BUFFER_SIZE;
102
+ }
103
+
104
+ int UARTClass::availableForWrite (void )
105
+ {
106
+ int head = _tx_buffer->_iHead ;
107
+ int tail = _tx_buffer->_iTail ;
108
+ if (head >= tail) return SERIAL_BUFFER_SIZE - 1 - head + tail;
109
+ return tail - head - 1 ;
82
110
}
83
111
84
112
int UARTClass::peek ( void )
85
113
{
86
114
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
87
- return -1 ;
115
+ return -1 ;
88
116
89
- return _rx_buffer->_aucBuffer [_rx_buffer->_iTail ] ;
117
+ return _rx_buffer->_aucBuffer [_rx_buffer->_iTail ];
90
118
}
91
119
92
120
int UARTClass::read ( void )
93
121
{
94
122
// if the head isn't ahead of the tail, we don't have any characters
95
123
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
96
- return -1 ;
124
+ return -1 ;
97
125
98
- uint8_t uc = _rx_buffer->_aucBuffer [_rx_buffer->_iTail ] ;
99
- _rx_buffer->_iTail = (unsigned int )(_rx_buffer->_iTail + 1 ) % SERIAL_BUFFER_SIZE ;
100
- return uc ;
126
+ uint8_t uc = _rx_buffer->_aucBuffer [_rx_buffer->_iTail ];
127
+ _rx_buffer->_iTail = (unsigned int )(_rx_buffer->_iTail + 1 ) % SERIAL_BUFFER_SIZE;
128
+ return uc;
101
129
}
102
130
103
131
void UARTClass::flush ( void )
104
132
{
133
+ while (_tx_buffer->_iHead != _tx_buffer->_iTail ); // wait for transmit data to be sent
105
134
// Wait for transmission to complete
106
135
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
107
- ;
136
+ ;
108
137
}
109
138
110
139
size_t UARTClass::write ( const uint8_t uc_data )
111
140
{
112
- // Check if the transmitter is ready
113
- while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
114
- ;
115
-
116
- // Send character
117
- _pUart->UART_THR = uc_data;
141
+ // Is the hardware currently busy?
142
+ if (((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY) |
143
+ (_tx_buffer->_iTail != _tx_buffer->_iHead ))
144
+ {
145
+ // If busy we buffer
146
+ unsigned int l = (_tx_buffer->_iHead + 1 ) % SERIAL_BUFFER_SIZE;
147
+ while (_tx_buffer->_iTail == l)
148
+ ; // Spin locks if we're about to overwrite the buffer. This continues once the data is sent
149
+
150
+ _tx_buffer->_aucBuffer [_tx_buffer->_iHead ] = uc_data;
151
+ _tx_buffer->_iHead = l;
152
+ // Make sure TX interrupt is enabled
153
+ _pUart->UART_IER = UART_IER_TXRDY;
154
+ }
155
+ else
156
+ {
157
+ // Bypass buffering and send character directly
158
+ _pUart->UART_THR = uc_data;
159
+ }
118
160
return 1 ;
119
161
}
120
162
121
163
void UARTClass::IrqHandler ( void )
122
164
{
123
165
uint32_t status = _pUart->UART_SR ;
124
166
125
- // Did we receive data ?
167
+ // Did we receive data?
126
168
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
127
169
_rx_buffer->store_char (_pUart->UART_RHR );
128
170
171
+ // Do we need to keep sending data?
172
+ if ((status & UART_SR_TXRDY) == UART_SR_TXRDY)
173
+ {
174
+ if (_tx_buffer->_iTail != _tx_buffer->_iHead ) {
175
+ _pUart->UART_THR = _tx_buffer->_aucBuffer [_tx_buffer->_iTail ];
176
+ _tx_buffer->_iTail = (unsigned int )(_tx_buffer->_iTail + 1 ) % SERIAL_BUFFER_SIZE;
177
+ }
178
+ else
179
+ {
180
+ // Mask off transmit interrupt so we don't get it anymore
181
+ _pUart->UART_IDR = UART_IDR_TXRDY;
182
+ }
183
+ }
184
+
129
185
// Acknowledge errors
130
- if ((status & UART_SR_OVRE) == UART_SR_OVRE ||
131
- (status & UART_SR_FRAME) == UART_SR_FRAME)
186
+ if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME)
132
187
{
133
- // TODO: error reporting outside ISR
188
+ // TODO: error reporting outside ISR
134
189
_pUart->UART_CR |= UART_CR_RSTSTA;
135
190
}
136
191
}
0 commit comments