Shop OBEX P1 Docs P2 Docs Learn Events
RTCC, Prescalers, and retiw — Parallax Forums

RTCC, Prescalers, and retiw

JamesxJamesx Posts: 132
edited 2005-08-25 02:08 in General Discussion
I am trying to get an ISR to execute 1440 times per second. That would be every 694.4 usec. Using the prescaler set to 1:256, the RTCC will be incremented once every 256 cycles. If the clock is set at 50 MHz, that would be 5.12 usec. Dividing the 694.4 by 5.12 yields 135.6, rounded to 136. So, if the interrupt occurred after the (prescaled) RTCC is incremented 136 times, we would be pretty close (5.12 * 136 = 696.3 usec).

But here's the question: at the end of the ISR, I presume you would need to use an retiw to reset the RTCC to -136. If I read the manuals correctly, that retiw would reset the prescalar. If it does, the count of machine cycles monitored by the prescaler gets lost, so the length of the total time to the next ISR becomes unpredictable (+/-256 machine cycles). It would be better if the program would exit the ISR just as the prescaler is rolling over, and retiw was executed at that time. Then, everything would stay lined up with proper complete prescaler durations.

Any suggestions on how to do this?

James

Comments

  • BeanBean Posts: 8,129
    edited 2005-08-19 15:00
    I don't think retiw resets the prescaler. I think setting the OPTION register resets it. I'm not 100% sure on those.
    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    "SX-Video·Module" Now available from Parallax for only $28.95

    http://www.parallax.com/detail.asp?product_id=30012

    Product web site: www.sxvm.com

    "One experiment is worth a thousand theories"
    ·
  • PJMontyPJMonty Posts: 983
    edited 2005-08-19 15:28
    James,

    No, just do a:


         mov w, #-136
         retiw
    



    and the SX will generate an interrupt every 136 prescaled cycles every time. If it didn't, every software project that depended on a fixed interrupt rate and used a prescaler other 1:1 wouldn't work.
      Thanks, PeterM
  • Paul BakerPaul Baker Posts: 6,351
    edited 2005-08-19 15:35
    Dont forget to compensate for the time your ISR takes to execute.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·1+1=10
  • PJMontyPJMonty Posts: 983
    edited 2005-08-19 19:58
    Paul,

    No, you don't have to compensate for anything. That's what the "-136" is all about. Thanks to the magic of integer math (and good design work by the folks that made the SX), the interrupt duration expressed as a negative number is added to the current RTCC value and the result is the number of cycles needed to create the same duration interrupt calculated from when the current interrupt began.

    Think about it - you never see people struggle to make sure that the interrupt code is always the same length no matter what path is chosen. If you had to do that, it would be next to impossible to create jitter free interrupts without herculean coding efforts.

    The really cool thing about the SX is that all you have to ensure is that the longest path of your interrupt code is shorter than the length of the interrupt period. Do this and you'll always have a fixed and jitter free interrupt rate. It doesn't matter if one path through the interrupt code takes 16 cycles and a different path takes 100. As long as the longest code path is shorter than the interrupt period, setting w to a negative version of the desired interrupt period lets the SX guarantee consistency.

    finally, remember that the interrupt code duration is counted in clock cycles, but the RTCC interrupt period is counted in prescaled clock cycles. If the prescaler is at 2:1, then setting an interrupt period of -100 gives you 200 clock cycle of execution due to the prescaler.

    Cool stuff.
      Thanks, PeterM
  • Paul BakerPaul Baker Posts: 6,351
    edited 2005-08-19 20:54
    You are correct, what confused me was this paragraph: "Adding W to RTCC allows the interrupt service routine to restore the RTCC to the value it contained at the time the main program was interrupted. To use this feature, the interrupt service routine should check the RTCC at the beginning of the routine and again at the end of the routine, and then put the adjustment value into W before returning from the interrupt." But carefully rereading this, its clear what they are describing is an equal time execution within the main program regardless of the time spent in the ISR, but James is seeeking equal time between ISR calls, and since the RTCC doesn't stop, this is automatically taken care of.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ·1+1=10
  • mojorizingmojorizing Posts: 249
    edited 2005-08-19 22:05
    Additionally, the first RTCC interrupt will be longer since RTCC counted up from 0 to 255, not from -136. This means you'll have to pre load RTCC with the correct number so that you'll get the correct elapsed time for that first interuppt. Subsequent RTCC interupts will be correct with mov w, #-136.

    later, Kevin

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    There are 10 kinds of people in the world.... those that know binary, and those that don't.
  • JamesxJamesx Posts: 132
    edited 2005-08-20 00:21
    Thanks, y'all, for your ideas. Kevin: the first interrupt being inaccurate won't matter to this application, but thanks for the reminder.
    Peter: you wrote "If it didn't, every software project that depended on a fixed interrupt rate and used a prescaler other 1:1 wouldn't work."
    That's what I thought, too, but I couldn't find any documentation to confirm that.
  • pjvpjv Posts: 1,903
    edited 2005-08-20 06:36
    Hi All;

    There is of course another way to deal with ISR timings.

    Often I need to exit the ISR from various different points, and sometimes it is a calculated exit, and it might not be convenient to have the value loaded in W to restore the RTCC. So, what can be done in those cases, is to write the desired restore value directly into the RTCC as soon as the ISR is entered, and from that point on, the number of steps to an exit is immaterial as the RTCC reload issue has already been dealt with.

    In doing this, it it importamt to realize that immediately after writing to the RTCC, its value is frozen for 3 (or was it 2?) instructions before it continues counting on subsequent instructions, hence a slight adjustment needs to be made for that.

    If I recall correctly, for this technique to be used as the first 2 lines in the ISR, I believe the code reads as:

    INTPERIOD EQU -100 ;for a 100 instruction, 2 uSec tick at 50 MHz

    ISR·········· MOV W,#INTPERIO+8············· ;negative interrupt period plus 8 overhead instruction ticks = -100+8 = -92
    ···············MOV· RTCC,W························;sets the rtcc for the next interrupt time, and RTCC can now be ignored from this point
    ···············......··································· ·;
    ·············· ......··································· ·;any arbitrary code
    ·············· RETI···································· ;exit the ISR without any further regard to the RTCC; do NOT use RETIW

    If for some reason, this RTCC treatment cannot be at the first 2 lines in the ISR, hence it must be dealt with further doen, then for every INSTUCTION downward, the "overhead" value must be increased by one.

    Normally I use the standard RETIW approach to exiting ISR, but on occasion, in complicated situations, the technique described here is more convenient.

    Also, please be aware that if you test this out, single stepping the SX Key in DEBUG mode, you can see the "frozen" RTCC value after it has been written, BUT the displayed value is incorrect by one count. Unfortunately just now I can't recall if it is one high or one low.

    Just another of the neat tricks you can do with an SX.

    Cheers,

    Peter (pjv)

    Post Edited (pjv) : 8/20/2005 6:35:58 AM GMT
  • BeanBean Posts: 8,129
    edited 2005-08-20 15:32
    Can anyone confirm if writing to the OPTION register resets the prescaler ?
    If not, does anything reset the prescaler ?
    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    "SX-Video·Module" Now available from Parallax for only $28.95

    http://www.parallax.com/detail.asp?product_id=30012

    Product web site: www.sxvm.com

    "One experiment is worth a thousand theories"
    ·
  • Guenther DaubachGuenther Daubach Posts: 1,321
    edited 2005-08-20 16:33
    Bean,

    I have carefully studied the SX 28 datasheet but could not find any information wether writing to the OPTION register resets the prescaler or not. I think, in "real life", this is nothing we need to be concerned about anyway. Usually, the OPTION register would be setup in the application's initialization section. There, it will be defined if the prescaler shall be used for the watchdog or for the RTCC, and what divide-by factor shall be used (if any).

    I usually write to the OPTION register at the very beginning of my applications, disabling the RTCC roll-over interrupt, then do aother initializations, like clearing the RAM, setting up the port configurations, etc. This makes sure that no interrupt occurs while variables and ports are not yet hplding defined states. Finally, before entering the main loop, I enable RTCC roll-over interrupts when the application shall make use if it with an ISR.

    Somehow, it would be logical if the prescaler were cleared to make sure a "clean" start when OPTION is modified. In case this is not so, the first call of the ISR might be out of timing, where all subesquent calls would be fine - IMO not a big problem at all.

    So, unless you plan to write some "tricky" application that modifies the OPTION register during "normal" program execution, e.g. to temporarily disable the RTCC intreerupt, it does not matter what happens to the prescaler.

    Finally, I think the only way to really find out if the prescaler is cleared or not during OPTION writes is to write a test application. Let me try to do that, and I'll report the results later. In case, someone already did this, please bail in.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Greetings from Germany,

    G
  • dkemppaidkemppai Posts: 315
    edited 2005-08-22 18:39
    pjv said...
    Hi All;

    There is of course another way to deal with ISR timings.

    Often I need to exit the ISR from various different points, and sometimes it is a calculated exit, and it might not be convenient to have the value loaded in W to restore the RTCC. So, what can be done in those cases, is to write the desired restore value directly into the RTCC as soon as the ISR is entered, and from that point on, the number of steps to an exit is immaterial as the RTCC reload issue has already been dealt with.
    I do this a lot. It just seems a lot cleaner.

    Again, be careful that all ISR routines are shorter than the ISR period. As for·checking ISR routine lengths,·for testing I like·to set and clear a bit on enter and exit of ISR routines and check timing with a good Oscilloscope! It's a lot easier than counting clock cycles manually...

    -Dan
    ·
  • Brian RileyBrian Riley Posts: 626
    edited 2005-08-23 23:50
    OK, let me see If I have this right ... I was looking at Jon's SX/B adaptation of Gunter SX robot code. he has an 8 MHz clock for a 104 return value for a 13 microsecond interrupt period. I am waiting on some 8 MHz resonators. In the meantime I want to run with 50 MHz resonators I do have, so pencil and paper in hand I figured a 1:4 pre-scaler value with a count of 163 gets me the same thing (13.04 usecs to be exact!) Did I figure it correctly?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cheers ... brian riley, n1bq, underhiull center, vermont
  • James NewtonJames Newton Posts: 329
    edited 2005-08-24 00:07
    http://www.sxlist.com/techref/scenix/isrcalc.htm

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    James Newton, Host of SXList.com
    james at sxlist,com 1-619-652-0593 fax:1-208-279-8767
    SX FAQ / Code / Tutorials / Documentation:
    http://www.sxlist.com Pick faster!



  • PJMontyPJMonty Posts: 983
    edited 2005-08-24 01:47
    Peter (pjv),

    While others choose different approaches, I am of the school that believes in every routine having a single entrance and single exit point. When coding in a language like C, there is a huge benefit to this when dealing with a function that allocates and then frees (or not) memory. If I had multiple exit points, then every place where I can exit I need to have code to handle the issue of whether or not to free memory. Further, if I add another pointer that gets memory allocated to it, then each of those exit points needs to have an additional check added to it.

    By having a single exit, I know that the code to (potentially) free any resources is in a single place at the end of the function. If I add resources, I just add the checks for free-ing them in that single location. Whenever I run Boundschecker on my C projects, it's extremely rare that I have resources that aren't free'd due to this coding practice. My programs never lose memory or resources simply because this approach makes it easy to avoid the problem.

    I follow the same approach when coding in assembly. The only exception I make is if I have a function that has to execute in the smallest number of cycles and I don't have enough cycles to add any extra checks or jumps. However, I only do that after I find out that I don't have enough room. The first rule of code optimizing is do your optimizing after the program already works. If you don't, you end up optimizing things you think are time or size critical only to find out that they aren't.

    I'm curious what situations make you have multiple exit points in your code.
      Thanks, PeterM
  • pjvpjv Posts: 1,903
    edited 2005-08-24 02:55
    Hi Peter;

    I agree with your approach completely, and follow that technique whenever appropriate. However, other than for tests, I have never written in anything other than assembler (I only know the most rudimentary high level language constructs, and for SX C, was VERY disappointed in the useless garbage it created), and have never had need for allocating/releasing resources. So my needs are very simple indeed, albeit excruciating in responsiveness. My preemptive and non preemptive "standard" RTOS ticks are 1 uSec, hence you can see I expect a LOT out of my ISRs; there are never cycles to waste.

    I do a LOT of work with state machine formats because they lend themselves very nicely to the co-operative non-preemptive as well as the peemptive multi-tasking RTOS environment I use; virtual UARTS for example. It lets me VERY conveniently run multiple threads at one time, where one thread need have only little regard for any other thread. - I would dread the situation I see in so many of these posts where people actually freeze the processor by using a "PAUSE" function to set timings; how horrid!

    The multiple exits I elude to are issues that arise principally where one exits the ISR from one of numerous states, and sometimes the decision to exit or not depends on simple SB/SNB bit tests, with no convenient immediate way to load up a value for W. Essentially the RETIW is a 2 instruction pair, and (only at times) this is inconvenient. In those cases I resort to exiting the ISR with a simple RETI, having previously (generally on entry into the ISR) set the desired RTCC value with a direct write as this is a good and simple solution to these situations.

    In essence, in my work processor performance is paramount, and speed is everything; hope this explains my rationale, Peter.

    Cheers,

    Peter (pjv)
  • PJMontyPJMonty Posts: 983
    edited 2005-08-24 06:34
    Peter (pjv),

    Interesting stuff. Yeah, I think a 1 MHz interrupt rate qualifies as fast. Also interesting that you pretty much only code in assembly. While I enjoy the fine grained control of working on embedded processors in assembly, there are also times I appreciate a high level language running on a system with a ton of ram and hard drive space. I think the variety keeps my head from exploding.
      Thanks, PeterM
  • pjvpjv Posts: 1,903
    edited 2005-08-24 16:30
    Hi Peter;

    Right. I'm not saying that high level languages have no place; far from it. It's just that I don't enjoy "big software" so I keep my interests focussed pretty much on embedded stuff that needs to be REAL FAST and yet can still be effectively managed in straight assembler, this way I get that really close interaction with the machine.

    I get real pleasure out of squeezing the most out of an SX; when you get deep into it, its amazing what can be accomplished with 50 Mips. For example, now that I have the RAMTRON serial FRAMS up and running in a streaming mode at 5 Mbits/sec, I intend to use that for generating/reading Psuedo Noise sequences for a direct sequence spread spectrum radio link I'm designing, and that would like to run continuously at 5 Mega Chips/Sec for 10 Mhz spreading......should be an awsome, almost undestructible link. We'll see.

    Enough of my rambling,

    Cheers,

    Peter (pjv)
  • Brian RileyBrian Riley Posts: 626
    edited 2005-08-25 02:08

    Thanks .... boy that sure is handy!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    cheers ... brian riley, n1bq, underhiull center, vermont
Sign In or Register to comment.