Forum: Mikrocontroller und Digitale Elektronik LPC1549 von Grund auf verstehen


von Doran S. (utzer)


Angehängte Dateien:

Lesenswert?

Hallo,

ich wollte mal, um mehr über die LPC Mikrocontroller zu lernen, das 
Tutorial von hier durcharbeiten: 
https://www.mikrocontroller.net/articles/LPC-Tutorial

Allerdings habe ich ein Board mit einem LPC1549, deshalb habe ich das 
Linker-Skript angepasst und im Anhang angehängt.

Mein Board hat eine LED an Port0_25, deshalb ich den Code der 
Main-Funktion wie folgt angepasst:
1
int main()
2
{
3
    /* enable GPIO0 (bit 14) and IOCON (bit 13) clock in the SYSAHBCLKCTRL0 register */
4
    *(volatile uint32_t*)0x400740C4 = (1 << 13) | (1 << 14);
5
    /* setup PIO0_25: GPIO (bits [2:0]), Pull-Up (bits [4:3]), digital mode (bit 7) */
6
    *(volatile uint32_t*)(0x400F8000 + 25 * 0x4) = (0x2 << 3);
7
    /* set PIO0_25 to output using the GPIO->DIR0 register */
8
    *(volatile uint32_t*)(0x1C000000 + 0x2000 + 0) |= (1U << 25);
9
10
    while(1)
11
    {
12
        /* toggle LED at PIO0_25 using GPIO->NOT0 register */
13
        *(volatile uint32_t*)(0x1C000000 + 0x2300 + 0) = (1U << 25);
14
        
15
        wait_cycles(10000);
16
    }
17
    
18
    return 0;
19
}

Dabei habe ich die Adressen der Register entsprechend der Memory Map es 
LPC1549 angepasst, aber leider tut sich nichts, die LED blinkt einfach 
nicht....

Hat jemand einen Tipp, wo der Fehler liegen könnte?
Muss ich noch irgendwie den Takt aktivieren?

Viele Grüße,
Doran

von Johannes S. (Gast)


Lesenswert?

Wie sieht es mit dem Startup Code aus? Die Initialisierung kann man aus 
CMSIS nehmen, der uC sollte aber ohne mit dem internen 12 MHz Oszillator 
laufen.
Was eventuell noch fehlt ist die power für gpio einzuschalten, ich weiß 
jetzt nicht ob das nach Reset per default für deinen Port gemacht wird.
Einfacher gehts jedenfalls mit MCUXPresso und einem Beispielprojekt.

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

Versuch mal
1
    *(volatile uint32_t*)0x400740C4 |= (1 << 13) | (1 << 14);
(|= vs. =).
Evtl. hast Du da wichtigen Einheiten den Takt abgestellt.

: Bearbeitet durch User
von Doran S. (utzer)


Angehängte Dateien:

Lesenswert?

Hallo,

Danke schon mal für die Tipps, ich habe es nun mit:
1
*(volatile uint32_t*)0x400740C4 |= (1 << 13) | (1 << 14);
versucht, es tut allerdings immer noch nicht.

Meinen Startup-Code habe ich mal angehängt, da er etwas länglich ist.
Habe mit LPCExpresso ein Beispielprojekt gemacht und damit funktioniert 
es (natürlich). Mir geht es halt darum, etwas über die Hardware zu 
lernen und deshalb will ich auf dieser unteren Ebene experimentieren.

Hat jemand noch eine Idee, woran es liegen könnte?

Viele Grüße,
Doran

von Christian T. (christian_t)


Lesenswert?

Hallo,

ich würde das Binary debuggen und gucken, was passiert (instruction 
stepping).

Hast du daran gedacht:
Stack-Pointer ist initialisiert?
Interrupt-Vektor -Tabelle ist da?
Die Checksum ist korrekt?
Der Reset-Handler wird aufgerufen?
Aus dem Reset-Handler wird Main aufgerufen?
...

Gruß,
Christian

von Johannes S. (Gast)


Lesenswert?

Dann vergleiche den Startup Code mal mit dem vom LPCXpresso Projekt. Bei 
den Int Vektoren hast du ganz schön gepfuscht, die sollten schon alle 
richtig definiert sein.
Auch ein SystemInit zum clock einstellen wird nicht aufgerufen.
Wenn du schon das LPCXpresso (ist mittlerweile veraltet und wurde durch 
MCUXpresso ersetzt) hast, dann nimm das funktionierende Projekt, setze 
einen Breakpoint auf den ResetHandler und du kannst im Debugger 
verfolgen was da gemacht wird.
Und das Schreiben auf die Registeradressen anstatt die passenden 
Headerfiles zu nutzen macht das ziemlich unleserlich. Sich auf die 
Kommentare verlassen zu müssen ist keine gute Idee.

von W.S. (Gast)


Lesenswert?

Doran S. schrieb:
> Hat jemand einen Tipp, wo der Fehler liegen könnte?
> Muss ich noch irgendwie den Takt aktivieren?

Ja, die diversen Fehler liegen bei dir.

Erstens frag ich mich, wozu du so ein Linkerscript bloß brauchst. Geht's 
nicht etwas einfacher?

Als nächstes solltest du dich beim Setup deines Chips um das Freigeben 
der benötigten Takte kümmern. Normalerweise kommen die Chips mit einer 
Default-Pineinstellung aus dem Reset. Wenn du da was ändern willst, mußt 
du eben die betreffenden Peripherie-Cores erstmal mit Takt versehen.

Vom Einstellen des eigentlichen Systemtaktes sehe ich hier mal ab, nimm 
du erstmal den internen Default-RC-Takt.

Du wirst also nicht umhin kommen, das zugehörige Referenzmanual zu 
lesen. Zu allererst das Kapitel über die GPIO's, dann das Kapitel über 
die Ports, dann das Kapitel über den Systemconfig-Block mit der 
Takterzeugung und -verteilung und den Stromsparmodi usw.

W.S.

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

Christian T. schrieb:
> Die Checksum ist korrekt?

Das wirds vielleicht sein.

@Doran
Wie flasht Du das Ding eigentlich?
Ist das ein LPCXpresso1549?

Ich hab's hier auf die Schnelle mit meinem LPCXpresso1549 noch nicht 
hingekriegt, wird leider weder von lpc21isp noch von OpenOCD 
unterstützt, und diese komische USB-Stick-Simulation funktioniert unter 
Linux auch nicht.

von Johannes S. (Gast)


Lesenswert?

Jürgen S. schrieb:
> wird leider weder von lpc21isp noch von OpenOCD
> unterstützt

OpenOCD müsste gehen mit CMSIS-DAP als interface.

Und das Schreiben auf das USB-MSD soll mit den mtools gehen.

das hatten wir hier schon mal:
Beitrag "LPC1549 lässt sich nicht programmieren"

von Jim M. (turboj)


Lesenswert?

Jürgen S. schrieb:
> Ich hab's hier auf die Schnelle mit meinem LPCXpresso1549 noch nicht
> hingekriegt

Mann kann die Dinger auf JLink oder CMSIS DAP umflashen. Suche mal bei 
NXP nach LPCScrypt. OpenOCD unterstützt sowohl Jlink als auch CMSIS DAP.

von Doran S. (utzer)


Angehängte Dateien:

Lesenswert?

Hallo nochmals,

Danke an alle für die Tipps, ich habe es jetzt zum Laufen bekommen.
Es lag hauptsächlich an der Vektor-Tabelle. Im Anhang die 
funktionierende Version in der Datei crt0.c

Außerdem habe ich noch etwas im makefile angepasst und hänge dieses auch 
an, vielleicht hilft es jemandem. Darin sieht man auch, wie ich mit den 
mtools unter Linux über das USB MSD den LPC1549 direkt flashe.

Die korrekte Checksumme schreibe ich mit dem Tool "checksum" aus dem 
Anhang.

Ja, das Board ist ein LPCXpresso1549.

Viele Grüße,
Doran

von Jim M. (turboj)


Lesenswert?

Mach da bloss die ganzen "magischen Zahlen" raus und nimm die Header von 
NXP.

Das kann man so nach einer Woche nicht mal selber mehr debuggen.

Das hier:
1
LPC_SYSCON->AHBCLKCTRLSET0 = SYSCON_AHBCLKCTRL0_GPIO0_Msk | SYSCON_AHBCLKCTRL0_IOCON_Msk;

erzeugt denselben Assembler Code beim Compilieren und ist deutlich 
besser lesbar.

von Doran S. (utzer)


Lesenswert?

Jim M. schrieb:
> Mach da bloss die ganzen "magischen Zahlen" raus und nimm die Header von
> NXP.
Jaaa, klar, da bin ich gerade dabei. Es ging mir eben darum, zur Übung 
mal wirklich alles von Hand zu machen. Für ernsthafte Projekte habe ich 
dann immer das LPCXpresso verwendet (und da das ja wohl veraltet ist, 
werde ich mal auf das MCUXpresso umsteigen....)

>
> Das kann man so nach einer Woche nicht mal selber mehr debuggen.
>
> Das hier:
>
1
> LPC_SYSCON->AHBCLKCTRLSET0 = SYSCON_AHBCLKCTRL0_GPIO0_Msk | 
2
> SYSCON_AHBCLKCTRL0_IOCON_Msk;
3
>
>
> erzeugt denselben Assembler Code beim Compilieren und ist deutlich
> besser lesbar.

Müsste da nicht wieder |= statt = sein?

von Johannes S. (Gast)


Lesenswert?

Doran S. schrieb:
> werde ich mal auf das MCUXpresso umsteigen....

es sieht alles gleich aus wie in LPCx, sind aber trotzdem viele Details 
verbessert.

> Müsste da nicht wieder |= statt = sein?
gut aufgepasst, aber es ging ja primär um die Namen.

von Jürgen S. (starblue) Benutzerseite


Lesenswert?

Bei mir blinkt es jetzt auch.

Nachdem ich R50 entfernt habe, kommt man jetzt auch in den 
UART-ISP-Modus. Dazu Reset drücken, während man die Taster ISP0 und ISP1 
heruntergedrückt hält.

R50 ist ein 470Ohm Pull-Up zu 5V(?) für ISP1, das wird dann vom Taster 
über 2,2kOhm Richtung Masse gezogen.  Sehr weit kommt es da nicht, d.h. 
der ISP1-Taster ist in der Default-Konfiguration des Boards nutzlos :-(. 
Was hat sich der Schaltungsentwickler wohl dabei gedacht?

Der On-Board Debugger ist mit lpcscrypt auf CMSIS-DAP geflasht (Hinweis: 
vorher alle anderen ähnlichen Geräte vom USB abstecken), bekommt aber 
keinen Kontakt zum LPC1549, scheitert bei der Umschaltung JTAG zu SWD.

Mit einem LPC-Link2 am Debug-Stecker bekomme ich eine Verbindung zum 
LPC1549, die üblichen Debugfunktionen wie Anhalten und Speicher ansehen 
gehen.  Flashen geht aber nicht, anscheinend funktioniert das Anhalten 
nach IAP nicht (getestet mit lpc17xx.cfg, ein lpc15xx.cfg gibt es 
nicht).

In lpc21isp habe ich Support für LPC15xx eingebaut, das scheint soweit 
zu gehen.  Demnächst auf Github.

Ich dachte erst, die ersten beiden Einträge der Vektortabelle + korrekte 
Checksum sollten für so ein simples Programm reichen, aber dann schießt 
die Checksum in den Anfang des Codes rein.  Mit zwei Einträgen mehr in 
der Tabelle geht's.

So, das reicht mir dann auch erstmal zum Thema LPCXpresso1549.  Das 
Board lag hier seit der Embedded World 2014 im Karton, und ich wollte 
immer mal damit spielen, bin aber vorher nie dazu gekommen.

von Brandy (Gast)


Lesenswert?

Hallo Doran,

Habe mir auch ein LPCXpresso1549-Board zugelegt.

Vielen Dank für die Dateien. Ist eine sehr schöne Minimalversion. Hast 
Du  das schon mal unter der MCUXpresso-Software zum Laufen bekommen?

von Doran S. (utzer)


Lesenswert?

Hallo Brandy,

das MCUXpresso verwende ich jetzt gar nicht mehr. Den Quellcode editiere 
ich einfach mit Kate (Texteditor) und kompiliert wird mit dem makefile 
von der Konsole aus. In dem makefile ist auch ein Teil drin um das 
Programm dann auf den Mikrocontroller zu flashen.

Wo hakte es denn bei Dir?

Habe mir dann auch noch eine Bibliothek gebastelt, mit der man die 
Peripherie (GPIO, Timer, ...) des Mikrocontrollers relativ komfortabel 
ansprechen kann. Habe das eben hauptsächlich gemacht, um dabei zu 
lernen.

Viele Grüße,
Doran

von Brandy (Gast)


Angehängte Dateien:

Lesenswert?

Das Programm wird zwar kompiliert, aber nach dem Upload mit J-Link läuft 
es nicht.
Mit der normalen GNU-MCU-Eclipse Umgebung geht das fehlerfrei. Das 
GNU-MCU-Projekt habe ich angehangen.
Ich kann nicht ganz nachvollziehen, was MCUXpresso da macht.
Von der Console bin ich eigentlich weg. Eclipse bietet schon einige 
Möglichkeiten in einer integrierten Umgebung. Muss halt nur vernünftig 
konfiguriert werden. Dafür gibt es ja genügend Tutorials.

Worum es mir eigentlich geht:
Ich benötige einen absolut minimalen startup-Code und Linkerscript ohne 
den ganzen Schnickschnack mit CMSIS usw. . Es sollen nur die minimal 
notwendigsten Initialisierungen ausführt werden (inkl. für C++).
Die restliche Hardware wird dann in Main initialisiert. Das hat zwei 
Gründe:
a) ich habe Projekte, die einen objektorientierten HAL benötigen. Den 
gibt es für zwei MCUs schon. Ich brauche daher nur den HAL anzupassen 
und kann die den LPC in den Projekten als Update verwenden.

b) Ich habe eine bessere Kontrolle über die Initialisierung in Main und 
es ist übersichtlicher, da die MCU-Hardware (und korrespondierende 
Board-Hardware) in Klassen gekapselt ist.

Vielleicht könntest Du noch die Initialisierungen für C++ hinzufügen.

Grüße

Karsten

von Doran S. (utzer)


Lesenswert?

Hallo Karsten,

spontan fällt mir da noch die Checksumme ein. Hast Du die 
berücksichtigt?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.