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?
Wenn Du willst, dass Dir ernsthaft geholfen wird, dann veröffentliche doch mal, was in den beiden Funktionen passiert (code);
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); }
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
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.??
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
-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.
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
was macht man dann, oder welche möglichkeit gibt es dann?? ich brauche die beiden interrupts.
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).
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
@ 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. ???
>@ 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
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(???)
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
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?
>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
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?!
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"); }
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
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.
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 | }
|
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
@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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.