Skip to content

Commit 2316ebf

Browse files
Add script to profile via qemu and gdb. Simple mixer profile example
1 parent bb55f80 commit 2316ebf

5 files changed

Lines changed: 126 additions & 2 deletions

File tree

src/main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ void TOUCH_Handler(); // temporarily in main()
3636
void VIDEO_Update();
3737
void PAGE_Test();
3838

39-
int main() __attribute__((weak));
39+
#if defined (TEST) || defined (PROFILE)
40+
#define main _main
41+
#endif
4042

4143
#ifndef DUMP_BOOTLOADER
4244
int main() {

src/target/qemu/.target_main.c.swp

-12 KB
Binary file not shown.

src/target/qemu/Makefile.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ SRC_C := $(wildcard $(SDIR)/target/$(TARGET)/*.c) \
2727

2828
SRC_C := $(filter-out $(SDIR)/target/common/stm32/spi_flash.c, $(SRC_C))
2929

30-
CFLAGS = -D"assert_param(x)=" -DSTM32F10X_HD -DSTM32F1 -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fdata-sections -ffunction-sections -I$(SDIR)/target/common/devo/msc2/lib -I$(SDIR)/target/common/devo/msc2 -I$(SDIR)/libopencm3/include -I$(SDIR)/target/common/filesystems -fno-builtin-printf -Os --specs=nano.specs
30+
CFLAGS = -DPROFILE -D"assert_param(x)=" -DSTM32F10X_HD -DSTM32F1 -mcpu=cortex-m3 -mthumb -mfix-cortex-m3-ldrd -fdata-sections -ffunction-sections -I$(SDIR)/target/common/devo/msc2/lib -I$(SDIR)/target/common/devo/msc2 -I$(SDIR)/libopencm3/include -I$(SDIR)/target/common/filesystems -fno-builtin-printf -Os --specs=nano.specs
3131
MODULE_FLAGS = -fno-builtin
3232

3333
LFLAGS = -nostartfiles -Wl,-gc-sections -Wl,-Map=$(TARGET).map,--cref -lc -lnosys -L$(SDIR) -Lobjs/$(TARGET)

src/target/qemu/target_main.c

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,51 @@
11
#include <libopencm3/stm32/gpio.h>
22
#include <libopencm3/stm32/rcc.h>
33
#include <libopencm3/cm3/scb.h>
4+
#include <libopencm3/cm3/systick.h>
45
#include "common.h"
6+
#include "mixer.h"
7+
#include "config/tx.h"
8+
#include "config/model.h"
59
#include "../common/devo/devo.h"
610

11+
void run_profile();
12+
void init_profile();
713
int main()
814
{
915
SCB_VTOR = VECTOR_TABLE_LOCATION;
1016
SCB_SCR &= ~SCB_SCR_SLEEPONEXIT; //sleep immediate on WFI
1117
rcc_clock_setup_in_hse_8mhz_out_72mhz();
18+
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
19+
systick_set_reload(0x00FFFFFF);
20+
systick_counter_enable();
1221
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN);
1322
gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_50_MHZ,
1423
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
1524
gpio_clear(GPIOC, GPIO12);
1625
gpio_set(GPIOC, GPIO12);
1726
gpio_clear(GPIOC, GPIO12);
27+
28+
init_profile();
29+
run_profile();
30+
}
31+
32+
void init_profile() {
33+
for (int i = 0; i < INP_HAS_CALIBRATION; i++)
34+
{
35+
Transmitter.calibration[i].min = CHAN_MIN_VALUE;
36+
Transmitter.calibration[i].max = CHAN_MAX_VALUE;
37+
Transmitter.calibration[i].zero = 0;
38+
}
39+
memset(Model.mixers, 0, sizeof(Model.mixers));
40+
for (unsigned i = 0; i < 1; i++) {
41+
Model.mixers[i].src = 1;
42+
Model.mixers[i].dest = (2 + i) % 5;
43+
Model.mixers[i].scalar = 100;
44+
Model.mixers[i].flags = MUX_REPLACE;
45+
}
46+
Model.num_channels = 12;
47+
}
48+
49+
void __attribute__ ((noinline)) run_profile() {
50+
MIXER_CalcChannels();
1851
}

utils/qemu.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# This script will profile the qemu.bin build and produce a calltrace log
2+
# It is meant to be loaded from within gdb via:
3+
# arm-none-eabi-gdb-py
4+
# source gdb
5+
# profile
6+
# An STM32 QEMU is needed (either docker or natively compiled): https://github.com/beckus/qemu_stm32
7+
# QEMU is started before running gdb via:
8+
# qemu-system-arm -S -s -M stm32-p103 -kernel qemu.bin
9+
10+
import gdb
11+
12+
compress = True
13+
14+
class func:
15+
def __init__(self, parent, pc, lr, name):
16+
self.exclusive = 0
17+
self.parent = parent
18+
self.pc = pc
19+
self.lr = lr
20+
self.children = []
21+
self.name = name
22+
def newchild(self, pc, lr, name):
23+
if compress:
24+
for child in self.children:
25+
if child.pc == pc:
26+
child.lr = lr
27+
return child
28+
newfunc = func(self, pc, lr, name)
29+
self.children.append(newfunc)
30+
return newfunc
31+
32+
def printstack(trace, depth=""):
33+
inclusive = trace.exclusive
34+
childstr = ""
35+
for child in trace.children:
36+
_str, incl = printstack(child, depth + " ")
37+
childstr += _str
38+
inclusive += incl
39+
childstr = "{}{} 0x{:02x} (ex:{} inc:{})\n".format(depth, trace.name, trace.pc, trace.exclusive, inclusive) + childstr
40+
if depth == "":
41+
print childstr
42+
else:
43+
return childstr, inclusive
44+
45+
topfunc = func(None, 0, 0, None)
46+
47+
class Profile(gdb.Command):
48+
def __init__(self):
49+
# This registers our class as "simple_command"
50+
super(Profile, self).__init__("profile", gdb.COMMAND_DATA)
51+
gdb.execute("file qemu.elf")
52+
gdb.execute("target remote localhost:1234")
53+
gdb.execute("set pagination off")
54+
self.trace = topfunc
55+
56+
def invoke(self, arg, from_tty):
57+
# When we call "simple_command" from gdb, this is the method
58+
# that will be called.
59+
#gdb.execute("set logging file /dev/null")
60+
#gdb.execute("set logging redirect on")
61+
#gdb.execute("set logging on")
62+
gdb.execute("b run_profile")
63+
gdb.execute("c")
64+
gdb.execute("disable")
65+
stop_pc = gdb.newest_frame().older().pc()
66+
67+
last_lr = int(gdb.parse_and_eval('$lr'))-1
68+
while True:
69+
frame = gdb.newest_frame()
70+
pc = frame.pc()
71+
lr = int(gdb.parse_and_eval('$lr'))-1
72+
if pc == self.trace.lr:
73+
print "Returned from {:02x}".format(self.trace.pc)
74+
self.trace = self.trace.parent
75+
#return
76+
elif lr != last_lr:
77+
self.trace = self.trace.newchild(pc, lr, frame.name())
78+
print "Called {}{:02x} (return: {:02x})".format(frame.name(), pc, lr)
79+
#return
80+
if pc == 0 or pc == stop_pc:
81+
break;
82+
self.trace.exclusive += 1
83+
last_lr = lr
84+
gdb.execute("si")
85+
#gdb.execute("set logging off")
86+
#gdb.execute("display")
87+
printstack(topfunc)
88+
89+
Profile()

0 commit comments

Comments
 (0)