Ich versuche gerade für den LPC1768 Multitasking zu programmiert und nun
habe ich folgendes Problem:
Ich habe zur Zeit zwei Tasks, eine die nur eine Variable inkrementiert
und eine Große, die einen Motor steuert und den Wert der Variable aus
der ersten Task auf dem Display ausgibt. So weit funktioniert alles
problemlos. Doch sobald ich die erste Task erweitere hängt die ganze
Software. Ich habe festgestellt, dass die Software dann hängt, wenn ich
eine lokale Variable verwende:
Funktionierende Funktion:
1
uint32_tidle_tick=0;
2
uint32_tcur_tick;
3
4
voididle(void){
5
6
while(1){
7
idle_tick++;
8
cur_tick=tick;
9
while((tick-cur_tick)<2000);
10
}
11
}
Nicht funktionierende Funktion:
1
uint32_tidle_tick=0;
2
3
voididle(void){
4
uint32_tcur_tick;
5
6
while(1){
7
idle_tick++;
8
cur_tick=tick;
9
while((tick-cur_tick)<2000);
10
}
11
}
Code zum Starten der ersten Task:
1
svc_handler_wrapper:
2
ldr r3, =current_task
3
ldr r1, [r3]
4
ldr r0, [r1]
5
ldmia r0!, {r4-r11}
6
msr psp, r0
7
orr r14, r14, #0x04
8
bx r14
Code zum Taskwechsel:
1
PendSV_Handler:
2
mrs r0, psp
3
ldr r3, =current_task
4
ldr r2, [r3]
5
stmdb r0!, {r4-r11}
6
str r0, [r2]
7
stmdb sp!, {r3, r14}
8
bl task_get_current
9
ldmia sp!, {r3, r14}
10
ldr r1, [r3]
11
ldr r0, [r1]
12
ldmia r0!, {r4-r11}
13
msr psp, r0
14
bx r14
Das die Funktion mit lokaler Variable nicht funktioniert kann meines
Erachtens nicht an der Stackgröße liegen, da ich der Funktion 256 Byte
als Stack zur Verfügung stelle.
Im Voraus schon einmal danke für die Hilfe.
sl
War auch nur ein Schuss ins Blaue, denn du hast ja vorsichtshalber fast
alles vom Quellcode weggelassen, was hier relevant ist.
Anders ausgedrückt: Fehler in Zeile 42.
Ok, dann liefere ich jetzt die anderen relevanten Funktionen noch nach.
Ich wollte zuerst nicht zu viel posten, um nicht gleich alle im Forum
abzuschrecken.
Resetfunktion:
1
stack_tidle_stack[256],main_stack[256];
2
3
voidResetHandler(void)
4
{
5
unsignedlong*pulSrc,*pulDest;
6
7
//
8
// Copy the data segment initializers from flash to SRAM in ROM mode
LPC_PWM1->MR0=100;// PMW base frequency = 5 MHz / 100 = 50 KHz
14
LPC_PWM1->MR1=50;// Match 1
15
LPC_PWM1->MCR=2;// reset TC on MR0
16
LPC_PWM1->PCR=(1<<9);// enable PWM1 outputs
17
LPC_PWM1->LER=3;// enable PWM0 - PWM6 match latch (reload)
18
LPC_PWM1->TCR=0x09;// enable PWM mode and start timer
19
20
GPIO1_SET(0);
21
GPIO1_CLR(1);
22
23
while(1){
24
dogm_clear();
25
dogm_set_cursor(0);
26
dogm_string(itoa(idle_tick,tmp_str,10));
27
GPIO1_SET(0);
28
GPIO1_CLR(1);
29
current_tick=tick;
30
while((tick-current_tick)<2000);
31
GPIO1_CLR(0);
32
current_tick=tick;
33
while((tick-current_tick)<1000);
34
GPIO1_SET(1);
35
current_tick=tick;
36
while((tick-current_tick)<2000);
37
GPIO1_SET(0);
38
current_tick=tick;
39
while((tick-current_tick)<1000);
40
}
41
42
return0;
43
}
Ich hoffe der Code ist einigermaßen verständlich. Leider sehen im Moment
sehen die einzelnen Codeabschnitte noch ziemlich zusammengewürfelt aus.
Jede Task für sich allein funktioniert. Deshalb denke ich, dass der
Fehler irgendwo im Taskwechsel liegt und dass sich das Problem nur dann
bemerkbar macht, wenn beide Tasks lokale Variablen verwenden, die auf
dem Stack abgelegt werden.
sl
@ sl (Gast)
>Ok, dann liefere ich jetzt die anderen relevanten Funktionen noch nach.>Ich wollte zuerst nicht zu viel posten, um nicht gleich alle im Forum>abzuschrecken.
Hast du aber. Lies mal was über Netiquette und poste demnächste
lange Quelltexte als Anhang.
Zu deinem eigentlichen Problem hilft dir ggf. der Artikel
Multitasking.
MFG
Falk
Jede Variable, die in mehr als einer Task verwendet wird, sollte
eigentlich volatile sein. So auch idle_tick. Kann dazu führen, dass in
der Hauptschleife immer der gleiche Wert angezeigt wird - hier aber
aufgrund der dogm Funktionen vermutlich nicht.
Das gilt an sich auch für current_task und next_task. Oftmals
funktioniert es auch ohne volatile und manche Experten (?) schaffen es,
dank etwas Glück ein Tasking-System komplett ohne volatile zu
fabrizieren, allerdings hängt man dann etwas davon ab, wie gross
Blickwinkel und Fähigkeiten des Compilers sind.
@ falk
Ok, die Netiquette hätte ich mir durchlesen sollen. Den Source habe ich
jetzt in einer kommentierten Version angehängt. Der Artikel zum
Multitasking hat mir leider nicht weitergeholfen.
@ A.K.
Die anderen Variablen müssen natürlich auch volatile sein, das ist so
definitive falsch, das Problem behebt es aber nicht.
Ich habe das Ganze jetzt nochmal getestet:
-Wenn ich nur eine Task laufen lasse, funktioniert alles problemlos.
-Wenn ich in beiden Tasks lokale Variablen verwende bleibt das Programm
stehen, eine Exception tritt allerdings keine auf. Der Prozessor bleibt
im Threadmode.
-Rufe ich in beiden Tasks Funktionen auf, kommt es zu einer
Hardfault-Exception.
-Tausche ich die beiden Tasks kommt es zu einer HardFault-Exception.
Ich kann mir das nur dadurch erklären, dass beim Starten der ersten Task
etwas mit dem Stack schiefgeht. Werden in einer Task nur Register
verwendet geht es problemlos. Werden aber in beiden Tasks Funktionen
aufgerufen, der Inhalt der Register also auf dem Stack
zwischengespeichert, oder lokale Variablen auf dem Stack allokiert,
kommt es zum Fehler. Also muss der Stack doch das Problem sein, oder?
Hab ich in der Funktion svc_handler_wrapper (system.asm) irgendeinen
Fehler übersehen?
Schon mal danke für die Hilfe.
mfg sl