Browse Source

Merge pull request #315 from KurtE/t4-HardwareSerial-Transmitter_enable

T4 SerialX more support (Transmitter enable, Formats, RX Fifo read in...)
teensy4-core
Paul Stoffregen 5 years ago
parent
commit
549f75e387
No account linked to committer's email address
2 changed files with 330 additions and 138 deletions
  1. +243
    -51
      teensy4/HardwareSerial.cpp
  2. +87
    -87
      teensy4/HardwareSerial.h

+ 243
- 51
teensy4/HardwareSerial.cpp View File

@@ -1,3 +1,32 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* 1. The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* 2. If the Software is incorporated into a build system that allows
* selection among a list of target devices, then similar target
* devices manufactured by PJRC.COM must be included in the list of
* target devices and selectable in the same manner.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#include "HardwareSerial.h"
#include "core_pins.h"
@@ -19,6 +48,18 @@
volatile uint32_t WATER;
} IMXRT_LPUART_t; */

//. From Onewire utility files
#define PIN_TO_BASEREG(pin) (portOutputRegister(pin))
#define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin))
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR
#define DIRECT_READ(base, mask) ((*((base)+2) & (mask)) ? 1 : 0)
#define DIRECT_MODE_INPUT(base, mask) (*((base)+1) &= ~(mask))
#define DIRECT_MODE_OUTPUT(base, mask) (*((base)+1) |= (mask))
#define DIRECT_WRITE_LOW(base, mask) (*((base)+34) = (mask))
#define DIRECT_WRITE_HIGH(base, mask) (*((base)+33) = (mask))

#define UART_CLOCK 24000000

#ifndef SERIAL1_TX_BUFFER_SIZE
@@ -74,12 +115,35 @@

#define IRQ_PRIORITY 64 // 0 = highest priority, 255 = lowest

#define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE)
#define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE)
#define CTRL_TX_ACTIVE (CTRL_ENABLE | LPUART_CTRL_TIE)
#define CTRL_TX_COMPLETING (CTRL_ENABLE | LPUART_CTRL_TCIE)
#define CTRL_TX_INACTIVE CTRL_ENABLE

void HardwareSerial::begin(uint32_t baud, uint8_t format)
// Copied from T3.x - probably should move to other location.
int nvic_execution_priority(void)
{
uint32_t priority=256;
uint32_t primask, faultmask, basepri, ipsr;

// full algorithm in ARM DDI0403D, page B1-639
// this isn't quite complete, but hopefully good enough
__asm__ volatile("mrs %0, faultmask\n" : "=r" (faultmask)::);
if (faultmask) return -1;
__asm__ volatile("mrs %0, primask\n" : "=r" (primask)::);
if (primask) return 0;
__asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::);
if (ipsr) {
if (ipsr < 16) priority = 0; // could be non-zero
else priority = NVIC_GET_PRIORITY(ipsr - 16);
}
__asm__ volatile("mrs %0, basepri\n" : "=r" (basepri)::);
if (basepri > 0 && basepri < priority) priority = basepri;
return priority;
}


void HardwareSerial::begin(uint32_t baud, uint16_t format)
{
//printf("HardwareSerial begin\n");
float base = (float)UART_CLOCK / (float)baud;
@@ -104,6 +168,9 @@ void HardwareSerial::begin(uint32_t baud, uint8_t format)
rx_buffer_tail_ = 0;
tx_buffer_head_ = 0;
tx_buffer_tail_ = 0;
rts_low_watermark_ = rx_buffer_total_size_ - hardware->rts_low_watermark;
rts_high_watermark_ = rx_buffer_total_size_ - hardware->rts_high_watermark;

transmitting_ = 0;

hardware->ccm_register |= hardware->ccm_value;
@@ -124,7 +191,7 @@ void HardwareSerial::begin(uint32_t baud, uint8_t format)

// Enable the transmitter, receiver and enable receiver interrupt
attachInterruptVector(hardware->irq, hardware->irq_handler);
NVIC_SET_PRIORITY(hardware->irq, IRQ_PRIORITY); // maybe should put into hardware...
NVIC_SET_PRIORITY(hardware->irq, hardware->irq_priority); // maybe should put into hardware...
NVIC_ENABLE_IRQ(hardware->irq);
uint16_t tx_fifo_size = (((port->FIFO >> 4) & 0x7) << 2);
uint8_t tx_water = (tx_fifo_size < 16) ? tx_fifo_size >> 1 : 7;
@@ -137,10 +204,50 @@ void HardwareSerial::begin(uint32_t baud, uint8_t format)
*/
port->WATER = LPUART_WATER_RXWATER(rx_water) | LPUART_WATER_TXWATER(tx_water);
port->FIFO |= LPUART_FIFO_TXFE | LPUART_FIFO_RXFE;
port->CTRL = CTRL_TX_INACTIVE;


// lets configure up our CTRL register value
uint32_t ctrl = CTRL_TX_INACTIVE;

// Now process the bits in the Format value passed in
// Bits 0-2 - Parity plus 9 bit.
ctrl |= (format & (LPUART_CTRL_PT | LPUART_CTRL_PE) ); // configure parity - turn off PT, PE, M and configure PT, PE
if (format & 0x04) ctrl |= LPUART_CTRL_M; // 9 bits (might include parity)
if ((format & 0x0F) == 0x04) ctrl |= LPUART_CTRL_R9T8; // 8N2 is 9 bit with 9th bit always 1

// Bit 5 TXINVERT
if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert

// write out computed CTRL
port->CTRL = ctrl;

// Bit 3 10 bit - Will assume that begin already cleared it.
// process some other bits which change other registers.
if (format & 0x08) port->BAUD |= LPUART_BAUD_M10;

// Bit 4 RXINVERT
uint32_t c = port->STAT & ~LPUART_STAT_RXINV;
if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert
port->STAT = c;


// bit 8 can turn on 2 stop bit mote
if ( format & 0x100) port->BAUD |= LPUART_BAUD_SBNS;

//Serial.printf(" stat:%x ctrl:%x fifo:%x water:%x\n", port->STAT, port->CTRL, port->FIFO, port->WATER );
};

inline void HardwareSerial::rts_assert()
{
DIRECT_WRITE_LOW(rts_pin_baseReg_, rts_pin_bitmask_);
}

inline void HardwareSerial::rts_deassert()
{
DIRECT_WRITE_HIGH(rts_pin_baseReg_, rts_pin_bitmask_);
}


void HardwareSerial::end(void)
{

@@ -150,40 +257,60 @@ void HardwareSerial::transmitterEnable(uint8_t pin)
{
while (transmitting_) ;
pinMode(pin, OUTPUT);
digitalWrite(pin, LOW);
transmit_pin_ = pin; // BUGBUG - Faster way?
transmit_pin_baseReg_ = PIN_TO_BASEREG(pin);
transmit_pin_bitmask_ = PIN_TO_BITMASK(pin);
DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_);
}

void HardwareSerial::setRX(uint8_t pin)
{
// BUGBUG Implement
//Serial.printf("SerialX TX(%d) param:%x stat:%x ctrl:%x fifo:%x water:%x\n", hardware->tx_pin, port->PARAM, port->STAT, port->CTRL, port->FIFO, port->WATER );
// Currently none of these have multiple
// possible RX pins

}

void HardwareSerial::setTX(uint8_t pin, bool opendrain)
{
// BUGBUG Implement
// Currently none of these have multiple
// possible TX pins
}


bool HardwareSerial::attachRts(uint8_t pin)
{
// BUGBUG Implement
return false;
if (!(hardware->ccm_register & hardware->ccm_value)) return 0;
if (pin < CORE_NUM_DIGITAL) {
rts_pin_baseReg_ = PIN_TO_BASEREG(pin);
rts_pin_bitmask_ = PIN_TO_BITMASK(pin);
pinMode(pin, OUTPUT);
rts_assert();
} else {
rts_pin_baseReg_ = NULL;
return 0;
}
return 1;
}

bool HardwareSerial::attachCts(uint8_t pin)
{
// BUGBUG Implement
return false;
if (!(hardware->ccm_register & hardware->ccm_value)) return false;
if ((pin != 0xff) && (pin == hardware->cts_pin)) {
// Setup the IO pin as weak PULL down.
*(portControlRegister(pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
*(portConfigRegister(hardware->cts_pin)) = hardware->cts_mux_val;
port->MODIR |= LPUART_MODIR_TXCTSE;
return true;
} else {
port->MODIR &= ~LPUART_MODIR_TXCTSE;
return false;
}
}

void HardwareSerial::clear(void)
{
// BUGBUG:: deal with FIFO
rx_buffer_head_ = rx_buffer_tail_;
//if (rts_pin_) rts_assert();
if (rts_pin_baseReg_) rts_assert();
}

int HardwareSerial::availableForWrite(void)
@@ -196,11 +323,6 @@ int HardwareSerial::availableForWrite(void)
return tail - head - 1;
}

size_t HardwareSerial::write9bit(uint32_t c)
{
return 0;
}




@@ -214,6 +336,29 @@ int HardwareSerial::available(void)
return rx_buffer_total_size_ + head - tail;
}

void HardwareSerial::addStorageForRead(void *buffer, size_t length)
{
rx_buffer_storage_ = (BUFTYPE*)buffer;
if (buffer) {
rx_buffer_total_size_ = rx_buffer_total_size_ + length;
} else {
rx_buffer_total_size_ = rx_buffer_total_size_;
}

rts_low_watermark_ = rx_buffer_total_size_ - hardware->rts_low_watermark;
rts_high_watermark_ = rx_buffer_total_size_ - hardware->rts_high_watermark;
}

void HardwareSerial::addStorageForWrite(void *buffer, size_t length)
{
tx_buffer_storage_ = (BUFTYPE*)buffer;
if (buffer) {
tx_buffer_total_size_ = tx_buffer_total_size_ + length;
} else {
tx_buffer_total_size_ = tx_buffer_total_size_;
}
}

int HardwareSerial::peek(void)
{
uint32_t head, tail;
@@ -244,13 +389,12 @@ int HardwareSerial::read(void)
c = rx_buffer_storage_[tail-rx_buffer_size_];
}
rx_buffer_tail_ = tail;
if (rts_pin_) {
if (rts_pin_baseReg_) {
uint32_t avail;
if (head >= tail) avail = head - tail;
else avail = rx_buffer_total_size_ + head - tail;
/*
if (avail <= rts_low_watermark_) rts_assert();
*/
}
return c;
}
@@ -261,17 +405,22 @@ void HardwareSerial::flush(void)
}

size_t HardwareSerial::write(uint8_t c)
{
// use the 9 bit version (maybe 10 bit) do do the work.
return write9bit(c);
}

size_t HardwareSerial::write9bit(uint32_t c)
{
uint32_t head, n;
//digitalWrite(3, HIGH);
//digitalWrite(5, HIGH);
// if (transmit_pin_) transmit_assert();
if (transmit_pin_baseReg_) DIRECT_WRITE_HIGH(transmit_pin_baseReg_, transmit_pin_bitmask_);
head = tx_buffer_head_;
if (++head >= tx_buffer_total_size_) head = 0;
while (tx_buffer_tail_ == head) {
/*
int priority = nvic_execution_priority();
if (priority <= IRQ_PRIORITY) {
if (priority <= hardware->irq_priority) {
if ((port->STAT & LPUART_STAT_TDRE)) {
uint32_t tail = tx_buffer_tail_;
if (++tail >= tx_buffer_total_size_) tail = 0;
@@ -284,7 +433,6 @@ size_t HardwareSerial::write(uint8_t c)
tx_buffer_tail_ = tail;
}
} else if (priority >= 256)
*/
{
yield(); // wait
}
@@ -296,9 +444,11 @@ size_t HardwareSerial::write(uint8_t c)
} else {
tx_buffer_storage_[head - tx_buffer_size_] = c;
}
__disable_irq();
transmitting_ = 1;
tx_buffer_head_ = head;
port->CTRL |= LPUART_CTRL_TIE; // (may need to handle this issue)BITBAND_SET_BIT(LPUART0_CTRL, TIE_BIT);
__enable_irq();
//digitalWrite(3, LOW);
return 1;
}
@@ -310,30 +460,45 @@ void HardwareSerial::IRQHandler()
uint32_t ctrl;

// See if we have stuff to read in.
if (port->STAT & LPUART_STAT_RDRF) {
// Todo - Check idle.
if (port->STAT & (LPUART_STAT_RDRF | LPUART_STAT_IDLE)) {
// See how many bytes or pending.
//digitalWrite(5, HIGH);
#if 1
n = port->DATA; // get the byte...
#else
if (use9Bits_ && (port().C3 & 0x80)) {
n = port().D | 0x100;
} else {
n = port().D;
}
#endif
head = rx_buffer_head_ + 1;
if (head >= rx_buffer_total_size_) head = 0;
if (head != rx_buffer_tail_) {
if (head < rx_buffer_size_) {
rx_buffer_[head] = n;
} else {
rx_buffer_storage_[head-rx_buffer_size_] = n;
}
uint8_t avail = (port->WATER >> 24) & 0x7;
if (avail) {
uint32_t newhead;
head = rx_buffer_head_;
tail = rx_buffer_tail_;
do {
n = port->DATA & 0x3ff; // Use only up to 10 bits of data
newhead = head + 1;

if (newhead >= rx_buffer_total_size_) newhead = 0;
if (newhead != rx_buffer_tail_) {
head = newhead;
if (newhead < rx_buffer_size_) {
rx_buffer_[head] = n;
} else {
rx_buffer_storage_[head-rx_buffer_size_] = n;
}
}
} while (--avail > 0) ;
rx_buffer_head_ = head;
if (rts_pin_baseReg_) {
uint32_t avail;
if (head >= tail) avail = head - tail;
else avail = rx_buffer_total_size_ + head - tail;
if (avail >= rts_high_watermark_) rts_deassert();
}
}

// If it was an idle status clear the idle
if (port->STAT & LPUART_STAT_IDLE) {
port->STAT |= LPUART_STAT_IDLE; // writing a 1 to idle should clear it.
}
//digitalWrite(5, LOW);
}

}

// See if we are transmitting and room in buffer.
ctrl = port->CTRL;
@@ -351,19 +516,22 @@ void HardwareSerial::IRQHandler()
} else {
n = tx_buffer_storage_[tail-tx_buffer_size_];
}
//if (use9Bits_) port().C3 = (port().C3 & ~0x40) | ((n & 0x100) >> 2);
port->DATA = n;
} while (((port->WATER >> 8) & 0x7) < 4); // need to computer properly
tx_buffer_tail_ = tail;
if (head == tail) port->CTRL = CTRL_TX_COMPLETING;
if (head == tail) {
port->CTRL &= ~LPUART_CTRL_TIE;
port->CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
}
//digitalWrite(3, LOW);
}

if ((ctrl & LPUART_CTRL_TCIE) && (port->STAT & LPUART_STAT_TDRE))
if ((ctrl & LPUART_CTRL_TCIE) && (port->STAT & LPUART_STAT_TC))
{
transmitting_ = 0;
//if (transmit_pin_) transmit_deassert();
port->CTRL = CTRL_TX_INACTIVE;
if (transmit_pin_baseReg_) DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_);

port->CTRL &= ~LPUART_CTRL_TCIE;
}
//digitalWrite(4, LOW);
}
@@ -420,10 +588,13 @@ const HardwareSerial::hardware_t UART6_Hardware = {
CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON),
0, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03, // pin 0
1, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02, // pin 1
0xff, // No CTS pin
IOMUXC_LPUART6_RX_SELECT_INPUT,
2, // page 473
2, // page 472
0, // No CTS
1, // page 861
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial1(&IMXRT_LPUART6, &UART6_Hardware, tx_buffer1, SERIAL1_TX_BUFFER_SIZE,
rx_buffer1, SERIAL1_RX_BUFFER_SIZE);
@@ -437,10 +608,13 @@ static HardwareSerial::hardware_t UART4_Hardware = {
CCM_CCGR1, CCM_CCGR1_LPUART4(CCM_CCGR_ON),
6, //IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01, // pin 6
7, // IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00, // pin 7
0xff, // No CTS pin
IOMUXC_LPUART4_RX_SELECT_INPUT,
2, // page 521
2, // page 520
0, // No CTS
2, // page 858
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial2(&IMXRT_LPUART4, &UART4_Hardware, tx_buffer2, SERIAL2_TX_BUFFER_SIZE,
rx_buffer2, SERIAL2_RX_BUFFER_SIZE);
@@ -454,10 +628,13 @@ static HardwareSerial::hardware_t UART2_Hardware = {
CCM_CCGR0, CCM_CCGR0_LPUART2(CCM_CCGR_ON),
15, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03, // pin 15
14, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02, // pin 14
18, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_01, // 18
IOMUXC_LPUART2_RX_SELECT_INPUT,
2, // page 491
2, // page 490
2, // page 473
1, // Page 855
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial3(&IMXRT_LPUART2, &UART2_Hardware,tx_buffer3, SERIAL3_TX_BUFFER_SIZE,
rx_buffer3, SERIAL3_RX_BUFFER_SIZE);
@@ -471,10 +648,13 @@ static HardwareSerial::hardware_t UART3_Hardware = {
CCM_CCGR0, CCM_CCGR0_LPUART3(CCM_CCGR_ON),
16, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07, // pin 16
17, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06, // pin 17
0xff, // No CTS pin
IOMUXC_LPUART3_RX_SELECT_INPUT,
2, // page 495
2, // page 494
0, // No CTS
0, // Page 857
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial4(&IMXRT_LPUART3, &UART3_Hardware, tx_buffer4, SERIAL4_TX_BUFFER_SIZE,
rx_buffer4, SERIAL4_RX_BUFFER_SIZE);
@@ -488,10 +668,13 @@ static HardwareSerial::hardware_t UART8_Hardware = {
CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON),
21, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11, // pin 21
20, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10, // pin 20
0xff, // No CTS pin
IOMUXC_LPUART8_RX_SELECT_INPUT,
2, // page 499
2, // page 498
0, // No CTS
1, // Page 864-5
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial5(&IMXRT_LPUART8, &UART8_Hardware, tx_buffer5, SERIAL5_TX_BUFFER_SIZE,
rx_buffer5, SERIAL5_RX_BUFFER_SIZE);
@@ -506,10 +689,13 @@ static HardwareSerial::hardware_t UART1_Hardware = {
CCM_CCGR5, CCM_CCGR5_LPUART1(CCM_CCGR_ON),
25, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13, // pin 25
24, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12, // pin 24
0xff, // No CTS pin
IOMUXC_LPUART1_RX_SELECT_INPUT,
2, // page 486
2, // page 485
0, // No CTS
0, // ??? Does not have one ???
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark

};
HardwareSerial Serial6(&IMXRT_LPUART1, &UART1_Hardware, tx_buffer6, SERIAL6_TX_BUFFER_SIZE,
@@ -524,11 +710,14 @@ static HardwareSerial::hardware_t UART7_Hardware = {
CCM_CCGR5, CCM_CCGR5_LPUART7(CCM_CCGR_ON),
28, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32, // pin 28
29, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31, // pin 29
0xff, // No CTS pin
IOMUXC_LPUART7_RX_SELECT_INPUT,
2, // page 458
2, // page 457
0, // No CTS
1, // Page 863

IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial7(&IMXRT_LPUART7, &UART7_Hardware, tx_buffer7, SERIAL7_TX_BUFFER_SIZE,
rx_buffer7, SERIAL7_RX_BUFFER_SIZE);
@@ -542,10 +731,13 @@ static HardwareSerial::hardware_t UART5_Hardware = {
CCM_CCGR3, CCM_CCGR3_LPUART5(CCM_CCGR_ON),
30, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24, // pin 30
31, // IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_23, // pin 31
0xff, // No CTS pin
IOMUXC_LPUART5_RX_SELECT_INPUT,
2, // page 450
2, // page 449
0, // No CTS
0,
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark
};
HardwareSerial Serial8(&IMXRT_LPUART5, &UART5_Hardware, tx_buffer8, SERIAL8_TX_BUFFER_SIZE,
rx_buffer8, SERIAL8_RX_BUFFER_SIZE);

+ 87
- 87
teensy4/HardwareSerial.h View File

@@ -1,6 +1,6 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2017 PJRC.COM, LLC.
* Copyright (c) 2019 PJRC.COM, LLC.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -33,6 +33,75 @@

#include "imxrt.h"

// Uncomment to enable 9 bit formats. These are default disabled to save memory.
//#define SERIAL_9BIT_SUPPORT
//
// On Windows & Linux, this file is in Arduino's hardware/teensy/avr/cores/teensy3
// folder. The Windows installer puts Arduino in C:\Program Files (x86)\Arduino
// On Macintosh, you must control-click Arduino and select "Show Package Contents", then
// look in Contents/Java/hardware/teensy/avr/cores/teensy3 to find this file.
//
// Teensy 4.x boards support 9 bit mode on all their serial ports


#define SERIAL_7E1 0x02
#define SERIAL_7O1 0x03
#define SERIAL_8N1 0x00
#define SERIAL_8E1 0x06
#define SERIAL_8O1 0x07
#define SERIAL_7E1_RXINV 0x12
#define SERIAL_7O1_RXINV 0x13
#define SERIAL_8N1_RXINV 0x10
#define SERIAL_8E1_RXINV 0x16
#define SERIAL_8O1_RXINV 0x17
#define SERIAL_7E1_TXINV 0x22
#define SERIAL_7O1_TXINV 0x23
#define SERIAL_8N1_TXINV 0x20
#define SERIAL_8E1_TXINV 0x26
#define SERIAL_8O1_TXINV 0x27
#define SERIAL_7E1_RXINV_TXINV 0x32
#define SERIAL_7O1_RXINV_TXINV 0x33
#define SERIAL_8N1_RXINV_TXINV 0x30
#define SERIAL_8E1_RXINV_TXINV 0x36
#define SERIAL_8O1_RXINV_TXINV 0x37
#ifdef SERIAL_9BIT_SUPPORT
#define SERIAL_9N1 0x84
#define SERIAL_9E1 0x8E
#define SERIAL_9O1 0x8F
#define SERIAL_9N1_RXINV 0x94
#define SERIAL_9E1_RXINV 0x9E
#define SERIAL_9O1_RXINV 0x9F
#define SERIAL_9N1_TXINV 0xA4
#define SERIAL_9E1_TXINV 0xAE
#define SERIAL_9O1_TXINV 0xAF
#define SERIAL_9N1_RXINV_TXINV 0xB4
#define SERIAL_9E1_RXINV_TXINV 0xBE
#define SERIAL_9O1_RXINV_TXINV 0xBF
#endif
// We have 1/2 bit stop setting
#define SERIAL_2STOP_BITS 0x100
#define SERIAL_8E2 (SERIAL_8E1 | SERIAL_2STOP_BITS)
#define SERIAL_8O2 (SERIAL_8O1 | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV (SERIAL_8E1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV (SERIAL_8O1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_TXINV (SERIAL_8E1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_TXINV (SERIAL_8O1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV_TXINV (SERIAL_8E1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV_TXINV (SERIAL_8O1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_TXINV | SERIAL_2STOP_BITS)
// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
// bit3: mode10: 1=10bit, 0=8bit
// bit4: rxinv, 0=normal, 1=inverted
// bit5: txinv, 0=normal, 1=inverted
// bit6: unused
// bit7: actual data goes into 9th bit


#ifdef __cplusplus
#include "Stream.h"
#include "core_pins.h"
@@ -64,12 +133,15 @@ public:
const uint32_t ccm_value;
const uint8_t rx_pin;
const uint8_t tx_pin;
//volatile uint32_t &rx_mux_register;
//volatile uint32_t &tx_mux_register;
const uint8_t cts_pin;
volatile uint32_t &rx_select_input_register;
const uint8_t rx_mux_val;
const uint8_t tx_mux_val;
const uint8_t cts_mux_val;
const uint8_t rx_select_val;
const uint16_t irq_priority;
const uint16_t rts_low_watermark;
const uint16_t rts_high_watermark;
} hardware_t;
public:
constexpr HardwareSerial(IMXRT_LPUART_t *myport, const hardware_t *myhardware,
@@ -79,7 +151,7 @@ public:
tx_buffer_(_tx_buffer), rx_buffer_(_rx_buffer), tx_buffer_size_(_tx_buffer_size), rx_buffer_size_(_rx_buffer_size),
tx_buffer_total_size_(_tx_buffer_size), rx_buffer_total_size_(_rx_buffer_size) {
}
void begin(uint32_t baud, uint8_t format=0);
void begin(uint32_t baud, uint16_t format=0);
void end(void);

virtual int available(void);
@@ -95,6 +167,8 @@ public:
bool attachCts(uint8_t pin);
void clear(void);
int availableForWrite(void);
void addStorageForRead(void *buffer, size_t length);
void addStorageForWrite(void *buffer, size_t length);
size_t write9bit(uint32_t c);

using Print::write;
@@ -120,20 +194,22 @@ private:
size_t rx_buffer_size_;
size_t tx_buffer_total_size_;
size_t rx_buffer_total_size_;
size_t rts_low_watermark_ = 0;
size_t rts_high_watermark_ = 0;
volatile uint8_t transmitting_ = 0;
volatile uint16_t tx_buffer_head_ = 0;
volatile uint16_t tx_buffer_tail_ = 0;
volatile uint16_t rx_buffer_head_ = 0;
volatile uint16_t rx_buffer_tail_ = 0;

// Currently using digitalWWrite...
int transmit_pin_=-1;
int rts_pin_=-1;
volatile uint32_t *transmit_pin_baseReg_ = 0;
uint32_t transmit_pin_bitmask_ = 0;

volatile uint32_t *rts_pin_baseReg_ = 0;
uint32_t rts_pin_bitmask_ = 0;

inline void transmit_assert() {digitalWrite(transmit_pin_, 1);}
inline void transmit_deassert() {digitalWrite(transmit_pin_, 0);}
inline void rts_assert() {digitalWrite(rts_pin_ , 0); }
inline void rts_deassert() {digitalWrite(rts_pin_ , 1); }
inline void rts_assert();
inline void rts_deassert();

void IRQHandler();
friend void IRQHandler_Serial1();
@@ -161,82 +237,6 @@ extern HardwareSerial Serial8;
#endif // __cplusplus


// Uncomment to enable 9 bit formats. These are default disabled to save memory.
//#define SERIAL_9BIT_SUPPORT
//
// On Windows & Linux, this file is in Arduino's hardware/teensy/avr/cores/teensy3
// folder. The Windows installer puts Arduino in C:\Program Files (x86)\Arduino
// On Macintosh, you must control-click Arduino and select "Show Package Contents", then
// look in Contents/Java/hardware/teensy/avr/cores/teensy3 to find this file.
//
// Teensy 3.x boards support 9 bit mode on all their serial ports
// Teensy LC only supports 9 bit mode on Serial1. Serial2 & Serial3 can't use 9 bits.


#define SERIAL_7E1 0x02
#define SERIAL_7O1 0x03
#define SERIAL_8N1 0x00
#define SERIAL_8E1 0x06
#define SERIAL_8O1 0x07
#define SERIAL_7E1_RXINV 0x12
#define SERIAL_7O1_RXINV 0x13
#define SERIAL_8N1_RXINV 0x10
#define SERIAL_8E1_RXINV 0x16
#define SERIAL_8O1_RXINV 0x17
#define SERIAL_7E1_TXINV 0x22
#define SERIAL_7O1_TXINV 0x23
#define SERIAL_8N1_TXINV 0x20
#define SERIAL_8E1_TXINV 0x26
#define SERIAL_8O1_TXINV 0x27
#define SERIAL_7E1_RXINV_TXINV 0x32
#define SERIAL_7O1_RXINV_TXINV 0x33
#define SERIAL_8N1_RXINV_TXINV 0x30
#define SERIAL_8E1_RXINV_TXINV 0x36
#define SERIAL_8O1_RXINV_TXINV 0x37
#ifdef SERIAL_9BIT_SUPPORT
#define SERIAL_9N1 0x84
#define SERIAL_9E1 0x8E
#define SERIAL_9O1 0x8F
#define SERIAL_9N1_RXINV 0x94
#define SERIAL_9E1_RXINV 0x9E
#define SERIAL_9O1_RXINV 0x9F
#define SERIAL_9N1_TXINV 0xA4
#define SERIAL_9E1_TXINV 0xAE
#define SERIAL_9O1_TXINV 0xAF
#define SERIAL_9N1_RXINV_TXINV 0xB4
#define SERIAL_9E1_RXINV_TXINV 0xBE
#define SERIAL_9O1_RXINV_TXINV 0xBF
#endif
// Teensy LC and 3.5 and 3.6 Uarts have 1/2 bit stop setting
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(KINETISL)
#define SERIAL_2STOP_BITS 0x100
#define SERIAL_8E2 (SERIAL_8E1 | SERIAL_2STOP_BITS)
#define SERIAL_8O2 (SERIAL_8O1 | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV (SERIAL_8E1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV (SERIAL_8O1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_TXINV (SERIAL_8E1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_TXINV (SERIAL_8O1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8E2_RXINV_TXINV (SERIAL_8E1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8O2_RXINV_TXINV (SERIAL_8O1_RXINV_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2 (SERIAL_8N1 | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_TXINV | SERIAL_2STOP_BITS)
#else
// for Teensy 3.0-3.2 we can fake 2 stop bits by using 9 bit mode
#define SERIAL_8N2 0x04
#define SERIAL_8N2_RXINV 0x14
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8N2_RXINV_TXINV 0x34
#endif
// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
// bit3: mode10: 1=10bit, 0=8bit
// bit4: rxinv, 0=normal, 1=inverted
// bit5: txinv, 0=normal, 1=inverted
// bit6: unused
// bit7: actual data goes into 9th bit


// TODO: replace with proper divisor+oversample calculation

Loading…
Cancel
Save