17#include "uart_rp2040.h"
18#include "gpio_rp2040.h"
19#include "system_rp2040.h"
23using namespace _UART0_;
24using namespace _UART1_;
25using namespace _IO_BANK0_;
26using namespace _RESETS_;
28function<void(
char)> uart_rp2040::_intHandler[2];
30int8_t uart_rp2040::_uart_tx_pins[2][4] =
31 { { 0, 12, 16, 28 }, { 4, 8, 20, 24 } };
33uart_rp2040::uart_rp2040(gpio_pin_t tx_pin, gpio_pin_t rx_pin,
34 uint32_t baud, uart_mode_t mode)
35: _init(false), _tx(tx_pin), _rx(rx_pin), _baud(baud), _mode(mode) {
37 bool tx_found =
false;
38 bool rx_found =
false;
39 for (_index=0; _index < 2; ++_index) {
42 for (
size_t i = 0; i < 4; ++i) {
43 if (tx_pin == _uart_tx_pins[_index][i]) {
46 if (rx_pin == (_uart_tx_pins[_index][i]+1)) {
50 if (tx_found && rx_found)
break;
52 assert(tx_found && rx_found);
55 _uart = (_index==0) ? &UART0 : &UART1;
56 _uart_set = (_index==0) ? &UART0_SET : &UART1_SET;
57 _uart_clr = (_index==0) ? &UART0_CLR : &UART1_CLR;
60void uart_rp2040::init() {
62 if (_index) RESETS_CLR.RESET.uart1 = 1;
63 else RESETS_CLR.RESET.uart0 = 1;
65 _tx.setSEL(GPIO_CTRL_FUNCSEL__uart);
66 _rx.setSEL(GPIO_CTRL_FUNCSEL__uart);
72 _uart_set->UARTCR.UARTEN <<= 1;
73 _uart_set->UARTLCR_H.FEN <<= 1;
77uart_rp2040::~uart_rp2040() {
81 while( (_uart->UARTFR.TXFE) == 0) ;
83 if (_index) RESETS_SET.RESET.uart1 = 1;
84 else RESETS_SET.RESET.uart0 = 1;
86 _tx.setSEL( GPIO_CTRL_FUNCSEL__null );
87 _rx.setSEL( GPIO_CTRL_FUNCSEL__null );
90bool uart_rp2040::available() {
92 return !_uart->UARTFR.RXFE;
95char uart_rp2040::getc() {
98 while(_uart->UARTFR.RXFE) ;
100 return _uart->UARTDR.DATA;
103void uart_rp2040::putc(
char c) {
106 while(_uart->UARTFR.TXFF) ;
108 _uart->UARTDR.DATA = (uint16_t)c;
111int uart_rp2040::puts(
const char *s) {
120void uart_rp2040::uartMode(uart_mode_t mode) {
122 if (mode & UART::BITS_7) {
123 _uart->UARTLCR_H.WLEN = 2;
125 if (mode & UART::BITS_8) {
126 _uart->UARTLCR_H.WLEN = 3;
128 if (mode & UART::NO_PARITY) {
129 _uart->UARTLCR_H.PEN = 0;
131 if (mode & UART::EVEN_PARITY) {
132 _uart->UARTLCR_H.PEN = 1;
133 _uart->UARTLCR_H.EPS = 1;
135 if (mode & UART::ODD_PARITY) {
136 _uart->UARTLCR_H.PEN = 1;
137 _uart->UARTLCR_H.EPS = 0;
139 if (mode & UART::STOPBITS_1) {
140 _uart->UARTLCR_H.STP2 = 0;
142 if (mode & UART::STOPBITS_2) {
143 _uart->UARTLCR_H.STP2 = 1;
147void uart_rp2040::setBaudrate(uint32_t baud) {
149 uint32_t baud_div = (8 * CLK_PERI) / _baud;
150 _uart->UARTIBRD = (baud_div >> 7);
151 _uart->UARTFBRD = ((baud_div & 0x7f) + 1) / 2;
153 _uart_set->UARTLCR_H <<= 0;
156void uart_rp2040::sendBreak(uint16_t ms) {
158 _uart_clr->UARTLCR_H.BRK <<= 1;
159 }
else if (ms == 0xffff) {
160 _uart_set->UARTLCR_H.BRK <<= 1;
162 _uart_set->UARTLCR_H.BRK <<= 1;
164 _uart_clr->UARTLCR_H.BRK <<= 1;
168void uart_rp2040::setDTR(
bool dtr) {
169 _uart->UARTCR.DTR = dtr;
172void uart_rp2040::setRTS(
bool rts) {
173 _uart->UARTCR.RTS = rts;
176void uart_rp2040::uartAttachIrq(function<
void(
char)> f) {
178 _intHandler[_index] = f;
180 _uart_set->UARTIMSC.RXIM <<= 1;
181 _uart_set->UARTIMSC.RTIM <<= 1;
183 NVIC_EnableIRQ((IRQn_Type)(UART0_IRQ_IRQn + _index));
186void uart_rp2040::uartDetachIrq () {
189 NVIC_DisableIRQ((IRQn_Type)(UART0_IRQ_IRQn + _index));
191 _uart_clr->UARTIMSC.RXIM <<= 1;
192 _uart_clr->UARTIMSC.RTIM <<= 1;
194 _uart_set->UARTICR.RXIC <<= 1;
195 _uart_set->UARTICR.RTIC <<= 1;
197 _intHandler[_index] =
nullptr;
200void uart_rp2040::uartEnableIrq () {
201 _uart_set->UARTIMSC.RXIM <<= 1;
202 _uart_set->UARTIMSC.RTIM <<= 1;
205void uart_rp2040::uartDisableIrq() {
206 _uart_clr->UARTIMSC.RXIM <<= 1;
207 _uart_clr->UARTIMSC.RTIM <<= 1;
210void uart_rp2040::enableFIFO(
bool val) {
212 _uart->UARTLCR_H.FEN = val;
219void UART0_IRQ_Handler(
void) {
220 while(!UART0.UARTFR.RXFE) {
221 uart_rp2040::_intHandler[0](UART0.UARTDR.DATA);
225void UART1_IRQ_Handler(
void) {
226 while(!UART1.UARTFR.RXFE) {
227 uart_rp2040::_intHandler[1](UART1.UARTDR.DATA);