-
Notifications
You must be signed in to change notification settings - Fork 155
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add script to profile via qemu and gdb. Simple mixer profile example
- Loading branch information
1 parent
bb55f80
commit 2316ebf
Showing
5 changed files
with
126 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,51 @@ | ||
#include <libopencm3/stm32/gpio.h> | ||
#include <libopencm3/stm32/rcc.h> | ||
#include <libopencm3/cm3/scb.h> | ||
#include <libopencm3/cm3/systick.h> | ||
#include "common.h" | ||
#include "mixer.h" | ||
#include "config/tx.h" | ||
#include "config/model.h" | ||
#include "../common/devo/devo.h" | ||
|
||
void run_profile(); | ||
void init_profile(); | ||
int main() | ||
{ | ||
SCB_VTOR = VECTOR_TABLE_LOCATION; | ||
SCB_SCR &= ~SCB_SCR_SLEEPONEXIT; //sleep immediate on WFI | ||
rcc_clock_setup_in_hse_8mhz_out_72mhz(); | ||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); | ||
systick_set_reload(0x00FFFFFF); | ||
systick_counter_enable(); | ||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); | ||
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ, | ||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); | ||
gpio_clear(GPIOC, GPIO12); | ||
gpio_set(GPIOC, GPIO12); | ||
gpio_clear(GPIOC, GPIO12); | ||
|
||
init_profile(); | ||
run_profile(); | ||
} | ||
|
||
void init_profile() { | ||
for (int i = 0; i < INP_HAS_CALIBRATION; i++) | ||
{ | ||
Transmitter.calibration[i].min = CHAN_MIN_VALUE; | ||
Transmitter.calibration[i].max = CHAN_MAX_VALUE; | ||
Transmitter.calibration[i].zero = 0; | ||
} | ||
memset(Model.mixers, 0, sizeof(Model.mixers)); | ||
for (unsigned i = 0; i < 1; i++) { | ||
Model.mixers[i].src = 1; | ||
Model.mixers[i].dest = (2 + i) % 5; | ||
Model.mixers[i].scalar = 100; | ||
Model.mixers[i].flags = MUX_REPLACE; | ||
} | ||
Model.num_channels = 12; | ||
} | ||
|
||
void __attribute__ ((noinline)) run_profile() { | ||
MIXER_CalcChannels(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# This script will profile the qemu.bin build and produce a calltrace log | ||
# It is meant to be loaded from within gdb via: | ||
# arm-none-eabi-gdb-py | ||
# source gdb | ||
# profile | ||
# An STM32 QEMU is needed (either docker or natively compiled): https://github.com/beckus/qemu_stm32 | ||
# QEMU is started before running gdb via: | ||
# qemu-system-arm -S -s -M stm32-p103 -kernel qemu.bin | ||
|
||
import gdb | ||
|
||
compress = True | ||
|
||
class func: | ||
def __init__(self, parent, pc, lr, name): | ||
self.exclusive = 0 | ||
self.parent = parent | ||
self.pc = pc | ||
self.lr = lr | ||
self.children = [] | ||
self.name = name | ||
def newchild(self, pc, lr, name): | ||
if compress: | ||
for child in self.children: | ||
if child.pc == pc: | ||
child.lr = lr | ||
return child | ||
newfunc = func(self, pc, lr, name) | ||
self.children.append(newfunc) | ||
return newfunc | ||
|
||
def printstack(trace, depth=""): | ||
inclusive = trace.exclusive | ||
childstr = "" | ||
for child in trace.children: | ||
_str, incl = printstack(child, depth + " ") | ||
childstr += _str | ||
inclusive += incl | ||
childstr = "{}{} 0x{:02x} (ex:{} inc:{})\n".format(depth, trace.name, trace.pc, trace.exclusive, inclusive) + childstr | ||
if depth == "": | ||
print childstr | ||
else: | ||
return childstr, inclusive | ||
|
||
topfunc = func(None, 0, 0, None) | ||
|
||
class Profile(gdb.Command): | ||
def __init__(self): | ||
# This registers our class as "simple_command" | ||
super(Profile, self).__init__("profile", gdb.COMMAND_DATA) | ||
gdb.execute("file qemu.elf") | ||
gdb.execute("target remote localhost:1234") | ||
gdb.execute("set pagination off") | ||
self.trace = topfunc | ||
|
||
def invoke(self, arg, from_tty): | ||
# When we call "simple_command" from gdb, this is the method | ||
# that will be called. | ||
#gdb.execute("set logging file /dev/null") | ||
#gdb.execute("set logging redirect on") | ||
#gdb.execute("set logging on") | ||
gdb.execute("b run_profile") | ||
gdb.execute("c") | ||
gdb.execute("disable") | ||
stop_pc = gdb.newest_frame().older().pc() | ||
|
||
last_lr = int(gdb.parse_and_eval('$lr'))-1 | ||
while True: | ||
frame = gdb.newest_frame() | ||
pc = frame.pc() | ||
lr = int(gdb.parse_and_eval('$lr'))-1 | ||
if pc == self.trace.lr: | ||
print "Returned from {:02x}".format(self.trace.pc) | ||
self.trace = self.trace.parent | ||
#return | ||
elif lr != last_lr: | ||
self.trace = self.trace.newchild(pc, lr, frame.name()) | ||
print "Called {}{:02x} (return: {:02x})".format(frame.name(), pc, lr) | ||
#return | ||
if pc == 0 or pc == stop_pc: | ||
break; | ||
self.trace.exclusive += 1 | ||
last_lr = lr | ||
gdb.execute("si") | ||
#gdb.execute("set logging off") | ||
#gdb.execute("display") | ||
printstack(topfunc) | ||
|
||
Profile() |