This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Software delay using msp430

Expert 1175 points


 

Can I implement software delays using Timers in msp430?

 

I mean, for example

//some code

//some code

delay(10);

//some code

delay(20);

The delay function will delay the execution by the milliseconds specified as the arguments

But it should not use the loos, only timers.

 

Is it possible to have such a delay mechanism??

 

 

  • Yes; set the relevant timer CCRx to the required value and wait for the interrupt flag in low power mode.

    The value to set your CCRx will depend on the current value of the timer and the clock frequency of the timer:

    CCRx target = (delay_ms * timerfreq) + tim_currval

    The simplest solution will be if you have a spare timer you can dedicate to the delay feature which can be stopped when not "delaying" and then restarted when a delay is prompted - in this case the starting value of the timer is always zero thus making the target value much easier to calculate. 

    Be careful of delay_ms targets that could generate invalid CCRx values that the timer will never reach - e.g. if the timer overflows at 4095 then a target of 5000 will never be reached and you will be stuck waiting forever.  Also be wary of any delays that could cause a wrapped-around value of the CCRx target as these would cause delays much shorter or longer than expected.

     

    Have a look at some of the sample code for your device for examples on how to use the timers.

     

     

    Chris.

  • You're the first one asking how to do a delay with a timer. Congrats!
    The usual question is 'why does my FOR loop not give the expected delay?'

    My proposed setup is to dedicate one timer for timing. Easiest case is to feed it with a 1MHz clock and let it run in continuous mode. Then set CCR0 to TAR+1000 (which will trigger an interrupt in 1000 microsecons = 1ms). Inside the tiemr interrupt service routine (ISR) I count up a global variable (giving my a system-wide timebase in ms) and increment CCR0 by 1000. So the next interrupt happens exactly 1ms after the last (no matter how long it took to enter the ISR and to execute it).

    For long-distance delays I can just wait for the global variable to advance the desired number of milliseconds.

    If I need shorter interupts, I set CCR1 to TAR+delay (in microseconds) and wait for CCR1IFG to be set. It is set as soon as the delay has expired and allows delays in the range of 1-2 microseconds, depending on MCLK, up to 65ms (one timer cycle).

    It' sbetter to use a macro for the delay rather than a real function, as any function call adds much overhead and hinders code optimization (clobbered return value registers, call and return instruction overhead etc).. A macro leads to more efficient code (especially if the time parameter is a constant value)

  • The only down-side to using a continuous milisecond tick is that you don't necessarily know at which point through the current timer interval you are when you start the delay thus introducing a variable delay of up to -1ms.  When using this sort of mechanism I always increment my delay target to ensure the MINIMUM target is met e.g. if I want to wait for 10ms I will set the delay value to 11 in order to ensure the delay is >10ms long.

     

    I agree in principle that macros tend to be better than a function however I believe in some situations it can actually be more effective to use functions - it all depends upon the context.  For example if you have to read the current TAR, calculate and set the new target, and then enter a wait mode (LPM or testing IFG) I think the macro will be a reasonable number of instructions.  If you use this macro a lot of times but have a limited amount of flash available then you reach a point where it can be more space-efficient to use a function.  Factors such as register/stack usage, available flash, required number of iterations, and execution speeds should be considered when deciding whether it is more effective to use a macro or a function.  I am not trying to start a big debate on the issue but merely point out that unfortunately engineering is not always black-and-white.

     

    Regards,

    Chris.

  • Chris Marchant said:
    The only down-side to using a continuous milisecond tick is that you don't necessarily know at which point through the current timer interval you are when you start the delay thus introducing a variable delay of up to -1ms.

    Indeed. It is less suited for short, relative delays. There the microsecond delay is better suited. But if it comes to delays of hundreds or thousands of milliseconds (the microsecond delay is only up to 65ms), having a continuous timebase is a good thing. Also, it allows sysncronizing to a system tick. The wait loop always ends at a 'full' millisecond. So you don't suffer a drift depending on program execution time.

    Chris Marchant said:
    I believe in some situations it can actually be more effective to use functions

    Only if the complexity exceeds a certain threshold. To call a function, the compiler must load the parameters in certain registers (it cannot use immediate constants or local/global variables) and it has to invalidate all registers which are commonly used for function value return (usually R12-R15). Then the call instruction itself takes 4 bytes. Not to count the increased stack usage for function return address and saving other registers clobbered inside the called function. Not to mention the additional execution time. If I need a 10µs delay (for external hardware) I don't want to add another 10µs function call overhead.
    If a macro is used, the compiler can optimize the code much better, so for small function (such as a wait loop for a timer tick or something that simple) a proper macro is superior.

    In fact, the mspgcc compiler often inlines a function rather than calling it, if some prerequisites are met. Of course this only works if the function is in the same source file. One prominent example is the auto-inlining of the code for a 16x16 bit multiplication (when using the 16 bit hardware multiplier) rather than calling a multiply function (which is done for 32x32 bit or 64x64 bit multiplications).

  • Jens-Michael Gross said:
    My proposed setup is to dedicate one timer for timing. Easiest case is to feed it with a 1MHz clock and let it run in continuous mode. Then set CCR0 to TAR+1000 (which will trigger an interrupt in 1000 microsecons = 1ms). Inside the tiemr interrupt service routine (ISR) I count up a global variable (giving my a system-wide timebase in ms) and increment CCR0 by 1000. So the next interrupt happens exactly 1ms after the last (no matter how long it took to enter the ISR and to execute it).

    I've been dreaming of this perfect timing example. 

    I bow to you JMG ^^

  • Jens-Michael Gross said:

    In fact, the mspgcc compiler often inlines a function rather than calling it, if some prerequisites are met. Of course this only works if the function is in the same source file. One prominent example is the auto-inlining of the code for a 16x16 bit multiplication (when using the 16 bit hardware multiplier) rather than calling a multiply function (which is done for 32x32 bit or 64x64 bit multiplications).

    Since this popped up four years later due to a late response, a couple updates:

    First, if you use -Os to optimize for space, mspgcc and msp430-elf gcc will probably not inline anything, even if the visible declaration has the __inline__ attribute/qualifier.  If you want something inlined for speed but otherwise want to optimize for space (-Os), you need this combination: __inline__ __attribute__((__always_inline__))

    Second, inline expansion of multiplication operations isn't related to function inlining; it's a difference in the code generator for those expressions.  In msp430-elf which replaced mspgcc all real multiplication expressions generate code that calls external functions that are selected by the -mhwmult= parameter to the compiler.  (Strength-reduced constant multiplies that are replaced by shift operations may be inlined.)

  • Peter, of course you’re right, the multiplication code ‘inlining’ is hardcoded into the compiler. Because it is a very common case. And because the use of mathematical operators is a special (and hardcoded) case anyway, as they are no function calls in C at all. (well, in C++, they could).
    It was just an (perhaps unlucky) example.
    My own optimized funcitons for mixed-size multiplications (e.g. 32x16->64bit) are subject to inlining. But of course they are real functions.

    Thanks for mentioning the __always_inline__  attribute. However, there are more pitfalls when using inlining. If the always inlined code is in a header file and included into multiple code files, it also requires the extern keyword, or else each object file will also get a callable function of this name, even if it is never used. Depending on the linker configuration, this may cause link errors.

  • Jens-Michael Gross said:
    Peter, of course you’re right, the multiplication code ‘inlining’ is hardcoded into the compiler. Because it is a very common case. And because the use of mathematical operators is a special (and hardcoded) case anyway, as they are no function calls in C at all. (well, in C++, they could).

    In msp430-elf GCC the C expression i*j, if it cannot be computed at compile time, is a function call whether or not an MPY peripheral is present.  Presumably that'll be fixed some day, but they're still figuring out how to handle the various MSP430 multiplier implementations so it's not there yet.

    I hadn't yet felt strong enough to try to explain to them how badly things will go wrong if somebody invokes multiplication operations from both interrupt handlers and interrupt-enabled code, but that's now registered on the GCC bugzilla.  [edit: Sorry, that part's wrong: I didn't read closely enough to see where the appropriate steps were taken.]

    Jens-Michael Gross said:
    Thanks for mentioning the __always_inline__  attribute. However, there are more pitfalls when using inlining. If the always inlined code is in a header file and included into multiple code files, it also requires the extern keyword, or else each object file will also get a callable function of this name, even if it is never used. Depending on the linker configuration, this may cause link errors.

    The classic solution for this case is to define the function in the header as static not extern, which eliminates the linker conflicts from inclusion in multiple translation units.  In GCC we have -ffunction-sections and -Wl,-gc-sections which drops unreferenced code from the final image, if the compiler isn't optimizing enough to notice that a function with internal linkage that is not referenced within the translation unit need not be generated.

    My issue with extern inline in C is that conforming use requires an external definition and you can't be sure whether the inline or external one will be used.  I've never encountered a case where I found the construct worth using.  If you want to use it, understand that what GCC promises and what the language requires are not the same thing.  See this for (possibly outdated) discussion relative to the Linux kernel, and section 6.7.4 of ISO/IEC 9899:201x draft N1570 available here for the uninterpreted details, or stackoverflow for exegesis and discussion.

  • On old MSPGCC 3.2, at least the 16 bit multiplication was inlined. The MPY32 is backwards compatible, so there was no problem. Even though the 32bit part of the MPY wasn’t used. Well, due to the C language restrictions, it didn’t handle 16x16->32 operations effectively, as this requires a cast to 32 bit in the source, and as a result, the32x32->32 function was called instead of directly using the MPY16

    However, I was talking about C language function calls, and “i*j” isn’t in C, while “mul(i,j)” is. No matter how the compiler internally solves this.

    Regarding inline with static or extern, my code is compiled as intended with the extern. With the __always_inline__ attribute, the function won’t ever get referenced, so no instance is required. And with the extern keyword, no function code is ever generated.
    If, for some reason, the compiler ignores the __always_inline__, then this will of course cause a linker error. But then, the code wasn’t built as intended anyway and the purpose of this inline “function” wasn’t met at all.
    Declaring the function static will only prevent linker conflicts - and as you said, with the function-sections, the superfluous instances will be discarded at link time. But in case the inlining failed, you won’t notice then.

  • Jens-Michael Gross said:
    On old MSPGCC 3.2, at least the 16 bit multiplication was inlined. The MPY32 is backwards compatible, so there was no problem. Even though the 32bit part of the MPY wasn’t used. Well, due to the C language restrictions, it didn’t handle 16x16->32 operations effectively, as this requires a cast to 32 bit in the source, and as a result, the32x32->32 function was called instead of directly using the MPY16

    As you know, I'm very familiar with what mspgcc did, from the five year old version you're using through the final release two years ago that supported inline multiplication code for four distinct MSP430 hardware multiplier peripherals including two MPY32 variants (non-existent "C language restrictions" were less relevant than non-existent MPY32 when the version you use was being actively developed).  But mspgcc is dead; I specified msp430-elf, which is mainline GCC (pre-5.0.0 now) compiled for the MSP430.  The GCC supplied by TI in Code Composer Studio 6+ is an early fork of this toolchain.

    Jens-Michael Gross said:
    However, I was talking about C language function calls, and “i*j” isn’t in C, while “mul(i,j)” is. No matter how the compiler internally solves this.

    That wasn't clear from your statement about "the auto-inlining of the code for a 16x16 bit multiplication (when using the 16 bit hardware multiplier)".  My point was that in msp430-elf integer multiply expressions are not inline but are instead calls to a subroutine with all the negative performance implications that result.  The target of the call is selected by -mhwmult, and if hardware multiply is specified it will be a hand-coded assembly function using MPY or MPY32 or MPY32 at 5xx addresses, so it's not a complete loss.   (My involvement with the msp430-elf toolchain is limited to using it, reporting and sometimes fixing bugs, and complaining when it does something poorly compared with mspgcc which it was intended to replace.)

    Jens-Michael Gross said:
    Regarding inline with static or extern, my code is compiled as intended with the extern. With the __always_inline__ attribute, the function won’t ever get referenced, so no instance is required. And with the extern keyword, no function code is ever generated.
    If, for some reason, the compiler ignores the __always_inline__, then this will of course cause a linker error. But then, the code wasn’t built as intended anyway and the purpose of this inline “function” wasn’t met at all.
    Declaring the function static will only prevent linker conflicts - and as you said, with the function-sections, the superfluous instances will be discarded at link time. But in case the inlining failed, you won’t notice then.

    Here the key is to understand that "extern inline" as you describe it is a GNU extension that pre-dates C99 support for inline functions.  The GNU documentation implies that combining it with __always_inline__ would provide no value.

    In C99, "extern inline" is not a sensible combination, leading to my confusion and perhaps to why the behavior it produced in GCC is now associated with the attribute__gnu_inline__.  Where code that works on non-GNU compilers is required (as in my case), the "portable" pre-C99 solution for code re-use in compilers that supported inline as an extension was to do static inline definitions in the header.

    What I learned in researching my original response is that in C99 the standard-conformant approach (not using "extern inline") is much better: an inline definition in the header with no storage-class specifier, and an extern declaration in a single translation unit that causes a global symbol to be bound to a callable implementation of the definition included from the header.  This is a feature that I will use in preference to "static inline" in future code, as it has no linker misbehavior, no duplicated non-inline functions, and no dependence on vendor extensions.

    When using GCC, __always_inline__ can be combined with either the "static inline" or C99 approaches to guarantee inline.  Without using vendor extensions there is no way to guarantee inlining in C99, though failing to provide an extern definition might serve as notification that it didn't work.

  • Yes, I know what you’ve done for the MSPGCC and I always value your explanations and take them as authoritative.

    However, these are no ‘non-existent C language restrictions”. It's the way, the C language defines how math operations are done/have to be done.
    In C, the result of a 16*16 bit multiplication is 16 bit. If you want a 32 bit result, you’ll have to cast at least one operand to 32 bit. Which implies (also part of the C standard) a cast of the secnd operand to 32 bit too. THis makes the whole thing a 32x32 bit multiplication. Unnecessarily, but required by the standard. Sure, a very smart compiler can detect this and instead doing a 32x32 multiplication, it can do a 16x16 bit multiplication and take the hardware-provided 32 bit result. MSPGCC 3.2.3 didn’t. And newer versions didn’t too for quite some time. I know that IAR now is smart enough. I don’t know whether msp430-elf does, as GCC by itself doesn’t know of this special capability of the MSP’s HW MPY. So I don’t know how good MSP430-elf is in undoing/ignoring the (required by the standard) cast to 32 bit.

    Regarding combining extern inline with __always_inline__, yes, ‘normally’, extern inline would be enough. However, “GCC does not inline any functions when not optimizing, unless you specify the ‘always_inline’ attribute for the function”, so in case of not optimizing (which is common for debugging), it does make a difference.
    And as you said: it ensures you get notified by a linker error if inlining doesn’t work for some reason. Which in case of time-critical code is better than having to face unexpected timing problems.

  • Jens-Michael Gross said:
    Yes, I know what you’ve done for the MSPGCC and I always value your explanations and take them as authoritative.

    And yet you say they're wrong.  Let's try one more time.

    From your original post:

    Jens-Michael Gross said:
    The MPY32 is backwards compatible, so there was no problem. Even though the 32bit part of the MPY wasn’t used. Well, due to the C language restrictions, it didn’t handle 16x16->32 operations effectively, as this requires a cast to 32 bit in the source, and as a result, the32x32->32 function was called instead of directly using the MPY16

    There is no 16x16->32 operation without a source language cast.  If i and j are 16 bits then i*j is a 16-bit operation on MSP430.  If you want a 16x16->32 operation at least one operand has to be cast to 32 bits in the source.  The language requires the second operand be promoted; there is no requirement the code writer make this explicit.  The  mspgcc I maintained produces the 32-bit result of (long)i*j using the 16-bit MPY, inline, loading it with 16-bit operands.

    Jens-Michael Gross said:
    Sure, a very smart compiler can detect this and instead doing a 32x32 multiplication, it can do a 16x16 bit multiplication and take the hardware-provided 32 bit result. MSPGCC 3.2.3 didn’t. And newer versions didn’t too for quite some time.

    True.  And the reason wasn't a C language restriction.

    Jens-Michael Gross said:
    So I don’t know how good MSP430-elf is in undoing/ignoring the (required by the standard) cast to 32 bit.

    It does this:

            MOV.W   &j, R10
            MOV.W   R10, R14 { BIT.W        #0x8000, R14 { SUBC.W   R15, R15 { INV.W R15, R15
            MOV.W   &i, R10
            MOV.W   R10, R12 { BIT.W        #0x8000, R12 { SUBC.W   R13, R13 { INV.W R13, R13
            CALL    #__mulsi2

    where __mulsi2 is a hand-coded assembly routine that uses the 16-bit multiply-and-accumulate operations to produce a 32-bit result.

    Jens-Michael Gross said:
    Regarding combining extern inline with __always_inline__, yes, ‘normally’, extern inline would be enough. However, “GCC does not inline any functions when not optimizing, unless you specify the ‘always_inline’ attribute for the function”, so in case of not optimizing (which is common for debugging), it does make a difference.

    Nice wiggle. Of course, that statement from the documentation conflicts with the later statement "If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly."

    If an extern inline definition is used only for inlining, and not-optimizing gcc doesn't do inlining without always_inline, what does not-optimizing gcc produce for calls referencing a bare extern inline definition?

    One would have to experiment to find out.  Be aware that older versions of GCC (I tried 4.7.2) do not behave the same as newer versions (I tried 5.0.0 from trunk as of 20141119).  In short, yes, the attribute does have an effect, but in version 5.0.0 using it with optimization disabled may produce multiply-defined symbol errors at link time.

  • Peter Bigot said:
    Yes, I know what you’ve done for the MSPGCC and I always value your explanations and take them as authoritative.

    And yet you say they're wrong.[/quote]Peter, I was talking about your explanations regarding the MSPGCC compiler internal workings. Not about everything in general :)
    Since I don’t know how MSPGCC worked internally, your intimate knowledge there is beyond questioning it, as it is the only source I have. For anything else, I take any sources I have, and if there are inconsistencies, I’m questioning all of them.

    However, I didn’t say you’re wrong. We’re just expressing things differently, and often don’t see that the other one said/meant the very same thing.

    Yes, there is no 16x16->32 operation in C without an explicit source language cast. That’s what I said. While often being used as an advantage, this is a C language limitation/restriction. To get a 32 bit result, you’ll need to cast one operand to 32bit first.
    The compiler is required to cast the other operand to 32 bit too then, and perform a 32x32->32 operation.
    Now if the compiler is smart enough, it may detect that the fist operand was only cast to 32bit to force a 32 bit result. In this case, it can take the original (not expanded) fist, and the original (not promoted) second operand and perform a 16x16-32 operation using the hardware multiplier. There is of course no requirement to really perform the casts, as long as the result is the same.

    However, previous compilers haven’t been that smart. They have seen a multiplication, ordered the first and second operand from the parser, got 32 bit and 16 bit, promoted the second and performed a 32x32->32 multiplication. Simple, straight, obvious - and less efficient. Apparently, the compilers have become smarter, but only recently.

     And true, the reason why previous compilers didn’t use this wasn’t a language restriction. I never meant it or said it this way. The reason of course was a lower level of smartness in analyzing the intentions of the code. The language restriction I was talking about was the requirement of a cast of the operands to get an untruncated result. Nobody ever forbid a compiler to be smart enough. They just weren’t.

     

    Peter Bigot said:
    Nice wiggle. Of course, that statement from the documentation conflicts with the later statement

    The two statements do not conflict. Quite the contrary, they both support my original intention: using “extern inline” ensures that there is never an instance of the function created. That’s exactly what the compiler shall do and what it apparently does, based on these two statements.
    And this is the intention of this construct. And the __always_inline__ shall ensure that it is inlined even on non-optimized code. If this fails for some reason, the result is a linker error about a missing reference. You can even enable a compiler warning if inlining fails, and why.

    Of course this is only to be used if a function shall be always inlined and never be called as a function. Under no circumstances.
    In some cases, a macro could be used for this too, but macros do not (easily) provide things like type-checking or return parameters.

  • Jens-Michael Gross said:
    Well, due to the C language restrictions, it  didn’t handle 16x16->32 operations effectively, as this requires a cast to 32 bit in the source, and as a result, the32x32->32 function was called instead of directly using the MPY16.

    Jens-Michael Gross said:
    And true, the reason why previous compilers didn’t use this wasn’t a language restriction. I never meant it or said it this way.

    I accept that you didn't mean it that way, though disagree that you didn't say it that way.  All I wanted to do was point out what you've now confirmed.  Thank you.

    Jens-Michael Gross said:
    The two statements do not conflict. Quite the contrary, they both support my original intention: using “extern inline” ensures that there is never an instance of the function created.

    Agreed.  The compiler is entitled to ignore the definition while still using the declaration that comes from the same language construct; I mistakenly conflated the two and inferred a non-existent contradiction.

    I stand by my clarification that "extern inline" will work as you describe only in GCC and only with certain options for standard conformance.  In other compilers and configurations (including default gcc 5.0)  it will do "bad things".

  • Peter Bigot said:
    I stand by my clarification that "extern inline" will work as you describe only in GCC and only with certain options for standard conformance.

    Agreed. Even tough I think that "extern inline" should (by the meaning of the two keywords) do the same on all compilers: inline, if possible, but never instantiate. Whether inlining can be forced, or performed at all, and how, if the __always_inline__ attribute is not available, is a different thing.
    If it doesn’t work, reworking of the code is required anyway, as the purpose of this is to always have the code inlined. And never call it as a function.

**Attention** This is a public forum