Forum: Mikrocontroller und Digitale Elektronik M16C62P Timer Interrupt


von Lunarfur (Gast)


Lesenswert?

Hallo,
ich bin absoluter Neuling was µCs angeht, und versuche anhand eines 
Evaluation Boards den M16C62P von Renesas kennen zu lernen.
Als IDE benutze ich den mitgelieferten HEW (4.02). Da die Anleitung vom 
EVB eher mager ist, versuche ich mich anhand des Tutorials von Prof. 
Brett Ninness (http://sigpromu.org/brett/elec3730/m16c_tut2.pdf) mit den 
verschiedenen Funktionen vertraut zu machen. (Habe nur port init 
verändert und die den Inhalt der if-schleife der interrupt fkt. 
verändert, da ich nur 4LEDs aber kein Display habe)
 Nachdem ich nun seit zwei Tagen keinen Timer Interrupt bekomme, frag 
ich mich, was ich falsch mache oder etwas vergesse:
ncrt30.a30 (Auszug)
1
mov.b  #03h,0ah  ;enable PRC1 and PRC0 bits
2
mov.b  #00h,04h  ;set processor mode 
3
mov.b  #08h,06h  ;set to no division mode on main clock
4
mov.b  #20h,07h  ;
5
mov.b  #00h,0ah  ;disable PRC1 and PRC0 bits
6
...
7
fset I
------
sample2.c
1
#pragma INTERRUPT TimerA0int
2
void TimerA0int(void)
3
{"lass LEDs an Port4 blinken"} //sind auch initialisiert
Timer initialisiert mit:
1
ta0mr = 0x80; //f32
2
ta0 = 0x7A11; //10Mhz-Quarz auf EVB -> soll 10Hz
3
ta0ic = 0x01; //priority lvl=1
4
tabsr |= 0x01; //starten

-> sect30.inc
1
.glb _TimerA0int
2
.lword _TimerA0int

Hab zusätzlich noch ein paar Ports (p4_0-p4_3) mit LEDs die bei 
interuppt blinken sollten.

Wenn ich debugge, ich hab ein Breakpoint in der Interrupt-Fkt., komme 
ich dort niemals hin..
Hab ich etwas wesentliches vergessen?

Dank im Voraus
Lunarfur

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Deine Angaben zu Quellcode sind unzureichend. Insbesondere interessiert, 
wie die Datei sect30.inc aussieht - das ist die Datei, in der die 
Interruptvektor-Tabelle angelegt ist. Fehlt deine Interruptroutine dort, 
wird sie nie angesprungen (s. 2. Inserting an ISR into the Interrupt 
Vector Table im o.g. Tutorial)

von Lunarfur (Gast)


Lesenswert?

Hi, erstmal danke für die Antwort. Hatte ich doch geschrieben:

> -> sect30.inc
> .glb _TimerA0int
> .lword _TimerA0int

um genau zu sein
1
.lword  dummy_int  ; vector 20  (for user) uart1 receive
2
.glb    _TimerA0int     ; declare reference for TimerA0int interrupt
3
.lword  _TimerA0int     ; vector 21  (for user) timer A0
4
;.lword  dummy_int  ; vector 21  (for user) timer A0

Habe das Forum nochmal durchsucht, aber auch der Zielprozessor ist 
korrekt ausgewählt.
Auch wenn ich nicht debugge, sondern flashe und dann resette passiert 
nichts.

von Lunarfur (Gast)


Lesenswert?

Vielleicht nochmal genauer

In meiner C-Datei:
1
#include "sfr62p.h"
2
3
void main(void);
4
void initport(void);
5
void initTimerA0(void);
6
void startTimerA0(void);
7
void setTimerA0int(void);
8
void TimerA0int(void);
9
10
#pragma INTERRUPT TimerA0int //#pragma INTERRUPT -> use function as ISR (Interrup Service Routine)
11
void TimerA0int(void)
12
{
13
    static unsigned char one_hundred_msec_count = 0;
14
    static unsigned char seconds = 0;
15
    
16
    asm("fset I");  //enable interrupts
17
    
18
    one_hundred_msec_count++;
19
    if (one_hundred_msec_count > 9)
20
    { p4_1=(~p4_1);
21
    
22
        seconds++;
23
        switch(seconds){
24
            case 10: p4=0x00;
25
            break;
26
            case 9: p4=0x01;
27
            break;
28
            case 8: p4=0x02;
29
            break;
30
            case 7: p4=0x03;
31
            break;
32
            case 6: p4=0x05;
33
            break;
34
            case 5: p4=0x06;
35
            break;
36
            case 4: p4=0x07;
37
            break;
38
            case 3: p4=0x08;
39
            break;
40
            case 2: p4=0x0B;
41
            break;
42
            case 1: p4=0x0D;
43
            break;
44
            case 0: p4=0x0F;
45
            break;
46
            default:seconds=0;
47
            p4=0x0F;
48
         
49
        }
50
        one_hundred_msec_count = 0;
51
    }
52
}
53
54
void main(void)
55
{
56
    //initialise ports for LED
57
    initport();
58
    //init TimerA0, 
59
    asm("FCLR I");  //disable interrupts
60
    initTimerA0();
61
    //set timer interrupt 
62
    setTimerA0int();
63
    //start timer 
64
    startTimerA0();
65
    asm("FSET I"); //enable interrupt 
66
    //anything else
67
    while(1);  
68
    
69
}
70
71
void initport(void)
72
{
73
    int i;
74
    pd4=0xFF; //all lines = output
75
    p4=0x00; //all LEDs on (inverted logic)
76
    for(i=0;i<25000;i++); //wait to make visible for the eye
77
    p4=0xFF; //LEDs off
78
}
79
80
void initTimerA0(void)
81
{
82
    //select timer mode
83
    ta0mr = 0x80;           // XX?0 0000 (Hardware Manual, REJ09B0185-0241, p. 145)
84
                            // |||| |||+- timer operation mode select bit
85
                            // |||| ||+-- timer operation mode select bit
86
                            //            00:  timer mode
87
                            //            01:  event counter mode
88
                            //            10:  one-shot timer mode
89
                            //            11:  PWM mode
90
                            // |||| |+--- set MR0 = 0 in timer mode
91
                            // |||| +---- set MR1 = 0 in timer mode
92
                            // |||+------ MR2 must always be 0 in timer mode
93
                            // ||+------- MR3 ???
94
                            // |+-------- count source select bits:
95
                            // +--------- count source select bits:
96
                            //            00:  f1 or f2
97
                            //            01:  f8
98
                            //            10:  f32
99
                            //            11:  fc32
100
    ta0 = 0xFFFF;
101
    //ta0 = 0x7A11; //Divide Count Source by n+1 (Q1:10Mhz/32=312,5kHz) for T=100ms -> n=3124+1
102
}
103
104
void setTimerA0int(void)
105
{
106
    ta0ic = 0x01;           // ---- XXXX    (Hardware Manual, REJ09B0185-0241, p.111)
107
                            //      ||||
108
                            //      |||+-- Interupt priority level select bit
109
                            //      ||+--- Interupt priority level select bit
110
                            //      |+---- Interupt priority level select bit
111
                            //      |      000: Level 0 (interrupt disabled)
112
                            //      |      001: Level 1
113
                            //      |      010: Level 2
114
                            //      |      011: Level 3
115
                            //      |      100: Level 4
116
                            //      |      101: Level 5
117
                            //      |      110: Level 6
118
                            //      |      111: Level 7
119
                            //      +----- Interupt request bit 
120
                            //             0: Interrupt not requested
121
                            //             1: Interrupt requested
122
}
123
124
void startTimerA0(void)
125
{
126
    //Add Timer A0 to CounterStartFlag (OR!)
127
    tabsr |= 0x01;          // ---- XXXX XXXX    (Hardware Manual, REJ09B0185-0241, p.141)
128
                            //      |||| ||||
129
                            //      |||| |||+ Timer A0 Count Start Flag (0:Stop, 1:Start)
130
                            //      |||| ||+- Timer A1 Count Start Flag 
131
                            //      ...  .+-- Timer A2 ...
132
    //alternatively set single bit:
133
    //ta0s=1; // 1: start timer A0 (count flag)
134
}

ncrt0.a30
1
start:
2
;---------------------------------------------------------------------
3
; after reset,this program will start
4
;---------------------------------------------------------------------
5
    ldc      #istack_top,isp      ;set istack pointer
6
    mov.b    #03h,0ah                ;enable PRC1 and PRC0 bits (disable write protection)
7
    mov.b    #00h,04h        ;set processer mode 
8
    mov.b      #08h,06h            ;set to no division mode on main clock
9
    mov.b    #00h,0ah                ;enabele wirte protection
10
11
.if __STACKSIZE__ != 0
12
    ldc      #0080h,flg
13
    ldc      #stack_top,sp      ;set stack pointer 
14
.else
15
    ldc      #0000h,flg
16
.endif
17
    ldc      #data_SE_top,sb      ;set sb register 
18
    ldintb   #__VECTOR_ADR__

sect30.inc wie vorher beschrieben... (ohne if in der vector section)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Es muss sichergestellt sein, dass der Vektor in der Tabelle an der 
richtigen Position steht. In der ersten Fassung sah ich das nicht. Der 
zweite Ausschnitt sieht OK aus.

Vorsicht bei dem Flashen, wenn sec30.inc nicht 101%ig richtig ist. Ein 
Vektor zuviel drin z.B. durch ein vergessenes Auskommentieren des 
entsprechenden dummy_ints und man kann sich aus dem M16C (und R8C) 
aussperren.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

In dem ausführlichen Code sehe ich keine Probleme. Bin ratlos.

von Lunarfur (Gast)


Lesenswert?

Das flashen geht, was ich daran sehe, dass er nach einem Reset die LEDSs 
kurz aufblinke lässt, also initport() wird auf jeden Fall ausgeführt.

von Lunarfur (Gast)


Lesenswert?

Ich weiß nicht woran es jetzt liegt, aber es funktioniert, nachdem ich 
ein Demo-Programm geladen habe, jetzt geht auch mein Code.
Was ich beim weiteren Stöbern gelernt habe, und evtl. anderen helfen 
kann:
Vergesst nicht den Assemblerbefehl fset I um das Interrupt Flag zu 
setzen.

Woran es auch gelegen haben könnte: Denkt bei der Einrichtung des 
Prozessormodes sowie der System Clock, dass das jeweilige Protection Bit 
auf 1 gesetzt wird, bevor ihr die Register setzt, sonst könnte es sein, 
dass ihr mit dem default nur 1/8 der CPU-Frequenz arbeitet und unter 
Umständen einfach nur auf das Interrupt so lange warten müsst.

Grüße
Lunarfur

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.