Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable qemu target for STM32 emulation #562

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

PhracturedBlue
Copy link
Contributor

This is going to be a test of using QEMU to run STM32 code in a controlled environment to help with debug as well as do profiling.

There is a QEMU branch supporting STM32 here: https://github.com/beckus/qemu_stm32
It can be compiled from source, or used via docker

The STM32 target is somewhat limited (no SPI...limited timer modes) so it won't currently be able to run protocol code unaided, but I'm going to experiment with its capabilities in this pull-request.

The best supported board is the Olimex P103 which is an STM32F103RB based board. That is the same chip in the Devo7e, and it will be too small for a monolithic build. Likely we'll either need to patch Qemu to support a more capable chip (like the 'VC' variant used in the devo8) or we'll need to get SPI support so we can enable module loading. That is for another day.

The 1st task will be to get everything initialized, and try to profile the mixer code.

Currently the code jus

@PhracturedBlue
Copy link
Contributor Author

On the plus side, I can connect gdb to the qemu image, and trace it just fine. On the downside QEMU doesn't actually have profiler support. the 4.9 or newer embedded-gcc builds (I'm using 8-2019q4), come with python support for gdb. using this I can generate a full call-trace by single-stepping through the entire program. It is very slow, but it does work. I can also use this to map back to the current function as well so I can sot-of create a rudimentary profiler. keeping track of function calls and returns is theoretically possible, but I'm not sure how well it will work. I'm not sure how much more effort I want to put in this direction.

@PhracturedBlue
Copy link
Contributor Author

well...I did some more work, and it is starting to be useful:
Here is the log for a single 'replace' mixer run through qemu:

    MIXER_CalcChannels 0x8002784 (ex:671 inc:6377)
      CLOCK_getms 0x8001324 (ex:3 inc:3)
      MIXER_MapChannel 0x80023ac (ex:243 inc:243)
      CHAN_ReadInput 0x80011e8 (ex:584 inc:946)
        CHAN_ReadRawInput 0x80010c4 (ex:305 inc:362)
          gpio_port_read 0x8002c22 (ex:57 inc:57)
      MIXER_EvalMixers 0x80025c0 (ex:179 inc:224)
        MIXER_ApplyMixer 0x80024a4 (ex:34 inc:45)
          CURVE_Evaluate 0x8002294 (ex:11 inc:11)
      MIXER_GetChannel 0x8002714 (ex:224 inc:4290)
        MIXER_ApplyLimits 0x8002604 (ex:946 inc:4066)
          get_trim 0x8002470 (ex:2976 inc:3120)
            MIXER_MapChannel 0x80023ac (ex:144 inc:144)

'ex' is the number of exclusive instructions (instructions executed directly in this function). 'inc' is the number of inclusive instructions (instructions executed in the current procedure and all its children). May still be buggy, but it seems to be working more or less

LINKFILE = $(SDIR)/target/$(TARGET)/$(TARGET).ld
LIBOPENCM3 = $(SDIR)/libopencm3/lib/libopencm3_stm32f1.a

SRC_C := $(wildcard $(SDIR)/target/$(TARGET)/*.c) \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should create a Makefile.inc for all STM32 related parts. this makefile, the one under devo/common, and the one under at9 are largely duplicatd.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes probably. This was only meant to be a proof-of-concept. certainly not ready for inclusion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also need an instruction on qemu as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some documentation now.

// timer clock (RCC_APB1ENR_TIM4EN), Port (GPIOB), Pin (GPIO9)
// Port clock RCC_APB2ENR_IOPBEN

void BACKLIGHT_Init()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cna u just include another real implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of these may be able to use a real implementation, but the qemu target does not have all STM32 features, and without proper SPI or clock support a lot of things won't work. Before I merge this, I'll clean up what can be done though.

@PhracturedBlue
Copy link
Contributor Author

Difference between curve options:
224 instructions per mixer for no curve
353 instructions per mixer when using a smoothed 13-point curve

13 point smooth
None 0x00 (ex:672 inc:6507)
  CLOCK_getms 0x8001364 (ex:3 inc:3)
  MIXER_MapChannel 0x80023ec (ex:243 inc:243)
  CHAN_ReadInput 0x8001228 (ex:584 inc:946)
    CHAN_ReadRawInput 0x8001104 (ex:305 inc:362)
      gpio_port_read 0x8002c62 (ex:57 inc:57)
  MIXER_EvalMixers 0x8002600 (ex:179 inc:353)
    MIXER_ApplyMixer 0x80024e4 (ex:34 inc:174)
      CURVE_Evaluate 0x80022d4 (ex:101 inc:140)
        compute_tangent 0x800202c (ex:39 inc:39)
  MIXER_GetChannel 0x8002754 (ex:224 inc:4290)
    MIXER_ApplyLimits 0x8002644 (ex:946 inc:4066)
      get_trim 0x80024b0 (ex:2976 inc:3120)
        MIXER_MapChannel 0x80023ec (ex:144 inc:144)
13 point interpolated
None 0x00 (ex:672 inc:6422)
  CLOCK_getms 0x8001364 (ex:3 inc:3)
  MIXER_MapChannel 0x80023ec (ex:243 inc:243)
  CHAN_ReadInput 0x8001228 (ex:584 inc:946)
    CHAN_ReadRawInput 0x8001104 (ex:305 inc:362)
      gpio_port_read 0x8002c62 (ex:57 inc:57)
  MIXER_EvalMixers 0x8002600 (ex:179 inc:268)
    MIXER_ApplyMixer 0x80024e4 (ex:34 inc:89)
      CURVE_Evaluate 0x80022d4 (ex:55 inc:55)
  MIXER_GetChannel 0x8002754 (ex:224 inc:4290)
    MIXER_ApplyLimits 0x8002644 (ex:946 inc:4066)
      get_trim 0x80024b0 (ex:2976 inc:3120)
        MIXER_MapChannel 0x80023ec (ex:144 inc:144)
expo
None 0x00 (ex:672 inc:6415)
  CLOCK_getms 0x800135c (ex:3 inc:3)
  MIXER_MapChannel 0x80023e4 (ex:243 inc:243)
  CHAN_ReadInput 0x8001220 (ex:584 inc:946)
    CHAN_ReadRawInput 0x80010fc (ex:305 inc:362)
      gpio_port_read 0x8002c5a (ex:57 inc:57)
  MIXER_EvalMixers 0x80025f8 (ex:179 inc:261)
    MIXER_ApplyMixer 0x80024dc (ex:34 inc:82)
      CURVE_Evaluate 0x80022cc (ex:35 inc:48)
        expou 0x8002214 (ex:13 inc:13)
  MIXER_GetChannel 0x800274c (ex:224 inc:4290)
    MIXER_ApplyLimits 0x800263c (ex:946 inc:4066)
      get_trim 0x80024a8 (ex:2976 inc:3120)
        MIXER_MapChannel 0x80023e4 (ex:144 inc:144)

@howard0su
Copy link
Contributor

How can I map to the time from instruction #? look like there is no direct mapping between.

@PhracturedBlue
Copy link
Contributor Author

It isn't working properly yet (maybe buggy in QEMU, I dunno yet), but you can query the systick timer (
0xE000E018) which should count-down at 8MHz on real hardware. I am currently seeing that it is taking ~3500 systick cycles per instruction on the emulator which makes no sense to me. I haven't had time to debug. Most commands take a single cycle (@systick frequency). load/store and 32bit multiply generally take 2. divide, jump branch and 64bit multiply take more.

--

@PhracturedBlue
Copy link
Contributor Author

After a lot of testing, I've concuded qemu does not accurately model the systick timer with regards to HCLK. This may note even be possible given that I'm note sure the details of pipeline stalling are even known. But currently systick cannot be reliably used to determine execution time in qemu.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants