This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

is this a good idea?

Hello,

I have a free running hardware timer on a LPC2478 (timers are 32 bit). no interrupts related to that timer are used.

can the following code corrupt the value latched from
the hardware timer, if the timer ticks just when the copy is done? can it cause a misbehavior of the loop? I know this is not a good programming example - I'm just curious.

unsigned long timer_value_ref = T2TC ;

do
{
}
while (T2TC - timer_value_ref < 1000) ;

  • can it cause a misbehavior of the loop?

    To judge that, you'll have to describe the desired behavior of the loop first.

    can the following code corrupt the value latched from the hardware timer, if the timer ticks just when the copy is done?

    On an ARM, the read should be atomic (unless the compiler messes things up), so there shouldn't be any atomicitiy issues.

    However, in the unlikely case that the loop takes longer than it takes the timer to overflow, you might get a longer delay than you expected.

  • thanks for your reply. I have a hardware timer running in an application. the last thing I want is to start disabling and re-enabling it just to query its value.
    could you please explain what you mean by this statement?
    On an ARM, the read should be atomic

    is this something built into the architecture itself? or is it a result of the generated assembly? do you mean that reading the value of a hardware timer prevents it from being updated by hardware?

  • The processor is fully 32-bit, so it can read a 32-bit variable from without the possibility of an ISR to interfere.

    But anyway - a variable handled by two threads or between the main application and an ISR should be specified as volatile, to make sure that the compiler always reloads the current value (possibly changed by the ISR or another thread) instead of loading the variable once and then just relying on the contents in a register.

  • is this something built into the architecture itself?

    The capability for it is built into the architecture - an ARM core can read a 32-bit value to a register with a single read access to memory.

    This is different from, say, an 8051 which needs multiple read accesses to move 16- or 32-bit values to its registers. In this case, consider the following scenario:

    Cycle n
    Timer value: 0xFFFFFFFF
    CPU reads byte0: 0xFF

    Cycle n+1
    Timer value: 0x00000000
    CPU reads byte1: 0x00

    Cycle n+2
    Timer value: 0x00000001
    CPU reads byte2: 0x00

    Cycle n+3
    Timer value: 0x00000002
    CPU reads byte3: 0x00

    So the CPU read the value 0x000000FF, which is clearly wrong. An ARM MCU would read the full 32 bits in the first cycle, 0xFFFFFFFF.

    or is it a result of the generated assembly?

    Well, the compiler could technically, theoretically, read the 32-bit value with multiple read accesses (2 if it reads 16-bit halfwords, 4 if it reads 8-bit chars), but that would be a fairly evil compiler, since there's only disadvantages to doing so (takes longer than a single 32-bit read and creates the possibility of atomicity issues).

    do you mean that reading the value of a hardware timer prevents it from being updated by hardware?

    If there's only a single 32-bit read, then the read value should be valid even if an update happened on the timers side. (Unless it's a borked timer implementation that's prone to glitches in the register, but that should be documented in the datasheet).

  • thank you very much for your explanations.

  • Just a note. If the ARM core/memory interface requires that the compiler switches to multiple smaller read/write operations for unaligned accesses, then you must not request that the compiler packs data that gets accesses from multiple threads or from application loop and ISR. The default is of course that the compiler do not pack the data.