T4.x Reduce EventResponder overhead on systic and yieldteensy4-core
@@ -41,6 +41,10 @@ EventResponder * EventResponder::lastInterrupt = nullptr; | |||
bool EventResponder::runningFromYield = false; | |||
// TODO: interrupt disable/enable needed in many places!!! | |||
// BUGBUG: See if file name order makes difference? | |||
uint8_t _serialEvent_default __attribute__((weak)) PROGMEM = 0 ; | |||
uint8_t _serialEventUSB1_default __attribute__((weak)) PROGMEM = 0 ; | |||
uint8_t _serialEventUSB2_default __attribute__((weak)) PROGMEM = 0 ; | |||
void EventResponder::triggerEventNotImmediate() | |||
{ | |||
@@ -335,10 +339,17 @@ void MillisTimer::runFromTimer() | |||
// with libraries using mid-to-high priority interrupts. | |||
extern "C" volatile uint32_t systick_millis_count; | |||
void systick_isr(void) | |||
{ | |||
systick_millis_count++; | |||
} | |||
extern "C" void systick_isr_with_timer_events(void) | |||
{ | |||
systick_millis_count++; | |||
MillisTimer::runFromTimer(); | |||
} | |||
@@ -59,6 +59,7 @@ | |||
* your function is called only one time, based on the last trigger | |||
* event. | |||
*/ | |||
extern "C" void systick_isr_with_timer_events(void); | |||
class EventResponder; | |||
typedef EventResponder& EventResponderRef; | |||
@@ -87,6 +88,7 @@ public: | |||
detachNoInterrupts(); | |||
_function = function; | |||
_type = EventTypeYield; | |||
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type... | |||
enableInterrupts(irq); | |||
} | |||
@@ -112,6 +114,8 @@ public: | |||
_function = function; | |||
_type = EventTypeInterrupt; | |||
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority | |||
// Make sure we are using the systic ISR that process this | |||
_VectorsRam[15] = systick_isr_with_timer_events; | |||
enableInterrupts(irq); | |||
} | |||
@@ -170,6 +174,7 @@ public: | |||
EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout); | |||
static void runFromYield() { | |||
if (!firstYield) return; | |||
// First, check if yield was called from an interrupt | |||
// never call normal handler functions from any interrupt context | |||
uint32_t ipsr; |
@@ -0,0 +1,45 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2019 PJRC.COM, LLC. | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining | |||
* a copy of this software and associated documentation files (the | |||
* "Software"), to deal in the Software without restriction, including | |||
* without limitation the rights to use, copy, modify, merge, publish, | |||
* distribute, sublicense, and/or sell copies of the Software, and to | |||
* permit persons to whom the Software is furnished to do so, subject to | |||
* the following conditions: | |||
* | |||
* 1. The above copyright notice and this permission notice shall be | |||
* included in all copies or substantial portions of the Software. | |||
* | |||
* 2. If the Software is incorporated into a build system that allows | |||
* selection among a list of target devices, then similar target | |||
* devices manufactured by PJRC.COM must be included in the list of | |||
* target devices and selectable in the same manner. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#include "HardwareSerial.h" | |||
#include "core_pins.h" | |||
#include "Arduino.h" | |||
// define our static objects | |||
HardwareSerial *HardwareSerial::s_serials_with_serial_events[CNT_HARDWARE_SERIAL]; | |||
uint8_t HardwareSerial::s_count_serials_with_serial_events = 0; | |||
// simple helper function that add us to the list of Serial ports that have | |||
// their own serialEvent code defined that needs to be called at yield. | |||
void HardwareSerial::addToSerialEventsList() { | |||
s_serials_with_serial_events[s_count_serials_with_serial_events++] = this; | |||
yield_active_check_flags |= YIELD_CHECK_HARDWARE_SERIAL; | |||
} | |||
@@ -253,8 +253,13 @@ void serial6_clear(void); | |||
class HardwareSerial : public Stream | |||
{ | |||
public: | |||
constexpr HardwareSerial() {} | |||
virtual void begin(uint32_t baud) { serial_begin(BAUD2DIV(baud)); } | |||
constexpr HardwareSerial(void (* const se)()) : _serialEvent(se) {} | |||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||
enum {CNT_HARDWARE_SERIAL = 6}; | |||
#else //(__MK64FX512__) || defined(__MK66FX1M0__) | |||
enum {CNT_HARDWARE_SERIAL = 3}; | |||
#endif | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial_begin(BAUD2DIV(baud)); | |||
serial_format(format); } | |||
@@ -283,6 +288,21 @@ public: | |||
return len; } | |||
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; } | |||
operator bool() { return true; } | |||
static inline void processSerialEventsList() { | |||
for (uint8_t i = 0; i < s_count_serials_with_serial_events; i++) { | |||
s_serials_with_serial_events[i]->doYieldCode(); | |||
} | |||
} | |||
protected: | |||
static HardwareSerial *s_serials_with_serial_events[CNT_HARDWARE_SERIAL]; | |||
static uint8_t s_count_serials_with_serial_events; | |||
void (* const _serialEvent)(); | |||
void addToSerialEventsList(); | |||
inline void doYieldCode() { | |||
if (available()) (*_serialEvent)(); | |||
} | |||
}; | |||
extern HardwareSerial Serial1; | |||
extern void serialEvent1(void); | |||
@@ -290,8 +310,8 @@ extern void serialEvent1(void); | |||
class HardwareSerial2 : public HardwareSerial | |||
{ | |||
public: | |||
constexpr HardwareSerial2() {} | |||
virtual void begin(uint32_t baud) { serial2_begin(BAUD2DIV2(baud)); } | |||
constexpr HardwareSerial2(void (* const se)()) : HardwareSerial(se) {} | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial2_begin(BAUD2DIV2(baud)); | |||
serial2_format(format); } | |||
@@ -327,8 +347,8 @@ extern void serialEvent2(void); | |||
class HardwareSerial3 : public HardwareSerial | |||
{ | |||
public: | |||
constexpr HardwareSerial3() {} | |||
virtual void begin(uint32_t baud) { serial3_begin(BAUD2DIV3(baud)); } | |||
constexpr HardwareSerial3(void (* const se)()) : HardwareSerial(se) {} | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial3_begin(BAUD2DIV3(baud)); | |||
serial3_format(format); } | |||
@@ -364,8 +384,8 @@ extern void serialEvent3(void); | |||
class HardwareSerial4 : public HardwareSerial | |||
{ | |||
public: | |||
constexpr HardwareSerial4() {} | |||
virtual void begin(uint32_t baud) { serial4_begin(BAUD2DIV3(baud)); } | |||
constexpr HardwareSerial4(void (* const se)()) : HardwareSerial(se) {} | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial4_begin(BAUD2DIV3(baud)); | |||
serial4_format(format); } | |||
@@ -401,8 +421,8 @@ extern void serialEvent4(void); | |||
class HardwareSerial5 : public HardwareSerial | |||
{ | |||
public: | |||
constexpr HardwareSerial5() {} | |||
virtual void begin(uint32_t baud) { serial5_begin(BAUD2DIV3(baud)); } | |||
constexpr HardwareSerial5(void (* const se)()) : HardwareSerial(se) {} | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial5_begin(BAUD2DIV3(baud)); | |||
serial5_format(format); } | |||
@@ -438,14 +458,14 @@ extern void serialEvent5(void); | |||
class HardwareSerial6 : public HardwareSerial | |||
{ | |||
public: | |||
constexpr HardwareSerial6() {} | |||
constexpr HardwareSerial6(void (* const se)()) : HardwareSerial(se) {} | |||
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. | |||
virtual void begin(uint32_t baud) { serial6_begin(baud); } | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial6_begin(baud); | |||
serial6_format(format); } | |||
#else | |||
virtual void begin(uint32_t baud) { serial6_begin(BAUD2DIV3(baud)); } | |||
virtual void begin(uint32_t baud); | |||
virtual void begin(uint32_t baud, uint32_t format) { | |||
serial6_begin(BAUD2DIV3(baud)); | |||
serial6_format(format); } |
@@ -31,7 +31,13 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
HardwareSerial Serial1; | |||
void serialEvent1() __attribute__((weak)); | |||
void serialEvent1() {} | |||
uint8_t _serialEvent1_default __attribute__((weak)) PROGMEM = 0 ; | |||
HardwareSerial Serial1(&serialEvent1); | |||
void HardwareSerial::begin(uint32_t baud) { | |||
serial_begin(BAUD2DIV(baud)); | |||
if (!_serialEvent1_default) addToSerialEventsList(); | |||
} | |||
@@ -27,11 +27,14 @@ | |||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
* SOFTWARE. | |||
*/ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
HardwareSerial2 Serial2; | |||
HardwareSerial2 Serial2(&serialEvent2); | |||
uint8_t _serialEvent2_default __attribute__((weak)) PROGMEM = 0 ; | |||
void serialEvent2() __attribute__((weak)); | |||
void serialEvent2() {} | |||
void HardwareSerial2::begin(uint32_t baud) { | |||
serial2_begin(BAUD2DIV2(baud)); | |||
if (!_serialEvent2_default) addToSerialEventsList(); | |||
} |
@@ -31,7 +31,11 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
HardwareSerial3 Serial3; | |||
HardwareSerial3 Serial3(&serialEvent3); | |||
void serialEvent3() __attribute__((weak)); | |||
void serialEvent3() {} | |||
uint8_t _serialEvent3_default __attribute__((weak)) PROGMEM = 0 ; | |||
void HardwareSerial3::begin(uint32_t baud) { | |||
serial3_begin(BAUD2DIV3(baud)); | |||
if (!_serialEvent3_default) addToSerialEventsList(); | |||
} |
@@ -33,9 +33,13 @@ | |||
#ifdef HAS_KINETISK_UART3 | |||
HardwareSerial4 Serial4; | |||
HardwareSerial4 Serial4(&serialEvent4); | |||
void serialEvent4() __attribute__((weak)); | |||
void serialEvent4() {} | |||
uint8_t _serialEvent4_default __attribute__((weak)) PROGMEM = 0 ; | |||
void HardwareSerial4::begin(uint32_t baud) { | |||
serial4_begin(BAUD2DIV3(baud)); | |||
if (!_serialEvent4_default) addToSerialEventsList(); | |||
} | |||
#endif |
@@ -33,9 +33,13 @@ | |||
#ifdef HAS_KINETISK_UART4 | |||
HardwareSerial5 Serial5; | |||
HardwareSerial5 Serial5(&serialEvent5); | |||
void serialEvent5() __attribute__((weak)); | |||
void serialEvent5() {} | |||
uint8_t _serialEvent5_default __attribute__((weak)) PROGMEM = 0 ; | |||
void HardwareSerial5::begin(uint32_t baud) { | |||
serial5_begin(BAUD2DIV3(baud)); | |||
if (!_serialEvent5_default) addToSerialEventsList(); | |||
} | |||
#endif |
@@ -33,9 +33,17 @@ | |||
#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0) | |||
HardwareSerial6 Serial6; | |||
HardwareSerial6 Serial6(&serialEvent6); | |||
void serialEvent6() __attribute__((weak)); | |||
void serialEvent6() {} | |||
uint8_t _serialEvent6_default __attribute__((weak)) PROGMEM = 0 ; | |||
void HardwareSerial6::begin(uint32_t baud) { | |||
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. | |||
serial6_begin(baud); | |||
#else | |||
serial6_begin(BAUD2DIV3(baud)); | |||
#endif | |||
if (!_serialEvent6_default) addToSerialEventsList(); | |||
} | |||
#endif |
@@ -1996,6 +1996,14 @@ static inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrde | |||
void _reboot_Teensyduino_(void) __attribute__((noreturn)); | |||
void _restart_Teensyduino_(void) __attribute__((noreturn)); | |||
// Define a set of flags to know which things yield should check when called. | |||
// Probably should be in a better spot. | |||
extern uint8_t yield_active_check_flags; | |||
#define YIELD_CHECK_USB_SERIAL 0x1 // check the USB for Serial.available() | |||
#define YIELD_CHECK_HARDWARE_SERIAL 0x2 // check Hardware Serial ports available | |||
#define YIELD_CHECK_EVENT_RESPONDER 0x4 // User has created eventResponders that use yield | |||
void yield(void); | |||
void delay(uint32_t msec); |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
void serialEvent() __attribute__((weak)); | |||
void serialEvent() { | |||
} | |||
uint8_t _serialEvent_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent1() __attribute__((weak)); | |||
void serialEvent1() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent1_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent2() __attribute__((weak)); | |||
void serialEvent2() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent2_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent3() __attribute__((weak)); | |||
void serialEvent3() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent3_default PROGMEM = 1; |
@@ -0,0 +1,8 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
#ifdef HAS_KINETISK_UART3 | |||
void serialEvent4() __attribute__((weak)); | |||
void serialEvent4() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent4_default PROGMEM = 1; | |||
#endif |
@@ -0,0 +1,8 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
#ifdef HAS_KINETISK_UART4 | |||
void serialEvent5() __attribute__((weak)); | |||
void serialEvent5() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent5_default PROGMEM = 1; | |||
#endif |
@@ -0,0 +1,8 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0) | |||
void serialEvent6() __attribute__((weak)); | |||
void serialEvent6() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent6_default PROGMEM = 1; | |||
#endif |
@@ -98,8 +98,8 @@ usb_seremu_class Serial; | |||
#endif // F_CPU | |||
void serialEvent() __attribute__((weak)); | |||
void serialEvent() {} | |||
//void serialEvent() __attribute__((weak)); | |||
//void serialEvent() {} | |||
void serialEventUSB1() __attribute__((weak)); | |||
void serialEventUSB1() {} | |||
void serialEventUSB2() __attribute__((weak)); |
@@ -31,32 +31,47 @@ | |||
#include <Arduino.h> | |||
#include "EventResponder.h" | |||
#ifdef USB_TRIPLE_SERIAL | |||
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL | YIELD_CHECK_USB_SERIALUSB1 | YIELD_CHECK_USB_SERIALUSB2; // default to check USB. | |||
#elif defined(USB_DUAL_SERIAL) | |||
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL | YIELD_CHECK_USB_SERIALUSB1; // default to check USB. | |||
#else | |||
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL; // default to check USB. | |||
#endif | |||
extern const uint8_t _serialEvent_default; | |||
void yield(void) __attribute__ ((weak)); | |||
void yield(void) | |||
{ | |||
static uint8_t running=0; | |||
if (!yield_active_check_flags) return; // nothing to do | |||
if (running) return; // TODO: does this need to be atomic? | |||
running = 1; | |||
if (Serial.available()) serialEvent(); | |||
// USB Serail - Add hack to minimize impact... | |||
if (yield_active_check_flags & YIELD_CHECK_USB_SERIAL) { | |||
if (Serial.available()) serialEvent(); | |||
if (_serialEvent_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIAL; | |||
} | |||
// Current workaround until integrate with EventResponder. | |||
#if defined(USB_DUAL_SERIAL) || defined(USB_TRIPLE_SERIAL) | |||
if (SerialUSB1.available()) serialEventUSB1(); | |||
if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB1) { | |||
if (SerialUSB1.available()) serialEventUSB1(); | |||
if (_serialEventUSB1_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB1; | |||
} | |||
#endif | |||
#ifdef USB_TRIPLE_SERIAL | |||
if (SerialUSB2.available()) serialEventUSB2(); | |||
#endif | |||
if (Serial1.available()) serialEvent1(); | |||
if (Serial2.available()) serialEvent2(); | |||
if (Serial3.available()) serialEvent3(); | |||
#ifdef HAS_KINETISK_UART3 | |||
if (Serial4.available()) serialEvent4(); | |||
#endif | |||
#ifdef HAS_KINETISK_UART4 | |||
if (Serial5.available()) serialEvent5(); | |||
#endif | |||
#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0) | |||
if (Serial6.available()) serialEvent6(); | |||
if (yield_active_check_flags & YIELD_CHECK_USB_SERIALUSB2) { | |||
if (SerialUSB1.available()) serialEventUSB1(); | |||
if (_serialEventUSB2_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIALUSB2; | |||
} | |||
#endif | |||
if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) { | |||
HardwareSerial::processSerialEventsList(); | |||
} | |||
running = 0; | |||
EventResponder::runFromYield(); | |||
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield(); | |||
}; |
@@ -41,6 +41,8 @@ EventResponder * EventResponder::lastInterrupt = nullptr; | |||
bool EventResponder::runningFromYield = false; | |||
// TODO: interrupt disable/enable needed in many places!!! | |||
// BUGBUG: See if file name order makes difference? | |||
uint8_t _serialEvent_default __attribute__((weak)) PROGMEM = 0 ; | |||
void EventResponder::triggerEventNotImmediate() | |||
{ | |||
@@ -342,7 +344,12 @@ extern "C" void systick_isr(void) | |||
{ | |||
systick_cycle_count = ARM_DWT_CYCCNT; | |||
systick_millis_count++; | |||
MillisTimer::runFromTimer(); | |||
} | |||
extern "C" void systick_isr_with_timer_events(void) | |||
{ | |||
systick_cycle_count = ARM_DWT_CYCCNT; | |||
systick_millis_count++; | |||
MillisTimer::runFromTimer(); | |||
} | |||
@@ -59,6 +59,7 @@ | |||
* your function is called only one time, based on the last trigger | |||
* event. | |||
*/ | |||
extern "C" void systick_isr_with_timer_events(void); | |||
class EventResponder; | |||
typedef EventResponder& EventResponderRef; | |||
@@ -87,6 +88,7 @@ public: | |||
detachNoInterrupts(); | |||
_function = function; | |||
_type = EventTypeYield; | |||
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type... | |||
enableInterrupts(irq); | |||
} | |||
@@ -112,6 +114,8 @@ public: | |||
_function = function; | |||
_type = EventTypeInterrupt; | |||
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority | |||
// Make sure we are using the systic ISR that process this | |||
_VectorsRam[15] = systick_isr_with_timer_events; | |||
enableInterrupts(irq); | |||
} | |||
@@ -168,9 +172,8 @@ public: | |||
// used with a scheduler or RTOS. | |||
bool waitForEvent(EventResponderRef event, int timeout); | |||
EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout); | |||
static void runFromYield() { | |||
if (!firstYield) return; | |||
if (!firstYield) return; | |||
// First, check if yield was called from an interrupt | |||
// never call normal handler functions from any interrupt context | |||
uint32_t ipsr; |
@@ -62,12 +62,19 @@ | |||
#define UART_CLOCK 24000000 | |||
extern "C" { | |||
extern void xbar_connect(unsigned int input, unsigned int output); | |||
} | |||
#if defined(ARDUINO_TEENSY41) | |||
SerialEventCheckingFunctionPointer HardwareSerial::serial_event_handler_checks[8] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; | |||
HardwareSerial *HardwareSerial::s_serials_with_serial_events[8]; | |||
#else | |||
SerialEventCheckingFunctionPointer HardwareSerial::serial_event_handler_checks[7] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}; | |||
HardwareSerial *HardwareSerial::s_serials_with_serial_events[7]; | |||
#endif | |||
uint8_t HardwareSerial::serial_event_handlers_active = 0; | |||
// define our static objects | |||
uint8_t HardwareSerial::s_count_serials_with_serial_events = 0; | |||
#define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE) | |||
@@ -193,7 +200,8 @@ void HardwareSerial::begin(uint32_t baud, uint16_t format) | |||
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 ); | |||
enableSerialEvents(); // Enable the processing of serialEvent for this object | |||
// Only if the user implemented their own... | |||
if (!(*hardware->serial_event_handler_default)) addToSerialEventsList(); // Enable the processing of serialEvent for this object | |||
}; | |||
inline void HardwareSerial::rts_assert() | |||
@@ -223,7 +231,6 @@ void HardwareSerial::end(void) | |||
rx_buffer_tail_ = 0; | |||
if (rts_pin_baseReg_) rts_deassert(); | |||
// | |||
disableSerialEvents(); // disable the processing of serialEvent for this object | |||
} | |||
void HardwareSerial::transmitterEnable(uint8_t pin) | |||
@@ -243,9 +250,9 @@ void HardwareSerial::setRX(uint8_t pin) | |||
// new pin - so lets maybe reset the old pin to INPUT? and then set new pin parameters | |||
// only change IO pins if done after begin has been called. | |||
if ((hardware->ccm_register & hardware->ccm_value)) { | |||
*(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = 5; | |||
*(portConfigRegister(hardware->rx_pins[rx_pin_index_].pin)) = 5; | |||
// now set new pin info. | |||
// now set new pin info. | |||
*(portControlRegister(hardware->rx_pins[rx_pin_new_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_new_index].pin)) = hardware->rx_pins[rx_pin_new_index].mux_val; | |||
if (hardware->rx_pins[rx_pin_new_index].select_input_register) { | |||
@@ -253,7 +260,29 @@ void HardwareSerial::setRX(uint8_t pin) | |||
} | |||
} | |||
rx_pin_index_ = rx_pin_new_index; | |||
break; | |||
return; // done. | |||
} | |||
} | |||
// If we got to here and did not find a valid pin there. Maybe see if it is an XBar pin... | |||
for (uint8_t i = 0; i < count_pin_to_xbar_info; i++) { | |||
if (pin_to_xbar_info[i].pin == pin) { | |||
// So it is an XBAR pin set the XBAR.. | |||
//Serial.printf("ACTS XB(%d), X(%u %u), MUX:%x\n", i, pin_to_xbar_info[i].xbar_in_index, | |||
// hardware->xbar_out_lpuartX_trig_input, pin_to_xbar_info[i].mux_val); | |||
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); | |||
xbar_connect(pin_to_xbar_info[i].xbar_in_index, hardware->xbar_out_lpuartX_trig_input); | |||
// We need to update port register to use this as the trigger | |||
port->PINCFG = LPUART_PINCFG_TRGSEL(1); // Trigger select as alternate RX | |||
// configure the pin. | |||
*(portControlRegister(pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;; | |||
*(portConfigRegister(pin)) = pin_to_xbar_info[i].mux_val; | |||
port->MODIR |= LPUART_MODIR_TXCTSE; | |||
if (pin_to_xbar_info[i].select_input_register) *(pin_to_xbar_info[i].select_input_register) = pin_to_xbar_info[i].select_val; | |||
//Serial.printf("SerialX::begin stat:%x ctrl:%x fifo:%x water:%x\n", port->STAT, port->CTRL, port->FIFO, port->WATER ); | |||
//Serial.printf(" PINCFG: %x MODIR: %x\n", port->PINCFG, port->MODIR); | |||
return; | |||
} | |||
} | |||
} | |||
@@ -315,6 +344,30 @@ bool HardwareSerial::attachCts(uint8_t pin) | |||
port->MODIR |= LPUART_MODIR_TXCTSE; | |||
return true; | |||
} else { | |||
// See maybe this a pin we can use XBAR for. | |||
for (uint8_t i = 0; i < count_pin_to_xbar_info; i++) { | |||
if (pin_to_xbar_info[i].pin == pin) { | |||
// So it is an XBAR pin set the XBAR.. | |||
//Serial.printf("ACTS XB(%d), X(%u %u), MUX:%x\n", i, pin_to_xbar_info[i].xbar_in_index, | |||
// hardware->xbar_out_lpuartX_trig_input, pin_to_xbar_info[i].mux_val); | |||
CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON); | |||
xbar_connect(pin_to_xbar_info[i].xbar_in_index, hardware->xbar_out_lpuartX_trig_input); | |||
// We need to update port register to use this as the trigger | |||
port->PINCFG = LPUART_PINCFG_TRGSEL(2); // Trigger select as alternate CTS pin | |||
// configure the pin. | |||
*(portControlRegister(pin)) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS; | |||
*(portConfigRegister(pin)) = pin_to_xbar_info[i].mux_val; | |||
if (pin_to_xbar_info[i].select_input_register) *(pin_to_xbar_info[i].select_input_register) = pin_to_xbar_info[i].select_val; | |||
port->MODIR |= LPUART_MODIR_TXCTSE; | |||
//Serial.printf("SerialX::begin stat:%x ctrl:%x fifo:%x water:%x\n", port->STAT, port->CTRL, port->FIFO, port->WATER ); | |||
//Serial.printf(" PINCFG: %x MODIR: %x\n", port->PINCFG, port->MODIR); | |||
return true; | |||
} | |||
} | |||
// Fell through so not valid pin for this. | |||
port->MODIR &= ~LPUART_MODIR_TXCTSE; | |||
return false; | |||
} | |||
@@ -551,30 +604,44 @@ void HardwareSerial::IRQHandler() | |||
} | |||
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::addToSerialEventsList() { | |||
s_serials_with_serial_events[s_count_serials_with_serial_events++] = this; | |||
yield_active_check_flags |= YIELD_CHECK_HARDWARE_SERIAL; | |||
} | |||
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--; | |||
} | |||
} | |||
const pin_to_xbar_info_t PROGMEM pin_to_xbar_info[] = { | |||
{0, 17, 1, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x1}, | |||
{1, 16, 1, nullptr, 0}, | |||
{2, 6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x0}, | |||
{3, 7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x0}, | |||
{4, 8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x0}, | |||
{5, 17, 3, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x0}, | |||
{7, 15, 1, nullptr, 0 }, | |||
{8, 14, 1, nullptr, 0}, | |||
{30, 23, 1, &IOMUXC_XBAR1_IN23_SELECT_INPUT, 0x0}, | |||
{31, 22, 1, &IOMUXC_XBAR1_IN22_SELECT_INPUT, 0x0}, | |||
{32, 10, 1, nullptr, 0}, | |||
{33, 9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x0}, | |||
#ifdef ARDUINO_TEENSY41 | |||
{36, 16, 1, nullptr, 0}, | |||
{37, 17, 1, &IOMUXC_XBAR1_IN17_SELECT_INPUT, 0x3}, | |||
{42, 7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x1}, | |||
{43, 6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x1}, | |||
{44, 5, 3, &IOMUXC_XBAR1_IN05_SELECT_INPUT, 0x1}, | |||
{45, 4, 3, &IOMUXC_XBAR1_IN04_SELECT_INPUT, 0x1}, | |||
{46, 9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x1}, | |||
{47, 8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x1} | |||
#else | |||
{34, 7, 3, &IOMUXC_XBAR1_IN07_SELECT_INPUT, 0x1}, | |||
{35, 6, 3, &IOMUXC_XBAR1_IN06_SELECT_INPUT, 0x1}, | |||
{36, 5, 3, &IOMUXC_XBAR1_IN05_SELECT_INPUT, 0x1}, | |||
{37, 4, 3, &IOMUXC_XBAR1_IN04_SELECT_INPUT, 0x1}, | |||
{38, 9, 3, &IOMUXC_XBAR1_IN09_SELECT_INPUT, 0x1}, | |||
{39, 8, 3, &IOMUXC_XBAR1_IN08_SELECT_INPUT, 0x1} | |||
#endif | |||
}; | |||
const uint8_t PROGMEM count_pin_to_xbar_info = sizeof(pin_to_xbar_info)/sizeof(pin_to_xbar_info[0]); | |||
@@ -125,7 +125,22 @@ extern "C" { | |||
#endif | |||
} | |||
typedef void(*SerialEventCheckingFunctionPointer)(); | |||
//=================================================================== | |||
// Should find a good home for this | |||
// Map IO pin to XBar pin... | |||
//=================================================================== | |||
// BUGBUG - find a good home | |||
typedef struct _pin_to_xbar_info{ | |||
const uint8_t pin; // The pin number | |||
const uint8_t xbar_in_index; // What XBar input index. | |||
const uint32_t mux_val; // Value to set for mux; | |||
volatile uint32_t *select_input_register; // Which register controls the selection | |||
const uint32_t select_val; // Value for that selection | |||
} pin_to_xbar_info_t; | |||
extern const pin_to_xbar_info_t pin_to_xbar_info[]; | |||
extern const uint8_t count_pin_to_xbar_info; | |||
class HardwareSerial : public Stream | |||
{ | |||
@@ -143,7 +158,8 @@ public: | |||
uint8_t serial_index; // which object are we? 0 based | |||
IRQ_NUMBER_t irq; | |||
void (*irq_handler)(void); | |||
void (*serial_event_handler_check)(void); | |||
void (* _serialEvent)(void); | |||
const uint8_t *serial_event_handler_default; | |||
volatile uint32_t &ccm_register; | |||
const uint32_t ccm_value; | |||
pin_info_t rx_pins[cnt_rx_pins]; | |||
@@ -153,6 +169,7 @@ public: | |||
const uint16_t irq_priority; | |||
const uint16_t rts_low_watermark; | |||
const uint16_t rts_high_watermark; | |||
const uint8_t xbar_out_lpuartX_trig_input; | |||
} hardware_t; | |||
public: | |||
constexpr HardwareSerial(IMXRT_LPUART_t *myport, const hardware_t *myhardware, | |||
@@ -183,9 +200,6 @@ public: | |||
size_t write9bit(uint32_t c); | |||
// Event Handler functions and data | |||
void enableSerialEvents(); | |||
void disableSerialEvents(); | |||
static void processSerialEvents(); | |||
static uint8_t serial_event_handlers_active; | |||
using Print::write; | |||
@@ -204,6 +218,12 @@ public: | |||
*/ | |||
operator bool() { return true; } | |||
static inline void processSerialEventsList() { | |||
for (uint8_t i = 0; i < s_count_serials_with_serial_events; i++) { | |||
s_serials_with_serial_events[i]->doYieldCode(); | |||
} | |||
} | |||
private: | |||
IMXRT_LPUART_t * const port; | |||
const hardware_t * const hardware; | |||
@@ -245,10 +265,15 @@ private: | |||
friend void IRQHandler_Serial7(); | |||
#if defined(ARDUINO_TEENSY41) | |||
friend void IRQHandler_Serial8(); | |||
static SerialEventCheckingFunctionPointer serial_event_handler_checks[8]; | |||
static HardwareSerial *s_serials_with_serial_events[8]; | |||
#else | |||
static SerialEventCheckingFunctionPointer serial_event_handler_checks[7]; | |||
static HardwareSerial *s_serials_with_serial_events[7]; | |||
#endif | |||
static uint8_t s_count_serials_with_serial_events; | |||
void addToSerialEventsList(); | |||
inline void doYieldCode() { | |||
if (available()) (*hardware->_serialEvent)(); | |||
} | |||
@@ -1,3 +1,4 @@ | |||
/* Teensyduino Core Library | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2019 PJRC.COM, LLC. | |||
@@ -44,17 +45,15 @@ void IRQHandler_Serial1() | |||
Serial1.IRQHandler(); | |||
} | |||
void serial_event_check_serial1() | |||
{ | |||
if (Serial1.available()) serialEvent1(); | |||
} | |||
// Serial1 | |||
static BUFTYPE tx_buffer1[SERIAL1_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer1[SERIAL1_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent1_default __attribute__((weak)) PROGMEM = 0 ; | |||
const HardwareSerial::hardware_t UART6_Hardware = { | |||
0, IRQ_LPUART6, &IRQHandler_Serial1, &serial_event_check_serial1, | |||
0, IRQ_LPUART6, &IRQHandler_Serial1, | |||
&serialEvent1, &_serialEvent1_default, | |||
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}}, | |||
@@ -66,12 +65,13 @@ const HardwareSerial::hardware_t UART6_Hardware = { | |||
0xff, // No CTS pin | |||
0, // No CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART6_TRG_INPUT // XBar Tigger | |||
}; | |||
HardwareSerial Serial1(&IMXRT_LPUART6, &UART6_Hardware, tx_buffer1, SERIAL1_TX_BUFFER_SIZE, | |||
rx_buffer1, SERIAL1_RX_BUFFER_SIZE); | |||
void serialEvent1() __attribute__((weak)); | |||
void serialEvent1() {Serial1.disableSerialEvents(); } // No use calling this so disable if called... | |||
//void serialEvent1() __attribute__((weak)); | |||
//void serialEvent1() {Serial1.disableSerialEvents(); } // No use calling this so disable if called... | |||
// C wrapper functions to help take care of places that used to call these from standard C | |||
void serial_print(const char *p) |
@@ -45,18 +45,16 @@ void IRQHandler_Serial2() | |||
Serial2.IRQHandler(); | |||
} | |||
void serial_event_check_serial2() | |||
{ | |||
if (Serial2.available()) serialEvent2(); | |||
} | |||
// Serial2 | |||
static BUFTYPE tx_buffer2[SERIAL2_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer2[SERIAL2_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent2_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART4_Hardware = { | |||
1, IRQ_LPUART4, &IRQHandler_Serial2, &serial_event_check_serial2, | |||
1, IRQ_LPUART4, &IRQHandler_Serial2, | |||
&serialEvent2, &_serialEvent2_default, | |||
CCM_CCGR1, CCM_CCGR1_LPUART4(CCM_CCGR_ON), | |||
#if defined(__IMXRT1052__) | |||
{{6,2, &IOMUXC_LPUART4_RX_SELECT_INPUT, 2}, {0xff, 0xff, nullptr, 0}}, | |||
@@ -68,10 +66,7 @@ static HardwareSerial::hardware_t UART4_Hardware = { | |||
0xff, // No CTS pin | |||
0, // No CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART4_TRG_INPUT | |||
}; | |||
HardwareSerial Serial2(&IMXRT_LPUART4, &UART4_Hardware, tx_buffer2, SERIAL2_TX_BUFFER_SIZE, | |||
rx_buffer2, SERIAL2_RX_BUFFER_SIZE); | |||
void serialEvent2() __attribute__((weak)); | |||
void serialEvent2() {Serial2.disableSerialEvents(); } // No use calling this so disable if called... |
@@ -44,27 +44,22 @@ void IRQHandler_Serial3() | |||
Serial3.IRQHandler(); | |||
} | |||
void serial_event_check_serial3() | |||
{ | |||
if (Serial3.available()) serialEvent3(); | |||
} | |||
// Serial3 | |||
static BUFTYPE tx_buffer3[SERIAL3_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer3[SERIAL3_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent3_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART2_Hardware = { | |||
2, IRQ_LPUART2, &IRQHandler_Serial3, &serial_event_check_serial3, | |||
CCM_CCGR0, CCM_CCGR0_LPUART2(CCM_CCGR_ON), | |||
2, IRQ_LPUART2, &IRQHandler_Serial3, | |||
&serialEvent3, &_serialEvent3_default, | |||
CCM_CCGR0, CCM_CCGR0_LPUART2(CCM_CCGR_ON), | |||
{{15,2, &IOMUXC_LPUART2_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
{{14,2, &IOMUXC_LPUART2_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
19, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00, // 19 | |||
2, // page 473 | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART2_TRG_INPUT | |||
}; | |||
HardwareSerial Serial3(&IMXRT_LPUART2, &UART2_Hardware,tx_buffer3, SERIAL3_TX_BUFFER_SIZE, | |||
rx_buffer3, SERIAL3_RX_BUFFER_SIZE); | |||
void serialEvent3() __attribute__((weak)); | |||
void serialEvent3() {Serial3.disableSerialEvents(); } // No use calling this so disable if called... | |||
@@ -45,27 +45,21 @@ void IRQHandler_Serial4() | |||
Serial4.IRQHandler(); | |||
} | |||
void serial_event_check_serial4() | |||
{ | |||
if (Serial4.available()) serialEvent4(); | |||
} | |||
// Serial4 | |||
static BUFTYPE tx_buffer4[SERIAL4_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer4[SERIAL4_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent4_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART3_Hardware = { | |||
3, IRQ_LPUART3, &IRQHandler_Serial4, &serial_event_check_serial4, | |||
3, IRQ_LPUART3, &IRQHandler_Serial4, | |||
&serialEvent4, &_serialEvent4_default, | |||
CCM_CCGR0, CCM_CCGR0_LPUART3(CCM_CCGR_ON), | |||
{{16,2, &IOMUXC_LPUART3_RX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}}, | |||
{{17,2, &IOMUXC_LPUART3_TX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}}, | |||
0xff, // No CTS pin | |||
0, // No CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART3_TRG_INPUT | |||
}; | |||
HardwareSerial Serial4(&IMXRT_LPUART3, &UART3_Hardware, tx_buffer4, SERIAL4_TX_BUFFER_SIZE, | |||
rx_buffer4, SERIAL4_RX_BUFFER_SIZE); | |||
void serialEvent4() __attribute__((weak)); | |||
void serialEvent4() {Serial4.disableSerialEvents(); } // No use calling this so disable if called... |
@@ -44,18 +44,14 @@ void IRQHandler_Serial5() | |||
{ | |||
Serial5.IRQHandler(); | |||
} | |||
void serial_event_check_serial5() | |||
{ | |||
if (Serial5.available()) serialEvent5(); | |||
} | |||
// Serial5 | |||
static BUFTYPE tx_buffer5[SERIAL5_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer5[SERIAL5_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent5_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART8_Hardware = { | |||
4, IRQ_LPUART8, &IRQHandler_Serial5, &serial_event_check_serial5, | |||
4, IRQ_LPUART8, &IRQHandler_Serial5, | |||
&serialEvent5, &_serialEvent5_default, | |||
CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON), | |||
#if defined(ARDUINO_TEENSY41) | |||
{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {46, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}}, | |||
@@ -69,11 +65,7 @@ static HardwareSerial::hardware_t UART8_Hardware = { | |||
2, // CTS | |||
#endif | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART8_TRG_INPUT | |||
}; | |||
HardwareSerial Serial5(&IMXRT_LPUART8, &UART8_Hardware, tx_buffer5, SERIAL5_TX_BUFFER_SIZE, | |||
rx_buffer5, SERIAL5_RX_BUFFER_SIZE); | |||
void serialEvent5() __attribute__((weak)); | |||
void serialEvent5() {Serial5.disableSerialEvents(); } // No use calling this so disable if called... |
@@ -44,29 +44,23 @@ void IRQHandler_Serial6() | |||
Serial6.IRQHandler(); | |||
} | |||
void serial_event_check_serial6() | |||
{ | |||
if (Serial6.available()) serialEvent6(); | |||
} | |||
// Serial6 | |||
static BUFTYPE tx_buffer6[SERIAL6_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer6[SERIAL6_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent6_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART1_Hardware = { | |||
5, IRQ_LPUART1, &IRQHandler_Serial6, &serial_event_check_serial6, | |||
5, IRQ_LPUART1, &IRQHandler_Serial6, | |||
&serialEvent6, &_serialEvent6_default, | |||
CCM_CCGR5, CCM_CCGR5_LPUART1(CCM_CCGR_ON), | |||
{{25,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}}, | |||
{{24,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}}, | |||
0xff, // No CTS pin | |||
0, // No CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART1_TRG_INPUT | |||
}; | |||
HardwareSerial Serial6(&IMXRT_LPUART1, &UART1_Hardware, tx_buffer6, SERIAL6_TX_BUFFER_SIZE, | |||
rx_buffer6, SERIAL6_RX_BUFFER_SIZE); | |||
void serialEvent6() __attribute__((weak)); | |||
void serialEvent6() {Serial6.disableSerialEvents(); } // No use calling this so disable if called... |
@@ -44,28 +44,21 @@ void IRQHandler_Serial7() | |||
Serial7.IRQHandler(); | |||
} | |||
void serial_event_check_serial7() | |||
{ | |||
if (Serial7.available()) serialEvent7(); | |||
} | |||
// Serial7 | |||
static BUFTYPE tx_buffer7[SERIAL7_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer7[SERIAL7_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent7_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART7_Hardware = { | |||
6, IRQ_LPUART7, &IRQHandler_Serial7, &serial_event_check_serial7, | |||
6, IRQ_LPUART7, &IRQHandler_Serial7, | |||
&serialEvent7, &_serialEvent7_default, | |||
CCM_CCGR5, CCM_CCGR5_LPUART7(CCM_CCGR_ON), | |||
{{28,2, &IOMUXC_LPUART7_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
{{29,2, &IOMUXC_LPUART7_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
0xff, // No CTS pin | |||
0, // No CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART7_TRG_INPUT | |||
}; | |||
HardwareSerial Serial7(&IMXRT_LPUART7, &UART7_Hardware, tx_buffer7, SERIAL7_TX_BUFFER_SIZE, | |||
rx_buffer7, SERIAL7_RX_BUFFER_SIZE); | |||
void serialEvent7() __attribute__((weak)); | |||
void serialEvent7() {Serial7.disableSerialEvents(); } // No use calling this so disable if called... |
@@ -45,19 +45,15 @@ void IRQHandler_Serial8() | |||
Serial8.IRQHandler(); | |||
} | |||
void serial_event_check_serial8() | |||
{ | |||
if (Serial8.available()) serialEvent8(); | |||
} | |||
// Serial8 | |||
static BUFTYPE tx_buffer8[SERIAL8_TX_BUFFER_SIZE]; | |||
static BUFTYPE rx_buffer8[SERIAL8_RX_BUFFER_SIZE]; | |||
uint8_t _serialEvent8_default __attribute__((weak)) PROGMEM = 0 ; | |||
static HardwareSerial::hardware_t UART5_Hardware = { | |||
7, IRQ_LPUART5, &IRQHandler_Serial8, &serial_event_check_serial8, | |||
7, IRQ_LPUART5, &IRQHandler_Serial8, | |||
&serialEvent8, &_serialEvent8_default, | |||
CCM_CCGR3, CCM_CCGR3_LPUART5(CCM_CCGR_ON), | |||
{{34,1, &IOMUXC_LPUART5_RX_SELECT_INPUT, 1}, {48, 2, &IOMUXC_LPUART5_RX_SELECT_INPUT, 0}}, | |||
{{35,1, &IOMUXC_LPUART5_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, | |||
@@ -65,10 +61,8 @@ static HardwareSerial::hardware_t UART5_Hardware = { | |||
50, // CTS pin | |||
2, // CTS | |||
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark | |||
XBARA1_OUT_LPUART5_TRG_INPUT | |||
}; | |||
HardwareSerial Serial8(&IMXRT_LPUART5, &UART5_Hardware, tx_buffer8, SERIAL8_TX_BUFFER_SIZE, | |||
rx_buffer8, SERIAL8_RX_BUFFER_SIZE); | |||
void serialEvent8() __attribute__((weak)); | |||
void serialEvent8() {Serial8.disableSerialEvents(); } // No use calling this so disable if called... | |||
#endif |
@@ -1546,6 +1546,11 @@ static inline uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrde | |||
void _reboot_Teensyduino_(void) __attribute__((noreturn)); | |||
void _restart_Teensyduino_(void) __attribute__((noreturn)); | |||
// Define a set of flags to know which things yield should check when called. | |||
extern uint8_t yield_active_check_flags; | |||
#define YIELD_CHECK_USB_SERIAL 0x1 // check the USB for Serial.available() | |||
#define YIELD_CHECK_HARDWARE_SERIAL 0x2 // check Hardware Serial ports available | |||
#define YIELD_CHECK_EVENT_RESPONDER 0x4 // User has created eventResponders that use yield | |||
void yield(void); | |||
void delay(uint32_t msec); |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
void serialEvent() __attribute__((weak)); | |||
void serialEvent() { | |||
} | |||
uint8_t _serialEvent_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent1() __attribute__((weak)); | |||
void serialEvent1() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent1_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent2() __attribute__((weak)); | |||
void serialEvent2() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent2_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent3() __attribute__((weak)); | |||
void serialEvent3() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent3_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent4() __attribute__((weak)); | |||
void serialEvent4() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent4_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent5() __attribute__((weak)); | |||
void serialEvent5() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent5_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent6() __attribute__((weak)); | |||
void serialEvent6() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent6_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent7() __attribute__((weak)); | |||
void serialEvent7() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent7_default PROGMEM = 1; |
@@ -0,0 +1,6 @@ | |||
#include <Arduino.h> | |||
#include "HardwareSerial.h" | |||
void serialEvent8() __attribute__((weak)); | |||
void serialEvent8() {} // No use calling this so disable if called... | |||
uint8_t _serialEvent8_default PROGMEM = 1; |
@@ -96,6 +96,4 @@ usb_seremu_class Serial; | |||
#endif | |||
#endif // F_CPU | |||
uint8_t usb_enable_serial_event_processing = 1; | |||
void serialEvent() __attribute__((weak)); | |||
void serialEvent() {usb_enable_serial_event_processing = 0;} | |||
@@ -31,24 +31,28 @@ | |||
#include <Arduino.h> | |||
#include "EventResponder.h" | |||
extern uint8_t usb_enable_serial_event_processing; // from usb_inst.cpp | |||
uint8_t yield_active_check_flags = YIELD_CHECK_USB_SERIAL; // default to check USB. | |||
extern const uint8_t _serialEvent_default; | |||
void yield(void) __attribute__ ((weak)); | |||
void yield(void) | |||
{ | |||
static uint8_t running=0; | |||
if (!yield_active_check_flags) return; // nothing to do | |||
if (running) return; // TODO: does this need to be atomic? | |||
running = 1; | |||
// USB Serail - Add hack to minimize impact... | |||
if (usb_enable_serial_event_processing && Serial.available()) serialEvent(); | |||
if (yield_active_check_flags & YIELD_CHECK_USB_SERIAL) { | |||
if (Serial.available()) serialEvent(); | |||
if (_serialEvent_default) yield_active_check_flags &= ~YIELD_CHECK_USB_SERIAL; | |||
} | |||
// Current workaround until integrate with EventResponder. | |||
if (HardwareSerial::serial_event_handlers_active) HardwareSerial::processSerialEvents(); | |||
if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) HardwareSerial::processSerialEventsList(); | |||
running = 0; | |||
EventResponder::runFromYield(); | |||
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield(); | |||
}; |