Add hardware Serial UARTs

This commit is contained in:
Earle F. Philhower, III 2021-03-13 10:24:18 -08:00
parent afce691957
commit f6fcfd147b
3 changed files with 208 additions and 2 deletions

148
cores/rp2040/SerialUART.cpp Normal file
View file

@ -0,0 +1,148 @@
/*
* Serial-over-UART for the Raspberry Pi Pico RP2040
*
* Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "SerialUART.h"
#include <hardware/gpio.h>
bool SerialUART::setPinout(pin_size_t tx, pin_size_t rx) {
const uint32_t uart_tx[2] = { 0b000010001000000000001000100000, 0b100000000000100010000000000010 };
const uint32_t uart_rx[2] = { 0b000001000100000000000100010000, 0b010000000000010001000000000001 };
if ( ((1 << tx) & uart_tx[uart_get_index(_uart)]) &&
((1 << rx) & uart_rx[uart_get_index(_uart)]) ) {
if (_running) {
pinMode(_tx, INPUT);
pinMode(_rx, INPUT);
}
_tx = tx;
_rx = rx;
if (_running) {
gpio_set_function(_tx, GPIO_FUNC_UART);
gpio_set_function(_rx, GPIO_FUNC_UART);
}
return true;
}
return false;
}
void SerialUART::begin(unsigned long baud, uint16_t config) {
_baud = baud;
uart_init(_uart, baud);
int bits, stop;
uart_parity_t parity;
switch (config & SERIAL_PARITY_MASK) {
case SERIAL_PARITY_EVEN: parity = UART_PARITY_EVEN; break;
case SERIAL_PARITY_ODD: parity = UART_PARITY_ODD; break;
default: parity = UART_PARITY_NONE; break;
}
switch ( config & SERIAL_STOP_BIT_MASK) {
case SERIAL_STOP_BIT_1: stop = 1; break;
default: stop = 2; break;
}
switch (config & SERIAL_DATA_MASK) {
case SERIAL_DATA_5: bits = 5; break;
case SERIAL_DATA_6: bits = 6; break;
case SERIAL_DATA_7: bits = 7; break;
default: bits = 8; break;
}
uart_set_format(_uart, bits, stop, parity);
gpio_set_function(_tx, GPIO_FUNC_UART);
gpio_set_function(_rx, GPIO_FUNC_UART);
_running = true;
_peek = -1;
}
void SerialUART::end() {
uart_deinit(_uart);
_running = false;
}
int SerialUART::peek() {
if (!_running) {
return -1;
}
if (_peek >= 0) {
return _peek;
}
_peek = uart_getc(_uart);
return _peek;
}
int SerialUART::read() {
if (!_running) {
return -1;
}
if (_peek >= 0) {
int ret = _peek;
_peek = -1;
return ret;
}
return uart_getc(_uart);
}
int SerialUART::available() {
if (!_running) {
return 0;
}
return (uart_is_readable(_uart)) ? 1 : 0;
}
int SerialUART::availableForWrite() {
if (!_running) {
return 0;
}
return (uart_is_writable(_uart)) ? 1 : 0;
}
void SerialUART::flush() {
// TODO, must be smarter way. Now, just sleep long enough to guarantee a full FIFO goes out (very conservative)
//int us_per_bit = 1 + (1000000 / _baud);
//delayMicroseconds(us_per_bit * 32 * 8);
uart_default_tx_wait_blocking();
}
size_t SerialUART::write(uint8_t c) {
if (!_running) {
return 0;
}
uart_putc_raw(_uart, c);
return 1;
}
size_t SerialUART::write(const uint8_t *p, size_t len) {
if (!_running) {
return 0;
}
size_t cnt = len;
while (cnt) {
uart_putc_raw(_uart, *p);
cnt--;
p++;
}
return len;
}
SerialUART::operator bool() {
return _running;
}
SerialUART Serial1(uart0, 0, 1);
SerialUART Serial2(uart1, 4, 5);

59
cores/rp2040/SerialUART.h Normal file
View file

@ -0,0 +1,59 @@
/*
* Serial-over-UART for the Raspberry Pi Pico RP2040
*
* Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __SERIALUART_H__
#define __SERIALUART_H__
#include <Arduino.h>
#include "api/HardwareSerial.h"
#include <hardware/uart.h>
class SerialUART : public HardwareSerial
{
public:
SerialUART(uart_inst_t *uart, pin_size_t tx, pin_size_t rx) { _uart = uart; _tx = tx; _rx = rx; }
bool setPinout(pin_size_t tx, pin_size_t rx);
void begin(unsigned long baud = 115200) override { begin(baud, SERIAL_8N1); };
void begin(unsigned long baud, uint16_t config) override;
void end() override;
virtual int peek() override;
virtual int read() override;
virtual int available() override;
virtual int availableForWrite() override;
virtual void flush() override;
virtual size_t write(uint8_t c) override;
virtual size_t write(const uint8_t *p, size_t len) override;
using Print::write;
operator bool() override;
private:
bool _running = false;
uart_inst_t *_uart;
pin_size_t _tx, _rx;
int _baud;
int _peek;
};
extern SerialUART Serial1; // HW UART 0
extern SerialUART Serial2; // HW UART 1
#endif

View file

@ -28,6 +28,7 @@ class SerialUSB : public Stream
public:
SerialUSB() { }
void begin(int baud = 115200);
void begin(int baud, uint16_t config) { begin(baud); };
void end();
virtual int peek() override;
@ -46,5 +47,3 @@ private:
extern SerialUSB Serial;
#endif