Hello, I'm trying to conceive a cooperative RTOS without the use of switch-case in every task to divide it in small chunks and exit C function properly as a lot of us have done. This way, the code for each task gets big and nasty pretty quick, not to say a switch-case in my opinion wastes a lot of CPU cycles and flash memory. Any way I've used this approach several times.
Almost a year ago I coded a small Preemptive RTOS for HCS08 (except memory paged devices) but found out that a full preemptive RTOS is almost useless in RAM-constrained devices because you have to give each task a small independent stack, enough to store all the program counters up to the deepest function it can enter, and CPU registers in stack when entering interrupts. So giving each task an independent stack enough for the worst case scenario results in lots of wasted RAM and careful checking you don't overflow each one of them.
However I liked a lot how small the C code for each task would be on a preemptive RTOS. Knowing that a context switch will be fired up after some time (preemptively) or when task decides to wait some miliseconds before continuing execution (cooperatively).
I have put a lot of thought on this, and I'm trying to conceive a Cooperative RTOS which uses only one stack, but without using switch-case, instead forcing a context switch with the software interrupt. Something like this:
Not having an independent stack for each task implies that for prior to each context switch (SWI triggering) the Stack Pointer must always point to the same address. In other words, stack must be always the same. All other CPU registers could easily be saved and restored inside SWI ISR, so that's no reason to worry about.
Im aware that when entering a C function, for each byte of arguments and local variables, stack increases as they are allocated into stack, but lets consider there are none of them.
I'm also aware that when a function is called inside a "function as task" it modifies the stack pointer, but when it returns, stack pointer returns to the previous value as it nothing happened. So this does not worry me.
If I haven't made myself clear I want to know if stack pointer changes between lines of C code inside a function for any reason. If so, I would like to know if there's a compiler argument to tell him not to do it.
So far I've coded a prototype handling some leds and a 16x2 LCD and it has been working flawlessly, software interruptions could be anywhere insife my "task function" and stack pointer doesn't change. But I don't want to develop more complex code if it won't be valid for other cases, and I would have wasted a lot of time.
Of course there's an inevitable drawback: a function that will act as a task could NEVER EVER have different local variables and arguments from each other, because they will increase the stack in different quantities, and stack pointer for each "function as task" will be different. Results would be catastrophic. A standard set of arguments (and local variables) could be handled easily saving and restoring them inside the context switch as long as each "function as task" uses the exact same ones (in fact they could have different names and data sizes, as long as the total bytes is the same for each one, but playing with the data sizes would be dangerous, so let's stick with "the exact same ones")