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