Browse Source

Merge pull request #489 from KurtE/serial_half_duplex

T3.x,T4.x LC Serial half duplex support
main
Paul Stoffregen 4 years ago
parent
commit
1268d2666f
No account linked to committer's email address
11 changed files with 303 additions and 20 deletions
  1. +9
    -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. +10
    -0
      teensy4/HardwareSerial.h
  11. +1
    -1
      teensy4/HardwareSerial1.cpp

+ 9
- 0
teensy3/HardwareSerial.h View File

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

// Half duplex support
#define SERIAL_HALF_DUPLEX 0x200
#define SERIAL_7E1_HALF_DUPLEX (SERIAL_7E1 | SERIAL_HALF_DUPLEX)
#define SERIAL_7O1_HALF_DUPLEX (SERIAL_7O1 | SERIAL_HALF_DUPLEX)
#define SERIAL_8N1_HALF_DUPLEX (SERIAL_8N1 | SERIAL_HALF_DUPLEX)

// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
@@ -109,6 +116,8 @@
// bit5: txinv, 0=normal, 1=inverted
// bit6: unused
// bit7: actual data goes into 9th bit
// bit8: 2 stop bits (T3.5/3.6 and LC)
// bit9: Half duplex


#if defined(KINETISK)

+ 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;
}

+ 10
- 0
teensy4/HardwareSerial.h View File

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

// Half duplex support
#define SERIAL_HALF_DUPLEX 0x200
#define SERIAL_7E1_HALF_DUPLEX (SERIAL_7E1 | SERIAL_HALF_DUPLEX)
#define SERIAL_7O1_HALF_DUPLEX (SERIAL_7O1 | SERIAL_HALF_DUPLEX)
#define SERIAL_8N1_HALF_DUPLEX (SERIAL_8N1 | SERIAL_HALF_DUPLEX)

// bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit
@@ -101,6 +108,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 +244,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