Reply by Glennis October 18, 20062006-10-18
Thx for your reply!!
/Glennis

Reply by Andrzej Ekiert October 13, 20062006-10-13
Glennis wrote:

> 9. Module: Interrupting a REPEAT Loop
I reported this one first :^)
> But i dont know how to implement the followinf soulution in my c > compiler C30, Mplab. >
void _ISR _T1Interrupt(void) { (...) SET_CPU_IPL(7); // end of interrupt } Regards, Andrzej Ekiert http://andrzejekiert.ovh.org/
Reply by Glennis October 13, 20062006-10-13
i!
I have been searching the web for the error generating my adress error
trap every 24 hours typ. And i found the solution in the errata
http://ww1.microchip.com/downloads/en/DeviceDoc/80198d.pdf module 9,

//*******************************************

9. Module: Interrupting a REPEAT Loop
When interrupt nesting is enabled (or
NSTDIS(INTCON1<15>) bit is '0'), the following
sequence of events will lead to an Address Error
trap:
1. REPEAT-loop is active
2. An interrupt is generated during the execution
of the REPEAT-loop.
3. The CPU executes the Interrupt Service
Routine (ISR) of the source causing the
interrupt.
4. Within the ISR, when the CPU is executing the
first instruction cycle of the 3-cycle RETFIE
(Return-from-interrupt) instruction, a second
interrupt is generated by a source with a higher
interrupt priority.
Work around
Processing of Interrupt Service Routines should
be disabled while the RETFIE instruction is being
executed. This may be accomplished in two
different ways:
1. Place a DISI instruction immediately before
the RETFIE instruction in all interrupt service
routines of interrupt sources that may be interrupted
by other higher priority interrupt sources
(with priority levels 1 through 6). This is shown
in Example 9 in the Timer1 ISR. In this example,
a DISI instruction inhibits level 1 through
level 6 interrupts for 2 instruction cycles, while
the RETFIE instruction is executed.
/***********************************

I have used
#define DISI_PROTECT(X){__asm__ volatile ("DISI #0x1FFF"); X;
DISICNT=0;}

for protecting the  flag and when enabling interrupt.
But i dont know how to implement the followinf soulution  in  my c
compiler  C30, Mplab.

/************************************
2. Immediately prior to executing the RETFIE
instruction, increase the CPU priority level by
modifying the IPL<2:0> (SR<7:5>) bits to '111'
as shown in Example 10. This will disable all
interrupts between priority levels 1 through 7.

Assembler code
__T1Interrupt: ;Timer1 ISR
PUSH W0
.......
BCLR IFS0, #T1IF
MOV.B #0xE0, W0
MOV.B WREG, SR
POP W0
RETFIE ;Another interrupt occurs
;here and it is processed
;correctly
/*********************************

My timer interrupt looks as following
/*********************************
void _ISR _T1Interrupt(void)
{

   uint32 nTimertickLowpower;
   DISI_PROTECT(T1IF = 0;); //protects the flag change se
http://ww1.microchip.com/downloads/en/DeviceDoc/80228c.pdf
   DISI_PROTECT(TMR1=0x0000);        //Clear contents of the timer_1
register
          // Clear the Timer1 Interrupt flag Status bit.
   if(g_MeasureNow)
   {
       ADON = 0;                // debug...turn AD off
       DISI_PROTECT(ADIF = 0;);                  // debug....clear ad
flag..
       ADON = 1;               // Turn AD module on
       CH0SA = g_acChanMap[g_uSampChan];  // CH0+ input
       SAMP = 1;               // Turn AD convertion on(sampling off)
       g_WaitForDone = true;

       g_nTimerTick++;

       //Special for handling the fact that thirdspeed is 64/3 = 21 +
21 + 22; Every third case wait one tick more.
       if(g_LowSpeed && (!IsTrigged() || g_bContinous)) //continous is
sampling at 1024 hz.
       {
           if(g_uCounter  <= 1)
           {

               nTimertickLowpower = g_nTimerTickComp;
           }
           else if(g_uCounter >= 2 )
           {
               nTimertickLowpower = g_nTimerTickComp + 1;

           }
       }
       else
       {

           nTimertickLowpower = g_nTimerTickComp;
       }


       if(g_nTimerTick >= nTimertickLowpower) //tick >= 22,3333333 64/3
21 + 21 + 22 = 64
       {
           if(g_uCounter >= 2)
           {
               g_uCounter = 0;
           }
           else
           {
               g_uCounter++;
           }

           g_ulHiGetTick += PR1_SLOW;
           g_nTimerTick = 0;
           g_TestOther = true;
           uint16 ulCurTime = g_ulHiGetTick & 0x8000;
           if(ulCurTime != g_ulLastTime)
           {
               (*g_pulTime)++;
               g_ulLastTime = ulCurTime;
           }
       }
       // Move from AD interrupt to here, to use idle mode better
   }
   else
   {
       if(T1CON_TCS)
           g_ulHiGetTick += PR1_SLOW;
       else
           g_ulHiGetTick += (PR1_SLOW/2);
       g_TestOther = true;

       uint16 ulCurTime = g_ulHiGetTick & 0x8000;
       if(ulCurTime != g_ulLastTime)
       {
           (*g_pulTime)++;
           g_ulLastTime = ulCurTime;
       }
   }
   // end of interrupt
}
/*****************************************

Help would be greatly appitiated.

/martin