T3.x,T4.x LC Serial half duplex supportteensy4-core
@@ -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) |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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) |
@@ -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) |
@@ -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) |
@@ -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... | |||
} | |||
} |
@@ -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; | |||
} |
@@ -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_; |
@@ -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}}, |