Browse Source

Merge pull request #474 from KurtE/eventResponder_reduce_overhead

T4.x Reduce EventResponder overhead on systic and yield
teensy4-core
Paul Stoffregen 4 years ago
parent
commit
b1f56c7d54
No account linked to committer's email address
44 changed files with 482 additions and 181 deletions
  1. +11
    -0
      teensy3/EventResponder.cpp
  2. +5
    -0
      teensy3/EventResponder.h
  3. +45
    -0
      teensy3/HardwareSerial.cpp
  4. +33
    -13
      teensy3/HardwareSerial.h
  5. +9
    -3
      teensy3/HardwareSerial1.cpp
  6. +7
    -4
      teensy3/HardwareSerial2.cpp
  7. +7
    -3
      teensy3/HardwareSerial3.cpp
  8. +7
    -3
      teensy3/HardwareSerial4.cpp
  9. +7
    -3
      teensy3/HardwareSerial5.cpp
  10. +11
    -3
      teensy3/HardwareSerial6.cpp
  11. +8
    -0
      teensy3/core_pins.h
  12. +6
    -0
      teensy3/serialEvent.cpp
  13. +6
    -0
      teensy3/serialEvent1.cpp
  14. +6
    -0
      teensy3/serialEvent2.cpp
  15. +6
    -0
      teensy3/serialEvent3.cpp
  16. +8
    -0
      teensy3/serialEvent4.cpp
  17. +8
    -0
      teensy3/serialEvent5.cpp
  18. +8
    -0
      teensy3/serialEvent6.cpp
  19. +2
    -2
      teensy3/usb_inst.cpp
  20. +32
    -17
      teensy3/yield.cpp
  21. +8
    -1
      teensy4/EventResponder.cpp
  22. +5
    -2
      teensy4/EventResponder.h
  23. +99
    -32
      teensy4/HardwareSerial.cpp
  24. +32
    -7
      teensy4/HardwareSerial.h
  25. +7
    -7
      teensy4/HardwareSerial1.cpp
  26. +5
    -10
      teensy4/HardwareSerial2.cpp
  27. +5
    -10
      teensy4/HardwareSerial3.cpp
  28. +4
    -10
      teensy4/HardwareSerial4.cpp
  29. +4
    -12
      teensy4/HardwareSerial5.cpp
  30. +4
    -10
      teensy4/HardwareSerial6.cpp
  31. +4
    -11
      teensy4/HardwareSerial7.cpp
  32. +4
    -10
      teensy4/HardwareSerial8.cpp
  33. +5
    -0
      teensy4/core_pins.h
  34. +6
    -0
      teensy4/serialEvent.cpp
  35. +6
    -0
      teensy4/serialEvent1.cpp
  36. +6
    -0
      teensy4/serialEvent2.cpp
  37. +6
    -0
      teensy4/serialEvent3.cpp
  38. +6
    -0
      teensy4/serialEvent4.cpp
  39. +6
    -0
      teensy4/serialEvent5.cpp
  40. +6
    -0
      teensy4/serialEvent6.cpp
  41. +6
    -0
      teensy4/serialEvent7.cpp
  42. +6
    -0
      teensy4/serialEvent8.cpp
  43. +1
    -3
      teensy4/usb_inst.cpp
  44. +9
    -5
      teensy4/yield.cpp

+ 11
- 0
teensy3/EventResponder.cpp View File

bool EventResponder::runningFromYield = false; bool EventResponder::runningFromYield = false;


// TODO: interrupt disable/enable needed in many places!!! // 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() void EventResponder::triggerEventNotImmediate()
{ {
// with libraries using mid-to-high priority interrupts. // with libraries using mid-to-high priority interrupts.


extern "C" volatile uint32_t systick_millis_count; extern "C" volatile uint32_t systick_millis_count;

void systick_isr(void) void systick_isr(void)
{
systick_millis_count++;
}

extern "C" void systick_isr_with_timer_events(void)
{ {
systick_millis_count++; systick_millis_count++;
MillisTimer::runFromTimer(); MillisTimer::runFromTimer();
} }






+ 5
- 0
teensy3/EventResponder.h View File

* your function is called only one time, based on the last trigger * your function is called only one time, based on the last trigger
* event. * event.
*/ */
extern "C" void systick_isr_with_timer_events(void);


class EventResponder; class EventResponder;
typedef EventResponder& EventResponderRef; typedef EventResponder& EventResponderRef;
detachNoInterrupts(); detachNoInterrupts();
_function = function; _function = function;
_type = EventTypeYield; _type = EventTypeYield;
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type...
enableInterrupts(irq); enableInterrupts(irq);
} }


_function = function; _function = function;
_type = EventTypeInterrupt; _type = EventTypeInterrupt;
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority 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); enableInterrupts(irq);
} }


EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout); EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout);


static void runFromYield() { static void runFromYield() {
if (!firstYield) return;
// First, check if yield was called from an interrupt // First, check if yield was called from an interrupt
// never call normal handler functions from any interrupt context // never call normal handler functions from any interrupt context
uint32_t ipsr; uint32_t ipsr;

+ 45
- 0
teensy3/HardwareSerial.cpp View File

/* 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;
}


+ 33
- 13
teensy3/HardwareSerial.h View File

class HardwareSerial : public Stream class HardwareSerial : public Stream
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial_begin(BAUD2DIV(baud)); serial_begin(BAUD2DIV(baud));
serial_format(format); } serial_format(format); }
return len; } return len; }
virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; } virtual size_t write9bit(uint32_t c) { serial_putchar(c); return 1; }
operator bool() { return true; } 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 HardwareSerial Serial1;
extern void serialEvent1(void); extern void serialEvent1(void);
class HardwareSerial2 : public HardwareSerial class HardwareSerial2 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial2_begin(BAUD2DIV2(baud)); serial2_begin(BAUD2DIV2(baud));
serial2_format(format); } serial2_format(format); }
class HardwareSerial3 : public HardwareSerial class HardwareSerial3 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial3_begin(BAUD2DIV3(baud)); serial3_begin(BAUD2DIV3(baud));
serial3_format(format); } serial3_format(format); }
class HardwareSerial4 : public HardwareSerial class HardwareSerial4 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial4_begin(BAUD2DIV3(baud)); serial4_begin(BAUD2DIV3(baud));
serial4_format(format); } serial4_format(format); }
class HardwareSerial5 : public HardwareSerial class HardwareSerial5 : public HardwareSerial
{ {
public: 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) { virtual void begin(uint32_t baud, uint32_t format) {
serial5_begin(BAUD2DIV3(baud)); serial5_begin(BAUD2DIV3(baud));
serial5_format(format); } serial5_format(format); }
class HardwareSerial6 : public HardwareSerial class HardwareSerial6 : public HardwareSerial
{ {
public: public:
constexpr HardwareSerial6() {}
constexpr HardwareSerial6(void (* const se)()) : HardwareSerial(se) {}
#if defined(__MK66FX1M0__) // For LPUART just pass baud straight in. #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) { virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(baud); serial6_begin(baud);
serial6_format(format); } serial6_format(format); }
#else #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) { virtual void begin(uint32_t baud, uint32_t format) {
serial6_begin(BAUD2DIV3(baud)); serial6_begin(BAUD2DIV3(baud));
serial6_format(format); } serial6_format(format); }

+ 9
- 3
teensy3/HardwareSerial1.cpp View File

#include <Arduino.h> #include <Arduino.h>
#include "HardwareSerial.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();
}


+ 7
- 4
teensy3/HardwareSerial2.cpp View File

* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
*/ */

#include <Arduino.h> #include <Arduino.h>
#include "HardwareSerial.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();
}

+ 7
- 3
teensy3/HardwareSerial3.cpp View File

#include <Arduino.h> #include <Arduino.h>
#include "HardwareSerial.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();
}

+ 7
- 3
teensy3/HardwareSerial4.cpp View File



#ifdef HAS_KINETISK_UART3 #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 #endif

+ 7
- 3
teensy3/HardwareSerial5.cpp View File



#ifdef HAS_KINETISK_UART4 #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 #endif

+ 11
- 3
teensy3/HardwareSerial6.cpp View File



#if defined(HAS_KINETISK_UART5) || defined (HAS_KINETISK_LPUART0) #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 #endif

+ 8
- 0
teensy3/core_pins.h View File

void _reboot_Teensyduino_(void) __attribute__((noreturn)); void _reboot_Teensyduino_(void) __attribute__((noreturn));
void _restart_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 yield(void);


void delay(uint32_t msec); void delay(uint32_t msec);

+ 6
- 0
teensy3/serialEvent.cpp View File


#include <Arduino.h>
void serialEvent() __attribute__((weak));
void serialEvent() {
}
uint8_t _serialEvent_default PROGMEM = 1;

+ 6
- 0
teensy3/serialEvent1.cpp View File


#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;

+ 6
- 0
teensy3/serialEvent2.cpp View File


#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;

+ 6
- 0
teensy3/serialEvent3.cpp View File


#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;

+ 8
- 0
teensy3/serialEvent4.cpp View File


#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

+ 8
- 0
teensy3/serialEvent5.cpp View File


#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

+ 8
- 0
teensy3/serialEvent6.cpp View File


#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

+ 2
- 2
teensy3/usb_inst.cpp View File



#endif // F_CPU #endif // F_CPU


void serialEvent() __attribute__((weak));
void serialEvent() {}
//void serialEvent() __attribute__((weak));
//void serialEvent() {}
void serialEventUSB1() __attribute__((weak)); void serialEventUSB1() __attribute__((weak));
void serialEventUSB1() {} void serialEventUSB1() {}
void serialEventUSB2() __attribute__((weak)); void serialEventUSB2() __attribute__((weak));

+ 32
- 17
teensy3/yield.cpp View File

#include <Arduino.h> #include <Arduino.h>
#include "EventResponder.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) __attribute__ ((weak));
void yield(void) void yield(void)
{ {
static uint8_t running=0; static uint8_t running=0;

if (!yield_active_check_flags) return; // nothing to do
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 (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 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 #endif
#ifdef USB_TRIPLE_SERIAL #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 #endif
if (yield_active_check_flags & YIELD_CHECK_HARDWARE_SERIAL) {
HardwareSerial::processSerialEventsList();
}
running = 0; running = 0;
EventResponder::runFromYield();
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield();
}; };

+ 8
- 1
teensy4/EventResponder.cpp View File

bool EventResponder::runningFromYield = false; bool EventResponder::runningFromYield = false;


// TODO: interrupt disable/enable needed in many places!!! // 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() void EventResponder::triggerEventNotImmediate()
{ {
{ {
systick_cycle_count = ARM_DWT_CYCCNT; systick_cycle_count = ARM_DWT_CYCCNT;
systick_millis_count++; 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();
}



+ 5
- 2
teensy4/EventResponder.h View File

* your function is called only one time, based on the last trigger * your function is called only one time, based on the last trigger
* event. * event.
*/ */
extern "C" void systick_isr_with_timer_events(void);


class EventResponder; class EventResponder;
typedef EventResponder& EventResponderRef; typedef EventResponder& EventResponderRef;
detachNoInterrupts(); detachNoInterrupts();
_function = function; _function = function;
_type = EventTypeYield; _type = EventTypeYield;
yield_active_check_flags |= YIELD_CHECK_EVENT_RESPONDER; // user setup a yield type...
enableInterrupts(irq); enableInterrupts(irq);
} }


_function = function; _function = function;
_type = EventTypeInterrupt; _type = EventTypeInterrupt;
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority 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); enableInterrupts(irq);
} }


// used with a scheduler or RTOS. // used with a scheduler or RTOS.
bool waitForEvent(EventResponderRef event, int timeout); bool waitForEvent(EventResponderRef event, int timeout);
EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout); EventResponder * waitForEvent(EventResponder *list, int listsize, int timeout);

static void runFromYield() { static void runFromYield() {
if (!firstYield) return;
if (!firstYield) return;
// First, check if yield was called from an interrupt // First, check if yield was called from an interrupt
// never call normal handler functions from any interrupt context // never call normal handler functions from any interrupt context
uint32_t ipsr; uint32_t ipsr;

+ 99
- 32
teensy4/HardwareSerial.cpp View File



#define UART_CLOCK 24000000 #define UART_CLOCK 24000000


extern "C" {
extern void xbar_connect(unsigned int input, unsigned int output);
}

#if defined(ARDUINO_TEENSY41) #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 #else
SerialEventCheckingFunctionPointer HardwareSerial::serial_event_handler_checks[7] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
HardwareSerial *HardwareSerial::s_serials_with_serial_events[7];
#endif #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) #define CTRL_ENABLE (LPUART_CTRL_TE | LPUART_CTRL_RE | LPUART_CTRL_RIE | LPUART_CTRL_ILIE)
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
// 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() 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)
// new pin - so lets maybe reset the old pin to INPUT? and then set new pin parameters // 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. // only change IO pins if done after begin has been called.
if ((hardware->ccm_register & hardware->ccm_value)) { 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;; *(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; *(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) { if (hardware->rx_pins[rx_pin_new_index].select_input_register) {
} }
} }
rx_pin_index_ = rx_pin_new_index; 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;
} }
} }
} }
port->MODIR |= LPUART_MODIR_TXCTSE; port->MODIR |= LPUART_MODIR_TXCTSE;
return true; return true;
} else { } 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; port->MODIR &= ~LPUART_MODIR_TXCTSE;
return false; return false;
} }
} }




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]);


+ 32
- 7
teensy4/HardwareSerial.h View File

#endif #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 class HardwareSerial : public Stream
{ {
uint8_t serial_index; // which object are we? 0 based 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);
void (* _serialEvent)(void);
const uint8_t *serial_event_handler_default;
volatile uint32_t &ccm_register; volatile uint32_t &ccm_register;
const uint32_t ccm_value; const uint32_t ccm_value;
pin_info_t rx_pins[cnt_rx_pins]; pin_info_t rx_pins[cnt_rx_pins];
const uint16_t irq_priority; const uint16_t irq_priority;
const uint16_t rts_low_watermark; const uint16_t rts_low_watermark;
const uint16_t rts_high_watermark; const uint16_t rts_high_watermark;
const uint8_t xbar_out_lpuartX_trig_input;
} hardware_t; } hardware_t;
public: public:
constexpr HardwareSerial(IMXRT_LPUART_t *myport, const hardware_t *myhardware, constexpr HardwareSerial(IMXRT_LPUART_t *myport, const hardware_t *myhardware,
size_t write9bit(uint32_t c); size_t write9bit(uint32_t c);
// Event Handler functions and data // Event Handler functions and data
void enableSerialEvents();
void disableSerialEvents();
static void processSerialEvents();
static uint8_t serial_event_handlers_active; static uint8_t serial_event_handlers_active;


using Print::write; using Print::write;
*/ */


operator bool() { return true; } 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: private:
IMXRT_LPUART_t * const port; IMXRT_LPUART_t * const port;
const hardware_t * const hardware; const hardware_t * const hardware;
friend void IRQHandler_Serial7(); friend void IRQHandler_Serial7();
#if defined(ARDUINO_TEENSY41) #if defined(ARDUINO_TEENSY41)
friend void IRQHandler_Serial8(); friend void IRQHandler_Serial8();
static SerialEventCheckingFunctionPointer serial_event_handler_checks[8];
static HardwareSerial *s_serials_with_serial_events[8];
#else #else
static SerialEventCheckingFunctionPointer serial_event_handler_checks[7];
static HardwareSerial *s_serials_with_serial_events[7];
#endif #endif
static uint8_t s_count_serials_with_serial_events;
void addToSerialEventsList();
inline void doYieldCode() {
if (available()) (*hardware->_serialEvent)();
}







+ 7
- 7
teensy4/HardwareSerial1.cpp View File


/* Teensyduino Core Library /* Teensyduino Core Library
* http://www.pjrc.com/teensy/ * http://www.pjrc.com/teensy/
* Copyright (c) 2019 PJRC.COM, LLC. * Copyright (c) 2019 PJRC.COM, LLC.
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];
uint8_t _serialEvent1_default __attribute__((weak)) PROGMEM = 0 ;


const HardwareSerial::hardware_t UART6_Hardware = { 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), 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}},
0xff, // No CTS pin 0xff, // No CTS pin
0, // No CTS 0, // No CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial1(&IMXRT_LPUART6, &UART6_Hardware, tx_buffer1, SERIAL1_TX_BUFFER_SIZE,
rx_buffer1, SERIAL1_RX_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 // C wrapper functions to help take care of places that used to call these from standard C
void serial_print(const char *p) void serial_print(const char *p)

+ 5
- 10
teensy4/HardwareSerial2.cpp View File

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];


uint8_t _serialEvent2_default __attribute__((weak)) PROGMEM = 0 ;

static HardwareSerial::hardware_t UART4_Hardware = { 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), CCM_CCGR1, CCM_CCGR1_LPUART4(CCM_CCGR_ON),
#if defined(__IMXRT1052__) #if defined(__IMXRT1052__)
{{6,2, &IOMUXC_LPUART4_RX_SELECT_INPUT, 2}, {0xff, 0xff, nullptr, 0}}, {{6,2, &IOMUXC_LPUART4_RX_SELECT_INPUT, 2}, {0xff, 0xff, nullptr, 0}},
0xff, // No CTS pin 0xff, // No CTS pin
0, // No CTS 0, // No CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial2(&IMXRT_LPUART4, &UART4_Hardware, tx_buffer2, SERIAL2_TX_BUFFER_SIZE,
rx_buffer2, SERIAL2_RX_BUFFER_SIZE); rx_buffer2, SERIAL2_RX_BUFFER_SIZE);


void serialEvent2() __attribute__((weak));
void serialEvent2() {Serial2.disableSerialEvents(); } // No use calling this so disable if called...

+ 5
- 10
teensy4/HardwareSerial3.cpp View File

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];
uint8_t _serialEvent3_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART2_Hardware = { 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}}, {{15,2, &IOMUXC_LPUART2_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
{{14,2, &IOMUXC_LPUART2_TX_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 19, //IOMUXC_SW_MUX_CTL_PAD_GPIO_AD_B1_00, // 19
2, // page 473 2, // page 473
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial3(&IMXRT_LPUART2, &UART2_Hardware,tx_buffer3, SERIAL3_TX_BUFFER_SIZE,
rx_buffer3, SERIAL3_RX_BUFFER_SIZE); rx_buffer3, SERIAL3_RX_BUFFER_SIZE);


void serialEvent3() __attribute__((weak));
void serialEvent3() {Serial3.disableSerialEvents(); } // No use calling this so disable if called...


+ 4
- 10
teensy4/HardwareSerial4.cpp View File

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];
uint8_t _serialEvent4_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART3_Hardware = { 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), CCM_CCGR0, CCM_CCGR0_LPUART3(CCM_CCGR_ON),
{{16,2, &IOMUXC_LPUART3_RX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}}, {{16,2, &IOMUXC_LPUART3_RX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}},
{{17,2, &IOMUXC_LPUART3_TX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}}, {{17,2, &IOMUXC_LPUART3_TX_SELECT_INPUT, 0}, {0xff, 0xff, nullptr, 0}},
0xff, // No CTS pin 0xff, // No CTS pin
0, // No CTS 0, // No CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial4(&IMXRT_LPUART3, &UART3_Hardware, tx_buffer4, SERIAL4_TX_BUFFER_SIZE,
rx_buffer4, SERIAL4_RX_BUFFER_SIZE); rx_buffer4, SERIAL4_RX_BUFFER_SIZE);


void serialEvent4() __attribute__((weak));
void serialEvent4() {Serial4.disableSerialEvents(); } // No use calling this so disable if called...

+ 4
- 12
teensy4/HardwareSerial5.cpp View File

{ {
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];
uint8_t _serialEvent5_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART8_Hardware = { 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), CCM_CCGR6, CCM_CCGR6_LPUART8(CCM_CCGR_ON),
#if defined(ARDUINO_TEENSY41) #if defined(ARDUINO_TEENSY41)
{{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {46, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}}, {{21,2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 1}, {46, 2, &IOMUXC_LPUART8_RX_SELECT_INPUT, 0}},
2, // CTS 2, // CTS
#endif #endif
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial5(&IMXRT_LPUART8, &UART8_Hardware, tx_buffer5, SERIAL5_TX_BUFFER_SIZE,
rx_buffer5, SERIAL5_RX_BUFFER_SIZE); rx_buffer5, SERIAL5_RX_BUFFER_SIZE);



void serialEvent5() __attribute__((weak));
void serialEvent5() {Serial5.disableSerialEvents(); } // No use calling this so disable if called...

+ 4
- 10
teensy4/HardwareSerial6.cpp View File

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];
uint8_t _serialEvent6_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART1_Hardware = { 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), CCM_CCGR5, CCM_CCGR5_LPUART1(CCM_CCGR_ON),
{{25,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}}, {{25,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}},
{{24,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}}, {{24,2, nullptr, 0}, {0xff, 0xff, nullptr, 0}},
0xff, // No CTS pin 0xff, // No CTS pin
0, // No CTS 0, // No CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial6(&IMXRT_LPUART1, &UART1_Hardware, tx_buffer6, SERIAL6_TX_BUFFER_SIZE,
rx_buffer6, SERIAL6_RX_BUFFER_SIZE); rx_buffer6, SERIAL6_RX_BUFFER_SIZE);

void serialEvent6() __attribute__((weak));
void serialEvent6() {Serial6.disableSerialEvents(); } // No use calling this so disable if called...

+ 4
- 11
teensy4/HardwareSerial7.cpp View File

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];
uint8_t _serialEvent7_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART7_Hardware = { 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), CCM_CCGR5, CCM_CCGR5_LPUART7(CCM_CCGR_ON),
{{28,2, &IOMUXC_LPUART7_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, {{28,2, &IOMUXC_LPUART7_RX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
{{29,2, &IOMUXC_LPUART7_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}}, {{29,2, &IOMUXC_LPUART7_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
0xff, // No CTS pin 0xff, // No CTS pin
0, // No CTS 0, // No CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, HardwareSerial Serial7(&IMXRT_LPUART7, &UART7_Hardware, tx_buffer7, SERIAL7_TX_BUFFER_SIZE,
rx_buffer7, SERIAL7_RX_BUFFER_SIZE); rx_buffer7, SERIAL7_RX_BUFFER_SIZE);


void serialEvent7() __attribute__((weak));
void serialEvent7() {Serial7.disableSerialEvents(); } // No use calling this so disable if called...

+ 4
- 10
teensy4/HardwareSerial8.cpp View File

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];
uint8_t _serialEvent8_default __attribute__((weak)) PROGMEM = 0 ;


static HardwareSerial::hardware_t UART5_Hardware = { 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), CCM_CCGR3, CCM_CCGR3_LPUART5(CCM_CCGR_ON),
{{34,1, &IOMUXC_LPUART5_RX_SELECT_INPUT, 1}, {48, 2, &IOMUXC_LPUART5_RX_SELECT_INPUT, 0}}, {{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}}, {{35,1, &IOMUXC_LPUART5_TX_SELECT_INPUT, 1}, {0xff, 0xff, nullptr, 0}},
50, // CTS pin 50, // CTS pin
2, // CTS 2, // CTS
IRQ_PRIORITY, 38, 24, // IRQ, rts_low_watermark, rts_high_watermark 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, 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 serialEvent8() __attribute__((weak));
void serialEvent8() {Serial8.disableSerialEvents(); } // No use calling this so disable if called...
#endif #endif

+ 5
- 0
teensy4/core_pins.h View File

void _reboot_Teensyduino_(void) __attribute__((noreturn)); void _reboot_Teensyduino_(void) __attribute__((noreturn));
void _restart_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 yield(void);


void delay(uint32_t msec); void delay(uint32_t msec);

+ 6
- 0
teensy4/serialEvent.cpp View File


#include <Arduino.h>
void serialEvent() __attribute__((weak));
void serialEvent() {
}
uint8_t _serialEvent_default PROGMEM = 1;

+ 6
- 0
teensy4/serialEvent1.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent2.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent3.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent4.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent5.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent6.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent7.cpp View File


#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;

+ 6
- 0
teensy4/serialEvent8.cpp View File


#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;

+ 1
- 3
teensy4/usb_inst.cpp View File

#endif #endif


#endif // F_CPU #endif // F_CPU
uint8_t usb_enable_serial_event_processing = 1;
void serialEvent() __attribute__((weak));
void serialEvent() {usb_enable_serial_event_processing = 0;}


+ 9
- 5
teensy4/yield.cpp View File

#include <Arduino.h> #include <Arduino.h>
#include "EventResponder.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) __attribute__ ((weak));
void yield(void) void yield(void)
{ {
static uint8_t running=0; static uint8_t running=0;
if (!yield_active_check_flags) return; // nothing to do
if (running) return; // TODO: does this need to be atomic? if (running) return; // TODO: does this need to be atomic?
running = 1; running = 1;




// USB Serail - Add hack to minimize impact... // 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. // 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; running = 0;
EventResponder::runFromYield();
if (yield_active_check_flags & YIELD_CHECK_EVENT_RESPONDER) EventResponder::runFromYield();
}; };

Loading…
Cancel
Save