I2C 4 KB 存储器目标¶
PxI2C4KbMemoryTarget 在 I2C(或 I3C)总线上模拟字节寻址存储器器件。控制器以 7 位 I2C 地址 加上 16 位存储器偏移(子地址,MSB 在前)访问器件,再读写连续字节块。
当你要测试控制器驱动程序、EEPROM 风格外设,或需要超过 8 位寻址的较大线性存储器数组时,这个目标很有用。
存储器模型¶
- 4 KB 存储器(
0x0000–0x0FFF)。 - 创建时配置的 静态 I2C 地址(例如
0x50)。 - 16 位子地址 作为写入事务的前两个数据字节送出(MSB 在前),或在带子地址的读取序列之前写入。
总线上典型写入如下:
典型带子地址读取如下:
Exerciser 在总线传输期间直接更新存储器。Python 可通过 read_mem / write_mem 查看或预载存储器,不必经过 I2C 控制器。
快速开始¶
将目标挂载到 I2C 总线,并从 Python 读写存储器:
from aqpxlib import AqProtocolExerciser
from aqpxlib.i2c import PxI2CBus, PxI2C4KbMemoryTarget
with AqProtocolExerciser.connect(port=60600) as px:
i2c_bus = PxI2CBus(px, scl=0, sda=1)
target = PxI2C4KbMemoryTarget(px, address=0x50)
target.attach_to_bus(i2c_bus)
target.write_mem(0x0100, [0x01, 0x02, 0x03, 0x04])
assert target.read_mem(0x0100, 4) == [0x01, 0x02, 0x03, 0x04]
target.detach_from_bus()
控制器访问¶
在同一条总线上使用 PxI2CController,以真实控制器的方式操作目标。将 16 位子地址以两个字节的 list 传给 i2c_write_addr / i2c_read_addr:
from aqpxlib import AqProtocolExerciser
from aqpxlib.i2c import PxI2CBus, PxI2CController, PxI2C4KbMemoryTarget
with AqProtocolExerciser.connect(port=60600) as px:
i2c_bus = PxI2CBus(px, scl=0, sda=1)
target = PxI2C4KbMemoryTarget(px, address=0x50)
target.attach_to_bus(i2c_bus)
i2c_controller = PxI2CController(px)
i2c_controller.attach_to_bus(i2c_bus)
sub_address = 0x0100
data = [0xDE, 0xAD, 0xBE, 0xEF]
i2c_controller.i2c_write_addr(
address=target.address,
sub_address=[(sub_address >> 8) & 0xFF, sub_address & 0xFF],
data=data,
)
read_back = i2c_controller.i2c_read_addr(
address=target.address,
sub_address=[(sub_address >> 8) & 0xFF, sub_address & 0xFF],
count=len(data),
)
assert read_back == data
# 确认存储器内容与控制器写入的内容一致.
assert target.read_mem(sub_address, len(data)) == data
i2c_controller.detach_from_bus()
target.detach_from_bus()
总线访问事件¶
当总线上其他器件读写此目标时,exerciser 会在目标实例上发出 memory_target_write_event 与 memory_target_read_event。这些是共用事件类型(I3C、SPI 等其他存储器目标也使用):
| 事件 | Payload 字段 | 发出时机 |
|---|---|---|
memory_target_write_event |
addr, data |
总线写入传输完成后 |
memory_target_read_event |
addr, count |
总线读取传输完成后 |
为每种事件类型分别订阅处理函数:
from aqpxlib.event import PxEventMsg
@target.on_event("memory_target_write_event")
def on_memory_target_write(event: PxEventMsg):
write = event.device_event.memory_target_write_event
print(f"Bus write @ 0x{write.addr:04x}: {write.data.hex()}")
@target.on_event("memory_target_read_event")
def on_memory_target_read(event: PxEventMsg):
read = event.device_event.memory_target_read_event
print(f"Bus read @ 0x{read.addr:04x}, {read.count} bytes")
事件只反映总线活动。从 Python 调用 read_mem / write_mem 不会发出存储器目标事件。
另见: 事件注册与处理函数设置。
I3C 总线支持¶
PxI2C4KbMemoryTarget 可挂载到 I3C 总线(valid_buses 包含 "i3c" 与 "i2c")。器件在 I3C SDA 线上以 I2C 风格目标运行。
API 参考¶
PxI2C4KbMemoryTarget
¶
PxI2C4KbMemoryTarget(
exerciser: AqProtocolExerciser,
address: int = 0,
config: I2C4KbMemoryTargetConfig | None = None,
*args,
**kwargs
)
Bases: PxAbstractTarget
I2C byte-addressable 4 KB memory target.
Emulates a 4 KB memory device on an I2C or I3C bus. Controllers access memory using a 7-bit device address plus a 16-bit sub-address (MSB first).
Use read_mem and write_mem to access memory from Python. Bus reads and
writes from a controller emit memory_target_read_event and
memory_target_write_event notifications.
| METHOD | DESCRIPTION |
|---|---|
add_event_handler |
Add an event handler to the current device instance. |
remove_event_handler |
Remove an event handler. |
get_event_handlers |
Retreive handlers registerd on this device. |
on_event |
Add an event handler to the instance by decorator. |
set_config |
Set the config of the target. |
detach_from_bus |
Detach the device from the bus. |
perform_operation |
Send an operation. |
attach_to_bus |
Attach the target to a bus. |
read_mem |
Read bytes from memory via the Protocol Exerciser API. |
write_mem |
Write bytes to memory via the Protocol Exerciser API. |
| ATTRIBUTE | DESCRIPTION |
|---|---|
available_events_map |
A reverse mapping of |
is_attached |
Check if the device is attached to a bus.
TYPE:
|
state |
Get the state of the device.
TYPE:
|
name |
Get the name of the device.
TYPE:
|
additional_data |
Get the opaque additional data blob associated with this device.
TYPE:
|
config |
Get the config of the device.
TYPE:
|
cts_op_name |
Get the name of CTS operation. Currently not available now.
TYPE:
|
address |
Static address of the device.
TYPE:
|
available_events_map
¶
A reverse mapping of field_name_by_number, which uses field name as key.
additional_data
¶
additional_data: bytes
Get the opaque additional data blob associated with this device.
add_event_handler
¶
Add an event handler to the current device instance.
get_event_handlers
¶
Retreive handlers registerd on this device.
on_event
¶
Add an event handler to the instance by decorator.
detach_from_bus
¶
Detach the device from the bus.
The opposite of the attach_to_bus method.
perform_operation
¶
Send an operation.
attach_to_bus
¶
attach_to_bus(bus: PxAbstractBus) -> None
Attach the target to a bus.
This method is used to make the device aware of the bus it is connected to. It is used to set the bus attribute of the device.
Note
This method will not automatically create an actual instance on
the Protocol Exerciser until user call the attach_to_bus method.
| PARAMETER | DESCRIPTION |
|---|---|
|
The bus to attach the device to
TYPE:
|
| RAISES | DESCRIPTION |
|---|---|
ValueError
|
If the device is already attached to a bus |
read_mem
¶
Read bytes from memory via the Protocol Exerciser API.
This does not perform an I2C bus transaction. Use a
PxI2CController to exercise the
target over the bus.
| PARAMETER | DESCRIPTION |
|---|---|
|
Starting 16-bit memory address (
TYPE:
|
|
Number of bytes to read.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
list[int]
|
Bytes read from memory as a list of integers ( |
write_mem
¶
Write bytes to memory via the Protocol Exerciser API.
This does not perform an I2C bus transaction. Use a
PxI2CController to exercise the
target over the bus.
| PARAMETER | DESCRIPTION |
|---|---|
|
Starting 16-bit memory address (
TYPE:
|
|
Bytes to write as a list of integers ( |