Forum: Mikrocontroller und Digitale Elektronik Interrupts beim ARM ( LPC2106 ) in C


von Armin Strobel (Gast)


Lesenswert?

Hallo,

ich hab folgendes Problem:

Ich möchte mit Cap1... PWM-Signale auswerten. Mir ist bisher eigentlich
fast klar was ich in welches regsiter zu schreiben hab, daß es
fuktioniert. Bisher hab ich nur in Assembler programmiert. Ich bin
bisher über einige C-Biblitheken gestolpert, aber die waren bisher nur
sehr schwer verwenden und sehr unvollständig. Kann mir da jemand
weiterhelfe?
P.S. fals es im text nicht ganz klar wurde ich möchte das in C
programieren.
Danke

von Ppp M. (sanic)


Lesenswert?

Hast du denn schon einmal generell Interrupts zum Laufen bekommen ?
Siehe auch:
http://www.mikrocontroller.net/articles/ARM-elf-GCC-Tutorial

von Armin Strobel (Gast)


Lesenswert?

Nein ich hab bisher noch kein Interrupt zum laufen gebracht, genau das
ist ja mein Problem. Klar hab ich mir das ARM-elf-GCC-Tutorial
angeschaut. Mir ist nur nicht klar wie ich C beibringen soll was es bei
dem interrupt machen soll. Hab bisher schon erfolgreich einige AVR
Programme in Assembler und ein paar wenige in C geschrieben. Mir ist
auch klar wie ich ihm beibringe bei welchen ereignissen er ein
Interrupt auslösen soll. Ich weiß nur nicht wie ich ihm beibringe was
er dann zu tuen hat.
Beim AVR:
void interrupt(....)
{.....
...
}

Beim ARM:
???

Kann mit dem folgendem nicht viel Anfangen:

void _attribute_ ((interrupt("IRQ"))) isr(void); // Prototyp

void _attribute_ ((interrupt("IRQ"))) isr(void){
  // A lot of Work
  VICVectAddr = 0;       // Acknowledge Interrupt
}

Bräuchte lediglich mal ein Beispielprogramm mit einer vernünftigen Lib.

von Ppp M. (sanic)


Lesenswert?

void _attribute_ ((interrupt("IRQ"))) isr(void){ }

Dies ist die Deklaration der Interrupt Service Routine.
Hier kommen deine Instruktionen rein, die beim jeweiligen Interrupt
ausgeführt werden. Wie du einen Interrupt angibst ist auch im
Tutorial.
Einen Timer Interrupt Code kann ich morgen mal posten. Der lässt eine
LED toggeln im 1 sek Abstand (bei 14,7456 Quarz x4 PLL = 58,xx MHz).

Grüße

von Lupin (Gast)


Lesenswert?

Ich glaube du solltest vorher auch die IRQs im CPU register aktivieren:

void enableIRQ(void) {
  asm volatile (
    "mrs  r0, cpsr\n"
    "and  r0, r0, #~0x00000080 \n"
    "msr  cpsr, r0\n"
  );
}


Lad dir mal WinARM runter und schau im examples ordner nach
"lpc2106_blink_switch_irq" da wird gezeigt wie man einen Timer mit
IRQ benutzt.

von Armin Strobel (Gast)


Lesenswert?

Erstmal danke an euch!

Hab ich doch alles schon längst gemacht.
lpc2106_blink_switch_irq ist ein sau dämliches Beispiel ( sorry für die
ausdrucksweise ).
Lest doch mal meine Frage genau durch.
Das mit dem IRQ aktivieren ist alles kein problem.

Nur leider weden die Interrupts in jder lib anderst benannt.

Hat niemand ein beispiel mit einem externen interrupt?

von Lupin (Gast)


Lesenswert?

Aber die werden doch immer ungefähr gleich benannt, oder?

Warum ist das beispiel denn so dämlich? wird da irgendwas falsch
gemacht?

von Ppp M. (sanic)


Lesenswert?

"Nur leider weden die Interrupts in jder lib anderst benannt."
Es ist egal wie die ISR heißt, du übergibst ja eh nur die Adresse in
ein Adresse des VICs.

Morgen gibt´s Code, ich hoffe das ist dann ausreichend ;)

Grüße

von Ppp M. (sanic)


Lesenswert?

Hier der versprochene Code:

#include <arch/philips/lpc2114.h>
#include <stdlib.h>
#include "armVIC.h"

#define VIC_TIMER1 5

volatile unsigned char stat;

void init_MCU(void);
void _attribute_ ((interrupt("IRQ"))) timer1(void);

void init_MCU(void){
  //PLL Multiplier
  SCB_PLLCFG = 4-1; // Multiplier auf 4x
  SCB_PLLCON = 0x01; // PLLE Set
  SCB_PLLFEED = 0xAA;  //PLL Feed Sequence
  SCB_PLLFEED = 0x55;
  while ( !( SCB_PLLSTAT & (1<<10) ) ); // PLOCK testen
  SCB_PLLCON = 0x03; // PLLC & PLLE Set
  SCB_PLLFEED=0xAA;  //PLL Feed Sequence
  SCB_PLLFEED=0x55;

  //Memory Accelerator Module
  MAM_MAMCR = 0;
  MAM_MAMTIM = 3; // MAM-Fetch cycle to 3 cclk (>40MHz)
  MAM_MAMCR = 2; // MAM fully enabled -> See Page 75 in the Datasheet

  //Pheriphal Bus
  SCB_VPBDIV = 1; //VPB Divider = 1

  PCB_PINSEL1 = 0x00; // All Pins has to be I/O Ports
}

void _attribute_ ((interrupt("IRQ"))) timer1(void){
  T1_IR = 1; // Clear interrupt flag by writing 1 to Bit 0
  if (stat == 0){
    GPIO0_IOSET=(1<<25);
  }else{
    GPIO0_IOCLR=(1<<25);
    stat = !stat;
  }
  VICVectAddr = 0;       // Acknowledge Interrupt
}

int main (void){
  GPIO0_IODIR|=(1<<28)|(1<<25);
  init_MCU();
  SCB_MEMMAP = 1;  //interrupt vectors reside in flash
  T1_PR=64; // Prescaler für Timer1
  T1_MR0=921600L-1; // Match every Second on 14,7456 * 4x PLL
  T1_MCR=3; // Interrupt on MR0 and RESET MR0 on Match
  T1_TCR=1; // Start Timer1

  VICIntEnClear = 0xFFFFFFFF;
  VICIntSelect = 0x00000000;
  VICVectAddr0=(unsigned long)timer1;
  VICVectCntl0=(1<<5) | VIC_TIMER1;
  VICIntEnable=(1<<VIC_TIMER1);
  enableIRQ();
}

Dieses Programm lässt eine LED toggeln die an Port0.25 angeschlossen
ist.

Grüße

von Ppp M. (sanic)


Lesenswert?

Fast vergessen:
die armVIC.c/.h gibt´s in den WinARM Examples irgendwo ;-)

Grüße

von Lupin (Gast)


Lesenswert?

Das solltest du so, oder so ähnlich ins wiki stellen, bis auf die CCO
frequenz ist das gut ;)

von Ppp M. (sanic)


Lesenswert?

Ja Ja, die CCO Frequenz ;)
Da muss ich nachher nochmal gucken.

von mthomas (Gast)


Lesenswert?

Heheh, "sau daemlich" ist gut. Vielleicht erstmal die C-Kentnisse
vertiefen, das Manual des gcc durchlesen (zumindest den Abschnitt
function attributes) sowie den Abschnitt zum VIC im LPC-Datenblatt
lesen und auch zumindest halbwegs nachvollziehen bevor man hier
Formulierungen wie "Lest doch mal meine Frage genau durch" oder
"habe ich schon laengst gemacht" (woher soll man das wissen) oder
"sau daemlich" abwirft.

Habe mir das "sau daemliche" Beispiel grade nochmal angeschaut, mir
faellt auf Anhieb nicht ein, wie man die notwendigen Einstellungen fuer
"was es bei dem interrupt machen soll" simpler demonstrieren kann.
Verbessungsvorschlaege dafuer sind natuerlich willkommen.
Implementierung der ISR und Einstellung der Adresse im VIC sind bei
externem Interrupt im Prinzip genau so wie in dem "daemlichen"
Beispiel.

Von welchen "libs" die Rede ist bleibt offen, vermute mal, es handelt
sich um die verschiedenen SFR-Defintionsdateien, aber "libs" sind das
nicht.

Martin Thomas - derjenige, der das "sau daemliche" Beispiel
herausgegeben hat.

von Ppp M. (sanic)


Lesenswert?

Echt Martin,
mach mal nicht so dämliche Beispiele!
Woher soll man denn wissen was der Controller in der ISR machen soll?
Unmöglich von dir ;-)

Grüße

von Armin Strobel (Gast)


Lesenswert?

Ups da bin ich wohl jemandem auf die Füße getreten. :-)
War da nur etwas geladen.
Für einen C-Anfänger wie mich ist das nicht gerade einfach zu
verstehen.
Sorry aber das obilge Beispiel find ich etwas anschaulicher.
(Geschmacksache)

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.