Browse Source

T3.x,T4.x LC Serial half duplex support

Migrating the half duplex support I did in the Stagnant and out of date PR to enhance Uarts: https://github.com/PaulStoffregen/cores/pull/419

To try to support Half duplex mode in a similar way like we do for RS485 like support.

With T3.x made use of bitband address for the TX Direction setting, so
Except for the begin which calls format, no code changed, we simply stored the bitband address of the TXDIR flag into the TXDIR variable that was already used for the set direction flag.

For T4.x - it is a little more work as there is no bitband support on M7 processors.  For GPIO there is a Set and Clear register which we use, but for the appropriate UART register there is no such setup of registers.  So I have to special case we are in that mode and do it... Also since not atomic I cli/sei...

Serial Half Duplex - Fix T4Serial1 and T-LC Serial1-3

Updates: T4
T4 Serial 1 did not have proper settings for IOMUXC_LPUART6_TX_SELECT_INPUT

Tested T4.1 Serial1-8

Tested T3.5 Serial1-6

T3.6 - Added support for LPUART which is Serial6 which now works.

T-LC
Make half duplex work on T-LC on Serials1-3

Tested on on T3.5 1-6
teensy4-core
Kurt Eckhardt 4 years ago
parent
commit
98f01a0d06
11 changed files with 293 additions and 20 deletions
  1. +3
    -0
      teensy3/HardwareSerial.h
  2. +55
    -0
      teensy3/serial1.c
  3. +50
    -0
      teensy3/serial2.c
  4. +55
    -0
      teensy3/serial3.c
  5. +26
    -0
      teensy3/serial4.c
  6. +18
    -0
      teensy3/serial5.c
  7. +17
    -0
      teensy3/serial6.c
  8. +29
    -10
      teensy3/serial6_lpuart.c
  9. +33
    -9
      teensy4/HardwareSerial.cpp
  10. +6
    -0
      teensy4/HardwareSerial.h
  11. +1
    -1
      teensy4/HardwareSerial1.cpp

+ 3
- 0
teensy3/HardwareSerial.h View File

@@ -101,6 +101,9 @@
#define SERIAL_8N2_TXINV 0x24
#define SERIAL_8N2_RXINV_TXINV 0x34
#endif

#define SERIAL_HALF_DUPLEX 0x200

// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit

+ 55
- 0
teensy3/serial1.c View File

@@ -101,6 +101,9 @@ static volatile uint8_t rx_buffer_tail = 0;
#endif
static uint8_t rx_pin_num = 0;
static uint8_t tx_pin_num = 1;
#if defined(KINETISL)
static uint8_t half_duplex_mode = 0;
#endif

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
@@ -114,6 +117,12 @@ static uint8_t tx_pin_num = 1;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5


void serial_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband
@@ -198,6 +207,34 @@ void serial_format(uint32_t format)
UART0_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
c = UART0_C1;
c |= UART_C1_LOOPS | UART_C1_RSRC;
UART0_C1 = c;

// Lets try to make use of bitband address to set the direction for ue...
#if defined(KINETISL)
switch (tx_pin_num) {
case 1: CORE_PIN1_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS ; break;
case 5: CORE_PIN5_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; break;
case 4: CORE_PIN4_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2) | PORT_PCR_PE | PORT_PCR_PS; break;
case 24: CORE_PIN24_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(4) | PORT_PCR_PE | PORT_PCR_PS; break;
}
half_duplex_mode = 1;
#else
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART0_C3, C3_TXDIR_BIT);
#endif

} else {
#if defined(KINETISL)
half_duplex_mode = 0;
#else
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART0_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
#endif
}
}

void serial_end(void)
@@ -369,6 +406,15 @@ void serial_putchar(uint32_t c)

if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) transmit_assert();
#if defined(KINETISL)
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART0_C3;
reg |= UART_C3_TXDIR;
UART0_C3 = reg;
__enable_irq();
}
#endif
head = tx_buffer_head;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
@@ -615,6 +661,15 @@ void uart0_status_isr(void)
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
#if defined(KINETISL)
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART0_C3;
reg &= ~UART_C3_TXDIR;
UART0_C3 = reg;
__enable_irq();
}
#endif
UART0_C2 = C2_TX_INACTIVE;
}
}

+ 50
- 0
teensy3/serial2.c View File

@@ -102,6 +102,9 @@ static volatile uint8_t rx_buffer_tail = 0;
static uint8_t rx_pin_num = 9;
static uint8_t tx_pin_num = 10;
#endif
#if defined(KINETISL)
static uint8_t half_duplex_mode = 0;
#endif

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
@@ -115,6 +118,11 @@ static uint8_t tx_pin_num = 10;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5

void serial2_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband
@@ -198,6 +206,30 @@ void serial2_format(uint32_t format)
UART1_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
c = UART1_C1;
c |= UART_C1_LOOPS | UART_C1_RSRC;
UART1_C1 = c;

// Lets try to make use of bitband address to set the direction for ue...
#if defined(KINETISL)
//CORE_PIN10_CONFIG = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(1) | PORT_PCR_PE | PORT_PCR_PS;
CORE_PIN10_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3);
half_duplex_mode = 1;
#else
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART1_C3, C3_TXDIR_BIT);
#endif

} else {
#if defined(KINETISL)
half_duplex_mode = 0;
#else
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART1_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
#endif
}
}

void serial2_end(void)
@@ -359,6 +391,15 @@ void serial2_putchar(uint32_t c)

if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
if (transmit_pin) transmit_assert();
#if defined(KINETISL)
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART1_C3;
reg |= UART_C3_TXDIR;
UART1_C3 = reg;
__enable_irq();
}
#endif
head = tx_buffer_head;
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
@@ -605,6 +646,15 @@ void uart1_status_isr(void)
if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
#if defined(KINETISL)
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART1_C3;
reg &= ~UART_C3_TXDIR;
UART1_C3 = reg;
__enable_irq();
}
#endif
UART1_C2 = C2_TX_INACTIVE;
}
}

+ 55
- 0
teensy3/serial3.c View File

@@ -104,6 +104,10 @@ static uint8_t rx_pin_num = 7;
#endif
static uint8_t tx_pin_num = 8;

#if defined(KINETISL)
static uint8_t half_duplex_mode = 0;
#endif

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer

@@ -112,6 +116,11 @@ static uint8_t tx_pin_num = 8;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5

void serial3_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband
@@ -180,6 +189,33 @@ void serial3_format(uint32_t format)
UART2_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
c = UART2_C1;
c |= UART_C1_LOOPS | UART_C1_RSRC;
UART2_C1 = c;


// Lets try to make use of bitband address to set the direction for ue...
#if defined(KINETISL)
switch (tx_pin_num) {
case 8: CORE_PIN8_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
case 20: CORE_PIN20_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); break;
}
half_duplex_mode = 1;
#else
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART2_C3, C3_TXDIR_BIT);
#endif

} else {
#if defined(KINETISL)
half_duplex_mode = 0;
#else
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART2_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
#endif
}

}

@@ -315,6 +351,15 @@ void serial3_putchar(uint32_t c)

if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return;
if (transmit_pin) transmit_assert();
#if defined(KINETISL)
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART2_C3;
reg |= UART_C3_TXDIR;
UART2_C3 = reg;
__enable_irq();
}
#endif
head = tx_buffer_head;
if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
@@ -456,6 +501,16 @@ void uart2_status_isr(void)
if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
#if defined(KINETISL)
if (transmit_pin) transmit_deassert();
if (half_duplex_mode) {
__disable_irq();
volatile uint32_t reg = UART2_C3;
reg &= ~UART_C3_TXDIR;
UART2_C3 = reg;
__enable_irq();
}
#endif
UART2_C2 = C2_TX_INACTIVE;
}
}

+ 26
- 0
teensy3/serial4.c View File

@@ -102,6 +102,11 @@ static uint8_t tx_pin_num = 32;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5

void serial4_begin(uint32_t divisor)
{
SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband
@@ -158,6 +163,27 @@ void serial4_format(uint32_t format)
UART3_BDL = bdl; // Says BDH not acted on until BDL is written
}
#endif
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
UART3_C1 |= UART_C1_LOOPS | UART_C1_RSRC;
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;

// Lets try to make use of bitband address to set the direction for ue...
#if defined(KINETISL)
transmit_pin = &UART3_C3;
transmit_mask = UART_C3_TXDIR;
#else
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART3_C3, C3_TXDIR_BIT);
#endif

} else {
#if defined(KINETISL)
if (transmit_pin == &UART3_C3) transmit_pin = NULL;
#else
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART3_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
#endif
}
}

void serial4_end(void)

+ 18
- 0
teensy3/serial5.c View File

@@ -101,6 +101,11 @@ static uint8_t tx_pin_num = 33;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5

void serial5_begin(uint32_t divisor)
{
SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband
@@ -149,6 +154,19 @@ void serial5_format(uint32_t format)
UART4_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART4_BDL = bdl; // Says BDH not acted on until BDL is written
}
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
UART4_C1 |= UART_C1_LOOPS | UART_C1_RSRC;
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;

// Lets try to make use of bitband address to set the direction for ue...
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART4_C3, C3_TXDIR_BIT);

} else {
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART4_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
}

}

void serial5_end(void)

+ 17
- 0
teensy3/serial6.c View File

@@ -101,6 +101,11 @@ static uint8_t tx_pin_num = 48;
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE

// BITBAND Support
#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000)
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define C3_TXDIR_BIT 5

void serial6_begin(uint32_t divisor)
{
SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband
@@ -149,6 +154,18 @@ void serial6_format(uint32_t format)
UART5_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud
UART5_BDL = bdl; // Says BDH not acted on until BDL is written
}
// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
UART5_C1 |= UART_C1_LOOPS | UART_C1_RSRC;
volatile uint32_t *reg = portConfigRegister(tx_pin_num);
*reg = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3) | PORT_PCR_PE | PORT_PCR_PS; // pullup on output pin;

// Lets try to make use of bitband address to set the direction for ue...
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(UART5_C3, C3_TXDIR_BIT);

} else {
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(UART5_C3, C3_TXDIR_BIT)) transmit_pin = NULL;
}
}

void serial6_end(void)

+ 29
- 10
teensy3/serial6_lpuart.c View File

@@ -38,8 +38,15 @@
#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit)))
#define BITBAND_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1)
#define BITBAND_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0)
#define TCIE_BIT 22
#define TIE_BIT 23

#define CTRL_TXDIR_BIT 29
#define CTRL_TIE_BIT 23
#define CTRL_TCIE_BIT 22
#define CTRL_TE_BIT 19
#define CTRL_RE_BIT 18
#define CTRL_LOOPS_BIT 7
#define CTRL_RSRC_BIT 5



////////////////////////////////////////////////////////////////
@@ -95,9 +102,6 @@ static volatile uint8_t rx_buffer_tail = 0;

static uint8_t tx_pin_num = 48;

// UART0 and UART1 are clocked by F_CPU, UART2 is clocked by F_BUS
// UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer


void serial6_begin(uint32_t desiredBaudRate)
{
@@ -225,6 +229,21 @@ void serial6_format(uint32_t format)

// For T3.6 See about turning on 2 stop bit mode
if ( format & 0x100) LPUART0_BAUD |= LPUART_BAUD_SBNS;

// process request for half duplex.
if ((format & SERIAL_HALF_DUPLEX) != 0) {
BITBAND_SET_BIT(LPUART0_CTRL, CTRL_LOOPS_BIT);
BITBAND_SET_BIT(LPUART0_CTRL, CTRL_RSRC_BIT);

CORE_PIN48_CONFIG = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(5);

// Lets try to make use of bitband address to set the direction for ue...
transmit_pin = (uint8_t*)GPIO_BITBAND_PTR(LPUART0_CTRL, CTRL_TXDIR_BIT);
} else {
if (transmit_pin == (uint8_t*)GPIO_BITBAND_PTR(LPUART0_CTRL, CTRL_TXDIR_BIT)) transmit_pin = NULL;
BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_LOOPS_BIT);
BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_RSRC_BIT);
}
}

void serial6_end(void)
@@ -307,6 +326,7 @@ void serial6_putchar(uint32_t c)

if (!(SIM_SCGC2 & SIM_SCGC2_LPUART0)) return;
if (transmit_pin) transmit_assert();

head = tx_buffer_head;
if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) {
@@ -329,7 +349,7 @@ void serial6_putchar(uint32_t c)
tx_buffer_head = head;

//LPUART0_CTRL |= LPUART_CTRL_TIE; // enable the transmit interrupt
BITBAND_SET_BIT(LPUART0_CTRL, TIE_BIT);
BITBAND_SET_BIT(LPUART0_CTRL, CTRL_TIE_BIT);

}

@@ -413,7 +433,6 @@ void lpuart0_status_isr(void)
{
uint32_t head, tail, n;
uint32_t c;

if (LPUART0_STAT & LPUART_STAT_RDRF) {
// if (use9Bits && (UART5_C3 & 0x80)) {
// n = UART5_D | 0x100;
@@ -440,8 +459,8 @@ void lpuart0_status_isr(void)
head = tx_buffer_head;
tail = tx_buffer_tail;
if (head == tail) {
BITBAND_CLR_BIT(LPUART0_CTRL, TIE_BIT);
BITBAND_SET_BIT(LPUART0_CTRL, TCIE_BIT);
BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_TIE_BIT);
BITBAND_SET_BIT(LPUART0_CTRL, CTRL_TCIE_BIT);
//LPUART0_CTRL &= ~LPUART_CTRL_TIE;
//LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
} else {
@@ -455,7 +474,7 @@ void lpuart0_status_isr(void)
if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) {
transmitting = 0;
if (transmit_pin) transmit_deassert();
BITBAND_CLR_BIT(LPUART0_CTRL, TCIE_BIT);
BITBAND_CLR_BIT(LPUART0_CTRL, CTRL_TCIE_BIT);
// LPUART0_CTRL &= ~LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
}
}

+ 33
- 9
teensy4/HardwareSerial.cpp View File

@@ -139,15 +139,23 @@ void HardwareSerial::begin(uint32_t baud, uint16_t format)

// uint32_t fastio = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);

*(portControlRegister(hardware->rx_pins[rx_pin_index_].pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
*(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = hardware->rx_pins[rx_pin_index_].mux_val;
if (hardware->rx_pins[rx_pin_index_].select_input_register) {
*(hardware->rx_pins[rx_pin_index_].select_input_register) = hardware->rx_pins[rx_pin_index_].select_val;
}

*(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);
*(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val;

// Maybe different pin configs if half duplex
half_duplex_mode_ = (format & SERIAL_HALF_DUPLEX) != 0;
if (!half_duplex_mode_) {
*(portControlRegister(hardware->rx_pins[rx_pin_index_].pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
*(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = hardware->rx_pins[rx_pin_index_].mux_val;
if (hardware->rx_pins[rx_pin_index_].select_input_register) {
*(hardware->rx_pins[rx_pin_index_].select_input_register) = hardware->rx_pins[rx_pin_index_].select_val;
}

*(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3);
*(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val;
} else {
// Half duplex maybe different pin pad config like PU...
*(portControlRegister(hardware->tx_pins[tx_pin_index_].pin)) = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3)
| IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3);
*(portConfigRegister(hardware->tx_pins[tx_pin_index_].pin)) = hardware->tx_pins[tx_pin_index_].mux_val;
}
if (hardware->tx_pins[tx_pin_index_].select_input_register) {
*(hardware->tx_pins[tx_pin_index_].select_input_register) = hardware->tx_pins[tx_pin_index_].select_val;
}
@@ -187,6 +195,9 @@ void HardwareSerial::begin(uint32_t baud, uint16_t format)
// Bit 5 TXINVERT
if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert

// Now see if the user asked for Half duplex:
if (half_duplex_mode_) ctrl |= (LPUART_CTRL_LOOPS | LPUART_CTRL_RSRC);

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

@@ -525,6 +536,13 @@ size_t HardwareSerial::write9bit(uint32_t c)
//digitalWrite(3, HIGH);
//digitalWrite(5, HIGH);
if (transmit_pin_baseReg_) DIRECT_WRITE_HIGH(transmit_pin_baseReg_, transmit_pin_bitmask_);
if(half_duplex_mode_) {
__disable_irq();
port->CTRL |= LPUART_CTRL_TXDIR;
__enable_irq();
//digitalWriteFast(2, HIGH);
}

head = tx_buffer_head_;
if (++head >= tx_buffer_total_size_) head = 0;
while (tx_buffer_tail_ == head) {
@@ -639,6 +657,12 @@ void HardwareSerial::IRQHandler()
{
transmitting_ = 0;
if (transmit_pin_baseReg_) DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_);
if(half_duplex_mode_) {
__disable_irq();
port->CTRL &= ~LPUART_CTRL_TXDIR;
__enable_irq();
//digitalWriteFast(2, LOW);
}

port->CTRL &= ~LPUART_CTRL_TCIE;
}

+ 6
- 0
teensy4/HardwareSerial.h View File

@@ -92,6 +92,9 @@
#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)

#define SERIAL_HALF_DUPLEX 0x200

// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
@@ -101,6 +104,8 @@
// bit6: unused
// bit7: actual data goes into 9th bit

// bit8: 2 stop bits
// bit9: Half Duplex Mode

#ifdef __cplusplus
#include "Stream.h"
@@ -235,6 +240,7 @@ private:
const hardware_t * const hardware;
uint8_t rx_pin_index_ = 0x0; // default is always first item
uint8_t tx_pin_index_ = 0x0;
uint8_t half_duplex_mode_ = 0; // are we in half duplex mode?

volatile BUFTYPE *tx_buffer_;
volatile BUFTYPE *rx_buffer_;

+ 1
- 1
teensy4/HardwareSerial1.cpp View File

@@ -57,7 +57,7 @@ const HardwareSerial::hardware_t UART6_Hardware = {
CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON),
#if defined(ARDUINO_TEENSY41)
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {52, 2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 0}},
{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 0}, {53, 2, nullptr, 0}},
{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {53, 2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 0}},
#else
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},

Loading…
Cancel
Save