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.
Hi!
Does anybody know, if there is a way to write custom prolog/epilog for interrupt functions? The context save/restore done by the compiler, differs whether the interrupt function calls any other function (this can be easily remedied, by including dummy function call), and it does not save all the CPU registers (XAR2, XAR3, and RPC are not saved) - this is what really troubles me.
I know that this could be done with 24xx family, by modifying coresponding I$$SAVE and I$$REST routines within real time support library.
Is there maybe some compiler directive, that enables to put some assembler code within the interrupt function (or any function for that mater), before the stack pointer is modified in order to create space for local variables. (maybe something like "naked" attribute for GCC for AVR micros)?
Regards, Mitja
Hi Brandon!
Thanks for checking, now I am sure I did not miss anything. I solved the issue with assembler macros based upon recomendations of "pdegli" in https://community.ti.com/forums/p/206/659.aspx#659. You But then I stumbled on a new issue.
Does the compiler keep the stack pointer (SP) always aligned on 32bit word boundary?
Based upon compiler output from my previous projects, I would say yes, but I did not found an explicit statement on this in TMS320C28x Optimizing C/C++ Compiler Users Guide. It just states, that the SP is aligned on function boundary. Therefore, if the function does not call any other function, the compiler could align the SP on the odd address.
Even more, if you use __enable_interrupts() and __disable_interrupts() intrinsic operator or SetDBGIER assembly function form DSP280x_DBGIER.asm, the SP is not aligned to the even address for a few instruction cycles, during which the interrupts are not disabled. This can cause trouble if you use OS, if the task context switch happens right when the SP in not aligned to 32bit word boundary. I am not sure that the DSP/BIOS handles this correctly, but the OS port I am working on has been corrected to handle this properly.
Just to inform and warn
Regards, Mitja
Mitja Nemec said:Does the compiler keep the stack pointer (SP) always aligned on 32bit word boundary?
Based upon compiler output from my previous projects, I would say yes, but I did not found an explicit statement on this in TMS320C28x Optimizing C/C++ Compiler Users Guide. It just states, that the SP is aligned on function boundary. Therefore, if the function does not call any other function, the compiler could align the SP on the odd address.
I had searched through the TMS320C28x Optimizing C/C++ Compiler Users Guide (SPRU514) for "stack" and found the following statement. It actually is found a couple of times in the document, but this instance was in Section 7.4.1, which talks about using assembly language modules with C/C++ code.
"The stack pointer (SP) must be even-aligned by the parent function prior to making a call to the child function. This is done by incrementing the stack pointer by 1, if necessary. If needed, the coder should increment the SP before making the call."
That tells me the compiler will not generate code to mis-align the stack pointer, but does not explicitly check for stack alignment. If assembly is used, either inline or functions implemented in assembly, that modify the stack, those functions need to handle the alignment.
Mitja Nemec said:Even more, if you use __enable_interrupts() and __disable_interrupts() intrinsic operator or SetDBGIER assembly function form DSP280x_DBGIER.asm, the SP is not aligned to the even address for a few instruction cycles, during which the interrupts are not disabled. This can cause trouble if you use OS, if the task context switch happens right when the SP in not aligned to 32bit word boundary. I am not sure that the DSP/BIOS handles this correctly, but the OS port I am working on has been corrected to handle this properly.
Interesting. Thanks for the warning.
The RPC register is pushed on to the stack by hardware when the LCR instruction is executed to make the function call and popped automatically when the LRETR is used to return. XAR1-3 are "save on call" registers, meaning that the function you are calling will be responsible for saving those registers if it wishes to use them. This would be automatically handled by the C compiler. The register conventions are noted in Section 7.2 of the compiler guide.
Also be sure to see section 7.3.1 and 7.3.2 to see the C calling conventions. You must be sure to follow those when doing any assembly programming.