Hi
ich bin ARM-Neuling und hab so meine Probleme.
ich will auf einem LPC2378 den CAN über interrupt laufen lassen, die
Beiträge hier im Forum haben mir leider noch nicht weiterhelfen können.
Meine Initialisierung sieht wie folgt aus :
.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode*/
17
18
.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */
19
.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */
20
21
[....]
22
23
/* Setup a stack for each mode - note that this only sets up a usable stack for User mode. Also each mode is setup with interrupts initially disabled. */
Problem ist nun: wenn mein Interrupt kommt bleibt der µC stehen
die Interrupt-Routine wird nicht ausgeführt.
Auf VICVectAddr23 steht 0x01B0, genau an dieser Speicheradresse befindet
sich laut Mapfile die Routine.
ich denke nun das ich mit den Bit's im CPSR irgend was falsch mache.
und noch eine Frage: wenn ein Interrupt am ARM anleigt wechselt er dann
in den IRQ-Mode? und such sich die entsprechende Adresse der
Interruproutien selber aus dem register?
Sollte der ARM lieber in einem anderem Modus laufen? momentan ist der
System mode eingestellt.
hoffe auf eure Hilfe ich bin am verzweifeln!!!
Hallo,
poste doch mal dein komplettes Startupfile, damit man sehen kann wie es
bei einem IRQ darin abläuft und ob die Adresse auch aus dem VICVectAddr
abgeholt und angesprungen wird. Es ist wichtig was an der Stelle der
IRQ-Exception steht.
Gruß Microman
//ldr PC, [PC,#-0xFF0] /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */
40
ldr PC, [PC, #-0x0120] // Vector from VicVectAddr
41
ldr PC, FIQ_Addr
42
43
Reset_Addr: .word Reset_Handler /* defined in this module below */
44
Undef_Addr: .word UNDEF_Routine /* defined in main.c */
45
SWI_Addr: .word SWI_Routine /* defined in main.c */
46
PAbt_Addr: .word UNDEF_Routine /* defined in main.c */
47
DAbt_Addr: .word UNDEF_Routine /* defined in main.c */
48
IRQ_Addr: .word IRQ_Routine /* defined in main.c */
49
FIQ_Addr: .word FIQ_Routine /* defined in main.c */
50
.word 0 /* rounds the vectors and ISR addresses to 64 bytes total */
51
52
# Reset Handler
53
54
Reset_Handler:
55
56
.extern TargetResetInit
57
ldr SP, =_stack_end @ temporary stack at Stack_Top
58
LDR R0, =TargetResetInit
59
MOV LR, PC
60
BX R0
61
62
/* Setup a stack for each mode - note that this only sets up a usable stack
63
for User mode. Also each mode is setup with interrupts initially disabled. */
64
65
66
ldr r0, =_stack_end
67
//Enter Undefined Instruction Mode and set its Stack Pointer
68
msr CPSR_c, #MODE_UND|I_BIT|F_BIT
69
mov sp, r0
70
sub r0, r0, #UND_STACK_SIZE
71
72
//Enter Abort Mode and set its Stack Pointer
73
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT
74
mov sp, r0
75
sub r0, r0, #ABT_STACK_SIZE
76
77
//Enter FIQ Mode and set its Stack Pointer
78
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT
79
mov sp, r0
80
sub r0, r0, #FIQ_STACK_SIZE
81
82
//Enter IRQ Mode and set its Stack Pointer
83
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT
84
mov sp, r0
85
sub r0, r0, #IRQ_STACK_SIZE
86
87
//Enter Supervisor Mode and set its Stack Pointer
88
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT
89
mov sp, r0
90
SUB sl, sp, #SVC_STACK_SIZE
91
//sub r0, r0, #SVC_STACK_SIZE
92
93
//Enter User Mode and set its Stack Pointer
94
// msr CPSR_c, #MODE_SYS|I_BIT|F_BIT
95
// mov sp, r0
96
97
98
// copy .data section (Copy from ROM to RAM)
99
ldr R1, =_etext
100
ldr R2, =_data
101
ldr R3, =_edata
102
LoopRel: cmp R2, R3
103
ldrlo R0, [R1], #4
104
strlo R0, [R2], #4
105
blo LoopRel
106
107
// Clear .bss section (Zero init)
108
mov R0, #0
109
ldr R1, =_bss_start
110
ldr R2, =_bss_end
111
LoopZI: cmp R1, R2
112
strlo R0, [R1], #4
113
blo LoopZI
114
115
/* Enter the C code */
116
b main
117
.endfunc
118
.end
Die I-Bit’s lasen ich damit es keine Probleme bei der Initialisierung
gibt. In meiner Main-Funktion enable ich dann die Interrupts über
Assembler:
1
#define IRQ_MASK 0x00000080
2
staticinlineunsignedasm_get_cpsr(void)
3
{
4
unsignedlongretval;
5
asmvolatile(" mrs %0, cpsr":"=r"(retval):/* no inputs */);
6
returnretval;
7
}
8
staticinlinevoidasm_set_cpsr(unsignedval)
9
{
10
asmvolatile(" msr cpsr, %0":/* no outputs */:"r"(val));
11
}
12
unsignedenableIRQ(void)
13
{
14
unsigned_cpsr;
15
16
_cpsr=asm_get_cpsr();
17
asm_set_cpsr(_cpsr&~IRQ_MASK);
18
return_cpsr;
19
}
Der Interrupt am ARM-Kern bewirkt auch das er zum richtigen Exception
Vector an Stelle 0x0018 springt, also zu der Zeile:
"ldr PC, [PC, #-0x0120] "ab hier denk ich läuft es schief.
Ziel ist ja dem Kern die Adresse der Interrupt-Routine mitzuteilen die
im VicVectAddr (0xFFFFFF00) steht. Die Aktion [PC, #-0x0120] springt
aber meiner Meinung falsch oder?
PC ist an dieser Stelle 0x18(befehlsanfang)+0x02 also 0x20
0x20-0x0120 ist bei mir 0xFFFFFEFF müsste man nicht 0x011F abziehen?
0x20-0x011F = 0xFFFFFF00
PS:
meine Interrupt-Routine habe ich so deklariert:
Zusatz:
laut Disassembly versteht der gcc Assambler anscheinend die Zeile
PC, [PC, #-0x0120] nicht! Allerdingst macht mein Debugger auch Blödsinn
wenn er asm-befegle bekommt
@Steffen H.:
Hab mir mal das UM zum LPC2378 geladen. Seltsam, bei NXP kann ich es
nicht herunter laden, sondern bei Keil.
VICAddress ist 0xFFFF FF00. Da im ARM-Mode, muß die Adresse von
0x18+8=0x20 aus um 0x120 zurück gerechnet werden.
Der Befehl ldr PC, [PC, #-0x0120] spricht generell einen 4k Addressraum
an, sieht damit korrekt aus.
Ich hoffe, du hast generell aber das richtige Startup-File, und nicht zu
viel darin manipuliert (weil da auch die deaktivierte Zeile eines
anderen Controllers mit anderem VIC-Vektor drin ist).
War da nicht noch was mit dem Default-Vektor???
wie meinst du das mit 0x18+8=0x20?
steht die 8 für 0x08 also für 8 Byte?
Wie du sagts sieht alles korrekt aus, aber wenn der µC in den IRQ-mode
geht springt er noch richtig zum Exception Vector aber von da aus macht
er nur noch Mist.
Weis auch nicht wie mir ein Default-Vektor weiterhelfen könnt.
@Steffen H.:
>wie meinst du das mit 0x18+8=0x20?>steht die 8 für 0x08 also für 8 Byte?
Ja, das scheint auch richtig so.
>Wie du sagts sieht alles korrekt aus, aber wenn der µC in den>IRQ-mode geht springt er noch richtig zum Exception Vector aber>von da aus macht er nur noch Mist.
An dieser Stelle soll das Register PC mit dem Inhalt der VICAddress
geladen werden. In deinem Fall sollte da der Inhalt von VICVectAddr23
(CAN_Handler) drin stehen.
Hat schon jemals ein anderer IRQ mal funktioniert?
>Weis auch nicht wie mir ein Default-Vektor weiterhelfen könnt.
OK, habs schon gesehen, im LPC23xx gibt es wohl keinen nicht
vektorisierten IRQ. Hat sich damit erledigt.
Ganz oben fand ich noch:
>VICVectCntl23 = 0x01;
Ist das so in Ordnung?
Hast du das richtige Registerfile (z.B. LPC2378.h) eingebunden?
Nicht, das die Registeradressen total nicht stimmen!
Im User Manual LPC2378 fand ich kein Register VICVectCntl23 !