11 Versuche
11.1 Starter
Im wesentlichen geht es hier nur darum, das “starter” Projekt als ersten Versuch zum Laufen zu bringen, so dass man sicher sein kann, dass die Installation der Tools auf dem PC funktioniert hat. Am Ende der README.md stehen noch ein paar kleinere Aufgaben.
11.2 GDB-Uebung
Siehe https://gitlab.com/hhoegl-tha/es/f446/gdb-uebung
Die Aufgaben sind in der Datei Aufgaben.md im Repo enthalten.
11.3 GNU-Start
https://gitlab.com/hhoegl-tha/es/f446/gnu_start
Die Aufgaben sind in der Datei Aufgaben.md im Repo enthalten.
11.4 CMSIS und Exceptions
11.4.1 starter-cmsis
Klonen Sie das Repository
https://gitlab.com/hhoegl-tha/es/f446/starter-cmsis
Der CMSIS Standard gibt eine Struktur vor für den Startup-Vorgang. Sehen Sie sich in src/ die beiden Dateien startup_stm32f446xx.s und system_stm32f4xx.can und untersuchen Sie wie der genaue Ablauf ist.
11.4.2 syshandler-cmsis
Klonen Sie das Repository
https://gitlab.com/hhoegl-tha/es/f446/syshandler-cmsis
Aktivieren Sie nacheinander immer genau eine der folgenden Exception-Quellen, kompilieren Sie das Programm, und verwenden Sie GDB um den genauen Ablauf zu studieren.
SysTick (entweder Variante 1 oder Variante 2)
Bus fault
Usage fault
Integer division by zero
FPU interrupt division by zero (finden Sie auch die Stelle im Quelltext, an der die FPU aktiviert wird). Die Register der FPU werden in [PM], Kap. 4.6 beschrieben.
SVC handler
Das Hauptprogramm triggert eine SVC Exception. Sehen Sie sich im
SVC_Handler()mit dem GDB den Stackframe an und ermitteln Sie, an welcher Stelle der SVC aufgerufen wurde. Daraus können Sie wiederum die SVC Service Nummer ermitteln.
Nehmen Sie in Ihren Bericht auf, was Sie gemacht haben, und beschreiben Sie auch kurz die einzelnen Exceptions.
In .estool/gdbinit ist eine Funktion flags definiert, mit der man das xPSR Register, in dem sich die Flags befinden, im Klartext ausgeben kann:
(arm-gdb) flags
N=0 Z=1 C=1 V=0 Q=0 GE=0 ICI/IT=0x0 Exc#=0
Wenn Sie im GDB das Kommando layout regs eingeben, dann sehen Sie auch die aktuellen Werte der Register, so wie das hier zu sehen ist:
https://tha.de/homes/hhoegl/home_data/es2/gdb-tui-window/gdb_tui_window.png
11.4.3 gpio-intr-cmsis
Klonen Sie das Repository
https://gitlab.com/hhoegl-tha/es/f446/gpio-intr-cmsis
Auf welchem Wert steht der Stack-Pointer
spbeim Programmstart beimain()?Gehen Sie im GDB mit
s(step) durch die Funktion__get_CONTROL(). Was wird ausgeführt?Schauen Sie sich auch die anderen Funktionen
__get_PRIMASK(),__get_FAULTMASK(),__set_BASEPRI()und__get_BASEPRI()an.Das Statusregister können Sie mit folgendem Kommando ausgeben:
(arm-gdb) p/x $xPSR $4 = 0x21000000 # beispielhafte AusgabeWas bedeuten die einzelnen Bits? Sehen Sie dazu in [PM] nach. Eine Hilfe bietet auch die GDB Funktion
flags, die Sie in.estool/gdbinitfinden. Damit kann man die Werte der einzelnen Flags ausgeben:(arm-gdb) flags N=0 Z=1 C=1 V=0 Q=0 GE=0 ICI/IT=0x0 Exc#=0Was macht das folgende C Präprozessor-Makro in
inc/main.h?/* register r, mask f, value v (taken from _VAL2FLD() and _FLD2VAL() macros) */ #define SETBF(r, f, v) r = ((r & ~(f ## _Msk)) | ((v << f ## _Pos) & f ## _Msk))Welche Vektornummer wird zu Beginn des Interrupt-Handlers
EXTI15_10_IRQHandler(void)imxPSRangezeigt? Wie werden die Vektoren gezählt?Schauen Sie sich den Exception Stack Frame zu Beginn des Interrupt-Handlers
EXTI15_10_IRQHandler(void)an. Achten Sie darauf, dass die Programmausführung exakt vor der ersten Instruktion im Handler stoppt. Es kann sein, dass Sie den Breakpoint durch eine Adresse setzen müssen, dazu verwenden Sie die Syntax:(arm-gdb) br *<address>Die Adresse finden Sie durch Disassemblieren des Handlers oder durch das Kommando
p &EXTI15_10_IRQHandler. Das&ist der “address-of” Operator, genau so wie in C.In GDB verwenden Sie das Kommando
disas <label>zum Disassemblieren.Sie finden Informationen zum Stack Frame in [PM], Abschnitt Exception entry and return (Kap. 2.3, “Exception Model”).
Finden Sie mit dem Debugger heraus, was im Thread Mode (also in der
main()Funktion) und im Handler Mode (also im Interrupt-Handler) jeweils eingestellt ist:Privilegierter (privileged access) oder nicht privilegierter (user access) Zugriff?
Wird der PSP oder der MSP stack pointer verwendet?
Sie brauchen dazu nur das
CONTROLRegister auslesen und interpretieren.
11.4.4 Literaturangaben
[SKRIPT] Kapitel 4.10
[PM] STM32F3, STM32F4 and STM32L4 Series Cortex®-M4 programming manual (PM0214). Siehe Kapitel 9.
- S. 43: Stack Frame Layout
- S. 37: Exception Model
- S. 44: Fault Handling
[BERTOLOTTI] Ivan Cibrario Bertolotti, Cortex-M Exception Handling (Blog post), 2015/2016
https://tha.de/homes/hhoegl/home_data/es2/exceptions/bertolotti
[EXC_PROC] Übersicht zum Exception Processing auf dem STM32
https://tha.de/homes/hhoegl/home_data/es2/exceptions/stm32_exc_proc/stm32_exc_proc.svg
[YIU] Yiu, The Definitive Guide to ARM® Cortex®-M3 and Cortex®-M4 Processors, 3rd ed.
Kap. 2, Introduction to Embedded Software Development
Kap. 12, Fault Exceptions and Fault Handling
11.5 BPG
Diese Aufgabe baut auf einem Tutorial das es auf github gibt, sie finden es unter:
https://github.com/cpq/bare-metal-programming-guide
Die Programmierung von Mikrocontrollern in der Sprache C ist dabei in einzelne Schritte aufgeteilt, die sich nacheinander im Funktionsumfang steigern (siehe Verzeichnis steps). Die einzelnen Schritte sind
step-0-minimal/step-1-blinky/step-2-systick/step-3-uart/step-4-printf/step-5-cmsis/step-6-clock/step-7-webserver/
Alle Schritte sind vom Schwierigkeitsgrad her relativ einfach. Das Tutorial ist für das Nucleo-F429ZI Board gemacht.
Die Schritte 0 bis 6 sind leicht anpassbar für das Nucleo-F446. Das wird eine ihrer Aufgaben sein.
Der Schritt step-7-webserver ist nur mit einem Board möglich, das einen Internetanschluss (eth, WiFi) hat. Das Programm verwendet die “mongoose” Network Library (https://github.com/cesanta/mongoose, https://mongoose.ws)
Wir werden das Programm auf einem NucleoF429ZI in Betrieb nehmen.
11.5.1 Debuggen
Im Tutorial wird der “Ozone” Debugger von Segger verwendet. Damit man ihn verwenden kann muss man leider den Debug Controller auf dem Nucleo Board mit einer neuen Firmware flashen, damit aus dem “STLINK” ein “J-Link” wird. Das finde ich nicht gut, deswegen bleiben wir bei dem bewährten Gespann aus OpenOCD und GDB. Damit die Anwendung leichter wird, habe ich das kleine Programm ogdb geschrieben.
https://gitlab.com/hhoegl-tha/es/ogdb
Man kann die Binärdatei von gitlab herunterladen und in einen Ordner legen, in dem ausführbare Dateien gefunden werden (Hinweis: Die PATH Umgebungsvariable muss diesen Ordner enthalten). In dem jeweiligen “Step” Ordner gibt man einfach das Kommando ogdb ein, damit wird der OpenOCD automatisch im Hintergrund gestartet und der GDB im TUI-Modus geöffnet. Dann sollte wie gewohnt das Debuggen in GDB möglich sein.
11.5.2 Ihre Aufgaben
Lesen Sie die ersten drei Schritte (0, 1, 2) im Tutorial und ändern Sie die Programme so, dass sie auf dem Nucleo-F446 laufen.
Meist müssen Sie dabei nur die zwei Zeilen im Linker-Skript ändern auf
flash(rx) : ORIGIN = 0x08000000, LENGTH = 512k sram(rwx) : ORIGIN = 0x20000000, LENGTH = 128kAusserdem ist die LED zu ändern auf Port A, Pin 5.
Bei Aufgaben die den UART verwenden ist der UART2 einzustellen.
Beschreiben Sie in Ihrem Bericht kurz, wie der Programmablauf ist. Sie müssen sich dazu den Quelltext genauer ansehen.
Wie funktionieren die Macros BIT, PIN, PINNO, PINBANK?
Was erledigt der Reset Vektor
_reset(void)?Was machen vor allem die zwei
forSchleifen?Wie wird der Reset Vektor in der Vektor-Tabelle abgelegt?
Welchen Wert hat der Stackpointer wenn das Programm bei Reset losläuft?
Wie funktioniert die Takteinstellung? (RCC)
Wie funktioniert der SysTick Interrupt in Verbindung mit
timer_expired()bei step-2-systick? In welchem zeitlichen Abstand wird der SysTick ausgelöst?Was passiert mit dem SysTick, wenn man das Programm im GDB mit
Ctrl-Cstoppt?Wie schafft man es in GDB, dass die folgenden Programmzeilen in
main()ausgeführt werden und das Programm bei/* stop */wieder stoppt?for (;;) { if (timer_expired(&timer, period, s_ticks)) { ... /* stop */
Bearbeiten Sie die Schritte 3-6.
step-3-uart
Was macht die Funktion
gpio_set_af()?Wie funktionieren
uart_init()unduart_write_buf()?
step-4-printf
Das Programm ist nun in mehrere Dateien aufgeteilt (hal.h, main.c, startup.c, syscalls.c). Was ist in den einzelnen Dateien drin?
Damit
printf()verwendet werden kann müssen Systemaufrufe implementiert werden. Welche sind das?
step-5-cmsis
Dieser Schritt verwendet die CMSIS Bibliothek von ARM. Der CMSIS Code wird dazu erst geholt. Beschreiben Sie wie das im Makefile funktioniert (Achtung: Die neuen CMSIS Verzeichnisse nicht in ihr Abgabe-Repo übernehmen, das wäre Platzverschwendung).
Welche Teile im Programm werden nun auf CMSIS ausgelagert?
step-6-clock
- Der Startup-Vorgang ist nun komplizierter! Versuchen Sie herauszubekommen, wie er genau abläuft. Es ist eine Assembler Datei daran beteiligt, die in der CMSIS liegt.
11.6 Cube
XXX Diese Aufgabe muss erst überarbeitet werden!
Dieser Versuch besteht aus zwei Teilen, GPIO_IO_TOGGLE und GPIO_EXTI. Beide Teile verwenden die STM32 CubeL4 Bibliothek.
11.6.1 GPIO_IO_TOGGLE
Klonen Sie das Repository https://gitlab.com/hhoegl-tha/es/l476/cube-demos. Danach finden Sie den Ordner in cube-demos/gpio_io_toggle.
Das originale README ist in readme.txt.
Der Quelltext für dieses Beispielprogramm stammt aus der CubeL4 Bibliothek. Es wurde lediglich ein Makefile hinzugefügt.
Es gibt folgende Abhängigkeiten:
Die CubeL4 Bibliothek für den STM32L476 wird benötigt. Sie ist in folgendem Repository:
XXX to do
Das Board Support Package (BSP) für das STM32L476-Nucleo wird benötigt.
Das BSP besteht aus einer Quelltextdatei
stm32l4xx_nucleo.cund einer Header-Datei (siehe Makefile). Die Kompilierung wird automatisch durch das Makefile gesteuert.
Mit dem Befehl make wird das Programm kompiliert.
Mit make flash kann man das Programm in den Mikrocontroller übertragen.
Mit make gdb startet man den Debugger. Der OpenOCD Server muss dazu laufen (siehe estool --start-oocd, estool --ask-oocd, estool --stop-oocd).
11.6.2 Aufgaben
Kompilieren Sie das Programm und lassen Sie es auf dem Nucleo Board laufen.
Welche Bedeutung haben die einzelnen Quelltext-Dateien? Die Aufteilung ist teilweise durch die CMSIS Bibliothek und teilweise durch die Cube Bibliothek vorgegeben.
├── Inc │ ├── main.h │ ├── stm32l4xx_hal_conf.h │ └── stm32l4xx_it.h ├── Src ├── main.c ├── startup_stm32l476xx.s ├── stm32l4xx_it.c └── system_stm32l4xx.cSchauen Sie dazu mit dem Editor in die einzelnen Dateien und studieren Sie den Quelltext.
Notieren Sie alle Programmteile, die nacheinander nach dem RESET Signal ablaufen. Denken Sie insbesondere an
- Startup-Code
- Initialisierung von
dataundbssSpeicherabschnitt - Vektortabelle
- Interrupt-Vektoren
- Takteinstellung
Gehen Sie in die einzelnen Verzeichnisse der Cube-Bibliothek und finden Sie heraus, aus welchen Bestandteilen sie besteht.
Gehen Sie im Editor an die Zeile
main.c:35und navigieren Sie nachHAL_Init(). Was macht diese Funktion?Zur Erinnerung: Mit
Ctrl-]kommen Sie in Vim an die Stelle an der die Funktion definiert ist. MitCtrl-Tspringen Sie wieder zurück.Gehen Sie im Editor an die Zeile
main.c:38und navigieren Sie zuSystemClock_Config();. Diese Funktion konfiguriert das Taktsystem des STM32. Besorgen Sie sich das Blockschaltbild der RCC-Einheit und finden Sie die genauen Takteinstellungen heraus. Das Kapitel 6 im Reference Manual behandelt die RCC-Einheit.Das Blockschaltbild finden Sie wenn Sie auf den Link mit den Literaturangaben gehen (unten) und nach “clocktree” suchen.
Finden Sie heraus, ob der SysTick Timer bei dieser Anwendung konfiguriert ist und läuft.
Wie funktioniert der Aufruf von
HAL_Delay(200);auf Zeilemain.c:49?In welchem Teil der Cube Bibliothek werden die LEDs und Taster auf dem Nucleo Board zusammengefasst?
Wie heissen die Funktionsaufrufe, mit denen die LEDs initialisiert und angesprochen werden?
Wozu gibt es die Funktion
assert_failed(...)in Zeilemain.c:131? Tipp: In der Cube Bibliothek gibt es oftassert()Aufrufe. Wozu dienen diese?
Literatur
Die benötigte Literatur finden Sie in Kapitel 9.
Die CubeL4 Bibliothek ist auf github unter
11.6.3 GPIO_EXTI
Der Beispielcode ist unter cube-demos/GPIO_EXTI/.
Durch Drücken des USER-Button (blaue Taste, B1) auf dem Nucleo-L476 wird ein Interrupt (EXTI) auf der fallenden Flanke ausgelöst. Der Interrupt-Handler toggelt die grüne USER-LED (LD2). Manchmal scheint das Umschalten der LED nicht richtig zu funktionieren. Das liegt daran, dass die Taste “prellt”, d.h. bei einmaligem Drücken werden mehrere Impulse erzeugt und der Interrupt-Handler wird dadurch mehrfach aufgerufen.
Das originale README ist in readme.txt.
11.6.4 Aufgaben
Kompilieren Sie das Programm und lassen Sie es auf dem Nucleo Board laufen.
Wie wird der Interrupt auf der User-Taste in
main.cprogrammiert? Gehen Sie alle Peripherieblöcke durch, die bei einem Interrupt beteiligt sind, also NVIC, EXTI, GPIO und SYSCFG.Wo ist der Interrupt-Handler
EXTI15_10_IRQHandler(...)definiert?Vollziehen Sie alle Schritte nach, die dieser Handler macht!
Die benötigte Literatur finden Sie in Kapitel 9.
11.7 RTOS
Literaturangaben
Siehe den Abschnitt “RTOS” in Kapitel 9.
CMSIS-RTOS API V1 Dokumentation https://www.keil.com/pack/doc/CMSIS/RTOS/html/index.html
Machen Sie sich mit der CMSIS-RTOS Doku vertraut, öffnen Sie im Menü auf der linken Seite nacheinander die Einträge für “Reference” und “CMSIS-RTOS API”. Dann sehen Sie die wesentichen API Funktionen sortiert in folgende Bereiche:
- Kernel
- Thread
- Generic Wait
- Timer
- Inter-Thread Comm
- Signals
- Msg Queue
- Memory Pool
- Mail Queue
- Mutex
- Semaph
- Generic Data Types
- Status and Error Codes
RTOS Abschnitt im Skript, Kapitel 6.
11.7.1 Papieraufgaben
Allgemeine Fragen (Motivation, warum RTOS nötig sind)
Der Artikel von Bill Earl, “Multi-tasking the Arduino”, beschreibt sehr anschaulich, wie man mehrere Sachen auf dem Mikrocontroller quasi-gleichzeitig erledigen kann, ohne einen echten Multi-Tasker zu haben. Beschreiben Sie die einzelnen Evolutionsstufen der Anwendung mit ihren Vor- und Nachteilen, die er in seinem Artikel beschreibt.
Lit.: https://learn.adafruit.com/multi-tasking-the-arduino-part-1
Wie entsteht bei Tasks eine race condition und wie vermeidet man sie?
Lit.: Elecia White, Making Embedded Systems, O’Reilly 2011. Kapitel 5: Managing the Flow of Activity
Hier sind hauptsächlich die Abschnitte “Scheduling and Operating System Basics” und “State Machines” von Interesse.
Hinweis: Leider werden ganz wenige Fachbücher in diesem Bereich von Frauen geschrieben, dieses hier ist eine Ausnahme und es ist auch wirklich sehr gut gemacht. Schauen Sie unbedingt mal rein!
Wer Interesse an einer weiteren anschaulichen Einführung in Echtzeit-Betriebssysteme hat, kann sich folgenden Auszug aus einem Buch anschauen (aus Jim Ledin, Architecting High-Performance Embedded Systems, Packt Publishing, Feb 2021): Link
Fragen zu FreeRTOS
Was sind typische Aufgaben eines Betriebssystems, z.B. GNU/Linux und welche davon werden von FreeRTOS unterstützt, gerne auch in Form einer Tabelle, in der Linux und FreeRTOS gegenüber gestellt wird.
Denken Sie dabei an Ressourcenverbrauch, Prozesse, Threads, Tasks, Scheduler, Speicherschutz, Dateien, I/O, Echtzeit.
Wie gross schätzen Sie den Ressourcenverbrauch von FreeRTOS an sich ein? Bietet der STM32L476 ausreichend CPU-Leistung, RAM und Flash dafür?
Wann eignet sich FreeRTOS in einem Projekt (oder Teilprojekt) und wann nicht? Bzw. was sind Kriterien die gegen bzw. für FreeRTOS in einem Projekt sprechen.
Das lässt sich gut beantworten, wenn man in das folgende FreeRTOS Tutorial schaut: Link
Lesen Sie die Abschnitte 1 bis 6.
Beschreiben Sie knapp die geplante Anwendung in eigenen Worten.
Welche Vor- und Nachteile hat die Programmierung ohne RTOS? (“Why use an RTOS Kernel?”)
Welche Vor- und Nachteile hat die Programmierung mit einem preemptiven RTOS?
Fragen zu “Mastering FreeRTOS” Link
Was versteht man unter Multitasking und welche Arten unterstützt FreeRTOS?
Welches Konstrukt der Sprache C kann zu einer Task gemacht werden?
Wie macht man in FreeRTOS eine Task? (1.2, Task Functions)
Welche Zustände kann eine Task haben? (1.6, Full task state machine)
Wie kann man eine Task verzögern? (S. 21)
Welche Prioritäten kann eine Task haben?
Was ist eine “Idle Task”?
Kann man die Priorität einer Task zur Laufzeit ändern, und wenn ja, wie? (1.8 Changing the priority of a task)
Welchen Scheduling-Algorithmus verwendet FreeRTOS? (Kap. 1.10)
Was ist eine “Queue”? (Kap. 2)
Wann blockiert eine Queue?
Kann eine Queue mehrere Sender und/oder mehrere Empfänger haben?
Was bedeutet “deferred interrupt processing”? (Kap. 3.2)
Wofür werden Semaphore typischerweise verwendet?
Was ist eine “Binary Semaphore”?
Was ist eine “Counting Semaphore”? (Kap. 3.3)
Was ist ein “Mutex”? (Kap. 4.3, S. 105)
Was ist “Priority Inversion”? (S. 111)
Was versteht man unter dem Begriff Gatekeeper Task und welches Problem wird damit entschärft?
Siehe Abschnitt 7.4 in Mastering the FreeRTOS Kernel zum Thema Gatekeeper Tasks.
Gibt es in FreeRTOS eine so komfortable Heap-Speicherverwaltung wie in der libc? Nennen Sie die in FreeRTOS implementierten Verfahren Siehe Kap. 2.2, Example Memory Allocation Schemes.
Welche der Alternativen
heap_X(x = 1, 2, 3, 4, 5) wird bei den FreeRTOS Beispielen verwendet?Alternativer Lesestoff: UM1722 Link
11.7.2 Praktische Aufgaben
Die Beispielprogramme sind in Gitlab unter https://gitlab.com/hhoegl-tha/es/l476/cube-demos
Hinweise:
Verwenden Sie die Tags (
make tags) zum Navigieren im Quelltext! Damit können Sie z.B. an die Stelle springen, an der die CMSIS-RTOS Funktionen oder die Board Support Package Funktionen definiert sind.Bei den FreeRTOS Aufgaben ist es nützlich, wenn man den Ablauf der Tasks bzw. Threads beobachten kann. Bei langsam laufenden Tasks ist dies mit LEDs möglich. Man kann z.B. noch folgende LEDs auf einem Steckbrett anschliessen:
- LED1: PA12
- LED2: PA11
- LED3: PB12
- LED4: PB11
- LED5: PA5 (das ist die grüne LED auf dem Board)
Die Definition dieser LEDs finden sie in der installierten Cube Bibliothek unter
stm32cubel4/freertos/BSP/freertos_leds.h.Verwenden Sie immer einen Vorwiderstand für jede LED. Ein Wert zwischen 220 und 470 Ohm sollte passen.
Komfortabler geht die Visualisierung der Tasks mit einem einfachen Logikanalysator, z.B. dem Saleae https://www.saleae.com. Wir haben solche Geräte im Labor zum Ausleihen. Es gibt auch preiswerte Klone zum Kaufen, siehe z.B. https://sigrok.org/wiki/MCU123_Saleae_Logic_clone.
Bei den meisten FreeRTOS Beispielen ist auch eine
readme.txtDatei vorhanden, in der die originale Funktionsweise beschrieben ist. Die Beispiele sind alle der Cube-Bibliothek für STM32L4 entnommen, manche sind leicht modifiziert worden, z.B. bei der Takteinstellung.
11.7.2.1 FreeRTOS_Thread_Creation
Finden Sie heraus, wie die einzelnen Tasks zeitlich nacheinander ablaufen und zeichnen Sie ein Task-Diagramm (x-Achse: Zeit, Y-Achse: die einzelnen Tasks).
11.7.2.2 FreeRTOS_SemaphoreFromISR
Dokumentieren Sie die Funktionsweise dieses Beispiels.
11.7.2.3 Gatekeeper Task
Dieses Beispiel ist als Programmgerüst in einem separaten Repository:
https://gitlab.informatik.hs-augsburg.de/es2/es2-nucl476/gatekeeper
In diesem Repository ist auch eine README.md, die sie lesen sollten.
Studieren Sie zunächst die Programme in den Ordnern:
FreeRTOS_MailFreeRTOS_Signal
Erstellen Sie nun ein Projekt mit fünf Threads (siehe Ordner gatekeeper nach git clone ...). Einer stellt den anderen die serielle Schnittstelle (USART2) zur Verfügung. Diese Funktion soll nicht blockieren, sondern den Inhalt, der über die serielle Schnittstelle ausgegeben werden soll, entgegennehmen und entsprechend umkopieren.
Nach einem Tastendruck (User Button) sollen die anderen vier Threads eine Ausgabe (über den vierten Thread) veranlassen.
Hinweise:
Welchen Synchronisationsmechanismus Sie verwenden ist Ihnen überlassen.
Zur Auswahl stehen Semaphore, Signal und Mail.Sie können das entsprechende Beispiel (Semaphore, Signal, Mail) kopieren, umbenennen und anpassen.
Das Gatekeeper Konzept wird im Buch “Mastering FreeRTOS” im Kapitel 7 beschrieben (“Resource Management”).
https://hhoegl.informatik.hs-augsburg.de/es2/prog/rtos/Mastering-FreeRTOS-2016.pdf
Abschnitt 7.4, S. 260 (Gatekeeper Tasks)
11.8 Low Power
Aufgaben
Schauen Sie sich den Quelltext für das Beispiel
PWR_ModesSelectionan und stellen Sie in einer Tabelle zusammen, was in den einzelnen Stromsparbetriebsarten jeweils zum Stromsparen angewendet wird.Sie finden den Beispielcode im Repo
Messen Sie die Stromaufnahme der
PWR_ModesSelectionAnwendung. Falls Sie ein Multimeter zu Hause haben, dann finden Sie heraus, welche Auflösung dessen kleinster Strommessbereich (Gleichstrom) hat. Sollten Sie auch noch ein Nucleo Board zu Hause haben, dann können Sie selber die Stromaufnahme des Boards über die beiden IDD Anschlüsse ermitteln.Falls Sie den Strom nicht selber messen können, finden Sie meine Messwerte unter Link
Bestimmen Sie die Stromstärken für die LED-Ein und LED-Aus Zustände aus dem Oszilloskop-Bild im Skript, Abschnitt 6.10 (“Praktische Strommessung”).
Welche Stromsparbetriebsarten kommen beim STM32L476 in Frage, wenn man einen Rauchmelder bauen möchte, der aus einer CR2032 Zelle (3,0V, 210mAh) gespeist werden soll und 10 bis 20 Jahre damit laufen soll?
Wie funktioniert das Programm
FreeRTOS_LowPower? Untersuchen Sie dazu den Quelltext.
Literatur
Skript, Abschnitt über Low-Power Programmierung Link
Designing Energy-Efficient Systems with Cortex-M Microcontrollers Link (Seiten 1-9)
STM32L4 ultra-low-power features overview (AN4621), 2017.
STM32L4 Reference Manual (RM0351), chap. 5.3 “Low-power modes”.
Elecia White, Making Embedded Systems, chap. 10 “Reducing Power Consumption”
Joseph Yiu, chap. 9 “Low Power and System Control Features”
11.9 Retarget
Repo: https://gitlab.com/hhoegl-tha/es/l476/retarget
Doku zur Newlib: https://sourceware.org/newlib
11.9.1 Aufgabe 1
Gehen Sie in das Programm a1/ (ein “baremetal” Programm) und testen Sie folgendes:
Kompilieren Sie das Programm, so wie es ist. Wie gross ist es?
In den Abschnitten (2) bis (12) wird immer eine Funktion aus der libc verwendet. Bauen Sie testweise einen dieser Abschntte in das Program ein (siehe die Kommentare im Programm) und kompilieren Sie das Programm. Gibt es Fehlermeldungen, wenn ja, welche?
Aktivieren Sie im Makefile die andere Zeile mit der Variable
PRO_SRCS(mit syscalls) und kompilieren Sie das Programm erneut. Warum klappt nun das Kompilieren?Achten Sie immer auf die Grösse des erzeugten Programms. Notieren Sie sich die Ausgabe von “size”, die in etwa so aussieht (natürlich haben Sie andere Werte):
size main.elf text data bss dec hex filename 24492 480 8280 33252 81e4 main.elfProgrammieren Sie in
retarget.cnoch die Funktion__io_getchar(), dieusart_receive_char()aufrufen soll. Auch letztere müssen Sie noch schreiben.Alle Eingabefunktionen (
getchar(),gets()undscanf()) benötigen diese Funktion, sonst funktionieren sie nicht!Gehen Sie durch alle 12 Testfälle (1) bis (12) in
Src/main.cund nehmen Sie den jeweiligen Code in Ihr Programm auf und testen ihn.Der Testfall (11) ist ein Test der im STM32L476 eingebauten Gleitkomma-Recheneinheit (FPU). Im Assembler-Listing findet man die erzeugten Assembler-Befehle für die FPU.
Im Makefile sind die Linker-Flags durch PRO_LDFLAGS gegeben. Die am Anfang aktivierte Zeile linkt das Programm mit der newlib. Die zweite (noch auskommentierte) Zeile aktiviert die newlib-nano. Testen Sie die Kompilierung mit
newlibund mitnewlib-nano.Notieren Sie die jeweils erzeugte Code-Grösse (siehe “size” Kommando).
11.9.2 Aufgabe 2
In a2/ ist nun ein Beispiel, das die Cube-Bibliothek verwendet. Auch bei diesem Programm sollte printf() über Retargeting zum Laufen gebracht werden. Sprechen Sie den UART über das Cube API an.
11.9.3 Aufgabe 3
In shell/ findet man ein Programm (mit Cube), das eine kleine Shell über den UART auf dem Mikrocontroller bereitstellt. Der Shell-Code kommt von dem freien Projekt “libemb”:
https://github.com/wendlers/libemb
In shell/README.md steht, wie man das Programm verwendet. Man kann es sowohl über ein Terminal-Programm wie z.B. minicom steuern, oder über ein Python Programm, das die serielle Schnittstelle per Programm steuert (serial_control.py). Ausserdem gibt es in Qt5/terminal/ noch ein in C++ geschriebenes grafisches Terminalprogramm das mit dem “Qt GUI Framework” geschrieben wurde. Die Quellen sind dabei, deshalb eignet sich das Programm gut zum Kennenlernen einer Qt Applikation. Das ausführbare Programm ist in Qt5/terminal/terminalpgm. Vollziehen Sie alle drei Möglichkeiten nach.
Anregung für weitere Aufgaben (optional)
Sie nehmen irgend eine Peripherieeinheit aus cube-demos und integrieren es in die Shell. Zum Beispiel lesen Sie einen A/D Wandler mit dem Kommando adc ein. Oder Sie stellen ein Servo, das an einem PWM-Ausgang hängt, mit pwm 30 auf den Winkel 30 Grad. Die Ansteuerung vom PC erfolgt mit dem Python Programm serial_control.py, das Sie auf die neuen Funktionen erweitern.
Anregung für eine Aufgabe mit Qt5-Programmierung (optional)
In Qt5/serialui sind Ansätze eines grafischen Programms, das dafür gedacht ist, mehrere Peripheriemodule des STM32 zu kontrollieren. Wie man das Programm kompiliert steht in serialui/README. Modifizieren Sie das Programm so, dass es zumindest die LED ein-/und auschalten kann. Sie können gerne auch eine oder mehrere der anderen angedeuteten Möglichkeiten weiter ausführen.
Um Programme mit Qt zu kompilieren, muss Qt erst mal installiert werden. Eine vollständige Installation benötigt jedoch sehr viel Platz (ca. 9 GByte). Sollte ihr freier Platz ausreichen, dann können Sie folgende Alternativen nutzen:
Installation aus dem Linux Paket-Repository:
sudo apt-get install qt5-default qtdeclarative5-dev qt5-qmakeMeine archivierten Qt5 Installer nutzen:
Online-Installer (während der Installation werden andere Pakete für Qt geholt)
https://hhoegl.informatik.hs-augsburg.de/pub/qt5/qt-unified-linux-x64-3.1.1-online.run
Offline-Installer (kann man auch ohne Netz installieren)
https://hhoegl.informatik.hs-augsburg.de/pub/qt5/qt-opensource-linux-x64-5.13.2.run
Man kann das Anlegen eines User-Account bei Qt überspringen, indem man die Eingabefelder beim Installer leert.
Download von https://www.qt.io/offline-installers (es ist nicht nötig, dass Sie einen Account bei Qt anlegen)
Eine weitere Alternative, die aber auch mehrere Gigabyte Platz braucht, ist die Anaconda Python Distribution, die Sie unter https://www.anaconda.com/distribution/ bekommen. Darin ist auch Qt5 enthalten.