This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

About interrupts

Hi all,

I'd like to know if is there any way to declare an interrupt function as naked in C using Code Composer 2.20. I mean, how can I avoid that the compiler automatically generates code to store/restore the registers in the stack? I'd like to do it on my own. I guess that I can write the ISR in assember rather than in Cto avoid this, but I'd prefer, if possible, a high-level language solution.

Thanks

Regards

 

  • From the C coding perspectives you're choices are "use the interrupt keyword" or "don't use the interrupt keyword".  If you want to do something very specialized as you describe you would need to write your own ISR in assembly language or perhaps an assembly language "wrapper" for a normal C function.

  •  Hello,

    Thanks for your reply. I've finally solved it writing the ISR in assembler and it is (almost) working ok but I've got one more question related to interrupts: when an interrupt occurs, does the processor force the stack pointer to be aligned to an even address before the registers (Acc,ST0,PC,...) are automatically pushed onto the stack? I've been digging in the datasheets but I haven't got a clear answer to this question.

    Thanks a million

    Regards 

     

  • Keep in mind that for 32-bit reads/writes the least significant address bit is ignored.  Therefore you need to be careful when doing 32-bit operations as you might overwrite something if the address is odd.

    The PROCESSOR will add 1 to the stack pointer during an interrupt.  This is documented in the 28x CPU and Instruction Set Reference Guide, spru430(d), in Chapter 3.4.  It does this to protect against the case that SP is odd when the interrupt occurred.

    The *C Compiler* requires that SP be even any time a C function is called.  This is documented in the C compiler guide, spru514(c), in Chapter 7.3.1.

    There's an assembly instruction "ASP" (align stack pointer) to do this for you with a corresponding NASP to un-do the change at the end of the function.  Just be careful that you don't nest multiple of those instructions or else you'll lose the value that was saved in the SPA bit (i.e. you need to preserve the SPA bit before calling it a second time).

    Brad

  • Hello,

     you can find good hints on how to save the CPU registers while servicing an interrupt in the CPU and instructions reference manual (spru430) and peeking into the assembler code generated by the C compiler when you declare a function using the interrupt keyword.

    Main registers are "hardware pushed" on the stack in 32bit aligned fashion and "hardware popped" upon executing the IRET instruction. The C compiler generates the code needed to save only those other registers which, it knows, are going to be used (mind this if you are planning to call assembler functions from within interrupt service routines) so it's rather optimized for simple interrupt servicing and it works fine. I suggest to use it to forget about all hassles with registers saving and restoring, though, if you need to save all CPU register like during an OS context switch, as far as I know, there are no shortcut: you have to write your own assembler code to deal with it.

     Regarding the Stack Pointer Alignment (ASP, NASP instructions), the correct procedure isn't straightforwardly explained anywhere in the manuals so I had to make some tries with the debugger while porting the uC-OSII  kernel but at last I was able to have the context save and restore working in a reasonable amount of time. Even if CPU automatically saves some registers aligned to even addresses the Stack Pointer is left in it's alignment state and the code must take care of that through ASP and NASP instrutions. I found that it works aligning the stack as first instruction and then restoring alignment after having saved the registers and then again aligning the stack before restoring the registers and restoring alignment just before the IRET instruction.

    Here is a snippet  of the code I found working to save all the CPU registers and later restore them.

    Interrupt vector point here:
        ASP
        PUSH    AR1H:AR0H
        PUSH    XAR2
        PUSH    XAR3
        PUSH    XAR4
        PUSH    XAR5
        PUSH    XAR6
        PUSH    XAR7
        PUSH    XT
        PUSH    RPC
        NASP

      Do something useful here...

        ASP
        POP        RPC
        POP        XT
        POP        XAR7
        POP        XAR6
        POP        XAR5
        POP        XAR4
        POP        XAR3
        POP        XAR2
        POP        AR1H:AR0H
        NASP
        IRET

    I hope this will be of some help.

     Regards