Using timing functions - page 4 - General Discussion and Assistance - CHDK Forum  

Using timing functions

  • 66 Replies
  • 27646 Views
Re: Using timing functions
« Reply #30 on: 11 / April / 2014, 11:27:39 »
Advertisements
Just tried making the variable global, and it works properly now. Can't believe I wasted an entire day just because I underestimated the intelligence of GCC  >:(

Quote
You could try to put
Code: [Select]

asm volatile ("nop\n");

inside you loop, that might stop the compiler from optimizing it out.
OK thanks I'll try that in the second problem I had in my previous post.

Re: Using timing functions
« Reply #31 on: 11 / April / 2014, 11:48:28 »
Just tried making the variable global, and it works properly now. Can't believe I wasted an entire day just because I underestimated the intelligence of GCC  >:(
Quote
You could try to put
Code: [Select]
asm volatile ("nop\n");
inside you loop, that might stop the compiler from optimizing it out.
OK thanks I'll try that in the second problem I had in my previous post.
FWIW,  the compiler may not have optimized the loop out.  All it needed to do was put "variable_to_increment" in a register rather than memory and the loop would run thousands of times faster than in your previous example.
« Last Edit: 11 / April / 2014, 11:53:04 by waterwingz »
Ported :   A1200    SD940   G10    Powershot N    G16

Re: Using timing functions
« Reply #32 on: 11 / April / 2014, 13:13:31 »
Quote
Quote

    You could try to put
    Code: [Select]

    asm volatile ("nop\n");

    inside you loop, that might stop the compiler from optimizing it out.

OK thanks I'll try that in the second problem I had in my previous post.
Actually it still freezes for some reason. But it works when I make it increment a global variable, so I'll call it fixed.

Quote
No need to guess, locate your functions in core/main.bin.dump or post that file here.
How would I go about locating a certain function in it? (not that I need to, but just out of interest) Would I look through the extracted strings, and what would I look for if so? For decompiling I'm using Radare. (not that I really know anything about assembly yet though)


Also, what's this about the timer not wrapping exactly?
Quote
Since the hardware counter wraps nearly (but not exactly  >:( ) once a second, ...
How much is "not exactly" out by, a few microseconds, or much more? Is it syncing with the internal RTC or something?

Re: Using timing functions
« Reply #33 on: 11 / April / 2014, 13:44:20 »
Quote
Also, what's this about the timer not wrapping exactly?
Quote
Since the hardware counter wraps nearly (but not exactly  >:( ) once a second, ...
How much is "not exactly" out by, a few microseconds, or much more? Is it syncing with the internal RTC or something?
More Software 101.   It's a 20 bit timer that increments once a uSec. 

2**20-1 = 1048575

So it wraps every 1.048575 seconds.
Ported :   A1200    SD940   G10    Powershot N    G16


Re: Using timing functions
« Reply #34 on: 11 / April / 2014, 14:01:20 »
Oh that explains it thanks. I was under the impression that it counted up to 2^20 every real second and that by 'microsecond' we were reffering to one 1048576th of a second. I would have thought this would be more logical but I guess the canon engineers thought differently.

So this won't be a problem, still I don't look forward to writing a wraparound though. Has anyone else written one yet by any chance?

*

Offline ahull

  • *****
  • 634
Re: Using timing functions
« Reply #35 on: 11 / April / 2014, 15:48:16 »
Oh that explains it thanks. I was under the impression that it counted up to 2^20 every real second and that by 'microsecond' we were reffering to one 1048576th of a second. I would have thought this would be more logical but I guess the canon engineers thought differently.

So this won't be a problem, still I don't look forward to writing a wraparound though. Has anyone else written one yet by any chance?

For the record, there is a logical, but possibly not very interesting reason for this (which you may already be aware of, in which case my apologies for butting in  ;) ).

Typically this sort of  timer is driven by an oscillator that runs at a precise frequency, rarely is that frequency an exact binary fraction of a second.

The exception being things like real time clock chips, and digital watch crystals who's purpose is to generate human readable time, and which typically run using a precision 32768 Hz crystal. This frequency is chosen because if we divide 32768 by 2^15 we get a precise 1Hz signal (i.e. if we count to 2^15 using a 32768 Hz oscillator it will take us exactly 1 second (+/- the accuracy of the crystal) see here for more details). 

The CPUs and other logic in a modern camera and other computing devices tend to run at many MHz or even  tens or hundreds of MHz,  and thus their frequencies are often, not easily divided by a power of 2 to give exactly 1Hz.

A 1MHz clock for example will give you precise timings in binary multiples of 1/1000,000 second but is not *exactly* related by a power of 2 to give precisely 1 second timings.

In practice, this is usually not a problem , so long as we know how many "ticks" of our clock will give us one second, we can use the counter part of the timer to count to this number, or down from this number to zero, then generate our interrupt (depending on the type of timer we are dealing with, some count from zero to the chosen number, some count down from the number to zero, some can be programmed to do either).

If we require interrupts at precise (for example one second) intervals, and if  we are dealing with a counter/timer , and if we know how to set up the counter and interrupt functions of this timer, and if we are able to handle the resultant interrupt(s), everything can be done in software.

I am not sure if all of these "ifs" are known in the  case of the Digic timers.

The timers we are looking at in the Digic processors are probably broadly similar in operation to this or this,
however since the Digic family are Canon specific hardware, their exact functional nature would have to be reverse engineered by comparing with similar devices, and by reading the code in the firmware to discern their operation. Some of this work has been done on the Magic Lantern site, and some has been done in this forum.
« Last Edit: 11 / April / 2014, 17:04:03 by ahull »

*

Offline reyalp

  • ******
  • 14118
Re: Using timing functions
« Reply #36 on: 11 / April / 2014, 23:53:35 »
More Software 101.   It's a 20 bit timer that increments once a uSec. 

2**20-1 = 1048575

So it wraps every 1.048575 seconds.
I realized I assumed this from srsa's description, without actually verifying. But it appears to be true:
Code: [Select]
con> .set_yield(-1,-1) local t0=peek(0xc0242014) while peek(0xc0242014) > t0 do end local tick0=get_tick_count() for i=1 ,10 do t0=peek(0xc0242014)while peek(0xc0242014) > t0 do end end return get_tick_count() - tick0
con 1> getm
1:return:10490
(. and getm are required instead of = because polling PTP fails when the camera is in a tight no yield loop like that.)
Don't forget what the H stands for.

*

Offline srsa_4c

  • ******
  • 4451
Re: Using timing functions
« Reply #37 on: 12 / April / 2014, 10:08:31 »
Quote
No need to guess, locate your functions in core/main.bin.dump or post that file here.
How would I go about locating a certain function in it? (not that I need to, but just out of interest)
That's the disassembled version of the CHDK core, created during compilation. All functions are identified by their names, so just search for that.
Quote
For decompiling I'm using Radare.
Hmmm. One more utility I didn't know about. Unfortunately neither of its graphical frontends (web, bokken) is working for me for ARM.
But, as written above, you don't need to decompile anything at this point.


Re: Using timing functions
« Reply #38 on: 12 / April / 2014, 14:20:30 »
Quote
That's the disassembled version of the CHDK core, created during compilation. All functions are identified by their names, so just search for that.
Ahh I see. Probably should have opened the file before just loading it into that program. The names are in there in several places.

Quote
Hmmm. One more utility I didn't know about. Unfortunately neither of its graphical frontends (web, bokken) is working for me for ARM.
Yeah it didn't work for me either, but it's terminal interface isn't too bad. Anyone know of any other decent free decompilers (that run on Linux)?

Quote
(. and getm are required instead of = because polling PTP fails when the camera is in a tight no yield loop like that.)
What is getm and how should it be used? I couldn't find anything on google about it, is it a CHDK only thing?


Quote
For the record, there is a logical, but possibly not very interesting reason for this (which you may already be aware of, in which case my apologies for butting in  ;) ). ...
Thanks for the explanation, I guess that shifts the problem back to why the crystals are all based on powers of 10, (with maybe a power of 2 thrown in eg. 16000000Hz). One of the problems humanity faces living under the curse of base 10, if only God / evolution had given us 8 (or 16) fingers instead.  >:(



Anyway, after giving up trying to get a good result messing about with that uSec timer, I tried the following:
Code: [Select]
void LED_flasher()
{
    while (variable_counting_repetitions < 65536)
    {
        *((volatile int *) AF_LED_ADDRESS) = LED_ON;
        while (variable_to_increment_0 < 1024)
        {
            variable_to_increment_0++;
        }
        //variable_to_increment = 0;
        *((volatile int *) AF_LED_ADDRESS) = LED_OFF;
        while (variable_to_increment_1 < 1024)
        {
            variable_to_increment_1++;
        }
        //variable_to_increment = 0;
        variable_counting_repetitions++;
        unread_variable = variable_to_increment_0 + variable_to_increment_1;
        variable_to_increment_0 = 0;
        variable_to_increment_1 = 0;
    }
   
    start_LED_flasher = 1;
    variable_counting_repetitions = 0;
    variable_to_increment_0 = 0;
    variable_to_increment_1 = 0;
}
(Note that the seemingly unnecessary unread_variable is needed to stop the compiler messing things up. Also the no-operation asm command didn't seem to help unfortunately)

Runs for 8 seconds (about one period per 80uS), and gives out a nice clean-looking signal. Just using my el-cheapo pocket DSO Nano (don't buy one, they're rubbish) at the moment, but I'll give it a proper analysis on the scope tomorrow. Of course, I don't actually plan on transmitting this fast, but this is just a proof of concept.

I'm not completely sure how the CPU allocates its clock cycles out, can I assume that while this is running, nothing else is? If so, with a bit of compensation for how long it takes the CPU to process the incoming/outgoing signal, this could probably be the basis of what I'll use for transmitting reasonably fast data-packets.

Re: Using timing functions
« Reply #39 on: 12 / April / 2014, 14:34:23 »
Anyone know of any other decent free decompilers (that run on Linux)?
While it's a bit simplistic and specialized,  this works under Wine and is tweaked for CHDK : CHDK_PT.  The source is available if you want to tweak it.

Quote
What is getm and how should it be used? I couldn't find anything on google about it, is it a CHDK only thing?
You need to study the code & docs for chdkptp.  It seems that reyalp no longer posts plain script code - just commands that run from the chdkptp command line  ;)

Quote
Thanks for the explanation, I guess that shifts the problem back to why the crystals are all based on powers of 10, (with maybe a power of 2 thrown in eg. 16000000Hz).

Think of it from the point of view of the embedded firmware engineer.  He wants things to run at well understood intervals, so a clock that lets him work in multiple of uSecs makes a lot of sense.

Quote
I'm not completely sure how the CPU allocates its clock cycles out, can I assume that while this is running, nothing else is?
Until it's interrupted or yields,  the current task gets all of the CPU.  I think that's what you were asking?
Ported :   A1200    SD940   G10    Powershot N    G16

 

Related Topics


SimplePortal 2.3.6 © 2008-2014, SimplePortal