haben Sie keine Ahnung, wo Sie stecken bleiben wir brauchen mehr Informationen, aber vielleicht ein kleines Skelett wird bestätigen, dass Sie zumindest diese wenigen Dinge tun. Hast du schon einmal einen Arm7 gemacht oder ist das das erste Mal, oder bist du in der Arm7/Arm-Welt versiert, aber kannst du die Interrupts einfach nicht zur Arbeit bringen?
starten.s
.globl _start
_start:
.globl _start
_start:
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
reset_handler: .word reset
undefined_handler: .word hang
swi_handler: .word hang
prefetch_handler: .word hang
data_handler: .word hang
unused_handler: .word hang
irq_handler: .word irq
fiq_handler: .word hang
reset:
;@ (PSR_IRQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD2
msr cpsr_c,r0
ldr sp,=0x40002000
;@ (PSR_FIQ_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD1
msr cpsr_c,r0
ldr sp,=0x40003000
;@ (PSR_SVC_MODE|PSR_FIQ_DIS|PSR_IRQ_DIS)
mov r0,#0xD3
msr cpsr_c,r0
ldr sp,=0x40004000
bl notmain
hang: b hang
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.globl dummy
dummy:
bx lr
.globl enable_irq
enable_irq:
mrs r0,cpsr
bic r0,r0,#0x80
msr cpsr_c,r0
bx lr
irq:
push {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
bl c_irq_handler
pop {r0,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
subs pc,lr,#4
ja das sind zu viele register ... nur brauchen die flüchtigen die compiler die anderen abdeckt.
notmain:
void c_irq_handler (void)
{
}
void notmain (void)
{
unsigned int ra;
for(ra=0;ra<100;ra++) dummy(ra);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
ram : ORIGIN = 0x40000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.bss : { *(.bss*) } > ram
}
denke ich nicht brauchen .bss
build
arm-none-eabi-as start.s -o start.o
arm-none-eabi-gcc -O2 -c notmain.c -o notmain.o
arm-none-eabi-ld -T flash.ld start.o notmain.o -o so.elf
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf -O binary so.bin
immer Ihre so.list untersuchen
sie haben eine interessante Art und Weise zu bestimmen, ob Sie einen Blitz dort haben, oder wenn sie in ihren Bootloader
Kriterium für gültigen Code-Dump sollte: Der reservierte ARM Interruptvektor Lage (0x0000 0014) enthalten sollte die 2er-Komplement der Check-Summe der restlichen Interrupt-Vektoren. Dies bewirkt, dass die Prüfsumme von allen Vektoren zusammen 0.
ich sein knapp über das noch tun, tun können, die von Hand oder haben ein Programm, kommen nach und tun es programmatisch.
Änderung es zu diesem
ldr pc,reset_handler
ldr pc,undefined_handler
ldr pc,swi_handler
ldr pc,prefetch_handler
ldr pc,data_handler
.word 0xb8a06f58 @ldr pc,unused_handler
ldr pc,irq_handler
ldr pc,fiq_handler
und das sollte gut funktionieren.
Wenn dies für elementare völlig nutzlos ist, dann lassen Sie mich wissen, wird diese Antwort löschen kein Problem.
notmain.c
void PUT32 (unsigned int, unsigned int);
unsigned int GET32 (unsigned int);
void enable_irq (void);
#define T0IR 0xE0004000
#define T0TCR 0xE0004004
#define T0PC 0xE0004010
#define T0MCR 0xE0004014
#define T0TC 0xE0004008
#define T0MCR0 0xE0004018
void c_irq_handler (void)
{
PUT32(T0IR,1);
}
void notmain (void)
{
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0TCR,1);
while(1)
{
if(GET32(T0IR&1)) break;
}
PUT32(T0IR,1);
PUT32(T0TCR,2);
PUT32(T0TCR,0);
PUT32(T0TC,0);
PUT32(T0MCR0,0x100000);
PUT32(T0MCR,0x1); //3);
PUT32(T0IR,1);
enable_irq();
PUT32(T0TCR,1);
while(1) continue;
}
dies nur knallte von dem manuellen nur knapp sein Ziel überprüfen, ob es eine Uhr für den Timer aktivieren war usw. Persönlich habe ich den gpio bis ersten, blinkt eine mit einem großen Zähler geführt Schleife
for(ra=0;ra<0x20000;ra++) dummy(ra);
dann einen Timer in einem Abfragemodus verwenden, bis zu blinken basierend auf der Zeit von dieser kann herausfinden, die Taktgeschwindigkeit, die in die uart führt, erhält die uart, (es nur freilaufende Einstieg) , haben eine triviale Routine zum Drucken von Daten
void hexstring (unsigned int d)
{
//unsigned int ra;
unsigned int rb;
unsigned int rc;
rb=32;
while(1)
{
rb-=4;
rc=(d>>rb)&0xF;
if(rc>9) rc+=0x37; else rc+=0x30;
uart_send(rc);
if(rb==0) break;
}
uart_send(0x0D);
uart_send(0x0A);
}
Oktal ist es noch einfacher, aber der Mensch ist es schwer, in Oktal zu denken ...
schließlich die Interrupt-Zeug, Code wie oben nehmen und ich würde die verschiedenen Register in den Timer abzufragen und drucken, würde sehen, ob dieses Interrupt-Register in einem Abfragemodus zuerst feuert (zweite, dritte, vierte ... ohne Interrupts zum Prozessor zu aktivieren (tun Sie das für eine Weile nicht).
Sobald ich es auf der peripheren Ebene sehen kann, die einige nicht so funktionieren, aber davon ausgehen, dass dies tut.Dann in diesem Fall gibt es ein VIC, und ich nehme an, das Register
VICRawIntr 0xFFFFF008
auch geltend gemacht werden soll, wenn das Timer-Interrupt aktiviert und gebrannt hat. Bestätigen Sie, dass es ist (Bit 4 erscheint) Bestätigen Sie, dass es verschwindet, wenn der Interrupt im Peripheriegerät gelöscht wird.
VICIntSelect wird auf Null zurückgesetzt, was irq ist, das ist es, was wir nicht brauchen, um es für jetzt zu berühren.
Ich gehe davon aus Bit 4 in VICIntEnable gesetzt
Sie dann die Abfrage, was erneut zu drucken, um zu sehen, was los ist.
Jetzt würde ich erwarten, dass der Interrupt in VICIRQStatus angezeigt wird (noch vollständig Abfragen die IRQ zum Prozessor noch nicht aktivieren) und weggehen, wenn das Peripheriegerät löscht, oder herausfinden, wie es zu löschen, wenn der periphere Interrupt gelöscht wird macht es nicht so weit.
JETZT ist es Zeit, die IRQ an den Prozessor zu aktivieren, und ich persönlich würde ein Byte in die uart schieben, um es herausspringen zu sehen. oder eine LED einschalten oder so.
In der Theorie löschen wir einfach die Peripherie und kehren zurück, um sicher zur Anwendung zurückzukehren.
Ich folge der gleichen Prozedur, egal, welcher Prozessor es MCU oder voller Größe ist, etc. Interrupts können Albträume sein und je mehr Code Sie schreiben, ohne zu testen, desto wahrscheinlicher zu scheitern. manchmal ist eine Zeile Code pro Test erforderlich. YMMV.
wieder, wenn dies völlig nutzlos ist, sorry, wird gelöscht. Ich glaube, ich habe eine/einige 2148, aber keine 2138, und ich werde keine bestellen, nur um Arbeitscode zu schreiben/zu testen. Seit dieser ARMV7TDMI war er arm und wurde in den gegenwärtigen Armvs populär, die viel schmerzhafter sind. die pi-zero und solche sind ziemlich lustig, wie sie alte Schule sind wie dieser arm7 ...
Ich denke, der Timer wäre der leichtere, um einen echten Interrupt von zu bekommen. ein anderer könnte ein gpio Pin sein, obwohl ich denke, das ist mehr Arbeit, würde aber einen Jumper zwischen den Pins binden, einen Ausgang zum anderen einen Eingang mit Interrupt Flankendetektion machen, wenn dieser Chip den Ausgang gpio verwendet, um den Zustand des Eingangs zu ändern eine saubere Art und Weise, und gehen Sie durch den gesamten Abrufprozess der Beobachtung des Interrupts treffen jede Schicht der Reihe nach und bestätigen Sie, dass Sie den Interrupt jedes Mal auf jeder Schicht entfernen können. dann knalle an den Rand des Kerns, und dann lass es schließlich in den Kern.
bieten ein minimales Programm, das nicht funktioniert ... –
nichts falsch mit Polling so lange wie Sie Ihr Timing treffen können, viel einfacher zu schreiben und zu debuggen, nur unterbrechen, wenn Sie unbedingt müssen. –
Ich/wir haben sehr viel Erfahrung mit Arm und anderen Muskelgruppen. Ich schätze, Ihre Beispiele sind relativ groß und um Ihre Füße nass zu machen, brauchen Sie das nicht ... –