opakovane vyvolani timer interrupt MCU PIC32MX695

Potřebuji poradit s nechtěným opakovaným vyvoláním přerušení timeru.
Nejprve uvedu, že používám MPLAB 8.9 a MPLABX a C32 compilátory od Microchipu.
Programovací jazyk C a neznám do hloubky procesor MIPS a jeho registry.
MCU PIC32MX695
Periférie mám prostudované z DS a REF.příručky.

BĚŽNÝ STAV:

  • T1 konfigurován 1:1 CLK:TMR a nastaven na vyvolání INT při TMR 5000 (IP1)
  • T4 konfigurován 1:64 a nastaven na volání INT při TMR při 200 (IP6)
  • obslužné rutiny provedou potřebné a vynulují IFS

**PROBLÉM:

  • T4 generuje jednou za cca 1000 vyvolání přerušení dvojíté přerušení
    Vysvětlím co myslím tím dvojíté: poprvé vyvolá T4 interupt správně po 200 cyklech CLK*64 a ihned v zápětí vyvolá přerušení znovu. Kontroloval jsem TMR4 a v tu chvíli má hodnotu 1. Měl by mít hodnotu 200.
    (poznámka: v uvedeném kódu nepočítám od 0 ale od 65300 do 65535, zkoušel jsem obojí - nemělo žádný vliv na chybu).
    **
    Z debugingu jsem zjistil, že se střídá vyvolávání rutiny přerušení T1 a T4 takto: T1 - T1 - T1 - T4 - T1… a jednou za čas dojde k variantě T1 - T1 - T4 - T1 - T1… Je to dáno nastavením časování a tak je to správně a nechci to měnit. Ještě se může stát, že přerušení T4 přeruší vykonávání T1 rutiny a to je taky správně, protože má vyšší prioritu.

Kód jsem upravoval různě a debugoval, přidal jsem si další timer T2 abych sledoval jak se střídavě vyvolávají INT.
A opravdu se potvrdilo náhodné vyvolání INT T4.
Ostatní periférie můžeme vyloučit protože jsou vypnuté.
Konfigurace portů je v pořádku.
Zkoušel jsem celý kód přepsat do použití pblib tzn. funkce a makra a stejný problém.

Protože jsem problém neidentifikoval píšu sem o pomoc.
Pravděpodbně mi pomůže někdo s dobrou znalostí řadiče přerušení a procesoru MIPS.

Rady typu kup si něco jiného, nepoužívej timery apod. prosím nepište - jsem dospělý a vím co chci :slight_smile: takže sám vím co je pro mě to nejlepší… a nyní je to MCU PIC32MX695! takže prosím pouze konstruktivní nápady a rady :slight_smile:

#define SYSCLK 80000000

//konfigurace MCU
SYSTEMConfigPerformance(SYSCLK);

//konfigurace periférií

//timer T1
IPC1bits.T1IP = 1;      //T1 interrupt priority 1
T1CON = 0x0;            //stop operaci timer1 - mozna neni nutne, ale pro jistotu
TMR1 = 0x0;				//nulovani timeru
PR1 = 5000;				//prah pro preruseni (toto je od 0 do 5000, zkousel jsem i od 60000 do 65535)
IFS0bits.T1IF = 0;      //clear T1 interrupt flag
T1CONbits.ON = 1;		//zapnuti periferie

//timer T4
IPC4bits.T4IP = 6;      //interrupt priority
T4CON = 0x0;            //stop operaci timer4 - mozna neni nutne, ale pro jistotu
T4CONbits.TCKPS = 0x06; //prescaler 64 - generovat impulz pro timer CLK/64
TMR4 = 0x0000;			//nulovani timeru
PR4 = 0xFFFF;			//prah 65535 - pocitam poprve od 0, nasledne od 65300 viz. dale
IFS0bits.T4IF = 0;      //clear T4 interrupt flag
T4CONbits.ON = 1;

//zapnuti systemu preruseni, konfiguraci radice preruseni jako multivectored provede funkce pblib
INTEnableSystemMultiVectoredInt();
IEC0bits.T1IE = 1;      //Timer1 interrupt enable
IEC0bits.T4IE = 1;      //Timer1 interrupt enable


//rutiny

void __ISR(_TIMER_1_VECTOR, ipl1) IT1Interrupt(void)    //obsluha LED displaye
{
	//...muj kod, globalni promenne jsou deklarovany volatile - zkousel jsem vse
	//...muj kod, pracuje s LAT registry
	//...muj kod, nenastavuje ani jinak neovlivnuje TMR4

    IFS0bits.T1IF = 0;		//vynulovat T1 IF
    TMR1 = 0x00;			//vynulovat timer1
}

void __ISR(_TIMER_4_VECTOR, ipl6) IT4Interrupt(void)
{
	//...muj kod, globalni promenne jsou deklarovany volatile - zkousel jsem vse
	//...muj kod, pracuje s LAT registry
	//...muj kod, nenastavuje ani jinak neovlivnuje TMR1

    WriteTimer4(65300);		//pocitat od 65300 do 65535 - varianta pouziti funkce knihovny pblib
    mT4ClearIntFlag();		//vynulovat T4 IF - varianta pouziti makra knihovny pblib
}

:arrow_right: administrator: přesunuto z "Off – topic"

prosím o přesunutí zprávy do MCU PIC - nechápu jak jsem to zakládal, že se to dostalo do off topic :frowning:

No… zkus nulovat T4 IF hned jak do otoho přerušení vlezeš a pak teprve ten zbytek. Mě se to stávalo na ARM - prostě cpu byl moc rychlej a kód krátkej a než to prošlo instrukční pipou tak jsem byl venku a příznak nebyl ještě smazán.

super, už se to zdá být v pořádku… děkuji moc - ani nevíš jak moc jsi mi pomohl!

Nulování jsem dal na začátek rutin a všude jsem ještě pro jistotu použil atomické instrukce. Zřejmě to bylo přesně jak jste psal.

Kdyby jsi potřeboval vyrobit plošný spoj (jednostranný nebo oboustranný bez prokovů a s nepájivou maskou) napište na martasg1@seznam.cz a já ti jej vyrobím zadarmo! (zabývám se výrobou DPS fotocestou s velmi vysokou přesností). Ušetřil jsi mi spoustu času…

ještě jednou děkuji

Rádo se stalo :wink: Za nabídku děkuji, ale výrobu DPS mám tak zvaně IN HOUSE :slight_smile: