Hallo Zusammen, bin gerade völlig mit den Nerven runter. Habe schon den ganzen Tag versucht einen einfachen Timerinterrupt zu erleben. Ich verwende Yagarto mit Eclipse usw. Der Controller ist ein LPC2148. Habe den Timer konfiguriert: TIMER0_MCR = 0x0003; TIMER0_MR0 = 0x3E8; TIMER0_TCR = 1; Das VIC-Zeugs ebenfalls: VICVectCntl0=0x20|4; VICVectAddr0=(unsigned long )timer0; VICIntEnable = 0x00000010; Meine Interruptroutine schaut so aus: void timer0(void) { TIMER0_IR=1; timercounter++; VICVectAddr=0; } Der Prototyp so: void timer0(void) _attribute_ ((interrupt("IRQ"))); Vielleicht hat von Euch ja jemand noch mehr aktive Zellen um den Fehler zu finden. Kann es sein, dass es so eine Art Global Interrupt Enable gibt? Wenn ja, wie rufe ich es auf? Viele Grüße Jansus
Jansus wrote: >... > Kann es sein, dass es so eine Art Global Interrupt Enable gibt? >... Ja, gibt es. Am einfachsten beim Startup dafür sorgen, dass I_BIT und F_BIT im CPSR des Modus, von dem aus main() aufgerufen wird, nicht gesetzt sind. Wie im Detail, kann man erst schreiben, wenn Startup-Code gezeigt wird. Irgendwo im Startup Assembler-Code werden die Stack-Pointer der verschiedenen Modi gesetzt. In der letzten Zeile mit der Form msr CPSR_c... schauen, ob ein |I_BIT|F_BIT am Ende steht (oder |0x80|0x40). Wenn ja, löschen (denn I_BIT gesetzt heisst IRQ-Exceptions aus). Ansonsten, falls Code im System-Mode ausgeführt wird (üblich bei "kleinen" ARM), kann man auch zur Laufzeit de-/aktivieren. In der Art:
1 | #define IRQ_MASK 0x00000080
|
2 | |
3 | static inline unsigned long get_cpsr(void) |
4 | {
|
5 | unsigned long retval; |
6 | asm volatile ("mrs %0, cpsr" : "=r" (retval) : /* no inputs */ ); |
7 | return retval; |
8 | }
|
9 | |
10 | static inline void set_cpsr(unsigned long val) |
11 | {
|
12 | asm volatile ("msr cpsr, %0" : /* no outputs */ : "r" (val) ); |
13 | }
|
14 | |
15 | void enableIRQ(void) |
16 | {
|
17 | unsigned long cpsr; |
18 | |
19 | cpsr = get_cpsr(); |
20 | set_cpsr(cpsr & ~IRQ_MASK); // clear I_BIT in CPSR |
21 | }
|
Timer-init habe ich jetzt nicht genau nachvollzogen, ist immer etwas mühsam mit Hex-Zahlen "Wüsten". Ansonsten gibt es noch ein paar potentielle Fallen: - _attribute_ ((interrupt("IRQ"))) funktioniert nicht in allen "Lebenslagen" bein arm GCC - IRQ-Exceptions-Vector muss PC aus der Vic-Addresse laden, falls kein Assembler-Wrapper genutzt wird. Im Startup sollte bei LPC2000 (<2300) am siebten Vektor sowas stehen: ldr pc,[pc,#-0xFF0] Martin Thomas
Hallo, vielen Dank für die schnelle Antwort! Habe inzwischen rausgefunden dass es wohl unterschiedliche Startupcodes gibt. Mal mit Interrupt-Fähigkeit, mal ohne. Da meiner recht kurz ausfällt, befürchte ich, dass ich den ohne Interruptfunktionalität erwischt habe. Leider bin ich ein absoluter Newbie was die ARMs angeht... Wie kann ich die oben genannten Funktionen verwenden? Wenn ich sie mir einfach in den Code reinkopiere, endet das im Absturz... Ich fände es schon etwas praktischer, wenn ich Interrupts im laufenden Programm de- bzw. aktivieren könnte. Schonmal herzlichen Dank im Voraus!!! Hier mal mein Startup-Code /* ************************************************************************ *************************************** crt.s STARTUP ASSEMBLY CODE ----------------------- Module includes the interrupt vectors and start-up code. ************************************************************************ *************************************** */ /* Stack Sizes */ .set UND_STACK_SIZE, 0x00000004 /* stack for "undefined instruction" interrupts is 4 bytes */ .set ABT_STACK_SIZE, 0x00000004 /* stack for "abort" interrupts is 4 bytes */ .set FIQ_STACK_SIZE, 0x00000004 /* stack for "FIQ" interrupts is 4 bytes */ .set IRQ_STACK_SIZE, 0X00000004 /* stack for "IRQ" normal interrupts is 4 bytes */ .set SVC_STACK_SIZE, 0x00000004 /* stack for "SVC" supervisor mode is 4 bytes */ /* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */ .set MODE_USR, 0x10 /* Normal User Mode */ .set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */ .set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */ .set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */ .set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */ .set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */ .set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */ .set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */ .set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */ .text .arm .global Reset_Handler .global _startup .func _startup _startup: # Exception Vectors _vectors: ldr PC, Reset_Addr ldr PC, Undef_Addr ldr PC, SWI_Addr ldr PC, PAbt_Addr ldr PC, DAbt_Addr nop /* Reserved Vector (holds Philips ISP checksum) */ ldr PC, [PC,#-0xFF0] /* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin */ ldr PC, FIQ_Addr Reset_Addr: .word Reset_Handler /* defined in this module below */ Undef_Addr: .word UNDEF_Routine /* defined in main.c */ SWI_Addr: .word SWI_Routine /* defined in main.c */ PAbt_Addr: .word UNDEF_Routine /* defined in main.c */ DAbt_Addr: .word UNDEF_Routine /* defined in main.c */ IRQ_Addr: .word IRQ_Routine /* defined in main.c */ FIQ_Addr: .word FIQ_Routine /* defined in main.c */ .word 0 /* rounds the vectors and ISR addresses to 64 bytes total */ # Reset Handler Reset_Handler: /* 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. */ ldr r0, =_stack_end msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */ mov sp, r0 sub r0, r0, #UND_STACK_SIZE msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */ mov sp, r0 sub r0, r0, #ABT_STACK_SIZE msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */ mov sp, r0 sub r0, r0, #FIQ_STACK_SIZE msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */ mov sp, r0 sub r0, r0, #IRQ_STACK_SIZE msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */ mov sp, r0 sub r0, r0, #SVC_STACK_SIZE msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ mov sp, r0 /* copy .data section (Copy from ROM to RAM) */ ldr R1, =_etext ldr R2, =_data ldr R3, =_edata 1: cmp R2, R3 ldrlo R0, [R1], #4 strlo R0, [R2], #4 blo 1b /* Clear .bss section (Zero init) */ mov R0, #0 ldr R1, =_bss_start ldr R2, =_bss_end 2: cmp R1, R2 strlo R0, [R1], #4 blo 2b /* Enter the C code */ b main .endfunc .end
Ich blicke einfach nicht durch! Gibt's nicht vielleicht irgendwo eine Art Tutorial in dem Startup-Codes erklärt werden? Zurück zu dem, den ich benutze. Was muss ich tun, um den gewünschten Mode einzuschalten? Und muss ich aus den 0x80 0x00 machen, um Interrupts generell zu aktivieren? Was ist eigentlich der Unterschied zwischen User und Systemmode? ???
So, habe in einem Tutorial von Jim Lynch die Files VIClowlevel.c und .h gefunden. Bin sie durchgegangen und kann sie glücklicherweise nachvollziehen. Passt ja auch sehr zu der Antwort von Martin Thomas. Habe die Dateien jetzt mal in mein Projekt eingebunden. Compilieren und debuggen funktioniert. Allerdings bleibt der µC in "asm_set_cpsr" hängen, bzw. führt die Zeile "asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );" nicht aus. Hat jemand eine Idee oder einen Tipp für mich?
Hi, ich hatte auch mal das gleiche Problem, also dass er diesen Befehle nicht kompiliert bzw. nicht ausführt ( Im Dissambly war er wegoptimiert worden.. ) musste dann leider für das Setzen der Interruptflags 2 Assembler Funktionen schreiben. Das hat dann eigentlich problemlos ( dank freundlicher Hilfe hier im Forum ) funktioniert. Thread: Beitrag "ARM Nested Interrupts mit Keil µVision mit RealView?"
Danke für die Antwort! Leider weiß ich mit Assembler nicht so viel anzufangen. Aber es war schon die Datei Nested_IRQ.s gemeint, oder? Was muss ich mit nested_irq_enable anstellen, damit es klappt? Ist das dann ein Ersatz für "asm volatile (" msr cpsr, %0" : /* no outputs */ : "r" (val) );" oder funktioniert meine obige Zeile dann erst?
Was mich etwas wundert: Das get_cpsr funktioniert ja, nur das set_cpsr nicht.
Im gezeigten Startup-Script wird main() im System-Mode mit deaktivierten IRQ- und FIQ-Exceptions ausgeführt:
1 | ... |
2 | msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */ |
3 | ... |
(der Kommentar irreführend) Hatte bereits weiter oben geschrieben, dass das I_BIT nicht gesetzt sein darf, um IRQ-Exceptions zu aktivieren. Also testweise ändern in:
1 | ... |
2 | msr CPSR_c, #MODE_SYS /* I_BIT cleared -> IRQ-Exception enabled, same for FIQ */ |
3 | ... |
inline-assembler "Geschichte" erstmal weglassen, kann man später immer noch nach schauen, wenn die eigentliche Interrupt-Verarbeitung funktioniert. Martin Thomas
Also ich hab's mal getestet. Einziger Effekt ist, dass mir alles abschmiert sobald ich den Timer aktivieren will (TIMER0_TCR = 0x1;).
Obwohl "alles abschmiert" erstmal ein Fortschritt, zumindest passiert jetzt etwas und dies wahrscheinlich dann, wenn der Interrupt auslöst. - VIC vor Aktivierung des Timer-Interrupts (TCR) eingestellt? Mglw. läuft der Interrupt noch ins Leere (Timer Match-Interrupt "feuert" da schon aktiviert aber VIC noch nicht entsprechend eingerichtet). IRQ-Exceptions sind ja bereits vom Startup global freigegben. Diese Reihenfolge mal ausprobieren: (1) MCR, MRO (init timer) (2) "VIC Zeugs" (configure VIC for Timer) (3) TCR (enable timer) - Default Interrupt Handler eingerichtet (Function auf die VICDefVectAddr zeigt)? Wird dieser aufgerufen? Default-Handler sollte man bei LPC2000 mit VIC190 (z. Zt. die <2300) immer einrichten, hilft nicht nur bei "spurious interrupts" sondern auch bei der Suche nach Fehlern in der VIC-Konfiguration. Martin Thomas
ups, sorry: statt "...Aktivierung des Timer-Interrupts..." "Aktivierung des Timers"
Die Reihenfolge habe ich richtig. Erst VIC dann Timer. Aktiviere den Timer auch erst kurz vor meiner Endlosschleife. VICDefVectAddr habe ich überhaupt nicht verwendet. Ich dachte "VICVectAddr0=(unsigned long )timer0;" würde alles managen? Wie verwende ich VICDefVectAddr korrekt? Weise ich dem eine andere Interrupt-Routine zu? Übrigens vielen, vielen Dank für die Tipps!
Ich habe inzwischen einen anderen Startup-Code und ein anderes Makefile verwendet. Habe meinen C-Code "integriert" und wer sagt's, Eclipse kompiliert und debuggt. Jedenfalls weiß ich jetzt was passiert. Wenn mal wieder alles abschmiert, steht im Disassembler "0x400000e0 <IRQHandler>: b 0x400000e0 <IRQHandler>". Der Interrupt löst aus, aber ich lande nicht in meiner Routine. Nur dummerweise weiß ich hier nicht weiter... Habe Makefile und Startup mal angehängt (wenn's klappt)
Okay, ich hab's! Muss im Startup statt IRQHandler halt meine Routine reinschreiben. Aber wie schaut's dann aus, wenn ich mehrere IRQ-Interrupts managen möchte?
Da habe ich schon wieder was dazu gelernt. Ich muss wohl einen IRQHandler selbst basteln und im Startup integrieren. Heißt das ich muss: 1. Register retten - aber welche? 2. Herausfinden wer oder was den Interrupt ausgelöst hat und dann in die entsprechende Routine springen - aber wie? 3. Register wieder zurückschreiben und Programm weiterlaufen lassen Stimmt das soweit? Hat das vielleicht schonmal jemand gemacht?
Wenn du in C programmierst, was ich annehme, sollte eigentlich der Compiler alle Register sichern. Was du per Hand retten musst ist das Linkregister. Es sei denn dir reicht es, dass mehrere Interrupts auftreten können, aber keine Priorisierung stattfindet. Für eine Priorisierung brauchst du Nested Interrupts ( die 2 Assembler Funktionen von vorher retten hier das Linkregister und "enablen" wieder alle Interrupts ). Das Linkregister musst du retten, da es für den IRQ Modus nur eines gibt und bei einem weiterem Interrupt wäre nun deine Rücksprungadresse verloren und du würdest im Nirgendwo landen, wenn du die ISR verlässt. Damit diese Priorisierung möglich ist, musst du im Startup folgendes ändern: _vectors: ldr pc, ResetAddr /* Reset */ ldr pc, UndefAddr /* Undefined instruction */ ldr pc, SWIAddr /* Software interrupt */ ldr pc, PAbortAddr /* Prefetch abort */ ldr pc, DAbortAddr /* Data abort */ ldr pc, ReservedAddr /* Reserved */ ldr pc, IRQAddr /* IRQ interrupt */ ldr pc, FIQAddr /* FIQ interrupt */ in _vectors: ldr pc, ResetAddr /* Reset */ ldr pc, UndefAddr /* Undefined instruction */ ldr pc, SWIAddr /* Software interrupt */ ldr pc, PAbortAddr /* Prefetch abort */ ldr pc, DAbortAddr /* Data abort */ LDR pc, [pc, #-0x0FF0] /* Vector from VicVectAddr */ ldr pc, FIQAddr /* FIQ interrupt */ ich hoffe, dass ich nichts übersehen habe.
Lasst die Sache mit nested Interrupts vorerst bleiben. Das ist was für Fortgeschrittene. Bleib bei einfachen Interrupts ohne IRQ-Handler in Assembler. Der Befehl ldr PC, [PC,#-0xFF0] an der Stelle vom IRQ-Einsprung war schon also richtig. Da wird der Vektor von VIC geholt und ein eigener Assembler IRQ-Handler ist überflüssig. Kleiner Nachteil: Ein sehr versionsresistenter GCC-Bug kann in Einzelfällen zu einem fehlerhaften IRQ-Handler führen. Das Risiko solltest du vorerst eingehen, und ggf. den vom Compiler erzeugten Code überprüfen. IIRC wird manchmal bei der Handhabung der Return-Adresse zweimal 4 abgezogen, einmal vorneweg, einmal hinten.
Vielen Dank! Ich habe die Zeile ausgetauscht und unten wieder IRQHandler anstatt meiner Routine eingesetzt. Leider passiert jetzt wieder garnichts. Meine Endlosschleife wird ausgeführt, aber von Interrupts keine Spur. Muss ich nicht irgendwie die Zuordnung von dem Interrupt zu dem IRQHandler herstellen? Priorisierung möchte ich schon, aber ich bin erstmal schon unheimlich glücklich wenn ich zwei Interrupts (beide IRQ, aber unterschiedliche Quellen) hinbekomme.
Der Disassembler sagt mir jetzt, dass ich im FIQHandler gelandet bin...
Du musst den VIC programmieren. Sonst geht garnichts. Aber das tust du schon (ob richtig habe jetzt ich nicht kontrolliert). Zudem wird in den Startups üblicherweise und richtigerweise der Interrupt noch nicht freigegeben. Das sollte nach der Basisinitialisierung im Programm erfolgen. Dazu siehe die Funktionen von Martin Thomas oben. Ob der Interrupt überhaupt ausgelöst wird und bei VIC ankommt, kannst du testhalber in der Schleife per Abfrage des Interrupt-Flag Registers vom VIC rausfinden. Im oben gezeigten Startup ist der IRQ-Stack zu klein. Sieh da lieber mal 256 Bytes vor (dein Handler braucht zwar weniger, aber das wird sicher mal mehr). Wenn der Controller bei CPSR auf die Nase fällt, dann möglicherweise weil er genau dann einen Interrupt verpasst bekommt und stecken bleibt. Für's Debugging per JTAG ist bei LPC2000ern hilfreich, wenn im Startup-Code als erstes eine mächtige Zählschleife sitzt, die die ersten paarhundert Millisekunden abläuft, bis der Debugger die CPU nach dem Reset eingefangen hat. Das ist ein Konstruktionsfehler der LPCs: JTAG kann den Prozessor nicht sofort aus Reset einfangen, sondern der läuft unkontrolliert los und irgendwann später kriegt das JTAG ihn zu fassen. Wenn da die Initialisierung schon durch ist, gibt's allerlei unlustige Effekte.
Ach ja: Beim LPC2138 ist vor dem ersten RAM-Zugriff eine spezielle Initialierung erforderlich. Kann sein, dass der LPC2148 das auch benötigt => Errata Sheet. Siehe irgendwelchen Startup-Codes im Netz, in manchen wird sich das sicher finden lassen.
Bin aktuell am zweiten Startup dran, da ich mit dem Skript wenigstens einen Interrupt erleben konnte. Aber auch nur wenn ich unten meine Routine unter IRQHandler eingetragen hatte und nicht die Zeile "ldr pc, [pc, #-0x0FF0] /* Vector from VicVectAddr */" sondern "ldr pc, IRQAddr" drinstehen hatte. Wegen der Zählschleife. Sind dafür die paar nops gedacht? Ist das überhaupt genug? /* * Some defines for the program status registers */ ARM_MODE_USER = 0x10 /* Normal User Mode */ ARM_MODE_FIQ = 0x11 /* FIQ Fast Interrupts Mode */ ARM_MODE_IRQ = 0x12 /* IRQ Standard Interrupts Mode */ ARM_MODE_SVC = 0x13 /* Supervisor Interrupts Mode */ ARM_MODE_ABORT = 0x17 /* Abort Processing memory Faults Mode */ ARM_MODE_UNDEF = 0x1B /* Undefined Instructions Mode */ ARM_MODE_SYS = 0x1F /* System Running in Priviledged Operating Mode */ ARM_MODE_MASK = 0x1F I_BIT = 0x80 /* disable IRQ when I bit is set */ F_BIT = 0x40 /* disable IRQ when I bit is set */ /* * Register Base Address */ .section .vectors,"ax" .code 32 /*********************************************************************** *****/ /* Vector table and reset entry */ /*********************************************************************** *****/ _vectors: ldr pc, ResetAddr /* Reset */ ldr pc, UndefAddr /* Undefined instruction */ ldr pc, SWIAddr /* Software interrupt */ ldr pc, PAbortAddr /* Prefetch abort */ ldr pc, DAbortAddr /* Data abort */ ldr pc, ReservedAddr /* Reserved */ ldr pc, [pc, #-0x0FF0] /* Vector from VicVectAddr */ ldr pc, FIQAddr /* FIQ interrupt */ ResetAddr: .word ResetHandler UndefAddr: .word UndefHandler SWIAddr: .word SWIHandler PAbortAddr: .word PAbortHandler DAbortAddr: .word DAbortHandler ReservedAddr: .word 0 IRQAddr: .word IRQHandler FIQAddr: .word FIQHandler .ltorg .section .init, "ax" .code 32 .global ResetHandler .global ExitFunction .extern main /*********************************************************************** *****/ /* Reset handler */ /*********************************************************************** *****/ ResetHandler: /* * Wait for the oscillator is stable */ nop nop nop nop nop nop nop nop /* * Setup a stack for each mode */ msr CPSR_c, #ARM_MODE_UNDEF | I_BIT | F_BIT /* Undefined Instruction Mode */ ldr sp, =__stack_und_end msr CPSR_c, #ARM_MODE_ABORT | I_BIT | F_BIT /* Abort Mode */ ldr sp, =__stack_abt_end msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT /* FIQ Mode */ ldr sp, =__stack_fiq_end msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* IRQ Mode */ ldr sp, =__stack_irq_end msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT /* Supervisor Mode */ ldr sp, =__stack_svc_end /* * Clear .bss section */ ldr r1, =__bss_start ldr r2, =__bss_end ldr r3, =0 bss_clear_loop: cmp r1, r2 strne r3, [r1], #+4 bne bss_clear_loop /* * Jump to main */ mrs r0, cpsr bic r0, r0, #I_BIT | F_BIT /* Enable FIQ and IRQ interrupt */ msr cpsr, r0 mov r0, #0 /* No arguments */ mov r1, #0 /* No arguments */ ldr r2, =main mov lr, pc bx r2 /* And jump... */ ExitFunction: nop nop nop b ExitFunction /*********************************************************************** *****/ /* Default interrupt handler */ /*********************************************************************** *****/ UndefHandler: b UndefHandler SWIHandler: b SWIHandler PAbortHandler: b PAbortHandler DAbortHandler: b DAbortHandler IRQHandler: b IRQHandler // wenn ich hier den Namen meiner Routine // reinsetze klappt es mit dem Interrupt FIQHandler: b FIQHandler .weak ExitFunction .weak UndefHandler, PAbortHandler, DAbortHandler .weak IRQHandler, FIQHandler .ltorg /*** EOF ***/
> Wegen der Zählschleife. Sind dafür die paar nops gedacht? Ist das > überhaupt genug? Nur wenn es dir gelingt, den Prozessor mit 10Hz zu takten.
> Ich debugge im RAM. Insofern denke ich es passt schon ;-) Es ist ja nicht so, dass das RAM dann rein garnicht funktioniert. Sondern dass es in bestimmten Fällen Mist baut. Merke: Wer ARM-Controller programmiert und verbaut, ohne vorher das dazugehörende Erratasheet gründlich gelesen zu haben, wird mit mindestens 3 Jahren PIC16 bestraft! ;-) EDIT: Das wird sicherlich nichts mit dem Problem hier zu tun haben. Aber trotzdem wichtig.
> Ich debugge im RAM. Insofern denke ich es passt schon ;-) Steht im Flash was drin? Das läuft nämlich dann so: Nach Reset läuft das Teil erst einmal eine Weile aus dem Flash. Dann fängt JTAG ihn ein und schickt ihn ins RAM. Wenn der im Flash-Code zu diesem Zeitpunkt schon irgendwas initialisiert hat, dann kann das deinen schönen Code höllisch durcheinander bringen. Einfachste Abhilfe: Für RAM-Debugging einmal vorweg einen Code flashen, der rein garnichts tut (Totschleife ab Reset). Oder aber besagte Zeitschleife vorneweg hat.
Ach Du Scheiße! Habe witzigerweise das Errata gelesen, aber falsch abgeschrieben. Hatte MAMTIM=0x04 gesetzt. Leider hält mich Eclipse gerade und schon seit ner Weile mit regelmäßigen Abstürzen vom Testen ab.
Diese MAMTIM Initialisierung sollte allerdings vor dem ersten RAM-Zugriff passieren. Also direkt nach Reset.
Ich könnte mir ja so in den Arsch beissen! Nachdem Eclipse mich jetzt Ewigkeiten vom Ausprobieren abgehalten hat, habe ich feststellen müssen, dass es einfach funktioniert!!! Witzigerweise ist die einzige Änderung das MAMTIM gewesen. Die PLL-Feed-Sequenz dauert jetzt zwar irgendwie länger, aber das ist mir jetzt mal echt egal! Auf jedenfall vielen Dank für Eure Tipps und Hilfe!!!! Den Stack werde ich gleich mal auf 256 stellen. Ne weitere Frage habe ich allerdings noch. Und zwar, wie mache ich das mit der Sicherung der Linkregister? Brauche ich das überhaupt? Möchte erstmal dahin kommen, dass ich keine Schwierigkeiten bekomme, wenn der Interrupt vom ADC in die Timerinterruptroutine fällt.
Bisher habe ich noch die PLL-Prozedur davor. Ist besser wenn ich das vertausche, oder?
> Ne weitere Frage habe ich allerdings noch. Und zwar, wie mache ich das > mit der Sicherung der Linkregister? Brauche ich das überhaupt? Möchte > erstmal dahin kommen, dass ich keine Schwierigkeiten bekomme, wenn der > Interrupt vom ADC in die Timerinterruptroutine fällt. Lass das mit dem Nesting sein, bis du ein Stück weiter bist. Die Interrupt-Routine läuft von haus aus mit abgeschalteten Interrupts das wird dann also nicht passieren.
> Bisher habe ich noch die PLL-Prozedur davor. Ist besser wenn ich das > vertausche, oder? Da die Voreinstellung auf "langsamst" steht, ist es eigentlich egal. So, jetzt ist wieder Doku greifbar. Es geht beim dem Fehler MAM.1 nicht um MAMTIM, sondern eher um MAMCR. Und das sollte man vorsorglich gleich machen, also bevor man das RAM anfasst, im Startup. Langsameres Flash-Timing hingegen sollte erst einmal keine Rolle spielen. Wenn man allerdings später am MAMTIM drehen will, sollte man beachten, dass man dies lieber nicht bei eingeschaltetem MAM macht. Das ist nun für deinen RAM-residenten Code nicht von Belang, aber pack es lieber trotzdem in den Startup rein. Schadet nicht und erspart Ärger später.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.