klonyyy / MCUViewer

Real-time embedded variable & trace viewer
GNU General Public License v3.0
802 stars 80 forks source link

Counter Plotting #45

Closed Mezamoha closed 6 months ago

Mezamoha commented 6 months ago

Hello,

I would like to thank you for the great software.

I have a question :

I tried to profile some function and counters and it works well for example

while(1){
ITM->PORT[0].u32 = size;
size++;
}

And the plot is as expected

image_2024-04-24_105301500

but when i tried to plot a cycle counter

while(1){
ITM->PORT[0].u32 = DWT->CYCCNT;
}

i get a fixed value so i'm not able to see the progression of this counter

image_2024-04-24_105554230

I would like to know if there is any solution or method to be able to get the correct plotting

Thanks a lot

klonyyy commented 6 months ago

Hello, this might be because DWT registers are altered during trace setup. The DWT might be used by the ITM peripheral (as far as I remember it is not used currently). Do you set up the counter by yourself in your code? Why do you want to display the cycles count?

Mezamoha commented 6 months ago

Thank you for your answer

In fact i'm interested in monitoring real-time counters such as LSUCNT, CPICNT, EXCCNT with Stmviewer. Here is my c code that i'm using with Stmviewer. The purpose is to know how those counters are impacted by our application. Is it possible to monitor these counters with Stmviewer in real-time ?

#include "core_cm4.h" 

void DWT_Init(void) {
    CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
    DWT->CTRL |= (DWT_CTRL_CYCCNTENA_Msk | DWT_CTRL_CPIEVTENA_Msk | DWT_CTRL_LSUEVTENA_Msk | DWT_CTRL_EXCEVTENA_Msk);
}

volatile void ITM_SendData(int port, unsigned int data) {
    while (ITM->PORT[port].u32 == 0);
    ITM->PORT[port].u32 = data;
}

void Send_DWT_Counters(void) {
    unsigned int cycles = DWT->CYCCNT;
    unsigned int cpi_count = DWT->CPICNT;
    unsigned int lsu_count = DWT->LSUCNT;
    unsigned int exc_count = DWT->EXCCNT;

    ITM_SendData(0, cycles);
    ITM_SendData(1, cpi_count);
    ITM_SendData(2, lsu_count);
    ITM_SendData(3, exc_count);
}

int main(void) {
    ITM_Init();
    DWT_Init();

    while (1) {
        Send_DWT_Counters();
    }
}
klonyyy commented 6 months ago

The main problem is that STMViewer's Trace Viewer module uses the ITM and DWT. If you do not need a synchronous output of the data I'd use the Variable Viewer and just assign these counter values to some global variables and plot them. This way you'll be able to read the counters in real time.

The Trace Viewer aims to be automatic (it sets up the registers by itself), this is why interfering with ITM and DWT in your application results in faulty output.

Mezamoha commented 6 months ago

Thank you for the clarifications.

I'll try the solution with the variable counters.

And if can i ask you more please ? I'm interested to know how i can access to those counters via ITM without writing them in my code (since TraceViewer set them automatically)

i suppose that this solution will be suitable in term of overhead

Thanks again

klonyyy commented 6 months ago

Actually the Trace Viewer does not utilize these counters. You can do it by hand in your application, just the display part in STMViewer should be done using VariableViewer, as it does not change the ITM settings.

Mezamoha commented 6 months ago

Great. Thanks a lot Have a good day