Forum: Mikrocontroller und Digitale Elektronik Bootloader & Interrupts (LPC2366)


von Nik B. (nikbamert)


Lesenswert?

Hallo allerseits!

Ich versuche nun seit Tagen die Interruptvektoren in einer Applikation, 
die per Secondary Bootloader auf einen LPC2366 geladen wird, zum laufen 
zu kriegen.

Der Bootloader steht an Adresse 0x0000, die Applikation wird an Adresse 
0x6000 ins Flash geschrieben und danach per Funktionspointer aufgerufen. 
Dies klappt auch soweit als dass keine Interrupts ausgeloest 
werden;dabei stuerzt die Applikation ab bzw. verlaeuft sich im Nirvana.

Dies OBWOHL ich die NXP Appnote dazu befolgt habe und die 
Interruptvektoren entsprechend aus der Applikation an den Anfang des 
RAMs kopiere (0x6000 -> 0x40000000) und das Mapping auf RAM umstelle.

Dies mache ich bevor der Bootloader die Applikation anspringt, der 
Bootloader laeuft im Supervisor mode damit die Stackadressen in der 
Applikation nachher erfolgreich gesetzt werden koennen.

Ich kann leider keinen der beiden Sourecodes posten aber falls ihr mir 
noch Tipps geben koennt, was ich moeglicherweise vergessen habe, bitte 
gerne, ich waere Euch sehr dankbar :-)

Gruss
Nik

von Microman (Gast)


Lesenswert?

Hallo Nik,

melde ich mich halt nochmal, vielleicht hilft es ja diese mal.
Wie ist der Sprung zu den Exception-Handlern gemacht. Eine 
Branchanweisung alleine wird nicht funktionieren. Ist der Jump zu den 
Handlern mit einem LDR-Befehl gemacht? Kopierst Du 0x40 Byte in den RAM?
Ich mache das z.B so:

Vectors:        LDR     PC, Reset_Addr
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                NOP     @ Reserved Vector
                LDR     PC, IRQ_Addr
                LDR     PC, FIQ_Addr

Reset_Addr:      .word     Reset_Handler
Undef_Addr:      .word     Undef_Handler
SWI_Addr:        .word     SWI_Handler
PAbt_Addr:       .word     PAbt_Handler
DAbt_Addr:       .word     DAbt_Handler
                 .word     0xB9206E28             @ Reserved Address
IRQ_Addr:        .word     IRQ_Handler
FIQ_Addr:        .word     FIQ_Handler



Gruß Microman

PS: Ist es jetzt doch nicht ein ein LPC2368 wie in den ersten Posting?

von Nik B. (nikbamert)


Lesenswert?

Hey Microman, danke dass du dich dem Problem nochmal annimst.
In dem anderen Thread habe ich erst am Montag geantwortet, da ich erst 
dann wieder an die Hardware konnte. Leider bist du nicht angemeldet 
sonst haette ich dir natuerlich eine PM geschickt :-)

Die 0x40 Bytes kopiere ich direkt bevor ich zur Applikation springe
1
  dst_ptr = (U32 *)0x40000000; 
2
  src_ptr = (U32 *)0x6000;
3
    
4
  for (j=0;j<(16);j++){dst_ptr[j] = src_ptr[j];}

Der Abschnitt im Startupcode der Applikation sieht bei mir aber etwas 
anders aus, ich habe mich schon gefragt woher dort die Adressen denn 
kommen sollen aber die betreffenden Konstanten nicht gefunden.

Der Code in dem Abschnitt ist unveraendert aus einem Projekt welches 
nach 0x0000 gelinkt wurde, kann gut sein dass hier der Fehler liegt. Ich 
muss allerdings auch gestehen, dass ich mit ARM-ASM nicht wirklich viel 
am Hut habe; Inwiefern muesste ich hier etwas anpassen? (bzw: wie kommst 
du auf die  0xB9206E28?)
1
Vectors         LDR     PC, Reset_Addr         
2
                LDR     PC, Undef_Addr
3
                LDR     PC, SWI_Addr
4
                LDR     PC, PAbt_Addr
5
                LDR     PC, DAbt_Addr
6
                NOP                            ; Reserved Vector 
7
;               LDR     PC, IRQ_Addr
8
                LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr
9
                LDR     PC, FIQ_Addr
10
11
Reset_Addr      DCD     Reset_Handler
12
Undef_Addr      DCD     Undef_Handler
13
SWI_Addr        DCD     SWI_Handler
14
PAbt_Addr       DCD     PAbt_Handler
15
DAbt_Addr       DCD     DAbt_Handler
16
                DCD     0                      ; Reserved Address 
17
IRQ_Addr        DCD     IRQ_Handler
18
FIQ_Addr        DCD     FIQ_Handler

LPC2366/68 ist je nach Hardwarerevision unterschiedlich, in der alten 
Version wurde noch mit dem 66er gearbeitet, mit welchem ich im Moment 
auch arbeite.

Gruss
Nik

von Microman (Gast)


Lesenswert?

Hallo Nik,

ich denke das Problem ist der Sprung zum VicVectAddr Register.

LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr

Wenn das Programm auf 0x0 gelinkt ist und der PC auf auf der Zeile 
steht, dann würde er den Inhalt von der Adresse 0x20-0x0120 = 0xFFFFFF00 
( an dieser Stelle ist das VicVectAddr-Register in dem die Sprungadresse 
der Interruptfunktion steht) in den PC laden und somit dahin springen.
Jetzt hast Du aber das Remapping eingeschaltet und der PC hat an dieser 
Stelle einen Offset von 0x40000000 ( ist jetzt ja im RAM) und die 
Berechnung und damit auch der Sprung, gehen vollkommen daneben. Eine 
Lösung ist der Umweg über den IRQ_Handler, falls dieser denn richtig 
implemetiert ist.

Vectors         LDR     PC, Reset_Addr
                LDR     PC, Undef_Addr
                LDR     PC, SWI_Addr
                LDR     PC, PAbt_Addr
                LDR     PC, DAbt_Addr
                NOP                            ; Reserved Vector
                LDR     PC, IRQ_Addr
;               LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr
                LDR     PC, FIQ_Addr

Reset_Addr      DCD     Reset_Handler
Undef_Addr      DCD     Undef_Handler
SWI_Addr        DCD     SWI_Handler
PAbt_Addr       DCD     PAbt_Handler
DAbt_Addr       DCD     DAbt_Handler
                DCD     0                      ; Reserved Address
IRQ_Addr        DCD     IRQ_Handler
FIQ_Addr        DCD     FIQ_Handler

So sollten dann die IRQ auch mit Remapping funktionieren. Einfach mal 
ausprobieren.

Gruß Microman

PS: Die 0xB9206E28 sind nur ein Platzhalter und ohne Bedeutung.

von Nik B. (nikbamert)


Lesenswert?

Achso so ist das, dankeschoen!
Ich habe dies soeben einmal ausprobiert, leider gibts immer noch 
aehnliche Anzeichen, teilweise schmiert er sogar no deutlich vor dem 
ersten Interrupt ab, dann aber an unterschiedlichen Stellen.

Ich vermute, dass es wohl auch noch was mit dem Stack zu tun hat. Dieser 
kannn angeblich nur im Supervisor mode neu initilisiert werden, aber 
dafuer
sorge ich ja, indem ich im Bootloader den Supervisor gar nicht erst 
verlasse, die App wird also noch im Supervisor mode aufgerufen.

Alle Beispiele fuer Bootloader, die ich finde, sind leider ziemlich 
unbrauchbar, da in der Applikation weder Interrupts noch gross etwas an 
Ram verwendet wird.

Hast du noch Ideen, wie ich das ganze immerhin anstaendig Debuggen 
koennte? Leider handelt es sich bei mir ja um ein zweiteilges Projekt, 
der uVision Debugger ist also ziemlich ratlos nachdem ich den Appsprung 
mache. Dort wuerde es aber erst so richtig interessant...

Gruss
Nik

von Nik B. (nikbamert)


Lesenswert?

Ich wollte es nun doch mit dem VicVect controller versuchen,
und habe daher die folgende Zeile(1) nach(2) modifiziert

(1)
LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr

(2)
LDR     PC, =0xFFFFFF00   ; Vector from VicVectAddr

Der Fehler bleibt bestehen, ich habe sogar noch ein neues Phaenomen;
printf spuckt mir nun teilweise den Inhalt innerhalb der 
Anfuehrungszeichen aus, sprich ich schribe printf("Dies ist eine Zahl 
%u", Zahl); dann kommt das auch genau so raus, ohne dass das %u ersetzt 
wuerde.

Was koennte das denn sein?

von Microman (Gast)


Lesenswert?

Hallo Nik,

werde Dir noch was zum debuggen mit Bootloader schreiben, zumindest so 
wie ich es umgesetzt habe, dauert aber noch bis zum WE. Poste doch noch 
mal den Code den Du für das Remapping verwendest, werde den dann mal mit 
dem von mir vergleichen.

Gruß Microman

von Nik B. (nikbamert)


Angehängte Dateien:

Lesenswert?

Hallo microman,

mein Remapping-code sieht folgendermassen aus:


Bootloader:
1
(Startup: entweder mit oder ohne usermode Switch, selbes ergebnis!)
2
3
U32 *src_ptr;
4
U32 *dst_ptr;
5
U32 j;
6
void (*appjump)(void);
7
8
src_ptr = (U32 *)0x6000; //Exeptionvects in app  
9
dst_ptr = (U32 *)0x40000000; //Ram
10
  
11
//Copy intvects to     
12
for (j=0;j<8;j++)
13
{dst_ptr[j] = src_ptr[j];}
14
      
15
//Set mapping to RAM
16
MEMMAP = 0x02;
17
18
appjump = (void (*)(void))0x6000;
19
appjump();

Den Startupcode der Anwendung habe ich angehaengt, die Makros "RAM_MODE" 
und "REMAP" sind gesetzt, es wird damit also dort auch nochmal MEMMAP 
auf 2 gesetzt.

Zusaetzlich habe ich die Stelle um die Exceptionvektoren noch einmal 
folgendermassen ueberarbeitet um dann doch zum VIC zu kommen (LDR geht 
so wie ichs oben gepostet habe ja nicht, da nur relativ nur ueber 12bit 
Adressraum gesprungen werden kann)
1
Vectors         LDR     PC, Reset_Addr         
2
                LDR     PC, Undef_Addr
3
                LDR     PC, SWI_Addr
4
                LDR     PC, PAbt_Addr
5
                LDR     PC, DAbt_Addr
6
                NOP                            ; Reserved Vector 
7
                LDR     PC, IRQ_Addr
8
;               LDR     PC, [PC, #-0x0120]     ; Vector from VicVectAddr
9
;               LDR     PC, =0xFFFFFF00
10
                LDR     PC, FIQ_Addr
11
12
Reset_Addr      DCD     Reset_Handler
13
Undef_Addr      DCD     Undef_Handler
14
SWI_Addr        DCD     SWI_Handler
15
PAbt_Addr       DCD     PAbt_Handler
16
DAbt_Addr       DCD     DAbt_Handler
17
                DCD     0                      ; Reserved Address 
18
IRQ_Addr        DCD     IRQ_Handler
19
FIQ_Addr        DCD     FIQ_Handler
20
Vic_Addr        DCD     0xFFFFFF00
21
22
              
23
Undef_Handler   B       Undef_Handler
24
SWI_Handler     B       SWI_Handler
25
PAbt_Handler    B       PAbt_Handler
26
DAbt_Handler    B       DAbt_Handler
27
;IRQ_Handler    B       IRQ_Handler
28
IRQ_Handler     LDR     R5, Vic_Addr
29
                LDR     PC, [R5]
30
FIQ_Handler     B       FIQ_Handler

Gruss
Nik

von Microman (Gast)


Lesenswert?

Hallo Nik,

mir ist bei deinem Code aufgefallen, daß Du nur 32 Byte kopierst. Du 
mußt aber 64 Byte kopieren. Erst die 32 Byte Exception-Vectoren und dann 
noch die 32 Byte der Sprungadressen. Deshalb werden auch 0x40 Byte 
"ge-remapped", damit ein Sprung überall in den Speicherraum möglich ist. 
Bitte ändere den Code doch wie folgt, und teste das Ergebnis.

//Copy intvects to
for (j=0;j<16;j++)
{dst_ptr[j] = src_ptr[j];}


Beim Debuggen habe ich ein Label mit folgendem Code in die Firmware 
eingebaut. Dieses Label wird direkt nach dem Flashen der Firmware, bei 
Dir auf 0x6000, angesprungen und augeführt, erst dann wird zur 
Reset-Handler gesprungen. Die Firmware ganz Du ganz normal debuggen, 
obwohl auf 0x0 noch ein Bootloader schlummert, der aber gar nicht 
aufgerufen wird beim Debuggen. Ausserdem stört Dich dieser Code nicht, 
denn die Firmware kann diesen Code gar nicht erreichen. Teste das doch 
mal aus.

.global Startup_Label
Startup_Label:
                .extern sys_remap_sectors_startup
                ldr     SP, =Stack_Top
                @ temporary stack at Stack_Top
                LDR     R0, =sys_remap_sectors_startup
                MOV     LR, PC
                BX      R0
                LDR     R0, =Reset_Handler
                BX      R0

.end

Gruß Microman

PS: Denke bitte daran, den Speicher von 0x40000000 bis 0x40000040 bei 
deiner Firmware als Reserved zu markieren; denn hier liegen ja deine 
"ge-remappten" Vectoren.

von Nik B. (nikbamert)


Lesenswert?

Hallo Microman,

danke dass du mich darauf hingewiesen hast-ich habe ganz uebersehen, 
dass ich nicht mehr 64 Bytes kopiere. Das habe ich im Zuge all der Tipps 
und Tricks, die im WWW aufstoebern konnte einmal ausprobiert und 
vergessen zurueck zu korrigieren. Leider bringt allerdings dies auch 
keine Aenderung.

Oben habe ich ja gepostet, inwiefern ich den VICvect nun anspringe,
hier ein Schnippsel daraus:
1
IRQ_Handler     LDR     R5, Vic_Addr
2
                LDR     PC, [R5]

Nun, damit startet meine Firmware noch, allerdings mit den selben 
Fehlern wie schon immer.
Aendere ich dies nun korrekterweise auf folgendes:
1
IRQ_Handler     LDR     R5, Vic_Addr
2
                MOV     PC, [R5]

dann startet gar nichts mehr. Weshalb? - Register in ein anderes 
Register geht mit LDR ja im Grunde nicht, MOV muesste dazu ja korrekt 
sein?

Ich denke der Fehler liegt schon um die Zeilen mit dem 
Vektorinterruptcontroller, aber mir gehen so langsam die Ideen aus, wie 
ich den wert aus 0xFFFFFF00 bei 0x6000 denn korrekt auslesen und 
anspringen koennte.

Das mit dem Debuggen werde ich gerne ausprobieren, danke!

Der 0x4000 0000 - 0x4000 0040 indem ich dem Keil mitteile er solle IRAM1 
erst ab 0x40000040 verwenden.
Gruss
Nik

von Nik B. (nikbamert)


Lesenswert?

Danke fuer deine Hilfe, ich habs nun endlich hingekriegt!
Was fuer mich voellig unverstaendlich ist, ist dass es fuer den vicVect 
dennoch folgende Zeile tut.

LDR     PC, [PC, #-0x0120]

Wie du mir ja dargestellt hast und mir nun auch einleuchtet, duerfte er 
diesen Bereich gar nicht erreichen, es funktioniert so aber auch von 
0x6000 aus.

Der Fehler lag bei den CCLK Einstellungen fuer die IAP Funktionen; Der 
Code wurde richtig ins Flash geladen, dafuer zickte er bei der 
Ausfuehrung dessen dann so richtig rum. (Oben genannte Phaenomene)


Nochmals Dankeschoen fuer deine Muehe :-)

Gruss
Nik

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.