Author Topic: Timing is everything  (Read 3380 times)

0 Members and 1 Guest are viewing this topic.

Offline PerranOakTopic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: gb
Timing is everything
« on: August 12, 2020, 02:42:37 pm »
I have got to grips with assembly and the timing of outputs, say, for accurate square wave creation or clock (as in alarm clock, etc.) updating.

What I can't figure out is how you do this in C. Surely, it compiles in a way that can't be relied upon for accurate timing purposes?

Even using timers, how do you know exactly how long it will take to perform the tasks after the triggering of the timer?
You can release yourself but the only way to go is down!
RJD
 

Offline agehall

  • Frequent Contributor
  • **
  • Posts: 390
  • Country: se
Re: Timing is everything
« Reply #1 on: August 12, 2020, 02:59:50 pm »
I don't think you should ever rely on C to be cycle exact. The code produced by a C compiler will probably be efficient but you can, in general, create more exact timings in assembly.

If you actually have the need for a instruction cycle perfect timing, why not mix and match? Write that bit in assembly and then the bulk of the code in C. Just make sure you disable all interrupts during the timing critical segments otherwise you never know what the timing will be.

Real question here though is if you really need that cycle exact timing? If so, maybe you are better off digging into FPGA land to ensure that your design executes in a predictable manner.
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 17272
  • Country: de
Re: Timing is everything
« Reply #2 on: August 12, 2020, 03:03:36 pm »
With C code one does not know the exact time a calculation will take. It can change with different compiler runs and optimization. With modern µCs that use caches or similar buffers even in ASM the run time is not so easy and can be effected from the context.
 In C one does need to use hardware support to get exact timing. Usually something like timers can create an accurate frequency or set some pins with a defined delay. Other HW parts may be used too, like DMA.  For some tasks it simply does not work in C and one may have to use ASM at least for the time critical part or use different hardware.
 

Offline PerranOakTopic starter

  • Frequent Contributor
  • **
  • Posts: 581
  • Country: gb
Re: Timing is everything
« Reply #3 on: August 12, 2020, 03:44:20 pm »
I see, thanks both.

Can you actually mix the two. Is it possible to write some assembly code then call it like a function?
You can release yourself but the only way to go is down!
RJD
 

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 17272
  • Country: de
Re: Timing is everything
« Reply #4 on: August 12, 2020, 04:00:09 pm »
One can mix C and ASM code. The details depend on the compiler used. Usually there are two options: one is using inline ASM to add a few ASM instruction directly inside the C code.

The other option is to use a separate ASM file to provide some functions (as a separate object file) that are than used in the C code. For the ASM function there would than be a header-file  (xxx-.h) to define the interface.

A very common example is inserting an instruction to block and later re-enable interrupts. This may be hidden in a predefined macro.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Timing is everything
« Reply #5 on: August 12, 2020, 04:13:30 pm »
Kleinstein notes the fundamentals, especially w.r.t. caches and interrupts.

However, there is one alternative where exact timing can be guaranteed due to:
  • FPGA-like i/o ports with timers, where you can specify the exact clock cycle on which the next output will occur (or record the clock cycle on which the last clock cycle did occur). Direct support for that in the language helps
  • no interrupts, no caches
  • IDE tool support that analyses the optimised code to determine all the possible timings between here and there

That is the XMOS xCORE devices and xC.

Here's a code fragment that bit-twiddles the control and data lines going to a simple LCD display controller. The timing of all the outputs are guaranteed to be correct with a resolution of 10ns.
Code: [Select]
// lcdE, lcdRW, are 1-bit ports connected to the LCD's enable and read/write lines
// lcdData is a 4-bit port connected to the LCD's data lines
// lcdE @ (x) <: 1  outputs a 1 when the timer is x

// interface timing in 100MHz ticks, taken directly from the LCD data sheet with margin added to assuage my pessimism
#define Tsp1    (6)     // min 40ns
#define Tsp2    (10)    // min 80ns
#define Thd2    (2)     // min 10ns
#define Tpw     (26)    // min 230ns
#define Td      (14)    // min 120ns
#define Tcyc    (60)    // min 500ns

static void lcdWriteByteNoWait(int byte) {
    uint32_t tStart;
    lcdRW <: 0 @ tStart;
    // high nybble
    lcdE @ (tStart+Tsp1) <: 1 ;
    lcdData @ (tStart+Tsp1+Tpw-Tsp2) <: (byte >> 4);
    lcdE @ (tStart+Tsp1+Tpw) <: 0;
    // low nybble
    lcdE @ (tStart+Tsp1+Tcyc) <: 1 ;
    lcdData @ (tStart+Tsp1+Tcyc+Tpw-Tsp2) <: (byte & 0xf);
    lcdE @ (tStart+Tsp1+Tcyc+Tpw) <: 0;
    // complete the two cycles; use RW to avoid optimisation
    // and to give an external hint it has finished
    lcdRW @ (tStart+Tsp1+Tcyc+Tcyc) <: 1;
}

FFI, see the XMOS literature :)
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline Twoflower

  • Frequent Contributor
  • **
  • Posts: 745
  • Country: de
Re: Timing is everything
« Reply #6 on: August 12, 2020, 04:36:39 pm »
Do you really need cycle exact timings? In that case I would think about to do some things in hardware (e.g. FPGA) as small changes (IRQs, different clock trees of internal busses vs. core) will potentially cause an unwanted jitter.

Depending on what your actual needs are you might check if the processor has some dedicated HW supporting you. Like Timers or PWM outputs can be used to generate an exact clock signal or other function blocks.

And I'm sure you're aware that if your application can accept some kind of jitter for the function but you need an exact timing over long time (e.g. second counter for a watch it doesn't matter if one call is after 1002ms and the next after 998ms) you don't stop and re-arm the timer that generates the interrupt just let it run all the time. It just triggers every 1000ms no matter what. Depending for example how much time the context switch takes the interrupt will be served might start sooner or later.
 

Offline NorthGuy

  • Super Contributor
  • ***
  • Posts: 3565
  • Country: ca
Re: Timing is everything
« Reply #7 on: August 12, 2020, 04:50:05 pm »
Your MCU probably has a PWM module which can produce the output without CPU. You can use it in C. If it's too slow, you may also need DMA to automatically move data to PWM.
« Last Edit: August 12, 2020, 06:32:35 pm by NorthGuy »
 

Online David Hess

  • Super Contributor
  • ***
  • Posts: 19240
  • Country: us
  • DavidH
Re: Timing is everything
« Reply #8 on: August 12, 2020, 07:40:44 pm »
A trick I have used is to precompute values to be stored in the *next* cycle, after storing the values in the current cycle.  So the first thing which happens after the interrupt is triggered is to store the values computed last cycle, and only then compute values for the next cycle which can involve a variable number of instruction cycles.  This removes jitter between the interrupt and store operations.
 
The following users thanked this post: jnz

Online Kleinstein

  • Super Contributor
  • ***
  • Posts: 17272
  • Country: de
Re: Timing is everything
« Reply #9 on: August 12, 2020, 08:12:49 pm »
With many µCs the time when an interrupt is actually executed can vary a little, e.g. depending on the instruction that is interrupted. So there can be some additional jitter at the start of the interrupt.

In some cases PWM mode can be programmed to change a pin at a predefined time, not effected by the exact time when the PWM registers are updated.
If nothing else help one can have an external flipflop to synchronize the output signal(s) to an external slower clock. This way one can also get around µC internal phase shifts that can happen from µC internal HW. I have seen the ADC and UART effect the phase of IO port changes with an AVR µC -  not much (sub ns), but visible.
 

Offline jnz

  • Frequent Contributor
  • **
  • Posts: 593
Re: Timing is everything
« Reply #10 on: August 12, 2020, 11:37:16 pm »
Your MCU probably has a PWM module which can produce the output without CPU. You can use it in C. If it's too slow, you may also need DMA to automatically move data to PWM.

This is the right answer. Waveform timing is exactly what PWM with DMA is for.

A trick I have used is to precompute values to be stored in the *next* cycle, after storing the values in the current cycle.  So the first thing which happens after the interrupt is triggered is to store the values computed last cycle, and only then compute values for the next cycle which can involve a variable number of instruction cycles.  This removes jitter between the interrupt and store operations.

This is a good answer for doing it the harder way.
 

Online David Hess

  • Super Contributor
  • ***
  • Posts: 19240
  • Country: us
  • DavidH
Re: Timing is everything
« Reply #11 on: August 12, 2020, 11:40:38 pm »
A trick I have used is to precompute values to be stored in the *next* cycle, after storing the values in the current cycle.  So the first thing which happens after the interrupt is triggered is to store the values computed last cycle, and only then compute values for the next cycle which can involve a variable number of instruction cycles.  This removes jitter between the interrupt and store operations.

This is a good answer for doing it the harder way.

If you are making the most of limited hardware, it may be the only way.  I do not think it is anymore difficult but it does require a change in perspective.
 

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 23122
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Timing is everything
« Reply #12 on: August 13, 2020, 07:03:44 am »
With many µCs the time when an interrupt is actually executed can vary a little, e.g. depending on the instruction that is interrupted. So there can be some additional jitter at the start of the interrupt.

Just so.

As you note below, that's avoided if you can ensure your general purpose i/o occurs when a timer times out without processor intervention.

Quote
In some cases PWM mode can be programmed to change a pin at a predefined time, not effected by the exact time when the PWM registers are updated.
If nothing else help one can have an external flipflop to synchronize the output signal(s) to an external slower clock. This way one can also get around µC internal phase shifts that can happen from µC internal HW. I have seen the ADC and UART effect the phase of IO port changes with an AVR µC -  not much (sub ns), but visible.

PWM is a very boring example of such an output change, of course!

If interrupt latency variations caused a problem with PWM outputs, then I'll bet it would be better to use a conventional DAC.
« Last Edit: August 13, 2020, 07:33:49 am by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->