Subsystemintegration¶
Diese Tutorials setzen voraus, dass Sie mit den Inhalten zu Einstieg in die Peripherie vertraut sind: GPIO, Shell, ADC-/PWM-Grundlagen und das Treibermuster rt_device_find(). Hier geht es von einzelnen Peripheriegeräten weiter zu Middleware und kombinierten Abläufen: Sensoren am I2C-Bus, grafische Benutzeroberfläche, BLE-Dienste, Audiowiedergabe, dauerhafte Datenspeicherung und einfache Koexistenztests.
Es geht nicht nur darum, jedes Subsystem einmal zum Laufen zu bringen. Sie sollen lernen, wie Firmware für SF32 typischerweise aufgebaut wird: von einem passenden SDK-Beispiel ausgehen, den Hardwarepfad überprüfen, ihn an die RT-Thread-Geräte- oder Middleware-Schicht anbinden und anschließend im Zusammenspiel mit dem restlichen Produkt testen.
Nutzen Sie diese Reihe, sobald die einzelnen Peripheriegeräte funktionieren und Integrationsrisiken relevant werden: gemeinsam genutzter Speicher, Timing, Stromverbrauch, boardspezifische Verdrahtung und Wechselwirkungen zwischen Middleware-Komponenten. Jede Übung soll eine klar abgegrenzte, testbare Funktionseinheit ergeben, nicht nur eine Demo, die auf einem Screenshot gut aussieht.
Bevor Sie beginnen¶
Die C-Beispiele sind Ausschnitte und keine vollständigen Quelldateien. Ergänzen Sie die für Ihr Projekt und Ihre SDK-Version erforderlichen Header, Deklarationen, Fehlerbehandlung und Ressourcenfreigabe.
Beispielpfade und unterstützte Boards können je nach SDK-Version variieren. Prüfen Sie vor dem Build die aktuelle Liste „Supported Platforms“ sowie die boardspezifischen Hardware- und Konfigurationsanforderungen jedes Beispiels; die Unterstützung eines Beispiels bedeutet nicht automatisch, dass das Board auch die anderen Beispiele unterstützt.
| Anforderung | Warum es wichtig ist |
|---|---|
| Funktionierende Shell | Sie benötigen list_thread, list_device, Logs und schnelle Inspektion. |
| Nachweislich funktionierender GPIO-Ein-/Ausgang | Viele Middleware-Demos benötigen weiterhin Taster, LEDs oder Interrupts. |
| Board-Schaltplan | Pins für I2C und Display, Audiopfad und Speicherlayout sind board-spezifisch. |
| Verifizierter Ausgangsstand | Bewahren Sie einen nachweislich funktionierenden Build auf, bevor Sie Funktionen kombinieren. |
| Möglichkeit, den Strom zu messen | Bei der Integration von Subsystemen kann sich der Ruhestrom ändern, auch wenn scheinbar alles funktioniert. |
Einen Sensor über I2C lesen¶
Ziel: mit einem realen Gerät am I2C-Bus kommunizieren statt mit einem einzelnen GPIO-Pin.
Zeit: 30–45 Minuten
Beispiel als Ausgangspunkt: example/hal/i2c/master oder example/rt_device/i2c/eeprom
struct rt_i2c_bus_device *bus = (struct rt_i2c_bus_device *)rt_device_find("i2c1");
struct rt_i2c_msg msgs[2] = { /* write register address, then read result */ };
rt_i2c_transfer(bus, msgs, 2);
Der Name i2c1 dient nur als Beispiel. Verwenden Sie den von Ihrem Board registrierten I2C-Gerätenamen und prüfen Sie, ob rt_device_find() ein gültiges Gerät zurückgibt, bevor Sie den Bus verwenden.
- Prüfen Sie im Datenblatt die I2C-Adresse des Sensors, das Registerlayout, die Versorgungsspannung und die erforderlichen Pull-ups.
- Ermitteln Sie, welchen
i2cX-Bus und welche Pins Ihr Board verwendet. - Passen Sie das EEPROM- oder Master-Beispiel für I2C an, um mit dem Sensor zu kommunizieren. Falls er ein Geräte-ID-Register besitzt, lesen Sie dieses zuerst; andernfalls beginnen Sie mit einem Register, dessen erwartetes Verhalten bekannt ist.
- Dekodieren Sie eine echte Messung und geben Sie sie über die Shell aus.
- Falls der Sensor einen Interrupt- oder Data-Ready-Pin hat, verbinden Sie ihn mit dem GPIO-Interrupt-Muster aus Einstieg in die Peripherie, Übung 2.
- Ersetzen Sie regelmäßiges Polling nach Möglichkeit durch ereignisgesteuerte Lesevorgänge.
Erfolgskriterien: Die Firmware liest ein bekanntes Register erwartungsgemäß (wenn verfügbar, ein Geräte-ID-Register), dekodiert einen plausiblen Sensorwert und blockiert das System nicht, wenn das Gerät fehlt.
Fehlerbehebung: Wenn Lesevorgänge durchgehend ausschließlich 0xff, ausschließlich 0x00 liefern oder ein Timeout auftritt, prüfen Sie Adressbreite, 7-Bit- vs. 8-Bit-Adressnotation, Pull-ups, Einschaltreihenfolge und ob eine andere Peripherie dieselben Pins belegt.
Was Sie gelernt haben: Mehrbyte-Transaktionen über I2C und wie man einen interruptgesteuerten GPIO-Pin mit einer Bus-Peripherie kombiniert.
Einen einfachen LVGL-Bildschirm erstellen¶
Ziel: ein sichtbares UI-Element auf dem Display darstellen, statt direkt in den Framebuffer zu schreiben.
Zeit: 45–60 Minuten
Beispiel als Ausgangspunkt: example/multimedia/lvgl/lvgl_v8_examples
lv_obj_t *label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Hello, SF32!");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
- Initialisieren Sie den Display-Treiber und prüfen Sie einfarbige Flächen, bevor Sie LVGL-Widgets debuggen.
- Erstellen Sie ein Label und ein Button-Widget.
- Verbinden Sie den Button-Callback, um den Labeltext zu ändern.
- Fügen Sie eine kleine Animation hinzu und beobachten Sie die CPU-Auslastung oder das Frame-Timing über Shell-Tools.
- Lesen Sie die Abschnitte der Grafikübersicht zu Pufferstrategie, partieller Aktualisierung und ePicasso, bevor Sie skalieren.
Erfolgskriterien: Der Bildschirm wird nach einem Reset zuverlässig initialisiert; konfigurierte Touch- oder Tastereingaben ändern den UI-Zustand, sofern sie verfügbar sind; und eine einfache Animation beeinträchtigt weder die Shell noch Bluetooth.
Fehlerbehebung: Trennen Sie Panel-Probleme von LVGL-Problemen. Wenn einfarbige Füllungen fehlschlagen, prüfen Sie Stromversorgung, Reset, Init-Sequenz, Pixelformat und Byte-Reihenfolge, bevor Sie den LVGL-Code anfassen.
Was Sie gelernt haben: das Objekt-/Ereignismodell von LVGL und die Display-Initialisierung, die jedem grafikintensiven Projekt vorausgeht.
BLE-Advertising und Verbindung als Peripheriegerät¶
Ziel: ein Smartphone oder ein anderes BLE-Zentralgerät über einen funktionierenden GATT-Dienst mit Ihrem Board verbinden.
Zeit: 45–60 Minuten
Beispiel als Ausgangspunkt: example/ble/peripheral
- Beginnen Sie mit dem einfachen BLE-Peripherie-Beispiel und prüfen Sie das Advertising mit einer BLE-Scanner-App.
- Verbinden Sie das Telefon mit dem Board und prüfen Sie, ob die Verbindung mehrere Minuten stabil bleibt.
- Wenn Sie Sensordaten senden möchten, richten Sie im GATT-Dienst des Beispiels eine passende Characteristic ein und aktualisieren Sie sie mit einem echten Messwert, etwa dem ADC-Wert aus Einstieg in die Peripherie, Übung 4, oder dem I2C-Sensorwert aus Übung 1 dieses Lernpfads.
- Konfigurieren Sie die erforderlichen Eigenschaften der Characteristic. Falls Sie Benachrichtigungen verwenden, aktivieren Sie sie und prüfen Sie, ob das Telefon die Wertänderungen empfängt.
- Testen Sie Trennung und Wiederverbindung sowie einen Reset des Boards während einer Verbindung.
- Lesen Sie die Bluetooth-Übersicht, bevor Sie einen individuellen Dienst entwerfen.
Erfolgskriterien: Das Gerät sendet Advertising-Pakete, stellt eine Verbindung her, stellt den konfigurierten GATT-Dienst bereit, tauscht Daten entsprechend den ausgewählten Characteristic-Eigenschaften aus und kehrt nach Trennung/Wiederverbindung in einen sauberen Zustand zurück.
Fehlerbehebung: Prüfen Sie diese Fälle: veraltete Bonding-Daten, „Gerät vergessen“ auf dem Smartphone, ein Neustart des Boards während einer Verbindung und Änderungen der Verbindungsparameter. Viele BLE-Fehler zeigen sich erst nach der ersten erfolgreichen Verbindung.
Was Sie gelernt haben: den Ablauf Advertising -> Verbindung -> GATT-Benachrichtigung, der in den meisten BLE-Produkten verwendet wird.
Lokale Audiodateien vom Speicher abspielen¶
Ziel: eine Audiodatei abspielen statt eines synthetisierten Tons.
Zeit: 45–60 Minuten
Beispiel als Ausgangspunkt: example/multimedia/audio/local_music
Die aktuelle Dokumentation nennt sf32lb52-lchspi-ulp als unterstützte Plattform für example/multimedia/audio/mp3_sd_player. Gehen Sie nicht davon aus, dass das Beispiel auch Ihr Board unterstützt. Prüfen Sie vor der Nutzung die Liste der unterstützten Plattformen und Hardwarevoraussetzungen.
- Laden Sie eine kleine Audiodatei im Format WAV oder MP3 auf das vom Beispiel erwartete Speichermedium.
- Bauen und flashen Sie das Beispiel.
- Prüfen Sie, ob die Wiedergabe startet, der Ton sauber ist und das Board beim Start nicht zurückgesetzt wird.
- Binden Sie die Start-/Stopp-Logik der Wiedergabe in den Taster-Handler aus Einstieg in die Peripherie, Übung 2 ein.
- Achten Sie auf Audioaussetzer durch Pufferunterläufe, während Shell-Logs ausgegeben oder Display-Inhalte aktualisiert werden.
- Lesen Sie die Audioübersicht, bevor Sie Abtastrate, Format oder Puffergröße ändern.
Erfolgskriterien: Die Wiedergabe lässt sich wiederholt starten, stoppen und erneut starten, ohne Knackgeräusche oder Pufferunterläufe. Nach dem Stoppen bleibt kein aktiver Leistungszustand unnötig bestehen.
Fehlerbehebung: Wenn der Ton verzerrt ist, prüfen Sie Abtastrate, Bittiefe, Ausgangspfad, Codec-Konfiguration, Dateiformat und Puffergröße. Prüfen Sie außerdem, ob die Lesevorgänge aus dem Speicher den Decoder rechtzeitig mit Daten versorgen.
Was Sie gelernt haben: wie Audio-Middleware des SDK, gepufferte Wiedergabe und Dateidekodierung zusammenspielen.
Persistente Daten speichern und abrufen¶
Ziel: Daten über Neustarts hinweg persistent halten, statt sie bei jedem Reset zu verlieren.
Zeit: 30–45 Minuten
Beispiel als Ausgangspunkt: example/storage/littlefs oder example/storage/flashdb
LittleFS eignet sich für dateiorientierte Daten. FlashDB ist eine eingebettete Datenbank mit Schlüssel-Wert-Modus (KVDB) und Zeitreihenmodus (TSDB); Speicher-Backend und Board-Unterstützung hängen von der Beispielkonfiguration ab. Prüfen Sie vor der Zielauswahl die offizielle Dokumentation zu LittleFS NOR und FlashDB.
Die folgenden POSIX-Aufrufe zeigen den Zugriff auf ein eingebundenes Dateisystem; es sind keine FlashDB-API-Aufrufe.
int fd = open("/data/log.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
write(fd, buf, len);
close(fd);
- Verwenden Sie ein Dateisystem wie LittleFS für dateibasierte Logs. Für strukturierte Einstellungen oder Datensätze mit Zeitstempel können Sie den KVDB- oder TSDB-Modus von FlashDB prüfen und das zu Board und Speicherbaustein passende Backend wählen.
- Prüfen Sie die vom Beispiel verwendete Partition und den Mount-Pfad.
- Schreiben Sie einen kleinen Log-Eintrag oder eine Einstellung.
- Schalten Sie das Board aus und wieder ein und prüfen Sie, ob die Daten weiterhin vorhanden sind.
- Protokollieren Sie periodisch Sensormesswerte aus Tutorial 1.
- Legen Sie eine einfache Aufbewahrungsregel fest, damit die Logs nicht unbegrenzt wachsen.
Erfolgskriterien: Daten überstehen einen Neustart, und die Firmware behandelt fehlenden, vollen oder neu formatierten Speicher robust.
Fehlerbehebung: Prüfen Sie Partitionslayout, Mount-Pfad, Flash-Lösch- und Schreibfehler sowie das Schließen der Dateien. Achten Sie auch darauf, dass die Schreibfrequenz zur erwarteten Schreibfestigkeit des Speichers passt.
Was Sie gelernt haben: wann ein Dateisystem oder eine eingebettete Datenbank sinnvoll ist und wie Produktzustand Resets übersteht.
Zwei Subsysteme absichtlich kombinieren¶
Ziel: zwei Subsysteme gleichzeitig betreiben und lernen, wie sie sich gegenseitig beeinflussen.
Zeit: 1 Stunde
Beispiel als Ausgangspunkt: Wählen Sie zwei der Tutorials 1–5 aus, die für Ihr Produkt am relevantesten sind.
- Wählen Sie zwei Subsysteme, die Ihr Produkt tatsächlich zusammen benötigt, etwa BLE plus einen Sensor am I2C-Bus, oder LVGL plus Audiowiedergabe.
- Prüfen Sie zunächst jedes Subsystem einzeln.
- Kombinieren Sie sie mit minimalen Änderungen.
- Testen Sie beide unter gleichzeitiger Last: etwa eine BLE-Benachrichtigung während eines Lesevorgangs am I2C-Bus, eine UI-Animation während der Audiowiedergabe oder einen Speicherschreibvorgang während einer Sensoraktualisierung.
- Beobachten Sie CPU-Auslastung, Logs, Speicher und sichtbares Verhalten.
- Vergleichen Sie Ihre Beobachtungen mit der Bluetooth-Übersicht, der Grafikübersicht und Energiesparendes Design im Überblick.
Erfolgskriterien: Beide Subsysteme funktionieren weiterhin unter gleichzeitiger Aktivität, und der Ruhestrom kehrt nach Testende auf das erwartete Niveau zurück.
Fehlerbehebung: Achten Sie auf lange blockierende Aufrufe, übermäßige Protokollausgaben, eine Häufung von Timer-Ereignissen, Schreibvorgänge in latenzkritischen Pfaden und Fehler bei der Cache-Verwaltung gemeinsam genutzter Puffer.
Was Sie gelernt haben: Auch einzeln funktionierende Subsysteme können sich gegenseitig beeinträchtigen, wenn sie CPU-Zeit, Speicherbandbreite, Interrupts und Energiemanagement gemeinsam nutzen.
Checkliste zur Subsystemintegration¶
- Jedes Tutorial beginnt mit einem SDK-Beispiel, dessen Funktion bereits nachgewiesen wurde.
- Zuerst wird jeder Hardwarepfad überprüft: ein bekanntes Sensorregister oder ein bekannter Messwert, die Panel-Füllung mit einer einfarbigen Fläche, BLE-Advertising, die Audioausgabe oder das Einbinden des Speichers.
- Die Funktion übersteht Reset und, sofern zutreffend, Trennung/Wiederverbindung.
- Fehlerpfade werden getestet: fehlender Sensor, fehlende Datei, getrenntes Telefon, voller Speicher.
- Mindestens ein kombinierter Lasttest wurde durchgeführt.
- Das Ruheverhalten wurde nach dem Stoppen jeder Funktion überprüft.
Wie es weitergeht¶
Produktvalidierung behandelt die Optimierung des Stromverbrauchs, OTA-Updates, die Inbetriebnahme kundenspezifischer Displays und Treiber, Bluetooth mit mehreren Verbindungen sowie das Debugging in der Produktion. So werden funktionierende Demos zu produktionsreifer Firmware.
Zuletzt aktualisiert: