Rockchip · AI & Linux Hub

Hardware-Schnittstellen

Rockchip-PCIe-Leistung: DMA, BAR, Interrupts, NVMe-Tests und Busoptimierung

Rockchip-PCIe-Leistung: DMA, BAR, Interrupts, NVMe-Tests und Busoptimierung — RK-KF-YF-460 V2.9.0

· ArmSoM Editorial · Rockchip source documentation · 31 Min. Lesezeit

Quelle: RK-KF-YF-460 V2.9.0 für Chips mit PCIe und Linux ab 4.4. Dies ist eine Plattformreferenz: SoC der ArmSoM-Platine, PCIe-Verdrahtung, SDK/BSP, Kernel und Peripherie prüfen. Alle Leistungstabellen stammen aus EVB-Tests des Herstellers, nicht aus ArmSoM-Messungen. Chinesisch verwendet chinesische Abbildungen, die übrigen Sprachen englische. Register-, Firmware-, Energie- und Formatierungsbeispiele erfordern gesicherte Testhardware und Prüfung mit dem tatsächlichen BSP.

ArmSoM Docs · Rockchip Linux

1. Hintergrund

1.1 Einleitung

Dieses Dokument beschreibt Leistungskennzahlen von RK-PCIe-Anwendungen und ihre Messverfahren. Ziel ist die Ermittlung der jeweiligen Kennzahlen über einfache, genaue und kontrollierbare Anwendungsschnittstellen. Der Hintergrundabschnitt erläutert das für die Tests benötigte Wissen, der Abschnitt zu Übertragungsraten liefert theoretische PCIe-Berechnungen; die übrigen Abschnitte behandeln konkrete Kennzahlen und Messverfahren.

1.2 PCIe sysfs

Linux PCIe unterstützt die sysfs-Schnittstelle mit hauptsächlich folgenden Ressourcen:

/sys/devices/pci0000:17
|-- 0000:17:00.0
|   |-- class
|   |-- config
|   |-- device
|   |-- enable
|   |-- irq
|   |-- local_cpus
|   |-- remove
|   |-- resource
|   |-- resource0
|   |-- resource1
|   |-- resource2
|   |-- resource2_wc        # 64bits-pref mem resource and supports write combining, which has an optimization effect on PCIe mem to dev operations.
|   |-- revision
|   |-- rom
|   |-- subsystem_device
|   |-- subsystem_vendor
|   `-- vendor
`-- ...

Ausführliche Referenz:

2. Übertragungsraten

2.1 PCIe-Bandbreite

PCIe-Generation Kodierung Übertragungsrate x1 Lane x2 Lane x4 Lane x8 Lane
1.0 8b/10b 2.5GT/s 250MB/s 500MB/s 1GB/s 2GB/s
2.0 8b/10b 5GT/s 500MB/s 1GB/s 2GB/s 4GB/s
3.0 128b/130b 8GT/s 984.6MB/s 1.969GB/s 3.938GB/s 7.877GB/s
4.0 128b/130b 16GT/s 1.969GB/s 3.938GB/s 7.877GB/s 15.754GB/s

Die Übertragungsrate wird in GT/s und nicht in Bit pro Sekunde (Gbps) angegeben: Sie enthält Verwaltungsbits, die keinen zusätzlichen Nutzdurchsatz liefern. Beispielsweise beansprucht 8b/10b bei PCIe 1.x/2.x 20 % (2/10) der Kanalbandbreite. Die Quelle definiert GT/s als Giga transaction per second, Transaktionen pro Sekunde, und Gbps als Giga Bits Per Second und erklärt, es gebe keine proportionale Umrechnung. Verfügbare Bandbreite: Throughput = Transfer Rate * Encoding Scheme. Das Quellenbeispiel für PCIe 2.0 lautet „58 / 10 = 4 Gbps = 500 MB/s“, für x8 „48 = 32 Gbps = 4 GB/s“. Diese Schreibweisen bleiben als Quellenunklarheit erhalten.

2.2 TLP-Overhead

Beim Durchlaufen der Transaktions- und Sicherungsschicht werden Verwaltungsinformationen hinzugefügt, darunter Paketköpfe und -enden (LCRC, ECRC usw.) sowie Paketnummern der Sicherungsschicht. Deshalb liegt die tatsächliche Datenrate der Nutzlast unter der Bandbreite.

Englische Originalabbildung — 8

Englische Originalabbildung — 8

Die maximalen TLP-Zusatzdaten von 28 Byte umfassen den Header (16 Byte), die optionale ECRC (4 Byte), die LCRC (4 Byte), die Sequenznummer (2 Byte) sowie die Rahmensymbole STP und END (2 Byte). Als Beispiel dient die PCIe-Gen3-Bandbreite:

PCIe-Generation Kodierung Übertragungsrate x1 Lane x2 Lane x4 Lane x8 Lane
3.0 128b/130b 8GT/s 984.6MB/s 1.969GB/s 3.938GB/s 7.877GB/s

Nach Berücksichtigung des TLP-Overheads:

PCIe-Generation Gen3 x1 Lane x2 Lane x4 Lane x8 Lane
PCIe-Bandbreite (ohne TLP-Overhead) 984.6MB/s 1.969GB/s 3.938GB/s 7.877GB/s
256B Nutzlast nach TLP-Overhead (256/284) 887.5MB/s 1.775GB/s 3.550GB/s 7.1002GB/s
128B Nutzlast nach TLP-Overhead (128/156) 807.8MB/s 1.616GB/s 3.232GB/s 6.464GB/s

2.3 Übertragungsraten in PCIe-Anwendungsszenarien

Unter zusätzlicher Berücksichtigung der DLLPs für Ack/Nak und Flusssteuerung sowie der Ordered Sets für Linktraining und Skip sinkt die tatsächliche Übertragungsrate weiter. In konkreten Anwendungsszenarien gilt eDMA als optimale Übertragungslösung.

3. Allgemeine Leistungsoptimierung

3.1 Maximale CPU- und DDR-Frequenz

Zur Anpassung den DVFS- und DRAM-Quellcode heranziehen.

3.2 CPU-Idle deaktivieren

Beispiel für die RK3588-Plattform:

/* dtsi disable cpu-sleep */
--- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi
@@ -585,6 +585,7 @@
idle-states {
    entry-method = "psci";
    CPU_SLEEP: cpu-sleep {
        compatible = "arm,idle-state";
        local-timer-stop;
        arm,psci-suspend-param = <0x0010000>;
        entry-latency-us = <100>;
        exit-latency-us = <120>;
        min-residency-us = <1000>;
+       status = "disabled";
    };
};

/* cmdline disable ARM's default wfi, for Android platform, please modify rk3588-android.dtsi */
--- a/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3588-linux.dtsi
@@ -12,7 +12,7 @@
chosen: chosen {
-               bootargs = "earlycon=uart8250,mmio32,0xfeb50000 console=ttyFIQ0 irqchip.gicv3_pseudo_nmi=0 root=PARTUUID=614e0000-0000 rw rootwait rcupdate.rcu_expedited=1 rcu_nocbs=all";
+               bootargs = "earlycon=uart8250,mmio32,0xfeb50000 console=ttyFIQ0 irqchip.gicv3_pseudo_nmi=0 root=PARTUUID=614e0000-0000 rw rootwait rcupdate.rcu_expedited=1 rcu_nocbs=all nohlt";
};

3.3 MPS-Strategie des PCIe-RC

Siehe den Abschnitt zur Konfiguration der Max Payload Size in Rockchip_Developer_Guide_PCIe_CN.pdf. Versuchsweise kann pci=pcie_bus_perf gesetzt werden. Anschließend prüfen, ob der eingestellte MPS von allen angeschlossenen PCIe-Geräten unterstützt wird.

3.4 Bus-QoS des Controllers anpassen

PCIe-Übertragungen, insbesondere DMA, belegen bei hohem Durchsatz Busbandbreite zwischen PCIe-Controller und DRAM und konkurrieren bei der Busarbitrierung mit anderen IP-Blöcken. In solchen Grenzfällen kann der Vorrang durch Anpassung der Bus-QoS des PCIe-Controllers erhöht werden. Die Einstellungen stehen im Anhang zu den PCIe-QoS-Registern der verschiedenen SoCs.

3.5 PCIe-ASPM anpassen

ASPM beeinflusst die Übertragungsleistung und sollte deshalb während der Tests deaktiviert werden. Im tatsächlichen Produkt kann der EP-Funktionstreiber ASPM dynamisch umschalten; geeignete Testszenarien müssen die Echtzeitanforderungen bestätigen.

3.6 CPU-Strategie gegen Jitter beim Zugriff der EP-CPU auf abgebildete Adressen

Wenn PCIe-Master und CPU-Master um DRAM konkurrieren, können folgende Einstellungen den PCIe-Zugriffsjitter reduzieren: Cache-Prefetch des SoC auf der RC-Seite deaktivieren und Write Streaming des SoC auf der RC-Seite deaktivieren. Diese Einstellungen in der Trust Firmware vorsichtig ändern und sicherstellen, dass das Gesamtprodukt weiterhin seine Anforderungen erfüllt.

3.7 Busstrategie gegen Jitter beim Zugriff der EP-CPU auf abgebildete Adressen

Für Anwendungen, die empfindlich auf PCIe-Jitter reagieren, siehe den Anhang zur DRAM-Scheduler-Aging-Anpassung für PCIe einiger SoCs. Beispiel RK3568:

io -4 -w 0xfe100010 0xff010101 # DDR timing configuration, further communication required, can be left unchanged during testing
io -4 -w 0xfe10002c 0x1 # Aging base reduced to 1, which affects all IPs
io -4 -w 0xfe100030 0x1 # The aging coefficient for the channel where PCIe is located is reduced to 1, with both base and coefficient at 1 for the fastest response speed

3.8 Leistungsschwankungen durch fehlerhafte PCIe-Signale überwachen

Anhand des Abschnitts zur Kernel-Stabilitätsstatistik in Rockchip_Developer_Guide_PCIe_CN.pdf prüfen, ob Leistungsschwankungen durch PCIe-Signalprobleme wie erneuten Linkaufbau oder TLP-Replay entstehen. Bei vielen fehlerhaften Paketen zuerst die Signalprobleme beheben und danach die Optimierung fortsetzen.

4. PCIe-Busleistung begrenzen

Wenn PCIe-Verkehr andere Module mit hohen Echtzeitanforderungen beeinträchtigt, etwa VOP-Flimmern beim RK3562, MIPI-CSI-Bildverluste durch PCIe0 beim RK3576, GMAC-Leistungsschwankungen beim RK3568 oder SATA-Leistungseinbußen beim RK3588 verursacht, folgende Maßnahmen einzeln testen. Anhand des QoS-Anhangs den Speicherzugriffs-Vorrang von PCIe senken. Anhand des Shaper-Anhangs die Zugriffsgranularität verkleinern und die Wirkung prüfen. Anhand des Bandbreitenbegrenzungs-Anhangs PCIe begrenzen, bis die betroffenen Module die Produktanforderungen erfüllen. Falls dies nicht hilft, prüfen, ob die chipinternen Datenzugriffsports der betroffenen Module verlegt werden können; einige Anzeigemodule wie vop und vicap besitzen diese Möglichkeit. Geeignete Prioritäts-, Shaper- und Bandbreitenwerte anschließend im Board-DTS festlegen:

  1. Die QoS-Knoten der PCIe-Controller im dtsi anhand des entsprechenden Anhangs ermitteln.
  1. Im Board-DTS den QoS-Knoten referenzieren und die getesteten Prioritäts- und Bandbreitenwerte setzen; Beispiel RK3568 PCIe2x1:
--- a/arch/arm64/boot/dts/rockchip/rk3568-xxx.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-xxx.dts
@@ -2325,16 +2325,25 @@
&qos_pcie2x1{
+       /* Priority parameters */
+       priority-init = <0x202>;
+       /* Bandwidth parameters */
+       mode-init = <0x1>;
+       bandwidth-init = <0x100>;
+       saturation-init = <0x100>;
};
  1. Den Shaper-Knoten im entsprechenden Anhang nachschlagen; Beispiel RK3562 PCIe2x1:
--- a/arch/arm64/boot/dts/rockchip/rk3562-xxx.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3562-xxx.dts
&shaping_pcie{
+   shaping-init = <0x5>;
};

Hinweis: Enthält das SoC-dtsi keinen Shaping-Konfigurationsknoten, lässt sich die Einstellung dort nicht festlegen. Die Registerkonfiguration dann direkt in den Code integrieren.

5. Controller: DMA-Durchsatz

5.1 Theoretische Datenrate

Die theoretische DMA-Rate nähert sich der Rate nach Abzug des TLP-Overheads; siehe den Abschnitt zum TLP-Overhead.

5.2 Testverfahren

5.2.1 Standard-EP-Test

Der Test basiert auf der Entwicklung der Standard-EP-Funktion und Kernel DMATEST. Für Linux siehe die entsprechenden Abschnitte in Rockchip_Developer_Guide_PCIe_CN.pdf, für RT-Thread in Rockchip_Developer_Guide_RT-Thread_PCIe_CN.md.

5.2.2 Weitere Parameter

  1. Hohe CPU- und DDR-Frequenzen einstellen.
  1. Die PCIe-RC-MPS-Strategie auf pci=pcie_bus_perf setzen.
  1. Für besseres Echtzeitverhalten und genaue DMA-Bandbreitenmessung den DMA-Abschluss per PIO abfragen.
diff --git a/drivers/pci/controller/dwc/pcie-dw-dmatest.c b/drivers/pci/controller/dwc/pcie-dw-dmatest.c
index 4b0d4d3e01c8..df4595af962e 100644
--- a/drivers/pci/controller/dwc/pcie-dw-dmatest.c
+++ b/drivers/pci/controller/dwc/pcie-dw-dmatest.c
@@ -231,7 +231,7 @@ struct dma_trx_obj *pcie_dw_dmatest_register(struct device *dev, bool irq_en)
        }

        /* Enable IRQ transfer as default */
-       dmatest_dev->irq_en = irq_en;
+       dmatest_dev->irq_en = false;
        cur_dmatest_dev++;

        return obj;

5.3 Testergebnisse

5.3.1 RK3568: Standard-EP-Test

Testgeräte: RC RK3568-EVB1-DDR4-V10, PCIe 3.0 2 lanes, ARM 1.99G, DDR 1.5G; EP RK3568-IOTEST-DDR3-V10, PCIe 3.0 2 lanes, ARM 1.99G, DDR 1.0G. Ergebnisse:

DMA-Größe 64B 256B 4K 64KB 1MB 4MB
Schreiben 12.2MB/s 51.7MB/s 529.1MB/s 941.6MB/s 1418.2MB/s 1454.3MB/s
Lesen 6.0MB/s 44.3MB/s 442.3MB/s 680.5MB/s 938.9MB/s 1080.2MB/s

5.3.2 RK3588: Standard-EP-Test

Testgeräte: RC RK3588-EVB1-LP4X-V10, PCIe 3.0 4 lanes, große Kerne 2.4G, kleine Kerne 1.8G; EP RK3588-EVB4-LP4X-V10 mit denselben PCIe- und Kernfrequenzangaben.

Ergebnisse:

DMA-Größe 64B 256B 4K 64KB 1MB 4MB
Schreiben 14.7MB/S 60.9MB/S 660.6MB/S 2313.4MB/S 3026.1MB/S 3066.1MB/s
Lesen 13.9MB/S 52.6MB/S 568.7MB/S 1490.5MB/S 1619.8MB/S 1660.6MB/s

5.3.3 RK3588 Gen2x1: Standard-EP-Test

Testgeräte: RC RK3588-EVB1-LP4X-V10, PCIe 3.0 4 lanes, große Kerne 2.4G, kleine Kerne 1.8G; EP RK3588-EVB4-LP4X-V10, PCIe 3.0 4 lanes (auf Gen2 1 lane herabgesetzt), große Kerne 2.4G, kleine Kerne 1.8G. Ergebnisse:

DMA-Größe 64B 256B 4K 64KB 1MB 4MB
Schreiben 3.8MB/S 14.6MB/S 152.7MB/S 362.6MB/S 419.5MB/S 427.1MB/s
Lesen 3.8MB/S 14.7MB/S 146.8MB/S 360.5MB/S 419.2MB/S 427.3MB/s

Dieses Ergebnis dient nur als Referenz. Die DMA-Fähigkeit des RK3588-PCIe3x4-Controllers ist theoretisch anhand des Standardtests für RK3588 zu bewerten.

5.3.4 RK1820 Gen2x1: Standard-EP-Test

Testgeräte: RC RK3588-EVB1-LP4X-V10, PCIe 3.0 4 lanes, große Kerne 2.4G, kleine Kerne 1.8G; EP RK1820-EVB1-V10, PCIe 2.0 1 lane. Ergebnisse für RK1820-SRAM:

DMA-Größe 64B 256B 4K 64KB 128KB 512KB
Schreiben 10MB/S 42MB/S 256MB/S 400MB/S 422MB/s 422MB/s
Lesen 8MB/S 36MB/S 192MB/S 310MB/S 325MB/s 330MB/s

Der Test dient nur als Referenz für die Übertragungsbandbreite. Weitere Tests müssen reale Anwendungen wie den chips_connect-Treiber einbeziehen. Ergebnisse für RK1820-DRAM:

DMA-Größe 64B 256B 4K 64KB 128KB 512KB
Schreiben 10MB/S 42MB/S 256MB/S 401MB/S 402MB/s 410MB/s
Lesen 8MB/S 36MB/S 193MB/S 314MB/S 320MB/s 323MB/s

Der Test dient nur als Referenz für die Übertragungsbandbreite. Weitere Tests müssen reale Anwendungen wie den chips_connect-Treiber einbeziehen.

6. Controller: BAR-Durchsatz

6.1 Einleitung

Der häufigste BAR-Zugriff aus Benutzersicht erfolgt über Load/Store mit 32 Bit. Deshalb basiert der Test auf 32-Bit-Load/Store im Userspace; gelesen und geschrieben wird über pci_mmap_resource von Linux PCIe sysfs.

6.2 Testanwendung

Details stehen im Quellcode resource_mmap_test.c im Anhang. Dort eine mmap-Ressource mit Device-Memory-Attributen auswählen, beispielsweise resource2. Übersetzen der Anwendung am Beispiel RK3588 Android:

/home1/ldq/rk-linux/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc -mcpu=cortex-a76 -O0 -static -DROPT -o resource_mmap_test resource_mmap_test.c

Die Optimierungsstufe -O0 ist erforderlich, damit Lese- und Schreibbefehle nicht wegoptimiert werden.

6.3 Testergebnisse

RC EP Store 32bits Load 32bits
RK3568 PCIe 3.0 2 lanes RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 52.5MB/s 3.7MB/s
RK3568 PCIe 2.0 1 lane RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 36.0MB/s 2.4MB/s
RK3588 PCIe 3.0 4 lanes RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 53.3MB/s 4.2MB/s
RK3588 PCIe 2.0 1 lane RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 26.7MB/s 2.6MB/s
RK3528 PCIe 2.0 1 lane RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 67.7MB/s 2.3MB/s
RK3562 PCIe 2.0 1 lane RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 66.3MB/s 2.3MB/s
RK3572 PCIe 2.0 1 lane RK3588 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 67.7MB/s 2.4MB/s

Die Ergebnisse für 64bits-pref (resource0..N) stimmen mit 32bits-np (resource0..N) überein.

6.4 Optimierungsrichtungen

6.4.1 Datenbreite erhöhen

Der Engpass beim BAR-Lesen und -Schreiben liegt hauptsächlich in der Anzahl der TLPs. Mehr Nutzdaten je TLP verringern deren Anzahl: Eine größere Datenbreite der Load/Store-Anforderungen auf dem Bus reduziert die Gesamtzahl. Typische BAR-Zugriffe sind Userspace-Load/Store mit 32 Bit; maßgeblich ist das tatsächliche Assemblerergebnis, beispielsweise:

str    w1, [x0]

Userspace-SIMD-Load/Store mit 128 Bit entstehen üblicherweise durch Compileroptimierung. Bei einem SoC mit SIMD kann beispielsweise -O3 dies erreichen; maßgeblich ist das Assemblerergebnis:

str    q1, [x1], #16

Kernel-Load/Store mit 32 Bit. Kernel-Schnittstellen memset_io/memcpy_fromio. Ergebnisse am Beispiel RK3588:

Zugriffsart Schreiben (MB/s) Lesen (MB/s)
Benutzermodus Load/Store 32bits 53 4
Benutzermodus Load/Store SIMD 128bits 203 16
Kernelmodus Load/Store 32bits 53 4
Kernelmodus memset_io/memcpy_fromio 106 7

Testumgebung: RC RK3588-EVB1-LP4X-V10, PCIe 3.0 4 lanes, große Kerne 2.4G, kleine Kerne 1.8G; EP RK3588-EVB4-LP4X-V10, PCIe 3.0 4 lanes, große Kerne 2.4G, kleine Kerne 1.8G. Userspace-Load/Store mit 32 Bit, V8-a-Assemblerbeispiel:

LDR <Wt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
STR <Wt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]

Userspace-SIMD-Load/Store mit 128 Bit, V8-a-Assemblerbeispiel:

LDR <Qt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]
STR <Qt>, [<Xn|SP>, (<Wm>|<Xm>){, <extend> {<amount>}}]

Kernel-Load/Store mit 32 Bit.

6.4.2 Multithreading: ohne Wirkung

Mehrere Instanzen von resource_mmap_test.c lesen und schreiben gleichzeitig verschiedene BARs. Der Logikanalysator zeigte keine erhöhte Busauslastung. Die tatsächliche Bandbreite stieg nicht wesentlich (höchstens 10 %), und auch ihre Auslastung nahm nicht zu; ein Wechsel der TLPs zwischen verschiedenen BAR-Räumen war jedoch zu beobachten.

7. Controller: ELBI-Interrupt-Reaktionsrate

7.1 Einleitung

ELBI (Endpoint Local Interrupt Bypass) wird im DWC-PCIe-EP-Modus über die Abbildung des EP-Konfigurationsraums umgesetzt. Der RC löst durch Schreiben der dort abgebildeten ELBI-Register einen EP-Interrupt aus und verbessert damit die Reaktionsfähigkeit des EP-Systems. Die ELBI-Reaktionsrate hängt vor allem von EP-Systembusbandbreite, Treiberoptimierung und Prozessorleistung ab.

7.2 Testanwendung

PCIe-ELBI-Sendecode auf der RC-Seite:

#include <linux/kthread.h>

// Create a new kernel thread to trigger ELBI interrupts
static int pcie_rkep_elbi_test_real(void *p)
{
    struct pcie_rkep *pcie_rkep = (struct pcie_rkep *)p;

    // In an infinite loop, call the rockchip_pcie_raise_elbi_irq function to trigger ELBI interrupts (using IRQ number 0)
    while(1)
        rockchip_pcie_raise_elbi_irq(pcie_rkep, 0);
}

// Use the pcie_rkep_elbi_test_real function to create a kernel thread to trigger ELBI interrupts
static int pcie_rkep_elbi_test(struct pcie_rkep *pcie_rkep)
{
    struct task_struct *tsk;

    // Use the pcie_rkep_test function to perform some test operations
    pcie_rkep_test(pcie_rkep);

    // Create a kernel thread named "rkep-elbi" and pass pcie_rkep as a parameter to the pcie_rkep_elbi_test_real function
    tsk = kthread_run(pcie_rkep_elbi_test_real, pcie_rkep, "rkep-elbi");
    if (IS_ERR(tsk)) {
        pr_err("rkep elbi start rk-pcie thread failed\n");
        return PTR_ERR(tsk);
    }

    return 0;
}

Integration des PCIe-ELBI-Sendecodes auf der RC-Seite:

 static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int ret, i;
@@ -774,6 +812,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                 pcie_rkep->obj_info->version);

        device_create_file(&pdev->dev, &dev_attr_rkep);
+       pcie_rkep_elbi_test(pcie_rkep);

        return 0;
 err_register_obj:

PCIe-ELBI-Geschwindigkeitsmesscode auf der EP-Seite:

#include <linux/kthread.h>

// Create a new kernel thread to measure the triggering frequency of ELBI interrupts
static int pcie_rkep_elbi_test_real(void *p)
{
    struct rockchip_pcie *rockchip = (struct rockchip_pcie *)p;
    int cur_count, last_count = rockchip->elbi_count;
    u64 us = 0;

    // In an infinite loop, perform the following operations every 1 second
    while(1) {
        msleep(1000); // Wait for 1 second

        // Get the current ELBI interrupt count
        cur_count = rockchip->elbi_count;

        // If the current interrupt count is not 0, calculate the time interval between the last and current interrupt counts (in microseconds)
        if (cur_count) {
            us = 1000000 / (cur_count - last_count);
        }

        // Print the current ELBI interrupt count and triggering frequency
        pr_err("elbi count=%d %lluus\n", cur_count, us);

        // Update the last interrupt count
        last_count = rockchip->elbi_count;
    }
}

// Use the pcie_rkep_elbi_test_real function to create a kernel thread to measure the triggering frequency of ELBI interrupts
static __maybe_unused int pcie_rkep_elbi_test(struct rockchip_pcie *rockchip)
{
    struct task_struct *tsk;
    // Create a kernel thread named "rkep-elbi" and pass rockchip as a parameter to the pcie_rkep_elbi_test_real function
    tsk = kthread_run(pcie_rkep_elbi_test_real, rockchip, "rkep-elbi");
    if (IS_ERR(tsk)) {
        pr_err("rkep elbi start rk-pcie thread failed\n");
        return PTR_ERR(tsk);
    }

    return 0;
}

Integration des PCIe-ELBI-Messcodes auf der EP-Seite:

 static int rockchip_pcie_ep_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
@@ -1276,6 +1316,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
                goto deinit_phy;

        rockchip_pcie_add_misc(rockchip);
+       pcie_rkep_elbi_test(rockchip);

        return 0;

7.3 Testergebnisse

RC EP Standardlatenz (us)
RK3568-EVB1-DDR4-V10 PCIe 3.0 2 lanes ARM: 1.99G DDR: 1.5G RK3568-IOTEST-DDR3-V10 PCIe 3.0 2 lanes ARM: 1.99G DDR: 1.0G 6
RK3588-EVB1-LP4X-V10 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G RK3588-EVB4-LP4X-V10 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 6

Konkrete Implementierung und Anwendungsszenarien hängen von Systemkonfiguration, Hardwareplattform und Treiberanforderungen ab.

7.4 Optimierungsrichtung

Die ELBI-Reaktionsrate hängt hauptsächlich von EP-Busbandbreite, Treiberoptimierung und Prozessorleistung ab. Beispiel RK3588:

Modell Standardlatenz (us) Register-Lese-/Schreibrate (us/s) Latenz bei deaktiviertem CPU_SLEEP (us) Latenz bei fester maximaler CPU-Frequenz (us)
RK3588 6 2 6 4

Die Register-Lese-/Schreibrate ist die maximale Rate, mit der der RC ELBI-Anforderungen über ELBI write config erzeugt. Wegen der Interrupt-Scheduling-Reaktionszeit des EP liegt die tatsächlich erreichte Reaktionsrate darunter.

8. Controller: MSI-Interrupt-Reaktionsrate

8.1 Einleitung

MSI (Message Signaled Interrupt) ist ein PCIe-Interruptübertragungsmechanismus: Eine Nachricht an eine bestimmte Adresse löst einen Interrupt aus. Ein Gerät kann mehrere Nachrichtenadressen besitzen, die jeweils einem Interrupt entsprechen. Dies ermöglicht parallele Verarbeitung und verbessert Reaktionsgeschwindigkeit sowie Systemleistung. Die MSI-Reaktionsrate hängt von RC-Systembusbandbreite, Treiberoptimierung und Prozessorleistung ab. Allgemein kann MSI die Interruptlatenz deutlich senken und auch unter hoher Last gute Reaktionsraten erhalten.

8.2 Testanwendung

PCIe-MSI-Sendecode auf der EP-Seite:

#include <linux/kthread.h>

// PCIe MSI RC and EP endpoint example code

static int pcie_rkep_elbi_test_real(void *p)
{
    struct rockchip_pcie *rockchip = (struct rockchip_pcie *)p;

    // EP endpoint continuously sends MSI interrupts to the RC endpoint
    while(1) {
        rockchip_pcie_raise_msi_irq(rockchip, 0);
    }
}

static int pcie_rkep_elbi_test(struct rockchip_pcie *rockchip)
{
    struct task_struct *tsk;

    // Create a kernel thread to execute the pcie_rkep_elbi_test_real function
    tsk = kthread_run(pcie_rkep_elbi_test_real, rockchip, "rkep-elbi");

    // Check if the thread creation was successful
    if (IS_ERR(tsk)) {
        pr_err("Failed to start rkep elbi thread\n");
        return PTR_ERR(tsk);
    }

    return 0;
}

Integration des PCIe-MSI-Sendecodes auf der EP-Seite:

 static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int ret, i;
@@ -774,6 +812,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                 pcie_rkep->obj_info->version);

        device_create_file(&pdev->dev, &dev_attr_rkep);
+       pcie_rkep_elbi_test(pcie_rkep);

        return 0;
 err_register_obj:

PCIe-MSI-Geschwindigkeitsmesscode auf der RC-Seite:

#include <linux/kthread.h>

static int pcie_rkep_elbi_test_real(void *p)
{
    struct pcie_rkep *pcie_rkep = (struct pcie_rkep *)p;
    int cur_count, last_count = pcie_rkep->msi_count;
    u64 us = 0;

    // Execute in an infinite loop, printing the current msi_count value and the time interval between two prints once per second
    while(1) {
        msleep(1000);
        cur_count = pcie_rkep->msi_count;
        if (cur_count) {
            us = 1000000 / (cur_count - last_count); // Calculate the time interval (microseconds)
        }
        pr_err("msi count=%d %lluus\n", cur_count, us); // Print msi_count and time interval
        last_count = pcie_rkep->msi_count;
    }
    return 0;
}

static __maybe_unused int pcie_rkep_elbi_test(struct pcie_rkep *pcie_rkep)
{
    struct task_struct *tsk;

    tsk = kthread_run(pcie_rkep_elbi_test_real, pcie_rkep, "rkep-elbi"); // Create a kernel thread to execute the pcie_rkep_elbi_test_real function
    if (IS_ERR(tsk)) {
        pr_err("rkep elbi start rk-pcie thread failed\n");
        return PTR_ERR(tsk);
    }

    return 0;
}

Aufrufbeispiel für den PCIe-MSI-Messcode auf der RC-Seite:

 static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int ret, i;
@@ -774,6 +812,7 @@ static int pcie_rkep_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                 pcie_rkep->obj_info->version);

        device_create_file(&pdev->dev, &dev_attr_rkep);
+       pcie_rkep_elbi_test(pcie_rkep);

        return 0;
 err_register_obj:

8.3 Testergebnisse

RC EP Standardlatenz (us)
RK3568-EVB1-DDR4-V10 PCIe 3.0 2 lanes ARM: 1.99G DDR: 1.5G RK3568-IOTEST-DDR3-V10 PCIe 3.0 2 lanes ARM: 1.99G DDR: 1.0G 2
RK3588-EVB1-LP4X-V10 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G RK3588-EVB4-LP4X-V10 PCIe 3.0 4 lanes Großer Kern 2.4G Kleiner Kern 1.8G 2

Konkrete Implementierung und Anwendungsszenarien hängen von Systemkonfiguration, Hardwareplattform und Treiberanforderungen ab.

8.4 Optimierungsrichtung

Die MSI-Ratenoptimierung entspricht der ELBI-Optimierung; Einzelheiten stehen im Abschnitt zur ELBI-Interrupt-Reaktionsrate des Controllers.

9. Controller: Reaktionsrate der Peripherie-CPU beim Zugriff auf abgebildete Adressen

9.1 Einleitung

PCIe ermöglicht CPU-Zugriffe auf der RC-Seite über BAR zum Lesen/Schreiben von Peripheriedaten sowie CPU-Zugriffe auf der EP-Seite über abgebildete Adressen zum Lesen/Schreiben von RC-Daten.

Englische Originalabbildung — 24

Englische Originalabbildung — 24

9.2 Testanwendung

Outbound für RK3588 EP konfigurieren. Die CPU greift auf die Outbound-Adresse zu und schreibt und liest anschließend; diesen Zyklus 10.000-mal wiederholen. RC-Test: CPU/DRAM auf hohe Frequenz setzen. Standardmäßig keine Zusatzlast; Lasten entsprechend dem Produktszenario ergänzen.

EP: test_memory unter U-Boot; EP-Befehlsbeispiel:

#define TEST_ITERATIONS 3000000

#define TEST_RECORD_LENGTH 256
static uint32_t record[TEST_RECORD_LENGTH];
static volatile uint32_t value;
static uint32_t max_duration;
static uint32_t total_duration;
static uint32_t loops;

void test_memory(volatile uint32_t *address) {
    ulong duration;

    int i;

    printf("Memory write-read test starting...\n");

    for (i = 0; i < TEST_ITERATIONS; i++) {
        // Get start time
        duration = get_ticks();

        // Write to memory
        *address = 0x12345678;

        // Read from memory
        value = *address;

        // Get end time
        duration = get_ticks() - duration;

        // Update maximum duration
        if (duration > max_duration) {
            max_duration = duration;
        }

        // Accumulate total duration
        total_duration += duration;
        //printf("Iteration %d: %lu ticks\n", i + 1, duration);
        record[duration]++;
    }

    // Calculate average duration
    uint32_t average_duration = total_duration / (loops * TEST_ITERATIONS);

    printf("Maximum duration: %u ticks %lu us\n", max_duration, max_duration / (gd->arch.timer_rate_hz / 1000000));
    printf("Average duration: %u ticks %lu us\n", average_duration, average_duration / (gd->arch.timer_rate_hz / 1000000));
    printf("ticks - count (24tick/1us)\n");
    for (i = 0; i < TEST_RECORD_LENGTH; i++) {
        if (record[i])
            printf("%d - %d\n", i, record[i]);
    }
}

static int main(void)
{
        printf("mmio mem\n");
        memset(record, 0, 4 * TEST_RECORD_LENGTH);
        max_duration = 0;
        total_duration = 0;
        for (loops = 1; loops < 1000; loops++) {
            test_memory((volatile u32 *)(0xf0000000));
        }
    }
}

9.3 Testergebnisse

9.3.1 RK3566 Gen2x1

Grundumgebung: RC RK_EVB_3566_LP4X_V10, standardmäßig PCIe Gen2x1, mps 128B; EP RK3588 EVB1, PCIe Gen3x4. Ergebnisse:

Beschreibung Mittelwert (us) Maximum (us)
Grundtest 1.7 2.3
DRAM-Lasttest 1.9 7.9

Ohne RC-DRAM-Last ist der Jitter der EP-CPU beim Zugriff auf den abgebildeten PCIe-Raum gering, mit RC-DRAM-Last deutlich. Übliche Maßnahmen stehen in den Abschnitten zur CPU- und Busstrategie gegen diesen Zugriffsjitter. Die RC-DRAM-Lasttests umfassen Bit Flip und Reversed Mem.

10. Peripherie: NVMe-Durchsatz

10.1 Testverfahren

10.1.1 CrystalMark mit fio nachbilden

Test Unterpunkt Testbefehl Einheit
SEQ1M Q32T1 READ   adb shell ./data/fio -filename=/mnt/test -direct=1 -iodepth 32 -thread -rw=read -ioengine=libaio -bs=1024K -size=10G -numjobs=1 -runtime=180 -group_reporting -name=read_seq_1024k_q32_t1 MB/s
SEQ1M Q32T1 WRITE   adb shell ./data/fio -filename=/mnt/test -direct=1 -iodepth 32 -thread -rw=write -ioengine=libaio -bs=1024K -size=10G -numjobs=1 -runtime=180 -group_reporting -name=write_seq_1024k_q32_t1 MB/s
RND4K Q32T1 READ Durchsatz adb shell ./data/fio -filename=/mnt/test -direct=1 -iodepth 32 -thread -rw=randread -ioengine=libaio -bs=4K -size=4G -numjobs=1 -runtime=180 -group_reporting -name=read_rand_4k_q32_t1 MB/s K(IOPS)
RND4K Q32T1 WRITE Durchsatz adb shell ./data/fio -filename=/mnt/test -direct=1 -iodepth 32 -thread -rw=randwrite -ioengine=libaio -bs=4K -size=4G -numjobs=1 -runtime=180 -group_reporting -name=write_rand_4k_q32_t1 MB/s K(IOPS)

Fehlt libaio in der Testumgebung, kann psync verwendet werden. psync simuliert mit mehreren Threads synchron die parallele gebündelte Übergabe von I/O-Anforderungen an den Kernel. libaio nutzt Kernel Native AIO und kann einen ganzen Anforderungsstapel auf einmal übergeben. Gegenüber psync verursacht dies weniger Aufwand, bietet bessere Leistung und eignet sich besser zur NVMe-Bewertung. ext4 im laufenden System erstellen, Beispiel Linux:

mkfs.ext4 /dev/nvme0n1
mount -t ext4 /dev/nvme0n1 /mnt

f2fs im laufenden System erstellen, Beispiel Android:

make_f2fs /dev/block/nvme0n1
mount -t f2fs -o fsync_mode=nobarrier /dev/block/nvme0n1 /mnt

10.2 Testergebnisse

10.2.1 RK3568 Gen3x2

Hostcontroller RK3568 EVB1 PCIe Gen3x2. Der Gen3x2-Übertragungsengpass liegt hauptsächlich im PCIe-Controller; daher werden CPU/DDR mit Standardparametern betrieben. Peripherie: Samsung 980 M.2 NVMe SSD 1TB PCIe Gen3x4. Ergebnisse der CrystalDiskMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 1510 \
SEQ1M Q32T1 WRITE 1488 \
RND4K Q32T1 READ 152 40
RND4K Q32T1 WRITE 145 37

10.2.2 RK3588 Gen3x4

Host RK3588 EVB1 PCIe Gen3x4, Port0/1 x4 RC. Feste Frequenzen: große Kerne 2.4G, kleine Kerne 1.8G; mq-deadline, f2fs nobarrier, LPDDR4X 2112MHz. Peripherie: Samsung 980 M.2 NVMe SSD 1TB PCIe Gen3x4. PC-CrystalDiskMark-Ergebnisse:

PC CrystalMark 8.0.1 Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 3222 \
SEQ1M Q32T1 WRITE 2600 \
RND4K Q32T1 READ 708 \
RND4K Q32T1 WRITE 486 \

Ergebnisse der CrystalMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 3219.2 \
SEQ1M Q32T1 WRITE 3108.7 \
RND4K Q32T1 READ 794 203
RND4K Q32T1 WRITE 647 165

10.2.3 RK3588 Gen3x2

Host RK3588 EVB1 PCIe3x4, Port0 x2 RC. Feste Frequenzen: große Kerne 2.4G, kleine Kerne 1.8G; mq-deadline, f2fs nobarrier, LPDDR4X 2112MHz. Peripherie: PHISON 128G BGA SSD. PC-CrystalDiskMark-Ergebnisse:

CrystalMark 8.0.1 Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 1615 \
RND4K Q32T1 READ 434 \
SEQ1M Q32T1 WRITE 626 \
RND4K Q32T1 WRITE 230 \

Ergebnisse der CrystalMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 1572.4 \
SEQ1M Q32T1 WRITE 600 \
RND4K Q32T1 READ 422 101
RND4K Q32T1 WRITE 355 90

10.2.4 RK3588s Gen2x1

Host RK3588s EVB1 PCIe2x1l1, Port0 x1 RC. Feste Frequenzen: große Kerne 2.4G, kleine Kerne 1.8G; mq-deadline, f2fs nobarrier, LPDDR4X 2112MHz.

Peripherie: PHISON 128G BGA SSD. Ergebnisse der CrystalDiskMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 407 \
SEQ1M Q32T1 WRITE 350 \
RND4K Q32T1 READ 400 102
RND4K Q32T1 WRITE 134 32

10.2.5 RK3528 Gen2x1

Host RK3528 EVB2, PCIe-Gen2x1-Controller. Der Gen2x1-Übertragungsengpass liegt vollständig im PCIe-Controller; deshalb bleiben CPU/DDR und weitere Testgeräteparameter auf Standardwerten. Peripherie: Samsung 980 M.2 NVMe SSD 1TB PCIe Gen3x4. Ergebnisse der CrystalDiskMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 410 \
SEQ1M Q32T1 WRITE 392 \
RND4K Q32T1 READ 327 83
RND4K Q32T1 WRITE 300 76

10.2.6 RK3562 Gen2x1

Host RK3562 EVB1, PCIe-Gen2x1-Controller. Der Gen2x1-Übertragungsengpass liegt vollständig im PCIe-Controller; deshalb bleiben CPU/DDR und weitere Testgeräteparameter auf Standardwerten. Peripherie: Samsung 980 M.2 NVMe SSD 1TB PCIe Gen3x4.

Ergebnisse der CrystalDiskMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 409 \
SEQ1M Q32T1 WRITE 391 \
RND4K Q32T1 READ 343 85
RND4K Q32T1 WRITE 253 63

10.2.7 RK3576 Gen2x1

Host RK3576 EVB1, PCIe-Gen2x1-Controller. Der Gen2x1-Übertragungsengpass liegt vollständig im PCIe-Controller; deshalb bleiben CPU/DDR und weitere Testgeräteparameter auf Standardwerten. Peripherie: Samsung 980 M.2 NVMe SSD 1TB PCIe Gen3x4. Ergebnisse der CrystalDiskMark-8.0.1-Nachbildung mit fio:

Testname Übertragungsrate MB/s IOPS (K)
SEQ1M Q32T1 READ 397 \
SEQ1M Q32T1 WRITE 391 \
RND4K Q32T1 READ 313 78
RND4K Q32T1 WRITE 255 63

11. Anhang

11.1 PCIe-Controller-QoS-Register verschiedener SoCs

Die Registerbefehlsbeispiele in der Tabelle stellen die höchste zulässige Priorität ein; nach Testbedingungen anpassen.

Chip Controller Registerbefehl Knoten im dtsi
RK1808 pcie0 io -4 0xfe880008 0x303 qos_pcie
RK3528 pcie2x1 io -4 0xff280188 0x404 qos_pcie
RK3562 pcie2x1 io -4 0xfeea0008 0x404 qos_pcie
RK3566 RK3568 pcie2x1 io -4 0xfe190008 0x80000303 qos_pcie2x1
RK3566 RK3568 pcie3x1 io -4 0xfe190088 0x80000303 qos_pcie3x1
RK3566 RK3568 pcie3x2 io -4 0xfe190108 0x80000303 qos_pcie3x2
RK3576 pcie0 io -4 0x27f0a008 0x303 qos_mmu0
RK3576 pcie1 io -4 0x27f0a088 0x303 qos_mmu1
RK3588 PCIe1L0/1/2 io -4 0xfdf3a008 0x404 qos_gic600_m0
RK3588 PCIe3x4 PCIe3x2 io -4 0xfdf3a208 0x404 qos_gic600_m1

11.2 PCIe-Controller-Shaper-Register einiger SoCs

Die Tabelle nennt Chips mit Shaper-Registern. Das Befehlsbeispiel setzt die maximal zulässige Zugriffsgranularität 0xff. Zulässig sind 0x1 bis 0xff; kleinere Werte bedeuten feinere Granularität. Nach tatsächlichen Testergebnissen anpassen.

Chip Controller Registerbefehl Shaping-Knoten im dtsi
RK3562 pcie2x1 io -4 0xfeea0088 0xff shaping_pcie
RK3576 pcie0 io -4 0x27f0a108 0xff Keiner
RK3576 pcie1 io -4 0x27f0a188 0xff Keiner
RK3588 PCIe1L0/1/2 io -4 0xfdf3a088 0xff Keiner
RK3588 PCIe3x4 PCIe3x2 io -4 0xfdf3a288 0xff Keiner

11.3 PCIe-Bandbreitenbegrenzungsregister einiger SoCs

Der zulässige Bereich reicht von 0 bis 0x1ff; ein kleinerer Wert bedeutet eine niedrigere PCIe-Bandbreitengrenze.

Chip Controller Registerbefehl
RK3562 pcie2x1 io -4 0xfeea000c 0x1
io -4 0xfeea0010 value
io -4 0xfeea0014 value
RK3566 RK3568 pcie2x1 io -4 0xfe19000c 0x1
io -4 0xfe190010 value
io -4 0xfe190014 value
RK3566 RK3568 pcie3x1 io -4 0xfe19008c 0x1
io -4 0xfe190090 value
io -4 0xfe190094 value
RK3566 RK3568 pcie3x2 io -4 0xfe19010c 0x1
io -4 0xfe190110 value
io -4 0xfe190114 value
RK3576 pcie0 io -4 0x27f0a00c 0x1
io -4 0x27f0a010 value
io -4 0x27f0a014 value
RK3576 pcie1 io -4 0x27f0a08c 0x1
io -4 0x27f0a090 value
io -4 0x27f0a094 value
RK3588 PCIe1L0/1/2 io -4 0xfdf3a00c 0x1
io -4 0xfdf3a010 value
io -4 0xfdf3a014 value
RK3588 PCIe3x4 PCIe3x2 io -4 0xfdf3a20c 0x1
io -4 0xfdf3a210 value
io -4 0xfdf3a214 value

11.4 PCIe-bezogene DRAM-Scheduler-Aging-Anpassung einiger SoCs

Chip Controller Registerbefehl Anmerkungen
RK3568 PCIe2x1/PCIe3x2/PCIe3x1 io -4 0xfe10002c 0x1
io -4 0xfe100030 0x1
Aging0 des Pfads zu DDR anpassen
RK3588(S) PCIe1L0/1/2 io -4 0xfe00002c 0x1
io -4 0xfe00003c 0x1
io -4 0xfe00202c 0x1
io -4 0xfe00203c 0x1
io -4 0xfe00402c 0x1
io -4 0xfe00403c 0x1
io -4 0xfe00602c 0x1
io -4 0xfe00603c 0x1
Port3 (aging3) aller vier Kanäle anpassen
RK3588(S) PCIe3x4 PCIe3x2 io -4 0xfe00002c 0x1
io -4 0xfe000038 0x1
io -4 0xfe00202c 0x1
io -4 0xfe002038 0x1
io -4 0xfe00402c 0x1
io -4 0xfe004038 0x1
io -4 0xfe00602c 0x1
io -4 0xfe006038 0x1
Port2 (aging2) aller vier Kanäle anpassen

Dieses Thema entdecken → · Lernpfade →