Mikrocontroller für das IoT - Teil 2: 430 bedeutet Grün

Den TI MSP430 mit Eclipse programmieren – das Tutorial

Tam Hanna

© Shutterstock / Abscent

Kaum ein Prozessorsystem ist so sagenumwoben wie der TI MSP430. Wer drei Personen nach ihrer Erfahrung fragt, bekommt meist drei verschiedene Antworten. Allen gemein ist nur, dass die Gestation der CPU irgendwie mit Energiesparen zu tun hat. Wir wollen uns einmal anschauen, wie man den 16-Bit-Microcontroller von Texas Instruments unter Eclipse zum Laufen bringt. En passant behandeln wir wichtige Grundlagen der Embedded-Programmierung.

Eine häufige Erzählung besagt, dass TI den MSP430 für die Realisierung einer Smart-Energy-Lösung benötigte: Ob der vergleichsweise komplexen Algorithmen war ein Achtbitter ungeeignet, während existierende Sechzehnbitter aufgrund ihres Stromverbrauchs die Gesamtlösung ad absurdum geführt hätten. Im mittlerweile nur mehr antiquarisch erhältlichen Buch „Signal And Image Processing Sourcebook“ findet sich ein Verweis auf den als TSS400 bezeichneten Vorgängerchip. Es handelte sich dabei um einen vierbittigen Mini-Microcontroller, der auf die Verarbeitung von Sensordaten optimiert war.

MSP430-CPUs sind beliebt, weil sie sowohl vom Preis als auch von den Ansprüchen an die sie umgebende Logik her mit Achtbittern vergleichbar sind. Wer die x Betriebsspannungen für einen komplexen DSP bereitstellen musste, weiß diese Vorteile zu schätzen. Dank der 16-Bit-Architektur des MSP430 steht trotzdem mehr Rechenleistung zur Verfügung.

Serie: Microcontroller für das Internet der Dinge

  • Teil 1: Arduino Uno mit Eclipse programmieren
  • Teil 2: Den TI MSP430 mit Eclipse programmieren
  • Teil 3: Ein Chip, sie zu knechten: STM32
  • Teil 4: Multi-Threading mit dem STM32F429
  • Teil 5: Grafik, Marke Eigenbau

TI MSP430 – Darreichungsform: innovativ!

Texas Instruments war eines der ersten Unternehmen, die Entwickler mit preiswerten Evaluationskits umgarnten. Unser in den folgenden Schritten verwendetes eZ430-F2013 ist ein Klassiker – das Produkt ist seit 2006 in fast unveränderter Form am Markt. Es ist insofern innovativ, als das Produkt aus zwei Teilen besteht. Die mit einer USB-Schnittstelle ausgestattete Platine enthält einen mehr oder weniger vollwertigen Debugger, der die über den Pfostenstecker angeschlossene CPU-Platine steuert. Zweitere lässt sich direkt in Schaltkreise implantieren, da sie alle Pins der MCU über Lötfelder exponiert.

Wer die Komponente bei TI oder einem Distributor seines Vertrauens bestellt, wird mit einem in einer DVD-Hülle befindlichen USB-Stick versorgt. Seine „Nutzbarmachung“ setzt etwas Handarbeit voraus: Die im Kasten „An die Arbeit!“ vorgeschlagenen Schritte stellen nur einen Weg dar.

An die Arbeit!

Die Vorbereitung des eZ430-F2013 setzt einen Lötkolben, dünnes (0,8 mm!) Lötzinn und eine abbrechbare Steckerleiste voraus. Sie ist auch ohne große Elektronikkenntnisse zu bewältigen.

 

1) Seitlich aufbrechen

Das rechteckige „Auge“ bietet genug Platz für einen Schraubenzieher. Achten Sie darauf, die direkt am Auge befindliche Planare nicht zu beschädigen.

 

2) Rest aufbrechen

Ziehen Sie einen dünnen Elektronikerschraubenzieher entlang, um die restlichen Füßchen aus ihren Holstern zu befördern. Gehen Sie dabei behutsam vor.

 

3) Zielboard abstecken

Trennen Sie zwecks Schadensvermeidung das Zielboard vom Brenner. Beachten Sie die Positionierung in der Mitte – links und rechts bleibt ein Pin frei.

 

4) Löten und prüfen

Löten Sie zwei Buchsenreihen in die vorgesehenen Aussparungen. Achten Sie darauf, die vier „kleinen“ Lötstellen dabei nicht zu überbrücken.

 

5) Deckel zerlegen

TI liefert eine transparente Abdeckung mit. Sie lässt sich durch „Ziehen“ mit dem Lötkolben zerlegen; entstehende Kunststofffäden beseitigt man mit einer Kleinfeile.

 

6) Zusammenbauen

Der Lohn der Mühen ist eine veränderte Version des USB-Sticks, die mit einer Steckerleiste versehen ist. Externe Peripherie lässt sich nun mit MF-Kabeln anstecken.

Software

Texas Instruments bietet seinen Entwicklern eine Vielzahl von Entwicklungsumgebungen an, die teilweise nur in Form von Evaluationslizenzen vorliegen. Wer auf eine quelloffene Toolchain und Eclipse setzt, hat aus lizenzrechtlicher Sicht wenig zu befürchten.

Unter Ubuntu 14.04 stehen die benötigten Werkzeuge im Repository zur Verfügung. Das Herunterladen lässt sich durch Eingabe von sudo apt-get install msp430-libc mspdebug msp430mcu binutils-msp430 gcc-msp430 gdb-msp430 bewerkstelligen; das Kommando lädt rund 30 MB herunter und nimmt danach 120 MB Festplattenplatz in Beschlag.

Als Eclipse-Version wollen wir Juno verwenden; zwecks reduziertem Aufwand bei der Installation von Erweiterungen nehmen wir die Distribution Eclipse IDE for C/C++ Developers. Starten Sie die IDE und verbinden Sie sich mit der Plug-in-Quelle CDT. Beschaffen Sie sich danach im Namespace CDT Main Features das Modul C/C++ Development SDK. Der Namespace CDT Optional Features wird um die beiden Module C/C++ Debugger Services Framework (DSF) Examples und C/C++ GDB Hardware Debugging erleichtert. Im Zusammenspiel mit allen Dependencies wird die Einrichtung der Erweiterungen rund fünf Minuten in Anspruch nehmen.

Hardware

Im nächsten Schritt folgt ein Funktionstest der Planare. Im Interesse der Sicherheit Ihres Equipments sollten Sie – Löten führt bei Informatikern erfahrungsgemäß oft zu lustigen Ergebnissen – diese Schritte entweder auf einer ausrangierten Workstation oder unter Nutzung eines mit eigener Stromversorgung und Sicherungen ausgestattetem Hubs durchführen.

Verbinden Sie das Entwicklungs-Kit zuerst nur mit dem mit Energie versorgten Hub, ohne diesen an den Rechner anzuschließen. Ein im Auslieferungszustand vorliegendes eZ430-F2013 enthält ein Programm, das bei Funktionieren die auf der Targetplatine befindliche LED heftig blinken lässt. Stellen Sie sodann eine Verbindung zwischen Hub und Workstation her. Die Eingabe von dmesg emittiert die letzten im Systemlog befindlichen Ereignisse. Beim Anlassen des Treibers kommt es traditionell zu einigen Fehlern – die Verbindung funktioniert, wenn die Workstation dem Entwickler-Kit eine ID zuweist:

 
tamhan@tamhan-elitebook:~$ dmesg

. . .

[ 1395.913982] ti_usb_3410_5052 2-1.3.1:2.0: TI USB 3410 1 port adapter converter detected

[ 1395.914124] usb 2-1.3.1: TI USB 3410 1 port adapter converter now attached to ttyUSB0

… und wieder Software

Auf Seiten von Eclipse ist nun die Erstellung eines Projekts vom Typ „C Project“ erforderlich; als Projektvorlage dient Executable | Empty Project | Linux GCC. Die Zuweisung des zu verwendenden GCC für den MSP430 erfolgt durch Rechtsklick auf das Projekt und die Auswahl der Menüoption Properties | C/C++ Build | Settings . Achten Sie darauf, in der Combobox Configuration die Option All Configurations auszuwählen, bevor Sie die folgenden Schritte durchführen.

Klicken Sie danach auf die Rubrik GCC C Compiler und geben Sie im Command-Feld den String msp430-gcc  -mmcu=msp430f2013 ein (Abb. 1). Im MCU-Bereich wird traditionell auf Größe optimiert – eine Einstellung, die sich in der Unterrubrik Optimization festlegen lässt. Zu guter Letzt benötigt der Compiler einige Includes, die das Ansprechen von prozessorspezifischer Hardware ermöglichen. Dazu folgt ein Klick auf GCC C Compiler | Includes, der hinzuzufügende Suchpfad lautet /usr/msp430/include.

Abb. 1: Eclipse weiß nun, dass es statt „gcc“ auf die Variante „msp430gcc“ setzen muss

In der Rubrik GCC C Linker wird als Kommando der String msp430-gcc -mmcu=msp430f2013 -Wl,-Map=${BuildArtifactFileBaseName}.map eingegeben. Der in geschwungenen Klammern gesetzte Teil informiert Eclipse darüber, dass dieser Teil des Befehls durch den Inhalt der Variable BuildArtifactFileBaseName ersetzt werden muss. In der Unterrubrik Libraries ist der Suchpfad /usr/msp430/lib erforderlich.

Der Assembler hört auf den Namen msp430-as, unter General ist zudem der Include-Pfad /usr/msp430/include notwendig. Im Tab Build Artifact muss dann noch als Artifact Extension elf ausgewählt werden.

Damit sind wir auch hier fertig. Erstellen Sie eine neue Datei namens main.c, die mit dem Code aus Listing 1 ausgestattet wird.

 
#include <msp430f2013.h>


int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;
  // P1.0 hosts LED
  P1DIR |= 0x01;
  while(1==1)
  {
    long i;
    P1OUT |= 0x01; // LED ON
    for(i=0;i<6000;i++){}
    P1OUT &= 0xfe; // LED OFF
    for(i=0;i<6000;i++){}
  }
}

Nach dem Laden der Headerdatei deaktivieren wir den Watchdog-Timer: Er findet in einem der folgenden Abschnitte weitere Erwähnung. Der Rest unseres Programms ist eine primitive Neuentwicklung des von Haus aus am MSP430-Target befindlichen Codes. Wir setzen den mit der LED verbundenen Pin als Erstes in den Ausgangsmodus, um ihn daraufhin regelmäßig ein- und auszuschalten.

Klicken Sie das Projekt im Project Explorer rechts an und wählen Sie die Option Build Project. In der Kommandozeile erscheint ein Build-Prozess, der nach folgendem Schema abgeschlossen wird:

 

11:02:46 **** Incremental Build of configuration Debug for project SUSMSP4301 ****

. . .

Finished building target: SUSMSP4301.elf

 

11:02:47 Build Finished (took 192ms)

Der Lohn der Mühen ist eine .elf-Datei, die die in den Microcontroller zu schreibenden Informationen enthält. Dies lässt sich von der Kommandozeile aus oder mit diversen Brennprogrammen bewerkstelligen.

Brenne direkt

In der Serienproduktion wandert das ELF-File zum Brenner, der fertige Chips zurückliefert. Während des Debuggings ist es sinnvoller, die Auslieferung per IDE zu erledigen. Als ersten Akt müssen wir den MSP-Testserver anwerfen, der die Verbindung zwischen MSP430-MCU und GDB-Instanz ermöglicht. Öffnen Sie dazu ein Terminalfenster, und geben Sie den Befehl aus Listing 2 ein.

 

Listing 2

tamhan@tamhan-elitebook:~$ mspdebug uif -d /dev/ttyUSB0

MSPDebug version 0.22 - debugging tool for MSP430 MCUs

. . .

Trying to open /dev/ttyUSB0 at 460800 bps...

. . .Configured for Spy-Bi-Wire

Device: MSP430F20x3

 

Use the "opt" command ("help opt") to set options.

Press Ctrl+D to quit.

(mspdebug)

Achten sie darauf, dass mspdebug den auf dem Zielboard befindlichen Prozessor wie im Listing gezeigt erkennt. Aktuelle Versionen des mspdebug-Werkzeugs sind nach dem Start im klassischen Terminalmodus – der für die Kommunikation per gdb notwendige Port wird erst auf explizite Anfrage geöffnet. Das vorherige Setzen von gdb_loop sorgt dafür, dass der Port auch nach dem Zusammenbruch der Verbindung zu einer GDB-Instanz offen bleibt:

 

 (mspdebug) opt gdb_loop true

 (mspdebug) gdb

Bound to port 2000. Now waiting for connection...

Lassen Sie das Terminalfenster sodann offen, um die Ausführung des Threads sicherzustellen. Die Interaktion zwischen Eclipse und GDB wird von mspdebug instrumentiert: Wer eine Zweibildschirmworkstation hat und sich mit GDB nicht gut auskennt, kann beim Beobachten den einen oder anderen Kniff herausfinden.

Klicken Sie auf Run | Debug Configuration und erstellen Sie eine neue Konfiguration vom Typ GDB Hardware Debugging. Im Debugger -Tab wird als Kommando der String msp430-gdb eingegeben; die Portnummer wird von 10000 auf 2000 angepasst. In der Textbox in der Rubrik Initialization Commands wird dann der String monitor erase eingegeben (Abb. 2).

Abb. 2: Die Default-Konfiguration funktioniert im Großen und Ganzen

Nach einem Klick auf Apply folgt das Antippen von Debug, woraufhin die Auslieferung auf den Prozessrechner beginnt. Der Lohn der Mühen ist eine permanent leuchtende LED – die Optimierung von GDB hat die leeren Korpusse der for-Schleifen gnadenlos eliminiert.

Ein einfacher Weg zum Austreiben dieses lästigen Verhaltens ist das Volatile-Setzen der Laufvariable – das Einfügen von beliebigen arithmetischen Kommandos nach dem Schema i=i+1 führt nicht zu einer Lösung:

 

while(1==1)
{
  volatile long i;
    P1OUT |= 0x01; // LED ON
    for(i=0;i<6000;i++)
    {    }

Das Schlüsselwort volatile genießt in der Embedded-Programmierung besondere Bedeutung. Es weist den Compiler darauf hin, dass die vom Pointer oder von der Variable referenzierten Werte vor jedem Zugriff neu auszulesen sind. Im vorliegenden Fall sorgt dies dafür, dass die Optimierung die Variable nicht tangiert. Weitere Informationen hierzu finden sich in einem lesenswerten englischsprachigen Artikel von Nigel Jones, der hier kostenlos bereitsteht.

Interface mich

TI bietet in der MSP430-Familie eine Vielzahl von Controllern an, die bis zu 8 KB RAM und 120 KB Codespeicher aufweisen. Unser Chip ist, nicht zuletzt ob der Minimierung des Stromverbrauchs, sehr frugal ausgestattet: Es stehen nur 128 Byte RAM zur Verfügung.

Da das Ansteuern von Displays und andere Lustigkeiten ob des geringen Speicherausbaus nur wenig Freude macht, wollen wir uns in diesem Teil der Serie stattdessen mit Grundlagen der Prozessortechnik befassen.

Achtung, Fehler

TI fertigt die hier verwendete MCU seit mehr als zehn Jahren unverändert: Manche Versionen weisen seltsame Fehlverhalten auf. Weitere Informationen dazu finden sich in den unter dieser URL einsehbaren Errata.

Als Erstes soll der Watchdog-Timer einer Betrachtung unterzogen werden. Microcontroller finden sich oft in performancekritischen Aufgaben wieder, in denen Systemausfälle todbringende Konsequenzen haben. Da Software in der Praxis nie fehlerfrei ist, begegnen Prozessorhersteller dem Risiko von in obskuren Subroutinen versteckten Bugs mit einer radikal-genialen Maßnahme:

Mit einem WDT ausgestattete MCUs zählen während der Programmausführung die anfallenden Taktzyklen über einen Vorteiler. Erreicht sein aus dem Speicherbereich heraus ansprechbares Akkumulatorregister einen bestimmten Wert, so startet die MCU neu. Dies passiert in der Hoffnung, dass der kritische Codepfad nach dem Neustart nicht abermals abgearbeitet wird.

Wir können uns dieses Verhalten anhand des folgenden Programms ansehen – es handelt sich dabei um eine Abart des soeben konstruierten Blinkers, der den Watchdog-Timer nicht deaktiviert. Zudem schalten wir die LED kurz aus, bevor wir die Mutter aller Langsamblinkprozesse loslassen (Listing 3).

 
int main(void)
{
  WDTCTL = WDT_MRST_32;
  // WDTCTL = WDTPW + WDTHOLD;

  P1DIR |= 0x01;
  while(1==1)
  {
    volatile long i;
    P1OUT &= 0xfe; // LED OFF
    for(i=0;i<10;i++){}
    P1OUT |= 0x01; // LED ON
    for(i=0;i<60000;i++){}
    P1OUT &= 0xfe; // LED OFF
    for(i=0;i<60000;i++){}
  }
}

Wer die auskommentierte Zeile reaktiviert, sieht eine langsam blinkende LED. Ist die Zeile vorhanden, so leuchtet die LED so gut wie permanent. Das menschliche Auge ist nicht in der Lage, das kurze Ausblenden vor dem Abfeuern des WDT zu sehen.

Töte ihn!
mspdebug verbindet sich immer nur mit einer GDB-Instanz. Dies ist insofern ärgerlich, als Sie die gerade aktive Debug-Session vor dem abermaligen Anklicken des Debug-Buttons von Hand beenden müssen. Unterbleibt dies, so werden Sie mit einem Fehler der Bauart „Error in final launch sequence“ belohnt.

Mit einem Digitalspeicheroszillograf lässt sich dieses Verhalten visualisieren. Verbinden Sie den positiven Teil der Probe mit dem Pin P2, während Ground an P14 angeschlossen wird. Weisen Sie das Gerät sodann an, bei einer fallenden Flanke zu triggern. Das bedeutet, dass der Oszillograph immer dann einen neuen Lesevorgang startet, wenn das anliegende Signal den Trigger-Pegel von oben nach unten durchschreitet. Das Ergebnis präsentiert sich wie in Abbildung 3 gezeigt.

Abb. 3: Der Digitalteil des Hybridoszillografen zeigt, dass wir es mit einer Schleife zu tun haben

Erfreulicherweise ist es nicht sonderlich schwer, unser Programm trotz eingeschaltetem WDT lauffähig zu bekommen. Ersetzen Sie den Korpus der while-Schleife durch ein Konstrukt, wie in Listing 4 zu sehen, um das Blinken zu reaktivieren.

 
  while(1==1)
  {
    volatile long i;
    P1OUT &= 0xfe; // LED OFF
    for(i=0;i<10;i++){}
    P1OUT |= 0x01; // LED ON
    for(i=0;i<60000;i++)
    {
       WDTCTL = WDTPW + WDTCNTCL;
    }
    P1OUT &= 0xfe; // LED OFF
    for(i=0;i<60000;i++)
    {
       WDTCTL = WDTPW + WDTCNTCL;
    }
  }

Der Watchdog des MSP430 nimmt Befehle nur über das WDTCTL-Register an: Eingehende Orders müssen stets mit der in WDTPW definierten Konstante beginnen. GCC baut das passende Byte in manche Konstanten ein – beim Löschbefehl WDTCNTCL (WatchDog Timer CouNTer CLear) müssen wir es von Hand antackern.

WDT auf Lepschi DIV
Das genaue Verhalten des Watchdog-Timers ist stark von Compiler und/oder Klassenbibliothek abhängig. Manche Anbieter schalten den WDT von Haus aus ab, um Supportanfragen zu minimieren. Andere Compilerhäuser lassen ihn – wie von TI vorgesehen – eingeschaltet; bei Programmen oder Bibliotheken mit langer Vorladezeit gibt es eine PreInit-Funktion, in der der WDT abgeschaltet werden kann.

Vom Interrupt

Prozessrechner müssen auf anstehende Ereignisse binnen Millisekunden reagieren: Wenn ein Radarwarner nach dem Erschnüffeln eines Lock-ons vor dem Absetzen einer Warnung Housekeeping betreibt, verliert der Pilot des Luftfahrzeugs wertvolle Reaktionszeit.

Microcontroller lösen dieses Problem seit Jahr und Tag durch Interrupts. Die je nach MCU-Familie verschieden stark ausgebaute IRQ-Logik überwacht das Auftreten von vom Entwickler vorzugebenden Ereignissen in Hardware: Tritt eines der als kritisch bezeichneten Events auf, so wird die Programmausführung sofort unterbrochen. Die MCU arbeitet sodann an anderer Stelle weiter – der Profi spricht vom Interrupt-Vektor –, um später wieder ins Hauptprogramm zurückzukehren.

Vor dem Anschließen der für die Interrupt-Übung notwendigen Hardware wollen wir einen Blick auf das in der Abbildung 4 gezeigte Schaltbild unserer Tochterplatine werfen.

Für uns ist die Situation insofern kritisch, als das Daughterboard permanent mit dem Programmieradapter verbunden ist: Pins 10 und 11 stehen nicht für eigene Schaltungen zur Verfügung, wenn wir den Debugger weiter nutzen wollen. Aus diesem Grund verbinden wir unseren für die Interrupt-Auslösung zuständigen Taster samt dem dazugehörenden „Schutzwiderstand“ mit Pin 5 der MCU: Er ist laut dem Pinout mit dem Port P 1.3 verbunden (Abb. 5).

Abb. 5: Der Widerstand sorgt dafür, dass der Taster die Stromversorgung nicht kurzschließt

Da ein Taster nur sehr wenig Strom braucht, können wir die notwendige Energie direkt aus dem Programmier-Dongle beziehen. Bei größeren Schaltungen sollten Sie ein externes Labornetzteil einsetzen: Achten Sie darauf, dass der MSP430 mit 5 V Versorgungs- oder Signalspannung nichts anzufangen weiß. Der Korpus unseres Polling-freien Programms sieht aus wie in Listing 5.

 
int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;
  P1DIR |= 0x01;
  P1IE |= BIT3;
  P1IFG &= ~BIT3;
  P1IES |= BIT3;
  eint();
  P1OUT &= 0xfe; // LED OFF

  volatile i;
  while(1==1)
  {
    i=i+1;
    i=i-1;
  }
}

Nach dem Konfigurieren der Ein- und Ausgangspins melden wir durch die Register P1IE und P1IFG Interesse an Interrupts an, die vom dritten Pin des Port 1 emittiert werden. P1IES legt die Art der Flanke fest, die Ereignisse auslöst: Der MSP430 kann entweder bei steigenden (Low auf High) oder bei fallenden (High auf Low) Transitionen reagieren. eint() schaltet die Interrupt-Logik des MSP430 scharf.

Eine Endlosschleife hält die CPU beschäftigt. Dies ist insofern wichtig, als der Flash-Speicher einer nicht vollständig programmierten MCU beliebige Anweisungen enthält: Das „Hinauslaufen“ aus dem Nutzcode ist einer der häufigsten Anfängerfehler in der Controllerprogrammierung.

Damit können wir uns der Realisierung des Event Handlers – Experten sprechen im Embedded-Bereich von einer „Interrupt Service Routine“ – zuwenden. Ihr Korpus sieht dann aus wie in Listing 6 dargestellt.

 
#include <legacymsp430.h>

int turn_on=1;
interrupt (PORT1_VECTOR) HandlePort1IRQ(void)
{
  if(turn_on==1)
  {
    P1OUT |= 0x01;
    turn_on=0;
    P1IES &= ~BIT3;
  }
  else
  {
    P1OUT &= 0xfe;
    turn_on=1;
    P1IES |= BIT3;
  }
  P1IE |= BIT3;
  P1IFG &= ~BIT3;
}

GCC bietet Entwicklern mit interrupt(typ) ein Intrinsic an, mit dem eine Funktion als für einen bestimmten Interrupt zuständig erklärt wird. Die dazu notwendigen Deklarationen finden sich in der Datei legacymsp430.h, die über eine Präprozessordirektive eingebunden wird.

Im nächsten Schritt folgt etwas „Bit Twiddling“. Der MSP430 setzt die Interrupt-Registrierung nach jedem Aufrufen der ISR zurück, weshalb wir unser weiteres Interesse durch Setzen von P1IE und P1IFG anmelden müssen. Zudem passen wir den Wert von P1IES an, um auf die gerade passende Flanke zu reagieren.

Die genauen Fähigkeiten der Interrupt-Hardware sind von Variante zu Variante unterschiedlich: Manche CPUs können mehrere Interrupts „sammeln“ oder sogar priorisieren, während andere alle IRQs als gleichermaßen wichtig betrachten und eine einmal laufende Interrupt-Serviceroutine nicht unterbrechen. Die Universität zu Washington bietet unter folgendem Link eine Präsentation an, die das Interrupt-System des MSP430 im Detail betrachtet.

Ha Nu Nodo Rah!

Der Stromverbrauch eines Prozessors wird von Betriebsspannung und Taktrate beeinflusst: Die Spannung fließt quadratisch ein, während die Taktfrequenz linear Berücksichtigung findet. In Zeiten variabler Taktfrequenzen spricht – zumindest in der Theorie – nichts dagegen, die Taktfrequenz in „guten Zeiten“ zu senken. Wenn die Interrupt-Logik die Überwachung aller wichtigen Aufgaben übernimmt, kann der Hauptprozessor während Ruhephasen langsamer arbeiten oder gar in Standby gehen.

TI unterscheidet sich von Microchip und Co. insofern, als die dezidierten Stromsparmodi des MSP430 sich nicht mit der (ebenfalls möglichen) Absenkung der Taktfrequenz befassen (Tabelle 1). Stattdessen schaltet der Controller schrittweise Taktquellen samt den dazugehörenden Peripheriegeräten ab: Was außer Betrieb ist, braucht logischerweise keine Energie mehr.

Modus Beschreibung Stromverbrauch
AM CPU rennt Rund 250 yA
LPM0 CPU halt, MCLK aus 50 yA
LPM1 CPU halt, MCLK aus, DCO angehalten, wenn nicht aktiv Keine Angabe im Datenblatt
LPM2 CPU halt, MCLK und SMCLK angehalten 25 yA
LPM3 CPU halt, nur ACLK aktiv 0,8 yA
LPM4 Alles tot, RAM wird weiter mit Strom versorgt 0,1 yA

Tabelle 1: Stromsparmodi des MSP430

Caveat Emptor
Wer die in Tabelle 1 im Feld Stromverbrauch angegebenen Werte durch die Kapazität der verwendeten Batterie dividiert, erleidet Schiffbruch. Alle Energiespeicher weisen einen als Selbstentladung bezeichneten Effekt auf. Bei sehr stromsparenden Systemen stellt er oft die eigentliche Beschränkung der Laufzeit dar.

Für unsere Tasterabfrage ist LPM4 ideal: Dank des externen Triggerings benötigen wir keinerlei Logik in der MCU. Es reicht völlig aus, wenn die 128 Byte Arbeitsspeicher mit Energie versorgt werden und der Wert der Flag gespeichert bleibt:

 
  while(1==1)
  {
    _BIS_SR(LPM4_bits);
    i=i+1;
    i=i-1;
  }

Die Nutzung des Intrinsics _BIS_SR schreibt die zum Aktivieren des Stromsparmodus notwendigen Bits in das Statusregister der MCU. Diese reagiert darauf mit Einschlafbewegungen – die Abarbeitung unserer Endlosschleife wird gestoppt.

Im Fall eines eingehenden Interrupts wacht der Prozessor auf und bearbeitet die in der ISR befindlichen Instruktionen. ISRs werden durch einen speziellen Return-Befehl terminiert, der die CPU zum Weiterschlafen animiert. Ist dies nicht gewünscht, so können Sie die Bits entweder löschen oder eine spezielle Version des Interrupt-Intrinsics nutzen:

 
interrupt (INTERRUPT_VECTOR) [wakeup] IntServiceRoutine(void)

{

     /* Any normal C code */

}

Ein weiteres Hilfsmittel zur Reduktion des Stromverbrauchs ist das Verbinden von nicht benötigten Pins mit Masse oder VCC. Im hier bereitstehenden Datenbuch findet sich im Abschnitt 2.5 eine Tabelle, die die „grünsten“ Verbindungsmöglichkeiten der einzelnen Pins beschreibt.

Geber der Zeiten

Unsere bisher verwendete for-Delay-Schleife mag in Codebeispielen häufig anzutreffen sein – diensterfahrene Embedded-Entwickler sehen sie extrem ungern. Das liegt daran, dass die genaue Verzögerung sowohl von der Taktrate der MCU als auch vom Compiler abhängig ist: Optimiert die GCC-Truppe das Addieren von Longs, so stimmt das Timing nicht mehr.

Microcontroller – der MSP430 ist hier keine Ausnahme – begegnen diesem Problem durch das Deployment von einem oder mehreren Timermodulen. Abbildung 6 zeigt die Struktur des Timer1 der MSP430-Familie.

Entwickler interagieren mit dem Timer normalerweise durch das Anfordern von Interrupts: Der Controller ruft eine ISR auf, wenn der im Zählregister gespeicherte Wert eine vorgegebene Grenze erreicht hat. Im Zusammenspiel mit den im vorigen Abschnitt besprochenen Stromsparmodi lässt sich so wertvolle Energie sparen.

Zu guter Letzt gibt es in manchen Versionen des MSP430 einen DMA-Controller, der Daten im Adressraum der CPU selbsttätig herumschiebt. Er wird gern im Zusammenspiel mit dem AD-Konverter verwendet – ein Thema, dem wir uns hier aus Platzgründen nicht weiter zuwenden können.

Fazit

MSP430-CPUs sind klassischen AVR-MCUs aufgrund ihrer 16-Bit-Wortbreite haushoch überlegen: Berechnungen laufen auf dem Core aus dem Hause TI wesentlich schneller ab; dank der architekturalen Ähnlichkeit zur PDP11 stehen ausgereifte Compiler zur Verfügung. Das Entwickler-Kit ist ein weiteres Verkaufsargument: Es ist wesentlich preiswerter als AVRICE und Co.; TI bietet ein Zielboard mit integriertem Kurzstreckenfunk an.

Auf der Sollseite steht beim MSP430 die im Vergleich zu AVR und PIC kleine Community. ARM-MCUs sind ob ihrer 32-Bit-Architektur noch leistungsfähiger, stellen an ihre Platinenumgebung aber höhere Ansprüche als die auch im DIP-Gehäuse erhältlichen und im Bereich Spannungsversorgung und Taktgeneration unkritischen MSP430-CPUs.

Geschrieben von
Tam Hanna
Tam Hanna
Tam Hanna befasst sich seit der Zeit des Palm IIIc mit der Programmierung und Anwendung von Handcomputern. Er entwickelt Programme für diverse Plattformen, betreibt Onlinenewsdienste zum Thema und steht unter tamhan@tamoggemon.com für Fragen, Trainings und Vorträge gern zur Verfügung.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.