2011-01-31 18:25:20 +01:00
# include <stdio.h>
# include <stdint.h>
# include <cpu.h>
# include <ltc4150.h>
2011-12-28 11:18:11 +01:00
# define MAX_TRACED_FUNCTIONS (256)
# define PROFILING_STACK_SIZE (256)
2011-01-31 18:25:20 +01:00
typedef struct {
uint32_t address ;
uint32_t time ;
uint32_t start_time ;
double consumption ;
double consumption_start ;
uint16_t counter ;
} profiling_info_t ;
static profiling_info_t functions [ MAX_TRACED_FUNCTIONS ] ;
2011-12-28 11:18:11 +01:00
static uint16_t profiling_stack [ PROFILING_STACK_SIZE ] ;
static uint16_t profiling_sp = 0 ;
static uint8_t function_pending = 0 ;
2011-01-31 18:25:20 +01:00
2011-12-28 11:18:11 +01:00
static uint16_t traced_functions = 0 ;
2011-01-31 18:25:20 +01:00
static uint8_t profiling = 0 ;
2013-06-21 03:52:57 +02:00
void __attribute__ ( ( __no_instrument_function__ ) ) profiling_init ( void )
{
2011-12-28 11:18:11 +01:00
uint16_t i ;
2013-06-21 03:52:57 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < MAX_TRACED_FUNCTIONS ; i + + ) {
2011-01-31 18:25:20 +01:00
functions [ i ] . address = 0 ;
functions [ i ] . time = 0 ;
functions [ i ] . consumption = 0 ;
functions [ i ] . counter = 0 ;
}
2013-06-21 03:52:57 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < PROFILING_STACK_SIZE ; i + + ) {
2011-01-31 18:25:20 +01:00
profiling_stack [ i ] = 0 ;
}
ltc4150_start ( ) ;
2013-06-21 03:52:57 +02:00
2011-01-31 18:25:20 +01:00
profiling = 1 ;
}
2013-06-21 03:52:57 +02:00
static int16_t __attribute__ ( ( __no_instrument_function__ ) ) get_function_index ( uint32_t addr )
{
2011-12-28 11:18:11 +01:00
uint16_t i ;
2013-06-21 03:52:57 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < MAX_TRACED_FUNCTIONS ; i + + ) {
if ( functions [ i ] . address = = addr ) {
2011-01-31 18:25:20 +01:00
return i ;
}
}
2013-06-21 03:52:57 +02:00
2011-01-31 18:25:20 +01:00
return - 1 ;
}
2013-06-21 03:52:57 +02:00
void __attribute__ ( ( __no_instrument_function__ ) ) __cyg_profile_func_enter ( void * func , void * caller )
{
2013-06-24 22:37:35 +02:00
if ( ! profiling ) {
2011-01-31 18:25:20 +01:00
return ;
}
2013-06-21 03:52:57 +02:00
2011-01-31 18:36:06 +01:00
int16_t idx = get_function_index ( ( uint32_t ) func ) ;
2013-06-21 03:52:57 +02:00
2011-12-28 11:18:11 +01:00
/* if function is not yet on traced */
2013-06-24 22:37:35 +02:00
if ( ( idx < 0 ) & & ( traced_functions < MAX_TRACED_FUNCTIONS ) ) {
2011-01-31 18:25:20 +01:00
idx = traced_functions + + ;
functions [ idx ] . address = ( uint32_t ) func ;
}
2011-12-28 11:18:11 +01:00
/* maximu of traceable functions reached */
2013-06-24 22:37:35 +02:00
else if ( idx < 0 ) {
2011-01-31 18:25:20 +01:00
return ;
}
2011-12-28 11:18:11 +01:00
/* check if a profiled function is pending */
2013-06-24 22:37:35 +02:00
if ( function_pending & & ( profiling_stack [ profiling_sp ] ! = idx ) ) {
2011-12-28 11:18:11 +01:00
functions [ idx ] . time + = T0TC - functions [ idx ] . start_time ;
//functions[idx].consumption += ltc4150_get_intcount() - functions[idx].consumption_start;
functions [ idx ] . consumption + = ltc4150_get_total_mAh ( ) - functions [ idx ] . consumption_start ;
}
/* push current function on profile stack */
profiling_sp + + ;
profiling_stack [ profiling_sp ] = idx ;
/* save stats for current function */
2011-01-31 18:25:20 +01:00
functions [ idx ] . start_time = T0TC ;
functions [ idx ] . counter + + ;
functions [ idx ] . consumption_start = ltc4150_get_total_mAh ( ) ;
// functions[idx].consumption_start = ltc4150_get_intcount();
}
2013-06-21 03:52:57 +02:00
void __attribute__ ( ( __no_instrument_function__ ) ) __cyg_profile_func_exit ( void * func , void * caller )
{
2013-06-24 22:37:35 +02:00
if ( ! profiling ) {
2011-01-31 18:25:20 +01:00
return ;
}
2013-06-21 03:52:57 +02:00
2011-01-31 18:36:06 +01:00
int16_t idx = get_function_index ( ( uint32_t ) func ) ;
2013-06-21 03:52:57 +02:00
2013-06-24 22:37:35 +02:00
if ( idx > = 0 ) {
2011-01-31 18:25:20 +01:00
functions [ idx ] . time + = T0TC - functions [ idx ] . start_time ;
//functions[idx].consumption += ltc4150_get_intcount() - functions[idx].consumption_start;
functions [ idx ] . consumption + = ltc4150_get_total_mAh ( ) - functions [ idx ] . consumption_start ;
}
2013-06-21 03:52:57 +02:00
2011-12-28 11:18:11 +01:00
/* reset pending flag */
function_pending = 0 ;
2013-06-21 03:52:57 +02:00
2011-12-28 11:18:11 +01:00
/* if another function is pending */
2013-06-24 22:37:35 +02:00
if ( profiling_sp ) {
if ( - - profiling_sp ) {
2011-12-28 11:18:11 +01:00
functions [ profiling_stack [ profiling_sp ] ] . start_time = T0TC ;
functions [ profiling_stack [ profiling_sp ] ] . consumption_start = ltc4150_get_total_mAh ( ) ;
}
}
2011-01-31 18:25:20 +01:00
}
2013-06-21 03:52:57 +02:00
void profiling_stats ( void )
{
2011-12-28 11:18:11 +01:00
uint16_t i ;
2013-06-21 03:52:57 +02:00
2013-06-24 22:37:35 +02:00
for ( i = 0 ; i < traced_functions ; i + + ) {
2013-06-21 03:52:57 +02:00
// printf("Function @%04lX was running %u times for %lu ticks, consuming %li ltc-ticks\n", functions[i].address, functions[i].counter, functions[i].time, functions[i].consumption);
printf ( " Function @%04lX was running %u times for %lu ticks, consuming %lf mAh \n " , functions [ i ] . address , functions [ i ] . counter , functions [ i ] . time , functions [ i ] . consumption ) ;
2011-01-31 18:25:20 +01:00
}
2013-06-21 03:52:57 +02:00
2011-01-31 18:25:20 +01:00
puts ( " ________________________________________________________ " ) ;
}