Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

Switch to shadow register set - ea problem

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

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- 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.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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.