Browse Source

Merge pull request #489 from KurtE/serial_half_duplex

T3.x,T4.x LC Serial half duplex support
teensy4-core
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

#define SERIAL_8N2_TXINV 0x24 #define SERIAL_8N2_TXINV 0x24
#define SERIAL_8N2_RXINV_TXINV 0x34 #define SERIAL_8N2_RXINV_TXINV 0x34
#endif #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 // bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable // bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit // bit2: mode, 1=9bit, 0=8bit
// bit5: txinv, 0=normal, 1=inverted // bit5: txinv, 0=normal, 1=inverted
// bit6: unused // bit6: unused
// bit7: actual data goes into 9th bit // bit7: actual data goes into 9th bit
// bit8: 2 stop bits (T3.5/3.6 and LC)
// bit9: Half duplex




#if defined(KINETISK) #if defined(KINETISK)

+ 55
- 0
teensy3/serial1.c View File

#endif #endif
static uint8_t rx_pin_num = 0; static uint8_t rx_pin_num = 0;
static uint8_t tx_pin_num = 1; 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 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 // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial_begin(uint32_t divisor)
{ {
SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband SIM_SCGC4 |= SIM_SCGC4_UART0; // turn on clock, TODO: use bitband
UART0_BDL = bdl; // Says BDH not acted on until BDL is written UART0_BDL = bdl; // Says BDH not acted on until BDL is written
} }
#endif #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) void serial_end(void)


if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return; if (!(SIM_SCGC4 & SIM_SCGC4_UART0)) return;
if (transmit_pin) transmit_assert(); 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; head = tx_buffer_head;
if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0; if (++head >= SERIAL1_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) { while (tx_buffer_tail == head) {
if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) { if ((c & UART_C2_TCIE) && (UART0_S1 & UART_S1_TC)) {
transmitting = 0; transmitting = 0;
if (transmit_pin) transmit_deassert(); 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; UART0_C2 = C2_TX_INACTIVE;
} }
} }

+ 50
- 0
teensy3/serial2.c View File

static uint8_t rx_pin_num = 9; static uint8_t rx_pin_num = 9;
static uint8_t tx_pin_num = 10; static uint8_t tx_pin_num = 10;
#endif #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 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 // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer
#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial2_begin(uint32_t divisor)
{ {
SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband SIM_SCGC4 |= SIM_SCGC4_UART1; // turn on clock, TODO: use bitband
UART1_BDL = bdl; // Says BDH not acted on until BDL is written UART1_BDL = bdl; // Says BDH not acted on until BDL is written
} }
#endif #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) void serial2_end(void)


if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return; if (!(SIM_SCGC4 & SIM_SCGC4_UART1)) return;
if (transmit_pin) transmit_assert(); 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; head = tx_buffer_head;
if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0; if (++head >= SERIAL2_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) { while (tx_buffer_tail == head) {
if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) { if ((c & UART_C2_TCIE) && (UART1_S1 & UART_S1_TC)) {
transmitting = 0; transmitting = 0;
if (transmit_pin) transmit_deassert(); 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; UART1_C2 = C2_TX_INACTIVE;
} }
} }

+ 55
- 0
teensy3/serial3.c View File

#endif #endif
static uint8_t tx_pin_num = 8; 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 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 // UART0 has 8 byte fifo, UART1 and UART2 have 1 byte buffer


#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial3_begin(uint32_t divisor)
{ {
SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband SIM_SCGC4 |= SIM_SCGC4_UART2; // turn on clock, TODO: use bitband
UART2_BDL = bdl; // Says BDH not acted on until BDL is written UART2_BDL = bdl; // Says BDH not acted on until BDL is written
} }
#endif #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
}


} }




if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return; if (!(SIM_SCGC4 & SIM_SCGC4_UART2)) return;
if (transmit_pin) transmit_assert(); 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; head = tx_buffer_head;
if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0; if (++head >= SERIAL3_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) { while (tx_buffer_tail == head) {
if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) { if ((c & UART_C2_TCIE) && (UART2_S1 & UART_S1_TC)) {
transmitting = 0; transmitting = 0;
if (transmit_pin) transmit_deassert(); 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; UART2_C2 = C2_TX_INACTIVE;
} }
} }

+ 26
- 0
teensy3/serial4.c View File

#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial4_begin(uint32_t divisor)
{ {
SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband SIM_SCGC4 |= SIM_SCGC4_UART3; // turn on clock, TODO: use bitband
UART3_BDL = bdl; // Says BDH not acted on until BDL is written UART3_BDL = bdl; // Says BDH not acted on until BDL is written
} }
#endif #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) void serial4_end(void)

+ 18
- 0
teensy3/serial5.c View File

#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial5_begin(uint32_t divisor)
{ {
SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband SIM_SCGC1 |= SIM_SCGC1_UART4; // turn on clock, TODO: use bitband
UART4_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud 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 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) void serial5_end(void)

+ 17
- 0
teensy3/serial6.c View File

#define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE #define C2_TX_COMPLETING C2_ENABLE | UART_C2_TCIE
#define C2_TX_INACTIVE C2_ENABLE #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) void serial6_begin(uint32_t divisor)
{ {
SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband SIM_SCGC1 |= SIM_SCGC1_UART5; // turn on clock, TODO: use bitband
UART5_BDH |= UART_BDH_SBNS; // Turn on 2 stop bits - was turned off by set baud 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 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) void serial6_end(void)

+ 29
- 10
teensy3/serial6_lpuart.c View File

#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) #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_SET_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 1)
#define BITBAND_CLR_BIT(reg, bit) (*GPIO_BITBAND_PTR((reg), (bit)) = 0) #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





//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////


static uint8_t tx_pin_num = 48; 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) void serial6_begin(uint32_t desiredBaudRate)
{ {


// For T3.6 See about turning on 2 stop bit mode // For T3.6 See about turning on 2 stop bit mode
if ( format & 0x100) LPUART0_BAUD |= LPUART_BAUD_SBNS; 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) void serial6_end(void)


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

head = tx_buffer_head; head = tx_buffer_head;
if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0; if (++head >= SERIAL6_TX_BUFFER_SIZE) head = 0;
while (tx_buffer_tail == head) { while (tx_buffer_tail == head) {
tx_buffer_head = head; tx_buffer_head = head;


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


} }


{ {
uint32_t head, tail, n; uint32_t head, tail, n;
uint32_t c; uint32_t c;

if (LPUART0_STAT & LPUART_STAT_RDRF) { if (LPUART0_STAT & LPUART_STAT_RDRF) {
// if (use9Bits && (UART5_C3 & 0x80)) { // if (use9Bits && (UART5_C3 & 0x80)) {
// n = UART5_D | 0x100; // n = UART5_D | 0x100;
head = tx_buffer_head; head = tx_buffer_head;
tail = tx_buffer_tail; tail = tx_buffer_tail;
if (head == 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_TIE;
//LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on... //LPUART0_CTRL |= LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
} else { } else {
if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) { if ((c & LPUART_CTRL_TCIE) && (LPUART0_STAT & LPUART_STAT_TC)) {
transmitting = 0; transmitting = 0;
if (transmit_pin) transmit_deassert(); 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... // LPUART0_CTRL &= ~LPUART_CTRL_TCIE; // Actually wondering if we can just leave this one on...
} }
} }

+ 33
- 9
teensy4/HardwareSerial.cpp View File



// uint32_t fastio = IOMUXC_PAD_SRE | IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3); // 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) { 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; *(hardware->tx_pins[tx_pin_index_].select_input_register) = hardware->tx_pins[tx_pin_index_].select_val;
} }
// Bit 5 TXINVERT // Bit 5 TXINVERT
if (format & 0x20) ctrl |= LPUART_CTRL_TXINV; // tx invert 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 // write out computed CTRL
port->CTRL = ctrl; port->CTRL = ctrl;


//digitalWrite(3, HIGH); //digitalWrite(3, HIGH);
//digitalWrite(5, HIGH); //digitalWrite(5, HIGH);
if (transmit_pin_baseReg_) DIRECT_WRITE_HIGH(transmit_pin_baseReg_, transmit_pin_bitmask_); 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_; head = tx_buffer_head_;
if (++head >= tx_buffer_total_size_) head = 0; if (++head >= tx_buffer_total_size_) head = 0;
while (tx_buffer_tail_ == head) { while (tx_buffer_tail_ == head) {
{ {
transmitting_ = 0; transmitting_ = 0;
if (transmit_pin_baseReg_) DIRECT_WRITE_LOW(transmit_pin_baseReg_, transmit_pin_bitmask_); 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; port->CTRL &= ~LPUART_CTRL_TCIE;
} }

+ 10
- 0
teensy4/HardwareSerial.h View File

#define SERIAL_8N2_RXINV (SERIAL_8N1_RXINV | 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_TXINV (SERIAL_8N1_TXINV | SERIAL_2STOP_BITS)
#define SERIAL_8N2_RXINV_TXINV (SERIAL_8N1_RXINV_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 // bit0: parity, 0=even, 1=odd
// bit1: parity, 0=disable, 1=enable // bit1: parity, 0=disable, 1=enable
// bit2: mode, 1=9bit, 0=8bit // bit2: mode, 1=9bit, 0=8bit
// bit6: unused // bit6: unused
// bit7: actual data goes into 9th bit // bit7: actual data goes into 9th bit


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


#ifdef __cplusplus #ifdef __cplusplus
#include "Stream.h" #include "Stream.h"
const hardware_t * const hardware; const hardware_t * const hardware;
uint8_t rx_pin_index_ = 0x0; // default is always first item uint8_t rx_pin_index_ = 0x0; // default is always first item
uint8_t tx_pin_index_ = 0x0; uint8_t tx_pin_index_ = 0x0;
uint8_t half_duplex_mode_ = 0; // are we in half duplex mode?


volatile BUFTYPE *tx_buffer_; volatile BUFTYPE *tx_buffer_;
volatile BUFTYPE *rx_buffer_; volatile BUFTYPE *rx_buffer_;

+ 1
- 1
teensy4/HardwareSerial1.cpp View File

CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON),
#if defined(ARDUINO_TEENSY41) #if defined(ARDUINO_TEENSY41)
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {52, 2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 0}}, {{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 #else
{{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, {{0,2, &IOMUXC_LPUART6_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
{{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, {{1,2, &IOMUXC_LPUART6_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},

Loading…
Cancel
Save