Skip to content

Conversation

@stephanosio
Copy link
Member

@stephanosio stephanosio commented Mar 24, 2022

Cherry-pick upstream patches to support I2C device emulation (e.g. LSM303DLHC magnetometer) for ARM targets

Zephyr SDK PR: zephyrproject-rtos/sdk-ng#449

microbuilder and others added 3 commits March 25, 2022 00:20
This commit adds emulation of the magnetometer on the LSM303DLHC.
It allows the magnetometer's X, Y and Z outputs to be set via the
mag-x, mag-y and mag-z properties, as well as the 12-bit
temperature output via the temperature property. Sensor can be
enabled with 'CONFIG_LSM303DLHC_MAG=y'.

Signed-off-by: Kevin Townsend <kevin.townsend@linaro.org>
Message-id: 20220130095032.35392-1-kevin.townsend@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 4fd1ebb)
Currently there is no way for a board model's Kconfig stanza to
say "I have an i2c bus which the user can plug an i2c device into,
build all the free-standing i2c devices". The Kconfig mechanism
for this is the "device group". Add an I2C_DEVICES group along
the same lines as the existing PCI_DEVICES. Simple free-standing
i2c devices which a user might plausibly want to be able to
plug in on the QEMU commandline should have
   default y if I2C_DEVICES
and board models which have an i2c bus that is user-accessible
should use
   imply I2C_DEVICES
to cause those pluggable devices to be built.

In this commit we mark only a fairly conservative set of i2c devices
as belonging to the I2C_DEVICES group: the simple sensors and RTCs
(not including PMBus devices or devices which need GPIO lines to be
connected).

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Message-id: 20220208155911.3408455-2-peter.maydell@linaro.org
(cherry picked from commit b5bf5a5)
For arm boards with an i2c bus which a user could reasonably
want to plug arbitrary devices, add 'imply I2C_DEVICES' to the
Kconfig stanza.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Hao Wu <wuhaotsh@google.com>
Message-id: 20220208155911.3408455-3-peter.maydell@linaro.org
(cherry picked from commit e117e97)
@stephanosio
Copy link
Member Author

@microbuilder

@microbuilder
Copy link
Member

Thanks @stephanosio

For reference sake, this sensor can added to QEMU at startup via:

$ qemu-system-arm -M mps2-an521 -device loader,file=build/zephyr/zephyr.elf -serial stdio \
  -monitor tcp:localhost:4444,server,nowait \
  -device lsm303dlhc_mag,id=lsm303,address=0x1E

We can be automatically handles this in Zephyr with an addition like this to the project cmake file:

if(BOARD MATCHES "mps2_an521")
  list(APPEND QEMU_EXTRA_FLAGS -device lsm303dlhc_mag,id=lsm303,address=0x1E)
endif()

For the device tree (mps2_an521 or mps3_an547 assumed here):

&i2c_shield1 {
	lsm303dlhc-magn@1e {
		compatible = "st,lsm303dlhc-magn";
		reg = <0x1e>;
		label = "LSM303DLHC-MAGN";
	};
};

Config settings:

CONFIG_I2C=y
CONFIG_I2C_SHELL=y
CONFIG_LSM303DLHC_MAGN=y

@stephanosio stephanosio changed the title Add LSM303DLHC magnetometer support Add I2C device emulation support for ARM targets Mar 24, 2022
@microbuilder
Copy link
Member

To update values for the magn or temp sensor, you have a several options, but the easiest to quickly test is with the monitor interface (see -monitor in an earlier comment here), then:

$ nc localhost 4444
QEMU 6.0.93 monitor - type 'help' for more information
(qemu) qom-list /machine/peripheral/
(qemu) qom-set lsm303 mag-x 1000
(qemu) qom-set lsm303 temperature 23000

Note: For the magnetometer 1 = 0.001 uT, and for the temperature sensor 1 = 0.001 C

@MaureenHelm
Copy link
Member

Cool! Looking forward to playing with this.

@yperess @erwango FYI

@yperess
Copy link

yperess commented Mar 24, 2022

Thanks, very exciting

@microbuilder
Copy link
Member

It's nice to have emulated devices that appear exactly the same as real HW on the I2C bus.

This should make testing specific edge cases with sensors much easier, although you'll need something to script the sensor data updates in parallel. Most languages have libraries to make communicting with QEMU possible, though, and it can be done in a bash script in a pinch.

I only emulate the magnetometer for now since it was a much simpler device than the accel (less than a dozen registers), but it's still useful as a proof of concept.

@erwango
Copy link
Member

erwango commented Mar 25, 2022

@avisconti FYI

@microbuilder
Copy link
Member

microbuilder commented Mar 25, 2022

This seems OK:

$ ./qemu-system-arm -device help | grep lsm
name "lsm303dlhc_mag", bus i2c-bus
$ ./qemu-system-arm -M mps2-an521 -S -monitor stdio \
  -device lsm303dlhc_mag,id=lsm303,address=0x1E

QEMU 6.2.0 monitor - type 'help' for more information
(qemu) VNC server running on ::1:5900
(qemu) qom-list /machine/peripheral
type (string)
lsm303 (child<lsm303dlhc_mag>)
(qemu) qom-get lsm303 temperature
0
(qemu) qom-set lsm303 temperature 23000
(qemu) qom-get lsm303 temperature
23000

After adding the DTS overlay and kconfig changes mentionned earlier in this PR, I built an image with:

$ west build -p -b mps2_an521 zephyr/samples/sensor/sensor_shell/

Then run it with:

$ ./qemu-system-arm -M mps2-an521 \
  -device loader,file=/home/ubuntu/zephyr/build/zephyr/zephyr.elf \
  -serial stdio   -monitor tcp:localhost:4444,server,nowait  \
   -device lsm303dlhc_mag,id=lsm303,address=0x1E
VNC server running on ::1:5900


uart:~$ i2c scan I2C_SHIELD1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:             -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
1 devices found on I2C_SHIELD1

uart:~$ sensor get LSM303DLHC-MAGN magn_xyz
channel idx=11 magn_xyz x =   0.000000 y =   0.000000 z =   0.000000

Update the register values via QOM in the qemu terminal:

$ nc localhost 4444
(qemu) qom-list /machine/peripheral/lsm303
qom-list /machine/peripheral/lsm303
type (string)
parent_bus (link<bus>)
realized (bool)
hotplugged (bool)
hotpluggable (bool)
address (uint8)
mag-y (int)
temperature (int)
mag-z (int)
mag-x (int)
(qemu) qom-set lsm303 mag-x 1000
qom-set lsm303 mag-x 1000
(qemu) qom-set lsm303 mag-z 1500
qom-set lsm303 mag-z 1500

Then scan the device again in zephyr's shell:

uart:~$ sensor get LSM303DLHC-MAGN magn_xyz
channel idx=11 magn_xyz x =   0.010000 y =   0.000000 z =   0.014285

Note that the z value doesn't exactly match the expected 0.015 since it will scale inputs to the closest valid value based on the magnetometer gain, etc.

@stephanosio stephanosio merged commit d68d237 into zephyr-qemu-v6.2.0 Mar 25, 2022
@stephanosio stephanosio deleted the add_lsm303dlhc branch March 25, 2022 13:25
nashif pushed a commit that referenced this pull request May 16, 2025
ASAN detected a leak when running the ahci-test
/ahci/io/dma/lba28/retry:

Direct leak of 35 byte(s) in 1 object(s) allocated from:
    #0 in malloc
    #1 in __vasprintf_internal
    #2 in vasprintf
    #3 in g_vasprintf
    #4 in g_strdup_vprintf
    #5 in g_strdup_printf
    #6 in object_get_canonical_path ../qom/object.c:2096:19
    #7 in blk_get_attached_dev_id_or_path ../block/block-backend.c:1033:12
    #8 in blk_get_attached_dev_path ../block/block-backend.c:1047:12
    #9 in send_qmp_error_event ../block/block-backend.c:2140:36
    #10 in blk_error_action ../block/block-backend.c:2172:9
    #11 in ide_handle_rw_error ../hw/ide/core.c:875:5
    #12 in ide_dma_cb ../hw/ide/core.c:894:13
    qemu#13 in dma_complete ../system/dma-helpers.c:107:9
    qemu#14 in dma_blk_cb ../system/dma-helpers.c:129:9
    qemu#15 in blk_aio_complete ../block/block-backend.c:1552:9
    qemu#16 in blk_aio_write_entry ../block/block-backend.c:1619:5
    qemu#17 in coroutine_trampoline ../util/coroutine-ucontext.c:175:9

Plug the leak by freeing the device path string.

Signed-off-by: Fabiano Rosas <farosas@suse.de>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241111145214.8261-1-farosas@suse.de>
[PMD: Use g_autofree]
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20241111170333.43833-3-philmd@linaro.org>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
(cherry picked from commit 23ea425)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
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.

7 participants