This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Having a single call in Idle thread to calculate CPU usage at runtime

Keil 4 allowed a function call in the idle loop which I utilized to generate how must time per second is spent in the idle loop

__task void os_idle_demon (void) {
  /* The idle demon is a system task, running when no other task is ready */
  /* to run. The 'os_xxx' function calls are not allowed from this task.  */

  for (;;) {
  /* HERE: include optional user code to be executed when no task runs.*/
    update_idle_time();
  }
}

//This called in Keil RTX os_idle_demon method which is when no other task or interrupts are running.
void update_idle_time(void)
{
  uint32_t dif, val;
  uint32_t irq_status = __get_PRIMASK();
  __disable_irq();  
  val = usCPUTIMER;
  dif = val-last_idle_time;
  last_idle_time = val;
  __set_PRIMASK(irq_status);
  if (dif)
  {
    if (dif < 3)  //If Counter only moves two or less then we must have only been in this task
      __atomic_add32(&idle_time_sum,dif);
    else
      __atomic_add32(&proc_time_sum,dif);
  }
}

This is the output of a stat command using a Keil 4 applications.  

You can see below we are keeping track of how many times a task is called, the Average, Minimum and Maximum Period and Execution Duration Stats.

We also have statistics on all enabled interrupts.

stat 10 
                                     |          Period (us)           |            Duration (us)     
IRQ Name       ID      Count Flg Pri |      Avg        Min        Max |      Avg        Min        Max  Last Start
       SysTick --          0  01   9        500          0          0          0          0          0                        
 (LEDs) TIMER1  2    2392850  03  19       1000        933       1067         43         41        112 2023/10/01,14:39:52.922
 (Enc2) TIMER3  4          0  0b   2          0          0          0          0          0          0                        
   (Mon) UART0  5          2  03  18    6667455        434  415817786         28         13         29 2023/10/01,14:39:52.855
   (VE1) UART1  6          0  0b   6          0          0          0          0          0          0                        
   (VE2) UART2  7          0  03   6          0          0          0          0          0          0 2023/09/12,10:18:42.620
   (VE3) UART3  8          0  0b   6          0          0          0          0          0          0                        
           RTC 17       2392  03   5    1000013     999987    1000040         41         34         63 2023/10/01,14:39:51.999
           NMI 18          0  0b   0          0          0          0          0          0          0 2023/09/11,11:32:24.844
  (Time) EINT1 19   11963581  03   1        200        198        202         20         19         22 2023/10/01,14:39:53.017
  (Enc1) EINT2 20          0  0b   2          0          0          0          0          0          0                        
 (Event) EINT3 21          0  0b   7          0          0          0          0          0          0 2023/09/11,11:32:24.832
          ENET 28     226691  03  24       9889         15     106792         13          8        128 2023/10/01,14:39:53.047
 (V/B/A) UART4 35          0  0b   6          0          0          0          0          0          0                        
          GPIO 38          0  0b  18          0          0          0          0          0          0                        
----------------------------------------------------------------------------------------------------
Task Name      ID      Count Flg Pri        Avg        Min        Max        Avg        Min        Max Last Start
          Init  1          5  03   0          0          0          0    1009616    1009437    1009623 2023/09/12,10:17:51.563
         Timer  2     239304  03 130      10000       9932      10068        300        276        473 2023/10/01,14:39:53.111
          File  3      23801  03  10     100220      99568     407107        232         28     307385 2023/10/01,14:39:53.038
       Monitor  4     237948  03   0      10000       9538     314555         27         18       1413 2023/10/01,14:39:52.858
           TCP  5     661775  03  50       3663         55       5520         79         29       1119 2023/10/01,14:39:53.153
        Serial  6      26087  03  40      90738         61     101397         85         49       1091 2023/10/01,14:39:53.141
      SPI UART  7     478619  03  60       5000       4931       5069         78         55        146 2023/10/01,14:39:53.176
       HP Insp  8    1196555  03 150       2000       1920       2079         11         10         79 2023/10/01,14:39:53.190
       LP Insp  9     478624  03 100       5000       4932       5068         15         13         77 2023/10/01,14:39:53.201
-
----------------------------------------------------------------------------------------------------
Total CPU Usage based off Idle Task Time in one second, Samples=10
Usage% Proc(us) Idle(us) Total(us)     @ Time       Dif   Index Idle Int  T2  T3  T4  T5  T6  T7  T8
 26.9,  268762,  731252,  1000014,    14:39:44,  0.000000, 180,  91,   0,  3,  0,  0,  1,  0,  0,  1
 26.9,  268522,  731492,  1000014,    14:39:45,  1.000000, 181,  83,   8,  2,  0,  0,  1,  0,  2,  0
 26.9,  268707,  731306,  1000013,    14:39:46,  1.000000, 182,  90,   0,  3,  0,  0,  2,  0,  0,  2
 26.9,  268596,  731443,  1000039,    14:39:47,  1.000000, 183,  84,   6,  2,  0,  0,  2,  0,  2,  0
 26.9,  268720,  731268,   999988,    14:39:48,  1.000000, 184,  88,   2,  3,  0,  0,  2,  0,  0,  2
 26.9,  268735,  731279,  1000014,    14:39:49,  1.000000, 185,  86,   4,  2,  0,  0,  2,  0,  2,  0
 26.9,  268992,  731021,  1000013,    14:39:50,  1.000000, 186,  86,   4,  3,  0,  0,  2,  0,  0,  2
 26.9,  268796,  731219,  1000015,    14:39:51,  1.000000, 187,  89,   2,  2,  0,  0,  1,  0,  1,  0
 26.9,  269012,  731027,  1000039,    14:39:52,  1.000000, 188,  84,   6,  3,  0,  0,  2,  0,  0,  2
 37.1,  371013,  628974,   999987,    14:39:53,  1.000000, 189,  78,   0,  2,  0, 13,  2,  0,  1,  0

I need all this functionality that is in the stat command to do troubleshooting at our customers sites.
We try to test our custom software the best we can on the hardware we have available, but sometimes issues
can only be duplicated at a customer site.

We can not plug in a pod to debug through the code. We meed to have all the tools needed for troubleshooting
in the final application.

We have a program logging system for high speed system file logs.
We also have a logic analyzer that used the high speed capability of our FPGA to get traces and events to trigger on issues.

We are in the process of porting this NXP Cortex-M3 Keil 4 application to the STMicro Cortex-M7 Keil 5 application.

This is what I have at the moment for the stat command in the Keil 5 application.

I very much love that you now keep track of free stack space in all tasks.

Number of Threads = 7, ID=0x20010F68
Idx=0, ID=0x20010F68, Name=      cmdline_Thread, St=2, Size=2048, Space=1128, pri=24
Idx=1, ID=0x20011430, Name=         Idle_Thread, St=1, Size= 256, Space= 184, pri= 1
Idx=2, ID=0x200114FC, Name=      netEth0_Thread, St=3, Size=1024, Space= 512, pri=43
Idx=3, ID=0x20010F24, Name=      appmain_Thread, St=3, Size=1024, Space= 796, pri=24
Idx=4, ID=0x20010EE0, Name=     initmain_Thread, St=3, Size=2048, Space=1112, pri=24
Idx=5, ID=0x20011474, Name=        Timer_Thread, St=3, Size=1024, Space= 772, pri=48
Idx=6, ID=0x200114B8, Name=      netCore_Thread, St=3, Size=1024, Space= 728, pri=46
                                               |          Period (us)           |            Duration (us)
IRQ Name                 ID      Count Flg Pri |      Avg        Min        Max |      Avg        Min        Max
            SysTick_IRQn  -1          0  0b  15          0          0          0          0          0          0
          HardFault_IRQn -13          0  0b   0          0          0          0          0          0          0
           BusFault_IRQn -11          1  0b   0          0          0          0          0          0          0
         UsageFault_IRQn -10          3  0b   0          0          0          0          0          0          0
     NonMaskableInt_IRQn -14          0  0b   0          0          0          0          0          0          0
     (PWR)    EXTI0_IRQn   6          0  0b   0          0          0          0          0          0          0
     (5Khz)   EXTI1_IRQn   7      20504  03   0        200        199        201          5          3          5
     (Events) EXTI2_IRQn   8          0  0b   2          0          0          0          0          0          0
              EXTI3_IRQn   9          0  00   0          0          0          0          0          0          0
              EXTI4_IRQn  10          0  00   0          0          0          0          0          0          0
            EXTI9_5_IRQn  23          0  00   0          0          0          0          0          0          0
      (1ms) TIM1_UP_IRQn  25       4077  03   5       1006        999       1014          6          6         14
    (Enc) EXTI15_10_IRQn  40          0  00   0          0          0          0          0          0          0
             SDMMC1_IRQn  49          0  00   0          0          0          0          0          0          0
                ETH_IRQn  61         71  03  10      70177         12     319147         10          9         19

Cmd>

https://community.arm.com/support-forums/f/keil-forum/32966/how-to-set-interrupt-priorities-in-cmsis-rtos-rtx
Below is quote from link above.
"the CMSIS-RTOS RTX kernel apparently does not disable interrupts explicitly. Instead, the atomic execution of critical sections
is implemented as the SVC (Supervisor Call) exception, which runs at priority higher than any task."

Keil sets SysTick to the lowest priority 15, but it uses the supervisor calls to do critical sections in the kernel.
What is the latency of these critical sections.

I need to know how much my 5Khz interrupt can vary.
See data above it is Avg 200, min=199, max=201.

Can we get access to add some small methods into the SysTick_Handler and All exception handlers.

This is one implemenation that I did for the Hard_Fault.

void HardFault_Handler(void)
{
  /* USER CODE BEGIN HardFault_IRQn 0 */
  startIRQTask(&bburam.IRQDataList[HARDFAULT_IRQ_NAME_IDX]);
  /* USER CODE END HardFault_IRQn 0 */
  while (1)
  {
    /* USER CODE BEGIN W1_HardFault_IRQn 0 */
    CIOB_HardFault_Handler();
    /* USER CODE END W1_HardFault_IRQn 0 */
  }
}


void CIOB_HardFault_Handler(void)
{
  InFaultHandler = TRUE;
  uint32_t loop_count = LED_FAULT_LOOP_CNT;
  printf("\nException %s has occurred, Check CIOB_Fault.log...\n\n", reset_names[CIOBRST_HARD_FAULT]);
  while (1)
  {
    HAL_GPIO_WritePin(GPIOK, ALL_LEDS_MASK, GPIO_PIN_RESET);

    HAL_GPIO_WritePin(GPIOK, HF_LED_PATTERN, GPIO_PIN_SET);
    HAL_Delay(LED_FAULT_DELAY);
    print_dot();
    HAL_GPIO_WritePin(GPIOK, HF_LED_PATTERN << 4, GPIO_PIN_SET);
    HAL_Delay(LED_FAULT_DELAY);
    print_dot();
    if (--loop_count == 0)
    {
      break;
    }
  }
  if (bbu_ram_present)
  {
    LogFaultData = &BBR.HardFault_Handler_Data;
#ifdef _INSP_CODE
    set_CatAlarmPin(DG_CPU_HARD_FAULT);
    proc_PLC_Outputs();
#endif //_INSP_CODE
  }
  else
    LogFaultData = &LocalFaultData;
 
  LogFaultData->current_sp  = __current_sp();
  LogFaultData->ret_addr    = __return_address();
  LogFaultData->PSP         = __get_PSP();
  LogFaultData->MSP         = __get_MSP();
  save_fault_data(LogFaultData);
  memset(logMsgStr,0,sizeof(logMsgStr));
  print_HardFaultData(LogFaultData, logMsgStr, sizeof(logMsgStr), TRUE, TRUE);
  printf("%s",logMsgStr);

  IncTimeStampCounter(&BBR.LifeCtrList[LCI_HARD_FAULT]);  

  cpu_manual_reset(CIOBRST_HARD_FAULT);    
}


Bottom line is I need to create a Windows Task Manager Prefomance tab for all active Interrupts and Threads.

Any help to achieve this goal would be very much appreciated.

Regards,
David Petersen
petersen@filtec.com
310-766-6319 Cell