EmbeddedRelated.com
Forums

What am I doing wrong?

Started by Julian Morrison September 16, 2005
> What am I doing wrong?
You are posting to usenet with a completely ambiguous subject line.
> The 16Cxxx PIC architecture requires the programmer to be aware of a > lot of things that are not very obvious. There are some pretty clunky > things about interrupts in particular. > > First, the stack is used only for return address information. > > You cannot push data onto it.
Which may actually be an advantage (for severely limited definitions of advantage) since the stack can be ignored and let to wrap around if you're coding in C and you want to use functions as if they were gotos, such as for coroutines.
> Second, the MOVFW instruction affects the ZERO flag.
Ah, that explains the swapf.
> You should not need to switch off the GIE from within an ISR as the > interrupt system is disabled until the RETFIE instruction is executed.
I was meaning: switch off the GIE when executing "regular" non-interrupt code that leaves bank 0 (to avoid being interrupted while in an unexpected bank). Also, if code passes through a critical section with GIE off, am I right it's a good idea to run the ISR manually to catch any missed interrupts (and rely on the retfie at the end to re-enable GIE)?
> NEVER USE ALL OF THE AVAILABLE REAL TIME IN THE INTERRUPT SERVICE > ROUTINES! > > In fact using more than 20% of the processor bandwidth in the ISRs can > make debug quite a challenge. Plus the interrupt response could be > quite bad.
When I said "do everything inside the ISR" I was meaning: sleep, wake on a timer interrupt, do what needs to be done, and sleep again. So the processor spends most of its time sleeping. Also, when doing this, only turn on the one timer interrupt; use the ISR to poll the others.
Julian Morrison schrieb:

> I was meaning: switch off the GIE when executing "regular" non-interrupt > code that leaves bank 0 (to avoid being interrupted while in an > unexpected bank).
It is good practice, to protect critical code sections, but why not save the context inside the ISR? If you let the PIC sleeping, the additonal instructions should not be a problem!
> Also, if code passes through a critical section with GIE off, am I right > it's a good idea to run the ISR manually to catch any missed interrupts > (and rely on the retfie at the end to re-enable GIE)?
Sorry, but it looks like you are missunderstanding the term ISR! An ISR is a pice of code, which is not called directly from the ohter code stuff. The entry to the ISR is placed to a special adress, and the processor itself run this code, if an event is detected. This event can be each enabled interrupt condition. If the processor jumps to the ISR, GIE will automaticly disabled, and inside the ISR you should never(!) re-enable interrupts (GIE). The RETFIE instruction is needed to leave the ISR and also re-enables interrupts. This is made to prevent nested runs of the ISR. You can also manualy check the interrupt conditions in your main programm, without(!) implementing an ISR. Then do not enable any interrupt, and only check the xxxF bits in INTCON and PIR1.
> When I said "do everything inside the ISR" I was meaning: sleep, wake on > a timer interrupt, do what needs to be done, and sleep again. So the > processor spends most of its time sleeping. Also, when doing this, only > turn on the one timer interrupt; use the ISR to poll the others.
If the PIC should sleep most time, and do some things from time to time, then you don't need implicitly a timer with interrupt. Often the the Watchdog is the better way, and with postscaler the PIC can sleep up to 2.3 sec. But please read the manual sections about all related things and conditions. HTH Michael
Michael Lange wrote:


>> Also, if code passes through a critical section with GIE off, am I >> right it's a good idea to run the ISR manually to catch any missed >> interrupts (and rely on the retfie at the end to re-enable GIE)? > > Sorry, but it looks like you are missunderstanding the term ISR!
Nope, not misunderstanding, being sneaky by doubling up the use of the ISR code. Based on the assumption: "retfie" is exactly equivalent to "bsf INTCON, 7" followed by "return". Therefore it doesn't matter who calls the ISR so long as this behaviour is intended. The code sequence I was thinking about: 1. normal code 2. GIE off 3. critical section (at this stage we need to check interrupts and switch on GIE) 4. jump to ISR via a normal "call" 5. ISR has been written to check interrupt bits 6. ISR conditionally does what needs doing 7. ISR finishes with "retfie" 8. retfie re-enables GIE and returns Result: code saved and simplified by checking interrupts in one place.
On Fri, 23 Sep 2005 12:09:31 +0100, Julian Morrison <julian@extropy.demon.co.uk> wrote:

>Michael Lange wrote: > > >>> Also, if code passes through a critical section with GIE off, am I >>> right it's a good idea to run the ISR manually to catch any missed >>> interrupts (and rely on the retfie at the end to re-enable GIE)? >> >> Sorry, but it looks like you are missunderstanding the term ISR! > >Nope, not misunderstanding, being sneaky by doubling up the use of the >ISR code. Based on the assumption: "retfie" is exactly equivalent to >"bsf INTCON, 7" followed by "return". Therefore it doesn't matter who >calls the ISR so long as this behaviour is intended. > >The code sequence I was thinking about: > >1. normal code >2. GIE off >3. critical section >(at this stage we need to check interrupts and switch on GIE) >4. jump to ISR via a normal "call" >5. ISR has been written to check interrupt bits >6. ISR conditionally does what needs doing >7. ISR finishes with "retfie" >8. retfie re-enables GIE and returns > >Result: code saved and simplified by checking interrupts in one place.
Why not just re-enable GIE - the interrupt will just happen if one is pending.
> Why not just re-enable GIE - the interrupt will just happen if one is > pending.
It will? What counts as "pending"? Will the interrupt fire if it happened at any time while GIE was off? Or, only if the cause is ongoing?
Julian Morrison wrote:
> > Why not just re-enable GIE - the interrupt will just happen if one is > > pending. > > It will? What counts as "pending"? Will the interrupt fire if it happened > at any time while GIE was off?
Yes, so you don't have to do anything.
> Or, only if the cause is ongoing?
The interrupt flags are sticky and are maintained regardless of the interrupt enables. (This also means it's usually disastrous to enable interrupts in the ISR.)
Julian Morrison schrieb:

> Nope, not misunderstanding, being sneaky by doubling up the use of the > ISR code. Based on the assumption: "retfie" is exactly equivalent to > "bsf INTCON, 7" followed by "return".
Not exactly, RETFIE prevent to re-enter the ISR before the return is executed! And that is a big difference.
> Therefore it doesn't matter who > calls the ISR so long as this behaviour is intended. > > The code sequence I was thinking about: > > 1. normal code > 2. GIE off > 3. critical section > (at this stage we need to check interrupts and switch on GIE) > 4. jump to ISR via a normal "call" > 5. ISR has been written to check interrupt bits > 6. ISR conditionally does what needs doing > 7. ISR finishes with "retfie" > 8. retfie re-enables GIE and returns > > Result: code saved and simplified by checking interrupts in one place.
Arrrghh! My result: It's not sneaky, you are fully missunderstand the whole concept of intrerrupts! This is my last hint: Before you think about such crazy stuff, study the basics and made some spimle things working. Michael
"Julian Morrison" <julian@extropy.demon.co.uk> wrote in message 
news:dh1dh0$pdb$1$8300dec7@news.demon.co.uk...
>> Why not just re-enable GIE - the interrupt will just happen if one is >> pending. > > It will? What counts as "pending"? Will the interrupt fire if it happened > at any time while GIE was off? Or, only if the cause is ongoing? >
We have not told you one of the really sneaky bit of the interrupt handling on the PIC processors. There are two global interrupt enable bits. One bit is the GIE bit in the INTCON register, bit 7. The other is buried inside the PIC with no direct access from the program. This bit is "set" when the RETFIE is executed and "cleared" when any interrupt is processed. For an interrupt to occur at least one interrupt source must be enabled, the GIE bit in INTCON must be set to one and the internal global interrupt enable must be "set". If the interrupt source is one of the peripheral device then the PEIE bit in INTCON must also be set to one. ----- An a second note as to "what else was wrong" in your code. There is a bug with the way you reload the TIMER ONE count register from the ISR. The bug is that the "t1rollover" is used to update TIMER ONE only when "rollover_count" reaches zero. This means the TIMER ONE will request an interrupt 10 milliseconds after the call to "SetClock" then count 65536 cycles 99 more times until "rollover_count" reaches zero. This results in a 6,498,064 cycles between changes of the LED. Or about 1.6 seconds using a 4MHz clock. But then you have already found this one. :)
"Keyser Soze" <noreturn@nothere.com> wrote in message 
news:j%40f.8409$oO2.3601@newssvr27.news.prodigy.net...
> [...snip...] > > There is a bug with the way you reload the TIMER ONE count register from > the ISR. > > The bug is that the "t1rollover" is used to update TIMER ONE only when > "rollover_count" reaches zero. > > This means the TIMER ONE will request an interrupt 10 milliseconds after > the call to "SetClock" then count 65536 cycles 99 more times until > "rollover_count" reaches zero. This results in a 6,498,064 cycles between > changes of the LED. Or about 1.6 seconds using a 4MHz clock.
this should be ---> 6.5 seconds <--- Forgot the divide by 4.