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

RTX166-Tiny and automatic variables is seen as not safe

After some work with RTX-tiny, I have taken the following note:
In RTX166-Tiny, the use of local (auto) variables is strongly impaired. RTX-Tiny shifts the contents of the stacks (user and system stack) at run-time. This can occur with any context-switch. This stack shift renders all pointers to variables on the user stack invalid. This concerns all pointers to variables declared within functions (without the declarator 'static') whether they were produced by the programmer or by the compiler.
Only the use of the basic types char, int, bit and their unsigned variants is safe.
The compiler adresses arrays and structures by pointers. Hence the use of those types is unsafe. The types long, float and doubles were not examined here.
By switching off round-robin multitasking, the location of the context-switch is exactly specified. Within sequences with no context-switch, the use of 'unsafe' types is then permissible.
My question to all who did use RTX-tiny: How did you get around this problems? Did I miss some important information?

  • Hello,
    the file Keil\C166\rtx_tiny\readme.txt describes the problem and its suggested workarounds:

    1. Problems with pointers to stack based variables
    ==================================================
    The RTX166 Tiny uses a stack swapping method to reduce the required stack
    space of the whole system.  However, due to the stack swapping, the addresses
    of automatic variables change during program execution.  This can cause
    problems with the program execution when you use a pointer to an automatic
    variable in your program.
    
    There are a couple of ways arround that problem as explained in the follwoing
    sample program.
    
    #pragma MOD167
    #include <string.h>
    #include <reg167.h>
    #include <intrins.h>
    
    #define TIM_INT_ENABLE  T0IE   /* same configuration as in CPUTIMER.INC   */
    
    /*****************************/
    /* RTX166 Tiny Task Function */
    /*****************************/
    void job (void) _task_ 0  {
             char a[16];           /* stack based variable                    */
      static char b[16];           /* static variable                         */
    
      strcpy (a, "Hello World");   /* this can fail since the address of the
                                      variable 'a' can change due to stack
                                      swapping during a task switch           */
    
    /* as a work-around you can disable the RTX166 Tiny Timer Interrupt       */
      TIM_INT_ENABLE = 0;          /* disable RTX166 Tiny Timer               */
      _nop_ ();                    /* two NOP's to make sure that 166/167     */
      _nop_ ();                    /* hardware has disabled the interrupt     */
      strcpy (a, "Hello World");   /* now it works, since there can be not
                                      RTX166 Tiny task switch                 */
      TIM_INT_ENABLE = 1;          /* enable RTX166 Tiny Timer                */
    
    /* another solution is to use static variables instead of stack based
       variables as in the following example                                  */
      strcpy (b, "Hello World");   /* this will always work.  The variable 'b'
                                      is a static variable which has a fixed
                                      memory location                         */
    }
    

  • I posted a similar question to keil support, and meanwhile I got this answer:
    --------------------------------------------
    beim struct return werden Pointer benutzt. Wenn die
    struct lokal definiert ist gibt es die in \keil\c166\rtx_tiny\readme.txt beschriebenen Probleme.

    Loesung: definieren Sie die struct
    ausserhalb der Funktion, damit der struct return klappt.
    --------------------------------------------

    This is indeed what I learnt by experience. Since I can't make use of static variables - my app concurrently runs several instances of the same function - I've had to find another solution. Now I have defined data channels (indeed static structures) for the return values of every instance. This of course works, but is not as friendly as with local structs.