diff options
Diffstat (limited to 'arduino/cores/nRF5/Uart.cpp')
-rwxr-xr-x | arduino/cores/nRF5/Uart.cpp | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/arduino/cores/nRF5/Uart.cpp b/arduino/cores/nRF5/Uart.cpp new file mode 100755 index 0000000..6eb5efd --- /dev/null +++ b/arduino/cores/nRF5/Uart.cpp @@ -0,0 +1,220 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + Copyright (c) 2016 Sandeep Mistry All right reserved. + + 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 "Uart.h" +#include "Arduino.h" +#include "wiring_private.h" + + +void serialEventRun(void) +{ + if (serialEvent && Serial.available() ) serialEvent(); +} + +Uart::Uart(NRF_UART_Type *_nrfUart, IRQn_Type _IRQn, uint8_t _pinRX, uint8_t _pinTX) +{ + nrfUart = _nrfUart; + IRQn = _IRQn; + uc_pinRX = g_ADigitalPinMap[_pinRX]; + uc_pinTX = g_ADigitalPinMap[_pinTX]; + uc_hwFlow = 0; + + _mutex = NULL; + _begun = false; +} + +Uart::Uart(NRF_UART_Type *_nrfUart, IRQn_Type _IRQn, uint8_t _pinRX, uint8_t _pinTX, uint8_t _pinCTS, uint8_t _pinRTS) +{ + nrfUart = _nrfUart; + IRQn = _IRQn; + uc_pinRX = g_ADigitalPinMap[_pinRX]; + uc_pinTX = g_ADigitalPinMap[_pinTX]; + uc_pinCTS = g_ADigitalPinMap[_pinCTS]; + uc_pinRTS = g_ADigitalPinMap[_pinRTS]; + uc_hwFlow = 1; + + _mutex = NULL; + _begun = false; +} + +void Uart::setPins(uint8_t pin_rx, uint8_t pin_tx) +{ + uc_pinRX = pin_rx; + uc_pinTX = pin_tx; +} + +void Uart::begin(unsigned long baudrate) +{ + begin(baudrate, (uint8_t)SERIAL_8N1); +} + +void Uart::begin(unsigned long baudrate, uint16_t /*config*/) +{ + // skip if already begun + if ( _begun ) return; + + nrfUart->PSELTXD = uc_pinTX; + nrfUart->PSELRXD = uc_pinRX; + + if (uc_hwFlow == 1) { + nrfUart->PSELCTS = uc_pinCTS; + nrfUart->PSELRTS = uc_pinRTS; + nrfUart->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos) | UART_CONFIG_HWFC_Enabled; + } else { + nrfUart->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos) | UART_CONFIG_HWFC_Disabled; + } + + uint32_t nrfBaudRate; + + if (baudrate <= 1200) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud1200; + } else if (baudrate <= 2400) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud2400; + } else if (baudrate <= 4800) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud4800; + } else if (baudrate <= 9600) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud9600; + } else if (baudrate <= 14400) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud14400; + } else if (baudrate <= 19200) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud19200; + } else if (baudrate <= 28800) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud28800; + } else if (baudrate <= 38400) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud38400; + } else if (baudrate <= 57600) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud57600; + } else if (baudrate <= 76800) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud76800; + } else if (baudrate <= 115200) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud115200; + } else if (baudrate <= 230400) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud230400; + } else if (baudrate <= 250000) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud250000; + } else if (baudrate <= 460800) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud460800; + } else if (baudrate <= 921600) { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud921600; + } else { + nrfBaudRate = UARTE_BAUDRATE_BAUDRATE_Baud1M; + } + + nrfUart->BAUDRATE = nrfBaudRate; + + nrfUart->ENABLE = UART_ENABLE_ENABLE_Enabled; + + nrfUart->EVENTS_RXDRDY = 0x0UL; + nrfUart->EVENTS_TXDRDY = 0x0UL; + + nrfUart->TASKS_STARTRX = 0x1UL; + nrfUart->TASKS_STARTTX = 0x1UL; + + nrfUart->INTENSET = UART_INTENSET_RXDRDY_Msk; + + NVIC_ClearPendingIRQ(IRQn); + NVIC_SetPriority(IRQn, 3); + NVIC_EnableIRQ(IRQn); + + _mutex = xSemaphoreCreateMutex(); + _begun = true; +} + +void Uart::end() +{ + NVIC_DisableIRQ(IRQn); + + nrfUart->INTENCLR = UART_INTENCLR_RXDRDY_Msk; + + nrfUart->TASKS_STOPRX = 0x1UL; + nrfUart->TASKS_STOPTX = 0x1UL; + + nrfUart->ENABLE = UART_ENABLE_ENABLE_Disabled; + + nrfUart->PSELTXD = 0xFFFFFFFF; + nrfUart->PSELRXD = 0xFFFFFFFF; + + nrfUart->PSELRTS = 0xFFFFFFFF; + nrfUart->PSELCTS = 0xFFFFFFFF; + + rxBuffer.clear(); + + vSemaphoreDelete(_mutex); + _mutex = NULL; + _begun = false; +} + +void Uart::flush() +{ + rxBuffer.clear(); +} + +void Uart::IrqHandler() +{ + if (nrfUart->EVENTS_RXDRDY) + { + nrfUart->EVENTS_RXDRDY = 0x0UL; + rxBuffer.store_char(nrfUart->RXD); + } +} + +int Uart::available() +{ + return rxBuffer.available(); +} + +int Uart::peek() +{ + return rxBuffer.peek(); +} + +int Uart::read() +{ + return rxBuffer.read_char(); +} + +size_t Uart::write(const uint8_t data) +{ + xSemaphoreTake(_mutex, portMAX_DELAY); + + nrfUart->TXD = data; + + while(!nrfUart->EVENTS_TXDRDY); + + nrfUart->EVENTS_TXDRDY = 0x0UL; + + xSemaphoreGive(_mutex); + + return 1; +} + +Uart SERIAL_PORT_HARDWARE( NRF_UART0, UARTE0_UART0_IRQn, PIN_SERIAL_RX, PIN_SERIAL_TX ); + +#ifdef HAVE_HWSERIAL2 +// TODO UART1 is UARTE only, need update class Uart to work +Uart Serial2( NRF_UARTE1, UARTE1_IRQn, PIN_SERIAL2_RX, PIN_SERIAL2_TX ); +#endif + +extern "C" +{ + void UARTE0_UART0_IRQHandler() + { + SERIAL_PORT_HARDWARE.IrqHandler(); + } +} |