Nios® II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
Intel Support hours are Monday-Fridays, 8am-5pm PST, except Holidays. Thanks to our community members who provide support during our down time or before we get to your questions. We appreciate you!

Need Forum Guidance? Click here
Search our FPGA Knowledge Articles here.
12409 Discussions

Registers in non-interrupt context switch.

Honored Contributor II

I am hardly trying to understand what should be a basic concept of the uC/OS port when a non-interrupt context switch occurs. 


Now all is fine with interrupt context switches: 

-ra, r0-r16 are all saved onto current task stack (exception.entry in alt_exception_entry.S) 

-OSIntCtxSw (os_cpu_a.s) saves remaining ra (again?), fp, r16-r23. Called in alt_irq_handler. 

-OSIntCtxSw then restores same regs onto new ready-to-run task stack. 

-exception.exit pops back ra, r0-r16 also on new stack. 


Everyone is happy. 

Now I would have expected macro OS_TASK_SW() to be defined as a TRAP instruction so that non-interrupt context switch also occurs in the same fashion. Instead, it is only mapped to OSCtxSw() (same as OSIntCtxSw), which only saves ra, fp, r16-r23. 


Now I am trying to make sense of this but I can't. Jean Labrosse's book does not provide insight to this. It says the OS_TASK_SW() can be defined as TRAP or fct call but in the book, OSCtxSw saves/restores all regs which is not the case in the Altera port. 


Then it must boil down to what is pushed/popped by the compiler. Can anyone understand this and provide insight? 




0 Kudos
1 Reply
Honored Contributor II

Please discard the original post. 


I took a good stack of paper with a fresh mind in the morning to realized all of this make sense. 


For those interested, I guess one of the key point is the "ra" register saved in the OSIntCtxSw/OSCtxSw assembly function that performs a big part of the magic by returning to the point where the original task was suspended, which is either in: 


1. after OS_TASK_SW() in OS_Sched() (os_core.c) if the task was voluntarily yielded by the OS. 


2. after OSIntCtxSw in OSIntExit (os_core.c) if the task was suspended from interrupt. 


Yep, so what appears to be a redundant save/restore of "ra" while in interrupt context is in fact a neat way to jump back to the appropriate code. 


This effectively allows using a direct call in non-interrupt context switch instead of a TRAP, which avoid saving/restoring all the registers manages in the exception entry/exit. 


Hope this can help some others to understand.