[[dtlab_t11]]

Rust auf Pi Pico

Bei diesem Thema untersuchen Sie wie schnell der ARM Cortex M0 auf dem Raspberry Pi Pico arbeitet. Dazu wird der Ausgang an einem GPIO geändert und die Änderung wird mit dem Oszilloskop gemessen. Dazu kommt dann die Messung der Ausführungszeit einer Primzahlensuche auf dem RP2040 und der Vergleich mit einer Ausführung auf dem Hostsystem. Der Code ist in Rust geschrieben.

Die Toolchain ist die gleiche wie im von Claudia Meitinger.

  • auf ihrem Rechner
  • Installieren Sie oder Microsoft Codium
  • In Codium:

FĂĽr Rust noch

rustup target add thumbv6m-none-eabi
cargo install elf2uf2-rs

Im ist ein git Repository, das die zwei Projekte

  • blinky - FĂĽr den Pi Pico
  • prime - FĂĽr den Hostrechner

enthält. Sie können das Repository auf ihrem Rechner mit

git clone https://caeis.etech.fh-augsburg.de/beckmanf/picofirst.git

installieren.

Das Rustprojekt Blinky enthält ein kleines Programm mit dem auf dem Pi Pico Board ohne Wifi die Onboard LED ein- und ausgeschaltet wird. Wechseln Sie in das Verzeichnis “picofirst/blinky”. Sie können das Programm mit

cargo run

kompilieren und auf den Raspberry Pi Pico laden. Das funktioniert nur wenn der Pi Pico im Mass Storage Mode ist. Dazu muss der “BOOTSEL” Taster auf dem Board gedrückt und gehalten werden während man das USB Kabel mit dem Rechner verbindet. Man kann sehen, dass der Pi Pico im Mass Storage Mode ist, wenn ein neues Laufwerk im Betriebssystem angezeigt wird. Mit “cargo run” wird das Programm kompiliert, auf den Pi Pico geladen. Damit wird der Mass Storage Mode verlassen und der Code ausgeführt.

Auf dem Pi Pico sollte jetzt die LED blinken.

Die blinkende LED dient zur ĂśberprĂĽfung, dass die Toolchain und der Pi Pico richtig funktioniert. Auf dem Pi Pico W mit Wifi ist die LED nicht direkt am RP2040 Prozessor angeschlossen, sondern am Wifichip CYW43439. Um dort die LED anzusteuern muss der Wifichip in Betrieb genommen werden. Das habe ich deshalb hier nicht gemacht.

Das Projekt “prime” enthält ein Programm zur Suche nach Primzahlen. Das Programm soll nicht auf dem Pi Pico, sondern auf dem Host - also ihrem Rechner oder dem Laborrechner - ausgeführt werden. Wechseln Sie in das Verzeichnis “picofirst/prime”. Sie können das Programm direkt mit

cargo run

starten. Das Programm in sucht die nächstkleinere Primzahl ausgehend von einer Zahl, die im Programm festgelegt ist. Die Zahl n ist im Code im Repository auf “1«56” = 2^56 = 72057594037927936 festgelegt. Sie sollten auf dem Terminal eine ähnliche Ausgabe wie diese sehen:

Mac:prime fritz$ cargo run
   Compiling prime v0.1.0 (/Users/fritz/pico/picofirst/prime)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/prime`
What is the next prime number smaller than 72057594037927936?
Found: 72057594037927931. This took 2.328603083s.
Mac:prime fritz$ 

Das Programm dient dazu eine Berechnung durchzuführen, die etwas länger dauert. Starten Sie das Programm einige Male und notieren Sie die Ausführungszeiten. In “blinky” ist diese Primzahlensuchfunktion auch schon integriert, aber noch nicht aktiv.

Kompilieren Sie das Programm jetzt im “Release” Modus. Damit wird der Rustcompiler eine höhere Codeoptimierung durchführen.

cargo run --release

Sie können das Programm nach dem Kompilieren auch direkt starten mit

./target/release/prime
./target/debug/prime

Vergleichen Sie die AusfĂĽhrungszeiten.

  • Schätzen Sie anhand des Rustcodes fĂĽr die Primzahlensuche ab, wie sich die AusfĂĽhrungszeit mit der Zahl n verhält. Es geht nicht um die absolute Zeit, sondern ob der Zusammenhang zwischen AusfĂĽhrungszeit und Zahl konstant, linear oder sonstwie ist.

In diesem Versuch soll jetzt nicht mehr die LED wechseln, sondern der Pin GP15 in Abbildung 1 links unten.

Abb. 1: Rasperry Pi Pinout

Dazu muss der Code in geändert werden.

  • Kommentieren Sie die delays in der loop aus. In der loop soll nur der Pin aus- und eingeschaltet werden.
  • Ă„ndern Sie den Pin von GP25 fĂĽr die LED auf GP15 fĂĽr den Pin links unten.
  • Messen Sie mit dem Oszilloskop die Frequenz und das an/aus Verhältnis des Signals am Pin 15.
  • Testen Sie “cargo run” und “cargo run –release”

Man kann sich mit

cargo rustc --release -- --emit asm

den Assemblercode generieren lassen. Der Assemblercode ist im Verzeichnis target/thumbv6m-none-eabi/release/deps und fängt mit dem Projektnamen “blinky” and und endet mit der Endung “.s”. Ein Pfad kann z.B. so aussehen: “target/thumbv6m-none-eabi/release/deps/blinky-cbc27bc4200d17af.s”.

Öffnen Sie die Datei mit Codium. Die Datei enthält sehr viel Code… Finden Sie die Schleife. Fügen Sie dazu die delay Funktionen nochmal in den Code ein und kompilieren Sie nochmal. Dann sollten Sie etwas ähnliches wie das hier:

	ldr	r6, .LCPI2_8
.LBB2_6:
	ldr	r0, .LCPI2_5
	str	r4, [r0]
	add	r5, sp, #8
	mov	r0, r5
	mov	r1, r6
	bl	_ZN8cortex_m5delay5Delay8delay_us17hb904cf74fb062a91E
	ldr	r0, .LCPI2_5
	str	r4, [r0, #4]
	mov	r0, r5
	mov	r1, r6
	bl	_ZN8cortex_m5delay5Delay8delay_us17hb904cf74fb062a91E
	b	.LBB2_6
.LBB2_7:
	strb	r5, [r0]

finden. Sie sehen die “cortex_m5delay” Funktionen. Das sind die Aufrufe für die delay Funktion. Nehmen Sie dann die Delayaufrufe wieder aus dem Code. Die Loop sollte jetzt kürzer sein. Erläutern Sie den Code, der den Pin 15 an- und ausschaltet.

Im finden Sie im Kapitel 2.3.1.7 die Register

  • SIO: GPIO_OUT_SET
  • SIO: GPIO_OUT_CLR

mit denen der Pegel an einem Pin eingestellt werden kann. Wenn man beispielsweise 1«3 = 0x00000008 in das Register GPIO_OUT_SET schreibt, dann wird der Ausgangspegel von GP03 auf High gesetzt. Damit das funktioniert muss vorher die Konfiguration des Pins gemacht werden - also beispielsweise, dass das ein Ausgang ist.

  • Erläutern Sie im Code wie auf die beiden Register geschrieben wird.

Die Primzahlensuche dauert im Vergleich zu dem Ein- und Ausschalten der Pins relativ lang. Jetzt geht es darum die AusfĂĽhrungszeiten auf dem Pi Pico mit den AusfĂĽhrungszeiten auf dem Hostrechner zu vergleichen. Dazu sollen die AusfĂĽhrungszeiten auf dem Pi Pico mit dem Oszilloskop gemessen werden.

  • FĂĽgen Sie die Primzahlensuchfunktion in die Loop ein.
  • Aktivieren Sie das Delay nach dem Ausschalten der LED/Pins.
  • Die Zeitdauer wie lange das Signal am Pin auf High ist, soll durch die Laufzeit der Primzahlensuche bestimmt sein. Die Zeitdauer wie lange das Signal auf low ist, soll konstant durch die Delayfunktion bestimmt sein.
  • Verändern Sie die Werte fĂĽr die Zahl n, messen Sie die Highphasen am Oszilloskop und notieren Sie die Zeiten
  • Erstellen Sie einen Graphen, der die AusfĂĽhrungszeit gegen die Zahl n darstellt.
  • Vergleichen Sie den Graphen mit den Ăśberlegungen aus Vorbereitung fĂĽr “prime”
  • Vergleichen Sie die AusfĂĽhrungszeit auf dem Pi Pico mit der AusfĂĽhrungszeit auf dem Host.

Um die Pins ein- und auszuschalten haben wir im Code die Funktionen wie “led_pin.set_low().unwrap()” aus dem “Hardware-Abstraction-Layer” HAL verwendet. Jetzt soll direkt auf die Register geschrieben werden. Das kann mit der Funktion “write_volatile(REG, 1«25)” gemacht werden. Die Funktion muss als “unsafe” markiert werden. Kommentieren Sie den Code für die Definition des REG Wertes und das “write_volatile” aus und ersetzten so den “led_pin.set_low()” Code.

  • Ersetzten Sie led_pin.set_low() durch einen direkten Registerzugriff
  • PrĂĽfen Sie ob der Code noch funktioniert
  • Schreiben Sie nun Code, der gleichzeitig GP15 und GP25 in der Loop ändert.
  • Schreiben Sie eine Variante mit direktem Registerzugriff und eine Variante mit HAL.
  • Gibt es einen Unterschied in der AusfĂĽhrungszeit?
  • dtlab_t11.txt
  • Last modified: 2025/06/02 15:28
  • by beckmanf