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