CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

DSPIC33E Interrupt Priority Issue

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
btondin



Joined: 19 May 2016
Posts: 5

View user's profile Send private message

DSPIC33E Interrupt Priority Issue
PostPosted: Thu May 19, 2016 4:30 pm     Reply with quote

Hello

I'm getting some trouble dealing with the DSPIC33E interrupts. I wrote a code that are intended to generate variable frequency sinusoidal waveform trough PWM in this way: i have a constant PWM frequency of 20KHz (limited by my IGBT module) being generated, a 32bit timer4/5 interrupt that is designated to read a sinus table and send the values to PDC of PWM module. When i change the timer4/5 basetime, i can change the frequency of the sine.
I put the priority of the timer4/5 interrupt in level 6, higher than all the other interrupts, so i supposed that nothing could interfere with the pace of this routine. But when i enable a delay_ms(1000) in the main routine, or i send something via serial, the output of PWM became erratic. Not only extends the sine width, but totally deforms it. The interrupt nesting is enabled. Any suggestion?

Thanks very much


Code:
void myputc(char caract) //My custom putc that are called in printf function
{

    while(!U1TXIF);
    U1TXREG = caract;
    U1TXIF = 0;
   
}

void Config_UART(int32  baud = 115200) //UART configuration
{
    RPOR2 = 1*256; //Configura pino RP39 como TX do UART [pino físico RB7]
    RPINR18 = 38;// Configura pino RP38 como RX do UART [pino físico RB6]

    STSEL = 0;// 1-Stop bit
    PDSEL_1 = 0;// No Parity, 8-Data bits
    PDSEL_0 = 0;

    ABAUD = 0;// Auto-Baud disabled
    BRGH = 0;// Standard-Speed mode
    U1BRG = (int16)(FOSC/(32*baud) - 1);

    UTXISEL_1 = 0;// Interrupt after one TX character is transmitted
    UTXISEL_0 = 0;
   
    URXISEL_1 = 0;// Interrupt after one RX character is received
    URXISEL_0 = 0;

    U1TXIP_2 = 0; U1TXIP_1 = 0; U1TXIP_0 = 0; //Prioridade 3
    U1RXIP_2 = 0; U1RXIP_1 = 0; U1RXIP_0 = 0; //Prioridade 3
    //U1TXIE = 1;// Enable UART TX interrupt
    //U1RXIE = 1;// Enable UART RX interrupt
    UARTEN = 1;// Enable UART
    UTXEN = 1;// Enable UART TX   

    delay_us(50);
}


#INT_TIMER5
void TIMER32Bbit_interrupt(void) //Timer4/5 routine. Sweeps the sinLUT table to generate the sine in the PWM output
{   
    flag_timer32 = 1;
   
    //PWM1IF = 0; //Desliga flag da interrupção do PWM 1

    PDC1 = sinLUT[sinaLUTptr];
    PDC2 = sinLUT[sinbLUTptr];
 
    sinaLUTptr++;
    sinbLUTptr++;   
   
    if(sinaLUTptr == 360) sinaLUTptr = 0;
    if(sinbLUTptr == 360) sinbLUTptr = 0;
    //LED2 = !LED2;
}



void ConfigTIMER32bit(float freq_sine)  //Timer4/5 configuration
{
    T32_PERIOD(freq_sine); //Hz
    T324 = 1; // Habilita modo 32 bit
    TON5 = 0; //Desliga Timer 5
    TON4 = 0; //Desliga Timer 4
    TGATE4 = 0; //Modo Timer
    TCKPS4_1 = 0; TCKPS4_0 = 0; //Prescaler em 1:1
    TCS4 = 0; //Clock é Fcy
    TMR5 = 0; //Zera registrador de contagem
    TMR4 = 0; //Zera registrador de contagem     
    T5IP_2 = 1; T5IP_1 = 1; T5IP_0 = 0; //Prioridade 6 da interrupção do timer de 32 bit   
    T5IF = 0; //Limpa flag de interrupção do TIMER 5
    T5IE = 1; //Habilita interrupção do TIMER 5   
}

void ConfigMEUMCPWM(void) //PWM module config
{
    ////// Configuração do time base [PTCON]//////
    PTEN = 0; // PWM time base OFF
    /* Set PWM Period on Primary Time Base */
    PTPER = (FOSC/FPWM)/4; // Compute Period for desired frequency (20KHZ) Prescaller 1:4   
    /* Set Phase Shift */
    PHASE1 = 0;
    PHASE2 = 0;
    PHASE3 = 0;
    /* Set Duty Cycles */
    PDC1 = 1;
    PDC2 = 1;
    PDC3 = 1;
    /* Set Dead Time Values */
    DTR1 = DTR2 = DTR3 = 1;  //Deadtime de 10*7.14ns
    ALTDTR1 = ALTDTR2 = ALTDTR3 = 1; //Deadtime de 10*7.14ns
    /* Set PWM Mode to Complementary */
    IOCON1 = IOCON2 = IOCON3 = 0xC000;
    /* Set Primary Time Base, Edge-Aligned Mode and Independent Duty Cycles */
    PWMCON1 = PWMCON2 = PWMCON3 = 0x0000;
    /* Configure Faults */
    FCLCON1 = FCLCON2 = FCLCON3 = 0x0003;
    /* 1:4 Prescaler */
    PTCON2 = 0x0002;
    /* Enable PWM Module */
    //PTEN = 1;
}

void main(void)  //The main code ?!
{
    ////// CONFIGURAÇÃO DAS PORTAS //////
    LATA = 0b0000000000000000;
    LATB = 0b0000000000010000;
   
    TRISA = 0b0000000000000001;  //Entrada ADC
    TRISB = 0b0000000111001100; //RB2 e RB3 entradas do comparador

    ANSELA = ANSELB = 0; //Todas as portas sendo digitais
    ANSA0 = ANSB2 = ANSB3 = 1; // PORTA.0 sendo analógica


    ///////// Clock em 70 MIPS com cristal de 12MHZ /////////
    CLKDIV = 1; // PLLPOST /2
    PLLFBD = 0b0000000001000100; //PLLDIV = 68 + 2

    ///////////////////////////////////

    ///// Interrupt Config ////////////
    NSTDIS = 0; //Enable interrupt nesting

    INT0EP = 0; //Interrupt 0 on POSITIVE edge
    INT0IP_2 = 0; //Prioridade 1 para interrupção externa 0
    INT0IP_1 = 0;
    INT0IP_0 = 1;
    INT0IF = 0;
    INT0IE = 0; //Desabilitar interrupção externa 0

    RPINR0 = 256*40; //Mapear no pino RB8 a entrada da INT1
    INT1EP = 0; //Interrupt 1 on POSITIVE edge
    INT1IP_2 = 0; //Prioridade 1 para interrupção externa 1
    INT1IP_1 = 0;
    INT1IP_0 = 1;
    INT1IF = 0;
    INT1IE = 0; //Desabilitar interrupção externa 1
    ///////////////////////////////////   
   
    delay_ms(10);
    //Config_UART(115200);
    Config_Comparator();
    ConfigMEUMCPWM();     //Configura módulo PWM
    ConfigTIMER2(30);      //Amostragem
    ConfigTIMER32bit(60);  //Configura timer de 32 bit (4/5)
   
    TON2 = 1; //Liga TIMER2
    Start_PWM();
   

    //INT0IE = 1; // habilita interrupção do encoder
    //INT1IE = 1; // habilita interrupção do botão
   
    while(1)
    {
        //delay_ms(1000);
        //printf(myputc, "Teste\n");
    }

}


This code is working well while the delay and printf are commented ;)


CCS 5.025
DSPIC33EP256MC202
Standard Run Mode
3V3
140MHz
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri May 20, 2016 10:49 am     Reply with quote

Do you get any compiler warnings regarding interrupts being disabled ?
(Make sure warnings are enabled in your project options).
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Fri May 20, 2016 2:49 pm     Reply with quote

Just something to try, but have you considered using the built in compiler mechanisms for setting up priority. I don't have time to read through your data sheet, but perhaps you are making a setup mistake.

Try setting the level using the CCS directive:

Code:

#INT_TIMER5 level=6
void TIMER32Bbit_interrupt(void) //Timer4/5 routine. Sweeps the sinLUT table to generate the sine in the PWM output
{   
    flag_timer32 = 1;
   
    //PWM1IF = 0; //Desliga flag da interrupção do PWM 1

    PDC1 = sinLUT[sinaLUTptr];
    PDC2 = sinLUT[sinbLUTptr];
 
    sinaLUTptr++;
    sinbLUTptr++;   
   
    if(sinaLUTptr == 360) sinaLUTptr = 0;
    if(sinbLUTptr == 360) sinbLUTptr = 0;
    //LED2 = !LED2;
}



enable nesting using:

Code:

#include <33EP256MC202.h>

#device NESTED_INTERRUPTS=TRUE


Position of this directive is important. I needs to be pretty early in the code. You will get compiler errors otherwise.

enable interrupts using the ccs functions:
Code:

   enable_interrupts(INT_TIMER5);
   //other interrupt enables here
   enable_interrupts(GLOBAL);


It helps to start with a smaller program too. As it is you have a lot of lines of code where you could have easily put in a slightly off value.

If it were me, I would start with a program that just had timer5 setup, the timer5 isr toggling an I/O, a second interrupt that triggers a long delay in the ISR (normally delays in an interrupt are bad, but we are testing nesting here, so it is only for testing...not production), and a small main with just enough config for all that plus a while loop with another long delay (a different value than the ISR test delay so you can tell the difference on a scope). CCS supplies functions for all of that.

Then you can see if the toggling happens with the right period or if either the ISR delay or the main delay (or both) inhibit it. If they do, trouble shoot that. Once you figure out what causes it, you can apply that to your actual program.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Sat May 21, 2016 2:24 am     Reply with quote

I have to agree with Jeremiah.

Classic example of having a C compiler, but trying to program in assembler!.
Each setups for the timers, for example could be done in a single line in CCS.

Learn the language you are using.

Realistically for 99.99% of code you should never have to touch a register directly. The fact that this code does this on just about every line, says 'not yet programming in CCS really'....

The whole code could be written in perhaps 1/4 the number of lines using CCS code.

However I suspect the actual problem is nothing to do with interrupt priorities.

Since there is no diagnostics shown, I'd suspect the chip is actually restarting. Probably stack overflow.
btondin



Joined: 19 May 2016
Posts: 5

View user's profile Send private message

PostPosted: Mon May 23, 2016 10:53 am     Reply with quote

Thanks very much. I will try to fix the problems using the tips you have given me. I will post the results soon
btondin



Joined: 19 May 2016
Posts: 5

View user's profile Send private message

PostPosted: Mon May 23, 2016 10:55 am     Reply with quote

PCM programmer wrote:
Do you get any compiler warnings regarding interrupts being disabled ?
(Make sure warnings are enabled in your project options).



Just warnings about unused variables and condition always TRUE
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Mon May 23, 2016 11:09 am     Reply with quote

So, just try recompiling with the stack enlarged.

printf, is a heavy user of stack space. Only take an interrupt inside a printf, and the stack usage will leap up.
Add:

#build (stack=256)

After the processor include file.

if it starts working you know what the problem is.
btondin



Joined: 19 May 2016
Posts: 5

View user's profile Send private message

PostPosted: Mon May 23, 2016 11:45 am     Reply with quote

Ttelmah wrote:
I have to agree with Jeremiah.

Classic example of having a C compiler, but trying to program in assembler!.
Each setups for the timers, for example could be done in a single line in CCS.

Learn the language you are using.

Realistically for 99.99% of code you should never have to touch a register directly. The fact that this code does this on just about every line, says 'not yet programming in CCS really'....

The whole code could be written in perhaps 1/4 the number of lines using CCS code.

However I suspect the actual problem is nothing to do with interrupt priorities.

Since there is no diagnostics shown, I'd suspect the chip is actually restarting. Probably stack overflow.



I know that using the built in functions of CCS easy the process of programming. But i'm not confortable to be attached to this "arduino" like resource.
btondin



Joined: 19 May 2016
Posts: 5

View user's profile Send private message

PostPosted: Mon May 23, 2016 11:52 am     Reply with quote

jeremiah wrote:

enable nesting using:

Code:

#include <33EP256MC202.h>

#device NESTED_INTERRUPTS=TRUE


Position of this directive is important. I needs to be pretty early in the code. You will get compiler errors otherwise.



OMG. I replaced the "NSTDIS = 0;" by the "#device NESTED_INTERRUPTS=TRUE" (in the beggining of the code) and everything is working fine. I really want to know what else the compiler did since the only thing i read on datasheet regarding enabling the nesting is keep NSTDIS low.

Thanks very much
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Mon May 23, 2016 4:06 pm     Reply with quote

btondin wrote:

OMG. I replaced the "NSTDIS = 0;" by the "#device NESTED_INTERRUPTS=TRUE" (in the beggining of the code) and everything is working fine. I really want to know what else the compiler did since the only thing i read on datasheet regarding enabling the nesting is keep NSTDIS low.

Thanks very much


To see what the compiler did, look at the LST file between where main starts and your first line of code. It is somewhere between those two points (can probably look for the address of the register the bit lies in). My guess is that there is an unlock sequence or a special order of operations for the bits, but I haven't looked at the datasheet, so that is just a guess.

That said, I know you don't want to rely on the built in features, but that is one of the main reasons to use CCS. If you want to directly manipulate all the registers, you are better off using a compiler that supports that better (like the microchip compiler). Using the built in capabilities of CCS allows the compiler to do more things at compile time, reducing your code footprint and optimizing the code much better than you can.

Ultimately it is up to you, but just wanted to at least help with that suggestion.
Ttelmah



Joined: 11 Mar 2010
Posts: 19504

View user's profile Send private message

PostPosted: Tue May 24, 2016 1:02 am     Reply with quote

Or, the definitions being used are wrong.....

Could be a simple typo.

However there are quite a few 'deeper' things that have to change once you enable priorities. For instance DISI instructions may need to stop one level and not higher ones. Code used inside the lower priority interrupt routines, may have to disable interrupts around some instructions, that would not apply when priorities are not used.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group