Mittwoch, 21. Mai 2014

printf(...) ganz einfach per Semihosting auf dem STM32F4

Lieber Entwickler,

bei einer Konsolenanwendung auf dem PC ist es (schlechte) gängige Praxis, permanent Debug-Ausgaben per System.out.println("") oder Console.Writeln("") oder printf("") auszugeben. Bei einfachen oder experimentellen Anwendungen entwickelt man insbesondere auch in Verbindung mit einem Debugger schnell ein Gefühl dafür, wo im Falle eines Fehlers nochmals Hand anzulegen ist.

Bei Entwicklungen mit dem Microcontroller ist man meist auf LEDs oder einfache LCD-Displays angewiesen, um Text auszugeben. Profis schreiben über über die serielle Schnittstelle raus und hängen sich mit einem Terminal-Programm an den Prozessor. Alle Lösungen haben jedoch Nachteile:

  • LEDs können nur seeehr einfache Informationen ausgeben. Einen komplexen Morsecode will wohl keiner entwickeln...
  • Ein LCD verlangt nach einigem Code, verbraucht rare IOs und kostet Geld
  • Die serielle Schnittstelle verbraucht einen UART und macht eine zusätzliche Kabelverbindung
Mit der Technik "Semihosting" bietet die STM32-Familie glücklicherweise eine sehr einfache Möglichkeit, Informationen vom Microcontroller über die Debug-Verbindung an den Host zu senden. Meine Toolchain ist bereits für Semihosting vorbereitet. Ein Beispielprojekt habe ich in hier abgelegt

Zur Aktivierung sind die folgenden Schritte notwendig.
  • Hole Dir mein Semihosting-Testprojekt
  • Du kannst dieses Projekt 1:1 verwenden. Es misst einfach nur die Spannung am PA1-Eingang und gibt diese jeder Sekunde aus. Bei mir ist dort ein Sharp-Infrarot-Entfernungsmesser angeschlossen. Wenn bei Dir nichts dort angschlossen ist, funktioniert die Anwendung trotzdem. Wesentlich sind die Dateien:
    • Inc/printf.h
    • Inc/semihosting.h
    • Src/printf.c
    • Src/semihosting.c
    • Src/sh_cmd.asm
  • Füge die asm- und die c-Dateien Deinem Src-Verzeichnis hinzu
  • Füge die h- Datei Deinem Inc-Verzeichnis hinzu
  • Aktiviere Semihosting in den Debugger-Settings (siehe Screenshot)
  • Füge #include "printf.h" in den User-Code-Bereich 0 der main.c hinzu
  • Füge in der while-Schleife jetzt einen printf-Befehl und eine Verzögerung hinzu, beispielsweise: "printf("Der Prozessor ist jetzt %u msec gelaufen, HAL_GetTick()); HAL_Delay(1000);"

Ein wenig seltsam mag erscheinen, dass ich hier eine eigene printf-Funktion verwende und nicht auf die integrierte Funktionalität der STM-Firmware-Library ("newlib") zurück greife. Grund hierfür ist, dass die newlib wirklich jedes Feature von printf unterstützt und sowohl viel Speicher im Flash als auch auf dem Heap verbraucht. Meine Implementierung (die ich natürlich 1:1 abkekupfert habe) realisiert eine mehr als ausreichende Teilmenge der Gesamtfunktionalität und bleibt herrlich kompakt.

Happy Coding

Sonntag, 11. Mai 2014

RTOS 8.0.1 auf dem STM32F4 discovery

Liebe Entwickler,
heute versuche ich, das FreeRTOS 8.0.1 auf meinem STM32F4 discovery zum Laufen zu bringen und mein Vorgehen hier zu beschreiben. Über die Installation der Toolchain hatte ich bereits geschrieben. Ziel ist es nun, mit Hilfe des vorbezeichneten OS die LEDs auf dem Board zum Blinken zu bringen.

  • Voraussetzung ist nun, dass ihr die Toolchain und das Basisprojekt funktioniert. Im Staccato:
    • Im CubeMX ein Projekt für das STM32F4 discovery erzeugen
    • --->Achte darauf, dass in der NVIC-Konfiguration 4bin für Preemption-Priorität und 0 Bits für die Subpriorität eingestellt sind<--
    • PINs der LEDs (PD12 - PD15) auf Output Mode PushPull umstellen
    • Code erzeugen und Eclipse C-Projekt im gleichen Verzeichnis erstellen
    • Include-Verzeichnisse hinzufügen
      • ${ProjDirPath}/Drivers/CMSIS/Device/ST/STM32F4xx/Include
      • ${ProjDirPath}/Drivers/CMSIS/Include
      • ${ProjDirPath}/Drivers/STM32F4xx_HAL_Driver/Inc
      • ${ProjDirPath}/Inc
    • Symbole definieren
      • Name="USE_HAL_DRIVER", Value leer lassen
      • Name= "STM32F407xx", Value leer lassen
    • Unnötige Header-Files in Drivers\CMSIS\Device\ST\STM32F4xx\Include ausschließen
    • Datei Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/gcc/startup_stm32f407xx.s umbenennen
    • Target Processor M4; softfp
    • Linker-File einbinden
    • Debugger-Option: -f board/stm32f4discovery.cfg
  • FreeRTOS-Installation
    • Lade Dir nun die FreeRTOS-Distribution herunter (http://www.freertos.org/) und entpacke es in ein Unterverzeichnis Deiner Repository-Verzeichnisses (bei mir c:\stm32ws\repository).
    • Benenne das "Source"-Verzeichis von FreeRTOS in "FreeRTOS" um und ziehe es bei gedrückter rechter Maustaste ins Projekt hinein --> "Link to Files and Folders", "WORKSPACE_LOC".
    • Lösche aus dem Source/Portable-Verzeichnis alle unnötigen Toolchains (!=GCC && !=MemMang) und Prozessortypen (!=ARM_CM4F) raus.
    • Besorge Dir aus der veralteten FreeRTOS-Distribution aus der CubeMX-Firmware (C:\stm32ws\repository\STM32Cube_FW_F4_V1.1.0\Middlewares\Third_Party\FreeRTOS\Source) das Verzeichnis CMSIS_RTOS und kopiere dieses in das FreeRTOS-Verzeicnis Deines Projektes. Verlinke das Verzeichnis nicht, weil wir da gleich eine Datei anpassen.
    • Passe die darin befindliche Datei cmsis_os.c  in der Funktion "osStatus osThreadIsSuspended(osThreadId thread_id)" in Zeile 1098 an :  if (xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED)...
    • Besorge Dir aus einem FreeRTOS-Demoprojekt der STM32-Firmware (Bsp: C:\stm32ws\repository\STM32Cube_FW_F4_V1.1.0\Projects\STM32F429I-Discovery\Applications\FreeRTOS\FreeRTOS_ThreadCreation\Inc) eine FreeRTOSConfig.h Datei und packe diese in den Inc-Ordner Deines Projektes.
    • Füge das darin befindlich Include Verzeichnis "C:\stm32ws\repository\FreeRTOS\FreeRTOS\include" wie zuvor beschrieben allen Configurations und allen Languages hinzu. Füge außerdem das Verzeichnis "C:\stm32ws\repository\FreeRTOS\FreeRTOS\portable/GCC/ARM_CM4F" hinzu
  • Füge das Board Support Package (BSP) für das STM32F4-Discovery Deinem Projekt hinzu.
    • Ziehe dazu den Ordner "C:\stm32ws\repository\STM32Cube_FW_F4_V1.1.0\Drivers\BSP\STM32F4-Discovery" mit rechter Maustaste in den Ordner "Drivers" Deines Projektes und mache einen Link über "WORKSPACE_LOC". 
    • Füge das darin befindlich Include Verzeichnis "C:\stm32ws\repository\STM32Cube_FW_F4_V1.1.0\Drivers\BSP\STM32F4-Discovery" wie zuvor beschrieben allen Configurations und allen Languages hinzu.
  • Führe ein Exclude from Project der Datei Drivers/CMSIS/RTOS/cmsis_os.h durch. Hierbei handelt es sich nur um ein rudimentäres Template, welches für unsere Zwecke unbrauchbar ist. Jene Datei, die aus diesem Template speziell für FreeRTOS entstehen muss, haben wir und weiter oben schon mit dem Verzeichnis "CMSIS_RTOS" ins Projekt geholt.
Die Vorbereitungen sind damit abgeschlossen. Hoffentlich habe ich bei der Doku keinen Schritt vergessen. Zur Sicherheit gebe ich Euch noch ein Foto der Includes und meiner Projektstruktur.



  • Die main.c Datei muss jetzt mit passenden Tasks und Initialisierungsaufrufen befüllt werden. Von großer Wichtigkeit ist an dieser Stelle jedoch der Aufruf des FreeRTOS-Schedulers nach jeder Millisekunde. Ich empfand es als geschickt, diesen n der Callback-Funktion des SysTick-Timers aufzurufen. Die Funktion xPortSysTickHandler() muss zunächst als "extern" deklariert werden und kann dann aufgerufen werden:
void HAL_SYSTICK_Callback(void){
    xPortSysTickHandler();
}
Das gesamte Projekt findet Ihr auf https://code.google.com/p/stm32tutor/source/browse/#svn%2Ftrunk%2Frtostest%2FSrc

Mittwoch, 7. Mai 2014

STM32F4 Discovery mit OpenSource Toolchain programmieren und debuggen

ACHTUNG: Dieser Beitrag ist mittlerweile veraltet

[2015-12-07] Lieber Entwickelnde,

das Rad der Zeit dreht sich weiter. Mittlerweile ist es nicht mehr erforderlich, sich seine Toolchain "so umständlich" zusammenzubauen, wie hier beschrieben. "ac6" bietet auf http://www.openstm32.org/HomePage eine auch von ST empfohlene freie Toolchain an, die letztlich die gleichen Komponenten einsetzt. Die Dinge sich jedoch fertig vorkonfiguriert und der Start geht einfach und schnell, übrigens auch für die F1-Serie. Aktuell entwickele ich sehr gerne damit!

HTH und happy Coding!


Liebe Entwicklerin, lieber Entwickler,

im Folgenden möchte ich Dir die Installation und Grundkonfiguration einer freien Toolchain für die STM32F4-Prozessorfamilie beschreiben. Diese „Kette der Werkzeuge“ versetzt Dich kostenlos in die Lage, Software mit hohem Komfort zu schreiben, zu compilieren, zu linken, auf den Prozessor zu übertragen, dort zur Ausführung zu bringen und zu debuggen. Dieses Tutorial setzt einen Windows-PC (in meinem Fall Windows 7, 64bit) und natürlich zum Ausprobieren ein Entwicklungsboard mit einem STM32F4 voraus. Ich liebe und empfehle das STM32F4-Discovery für etwa 15Euro bei diversen Online-Händlern. Du brauchst etwa 1 Stunde, um die klassische blinkende Leuchtdiode zu bekommen. Die Toolchain funktioniert mit geringfügigen Änderungen auch mit anderen Mitgliedern der STM32-Familie.