mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AT91SAM7S mit zwei aktivien interrupts


Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
programmiere AT91SAM7S mit Eclipse.
die DBGU benutzt interrupt, so wie PWM-ausgabe, und der PIT.
benutze z.b. folgende initialisierung:
 AT91F_DBGU_Init();
 PIT_starten();

in beiden funktionen werden entsprechende interrupts mit funktion 
AT91F_AIC_ConfigureIt konfiguriert und mit weiteren funktion aktiviert.
letztendlich funktioniert nur der PIT-interrupt, der von DBGU dann 
nicht.
und wenn man folgendermaßen initialisiert:
 PIT_starten();
 AT91F_DBGU_Init();

dann funktioniert der PIT-interrupt nicht, aber der von DBGU. meine 
folgerung daraus, die AT91F_AIC_ConfigureIt funktion schaltet den davor 
eingestellten interrupt aus, oder??
was muss man denn dann machen um mehrere aktive interrupts zu haben?

Autor: Patrick (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du willst, dass Dir ernsthaft geholfen wird, dann veröffentliche 
doch mal, was in den beiden Funktionen passiert (code);

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry.

void PIT_starten(unsigned long t)
{
 AT91F_PITInitSolfas(AT91C_BASE_PITC,
                     t,  //Periode in µsecond
                     EXT_OSC);  //system clock freq in MHz


 AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
           AT91C_ID_SYS,
           5,
           AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
           PIT_interrupt);

 AT91F_PITC_CfgPMC(); // Enable Peripheral clock in PMC for PITC

 AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);

 AT91F_PITEnableInt(AT91C_BASE_PITC); //Enable interrupts
}




void AT91F_DBGU_Init(char* InBuffer)
{
 locInBuffer = InBuffer;

 // Open PIO for DBGU
 AT91F_DBGU_CfgPIO();

 // Configure DBGU
 AT91F_US_Configure ((AT91PS_USART) AT91C_BASE_DBGU, // DBGU base 
address
         EXT_OSC,                        // CHANGED to MAIN_OSC
         AT91C_US_ASYNC_MODE,            //
         AT91C_DBGU_BAUD ,               // Baudrate
         0);                             // Timeguard

 // Enable Transmitter & receivier
 AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN;

 //DBGU Interrupt konfiguration
 AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
                         AT91C_ID_SYS,
                         DBGU_INTERRUPT_LEVEL,
                         AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
                         DBGU_IRQ_Handler);

 AT91F_AIC_EnableIt (AT91C_BASE_AIC,AT91C_ID_SYS);

 AT91F_PDC_Open (AT91C_BASE_PDC_DBGU);

 // enable interrupt
 AT91F_DBGU_InterruptEnable(AT91C_BASE_DBGU,AT91C_US_RXRDY);
}

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo mirko,
dein problem rührt daher, das sowohl pit als auch dbgu den sleben 
interrput nutzen (system interrupt).
der interrupt handler muß nun unterscheiden woher der interrupt kam.

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich mache jetzt die abfrage in beiden interrupt handler von wo der 
interrupt kam und zwar so:
  -für DBGU :  if (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY)
               {
                 handleanweisungen
               }

  -für PIT :   if (AT91C_BASE_PITC->PITC_PISR == 1)//PITS = 1 ?
         {
                 handleanweisungen
               }

trotztdem funktioniert DBGU dann nicht.??

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo mirko,
wenn du den vollständigen source codes der initialisierung und des 
interrupt handlers hier veröffentlichst dann kann man dir vielleicht 
auch wirklich helfen.


gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-PIT-interrupthandler:

 void PIT_interrupt()
{
  unsigned int temp;
  if (AT91C_BASE_PITC->PITC_PISR == 1)//Abfrage von wo Interrupt kam
  {
  AT91F_PITDisableInt(AT91C_BASE_PITC);  // Interrupt deaktivieren
        temp = AT91C_BASE_PITC->PITC_PIVR;   // Zurücksetzen der Zähler, 
dadurch wird auch der PITS = 0
    AT91C_BASE_PITC->PITC_PIMR  = AT91C_BASE_PITC->PITC_PIMR & 
(!(AT91C_PITC_PITEN)); // PIT ausschalten

  AT91F_DBGU_Printk("PIT geht \n\r");
  }
}






-DBGU-interrupthandler:

void DBGU_IRQ_Handler(void)
{
  unsigned int StatusDBGU;
  unsigned int j;
  static unsigned int i;
  static char myBuffer[MAX_LENGTH];

  StatusDBGU= AT91C_BASE_DBGU->DBGU_CSR;

  AT91F_DBGU_InterruptDisable(AT91C_BASE_DBGU,AT91C_US_RXRDY);

  if (StatusDBGU & AT91C_US_RXRDY)//Abfrage von wo Interrupt kam
  {
      myBuffer[i] = AT91C_BASE_DBGU->DBGU_RHR;
      AT91C_BASE_DBGU->DBGU_THR = myBuffer[i]; // Echo
      if ((myBuffer[i] == 10) || (myBuffer[i] == 13))  //check  CR , CF
      {
        myBuffer[i] = 0;
    if (i>0)
    {
      for (j=0; j<=i; j++) locInBuffer[j] = myBuffer[j];

      for (j=0; j<MAX_LENGTH; j++)  myBuffer[j] = '\0';

      i=0;
      AT91F_DBGU_Printk("\n\r");
    }
      }
      else
      {
        i++;
        if (i == MAX_LENGTH-1) i=0;
        myBuffer[i] = 0;
      }

  AT91F_DBGU_InterruptEnable(AT91C_BASE_DBGU,AT91C_US_RXRDY);

  //* Reset the status bit for error
  AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTSTA;
  }
}






die initfunktionen sind oben.

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
wenn die initfunktionen tatsächlich immer noch so aussehen wie o.a. dann 
kann das nicht funkt.

es darf nur ein interrupr handler für den system interrupt angemeldet 
sein (mit funktion AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, 
AT91C_ID_SYS,...).

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was macht man dann, oder welche möglichkeit gibt es dann?? ich brauche 
die beiden interrupts.

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe mit AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
AT91C_ID_US0,...)  und AT91F_AIC_EnableIt (AT91C_BASE_AIC,AT91C_ID_US0) 
versucht.in diesem fall funktioniert der DBGU-interrupt auch aleine 
nicht(PIT-interrupt ist nicht aktiviert/initialisiert).

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
mit
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_US0,...
init. du den interrupt für den usart 0 und nicht den debug usart!!


gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ gerhard: ich glaube ich kann doch AT91C_ID_SYS für beide interrupts 
benutzen sehe datenblatt s.153 "The Interrupt Source 1 is always located 
at System Interrupt. This is the result of the OR-wiring
of the system peripheral interrupt lines, such as the System Timer, the 
Real Time Clock, the
Power Management Controller and the Memory Controller. When a system 
interrupt occurs, the
service routine must first distinguish the cause of the interrupt. This 
is performed by reading successively
the status registers of the above mentioned system peripherals." ich 
muss nur  die statusregister abfragen wo der interrupt geschehen ist. du 
hast es doch oben selbs gesagt.
???

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>@ gerhard: ich glaube ich kann doch AT91C_ID_SYS für beide interrupts
>benutzen
ja sicher, aber in deinem geposteten code verwendest du AT91C_ID_US0 und 
nicht AT91C_ID_SYS!

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
meinst du diesen beitrag?

>habe mit AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
>AT91C_ID_US0,...)  und AT91F_AIC_EnableIt (AT91C_BASE_AIC,AT91C_ID_US0)
>versucht.in diesem fall funktioniert der DBGU-interrupt auch aleine
>nicht(PIT-interrupt ist nicht aktiviert/initialisiert).

wenn ja, dann habe ich dies nur so mal ausprobiert.
mein letzter beitrag war auf den von 19.10.2007 15:28 bezogen. 
vielleicht ist die abfrage in 22.10.2007 14:19 nicht richtig?



aber dieser beitrag von dir

>hallo mirko,
>dein problem rührt daher, das sowohl pit als auch dbgu den sleben
>interrput nutzen (system interrupt).
>der interrupt handler muß nun unterscheiden woher der interrupt kam.
>
>gruss
>gerhard


und dieser

>hallo,
>wenn die initfunktionen tatsächlich immer noch so aussehen wie o.a. dann
>kann das nicht funkt.
>
>es darf nur ein interrupr handler für den system interrupt angemeldet
>sein (mit funktion AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
>AT91C_ID_SYS,...).
>
>gruss
>gerhard

widersprechen sich doch(???)

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
um es klarer zu machen hier die init. des system-interrupts:
// System-Interrupt im AIC init.
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                      AT91C_ID_SYS,
                      SYSTEM_INTERRUPT_LEVEL,
                      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
                      SystemIrqHandler);

im SystemIrqHandler kommt dann die abfrager nach der interrupt quelle.

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
wie kann ich dann die beiden interrupts benutzen?

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
mir ist folgendes nicht ganz klar. die systeminterrupts sind ja PIT, 
RTT, WDT, DBGU, PMC und RSTC. und diese sind ja "verodert". meine frage 
jetzt ist, ob man 2(oder mehr) der 6 systeminterrupts gleichzeitig 
verwenden kann?
sprich es finden 2 systeminterrupts gleichzeitig statt, diese werden der 
priorität nach abgearbeitet. zusätzlich wird in den entsprechenden 
interrupthandlern unterschieden  (statusregister abfragen) von wo der 
interrupt kam.
oder kann nur einer von 6 systeminterrupts verwendet werden?

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>oder kann nur einer von 6 systeminterrupts verwendet werden?
es gibt keine 6 system interrupts sondern 6 peripherie blöcke die den 
system interrupt nutzen!
und da es sich nur um einen interrupt handelt hat der auch nur eine 
priorität.
und wenn du alle 6 peripherie blöcke nutzt können die gleichzeitig einen 
interrupt auslösen der dann vom system interrupt handler behandelt 
werden muß.

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hat lange gedauert :)  aber ich glaube ich habe es jetzt verstanden.

ich mache den hier:
// System-Interrupt im AIC init.
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                      AT91C_ID_SYS,
                      SYSTEM_INTERRUPT_LEVEL,
                      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
                      SystemIrqHandler);


dann den:

SystemIrqHandler
{
  if(DBGU-interrupt)
    {
       DBGU-anweisungen
    }
  if(PIT-interrupt)
    {
       PIT-anweisungen
    }
}


richtig?!

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>richtig?!
ja!

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke für deine hilfe und GEDULD!! :)

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt gehen beide interrupts, danke!
habe jetzt ein anderes problem mit PIT.  ich starte mit der eingabe 
"delay" in hyperterminal den pit-interrupt. nach einer sekunde wird "PIT 
geht" ausgegeben also der pit-interrupt wird ein mal auch ordnungsgemäß 
durchgeführt. wenn ich aber jetzt irgendeinen buchstaben in ht eingebe 
wird noch mal "PIT geht" ausgegeben obwohl der pit-interrupt im 
PIT_IRQ_Handler ausgeschaltet wird und erst wieder mit eintippen von 
"delay" wieder eingeschaltet wird. wenn man jetzt wieder "delay" eingibt 
wiederholt sich das ganze. beim debuggen habe ich auch gesehen, dass 
beim 2-er(ungewolter) "PIT geht" ausgabe beide interrupts stattfinden. 
schalte ich den PIT-interrupt nicht richtig aus oder werden die 
PIT-zähler nicht richtig zurückgesetzt?


void PIT_IRQ_Handler()
{
  unsigned int status;

  AT91F_PITDisableInt(AT91C_BASE_PITC);  // Interrupt deaktivieren
  status = AT91C_BASE_PITC->PITC_PIVR;   // Zurücksetzen der Zähler
  AT91C_BASE_PITC->PITC_PIMR  = AT91C_BASE_PITC->PITC_PIMR & 
~AT91C_PITC_PITEN; // PIT ausschalten

  AT91F_DBGU_Printk("PIT geht \n\r");
}

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich würde die reihenfolge umdrehen:
  status = AT91C_BASE_PITC->PITC_PIVR;   // Zurücksetzen der Zähler
AT91F_PITDisableInt(AT91C_BASE_PITC);  // Interrupt deaktivieren

gruss
gerhard

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
habe schon alle möglichen reihenfolgen ausprobiert, nix.
ich glaube die zweite "PIT geht"-ausgabe hat was damit zu tun:

When CPIV and PICNT values are obtained by reading the Periodic Interval 
Value Register (PIT_PIVR), the overflow counter (PICNT) is reset and the 
PITS is cleared, thus acknowledging the interrupt.
The PIT may be enabled/disabled using the PITEN bit in the PIT_MR 
register (disabled on reset). The PITEN bit only becomes effective when 
the CPIV value is 0. Figure 16-2 illustrates the PIT counting. After the 
PIT Enable bit is reset (PITEN= 0), the CPIV goes on counting until the 
PIV value is reached, and is then reset. PIT restarts counting, only if 
the PITEN is set again.

nach lesen von PIT_PIVR wird zwar PICNT und PITS resetet aber CPIV läuft 
dann wahrscheinlich ein mal von null bis PIV nach. so wird dann 
irgendwie der 2-e ungewollte interrupt ausgelöst. aber verstehe nicht 
wie, da ich ja diesen deaktiviere und sogar den PIT ausschalte.

Autor: Mirko (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
jetzt warte ich bis beide zähler null sind(also bis CPIV nachläuft), 
dann gibt es keine 2-e ausgabe. aber das ist doch nicht das richtige, da 
man sich länger in der irq-routine aüfhält als man eingegeben hat.

 void PIT_IRQ_Handler(void)
{
  unsigned int status;
  
  AT91C_BASE_PITC->PITC_PIMR  = AT91C_BASE_PITC->PITC_PIMR & ~AT91C_PITC_PITEN; // PIT ausschalten
  
  AT91F_PITDisableInt(AT91C_BASE_PITC);  // Interrupt deaktivieren
  
  status = AT91C_BASE_PITC->PITC_PIVR;   // Zurücksetzen der Zähler
  
  AT91F_DBGU_Printk("PIT geht \n\r");
  
  while(status!=0) // warten bis beide Zähler 0 sind
  {
    status = AT91C_BASE_PITC->PITC_PIVR;
  }   
} 

Autor: Michael M. (mkt)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich beschäftige mich zur Zeit mit der SAM7 Serie,
zur Zeit versuche ich den Receive Interrupt anzuwerfen,
der Interrupt wird ausgelöst, das System hängt sich auf,

es kann sein das diese Frage Sehr Dumm ist, wie kann ich
das Interrupt Flag löschen, so das der Interrupt nicht immer
ausgelöst wird.

Dank

Autor: gerhard (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael
wenn du uns verraten könntest um welchen interrupt es sich handelt dann 
könnte man dir vielleicht auch helfen.
meist wird der interrupt durch lesen des zugehörigen status registers 
gelöscht.

gruss
gerhard

Autor: mkt (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke,

Gerhard, genau das war der richtige hinweis,
ich habe den Receive IRQ aktiviert, aber nicht
die Daten aus dem Rec Register ausgelesen.

noch mal besten Dank für den Tip

Michael

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.