0

Clue and RTOS
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Clue and RTOS

by defragster on Mon Jul 06, 2020 12:00 am

The LEARN for the CLUE has a TBD note on RTOS - the code exposes some info.
First look was the CLUE factory sketch - under RTOS but just the loop() task - it takes 540+ms to cycle through a display update loop without any delay - that is scary slow for what I hoped to see. So other timing tests. A Teensy 3.2 at 48 Mhz was faster - similar M4 - NRF designed for low power with Float support.

Reading the RTOS related code the loop() is started TASK_PRIO_LOW not NORMA?. Adding a second task loop2() and other adventures as in the code below got the count of loop()'s second up - the second task helped, but not sure if legal - but so did adding a new/second :: Scheduler.startLoop(loop);

But when instantiated with params as indicated in the code - just added according to the read.me - things act like that was not properly implemented?

Purchase here was some SENSE and CLUE both - and they both respond the same. If the #defines are cycled in one by one the effect on the runtime is observable as noted in comments.

Two other issues - perhaps for other threads
> in setup() the resolution of micros() is tested and noted to be 976us per micros() tick - I didn't look at the implementation - but that is really bad at almost 1ms for a function that takes longer to return
> The CLUE with " pinMode( PIN_LED2, OUTPUT ); " starts the the white LEDS ON - as shown in code digitalWrite( PIN_LED2, 0 ); executed before didn't turn them on until used later.

Here is the code used showing the RTOS confusion- loop() and loop2() are simple calls to LED toggle as in the one example - showing the cycle time. Where the blinks are made no delay(). This will be an issue adding 'tasks' when Bluetooth also adds a task I suspect - but haven't gotten that far yet.
Code: Select all | TOGGLE FULL SIZE
//  FOR SENSE :::
#define SHOWBAD 1   // ONLY runs loop() and not loop2() // 177K
//#define SHOWBROKEN  1 // Never runs loop() only loop2()  // 87K each
//#define DUALGOOD 1 // 170K
//#define DUALBETTER 1 // 172K
//  DEFAULT ELSE // 170K

//  FOR CLUE :::
//#define SHOWBAD 1   // ONLY runs loop() and not loop2() // 176K
//#define SHOWBROKEN  1 // Never runs loop() only loop2()  // 86K each
//#define DUALGOOD 1        // 169K
//#define DUALBETTER 1    // 172K
//  DEFAULT ELSE          // without loop2() Scheduler // 169K

// NRF52 micros() are 976us apart - and take extra runtime

#ifdef ARDUINO_NRF52840_CLUE
#define OTHERLED PIN_LED2 // CLUE front whites
#endif
#ifdef ARDUINO_NRF52840_FEATHER_SENSE
#define OTHERLED LED_BLUE
#endif

void setup()
{
  while (!Serial && millis() < 6000) delay(10);
  Serial.println("\nScheduler RTOS DualBlink test!");
  Serial.println( __FILE__ " " __DATE__ " " __TIME__);
  digitalWrite( OTHERLED, 0); // CLUE PIN_LED2 powers up ON ???
  pinMode( OTHERLED, OUTPUT );

#ifdef SHOWBAD
  Scheduler.startLoop(loop, 1024, TASK_PRIO_NORMAL , "loop");
  Scheduler.startLoop(loop2, 1024, TASK_PRIO_NORMAL, "loop2"); // NEVER RUNS
#elif SHOWBROKEN
  Scheduler.startLoop(loop2, 1024, TASK_PRIO_NORMAL, "loop2"); // loop() NEVER RUNS
#elif DUALBETTER
  Scheduler.startLoop(loop);
  Scheduler.startLoop(loop2);
#elif DUALGOOD
  Scheduler.startLoop(loop2);
#else // SINGLESLOW
  // default :: loop() starts with TASK_PRIO_LOW ??
#endif
  uint32_t ttest[10];
  ttest[0]=micros();
  for ( int ii = 0; ii < 9; ) {
    if ( ttest[ii] != micros() )
      ttest[++ii] = micros();
  }
  for ( int ii = 0; ii < 9; ii++ ) {
    Serial.println( ttest[ii] );
    Serial.println( ttest[ii+1]-ttest[ii] );
  }
}

void loop() //    Toggle led1 every 1 second
{
  timeCntPrt( LED_RED, 1000 );
}

void loop2()  //    Toggle led1 every 0.5 second
{
  timeCntPrt( OTHERLED, 500 );
}

void timeCntPrt( uint32_t aPin, uint32_t aWait)  //
{
  static uint32_t Waits[50], Counts[50], allCnt;
  if ( 0 == Counts[aPin] ) {
    Counts[aPin]++;
    Waits[aPin] = millis();
  }
  else {
    Counts[aPin]++;
    if ( millis() - Waits[aPin] >= aWait ) {
      digitalToggle(aPin);
      Waits[aPin] += aWait;
      Serial.printf( "\tPin#%u C#=%u\t", aPin, Counts[aPin] );
      allCnt += Counts[aPin];
      if ( aPin == LED_RED ) {
        Serial.printf( ">>> All Counts #=%u\n", allCnt );
        allCnt = 0;
      }
      Counts[aPin] = 1;
    }
  }
}

defragster
 
Posts: 14
Joined: Sun Apr 05, 2015 5:48 am

Re: Clue and RTOS

by defragster on Mon Jul 06, 2020 5:13 am

Just found this example : ...\AppData\Local\Arduino15\packages\adafruit\hardware\nrf52\0.20.1\libraries\InternalFileSytem\examples\Internal_StressTest\Internal_StressTest.ino

It does work on SENSE and CLUE doing a file system test - which is nice as had not found Adafruit_LittleFS.h example before. Though it may be using on chip flash not 2MB QSPI? Also exposes some use of the TaskHandle details.

It does Scheduler.startLoop(loop, ...) four times and it works? I duplicated loop() to loop2() and edited one of those lines and made a directory for loops2 and that worked as well.

Not sure why the code above as SHOWBAD and SHOWBROKEN fail to schedule and run both loop and loop2 in that case? Works in other cases - they don't use delay - but isn't there a yield as needed on task exiting?

Also looked at micros() - it is limited by clock ticks as presented under RTOS it seems?

defragster
 
Posts: 14
Joined: Sun Apr 05, 2015 5:48 am

Please be positive and constructive with your questions and comments.