Skip to content

Commit a802e0a

Browse files
committed
cores/xmc/: Add Uart class for Serial implementation.
Signed-off-by: zhanglinjing <[email protected]>
1 parent 05590a7 commit a802e0a

File tree

4 files changed

+383
-4
lines changed

4 files changed

+383
-4
lines changed

cores/xmc/Arduino.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,12 @@ extern void loop(void);
340340

341341
#ifdef __cplusplus
342342
} // extern "C"
343-
// #include "Tone.h"
344-
// #include "WMath.h"
343+
// #include "Tone.h"
344+
// #include "WMath.h"
345+
#include "Uart.h"
345346
#endif // __cplusplus
346347

347348
// #include "Print.h"
348-
// #include "HardwareSerial.h"
349349

350350
//****************************************************************************
351351
// @Board Variant Includes

cores/xmc/Uart.cpp

+242
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
/*
2+
Copyright (c) 2011 Arduino. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
//****************************************************************************
20+
// @Project Includes
21+
//****************************************************************************
22+
#include "Uart.h"
23+
#include "Arduino.h"
24+
25+
//****************************************************************************
26+
// @Local Functions
27+
//****************************************************************************
28+
29+
// Constructors ////////////////////////////////////////////////////////////////
30+
31+
Uart::Uart(XMC_UART_t *xmc_uart_config,
32+
arduino::RingBuffer *rx_buffer,
33+
arduino::RingBuffer *tx_buffer) {
34+
_XMC_UART_config = xmc_uart_config;
35+
_rx_buffer = rx_buffer;
36+
_tx_buffer = tx_buffer;
37+
}
38+
39+
// Public Methods //////////////////////////////////////////////////////////////
40+
41+
void Uart::begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
42+
43+
void Uart::begin(unsigned long baud, unsigned short config) {
44+
begin(baud, static_cast<XMC_UART_MODE_t>(config));
45+
}
46+
47+
void Uart::begin(unsigned long baud, XMC_UART_MODE_t config) {
48+
XMC_UART_CH_CONFIG_t uart_ch_config;
49+
uart_ch_config.oversampling = 0; // Must be 0 or valid oversample for baud rate calculations
50+
uart_ch_config.baudrate = baud;
51+
uart_ch_config.data_bits = (uint8_t)(config & 0x00fU);
52+
uart_ch_config.frame_length = uart_ch_config.data_bits; // Set same as data bits length
53+
uart_ch_config.parity_mode = (XMC_USIC_CH_PARITY_MODE_t)(config & ~0xffU);
54+
uart_ch_config.stop_bits = (uint8_t)((config & 0x0f0U) >> 4);
55+
56+
XMC_UART_CH_Init(_XMC_UART_config->channel, &uart_ch_config);
57+
58+
// dx0 is UART RX: source must be set
59+
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX0,
60+
_XMC_UART_config->input_source_dx0);
61+
62+
// Additional input multiplexing
63+
// Check if dx1 is used
64+
if (_XMC_UART_config->input_source_dx1 != XMC_INPUT_INVALID)
65+
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX1,
66+
_XMC_UART_config->input_source_dx1);
67+
68+
// Check if dx2 is used
69+
if (_XMC_UART_config->input_source_dx2 != XMC_INPUT_INVALID)
70+
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX2,
71+
_XMC_UART_config->input_source_dx2);
72+
73+
// Check if dx3 is used
74+
if (_XMC_UART_config->input_source_dx3 != XMC_INPUT_INVALID)
75+
XMC_USIC_CH_SetInputSource(_XMC_UART_config->channel, XMC_USIC_CH_INPUT_DX3,
76+
_XMC_UART_config->input_source_dx3);
77+
78+
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_ALTERNATIVE_RECEIVE |
79+
XMC_UART_CH_EVENT_STANDARD_RECEIVE);
80+
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
81+
XMC_USIC_CH_INTERRUPT_NODE_POINTER_RECEIVE,
82+
_XMC_UART_config->irq_service_request);
83+
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
84+
XMC_USIC_CH_INTERRUPT_NODE_POINTER_ALTERNATE_RECEIVE,
85+
_XMC_UART_config->irq_service_request);
86+
XMC_USIC_CH_SetInterruptNodePointer(_XMC_UART_config->channel,
87+
XMC_USIC_CH_INTERRUPT_NODE_POINTER_TRANSMIT_BUFFER,
88+
_XMC_UART_config->irq_service_request);
89+
NVIC_SetPriority(_XMC_UART_config->irq_num, 3);
90+
NVIC_EnableIRQ(_XMC_UART_config->irq_num);
91+
92+
XMC_UART_CH_Start(_XMC_UART_config->channel);
93+
94+
// TX pin setup put here to avoid startup corrupted characters being first sent
95+
XMC_GPIO_Init(_XMC_UART_config->tx.port, _XMC_UART_config->tx.pin,
96+
&(_XMC_UART_config->tx_config));
97+
98+
XMC_GPIO_Init(_XMC_UART_config->rx.port, _XMC_UART_config->rx.pin,
99+
&(_XMC_UART_config->rx_config));
100+
}
101+
102+
void Uart::end(void) {
103+
// Wait for any outstanding data to be sent
104+
flush();
105+
// Disable UART interrupt in NVIC
106+
NVIC_DisableIRQ(_XMC_UART_config->irq_num);
107+
// Clear any received data after stopping interrupts
108+
_rx_buffer->_iHead = _rx_buffer->_iTail;
109+
}
110+
111+
void Uart::setInterruptPriority(uint32_t priority) {
112+
NVIC_SetPriority(_XMC_UART_config->irq_num, priority & 0x03);
113+
}
114+
115+
uint32_t Uart::getInterruptPriority() { return NVIC_GetPriority(_XMC_UART_config->irq_num); }
116+
117+
int Uart::available(void) {
118+
int head = _rx_buffer->_iHead; // Snapshot index affected by irq
119+
if (head >= _rx_buffer->_iTail)
120+
return head - _rx_buffer->_iTail;
121+
return SERIAL_BUFFER_SIZE - _rx_buffer->_iTail + head;
122+
}
123+
124+
int Uart::availableForWrite(void) {
125+
int tail = _tx_buffer->_iTail; // Snapshot index affected by irq
126+
if (_tx_buffer->_iHead >= tail)
127+
return SERIAL_BUFFER_SIZE - 1 - _tx_buffer->_iHead + tail;
128+
return tail - _tx_buffer->_iHead - 1;
129+
}
130+
131+
int Uart::peek(void) {
132+
if (_rx_buffer->_iHead == _rx_buffer->_iTail)
133+
return -1;
134+
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail];
135+
}
136+
137+
int Uart::read(void) {
138+
// if the head isn't ahead of the tail, we don't have any characters
139+
if (_rx_buffer->_iHead == _rx_buffer->_iTail)
140+
return -1;
141+
142+
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail];
143+
_rx_buffer->_iTail++;
144+
if (_rx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
145+
_rx_buffer->_iTail = 0;
146+
return uc;
147+
}
148+
149+
void Uart::flush(void) {
150+
while (_tx_buffer->_iHead != _tx_buffer->_iTail)
151+
; // wait for transmit data to be sent
152+
153+
while (XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) ==
154+
XMC_USIC_CH_TBUF_STATUS_BUSY)
155+
;
156+
}
157+
158+
size_t Uart::write(const uint8_t uc_data) {
159+
// Is the hardware currently busy?
160+
#if defined(SERIAL_USE_U1C1)
161+
if (_tx_buffer->_iTail != _tx_buffer->_iHead)
162+
#else
163+
if ((XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) ==
164+
XMC_USIC_CH_TBUF_STATUS_BUSY) ||
165+
(_tx_buffer->_iTail != _tx_buffer->_iHead))
166+
#endif
167+
{
168+
// If busy we buffer
169+
int nextWrite = _tx_buffer->_iHead + 1;
170+
if (nextWrite >= SERIAL_BUFFER_SIZE)
171+
nextWrite = 0;
172+
173+
// This should always be false but in case transmission is completed before buffer, we need
174+
// to reenable IRQ
175+
if (XMC_USIC_CH_GetTransmitBufferStatus(_XMC_UART_config->channel) !=
176+
XMC_USIC_CH_TBUF_STATUS_BUSY) {
177+
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
178+
XMC_UART_CH_Transmit(_XMC_UART_config->channel,
179+
_tx_buffer->_aucBuffer[_tx_buffer->_iTail]);
180+
_tx_buffer->_iTail++;
181+
if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
182+
_tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
183+
// Size calculate the correct index value
184+
}
185+
186+
unsigned long startTime = millis();
187+
while (_tx_buffer->_iTail == nextWrite) {
188+
if (millis() - startTime > 1000) {
189+
return 0; // Spin locks if we're about to overwrite the buffer. This continues once
190+
// the data is
191+
// sent
192+
}
193+
}
194+
195+
_tx_buffer->_aucBuffer[_tx_buffer->_iHead] = uc_data;
196+
_tx_buffer->_iHead = nextWrite;
197+
} else {
198+
// Make sure TX interrupt is enabled
199+
XMC_UART_CH_EnableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
200+
// Bypass buffering and send character directly
201+
XMC_UART_CH_Transmit(_XMC_UART_config->channel, uc_data);
202+
}
203+
return 1;
204+
}
205+
206+
void Uart::IrqHandler(void) {
207+
uint32_t status = XMC_UART_CH_GetStatusFlag(_XMC_UART_config->channel);
208+
209+
// Did we receive data?
210+
if ((status & (XMC_UART_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
211+
XMC_UART_CH_STATUS_FLAG_RECEIVE_INDICATION)) != 0U) {
212+
XMC_UART_CH_ClearStatusFlag(_XMC_UART_config->channel,
213+
(XMC_UART_CH_STATUS_FLAG_ALTERNATIVE_RECEIVE_INDICATION |
214+
XMC_UART_CH_STATUS_FLAG_RECEIVE_INDICATION));
215+
216+
while (_XMC_UART_config->channel->RBUFSR &
217+
(USIC_CH_RBUFSR_RDV0_Msk | USIC_CH_RBUFSR_RDV1_Msk))
218+
_rx_buffer->store_char(XMC_UART_CH_GetReceivedData(_XMC_UART_config->channel));
219+
}
220+
221+
// Do we need to keep sending data?
222+
if ((status & XMC_UART_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION) != 0U) {
223+
XMC_UART_CH_ClearStatusFlag(_XMC_UART_config->channel,
224+
XMC_UART_CH_STATUS_FLAG_TRANSMIT_BUFFER_INDICATION);
225+
226+
if (_tx_buffer->_iTail != _tx_buffer->_iHead) {
227+
XMC_UART_CH_Transmit(_XMC_UART_config->channel,
228+
_tx_buffer->_aucBuffer[_tx_buffer->_iTail]);
229+
_tx_buffer->_iTail++;
230+
if (_tx_buffer->_iTail >= SERIAL_BUFFER_SIZE)
231+
_tx_buffer->_iTail %= SERIAL_BUFFER_SIZE; // If iTail is larger than Serial Buffer
232+
// Size calculate the correct index value
233+
} else {
234+
// Mask off transmit interrupt so we don't get it any more
235+
XMC_UART_CH_DisableEvent(_XMC_UART_config->channel, XMC_UART_CH_EVENT_TRANSMIT_BUFFER);
236+
}
237+
}
238+
}
239+
240+
//****************************************************************************
241+
// END OF FILE
242+
//****************************************************************************

cores/xmc/Uart.h

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
Copyright (c) 2011 Arduino. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
#pragma once
19+
20+
//****************************************************************************
21+
// @External Prototypes
22+
//****************************************************************************
23+
24+
#include "Arduino.h"
25+
//****************************************************************************
26+
// @Project Includes
27+
//****************************************************************************
28+
#include "api/HardwareSerial.h"
29+
#include "api/RingBuffer.h"
30+
31+
//****************************************************************************
32+
// @Typedefs
33+
//****************************************************************************
34+
// Define config for Serial.begin(baud, config);
35+
#undef SERIAL_5N1
36+
#undef SERIAL_6N1
37+
#undef SERIAL_7N1
38+
#undef SERIAL_8N1
39+
#undef SERIAL_5N2
40+
#undef SERIAL_6N2
41+
#undef SERIAL_7N2
42+
#undef SERIAL_8N2
43+
#undef SERIAL_5E1
44+
#undef SERIAL_6E1
45+
#undef SERIAL_7E1
46+
#undef SERIAL_8E1
47+
#undef SERIAL_5E2
48+
#undef SERIAL_6E2
49+
#undef SERIAL_7E2
50+
#undef SERIAL_8E2
51+
#undef SERIAL_5O1
52+
#undef SERIAL_6O1
53+
#undef SERIAL_7O1
54+
#undef SERIAL_8O1
55+
#undef SERIAL_5O2
56+
#undef SERIAL_6O2
57+
#undef SERIAL_7O2
58+
#undef SERIAL_8O2
59+
60+
typedef enum XMC_UART_MODE {
61+
SERIAL_5N1 = 0x15 | XMC_USIC_CH_PARITY_MODE_NONE,
62+
SERIAL_6N1 = 0x16 | XMC_USIC_CH_PARITY_MODE_NONE,
63+
SERIAL_7N1 = 0x17 | XMC_USIC_CH_PARITY_MODE_NONE,
64+
SERIAL_8N1 = 0x18 | XMC_USIC_CH_PARITY_MODE_NONE,
65+
SERIAL_5N2 = 0x25 | XMC_USIC_CH_PARITY_MODE_NONE,
66+
SERIAL_6N2 = 0x26 | XMC_USIC_CH_PARITY_MODE_NONE,
67+
SERIAL_7N2 = 0x27 | XMC_USIC_CH_PARITY_MODE_NONE,
68+
SERIAL_8N2 = 0x28 | XMC_USIC_CH_PARITY_MODE_NONE,
69+
SERIAL_5E1 = 0x15 | XMC_USIC_CH_PARITY_MODE_EVEN,
70+
SERIAL_6E1 = 0x16 | XMC_USIC_CH_PARITY_MODE_EVEN,
71+
SERIAL_7E1 = 0x17 | XMC_USIC_CH_PARITY_MODE_EVEN,
72+
SERIAL_8E1 = 0x18 | XMC_USIC_CH_PARITY_MODE_EVEN,
73+
SERIAL_5E2 = 0x25 | XMC_USIC_CH_PARITY_MODE_EVEN,
74+
SERIAL_6E2 = 0x26 | XMC_USIC_CH_PARITY_MODE_EVEN,
75+
SERIAL_7E2 = 0x27 | XMC_USIC_CH_PARITY_MODE_EVEN,
76+
SERIAL_8E2 = 0x28 | XMC_USIC_CH_PARITY_MODE_EVEN,
77+
SERIAL_5O1 = 0x15 | XMC_USIC_CH_PARITY_MODE_ODD,
78+
SERIAL_6O1 = 0x16 | XMC_USIC_CH_PARITY_MODE_ODD,
79+
SERIAL_7O1 = 0x17 | XMC_USIC_CH_PARITY_MODE_ODD,
80+
SERIAL_8O1 = 0x18 | XMC_USIC_CH_PARITY_MODE_ODD,
81+
SERIAL_5O2 = 0x25 | XMC_USIC_CH_PARITY_MODE_ODD,
82+
SERIAL_6O2 = 0x26 | XMC_USIC_CH_PARITY_MODE_ODD,
83+
SERIAL_7O2 = 0x27 | XMC_USIC_CH_PARITY_MODE_ODD,
84+
SERIAL_8O2 = 0x28 | XMC_USIC_CH_PARITY_MODE_ODD
85+
} XMC_UART_MODE_t;
86+
87+
//****************************************************************************
88+
// @Class Definitionsw
89+
//****************************************************************************
90+
class Uart : public arduino::HardwareSerial {
91+
public:
92+
XMC_UART_t *_XMC_UART_config;
93+
94+
Uart(XMC_UART_t *xmc_uart_config,
95+
arduino::RingBuffer *rx_buffer,
96+
arduino::RingBuffer *tx_buffer);
97+
98+
void begin(unsigned long);
99+
void begin(unsigned long baudrate, uint16_t config) override;
100+
void begin(unsigned long, XMC_UART_MODE_t config);
101+
void end();
102+
int available(void);
103+
int availableForWrite(void);
104+
int peek(void);
105+
int read(void);
106+
void flush(void);
107+
108+
// virtual size_t readBytes(char *buffer, size_t length) ; // read chars from stream into buffer
109+
// virtual size_t readBytes(uint8_t *buffer, size_t length) ;
110+
111+
size_t write(const uint8_t);
112+
113+
// virtual size_t write(const uint8_t *buffer, size_t size) ;
114+
inline size_t write(unsigned long n) { return write((uint8_t)n); }
115+
116+
inline size_t write(long n) { return write((uint8_t)n); }
117+
118+
inline size_t write(unsigned int n) { return write((uint8_t)n); }
119+
120+
inline size_t write(int n) { return write((uint8_t)n); }
121+
122+
using Print::write; // pull in write(str) and write(buf, size) from Print
123+
124+
operator bool() { return true; }
125+
126+
void setInterruptPriority(uint32_t priority);
127+
uint32_t getInterruptPriority();
128+
129+
void IrqHandler(void);
130+
131+
private:
132+
arduino::RingBuffer *_rx_buffer;
133+
arduino::RingBuffer *_tx_buffer;
134+
};
135+
136+
extern Uart Serial;
137+
extern Uart Serial1;

0 commit comments

Comments
 (0)