Browse Source

T3.x(LC) - yield and eventResponder speedups if not used

Code is setup that if there are no eventResponders that have registered to do interrupt calls, don't have the systic code in place to look for it.

Also yield code.  Now figures out if the user has any code that installs their own serialEventX methods, to call them, but if they have left the default weak pointer versions, to not call them in yield.  Likewise will only look for eventRespnder events if the sketch has actually attached any events.  If none of these conditions are true, yield will just check one flag and return.

T3.x Serial events cleanup
main
Kurt Eckhardt 4 years ago
parent
commit
2954ed6425
20 changed files with 232 additions and 51 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

+ 11
- 0
teensy3/EventResponder.cpp View File

@@ -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();
}




+ 5
- 0
teensy3/EventResponder.h View File

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

+ 45
- 0
teensy3/HardwareSerial.cpp View File

@@ -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;
}


+ 33
- 13
teensy3/HardwareSerial.h View File

@@ -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); }

+ 9
- 3
teensy3/HardwareSerial1.cpp View File

@@ -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();
}


+ 7
- 4
teensy3/HardwareSerial2.cpp View File

@@ -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();
}

+ 7
- 3
teensy3/HardwareSerial3.cpp View File

@@ -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();
}

+ 7
- 3
teensy3/HardwareSerial4.cpp View File

@@ -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

+ 7
- 3
teensy3/HardwareSerial5.cpp View File

@@ -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

+ 11
- 3
teensy3/HardwareSerial6.cpp View File

@@ -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

+ 8
- 0
teensy3/core_pins.h View File

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

+ 6
- 0
teensy3/serialEvent.cpp View File

@@ -0,0 +1,6 @@

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

+ 6
- 0
teensy3/serialEvent1.cpp View File

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

+ 6
- 0
teensy3/serialEvent2.cpp View File

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

+ 6
- 0
teensy3/serialEvent3.cpp View File

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

+ 8
- 0
teensy3/serialEvent4.cpp View File

@@ -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

+ 8
- 0
teensy3/serialEvent5.cpp View File

@@ -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

+ 8
- 0
teensy3/serialEvent6.cpp View File

@@ -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

+ 2
- 2
teensy3/usb_inst.cpp View File

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

+ 32
- 17
teensy3/yield.cpp View File

@@ -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();
};

Loading…
Cancel
Save