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.