Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12600 Discussions

Switch to shadow register set - ea problem

Altera_Forum
Honored Contributor II
2,186 Views

Hi, all! 

 

 

I can not switch to shadow register set. I am trying to do this in my main() function, outside any interrupt handler. I am using directions from the "Changing Register Sets" section of the Nios II Processor Reference Handbook (here is a link (http://www.altera.com/literature/hb/nios2/n2cpu_nii51003.pdf#page=28)). 

 

 

Directions are:  

If the processor is currently running in the normal register set, insert the new register set number in estatus.CRS, and execute eret. 

 

 

Here is my code, placed in the main() (project is created from Hello world template):  

// prologue asm("addi sp,sp,-8"); asm("stw r16,0(sp)"); asm("stw r17,4(sp)"); // estatus.CRS = 1 asm("movhi r16,0xffff"); asm("ori r16,r16,0x03ff"); asm("rdctl r17,status"); asm("and r17,r17,r16"); asm("ori r17,r17,0x0400"); asm("wrctl estatus,r17"); // switch asm("eret"); // <------- processor hangs here // wrap asm("ldw r16,0(sp)"); asm("ldw r17,4(sp)"); asm("addi sp,sp,8");  

 

 

The problem is that processor hangs on eret because ea - register with the return address - points to eret itself. 

 

 

I tried to change ea manually with something like addi ea,ea,8, but this does not help. Is there any way to properly adjust the ea before eret? And is it possible to change a register set in the main? 

 

 

I would appreciate any help or advice. 

 

 

With regards, 

Olga
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
591 Views

Dunno, but you could refer to NiosII's "crt0.S" code as it's built to deal with initializing multiple shadow register sets. Perhaps, it will give you an idea of how to proceed. 

 

Good luck! 

 

slacker
0 Kudos
Altera_Forum
Honored Contributor II
591 Views

What are you trying to achieve? 

Looks like some kind of cheap thread/context switch? 

However you'll need to initialise all the registers in the shadow set somewhere - then there will be a return address. 

OTOH you don't want an 'eret' you would normally just do the function return with the new registers. 

 

However trying to add code like that into a C function with asm statements is doomed (because of the way the compiler gerenates and optimises code). You'd need to write it as a C callable asm function in a .s file.
0 Kudos
Altera_Forum
Honored Contributor II
591 Views

 

--- Quote Start ---  

you could refer to NiosII's "crt0.S" code as it's built to deal with initializing multiple shadow register sets 

--- Quote End ---  

 

 

Thanks! I have looked up in crt0.S, here is a proper code for switching and it works: 

 

nextpc ea addi ea,ea,8 eret  

 

I guess, the problem was with debugger. I used Instruction Stepping Mode and value of ea was changing on every step. If the program runs continuously to the breakpoint, located after eret, everything is fine and register sets actually switch. 

 

The only thing, that I still can not explain, is why debugger changes ea.
0 Kudos
Altera_Forum
Honored Contributor II
591 Views

dsl, 

 

Yes, I do intend to use it for a quick context switch for a bare metal application. One of the main reasons - is to have a separate stack for a subroutine.  

 

And thank you for idea about a separate .s file. I don't know, why I have not done it earlier - code become much neater!
0 Kudos
Altera_Forum
Honored Contributor II
591 Views

Not sure, I'd have thought it used ba and would preserve ea. 

Perhaps there are some other things going on? 

It might be that you have the jtag uart enabled as well, and it is taking an interupt because of the data transfers done by the debugger. 

 

If you are doing true 'bare metal' you don't want any of the Altera libc stuff at all. 

I've posted extracts from the linker script I use before now. 

Basically the entry point code just sets %sp and %gp and then jumps to my C code - that is all the initialisation you need.
0 Kudos
Reply