controller/Src/profiling.c

128 lines
3.6 KiB
C

/***********************************************************************
File Name : 'profiling.c'
Title : PROFILER
Description : Code time profiler with output to ITM Stimulus Port 0
Debug (printf) Viewer
Time accuracy 1µS
Examle output:
Profiling "Start" sequence:
--Event-----------------------|--timestamp--|---delta_t----
GLCD_Init : 41 us | + 41 us
OLED_Init : 5288 us | + 5247 us
u8g_SetFont : 5292 us | + 4 us
HAL_Delay(10) : 10004967 us | + 9999675 us
Author : Serj Bashlayev
https://github.com/Serj-Bashlayev
email: phreak_ua@yahoo.com
Created : 16/08/2016
Revised : 04/10/2018
Version : 3.0
Target MCU : STM32
Compiler : ARM Compiler v5.04 for µVision armcc
Editor Tabs : 2
***********************************************************************/
/* Includes ----------------------------------------------------------*/
#include "profiling.h"
/* Private Definitions -----------------------------------------------*/
#define DEBUG_PRINTF printf
#define __PROF_STOPED 0xFF
/* External variables ------------------------------------------------*/
/* Private variables -------------------------------------------------*/
static uint32_t time_start; // profiler start time
static const char *prof_name; // profiler name
static uint32_t time_event[MAX_EVENT_COUNT]; // events time
static const char *event_name[MAX_EVENT_COUNT]; // events name
static uint8_t event_count = __PROF_STOPED; // events counter
/* Private function prototypes ---------------------------------------*/
/* -------------------------------------------------------------------*/
/**
* redefinition fputc() for output printf(..) to ITM Stimulus Port 0
*/
struct __FILE { int handle; /* Add whatever needed */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
ITM_SendChar(ch);
return(ch);
}
/**
* @brief Start profiler, save profiler name and start time
*
* @param profile_name Profiler name
*/
void PROFILING_START(const char *profile_name)
{
prof_name = profile_name;
event_count = 0;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; // enable counter
//DWT->CYCCNT = time_start = 0;
time_start = DWT->CYCCNT;
}
/**
* @brief Event. Save events name and time
*
* @param event Event name
*/
void PROFILING_EVENT(const char *event)
{
if (event_count == __PROF_STOPED)
return;
if (event_count < MAX_EVENT_COUNT)
{
time_event[event_count] = DWT->CYCCNT;
event_name[event_count] = event;
event_count++;
}
}
/**
* @brief Stop profiler. Print event table to ITM Stimulus Port 0
*/
void PROFILING_STOP(void)
{
int32_t tick_per_1us;
int32_t time_prev;
int32_t timestamp;
int32_t delta_t;
tick_per_1us = SystemCoreClock / 1000000;
if (event_count == __PROF_STOPED)
{
DEBUG_PRINTF("\r\nWarning: PROFILING_STOP WITHOUT START.\r\n");
return;
}
DEBUG_PRINTF("Profiling \"%s\" sequence: \r\n"
"--Event-----------------------|--timestamp--|----delta_t---\r\n", prof_name);
time_prev = 0;
for (int i = 0; i < event_count; i++)
{
timestamp = (time_event[i] - time_start) / tick_per_1us;
delta_t = timestamp - time_prev;
time_prev = timestamp;
DEBUG_PRINTF("%-30s:%9d us | +%9d us\r\n", event_name[i], timestamp, delta_t);
}
DEBUG_PRINTF("\r\n");
event_count = __PROF_STOPED;
}