Forum: Mikrocontroller und Digitale Elektronik MSP430F1611 TimerA Interrupt Problem


von Stephan Bode (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

>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!!!)

von Stephan Bode (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Stefan (Gast)


Lesenswert?

>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.

von Stephan Bode (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Stefan (Gast)


Lesenswert?

>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... ;-)

von Stefan (Gast)


Lesenswert?

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...???!!!

von Stephan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

>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

von Stefan (Gast)


Lesenswert?

>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

von Falk B. (falk)


Lesenswert?

@ 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

von Stephan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

>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!

von Stephan (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@ 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

von Stefan (Gast)


Lesenswert?

Ich würd ja mal C4 und C5 raushaun!

von Stephan (Gast)


Lesenswert?

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

von Stephan (Gast)


Lesenswert?

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

von Stefan (Gast)


Lesenswert?

>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!

von Stephan (Gast)


Lesenswert?

>>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!

von Christian R. (supachris)


Lesenswert?

Oder Eclipse + MSPGCC-Plugin, das sollte auch unter Linux gehn. Oder 
bist du so ein Kommandozeilen-Fetischist? ;)

von Stefan (Gast)


Lesenswert?

>Ich hatte mir vorgenommen, unter Linux zu entwickeln.
Linux wird überbewertet ;-)

von Stephan (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.