Forum: Mikrocontroller und Digitale Elektronik AT91SAM7S mit zwei aktivien interrupts


von Mirko (Gast)


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?

von Patrick (Gast)


Lesenswert?

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

von Mirko (Gast)


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

von gerhard (Gast)


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

von Mirko (Gast)


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

von gerhard (Gast)


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

von Mirko (Gast)


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.

von gerhard (Gast)


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

von Mirko (Gast)


Lesenswert?

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

von Mirko (Gast)


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

von gerhard (Gast)


Lesenswert?

hallo,
mit
1
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

von Mirko (Gast)


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

von gerhard (Gast)


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

von Mirko (Gast)


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(???)

von gerhard (Gast)


Lesenswert?

um es klarer zu machen hier die init. des system-interrupts:
1
// System-Interrupt im AIC init.
2
AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
3
                      AT91C_ID_SYS,
4
                      SYSTEM_INTERRUPT_LEVEL,
5
                      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE,
6
                      SystemIrqHandler);

im SystemIrqHandler kommt dann die abfrager nach der interrupt quelle.

gruss
gerhard

von Mirko (Gast)


Lesenswert?

wie kann ich dann die beiden interrupts benutzen?

von Mirko (Gast)


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?

von gerhard (Gast)


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

von Mirko (Gast)


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

von gerhard (Gast)


Lesenswert?

>richtig?!
ja!

von Mirko (Gast)


Lesenswert?

danke für deine hilfe und GEDULD!! :)

von Mirko (Gast)


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");
}

von gerhard (Gast)


Lesenswert?

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

gruss
gerhard

von Mirko (Gast)


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.

von Mirko (Gast)


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.

1
 void PIT_IRQ_Handler(void)
2
{
3
  unsigned int status;
4
  
5
  AT91C_BASE_PITC->PITC_PIMR  = AT91C_BASE_PITC->PITC_PIMR & ~AT91C_PITC_PITEN; // PIT ausschalten
6
  
7
  AT91F_PITDisableInt(AT91C_BASE_PITC);  // Interrupt deaktivieren
8
  
9
  status = AT91C_BASE_PITC->PITC_PIVR;   // Zurücksetzen der Zähler
10
  
11
  AT91F_DBGU_Printk("PIT geht \n\r");
12
  
13
  while(status!=0) // warten bis beide Zähler 0 sind
14
  {
15
    status = AT91C_BASE_PITC->PITC_PIVR;
16
  }   
17
}

von Michael M. (mkt)


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

von gerhard (Gast)


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

von mkt (Gast)


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

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.