Add some support for serialEventX calls when yield is called. Currently keep table of which SerialX objects are Used (.begin called) and each has their own function which does the if (Serial1.available()) serialEvent1(); Calling SerialX.end(), removes the call from the list. Also the default weak pointer serialEventX functions call the disable function, as to only be called once as no one is actually processing them... At some point will integrate this with EventResponderteensy4-core
#define UART_CLOCK 24000000 | #define UART_CLOCK 24000000 | ||||
SerialEventCheckingFunctionPointer HardwareSerial::serial_event_handler_checks[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; | |||||
uint8_t HardwareSerial::serial_event_handlers_active = 0; | |||||
#define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE) | #define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE) | ||||
#define CTRL_TX_ACTIVE (CTRL_ENABLE | LPUART_CTRL_TIE) | #define CTRL_TX_ACTIVE (CTRL_ENABLE | LPUART_CTRL_TIE) | ||||
if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert | if (format & 0x10) c |= LPUART_STAT_RXINV; // rx invert | ||||
port->STAT = c; | port->STAT = c; | ||||
// bit 8 can turn on 2 stop bit mote | // bit 8 can turn on 2 stop bit mote | ||||
if ( format & 0x100) port->BAUD |= LPUART_BAUD_SBNS; | if ( format & 0x100) port->BAUD |= LPUART_BAUD_SBNS; | ||||
//Serial.printf(" stat:%x ctrl:%x fifo:%x water:%x\n", port->STAT, port->CTRL, port->FIFO, port->WATER ); | //Serial.printf(" stat:%x ctrl:%x fifo:%x water:%x\n", port->STAT, port->CTRL, port->FIFO, port->WATER ); | ||||
enableSerialEvents(); // Enable the processing of serialEvent for this object | |||||
}; | }; | ||||
inline void HardwareSerial::rts_assert() | inline void HardwareSerial::rts_assert() | ||||
rx_buffer_tail_ = 0; | rx_buffer_tail_ = 0; | ||||
if (rts_pin_baseReg_) rts_deassert(); | if (rts_pin_baseReg_) rts_deassert(); | ||||
// | // | ||||
disableSerialEvents(); // disable the processing of serialEvent for this object | |||||
} | } | ||||
void HardwareSerial::transmitterEnable(uint8_t pin) | void HardwareSerial::transmitterEnable(uint8_t pin) | ||||
} | } | ||||
//digitalWrite(4, LOW); | //digitalWrite(4, LOW); | ||||
} | } | ||||
void HardwareSerial::processSerialEvents() | |||||
{ | |||||
if (!serial_event_handlers_active) return; // bail quick if no one processing SerialEvents. | |||||
uint8_t handlers_still_to_process = serial_event_handlers_active; | |||||
for (uint8_t i = 0; i < 8; i++) { | |||||
if (serial_event_handler_checks[i]) { | |||||
(*serial_event_handler_checks[i])(); | |||||
if (--handlers_still_to_process == 0) return; | |||||
} | |||||
} | |||||
} | |||||
void HardwareSerial::enableSerialEvents() | |||||
{ | |||||
if (!serial_event_handler_checks[hardware->serial_index]) { | |||||
serial_event_handler_checks[hardware->serial_index] = hardware->serial_event_handler_check; // clear it out | |||||
serial_event_handlers_active++; | |||||
} | |||||
} | |||||
void HardwareSerial::disableSerialEvents() | |||||
{ | |||||
if (serial_event_handler_checks[hardware->serial_index]) { | |||||
serial_event_handler_checks[hardware->serial_index] = nullptr; // clear it out | |||||
serial_event_handlers_active--; | |||||
} | |||||
} |
extern void IRQHandler_Serial8(); | extern void IRQHandler_Serial8(); | ||||
} | } | ||||
typedef void(*SerialEventCheckingFunctionPointer)(); | |||||
class HardwareSerial : public Stream | class HardwareSerial : public Stream | ||||
{ | { | ||||
public: | public: | ||||
typedef struct { | typedef struct { | ||||
uint8_t serial_index; // which object are we? 0 based | |||||
IRQ_NUMBER_t irq; | IRQ_NUMBER_t irq; | ||||
void (*irq_handler)(void); | void (*irq_handler)(void); | ||||
void (*serial_event_handler_check)(void); | |||||
volatile uint32_t &ccm_register; | volatile uint32_t &ccm_register; | ||||
const uint32_t ccm_value; | const uint32_t ccm_value; | ||||
const uint8_t rx_pin; | const uint8_t rx_pin; | ||||
void addStorageForRead(void *buffer, size_t length); | void addStorageForRead(void *buffer, size_t length); | ||||
void addStorageForWrite(void *buffer, size_t length); | void addStorageForWrite(void *buffer, size_t length); | ||||
size_t write9bit(uint32_t c); | size_t write9bit(uint32_t c); | ||||
// Event Handler functions and data | |||||
void enableSerialEvents(); | |||||
void disableSerialEvents(); | |||||
static void processSerialEvents(); | |||||
using Print::write; | using Print::write; | ||||
// Only overwrite some of the virtualWrite functions if we are going to optimize them over Print version | // Only overwrite some of the virtualWrite functions if we are going to optimize them over Print version | ||||
friend void IRQHandler_Serial7(); | friend void IRQHandler_Serial7(); | ||||
friend void IRQHandler_Serial8(); | friend void IRQHandler_Serial8(); | ||||
static SerialEventCheckingFunctionPointer serial_event_handler_checks[8]; | |||||
static uint8_t serial_event_handlers_active; | |||||
}; | }; | ||||
extern HardwareSerial Serial1; | extern HardwareSerial Serial1; |
Serial1.IRQHandler(); | Serial1.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial1() | |||||
{ | |||||
if (Serial1.available()) serialEvent1(); | |||||
} | |||||
// Serial1 | // Serial1 | ||||
static BUFTYPE tx_buffer1[SERIAL1_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer1[SERIAL1_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer1[SERIAL1_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer1[SERIAL1_RX_BUFFER_SIZE]; | ||||
const HardwareSerial::hardware_t UART6_Hardware = { | const HardwareSerial::hardware_t UART6_Hardware = { | ||||
IRQ_LPUART6, &IRQHandler_Serial1, | |||||
0, IRQ_LPUART6, &IRQHandler_Serial1, &serial_event_check_serial1, | |||||
CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), | CCM_CCGR3, CCM_CCGR3_LPUART6(CCM_CCGR_ON), | ||||
0, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03, // pin 0 | 0, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_03, // pin 0 | ||||
1, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02, // pin 1 | 1, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_02, // pin 1 | ||||
rx_buffer1, SERIAL1_RX_BUFFER_SIZE); | rx_buffer1, SERIAL1_RX_BUFFER_SIZE); | ||||
void serialEvent1() __attribute__((weak)); | void serialEvent1() __attribute__((weak)); | ||||
void serialEvent1() {} | |||||
void serialEvent1() {Serial1.disableSerialEvents(); } // No use calling this so disable if called... |
Serial2.IRQHandler(); | Serial2.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial2() | |||||
{ | |||||
if (Serial2.available()) serialEvent2(); | |||||
} | |||||
// Serial2 | // Serial2 | ||||
static BUFTYPE tx_buffer2[SERIAL2_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer2[SERIAL2_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer2[SERIAL2_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer2[SERIAL2_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART4_Hardware = { | static HardwareSerial::hardware_t UART4_Hardware = { | ||||
IRQ_LPUART4, &IRQHandler_Serial2, | |||||
1, IRQ_LPUART4, &IRQHandler_Serial2, &serial_event_check_serial2, | |||||
CCM_CCGR1, CCM_CCGR1_LPUART4(CCM_CCGR_ON), | CCM_CCGR1, CCM_CCGR1_LPUART4(CCM_CCGR_ON), | ||||
6, //IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01, // pin 6 | 6, //IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_01, // pin 6 | ||||
7, // IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00, // pin 7 | 7, // IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00, // pin 7 | ||||
void serialEvent2() __attribute__((weak)); | void serialEvent2() __attribute__((weak)); | ||||
void serialEvent2() {} | |||||
void serialEvent2() {Serial2.disableSerialEvents(); } // No use calling this so disable if called... |
Serial3.IRQHandler(); | Serial3.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial3() | |||||
{ | |||||
if (Serial3.available()) serialEvent3(); | |||||
} | |||||
// Serial3 | // Serial3 | ||||
static BUFTYPE tx_buffer3[SERIAL3_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer3[SERIAL3_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer3[SERIAL3_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer3[SERIAL3_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART2_Hardware = { | static HardwareSerial::hardware_t UART2_Hardware = { | ||||
IRQ_LPUART2, &IRQHandler_Serial3, | |||||
2, IRQ_LPUART2, &IRQHandler_Serial3, &serial_event_check_serial3, | |||||
CCM_CCGR0, CCM_CCGR0_LPUART2(CCM_CCGR_ON), | CCM_CCGR0, CCM_CCGR0_LPUART2(CCM_CCGR_ON), | ||||
15, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03, // pin 15 | 15, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_03, // pin 15 | ||||
14, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02, // pin 14 | 14, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_02, // pin 14 | ||||
rx_buffer3, SERIAL3_RX_BUFFER_SIZE); | rx_buffer3, SERIAL3_RX_BUFFER_SIZE); | ||||
void serialEvent3() __attribute__((weak)); | void serialEvent3() __attribute__((weak)); | ||||
void serialEvent3() {} | |||||
void serialEvent3() {Serial3.disableSerialEvents(); } // No use calling this so disable if called... | |||||
Serial4.IRQHandler(); | Serial4.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial4() | |||||
{ | |||||
if (Serial4.available()) serialEvent4(); | |||||
} | |||||
// Serial4 | // Serial4 | ||||
static BUFTYPE tx_buffer4[SERIAL4_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer4[SERIAL4_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer4[SERIAL4_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer4[SERIAL4_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART3_Hardware = { | static HardwareSerial::hardware_t UART3_Hardware = { | ||||
IRQ_LPUART3, &IRQHandler_Serial4, | |||||
3, IRQ_LPUART3, &IRQHandler_Serial4, &serial_event_check_serial4, | |||||
CCM_CCGR0, CCM_CCGR0_LPUART3(CCM_CCGR_ON), | CCM_CCGR0, CCM_CCGR0_LPUART3(CCM_CCGR_ON), | ||||
16, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07, // pin 16 | 16, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_07, // pin 16 | ||||
17, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06, // pin 17 | 17, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_06, // pin 17 | ||||
void serialEvent4() __attribute__((weak)); | void serialEvent4() __attribute__((weak)); | ||||
void serialEvent4() {} | |||||
void serialEvent4() {Serial4.disableSerialEvents(); } // No use calling this so disable if called... |
Serial5.IRQHandler(); | Serial5.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial5() | |||||
{ | |||||
if (Serial5.available()) serialEvent5(); | |||||
} | |||||
// Serial5 | // Serial5 | ||||
static BUFTYPE tx_buffer5[SERIAL5_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer5[SERIAL5_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer5[SERIAL5_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer5[SERIAL5_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART8_Hardware = { | static HardwareSerial::hardware_t UART8_Hardware = { | ||||
IRQ_LPUART8, &IRQHandler_Serial5, | |||||
4, IRQ_LPUART8, &IRQHandler_Serial5, &serial_event_check_serial5, | |||||
CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON), | CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON), | ||||
21, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11, // pin 21 | 21, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_11, // pin 21 | ||||
20, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10, // pin 20 | 20, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_10, // pin 20 | ||||
void serialEvent5() __attribute__((weak)); | void serialEvent5() __attribute__((weak)); | ||||
void serialEvent5() {} | |||||
void serialEvent5() {Serial5.disableSerialEvents(); } // No use calling this so disable if called... |
Serial6.IRQHandler(); | Serial6.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial6() | |||||
{ | |||||
if (Serial6.available()) serialEvent6(); | |||||
} | |||||
// Serial6 | // Serial6 | ||||
static BUFTYPE tx_buffer6[SERIAL6_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer6[SERIAL6_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer6[SERIAL6_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer6[SERIAL6_RX_BUFFER_SIZE]; | ||||
uint32_t IOMUXC_LPUART1_RX_SELECT_INPUT; // bugbug - does not exist so hack | uint32_t IOMUXC_LPUART1_RX_SELECT_INPUT; // bugbug - does not exist so hack | ||||
static HardwareSerial::hardware_t UART1_Hardware = { | static HardwareSerial::hardware_t UART1_Hardware = { | ||||
IRQ_LPUART1, &IRQHandler_Serial6, | |||||
5, IRQ_LPUART1, &IRQHandler_Serial6, &serial_event_check_serial6, | |||||
CCM_CCGR5, CCM_CCGR5_LPUART1(CCM_CCGR_ON), | CCM_CCGR5, CCM_CCGR5_LPUART1(CCM_CCGR_ON), | ||||
25, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13, // pin 25 | 25, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_13, // pin 25 | ||||
24, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12, // pin 24 | 24, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B0_12, // pin 24 | ||||
rx_buffer6, SERIAL6_RX_BUFFER_SIZE); | rx_buffer6, SERIAL6_RX_BUFFER_SIZE); | ||||
void serialEvent6() __attribute__((weak)); | void serialEvent6() __attribute__((weak)); | ||||
void serialEvent6() {} | |||||
void serialEvent6() {Serial6.disableSerialEvents(); } // No use calling this so disable if called... |
Serial7.IRQHandler(); | Serial7.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial7() | |||||
{ | |||||
if (Serial7.available()) serialEvent7(); | |||||
} | |||||
// Serial7 | // Serial7 | ||||
static BUFTYPE tx_buffer7[SERIAL7_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer7[SERIAL7_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer7[SERIAL7_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer7[SERIAL7_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART7_Hardware = { | static HardwareSerial::hardware_t UART7_Hardware = { | ||||
IRQ_LPUART7, &IRQHandler_Serial7, | |||||
6, IRQ_LPUART7, &IRQHandler_Serial7, &serial_event_check_serial7, | |||||
CCM_CCGR5, CCM_CCGR5_LPUART7(CCM_CCGR_ON), | CCM_CCGR5, CCM_CCGR5_LPUART7(CCM_CCGR_ON), | ||||
28, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32, // pin 28 | 28, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_32, // pin 28 | ||||
29, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31, // pin 29 | 29, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_31, // pin 29 | ||||
void serialEvent7() __attribute__((weak)); | void serialEvent7() __attribute__((weak)); | ||||
void serialEvent7() {} | |||||
void serialEvent7() {Serial7.disableSerialEvents(); } // No use calling this so disable if called... |
Serial8.IRQHandler(); | Serial8.IRQHandler(); | ||||
} | } | ||||
void serial_event_check_serial8() | |||||
{ | |||||
if (Serial8.available()) serialEvent8(); | |||||
} | |||||
// Serial8 | // Serial8 | ||||
static BUFTYPE tx_buffer8[SERIAL8_TX_BUFFER_SIZE]; | static BUFTYPE tx_buffer8[SERIAL8_TX_BUFFER_SIZE]; | ||||
static BUFTYPE rx_buffer8[SERIAL8_RX_BUFFER_SIZE]; | static BUFTYPE rx_buffer8[SERIAL8_RX_BUFFER_SIZE]; | ||||
static HardwareSerial::hardware_t UART5_Hardware = { | static HardwareSerial::hardware_t UART5_Hardware = { | ||||
IRQ_LPUART5, &IRQHandler_Serial8, | |||||
7, IRQ_LPUART5, &IRQHandler_Serial8, &serial_event_check_serial8, | |||||
CCM_CCGR3, CCM_CCGR3_LPUART5(CCM_CCGR_ON), | CCM_CCGR3, CCM_CCGR3_LPUART5(CCM_CCGR_ON), | ||||
30, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24, // pin 30 | 30, //IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_24, // pin 30 | ||||
31, // IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_23, // pin 31 | 31, // IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_23, // pin 31 | ||||
HardwareSerial Serial8(&IMXRT_LPUART5, &UART5_Hardware, tx_buffer8, SERIAL8_TX_BUFFER_SIZE, | HardwareSerial Serial8(&IMXRT_LPUART5, &UART5_Hardware, tx_buffer8, SERIAL8_TX_BUFFER_SIZE, | ||||
rx_buffer8, SERIAL8_RX_BUFFER_SIZE); | rx_buffer8, SERIAL8_RX_BUFFER_SIZE); | ||||
void serialEvent7() __attribute__((weak)); | |||||
void serialEvent7() {} | |||||
void serialEvent8() __attribute__((weak)); | |||||
void serialEvent8() {Serial8.disableSerialEvents(); } // No use calling this so disable if called... |
if (running) return; // TODO: does this need to be atomic? | if (running) return; // TODO: does this need to be atomic? | ||||
running = 1; | running = 1; | ||||
#if 0 | |||||
// TODO: all serialEvent to use EventResponder | |||||
if (Serial.available()) serialEvent(); | |||||
if (Serial1.available()) serialEvent1(); | |||||
if (Serial2.available()) serialEvent2(); | |||||
if (Serial3.available()) serialEvent3(); | |||||
if (Serial4.available()) serialEvent4(); | |||||
if (Serial5.available()) serialEvent5(); | |||||
if (Serial6.available()) serialEvent6(); | |||||
#endif | |||||
// Current workaround until integrate with EventResponder. | |||||
HardwareSerial::processSerialEvents(); | |||||
running = 0; | running = 0; | ||||
EventResponder::runFromYield(); | EventResponder::runFromYield(); | ||||
}; | }; |