From 45337262149a4b300c53972ef71859c202e5966a Mon Sep 17 00:00:00 2001 From: Oliver Hahm Date: Mon, 31 Jan 2011 18:25:20 +0100 Subject: [PATCH] * introduced energy profiling (yet in a very early state) --- board/msba2-common/drivers/msba2-ltc4150.c | 8 +- cpu/arm_common/Jamfile | 5 + cpu/arm_common/Jamrules.arm_common | 5 + cpu/arm_common/profiling.c | 109 +++++++++++++++++++++ cpu/lpc2387/lpc2387-gpioint.c | 4 +- drivers/Jamfile | 2 +- drivers/include/ltc4150.h | 1 + drivers/ltc4150.c | 10 +- sys/auto_init.c | 4 + 9 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 cpu/arm_common/profiling.c diff --git a/board/msba2-common/drivers/msba2-ltc4150.c b/board/msba2-common/drivers/msba2-ltc4150.c index c590dee8d..4e6534c02 100644 --- a/board/msba2-common/drivers/msba2-ltc4150.c +++ b/board/msba2-common/drivers/msba2-ltc4150.c @@ -45,19 +45,19 @@ and the mailinglist (subscription via web site) #include "ltc4150_arch.h" #include "gpioint.h" -void ltc4150_disable_int(void) { +void __attribute__((__no_instrument_function__)) ltc4150_disable_int(void) { gpioint_set(0, BIT4, GPIOINT_DISABLE, NULL); } -void ltc4150_enable_int(void) { +void __attribute__((__no_instrument_function__)) ltc4150_enable_int(void) { gpioint_set(0, BIT4, GPIOINT_FALLING_EDGE, <c4150_interrupt); } -void ltc4150_sync_blocking(void) { +void __attribute__((__no_instrument_function__)) ltc4150_sync_blocking(void) { while(!(FIO0PIN & BIT4)) {}; } -void ltc4150_arch_init() { +void __attribute__((__no_instrument_function__)) ltc4150_arch_init() { FIO0DIR |= BIT5; FIO0SET = BIT5; } diff --git a/cpu/arm_common/Jamfile b/cpu/arm_common/Jamfile index 0252c7578..1889eef63 100644 --- a/cpu/arm_common/Jamfile +++ b/cpu/arm_common/Jamfile @@ -30,6 +30,11 @@ SubDir TOP cpu arm_common ; Module arm_common : common.s bootloader.c VIC.c atomic.s arm_cpu.c iap.c ; UseModule arm_common ; +Module profiling : profiling.c ; +if $(PROFILING) { + UseModule profiling ; +} + Module hwtimer_cpu : hwtimer_cpu.c ; Objects syscalls.c ; diff --git a/cpu/arm_common/Jamrules.arm_common b/cpu/arm_common/Jamrules.arm_common index dac4bff7d..afb14fa24 100644 --- a/cpu/arm_common/Jamrules.arm_common +++ b/cpu/arm_common/Jamrules.arm_common @@ -40,9 +40,14 @@ LINK = $(CC) ; OPTIM = -Os ; #OPTIM = -O0 -g ; + CCFLAGS += -std=gnu99 -Wall -mcpu=arm7tdmi-s -mfloat-abi=soft -mfpu=vfp ; LINKFLAGS = -mcpu=arm7tdmi-s -static -lgcc -nostartfiles -T [ FPath $(TOP) cpu $(CPU) linkerscript.x ] ; +if $(PROFILING) = 1 { + CCFLAGS += -g -finstrument-functions ; +} + AS = $(TOOLCHAIN)as ; ASFLAGS += -mcpu=arm7tdmi-s --defsym $(CPU)=1 -mfloat-abi=soft -mfpu=vfp ; diff --git a/cpu/arm_common/profiling.c b/cpu/arm_common/profiling.c new file mode 100644 index 000000000..8bbe2c0ed --- /dev/null +++ b/cpu/arm_common/profiling.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#define MAX_TRACED_FUNCTIONS (32) +#define PROFILING_STACK_SIZE (16) + +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]; +static uint8_t profiling_stack[PROFILING_STACK_SIZE]; +static uint8_t profiling_sp = 0; + +static uint8_t traced_functions = 0; +static uint8_t profiling = 0; + +void __attribute__((__no_instrument_function__)) profiling_init(void) { + uint8_t i; + for (i = 0; i < MAX_TRACED_FUNCTIONS; i++) { + functions[i].address = 0; + functions[i].time = 0; + functions[i].consumption = 0; + functions[i].counter = 0; + } + for (i = 0; i < PROFILING_STACK_SIZE; i++) { + profiling_stack[i] = 0; + } + + ltc4150_start(); + + profiling = 1; +} + +static int16_t __attribute__((__no_instrument_function__)) get_function_index(uint32_t addr) { + uint8_t i; + for (i = 0; i < MAX_TRACED_FUNCTIONS; i++) { + if (functions[i].address == addr) { + return i; + } + } + return -1; +} + +void __attribute__((__no_instrument_function__)) __cyg_profile_func_enter (void *func, void *caller) { + if (!profiling) { + return; + } + /* + uint8_t i; + int16_t idx = -1; + for (i = 0; i < MAX_TRACED_FUNCTIONS; i++) { + if (functions[i].address == (uint32_t) func) { + idx = i; + break; + } + } + */ + uint8_t idx = get_function_index((uint32_t) func); + if ((idx < 0) && (traced_functions < MAX_TRACED_FUNCTIONS)) { + idx = traced_functions++; + functions[idx].address = (uint32_t) func; + } + else if (idx < 0) { + return; + } + functions[idx].start_time = T0TC; + functions[idx].counter++; + functions[idx].consumption_start = ltc4150_get_total_mAh(); + // functions[idx].consumption_start = ltc4150_get_intcount(); +} + +void __attribute__((__no_instrument_function__)) __cyg_profile_func_exit (void *func, void *caller) { + if (!profiling) { + return; + } + /* + uint8_t i; + int16_t idx = -1; + for (i = 0; i < MAX_TRACED_FUNCTIONS; i++) { + if (functions[i].address == (uint32_t) func) { + idx = i; + break; + } + } + */ + uint8_t idx = get_function_index((uint32_t) func); + if (idx >= 0) { + 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; + } +} + +void profiling_stats(void) { + uint8_t i; + for (i = 0; i < traced_functions; i++) { +// 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); + } + puts("________________________________________________________"); +} diff --git a/cpu/lpc2387/lpc2387-gpioint.c b/cpu/lpc2387/lpc2387-gpioint.c index e33fc854a..7ce594141 100644 --- a/cpu/lpc2387/lpc2387-gpioint.c +++ b/cpu/lpc2387/lpc2387-gpioint.c @@ -123,7 +123,7 @@ gpioint_set(int port, uint32_t bitmask, int flags, fp_irqcb callback) return true; // success } /*---------------------------------------------------------------------------*/ -static void test_irq(int port, unsigned long f_mask, unsigned long r_mask, struct irq_callback* pcb) +static void __attribute__ ((__no_instrument_function__)) test_irq(int port, unsigned long f_mask, unsigned long r_mask, struct irq_callback* pcb) { /* Test each bit of rising and falling masks, if set trigger interrupt * on corresponding device */ @@ -148,7 +148,7 @@ void GPIO_IRQHandler(void) __attribute__((interrupt("IRQ"))); * Invoked whenever an activated gpio interrupt is triggered by a rising * or falling edge. */ -void GPIO_IRQHandler(void) { +void __attribute__ ((__no_instrument_function__)) GPIO_IRQHandler(void) { if( IO_INT_STAT & BIT0 ) { // interrupt(s) on PORT0 pending unsigned long int_stat_f = IO0_INT_STAT_F; // save content unsigned long int_stat_r = IO0_INT_STAT_R; // save content diff --git a/drivers/Jamfile b/drivers/Jamfile index 9713df17f..3dbeed6d7 100644 --- a/drivers/Jamfile +++ b/drivers/Jamfile @@ -29,7 +29,7 @@ SubDir TOP drivers ; Module sht11 : sht11.c : hwtimer ; -Module ltc4150 : ltc4150.c : board_ltc4150 ; +Module ltc4150 : ltc4150.c : board_ltc4150 hwtimer ; SubInclude TOP drivers cc110x ; SubInclude TOP drivers cc110x_ng ; diff --git a/drivers/include/ltc4150.h b/drivers/include/ltc4150.h index 88160c891..4a3c05515 100644 --- a/drivers/include/ltc4150.h +++ b/drivers/include/ltc4150.h @@ -11,5 +11,6 @@ double ltc4150_get_current_mA(); double ltc4150_get_total_mAh(); double ltc4150_get_avg_mA(); int ltc4150_get_interval(); +long ltc4150_get_intcount(void); #endif /* __LTC4150_H */ diff --git a/drivers/ltc4150.c b/drivers/ltc4150.c index 7c50553a8..947265f6a 100644 --- a/drivers/ltc4150.c +++ b/drivers/ltc4150.c @@ -46,11 +46,11 @@ static unsigned int last_int_time; static unsigned int last_int_duration; static unsigned int start_time; -static double int_to_coulomb(int ints) { +static double __attribute__((__no_instrument_function__)) int_to_coulomb(int ints) { return ((double)ints) / (_GFH * _R_SENSE); } -static double coulomb_to_mA(double coulomb){ +static double __attribute__((__no_instrument_function__)) coulomb_to_mA(double coulomb){ return (coulomb * 1000) / 3600; } @@ -62,7 +62,7 @@ double ltc4150_get_current_mA() { return 1000000000/(ltc4150_get_last_int_duration_us()*(_GFH * _R_SENSE)); } -double ltc4150_get_total_mAh() { +double __attribute__((__no_instrument_function__)) ltc4150_get_total_mAh() { return coulomb_to_mA(int_to_coulomb(int_count)); } @@ -74,7 +74,7 @@ int ltc4150_get_interval() { return HWTIMER_TICKS_TO_US(last_int_time - start_time); } -unsigned long ltc4150_get_intcount() { +unsigned long __attribute__((__no_instrument_function__)) ltc4150_get_intcount() { return int_count; } @@ -96,7 +96,7 @@ void ltc4150_stop() { ltc4150_disable_int(); } -void ltc4150_interrupt() +void __attribute__((__no_instrument_function__)) ltc4150_interrupt() { uint32_t now = hwtimer_now(); if (now >= last_int_time) { diff --git a/sys/auto_init.c b/sys/auto_init.c index e9e7a4d48..c142d7ef3 100644 --- a/sys/auto_init.c +++ b/sys/auto_init.c @@ -52,6 +52,10 @@ void auto_init(void) { #ifdef MODULE_LTC4150 DEBUG("Auto init ltc4150 module.\n"); ltc4150_init(); +#endif +#ifdef MODULE_PROFILING + extern void profiling_init(void); + profiling_init(); #endif main(); }