Hallo Experten, ich habe gerade begonnen mit dem MSP430F1611 in Assembler zu programmieren. Ich benutze unter Linux den msp430-gcc und den ddd mit msp430-debugger. Ich habe das OLIMEX MSP430-P1611 Eval Board. Ich möchte den 32,768 KHz Quartz für MCLK und ACLK 1:1 verwenden, um mit dem TimerA im "count up to TACCR0" mode jede Sekunde einen Interrupt auszulösen. Hat der TimerA den Wert in TACCR0 erreicht, setzt die zugehörige ISR (TIMERA0_ISR) im Register R13 ein Flag. Der Mainloop fragt ständig das Flag ab und toggelt eine LED an Port 6 bit 0 wenn das Flag gesetzt wurde. Anschließend wird das Flag wieder gelöscht. Alle anderen ISRs setzen entsprechend ihrer Priorität Bits in R14. Eigentlich ganz einfach, oder??? Aber es klappt nicht! Problem: Wenn der das Zählerregister (TAR) vom TimerA den in TACCR0 vorgegeben Soll-Wert (hier testweise 0xA) erreicht, springt der Programmcounter auf den Wert 0xffff . Dann verabschiedet sich das Programm, klar! Der MCLK läuft mit ca. 60kHz statt mit 32kHz. Der ACLk läuft mit der gleichen Frequenz wie der MCLK aber nur mit einigen 100mV Amplitude. Was mache ich falsch?? Hoffentlich könnt Ihr mir helfen! Stephan Hier der Assembler Code: #include <signal.h> #include <io.h> #include <msp430x16x.h> #define P6OUT 0x35 #define P6DIR 0x36 #define P6SEL 0x37 #define P5DIR 0x32 #define P5SEL 0x33 .section .text ;----------------------------------------------------------------------- ------ ; Program RESET ;----------------------------------------------------------------------- ------ RESET: MOV #__stack,R1 ; Initialize stackpointer CALL #Setup ; basic hardware setup ;----------------------------------------------------------------------- ------ ; Mainloop ;----------------------------------------------------------------------- ------ Mainloop: BIT #0x01,R13 ; Test if flag is set. (set after INT) JZ Mainloop ; Loop if flag is not set BIT.b #0x01,&P6OUT ; Test if LED is off (P6.0 = 1) JNZ Ledon ; Jump to Ledon Ledoff: BIS.b #0x01,&P6OUT ; Turn LED off BIC #0x01,R13 ; Clear flag JMP Mainloop ; Wait for next INTERRUPT Ledon: BIC.b #0x01,&P6OUT ; Turn LED on BIC #0x01,R13 ; Clear flag JMP Mainloop ; Wait for next INTERRUPT ;----------------------------------------------------------------------- ------ ; Setup: Configure Modules and Control Registers ;----------------------------------------------------------------------- ------ Setup: MOV #WDTPW+WDTHOLD,&WDTCTL ; Stop Watchdog Timer BIS.b #0x38,&P5SEL ; Select I/O for P5.4-6 BIS.b #0x38,&P5DIR ; Set output direction for P5.4-6 BIC.b #0x01,&P6SEL ; select I/O-function for P6.0 BIS.b #0x01,&P6DIR ; set P6.0 direction to output BIC.b #0x01,&P6OUT ; clear P6.0 (turn LED on) CLR R13 ; clear R13 incl. flag CLR R14 ; clear R14 for Interrupt source detect MOV #TASSEL0+TACLR, &TACTL ; ACLK for Timer_A. BIS #CCIE,&CCTL0 ; Enable CCR0 interrupt. MOV #0xA,&CCR0 ; load CCR0 with 10. ; MOV #0x7FFF,&CCR0 ; load CCR0 with 32,767. BIS.b #SELM1+SELM0,&BCSCTL2 ; set MCLK source to LFXT1CLK BIS #MC0,&TACTL ; start TA in "up to CCR0" mode EINT ; Enable interrupts RET ; Done with setup ;----------------------------------------------------------------------- ------ ; Interrupt service routines: ;----------------------------------------------------------------------- ------ DACDMA_VECTOR_ISR: BIS #0x8000,R14 ; 0xFFE0 DAC12/DMA RETI PORT2_VECTOR_ISR: BIS #0x4000,R14 ; 0xFFE2 Port 2 RETI USART1TX_VECTOR_ISR: BIS #0x2000,R14 ; 0xFFF4 USART 1 Transmit RETI USART1RX_VECTOR_ISR: BIS #0x1000,R14 ; 0xFFF6 USART 1 Receive RETI PORT1_VECTOR_ISR: BIS #0x800,R14 ; 0xFFE8 Port 1 RETI TIMERA1_ISR: BIS #0x400,R14 ; 0xFFEA Timer A CC1-2, TA RETI TIMERA0_ISR: BIS #0x01,R13 ; 0xFFEC Timer A CC0 RETI ADC12_VECTOR_ISR: BIS #0x100,R14 ; 0xFFEE ADC RETI USART0TX_VECTOR_ISR: BIS #0x80,R14 ; 0xFFF0 USART 0 Transmit RETI USART0RX_VECTOR_ISR: BIS #0x40,R14 ; 0xFFF2 USART 0 Receive I2C tx/rx RETI WDT_VECTOR_ISR: BIS #0x20,R14 ; 0xFFF4 Watchdog Timer RETI COMPARATORA_VECTOR_ISR: BIS #0x10,R14 ; 0xFFF6 Comparator A RETI TIMERB1_VECTOR_ISR: BIS #0x08,R14 ; 0xFFF8 Timer B CC1-2, TB RETI TIMERB0_ISR: BIS #0x04,R14 ; 0xFFFA TIMER B CC0 RETI NMI_ISR: BIS #0x02,R14 ; 0xFFFC Non maskable RETI ;----------------------------------------------------------------------- ------ ; MSP430F1611 interrupt vector table ;----------------------------------------------------------------------- ------ .section .vectors .org DACDMA_VECTOR,0xFF .word DACDMA_VECTOR_ISR ; 0xFFE0 DAC12/DMA .org PORT2_VECTOR,0xFF .word PORT2_VECTOR_ISR ; 0xFFE2 Port 2 .org USART1TX_VECTOR,0xFF .word USART1TX_VECTOR_ISR ; 0xFFF4 USART 1 Transmit .org USART1RX_VECTOR,0xFF .word USART1RX_VECTOR_ISR ; 0xFFF6 USART 1 Receive .org PORT1_VECTOR,0xFF .word PORT1_VECTOR_ISR ; 0xFFE8 Port 1 .org TIMERA1_VECTOR,0xFF .word TIMERA1_ISR ; 0xFFEA Timer A CC1-2, TA .org TIMERA0_VECTOR,0xFF .word TIMERA0_ISR ; 0xFFEC Timer A CC0 .org ADC12_VECTOR,0xFF .word ADC12_VECTOR_ISR ; 0xFFEE ADC .org USART0TX_VECTOR,0xFF .word USART0TX_VECTOR_ISR ; 0xFFF0 USART 0 Transmit .org USART0RX_VECTOR,0xFF .word USART0RX_VECTOR_ISR ; 0xFFF2 USART 0 Receive I2C tx/rx .org WDT_VECTOR,0xFF .word WDT_VECTOR_ISR ; 0xFFF4 Watchdog Timer .org COMPARATORA_VECTOR,0xFF .word COMPARATORA_VECTOR_ISR ; 0xFFF6 Comparator A .org TIMERB1_VECTOR,0xFF .word TIMERB1_VECTOR_ISR ; 0xFFF8 Timer B CC1-2, TB .org TIMERB0_VECTOR,0xFF .word TIMERB0_ISR ; 0xFFFA TIMER B CC0 .org NMI_VECTOR,0xFF .word NMI_ISR ; 0xFFFC Non maskable .org RESET_VECTOR,0xFF .word RESET ; POR, external RST, Watchdog
>Ich möchte den 32,768 KHz Quartz für MCLK und ACLK 1:1 verwenden, um mit >dem TimerA im "count up to TACCR0" mode jede Sekunde einen Interrupt >auszulösen. Ich würde MCLK nicht auf 32,768kHz setzen, sondern auf DCO belassen. Die CPU mit 32,768kHz zu takten bringt keinen Vorteil! ACLK für TMR_A ist OK >Der MCLK läuft mit ca. 60kHz statt mit 32kHz. Der ACLk läuft mit der >gleichen Frequenz wie der MCLK aber nur mit einigen 100mV Amplitude. Wo gemessen? An P5.4 und P5.6? Auch mal an XOUT direkt gemessen? >BIS.b #0x38,&P5SEL ; Select I/O for P5.4-6 >BIS.b #0x38,&P5DIR ; Set output direction for P5.4-6 Damit wählst Du aber P5.3-P5.5 aus! BIS.b #0x70,... sollte funktionieren >.org TIMERA0_VECTOR,0xFF >.word TIMERA0_ISR ; 0xFFEC Timer A CC0 Ich kenne mich mit Deiner tool-chain nicht aus, aber warum steht bei .org ein 0xFF dahinter? Ist in TIMERA0_VECTOR nur das Low-Byte (0xEC) definiert? Nicht dass Deine Vektoren ins Nirwana zeigen und der µC deshalb abschmiert?! Generell: -Vcc geprüft? -eventuell beim Setup kleine Warteschleife, um ACLK stabilisieren zu lassen (kann u.U. mehrere 100ms dauern!!!)
Hallo Stefan, vielen Dank für Deine Tipps. Ich werde sie heute Abend eingehend prüfen. Mit den Ports P5 hast Du natürlich recht! Es muss 0x70 statt 0x38 für P5.4 - P5.6 heißen. Habe das gerade auch geprüft, jetzt stimmt die Amplitude von ACLK! Das mit den Interrupt-Vektoren (0xFF) kommt mir auch komisch vor. Ich habe das aus einem TI Sample Code. Im Assembler Listing baut er es meiner Meinung aber richtig zusammen. Ich poste das später gleich mal. Habe auch schon den Stackinitialisierungsmakro __stack im Verdacht gehabt. Der initialisiert den Stack mit 0x3900. Laut Datenblatt geht der RAM Bereich von 0x1100 bis 0x38FF. Tja!? Ich habe ihn schon auf 0x3800 initialisiert, hilft aber nichts. Muß ich den DCO dann noch irgendwie kalibrieren? Oder kann der mit den Defaultwerten laufen? Das mit der Warteschleife für ACLK-Stabilisierung probiere ich gleich mal aus! Später mehr, vielen Dank nochmals. Gruß Stephan
@ Stephan Bode (Gast) >auszulösen. Hat der TimerA den Wert in TACCR0 erreicht, setzt die >zugehörige ISR (TIMERA0_ISR) im Register R13 ein Flag. Der Mainloop >fragt ständig das Flag ab und toggelt eine LED an Port 6 bit 0 wenn das >Flag gesetzt wurde. Anschließend wird das Flag wieder gelöscht. Warum toggelst du die LED nicht in der ISR? >Der MCLK läuft mit ca. 60kHz statt mit 32kHz. Der ACLk läuft mit der >gleichen Frequenz wie der MCLK aber nur mit einigen 100mV Amplitude. ??? Lässt du MCLK ausgeben? Dann muss dort ein solides Digitalsignal rauskommen. Mit ASM kenn ich mich auf dem MSP nicht aus. >gehabt. Der initialisiert den Stack mit 0x3900. Laut Datenblatt geht der >RAM Bereich von 0x1100 bis 0x38FF. Passt schon. Der Stack wird über Predekrement adressier. >Muß ich den DCO dann noch irgendwie kalibrieren? Oder kann der mit den >Defaultwerten laufen? Sicher. Wozu brauchst du einen hochpräzisen Takt zum LED toggeln? MfG Falk
>Das mit den Interrupt-Vektoren (0xFF) kommt mir auch komisch vor. Ich >habe das aus einem TI Sample Code. Der TI Sample Code lautet aber:
1 | ORG 0FFECh ; Timer_A0 Vector |
2 | DW TA0_ISR ; |
Ich würde mir die Definition von TIMERA0_VECTOR bzw. die Doku zu .org für Dein Tool nochmal genauer anschauen, ob das
1 | .org TIMERA0_VECTOR, 0xFF |
wirklich das macht, was es soll! >Der initialisiert den Stack mit 0x3900. Laut Datenblatt geht der >RAM Bereich von 0x1100 bis 0x38FF 0x3900 stimmt schon. Der Stack wird von oben her "befüllt". Zuerst wird dekrementiert (beim 1. Mal bist Du dann richtig bei 0x38FF oder kleiner) und dann wird auf den Stack geschrieben. >Muß ich den DCO dann noch irgendwie kalibrieren? Oder kann der mit den >Defaultwerten laufen? Für Dein "simples" Beispiel kann der DCO so bleiben, wie er nach dem Reset voreingestellt ist (ca. 1MHz). Wenn Du aber z.B. noch eine UART brauchst, oder einen zweiten genauen Timer (der vom DCO getaktet wird), dann solltest Du den DCO immer mal wieder auf die 32,768kHz synchronisieren. Gibt's auch Bsp. von TI. Bei Bedarf nochmal nachfragen! >Das mit der Warteschleife für ACLK-Stabilisierung probiere ich gleich >mal aus! Das kann nicht schaden ;-) Hat TI übrigens auch im Bsp. gemacht.
Hallo, @ Falk: Natürlich hätte ich die LED auch in der ISR toggeln können. Ich will mir nur gleich angewöhnen, flags in der ISR zu setzen, und die Hauptarbeit im Mainloop zu erledigen. Mir fällt aber gerade ein, dass die ISRs nicht reentrant sind, sofern man nicht das GIE manuell verändert, die ISR beliebig vollpacken, oder? Es sei denn, ich möchte in einem best. Zeitintervall Interrupts haben, dann sollte die ISR Abarbeitung nicht länger als das Zeitintervall dauern. Momentan läuft die CPU nur im Debugger, dann sehe ich auch einen sauberen MCLK auf dem Oszi. Danke an Euch für den Tipp mit der Predekrementadressierung des Stack, das hatte ich überlesen! Ich weiß, dass ich zum LED toggeln keinen hochpräzisen Clock noch Flags in den ISRs benötige, aber es soll ja auch nicht nur beim toggeln bleiben :-) @ Stefan: Ich habe mich hauptsächlich an den im www.mikrocontroller.net angegebenen Beispielen orientiert unter http://www.mikrocontroller.net/articles/MSPGCC findet man unter "MSPGCC Beispiele & Appnotes" den link auf ein CVS Repository: http://mspgcc.cvs.sourceforge.net/mspgcc/examples/ Dort findet man die TI Beispiele SLAA* oder SLAC* wieder. Die Beispiele für die IAR workbench und CCES von der TI homepage www.msp430.com verwenden eine Syntax, die der msp430-gcc nicht versteht. In diesen Assembler files findet sich z.B. keine ".section .text" Anweisung. Kommentiere ich in meinem assembler code die .sections aus, streikt der msp430-gcc. Auch mit ORG 0FFECh bzw. DW kommt er nicht klar und meldet: msp430-gcc -g -O2 -mmcu=msp430x1611 -D_GNU_ASSEMBLER_ -nostartfiles -nostandartlibs main.S -o main main.S: Assembler messages: main.S:104: Error: unknown opcode `org' main.S:105: Error: unknown opcode `dw' make: *** [main] Fehler 1 bzw.: main.S:104: Error: attempt to move .org backwards die Doku zum gnu assembler gas, der meiner Meinung nach hinter dem msp430-gcc bzw. msp430-as steckt sagt folgendes zur .org Direktive: ------------------------------------------------------------------------ --- .org new-lc , fill .org will advance the location counter of the current section to new-lc. new-lc is either an absolute expression or an expression with the same section as the current subsection. That is, you can't use .org to cross sections: if new-lc has the wrong section, the .org directive is ignored. To be compatible with former assemblers, if the section of new-lc is absolute, will issue a warning, then pretend the section of new-lc is the same as the current subsection. .org may only increase the location counter, or leave it unchanged; you cannot use .org to move the location counter backwards. Because tries to assemble programs in one pass new-lc may not be undefined. If you really detest this restriction we eagerly await a chance to share your improved assembler. Beware that the origin is relative to the start of the section, not to the start of the subsection. This is compatible with other people's assemblers. When the location counter (of the current subsection) is advanced, the intervening bytes are filled with fill which should be an absolute expression. If the comma and fill are omitted, fill defaults to zero. nachzulesen bei:http://www.cs.utah.edu/dept/old/texinfo/as/as.html#SEC90 ------------------------------------------------------------------------ --- So sieht mein Assembler listing der Interrupttabelle aus (erzeugt mit msp430-objdump -DSt main > main.lst: 0000ffe0 <_vectors_end-0x20>: ffe0: 60 40 interrupt service routine at 0x4060 ffe2: 66 40 interrupt service routine at 0x4066 ffe4: 6c 40 interrupt service routine at 0x406c ffe6: 72 40 interrupt service routine at 0x4072 ffe8: 78 40 interrupt service routine at 0x4078 ffea: 7e 40 interrupt service routine at 0x407e ffec: 84 40 interrupt service routine at 0x4084 ffee: 88 40 interrupt service routine at 0x4088 fff0: 8e 40 interrupt service routine at 0x408e fff2: 94 40 interrupt service routine at 0x4094 fff4: 9a 40 interrupt service routine at 0x409a fff6: a0 40 interrupt service routine at 0x40a0 fff8: a6 40 interrupt service routine at 0x40a6 fffa: aa 40 interrupt service routine at 0x40aa fffc: ae 40 interrupt service routine at 0x40ae fffe: 00 40 interrupt service routine at 0x4000 So ist es doch richtig, oder? folgendes Setup habe ich jetzt: ------------------------------------------------------------------------ --- Setup: MOV #WDTPW+WDTHOLD,&WDTCTL ; Stop Watchdog Timer BIS.b #0x70,&P5SEL ; Select I/O for P5.4-6 BIS.b #0x70,&P5DIR ; Set output direction for P5.4-6 BIC.b #0x01,&P6SEL ; select I/O-function for P6.0 BIS.b #0x01,&P6DIR ; set P6.0 direction to output BIC.b #0x01,&P6OUT ; clear P6.0 (turn LED on) CLR R13 ; clear R13 incl. flag CLR R14 ; clear R14 for Interrupt source detect MOV #TASSEL0+TACLR, &TACTL ; ACLK for Timer_A. BIS #CCIE,&CCTL0 ; Enable CCR0 interrupt. MOV #0xA,&CCR0 ; load CCR0 with 10. ; MOV #0x7FFF,&CCR0 ; load CCR0 with 32,767. BIS #MC0,&TACTL ; start TA in "up to CCR0" mode EINT ; Enable interrupts RET ; Done with setup ------------------------------------------------------------------------ --- Der ACLK hat auf dem OSZI ca. 7µs high level und fast 10µs low level. Das macht etwa 58,8kHz. Amplitude ist etwa 3,3V. Der MCLK läuft mit ~1MHz und 3,3V schön symmetrisch. Da ist doch etwas nicht in Ordnung, oder? Da ich das Olimex Board habe, habe ich mir über Spannungsversorgung keine großen Sorgen gemacht. Mit obigem Setup, zählt der Zähler überhaupt nicht mehr, ich kann im Einzelschrittmodus mit dem Debugger durch die Main-Schleife steppen, ohne das ein Interrupt kommt. Lasse ich den debugger laufen mit Continue, ist kurz danach der MCLK aus. Das kann doch nicht so schwer sein, oder? Was meint Ihr? Stephan
@ Stephan Bode (Gast) >@ Falk: Natürlich hätte ich die LED auch in der ISR toggeln können. Ich >will mir nur gleich angewöhnen, flags in der ISR zu setzen, und die >Hauptarbeit im Mainloop zu erledigen. Mir fällt aber gerade ein, dass Gute Einstellung! Hast wohl den Artikel Interrupt gelesen? ;-) >die ISRs nicht reentrant sind, sofern man nicht das GIE manuell >verändert, die ISR beliebig vollpacken, oder? Es sei denn, ich möchte in ??? Interrupts sind eigentlich nie reentrant. Ein reentranter Aufruf wäre ein Programmier/Timingfehler. >ISRs benötige, aber es soll ja auch nicht nur beim toggeln bleiben :-) Dann nimm eine Quarz am Oszillator. >.org may only increase the location counter, or leave it unchanged; you >cannot use .org to move the location counter backwards. Na dann schreib das .org eben WIRKLICH ans Ende deines Quellcodes. >So ist es doch richtig, oder? Bin ich mir nicht sicher. Dort müsste doch DIREKT der Sprung in deine Routine drinstehen, bzw die Adresse. >Der ACLK hat auf dem OSZI ca. 7µs high level und fast 10µs low level. >Das macht etwa 58,8kHz. Amplitude ist etwa 3,3V. Der MCLK läuft mit ??? Wenn ACLK vom 32k Quarz kommt, dann müssen da auch 32kHz rauskommen, auch recht nahe an 50% Duty Cycle. Per default wird ja der 32k Quarz genutz. Hoffentlich stellts du dann nicht extra was falsches ein. >Continue, ist kurz danach der MCLK aus. Das kann doch nicht so schwer >sein, oder? Was meint Ihr? Eigentlich nicht. Stell mal gar nix an den Ozillatoreinstellungen rum, aktiviere nur die Ausgabe von MCLK und ACLK an den Pins. MfG Falk
>Es sei denn, ich möchte in >einem best. Zeitintervall Interrupts haben, dann sollte die ISR >Abarbeitung nicht länger als das Zeitintervall dauern. Die Bearbeitungsdauer einer ISR sollte immer kürzer sein, als deren Aufruf. Sonst kommt das System ja nicht mehr hinterher... >die ISRs nicht reentrant sind meinst Du dieselbe ISR oder eine andere? Dieselbe ISR nocheinmal aufzurufen, während sie selbst noch bearbeitet wird, kann nie gut gehen. Eine andere ISR kann man mal dazwischenschieben. Dann muss man aber ganz genau wissen, was man tut! >>ISRs benötige, aber es soll ja auch nicht nur beim toggeln bleiben :-) >Dann nimm eine Quarz am Oszillator. Nicht unbedingt. Wenn man z.B. im Batteriebetrieb stromsparend arbeiten will, ist ein 32,768kHz Uhrenquarz die erste Wahl, da dieser im Sleep Modus weiterlaufen kann und dabei grad mal ~1µA zieht. Der interne DCO kann sehr einfach auf die Uhrenquarzfrequenz synchronisiert werden, was ein präzises Timing ermöglicht! >0000ffe0 <_vectors_end-0x20>: >... >ffec: 84 40 interrupt service routine at 0x4084 >... >So ist es doch richtig, oder? Wenn an Adresse 0x4084 Deine ISR für den CCR0-IRQ anfängt... Ja! Schau in Deiner main.lst nach, ob die ISR-Adresse stimmt. Aber ich glaube schon, dass es stimmt:
1 | TIMERA0_ISR: BIS #0x01,R13 ; 0xFFEC Timer A CC0 |
2 | RETI
|
Die ISR belegt 4Bytes an Code und der nächste Eintrag in der Vector-Tabelle ist genau 4 Bytes später (0x4088) >Der ACLK hat auf dem OSZI ca. 7µs high level und fast 10µs low level. >Das macht etwa 58,8kHz. Amplitude ist etwa 3,3V. Nochmal: Gemessen an P5.6 (Pin50) oder an XOUT (Pin9)? Sind auf dem Olimexboard eignetlich C4 und C5 bestückt? Sollten sie nicht, da der MSP die Load-Kondensatoren für Uhrenquarz schon integriert hat. Zum CLK-Problem muss ich erstmal weiter nachdenken... ;-)
Also ich hab's grad mal ausprobiert...
Hab zwar 'nen F1232 und die IAR-Entwicklungsumgebung, aber vom Prinzip
her hab ich Deine Initialisierung für die Basic Clocks sowie für den
Timer_A hergenommen und alles hat auf Anhieb funktioniert!
Die Software an sich scheint also in Ordnung zu sein.
Ich vermute eher ein Hardwareproblem bei Deinem Quarz, MSP, Board, ...?
Oder dass eben doch was nicht mit den IRQ-Vektoren stimmt.
Versuch mal beim Debuggen nur einen Breakpoint in der ISR zu setzen und
im Continuous-Mode laufen zu lassen, ob er wirklich in der ISR ankommt
und was er dort dann macht.
>ist kurz danach der MCLK aus
Da der MCLK vom internen DCO getaktet wird und die Ausgabe an P5.4 ein
HW-Feature ist, scheint sich der µC irgendwie ganz dramatisch zu
verabschieden oder in einem Endlos-Reset zu hängen...???!!!
Hallo, @ Falk: Ja, ich bin sehr bemüht ordentlich zu programmieren :-) Ich hatte mir auch zwei Bücher über den MSP430 ausgeliehen, eins von Luecke und das andere von Nagy. Eigentlich stelle ich nicht viel an den Oszillatoreinstellungen rum. Das OSCOFF bit im SR ist bei mir nicht gesetzt (Default), da ich den MCLK vom DCO speise. Im Manual steht folgendes zum OSCOFF: --------------------------------------------------------------------- OSCOFF Oscillator Off. This bit, when set, turns off the LFXT1 crystal oscillator, when LFXT1CLK is not use for MCLK or SMCLK --------------------------------------------------------------------- Muss ich das OSCOFF dann setzen, wenn ich den LFXT1 nicht für MCLK und SMCLK sondern nur für ACLK brauche? @ Stefan: > Die Bearbeitungsdauer einer ISR sollte immer kürzer sein, als deren Aufruf. Sonst kommt das System ja nicht mehr hinterher... Da bin ich ganz Deiner Meinung. > Wenn an Adresse 0x4084 Deine ISR für den CCR0-IRQ anfängt... Ja! > Schau in Deiner main.lst nach, ob die ISR-Adresse stimmt. > Aber ich glaube schon, dass es stimmt: Ich habe die main.lst gerade nicht da, aber ich habe früher dort schon nachgesehen, die Adressen an denen die ISRs im Speicher beginnen stimmen nach dem compilieren mit den von mir in der section vectors eingetragenen Interruptvektoren überein. Wenn ich im debugger den PC mit set $pc=0xFFEC auf 0xFFEC stelle, müsste er dann nicht im nächsten Schritt in die entsprechende ISR springen? >>Der ACLK hat auf dem OSZI ca. 7µs high level und fast 10µs low level.Das macht etwa 58,8kHz. Amplitude ist etwa 3,3V. >Nochmal: Gemessen an P5.6 (Pin50) oder an XOUT (Pin9)? Das habe ich am P5.6 gemessen! Am Pin9 ist kein CLK-Signal. Bin mir bei letzterem nicht mehr ganz sicher, werde ich heute Abend nochmal überprüfen! Das wäre schon komisch oder? Auf dem Olimexboard sind C4 und C5 mit jeweils 10pF bestückt! Vielleicht baue ich die mal aus. Ich kann mir aber nicht vorstellen, das Olimex die bestückt hat, ohne dass sie einen Sinn haben. Oder? Stephan
>Muss ich das OSCOFF dann setzen, wenn ich den LFXT1 nicht für MCLK und >SMCLK sondern nur für ACLK brauche? NEIN Mit OSCOFF schaltest Du LFXT1 ab und damit würdest Du ACLK auch abschalten! Der obige Satz besagt lediglich, dass OSCOFF nur dann gesetzt werden kann, wenn LFXT1 nicht für MCLK oder SMCLK benutzt wird. Sozusagen ein Sicherheitsfeature gegen versehentliches Ausschalten des Mainclocks
>Wenn ich im debugger den PC mit >set $pc=0xFFEC auf 0xFFEC stelle, müsste er dann nicht im nächsten >Schritt in die entsprechende ISR springen? Ähhh..... nee! In 0xFFEC steht ja kein Code oder Sprungbefehl sondern nur eine Adresse, zu der gesprungen werden soll. Also set $pc=0x4084 erscheint mir erfolgversprechender
@ Stephan (Gast) >eingetragenen Interruptvektoren überein. Wenn ich im debugger den PC mit >set $pc=0xFFEC auf 0xFFEC stelle, müsste er dann nicht im nächsten >Schritt in die entsprechende ISR springen? NEIN! Der MSP hat keine Interrupttabelle wie der AVR! Dort stehen nur Adressen, KEIN Sprungbefehle in die ISR. Also ist ein Sprung IN die Interruptvektoren total falsch! >Auf dem Olimexboard sind C4 und C5 mit jeweils 10pF bestückt! Vielleicht >baue ich die mal aus. Ich kann mir aber nicht vorstellen, das Olimex die >bestückt hat, ohne dass sie einen Sinn haben. Oder? Die sind nur sinnvoll, wenn man einen normalen Quarz mit 1..8 MHz benutzt. MfG Falk
Hallo, @ Falk, Stefan >>Wenn ich im debugger den PC mit >>set $pc=0xFFEC auf 0xFFEC stelle, müsste er dann nicht im nächsten >>Schritt in die entsprechende ISR springen? >Ähhh..... nee! >In 0xFFEC steht ja kein Code oder Sprungbefehl sondern nur eine Adresse, >zu der gesprungen werden soll. >Also set $pc=0x4084 erscheint mir erfolgversprechender OK, natürlich, ihr habt recht! Dort stehen keine JMPs o.ä. sondern nur Sprungadressen! Aaaarggh! Kann der TimerA CCIFG0-Interrupt ausgelöst werden, indem im TACCTL0 Register das bit 0 (CCIFG) manuell gesetzt wird? Falls ja, könnte so getestet werden, ob die ISR richtig angesprungen wird? Muss im TACTL Register das bit 1 TAIE gesetzt werden, damit der CCIFG0-Interrupt beachtet wird? @ Stefan: Danke, dass Du meine Setup Routine getestet hast. Ich vermute auch, dass etwas mit der Hardware nicht stimmt. Aber wenn, dann nur, weil es nicht richtig konfiguriert ist. Ich habe das uart_test Beispiel (siehe Link zu den mspgcc-Beispielen weiter oben im Posting) mit dem mspgcc compiliert. Das klappt einwandfrei. Dort wird über RS232 ein Zeichen (vom Hyperterminal) empfangen und mit einem Bytecount zurückgesendet. Ich werde das Programm mal laden und die Signale ausmessen. Liegt der 32kHz CLK auch am Pin 9 XOUT? @ Falk: > Die sind nur sinnvoll, wenn man einen normalen Quarz mit 1..8 MHz benutzt. Stören die, wenn der 32kHz Uhrenquartz statt einem 1..8 MHz Quartz verwendet wird? Stephan
>Kann der TimerA CCIFG0-Interrupt ausgelöst werden, indem im TACCTL0 >Register das bit 0 (CCIFG) manuell gesetzt wird? Laut User-Guide ja! >Falls ja, könnte so getestet werden, ob die ISR richtig angesprungen wird? s. o. >Muss im TACTL Register das bit 1 TAIE gesetzt werden, damit der >CCIFG0-Interrupt beachtet wird? Nein, TAIE ist der Timer-Overflow-IRQ! >Liegt der 32kHz CLK auch am Pin 9 XOUT? Mit Sicherheit. Das ist ja der Quarz angeschlossen (und an XIN) >Stören die, wenn der 32kHz Uhrenquartz statt einem 1..8 MHz Quartz >verwendet wird? Wenn Dein "uart_test" Beispiel mit dem Uhrenquarz funktioniert, dann wohl nicht. Aber eigentlich sind sie unnötig, da ja 2x 6pF bereits im MSP drin sind. Ich würde sie für den Uhrenquarzbetrieb auslöten!
Guten Abend, Es ist kaum zu fassen, aber ich kann an keinem der beiden Pins XIN, XOUT ein CLK signal messen. Ich habe über beiden Pins gemessen und von jedem Pin zu GND. Ich habe in meiner SETUP Routine den ACLK ungeteilt auf den Pin P5,6 ausgegeben, dort messe ich einen Clock, der aber mit ca. 17-20µs zu schnell ist. Was kann denn das bloss sein? Stephan
@ Stephan (Gast) >Es ist kaum zu fassen, aber ich kann an keinem der beiden Pins XIN, XOUT >ein CLK signal messen. Ich habe über beiden Pins gemessen und von jedem Wie misst du denn? Hoffentlich mit einem 10:1 Tastkopf. Und selbst das könnte unter Umständen den Oszillator abwürgen. Und vor allem wie misst du ÜBER den PINs? Hoffentlich nicht mit der Masse vom Oszi an einem Pin. >Pin zu GND. Ich habe in meiner SETUP Routine den ACLK ungeteilt auf den >Pin P5,6 ausgegeben, dort messe ich einen Clock, der aber mit ca. >17-20µs zu schnell ist. Was kann denn das bloss sein? Es liegt was im Argen. 32kHz sind ~33us Periodendauer. Und das so ziemlich genau. MfG Falk
Guten Tag! Nachdem ich auf dem Olimex-Board MSP430-P1611 die Kondensatoren C4 und C5 am 32kHz Quartz ausgelötet habe, hat der ACLK an P5.6 eine Periodendauer von ca. 30µs. Am XOUT messe ich trotzdem kein Signal, ich vermute es liegt an meinem Messequipment. Zu den Interrupt Routinen hatte ich mit mit msp430-objdump -DS main > asm.lst das assembler listing ausgeben lassen. Am Ende des Listings finde ich folgendes: ------------------------------------------------------------------------ --- Disassembly of section .vectors: 0000ffe0 <_vectors_end-0x20>: ffe0: 5a 40 interrupt service routine at 0x405a ffe2: 60 40 interrupt service routine at 0x4060 ffe4: 66 40 interrupt service routine at 0x4066 ffe6: 6c 40 interrupt service routine at 0x406c ffe8: 72 40 interrupt service routine at 0x4072 ffea: 78 40 interrupt service routine at 0x4078 ffec: 7e 40 interrupt service routine at 0x407e ffee: 82 40 interrupt service routine at 0x4082 fff0: 88 40 interrupt service routine at 0x4088 fff2: 8e 40 interrupt service routine at 0x408e fff4: 94 40 interrupt service routine at 0x4094 fff6: 9a 40 interrupt service routine at 0x409a fff8: a0 40 interrupt service routine at 0x40a0 fffa: a4 40 interrupt service routine at 0x40a4 fffc: 00 40 interrupt service routine at 0x4000 fffe: 00 40 interrupt service routine at 0x4000 ------------------------------------------------------------------------ --- So ähnlich hatte ich das schon einmal gepostet. Beim RESET und dem RST/NMI Interrupt wird zur Adresse 0x4000 gesprungen, die anderen ISR sind an den entsprechenden Adressen definiert. Nächster Schritt: LPT1 freigeben: modprobe ppdev chmod 666 /dev/parport0 gdb-proxy starten: msp430-gdbproxy --port=2000 msp430 ddd Debugger starten: ddd --debugger msp430-gdbproxy Im ddd mit dem Button "connect" debugger und CPU verbinden. Programm flashen mit load main symbol-file main PC steht dann auf 0x4000, SP ist auf 0x3900 initialisiert. Dann mit disassemble 0xffe0 0xffff den Speicherbereich des MSP430F1611 angezeigt, an dem die Sprungadressen zu den ISRs sind. Das hoffe ich zumindest :-). Folgendes Resultat: (gdb) disassemble 0xffe0 0xffff Dump of assembler code from 0xffe0 to 0xffff: 0x0000ffe0: interrupt service routine at 0xffff 0x0000ffe2: interrupt service routine at 0xffff 0x0000ffe4: interrupt service routine at 0xffff 0x0000ffe6: interrupt service routine at 0xffff 0x0000ffe8: interrupt service routine at 0xffff 0x0000ffea: interrupt service routine at 0xffff 0x0000ffec: interrupt service routine at 0xffff 0x0000ffee: interrupt service routine at 0xffff 0x0000fff0: interrupt service routine at 0xffff 0x0000fff2: interrupt service routine at 0xffff 0x0000fff4: interrupt service routine at 0xffff 0x0000fff6: interrupt service routine at 0xffff 0x0000fff8: interrupt service routine at 0xffff 0x0000fffa: interrupt service routine at 0xffff 0x0000fffc: interrupt service routine at 0xffff 0x0000fffe: interrupt service routine at 0xffff End of assembler dump. (gdb) Deswegen kommt die CPU nach einem RESET nicht in die Pötte, weil sofort nach einem RESET an 0xffff gesprungen wird, oder verstehe ich das wieder falsch? Woran könnte das liegen? Stephan
Hurra! Jetzt geht es, ich habe nach dem laden des Programms in die CPU mit dem debugger die Speicheradressen nachträglich geändert und zwar folgendermassen: (gdb) set *0xfffe = 0x4000 (gdb) set *0xfffc = 0x4000 (gdb) set *0xffec = 0x4084 (gdb) disassemble 0xffe0 0xffff Dump of assembler code from 0xffe0 to 0xffff: 0x0000ffe0: interrupt service routine at 0xffff 0x0000ffe2: interrupt service routine at 0xffff 0x0000ffe4: interrupt service routine at 0xffff 0x0000ffe6: interrupt service routine at 0xffff 0x0000ffe8: interrupt service routine at 0xffff 0x0000ffea: interrupt service routine at 0xffff 0x0000ffec: interrupt service routine at 0x4084 0x0000ffee: interrupt service routine at 0xffff 0x0000fff0: interrupt service routine at 0xffff 0x0000fff2: interrupt service routine at 0xffff 0x0000fff4: interrupt service routine at 0xffff 0x0000fff6: interrupt service routine at 0xffff 0x0000fff8: interrupt service routine at 0xffff 0x0000fffa: interrupt service routine at 0xffff 0x0000fffc: interrupt service routine at 0x4000 0x0000fffe: interrupt service routine at 0x4000 End of assembler dump. (gdb) c Continuing. Jetzt geht es! Nun muss ich herausfinden, warum in meinem object file die Interruptvektortabelle richtig ist, aber nicht richtig in die CPU geladen wird. Habt ihr vielleicht schon eine Idee? Gruß Stephan
>Hurra! Na also :-) >Nachdem ich auf dem Olimex-Board MSP430-P1611 die Kondensatoren C4 und >C5 am 32kHz Quartz ausgelötet habe Ich weiß nicht, was Olimex sich da gedacht hat, C4 und C5 zu bestücken? Die sind eigentlich nur dann vorzusehen, falls man anstelle von Q1 (32kHZ) den Q2 (HF-Quarz) bestückt!
1 | >Disassembly of section .vectors: |
2 | >0000ffe0 <_vectors_end-0x20>: |
3 | > ... |
4 | > ffec: 7e 40 interrupt service routine at 0x407e |
Wieso auf einmal 0x407E und nicht 0x4084 ?
1 | >(gdb) disassemble 0xffe0 0xffff |
2 | >Dump of assembler code from 0xffe0 to 0xffff: |
3 | >0x0000ffe0: interrupt service routine at 0xffff |
4 | ...
|
>Deswegen kommt die CPU nach einem RESET nicht in die Pötte, weil sofort >nach einem RESET an 0xffff gesprungen wird, oder verstehe ich das wieder >falsch? Woran könnte das liegen? Das kann jetzt auch nicht sein, denn wenn der µC direkt nach dem Reset nach 0xFFFF hüpft, schmiert er ab oder macht 'nen Endlos-Reset. Dann würde aber niemals Deine Init-Routine ausgeführt werden, die die Clocks setzt und P5.4 und P5.6, wodurch Du ja ACLK und MCLK messen kannst! Vielleicht nimmt er tatsächlich die Adresse 0x407E anstelle von 0x4084 (s.oben) und hängt sich dann auf? >Nun muss ich herausfinden, warum in meinem object file >die Interruptvektortabelle richtig ist, aber nicht richtig in die CPU >geladen wird. Habt ihr vielleicht schon eine Idee? Nee, leider nicht! Vielleicht im GCC-Forum mal die Spezialisten über Deine Tools ausfragen? Warum benutzt Du nicht die freie IAR-Kickstart Entwicklungsumgebung? C-Code Beschränkung 2 oder 4k, Assembler unbegrenzt. Habe damit bislang persönlich sehr gute Erfahrungen gemacht!
>>Deswegen kommt die CPU nach einem RESET nicht in die Pötte, weil sofort >>nach einem RESET an 0xffff gesprungen wird, oder verstehe ich das wieder >>falsch? Woran könnte das liegen? >Das kann jetzt auch nicht sein, denn wenn der µC direkt nach dem Reset >nach 0xFFFF hüpft, schmiert er ab oder macht 'nen Endlos-Reset. >Dann würde aber niemals Deine Init-Routine ausgeführt werden, die die >Clocks setzt und P5.4 und P5.6, wodurch Du ja ACLK und MCLK messen >kannst! >Vielleicht nimmt er tatsächlich die Adresse 0x407E anstelle von 0x4084 >(s.oben) und hängt sich dann auf? Der µC ist auch sofort abgestürzt und nicht in die Setup-Routine gegangen etc., wenn ich ihn ohne debugger geflasht und gestartet habe mit msp430-jtag -e main von der Commandozeile. Das steppen ging nur im debugger. Nach dem Verbinden des debuggers mit der CPU (Button Connect) stand der PC immer auf 0xffff. Den habe ich dann mit set $pc=0x4000 auf die Setup-Routine gesetzt und konnte anschließend steppen. Beim schrittweisen steppen sind nie Interrupts aufgetreten, warum weiß ich auch nicht. Sobald ich aber den µC mit dem Befehl continue "von der Leine" gelassen habe ist er abgeschmiert. Dann war nach kurzer Zeit der MCLK weg, wie gesagt. Jetzt wo ich die ISR-Sprungvektoren manuell geändert habe, steht der µC nach dem Connect im Debugger sofort auf 0x4000! Wenn ich jetzt steppe, treten immer noch keine Interrupts auf. Er läuft jetzt aber im Continue, un auch, wenn ich den JTAG stecker vom board ziehe! Bezüglich 0x407e und 0x4084: Da habe ich wahrscheinlich das assembler listing von meinem Programm erwischt, bei dem ich einige Zeilen in Mainloop auskommentiert habe. Ich habe die Zeilen wieder einkommentiert und überprüft. An Adresse 0xffec steht die Sprungadresse 0x4084, die ISR für den TIMERA Interrupt befindet sich an 0x4084. Habe ich beides mit disassemble überprüft, und nicht etwa im object file ;-))) >Warum benutzt Du nicht die freie IAR-Kickstart Entwicklungsumgebung? >C-Code Beschränkung 2 oder 4k, Assembler unbegrenzt. Die läuft nur unter Windows, oder? Ich hatte mir vorgenommen, unter Linux zu entwickeln. Sicher würde mir die IAR IDE so manchen Albtraum wie den letzten ersparen. Mal sehen!
Oder Eclipse + MSPGCC-Plugin, das sollte auch unter Linux gehn. Oder bist du so ein Kommandozeilen-Fetischist? ;)
>Ich hatte mir vorgenommen, unter Linux zu entwickeln.
Linux wird überbewertet ;-)
Linux oder Windows, hin oder her, beides hat Vor und Nachteile... bevor an dieser Stelle große Diskussionen über das richtige Betriebssystem losbrechen :-) möchte ich Euch für Eure tatkräftige Unterstützung danken. Ihr habt mir sehr weitergeholfen! Ich werde mich mal an das gcc Forum wenden, was evtl. mit dem debugger oder meinen object files nicht stimmt. Wie gesagt, es wird nicht beim Toggeln der LED bleiben.... :-) Also bis bald! Gruß Stephan
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.