Hallo beisammen,
ich habe mir grad ein Board gebastelt mit einem LPC2103 als Controller
und habe begonnen einige Code-Beispiele zusammenzubasteln, UART, EA-DOG,
Fast-I/O etc...
Fast I/O funktioniert schon super, EA-DOG auch schon (stelle ich
demnächst mal online), nur gibt es ein Problem, will man timing mit
Timer-Interrupts betreiben. Auch die Interrupts der UART-Schnittstelle
machen Probleme.
Es folgt ein kurzes Example, das ich zusammengebastelt habe um nicht
irrsinninge Codemengen einstellen zu müßen, welches die grundlegende
Problematik vermitteln sollte:
Meine Main.c:
1 | #include "lpc2103.h" // gechecked, laut Datenblatt okay!
|
2 | #include "main.h"
|
3 | #include <math.h>
|
4 | #include "/usr/local/arm/arm-elf/include/sys/string.h"
|
5 | #include "/usr/local/arm/arm-elf/include/sys/types.h"
|
6 |
|
7 | # compiled with arm-elf-gcc (GCC) 4.1.0
|
8 |
|
9 | int main(void)
|
10 | {
|
11 | unsigned int i;
|
12 |
|
13 | sysinit();
|
14 |
|
15 | // set-up interrupts
|
16 | MEMMAP = (1 << 0); // map interrupt vectors space into FLASH
|
17 | VICIntEnClr = 0xFFFFFFFF; // clear all interrupts
|
18 | VICIntSelect = 0x00000000; // clear all FIQ selections == alles ist trad. IRQ
|
19 | VICDefVectAddr = (unsigned long) reset; // point unvectored IRQs to reset() (aus startup)
|
20 |
|
21 | // Timer 2, siehe: http://www.keil.com/forum/docs/thread10347.asp
|
22 | T2PR = 0x00000005; //Load prescaler
|
23 | T2TCR = 0x00000002; //Reset counter and prescaler
|
24 | T2MCR = 0x00000003; //match reset the counter and generate an interrupt
|
25 | T2MR0 = 0x00000010; //cycle time
|
26 | T2TCR = 0x00000001; //enable timer
|
27 | VICVectAddr4 = (unsigned long)ISR; //Set the timer ISR vector address
|
28 | VICVectCntl4 = 0x0000003A; //Set channel control
|
29 | VICIntEnable |= 0x04000000; //Enable the TIMER2 interrupt
|
30 |
|
31 | // FIO
|
32 | FIODIR |= 1 << 4; // P0.4 is an output
|
33 | while( 1 )
|
34 | {
|
35 | i++;
|
36 | }
|
37 | }
|
38 |
|
39 | void __attribute__ ((interrupt("IRQ"))) ISR(void)
|
40 | {
|
41 | FIOCLR = 1 << 4;
|
42 | T2IR = 0x00000001; //Clear match 0 interrupt
|
43 | VICVectAddr = 0x00000000; //Dummy write to signal end of interrupt
|
44 | FIOSET = 1 << 4;
|
45 | }
|
46 |
|
47 | void sysinit(void)
|
48 | {
|
49 | // PLL Setup
|
50 | PLLCFG |= (1 << 0) | (1 << 5); // M=1 und P = 1, schon dekrementiert
|
51 | // das sollten 40 MHz Bustakt ergeben
|
52 |
|
53 | // PLL starten
|
54 | PLLCON |= (1 << 0);
|
55 | PLLFEED = 0xAA; // Make it happen. These two updates
|
56 | PLLFEED = 0x55; // MUST occur in sequence.
|
57 |
|
58 | // wait for settling PLL
|
59 | while (!(PLLSTAT & (1 << 10)))
|
60 | continue;
|
61 |
|
62 | // PLL starten und connectieren
|
63 | PLLCON = (1 << 1) | (1 << 0);
|
64 | PLLFEED = 0xAA; // Make it happen. These two updates
|
65 | PLLFEED = 0x55; // MUST occur in sequence.
|
66 |
|
67 | // Memory Acceleration
|
68 | MAMTIM = 3; // 3 cycles
|
69 | MAMCR = 2; // full acceleration
|
70 |
|
71 | // peripheral clock
|
72 | APBDIV = 1; // periph clock = processor clock
|
73 |
|
74 | // fast GPIO
|
75 | SCS = (1 << 0); //enable fast GPIO in System Control Setup
|
76 |
|
77 | }
|
Es wird nix großartiges betrieben, sysinit setzt die üblichen parameter
für die PLL etc.
Nachfolgend werden die Interrupts in den Flash-Bereich gebracht, IRQs
aktiviert und FIQ's deaktiviert, etc.
Danach wird laut einem KEIL-example Timer2 angeworfen, der in
regelmäßigen Intervallen den Handler aufrufen sollte.
Das tut er aber nicht!
Oszi: 20 MHz, Clock: 40 MHz
GCC 4.1.0
crt0.S und linker-Skript (ROM) habe ich angehängt, sind aus Beispielen
zusammenkopiert.
Meine Vermutung: Irgendetwas mit den startup-Skript stimmt nicht. Ich
kenne mich aber zu wenig aus. Vielleicht kann bitte mal jemand drüber
sehen, der sich damit besser auskennt.
Ürbigens: Das gleiche Problem mit den IRQ-SR habe ich auch mit dem UART,
etc... die Routine wird einfach nicht aufgerufen.
Vielleicht weiß ja jemand Rat!
Beste Grüße - Franz