Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Variable delay loop accurate to the instruction cycle?

Status
Not open for further replies.

NateO

Technical User
Apr 21, 2006
3
0
0
CA
After searching your forum I haven't been able to come up with anything that fits my predicament. I'm hoping one of you experts can point me in the right direction.

I'm working on removing jitter from a clock that connects to a PC through an ISA bus. The system in question was designed and built around 18 years ago and all of the designers have since retired. At the moment we have around 6 us of jitter in the clock, but since we're using it to synchronise data collection at a wide variety of points across Canada (synched to a GPS time signal) it needs to be even better.

We've managed to track the jitter to a simple loop that basically waits for an interrupt. Because the interrupt can happen at any time during the loop and on any instruction, there are around 4 cycles of variablility (at approx 1.61 us / cycle). To remove this jitter all I need to do is synch the entry into that loop with a known instruction cycle. I can access a free running counter to determine the current cycle, but that takes time. Ideally I'd determine how many cycles I need to count, subtract the overhead from the calculation, and then count out that number. However, I can't come up with a way to count out a variable number of cycles that is accurate to the cycle. For instance, if I used a simple loop like

LOOP
DEC X
BNE LOOP

to count out X cycles I'd still be working with a 3 cycle delay every time I hit the branch. To my thinking that means my loop can only count in multiples of 4 instruction cycles. Is there a simple way of counting out an exact (but variable) number of instruction cycles?

The system we're using runs a Hitachi HD6303X microprocessor and I've been using a WinTek compiler. The interrupt I'm waiting for is an output compare interrupt triggered when the free running counter equals the output compare register. I tried briefly to use the WAI command to simply wait for the next interrupt but I'm not sure if it only waits for a hardware interrupt or if the OCI will successfully trigger it.

I know this message is really long winded but I wanted to give as much info on my problem as I could. Also no, this isn't a school project, but if anyone here has helpful information I'd be more than willing to assign them a mark based on just how helpful they were.

Thanks to anyone who reads this whole thing, and double thanks to anyone who tries to help.

-Nate
 
I'm not sure if I understand, but if you want to have a system doing something accurate to one cycle on any processor I'd have doubts about whether it's possible. There are all sorts of things that can hold the processor up for several cycles, including dynamic ram refresh, which can inflict wait-states. Remember, even if the loop is entirely inside the processor's cache and independant of the world, the moment the interrupt happens, the processor will need to interact with the world, and if the world is busy refreshing its dram, you'll have a delay. But I'm not an expert so ignore this if it's all rubbish!
 
Perhaps this pseudo code.
Code:
    ; read current cycle count
    ; subtract overhead
    ; jmp to zero_time - result
max_time:
    nop
    nop
    nop
    nop
    ; as many more nops for your max delay
    nop
    nop
zero_time:
    ; start of critical routine

Essentially, you have a big list of nop instructions (usually 1 cycle), and you compute a jump to the right spot which would give you the delay you calculated.

The larger the delay, the further away from zero_time you jump to and the more nop instructions you end up executing.

If you have a particularly large time interval to burn, then consider using some other function to wait for the bulk of the time and use this to wait for the accurate remainder.

--
 
The 6303 from hitachi and also the 6803 from motorola only read the interrupt pin during a instruction fetch.
So in your example the minimum delay would be that of
the branch that takes 3 cycle's to execute (if branch taken).
The minimum delay possibly with the 6303 is indeed the nop
but it takes 2 cycle's.
There is no instruction in the 6303 that actualy needs only 1 cycle.

You can use the wait instruction to sychronise since
it take's just in cycle to start the interrupt handling
but only afther the wait has done some work for it one.
Afther that it scans the interrupt pint and the internal
interrupt at every clock cycle.
So if you do not want the timer overflow or anny other
internal interupt take over your interrupt pin disable
the internal interrupt sources first.

The tomer output compare interrupt will be handled if you
enable it.

Succes, Tessa
 
First off thanks to all for the replies.

Lionel: Yeah, I have the nagging suspicion that what I'm trying to do might be close to impossible but they're paying me to give 'er a go, so I'd better do what I can. At this point I'm mostly hoping to get the clock jitter as small as possible, and I think I can improve on it's current state.

Salem: I'm actually trying to get that method to work right now. I figure that if the interrupt always triggers on a NOP then I can effectively eliminate jitter beyond the length of a single null operator (not including other delays as mentioned by Lionel). The first couple attempts haven't had much success, but at least I feel like I'm getting somewhere.

Tessa: Is there anything more to the WAI command than just putting it where you would like the code to wait? The output compare interrupt is already enabled (it's integral to the operation of our clock) but I simply tossing the WAI command in where I wanted the delay caused the system to hang (I assume waiting for an interrupt that never came). I'll try playing around with it a bit more to see if I can work it out.

Thanks again for the replies. It's been a while since I spent time with assembler so I'm still trying to remember the subtleties.

-Nate
 
You can put the wait allmost anywere, but be sure that
you let the global interrupt enabled.
That is: use a CLI before you goto the WAI instruction
else it can only be interrupted by the non maskeble
interrupt.
There is something that you have be sure of: the WAI
instruction can only do its proper work if it has the
time to put the register on the stack, so it has to be
executed in a time-slot that you know that the previous
interrupt has occurred and the next is to come only
afther +- 11 cycles.

Plaese don't get confused by the way the 80x86 interrupt
mask, it work just in the oposit.

So to enable the interrupt use CLI
to disable the interrupt use SEI.

Succes, Tessa

p.s. Using the WAI instruction is the only way to get the
minimum clock jitter, since that is the only
instruction that puts de registers on stack and
then waits for a interrupt.
From that point there is a stable cycle count when
a interupt is handled.
Even using the NOP can't garanty that.
 
A plusses (plusi?) all around. I used a combination of the two ideas to create a loop that eats up most of the time (down to the last 13 or so cycles) and then hits the WAI command. At first glance I'm now working with a nicely negligable jitter that's less than 1.5 us. I'm sure there are things that could cause it to jump around a little in certian situations, but if it stays around there during regular operation I'm more than happy.

Thanks again for the replies and advice. It's always good to have my ideas validated by someone who actually knows what they're doing.

-Nate
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top