View previous topic :: View next topic |
Author |
Message |
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
Very Peculiar Problem [SOLVED] |
Posted: Sun Jul 28, 2013 11:57 am |
|
|
Hi all,
I am facing a peculiar problem, there are five tasks and each task will be executed at different interval time (200ms, 1 sec, 6 sec, 3 sec and ten min).
Tasks are executing perfectly for some time say few hours, vafter that No tasks are executing exactly for fixed time say 1 hour 9 mins and after that time duration again the tasks are started to executing. The peculiar problem I noticed is it is entering the interrupt and flag is getting set, but in main loop the if condition is getting false but it should not be so.
Example :
Isr Routine
Code: |
isr
{
interrupt disable
flag=true; //flag is getting enabled here correctly each time
interrupt enable
} |
under main routine
Code: |
while(1)
{
if(flag==true) //while i place break point here and watch the flag value , //flag is equal to true only , but it is not entering into the condition loop.
{
interrupt disable
tasks;
flag=false;
interrupt enable
}
}
|
This is my actual code snippet
Code: |
#INT_TIMER0
void timer0_isr(void) //3 Seconds
{
disable_interrupts(GLOBAL);
TASK_LSTSMS=D_TRUE;
_6secDelay++; //six Sec
_cumulativeUpdateDelay++; //ten Min
restart_wdt();
if(_6secDelay>D_TIME_RELATED_DLY)
{
_6secDelay=0;
TASK_TMRLTD=D_TRUE;
}
else // For Latency
{
if(_cumulativeUpdateDelay>=D_CUM_UPD_DLY)//every ten mins
{
_cumulativeUpdateDelay=0;
TASK_CUMUPD2MEM=D_TRUE;
}
}
set_timer0(D_TM0_DLY);
enable_interrupts(GLOBAL); //very important
}
#INT_TIMER1
void timer1_isr(void) //100 Ms
{
disable_interrupts(GLOBAL);
restart_wdt();
_200msDelay++;
_1secDelay++;
if(_1secDelay>=D_LST_SMS_DLY)
{
_1secDelay=0;
TASK_TAMPCHK=D_TRUE;
}
if(_200msDelay>D_ENERGYAH_UPD_DLY)
{
_200msDelay=0;
TASK_AHCALC=D_TRUE;
}
set_timer1(D_TM1_DLY);
enable_interrupts(GLOBAL);
}
in main
while(1)
{
if(TASK_AHCALC==D_TRUE)
{
disable_interrupts(GLOBAL);
//ah tasks goes here
TASK_AHCALC=D_FALSE;
enable_interrupts(GLOBAL);
}
if(TASK_TAMPCHK==D_TRUE)
{
disable_interrupts(GLOBAL);
//sensing tasks goes here
TASK_TAMPCHK=D_FALSE;
enable_interrupts(GLOBAL);
}
if(TASK_TMRLTD==D_TRUE)
{
disable_interrupts(GLOBAL);
//time related tasks
TASK_TMRLTD=D_FALSE;
enable_interrupts(GLOBAL);
}
if(TASK_LSTSMS==D_TRUE)
{
disable_interrupts(GLOBAL);
//tasks
TASK_LSTSMS=D_FALSE;
enable_interrupts(GLOBAL);
}
if(TASK_CUMUPD2MEM==D_TRUE)
{
disable_interrupts(GLOBAL);
//tasks
TASK_CUMUPD2MEM=D_FALSE;
enable_interrupts(GLOBAL);
}
|
Last edited by Es_prog on Thu Aug 01, 2013 6:25 am; edited 1 time in total |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Jul 28, 2013 1:16 pm |
|
|
Speed things up by a factor of 1,000 or more.
Then you won't have to wait so long for the error to occur.
You should then be able to see the problem for yourself.
Mike |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 28, 2013 2:24 pm |
|
|
Why do you think you should manually disable and enable global interrupts
while still inside the interrupt service routine ? I don't think you have seen
that in any CCS example or in the manual. I'm curious, because you have
labeled it "very important".
Also, what's your PIC and compiler version ?
Quote: |
#INT_TIMER0
void timer0_isr(void) //3 Seconds
{
disable_interrupts(GLOBAL);
TASK_LSTSMS=D_TRUE;
_6secDelay++; //six Sec
_cumulativeUpdateDelay++; //ten Min
restart_wdt();
if(_6secDelay>D_TIME_RELATED_DLY)
{
_6secDelay=0;
TASK_TMRLTD=D_TRUE;
}
else // For Latency
{
if(_cumulativeUpdateDelay>=D_CUM_UPD_DLY)//every ten mins
{
_cumulativeUpdateDelay=0;
TASK_CUMUPD2MEM=D_TRUE;
}
}
set_timer0(D_TM0_DLY);
enable_interrupts(GLOBAL); //very important
}
#INT_TIMER1
void timer1_isr(void) //100 Ms
{
disable_interrupts(GLOBAL);
restart_wdt();
_200msDelay++;
_1secDelay++;
if(_1secDelay>=D_LST_SMS_DLY)
{
_1secDelay=0;
TASK_TAMPCHK=D_TRUE;
}
if(_200msDelay>D_ENERGYAH_UPD_DLY)
{
_200msDelay=0;
TASK_AHCALC=D_TRUE;
}
set_timer1(D_TM1_DLY);
enable_interrupts(GLOBAL);
}
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Sun Jul 28, 2013 3:03 pm |
|
|
Also you only need one ISR,set for 200ms, your 'smallest' time unit.
Besides simplifying the code,all tasks are 'synced' to a 'master' time unit.
If you check the software RTC in the code library, you can see another way to have several tasks execute.
hth
jay |
|
|
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
|
Posted: Sun Jul 28, 2013 3:23 pm |
|
|
@ Mike Walne
How to speed up, give me some hint plz
@ PCM Programmer
I have used global interrupt disable to avoid recurrence of same interrupt. Using 4.127 version. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 28, 2013 3:27 pm |
|
|
Quote: | Also, what's your PIC and compiler version ?
Using 4.127 version |
What is your PIC ? |
|
|
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
|
Posted: Sun Jul 28, 2013 3:30 pm |
|
|
@ PCM
It is PIC 18F67K90 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 28, 2013 3:52 pm |
|
|
Quote: | I have used global interrupt disable to avoid recurrence of same interrupt |
The PIC automatically disables Global interrupts in hardware when it
gets an interrupt. You don't have to do it. When your interrupt routine
is done and the compiler returns the interrupt, then Global interrupts
are re-enabled. You don't have to do it, and you should not do it. |
|
|
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
|
Posted: Sun Jul 28, 2013 4:03 pm |
|
|
@ PCM
Problem i m facing is due to manual entry of global disable and enable? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jul 28, 2013 5:22 pm |
|
|
It could be. When you re-enable Global interrupts at the end of your
user code in the interrupt routine the program execution is as shown below.
See all those instructions in the middle ? You have prematurely allowed
a new interrupt to occur in the middle of the exit code of the CCS
interrupt dispatcher:
Code: |
.................... enable_interrupts(GLOBAL); //very important
000A6: MOVLW C0
000A8: IORWF INTCON,F // User manually enables Global ints
=======
000AA: BCF INTCON.T0IF
000AC: GOTO 0058
00058: MOVFF 0E,00
0005C: MOVFF 0F,01
00060: MOVFF 10,02
00064: MOVFF 11,03
00068: MOVFF 0C,FSR0L
0006C: MOVFF 07,FSR0H
00070: BSF 07.7
00072: MOVFF 08,FSR1L
00076: MOVFF 09,FSR1H
0007A: MOVFF 0A,FSR2L
0007E: MOVFF 0B,FSR2H
00082: MOVFF 12,PRODL
00086: MOVFF 13,PRODH
0008A: MOVFF 14,PCLATH
0008E: MOVFF 15,PCLATU
00092: MOVF 04,W
00094: MOVFF 06,BSR
00098: MOVFF 05,STATUS
=========
0009C: RETFIE 0 // The 18F67K90 re-enables Global interrupts here |
When you do this, you allow a new interrupt (from a different timer)
to enter the CCS interrupt dispatcher code before the previous interrupt
is finished exiting the interrupt dispatcher. There is only one instance of
interrupt dispatcher code. It's not re-entrant. Do not do this. Do not
manually enable global interrupts while still inside your user code.
Let the CCS interrupt dispatcher handle it. |
|
|
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
|
Posted: Sun Jul 28, 2013 11:54 pm |
|
|
@ PCM
Thanks, I have changed the code as you said and its now in testing phase. |
|
|
Es_prog
Joined: 27 Jul 2013 Posts: 6
|
|
Posted: Wed Jul 31, 2013 3:48 am |
|
|
@PCM,
Thanks, your solution have solved my problem. |
|
|
|