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

SPI/I2C exposed (QEMU-157) #37

Open
HikingDev opened this issue Mar 20, 2022 · 8 comments
Open

SPI/I2C exposed (QEMU-157) #37

HikingDev opened this issue Mar 20, 2022 · 8 comments

Comments

@HikingDev
Copy link

Hi,

i am trying to understand how to stimulate the Simulated Peripherals.
I do understand how to communicate via Sockets to the UART Peripheral.
Is there any way to use Sockets to communicate to SPI and/or I2C?

@igrr
Copy link
Member

igrr commented Mar 20, 2022

Hi @HikingDev,
As far as I know QEMU doesn't support SPI/I2C forwarding via sockets. There is a number of SPI and I2C devices implemented in QEMU itself, such as certain temperature sensors and ADCs. In theory they can be used as described here: https://gist.github.com/jonte/b4bd83a5f2e8330418b1f3322bff74f2.

However this approach currently doesn't work with this ESP32 fork. It is because the SPI/I2C "buses" (QEMU term, no relation to physical buses) are not attached to the "default system bus". If a peripheral is attached to the default system bus in QEMU, it gets reset on system reset. On an ESP32 however there are multiple types of system reset, some of which do not reset all the peripherals. To emulate those reset types all peripherals got attached to a separate bus, unreachable from sysbus_default.

For SPI and I2C I think we can live with slightly imprecise emulation and have them reset on every type of system reset. That should make it possible to attach them to sysbus_default, and thus to attach emulated peripherals to SPI and I2C.
This still doesn't enable SPI or I2C communication over sockets, but it's a start.

@HikingDev
Copy link
Author

Hi @igrr ,
thank you for the quick response.
I am trying to read more about the "multiple types of system reset" as well as understanding the QEMU bus system.

Unfortunately the emulated SPI and I2C devices are not useful for our use case.

We use the esp32 as wifi module slave in Station Mode.
The net communicaiton happens via SPI whereas the commands (Scan, Connect etc) is done via UART.
So far the simulated host is able to update the firmware via UART on the emulated ESP32.
Of course it would be awesome if at some point the SPI protocol parallel to to already possible UART protocol could be developed and tested.

I I think that the exposed Devices are not a rare use case. Would you say that it is a rather complex task, exposing the aforementioned devices?

I guess i need to understand a little more of the internals of QEMU in general.

@igrr
Copy link
Member

igrr commented Mar 21, 2022

I think there are three things which would have to be implemented:

  • Support for SPI slave mode emulation on the ESP32. Currently only master mode is supported. It seems to be a bit tricky to support both, since in QEMU the device can't be both master and slave on the same bus, as far as I can tell. So we'll have to somehow split the SPI peripheral into two devices.
  • Implement some kind of SPI master which would implement a character device type. This part wouldn't be ESP32 specific.
  • Figure out how to attach ESP32 SPI slave peripheral to to this custom SPI master, if the user requests to create it.

If you are interested in implementing this, I can give you a few pointers around the codebase.

Unfortunately we can't commit to implementing this functionality ourselves. Medium term, our goals for QEMU will be related to improving emulation of security-related peripherals and adding emulation of new chips (ESP32-S2, ESP32-C3).

@HikingDev
Copy link
Author

This sounds rather time intensive.
We are currently discussing if such a task could be formulated and amplified that it is sufficient for bachelor thesis.
Unfortunately I doubt that I have and/or get the time capacity implement it (whereas I am intrigued to learn more about QEMU).

I will let you know if we somehow get the resources to implement a "QEMU SPI Slave"

igrr pushed a commit that referenced this issue Aug 2, 2022
Include the qtest reproducer provided by Alexander Bulekov
in https://gitlab.com/qemu-project/qemu/-/issues/542.
Without the previous commit, we get:

  $ make check-qtest-i386
  ...
  Running test tests/qtest/intel-hda-test
  AddressSanitizer:DEADLYSIGNAL
  =================================================================
  ==1580408==ERROR: AddressSanitizer: stack-overflow on address 0x7ffc3d566fe0
      #0 0x63d297cf in address_space_translate_internal softmmu/physmem.c:356
      #1 0x63d27260 in flatview_do_translate softmmu/physmem.c:499:15
      #2 0x63d27af5 in flatview_translate softmmu/physmem.c:565:15
      #3 0x63d4ce84 in flatview_write softmmu/physmem.c:2850:10
      #4 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18
      #5 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16
      #6 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12
      #7 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12
      #8 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12
      #9 0x62ae5ec0 in stl_le_dma include/sysemu/dma.h:275:1
      #10 0x62ae5ba2 in stl_le_pci_dma include/hw/pci/pci.h:871:1
      #11 0x62ad59a6 in intel_hda_response hw/audio/intel-hda.c:372:12
      #12 0x62ad2afb in hda_codec_response hw/audio/intel-hda.c:107:5
      #13 0x62aec4e1 in hda_audio_command hw/audio/hda-codec.c:655:5
      #14 0x62ae05d9 in intel_hda_send_command hw/audio/intel-hda.c:307:5
      #15 0x62adff54 in intel_hda_corb_run hw/audio/intel-hda.c:342:9
      #16 0x62adc13b in intel_hda_set_corb_wp hw/audio/intel-hda.c:548:5
      #17 0x62ae5942 in intel_hda_reg_write hw/audio/intel-hda.c:977:9
      #18 0x62ada10a in intel_hda_mmio_write hw/audio/intel-hda.c:1054:5
      #19 0x63d8f383 in memory_region_write_accessor softmmu/memory.c:492:5
      #20 0x63d8ecc1 in access_with_adjusted_size softmmu/memory.c:554:18
      #21 0x63d8d5d6 in memory_region_dispatch_write softmmu/memory.c:1504:16
      #22 0x63d5e85e in flatview_write_continue softmmu/physmem.c:2812:23
      #23 0x63d4d05b in flatview_write softmmu/physmem.c:2854:12
      #24 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18
      #25 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16
      #26 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12
      #27 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12
      #28 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12
      #29 0x62ae5ec0 in stl_le_dma include/sysemu/dma.h:275:1
      #30 0x62ae5ba2 in stl_le_pci_dma include/hw/pci/pci.h:871:1
      #31 0x62ad59a6 in intel_hda_response hw/audio/intel-hda.c:372:12
      #32 0x62ad2afb in hda_codec_response hw/audio/intel-hda.c:107:5
      #33 0x62aec4e1 in hda_audio_command hw/audio/hda-codec.c:655:5
      #34 0x62ae05d9 in intel_hda_send_command hw/audio/intel-hda.c:307:5
      #35 0x62adff54 in intel_hda_corb_run hw/audio/intel-hda.c:342:9
      #36 0x62adc13b in intel_hda_set_corb_wp hw/audio/intel-hda.c:548:5
      #37 0x62ae5942 in intel_hda_reg_write hw/audio/intel-hda.c:977:9
      #38 0x62ada10a in intel_hda_mmio_write hw/audio/intel-hda.c:1054:5
      #39 0x63d8f383 in memory_region_write_accessor softmmu/memory.c:492:5
      #40 0x63d8ecc1 in access_with_adjusted_size softmmu/memory.c:554:18
      #41 0x63d8d5d6 in memory_region_dispatch_write softmmu/memory.c:1504:16
      #42 0x63d5e85e in flatview_write_continue softmmu/physmem.c:2812:23
      #43 0x63d4d05b in flatview_write softmmu/physmem.c:2854:12
      #44 0x63d4cb18 in address_space_write softmmu/physmem.c:2950:18
      #45 0x63d4d387 in address_space_rw softmmu/physmem.c:2960:16
      #46 0x62ae12f2 in dma_memory_rw_relaxed include/sysemu/dma.h:89:12
      qemu#47 0x62ae104a in dma_memory_rw include/sysemu/dma.h:132:12
      #48 0x62ae6157 in dma_memory_write include/sysemu/dma.h:173:12
      ...
  SUMMARY: AddressSanitizer: stack-overflow softmmu/physmem.c:356 in address_space_translate_internal
  ==1580408==ABORTING
  Broken pipe
  Aborted (core dumped)

Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
Acked-by: Thomas Huth <[email protected]>
Message-Id: <[email protected]>
Signed-off-by: Thomas Huth <[email protected]>
@TobiasNils
Copy link

For SPI and I2C I think we can live with slightly imprecise emulation and have them reset on every type of system reset. That should make it possible to attach them to sysbus_default, and thus to attach emulated peripherals to SPI and I2C.

Hi @igrr ,
we are currently trying to figure out how to attach emulated peripherals to SPI. Would you be so kind and expand a little on how this "reset on every type of system reset" could be accomplished?

@github-actions github-actions bot changed the title SPI/I2C exposed SPI/I2C exposed (QEMU-157) Jul 14, 2023
@igrr
Copy link
Member

igrr commented Jul 14, 2023

Could you try replacing s->&periph_bus with NULL in

qdev_realize(DEVICE(&s->spi[i]), &s->periph_bus, &error_fatal);
and see if that helps?

@lcgamboa
Copy link

Hi @TobiasNils,

in my fork I use ssi_create_peripheral(s->spi[2].spi, "picsimlab_spi"); to attach the picsimlab_spi slave peripheral. You can use this code as a base, just add the functionality you want to implement in the xxx_SPI_transfer function that is called every time ESP32 sends a byte and blocks qemu waiting for a return byte.

@TobiasNils
Copy link

Thanks a lot @igrr and @lcgamboa. We will do some tests and report back.

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

No branches or pull requests

5 participants