Cycle counter on ARM Cortex M4 (or M3)?

前端 未结 5 1772
陌清茗
陌清茗 2020-12-03 00:13

I\'m trying to profile a C function (which is called from an interrupt, but I can extract it and profile it elsewhere) on a Cortex M4.

What are the possibilities to

5条回答
  •  孤城傲影
    2020-12-03 00:41

    Expanding previous answers with a DWT_CYCCNT example (STM32) in main (similar to my other post).

    Note: I added a delay method as well. You can verify stopwatch_delay by calling STOPWATCH_START, run stopwatch_delay(ticks), then call STOPWATCH_STOP and verify with CalcNanosecondsFromStopwatch(m_nStart, m_nStop). Adjust ticks as needed.

    uint32_t m_nStart;               //DEBUG Stopwatch start cycle counter value
    uint32_t m_nStop;                //DEBUG Stopwatch stop cycle counter value
    
    #define DEMCR_TRCENA    0x01000000
    
    /* Core Debug registers */
    #define DEMCR           (*((volatile uint32_t *)0xE000EDFC))
    #define DWT_CTRL        (*(volatile uint32_t *)0xe0001000)
    #define CYCCNTENA       (1<<0)
    #define DWT_CYCCNT      ((volatile uint32_t *)0xE0001004)
    #define CPU_CYCLES      *DWT_CYCCNT
    #define CLK_SPEED         168000000 // EXAMPLE for CortexM4, EDIT as needed
    
    #define STOPWATCH_START { m_nStart = *((volatile unsigned int *)0xE0001004);}
    #define STOPWATCH_STOP  { m_nStop = *((volatile unsigned int *)0xE0001004);}
    
    
    static inline void stopwatch_reset(void)
    {
        /* Enable DWT */
        DEMCR |= DEMCR_TRCENA; 
        *DWT_CYCCNT = 0;             
        /* Enable CPU cycle counter */
        DWT_CTRL |= CYCCNTENA;
    }
    
    static inline uint32_t stopwatch_getticks()
    {
        return CPU_CYCLES;
    }
    
    static inline void stopwatch_delay(uint32_t ticks)
    {
        uint32_t end_ticks = ticks + stopwatch_getticks();
        while(1)
        {
                if (stopwatch_getticks() >= end_ticks)
                        break;
        }
    }
    
    uint32_t CalcNanosecondsFromStopwatch(uint32_t nStart, uint32_t nStop)
    {
        uint32_t nDiffTicks;
        uint32_t nSystemCoreTicksPerMicrosec;
    
        // Convert (clk speed per sec) to (clk speed per microsec)
        nSystemCoreTicksPerMicrosec = CLK_SPEED / 1000000;
    
        // Elapsed ticks
        nDiffTicks = nStop - nStart;
    
        // Elapsed nanosec = 1000 * (ticks-elapsed / clock-ticks in a microsec)
        return 1000 * nDiffTicks / nSystemCoreTicksPerMicrosec;
    } 
    
    void main(void)
    {
        int timeDiff = 0;
        stopwatch_reset();
    
        // =============================================
        // Example: use a delay, and measure how long it took
        STOPWATCH_START;
        stopwatch_delay(168000); // 168k ticks is 1ms for 168MHz core
        STOPWATCH_STOP;
    
        timeDiff = CalcNanosecondsFromStopwatch(m_nStart, m_nStop);
        printf("My delay measured to be %d nanoseconds\n", timeDiff);
    
        // =============================================
        // Example: measure function duration in nanosec
        STOPWATCH_START;
        // run_my_function() => do something here
        STOPWATCH_STOP;
    
        timeDiff = CalcNanosecondsFromStopwatch(m_nStart, m_nStop);
        printf("My function took %d nanoseconds\n", timeDiff);
    }
    

提交回复
热议问题