Forum: Mikrocontroller und Digitale Elektronik LPC2368: RTC löst dauernd IRQ aus


von Christian J. (elektroniker1968)


Lesenswert?

Hallo,

vielleicht sollte ich doch einen Sammelthread aufmachen....

Ich möchte einfach nur jede Minute durch die RTC im LPC2368 einen IRQ 
auslösen. Die IRQs werden auch ausgelöst aber dauernd, d.h. der uC ist 
sofort nach Verlassen der ISR wieder drin, hat kaum für was anderes 
Zeit. Die LEDS flimmern beide gleichmässig, statt jede Minute zu 
wechseln.

Dabei lösche ich doch die IRQ Anforderung
RTC_ILR  |= RTC_ILR_RTCCIF;     // 1= RTC IRQ Flags
in der ISR.

Mir fällt nichts mehr ein, habe das Keil Beispiel studiert, das sieht 
genauso aus wie meines. Das  __ARMLIB_enableIRQ() ist übrigens nur ein 
Makro für Rowley Programme, ähnliche dem IEENABLE bei Keil. 
VECTORED_IRQ_INTERRUPTS habe ich im Präprozessor auch definiert, sonst 
läuft die ISR gar nicht.

Der Aufruf
1
 Init_RTC();
2
 Init_RTC_ISR(RTC_CIIR_IMMIN);
3
 __ARMLIB_enableIRQ();


Hier der Code
1
void Init_RTC()
2
{
3
  RTC_CCR = 0;         // RTC ausschalten
4
  PCONP    |=  (1 << 9);   // RTC mit Strom versorgen
5
  RTC_AMR  = 0xff;       // Alle Alarms deaktivieren
6
  RTC_CIIR  = 0;       // Alle IRQs aus
7
8
  // Die RTC starten und auf 32khz Quarz legen
9
  RTC_CCR |= (1<<CCR_CLKSRC_BIT);
10
  RTC_CCR |= (1<<CCR_CLKEN_BIT) ;
11
}
12
13
14
// ISR installieren (mode, s. header file)
15
BOOL Init_RTC_ISR(uint8_t mode)
16
{
17
18
  RTC_ILR &= ~(1 << RTC_ILR_RTCCIF);  // Lösche das RTC_ILR, pending IRQ's
19
  RTC_CIIR  = mode;            // Setze 1s IRQ Auslösung, alle anderen Bits = 0
20
21
  // Installiere die ISR
22
23
/* alternativer Code statt Keil, läuft auch
24
  VICVectAddr13 = (uint32_t)&RTC_ISR;
25
  VICIntEnable = 1 << RTC_INT;
26
*/
27
28
  if ((Install_irq (RTC_INT, (void*)RTC_ISR,LOWEST_PRIORITY)) == FALSE)
29
  return FALSE;
30
31
  return TRUE;
32
33
}

Die ISR
1
/ Die ISR der RTC
2
void __attribute__ ((interrupt("IRQ"))) RTC_ISR (void)
3
{
4
  static char sw = 0;
5
6
  if (sw == 0)  {
7
  LED1_ON();
8
  LED2_OFF();
9
    sw  = 1;
10
  }
11
  else if (sw == 1)
12
  {
13
  LED1_OFF();
14
  LED2_ON();
15
  sw = 0;
16
  }
17
18
  RTC_ILR  |= RTC_ILR_RTCCIF;     // 1= RTC IRQ Flags löschen
19
  VICVectAddr = 0;         // IRQ löschen
20
21
}

Die Defines
1
#define RTC_ILR_RTCCIF    0x01      //ILR Register, Bit für pending IRQs der Uhr
2
3
// RTC: Counter Increment IRQ Register Bits
4
#define RTC_CIIR_IMSEC    0x00000001
5
#define RTC_CIIR_IMMIN    0x00000002
6
#define RTC_CIIR_IMHOUR    0x00000004
7
#define RTC_CIIR_IMDOM    0x00000008
8
#define RTC_CIIR_IMDOW    0x00000010
9
#define RTC_CIIR_IMDOY    0x00000020
10
#define RTC_CIIR_IMMON    0x00000040
11
#define RTC_CIIR_IMYEAR    0x00000080

von Christian J. (elektroniker1968)


Lesenswert?

Hinweis:

Das Blinken funktioniert, wenn ich in der ISR das IF Flag abfrage und 
nur dann die LEDS ansteuere

if (RTC_ILR & (1<<RTC_ILR_RTCALF))

Leider nütztt das nur wenig, weil die ISR nach wie vor dauernd 
aufgerufen wird und ich nicht weiss warum. Testweise habe ich auch die 
Zeile eingefügt.

RTC_ILR  |= (1<<RTC_ILR_RTCCIF) | (1<<RTC_ILR_RTCALF) | 
(1<<RTC_ILR_RTSSF);

die alle IRQ Quellen der RTC zurücksetzt (1=IRQ löschen)

Ratlos.....

von Kai F. (k-ozz)


Lesenswert?

Ich glaube, du würfelst in deiner Notation etwas durcheinander.
Du hast folgendes Define gemacht:
1
#define RTC_ILR_RTCCIF    0x01      //ILR Register, Bit für pending IRQs der Uhr
Dann verwendest du dieses Define aber für ein Shift-Befehl.
Wenn du nun aber (1 << RTC_ILR_RTCCIF) schreibst, dann kommt doch 0x02 
raus!? Das willst du aber eigentlich nicht!
Noch ein anderes "Problem". Die Schreibweise RTC_ILR |= xxx bzw. RTC_ILR 
&= xxx ist unnötig, da Bits in dem Register nur gelöscht werden, wenn 
man 1en (Einsen) schreibt. In deiner ISR solltest du also einfach 
schreiben:
1
RTC_ILR = RTC_ILR_RTCCIF;

Zur Sicherheit solltest du evtl. in der ISR alle anliegenden Interrupts 
löschen, d.h. folgendes schreiben:
1
RTC_ILR = (RTC_ILR_RTCCIF | RTC_ILR_RTCALF | RTC_ILR_RTSSF);

Der schuldige dürfte bei dir wohl der Sub-Second Interrupt sein:
füge mal folgendes in deine Init_RTC_ISR ein:
1
RTC_CISS = 0x00;
Damit wird der Sub-Second Interrupt deaktiviert.

von Christian J. (elektroniker1968)


Lesenswert?

Hallo Kai,

der "Schuldige" war der Sub Second IRQ, weil der bei Reset undefiniert 
ist.
(Das weiss man aber auch nur, wenn  mal mal in die Falle reingelaufen 
ist)
Habe ich auch erst herausgefunden als ich mir mal das ILR Register im 
Debugfenster angeschaut habe. Natürlich auch das was Du bemerkt hast.

Ich habe aber noch eine "doofe"  Frage:

Vom PIC her bin ich es gewohnt zu sparen, d.h. Flags kriegen nur ein Bit 
spendiert in einem Byte. Das geht bei dem CCS Compiler, da er den Typ 
bit kennt. Nun lese ich aber immer wieder dass selbst Flags mit uint32_t 
oder unsigned long definiert werden. d.h. sie knallen ganze 32 Bit weg.

Manche RTC Register scheinen nur 8 Bit zu haben, andere 32 Bit. Oder 
haben alle 32 Bit? Oft sieht man ja : Bit 15:32 undefined oder so. Aber 
eben nicht beim IRL; das wird zB als 4 Bit register beschrieben.

Wie adressiert der ARM7 denn nun besser? Wenn ich uint8 für ein kleine 
Zahl nehme oder uint32?

Das Battery RAM wird beschrieben dass es nur 32 Bitr adressierbar ist 
mit "Alignment = 4". Dh. kann man dort gar keine Bytes speichern sondern 
nur uint32.

PS: Spezi Frage: Hat schonmal jemand versuche die RTC genau zu stellen? 
Uhr daneben, Debugger an, los bei genauer Zeit und Debugger wieder 
stoppen. Da der Wiggler ständig resettet, auch wenn man das Debuggen 
abbricht wird die Set Routine auch immer wieder neu durchlaufen und die 
Zeit wieder verstellt bis man den Set Befehl auskommentiert hat. Einzige 
Chance die ich hatte war eine Variable im Battrery Ram anzulegen und die 
nach dem Setzen der Zeit zu verstellen, dass das Setzen nicht erneut 
durchlaufen wird....


Gruss,
Christian

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.