RAM & CPU Usage on Teensy 4.1

lukeskywalker

New member
Hi,

I am trying to measure cpu and ram usage on my teensy 4.1.

I found this sketch on an older post on this forum, however when I run it I get inaccurate results. The cpu usage shows over 100%, do I need to modify it to for the increased processor speed on the 4.1.

Any ideas would be greatly appreciated thank you.

Code:
//auto detect speed of your teensy 3.2
#if F_CPU == (24000000L) //24mhz
#define UNLOADED_IDLE_COUNTS 152000
#elif F_CPU == (48000000L) //48mhz
#define UNLOADED_IDLE_COUNTS 280000
#elif F_CPU == (72000000L) //72mhz
#define UNLOADED_IDLE_COUNTS 360000
#else //96mhz
#define UNLOADED_IDLE_COUNTS 420000
#endif

//set cpu percent scale to a linear one
#define LOG 0
#define LIN 1
#define SCALE LIN

static IntervalTimer cpu;

uint32_t Idle_Counter;
uint8_t CPU_Utilization_Info_Read_To_Compute;
uint32_t Prev_Idle_Counter;
uint32_t Idle_Counts;
uint32_t Calculate_Idle_Counts (void);


extern "C" char* sbrk(int incr);
int freeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}


void setup()
{

  delay(1000);
  // initialize the serial communication at max speed:
  Serial.begin(250000);

  Serial.println("started");
  cpu.begin(Update_Task_Ready_Flags, 1000);

}
uint32_t Read_Idle_Counts(void)
{
  return Idle_Counts;
}
uint32_t Calculate_CPU_Utilization (uint32_t temp_counts)
{
  return 100 - ((100 * temp_counts) / UNLOADED_IDLE_COUNTS);
}
uint32_t Calculate_Idle_Counts (void)
{
  Idle_Counts = Idle_Counter - Prev_Idle_Counter;
  Prev_Idle_Counter = Idle_Counter;
  return Idle_Counts;
}
bool One_MS_Task_Ready;
bool Ten_MS_Task_Ready;
bool One_Hundred_MS_Task_Ready;
bool One_S_Task_Ready;
inline void One_MS_Task(void)
{

}
inline void Ten_MS_Task(void)
{
  //uncomment line below to put in some cpu load :)
  //delay(8);
}
inline void One_Hundred_MS_Task(void)
{

}
inline void One_S_Task(void)
{
  uint32_t idleCounts = Calculate_Idle_Counts();
#if SCALE == (LOG)
  uint8_t percent1 = (Calculate_CPU_Utilization(idleCounts)*2)/2;
  uint8_t percent2 = (Calculate_CPU_Utilization(idleCounts)*2)/2;
  uint8_t percent = (percent1*percent2)/100;
#elif SCALE == (LIN)
  uint8_t percent = Calculate_CPU_Utilization(idleCounts);
#endif
  //output percent to serial monitor
  Serial.print(F("CPU usage: "));
  Serial.print(percent);
  Serial.println(F("%"));
  Serial.print(F("Free RAM: "));
  Serial.println(freeRam());
}
inline void Run_Tasks(void)
{
  if(One_MS_Task_Ready)
  {
    One_MS_Task_Ready=0;
    One_MS_Task();
  }
  if(Ten_MS_Task_Ready)
  {
    Ten_MS_Task_Ready=0;
    Ten_MS_Task();
  }
  if(One_Hundred_MS_Task_Ready)
  {
    One_Hundred_MS_Task_Ready=0;
    One_Hundred_MS_Task();
  }
  if(One_S_Task_Ready)
  {
    One_S_Task_Ready=0;
    One_S_Task();
  }
}
void loop()
{
  Idle_Counter++; 
  Run_Tasks();
}
/* WARNING this function called from ISR */
void Update_Task_Ready_Flags(void)
{
  static uint32_t counter;
  One_MS_Task_Ready=1;
  counter++;
  if((counter%10)==0)
  {
    Ten_MS_Task_Ready=1;
  }
  if((counter%100)==0)
  {
    One_Hundred_MS_Task_Ready=1;;
  }
  if(counter == 1000)
  {
    One_S_Task_Ready=1;
    counter=0;
  }  
}

Screen Shot 2022-04-06 at 17.31.28 PM.png [2] copy.png
 
Not sure of the source post used for ref, but it seems to be T_3.2 pr 3.1 with default max F_CPU of 96 MHz

Adding these two lines before the ELSE at the top:
Code:
[B]#elif F_CPU == (600000000L) //600mhz
#define UNLOADED_IDLE_COUNTS 13600000
[/B][COLOR="#FF0000"]#else //96mhz[/COLOR]

Then shows ZERO% usage, and when 8ms each 10ms is used it shows 84% used which may be about right.

The "Free RAM" is horribly wrong as well - there are other posts that show the proper way to calc FREE RAM on 1062.
 
The way that code is written - it "CALLS" a couple of empty functions as the baseline.

For that Here showed 13627933 for Idle_Counter where the above number gives 0%

It then shows 84% with delay(8) and 8 ms delay, with overhead of call to yield() etc, replacing with delayMicroseconds(8000); drops that to 83%

Some of the extra 3% may be in even calling the function in Run_Tasks(), which the compiler may optimize away given they are empty.
 
Back
Top