Why not use an inline assembly statement to do what you want?

See the inline assembler cookbook

A simple (readable) multiline example from there (a very short delay) which can go right into your AVR-GCC program:

asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ::);

Since you seem to know your assembly, you should be good ready to rock with inline assembly as well.

Answer from Windell Oskay on Stack Exchange
🌐
Nongnu
nongnu.org › avr-libc › user-manual › group__avr__cpufunc.html
avr-libc: <avr/cpufunc.h>: Special AVR CPU functions
For debugging purposes, a NOP can be useful to have an instruction that is guaranteed to be not optimized away by the compiler, so it can always become a breakpoint in the debugger. Write __value to Configuration Change Protected (CCP) IO register at __ioaddr. Generated on Sat Jan 29 2022 00:24:04 for avr...
🌐
GNU
gcc.gnu.org › onlinedocs › gcc › AVR-Built-in-Functions.html
AVR Built-in Functions (Using the GNU Compiler Collection (GCC))
For each built-in function for AVR, there is an equally named, uppercase built-in macro defined. That way users can easily query if or if not a specific built-in is implemented or not. For example, if __builtin_avr_nop is available the macro __BUILTIN_AVR_NOP is defined to 1 and undefined otherwise.
Top answer
1 of 3
2

Why not use an inline assembly statement to do what you want?

See the inline assembler cookbook

A simple (readable) multiline example from there (a very short delay) which can go right into your AVR-GCC program:

asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ::);

Since you seem to know your assembly, you should be good ready to rock with inline assembly as well.

2 of 3
2

I think that GCC's naked attribute does what you want. It skips generating any function header or footer, so you need to do your own reti.

void INT0_vect(void) __attribute__ ((signal, naked)); 

void INT0_vect(void) 
{
    TCCR1B = 0x09;
    asm volatile("reti"); 
} 

FreeRTOS uses this scheme for context switching on AVR, they explicitly store all registers. You may only want a subset:

    #define portSAVE_CONTEXT()      \
    asm volatile (  "push   r0                                              \n\t"   \
                                    "in             r0, __SREG__                    \n\t"   \
                                    "cli                                                    \n\t"   \
                                    "push   r0                                              \n\t"   \
                                    "push   r1                                              \n\t"   \
                                    "clr    r1                                              \n\t"   \
                                    "push   r2                                              \n\t"   \
                                    "push   r3                                              \n\t"   \
                                    "push   r4                                              \n\t"   \
                                    "push   r5                                              \n\t"   \
                                    "push   r6                                              \n\t"   \
                                    "push   r7                                              \n\t"   \
                                    "push   r8                                              \n\t"   \
                                    "push   r9                                              \n\t"   \
                                    "push   r10                                             \n\t"   \
                                    "push   r11                                             \n\t"   \
                                    "push   r12                                             \n\t"   \
                                    "push   r13                                             \n\t"   \
                                    "push   r14                                             \n\t"   \
                                    "push   r15                                             \n\t"   \
                                    "push   r16                                             \n\t"   \
                                    "push   r17                                             \n\t"   \
                                    "push   r18                                             \n\t"   \
                                    "push   r19                                             \n\t"   \
                                    "push   r20                                             \n\t"   \
                                    "push   r21                                             \n\t"   \
                                    "push   r22                                             \n\t"   \
                                    "push   r23                                             \n\t"   \
                                    "push   r24                                             \n\t"   \
                                    "push   r25                                             \n\t"   \
                                    "push   r26                                             \n\t"   \
                                    "push   r27                                             \n\t"   \
                                    "push   r28                                             \n\t"   \
                                    "push   r29                                             \n\t"   \
                                    "push   r30                                             \n\t"   \
                                    "push   r31                                             \n\t"   \
                                    "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "in             r0, 0x3d                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                                    "in             r0, 0x3e                                \n\t"   \
                                    "st             x+, r0                                  \n\t"   \
                            );

#define portRESTORE_CONTEXT()                                                           \
    asm volatile (  "lds    r26, pxCurrentTCB               \n\t"   \
                                    "lds    r27, pxCurrentTCB + 1   \n\t"   \
                                    "ld             r28, x+                                 \n\t"   \
                                    "out    __SP_L__, r28                   \n\t"   \
                                    "ld             r29, x+                                 \n\t"   \
                                    "out    __SP_H__, r29                   \n\t"   \
                                    "pop    r31                                             \n\t"   \
                                    "pop    r30                                             \n\t"   \
                                    "pop    r29                                             \n\t"   \
                                    "pop    r28                                             \n\t"   \
                                    "pop    r27                                             \n\t"   \
                                    "pop    r26                                             \n\t"   \
                                    "pop    r25                                             \n\t"   \
                                    "pop    r24                                             \n\t"   \
                                    "pop    r23                                             \n\t"   \
                                    "pop    r22                                             \n\t"   \
                                    "pop    r21                                             \n\t"   \
                                    "pop    r20                                             \n\t"   \
                                    "pop    r19                                             \n\t"   \
                                    "pop    r18                                             \n\t"   \
                                    "pop    r17                                             \n\t"   \
                                    "pop    r16                                             \n\t"   \
                                    "pop    r15                                             \n\t"   \
                                    "pop    r14                                             \n\t"   \
                                    "pop    r13                                             \n\t"   \
                                    "pop    r12                                             \n\t"   \
                                    "pop    r11                                             \n\t"   \
                                    "pop    r10                                             \n\t"   \
                                    "pop    r9                                              \n\t"   \
                                    "pop    r8                                              \n\t"   \
                                    "pop    r7                                              \n\t"   \
                                    "pop    r6                                              \n\t"   \
                                    "pop    r5                                              \n\t"   \
                                    "pop    r4                                              \n\t"   \
                                    "pop    r3                                              \n\t"   \
                                    "pop    r2                                              \n\t"   \
                                    "pop    r1                                              \n\t"   \
                                    "pop    r0                                              \n\t"   \
                                    "out    __SREG__, r0                    \n\t"   \
                                    "pop    r0                                              \n\t"   \
                            );
🌐
Stanford University
web.stanford.edu › class › ee281 › projects › aut2002 › yingzong-mouse › media › GCCAVRInlAsmCB.pdf pdf
GCC-AVR Inline Assembler Cookbook 1/13 GCC-AVR Inline Assembler Cookbook
GCC-AVR Inline Assembler Cookbook · 4/13 · 2 Assembler Code · You can use the same assembler instruction mnemonics, as you'd use with any other AVR assembler. And you can write as many assembler statements into one code string as you like and your flash · memory is able to hold. To make it more readable, you should put each statement on a seperate line: asm volatile("nop\n\t" "nop\n\t" "nop\n\t" "nop\n\t" ::); The linefeed and tab characters will make the assembler listing generated by the compiler more ·
🌐
Linux Man Pages
linux.die.net › man › 1 › avr-gcc
avr-gcc(1): GNU project C/C++ compiler - Linux man page
Normally the gcc program will exit with the code of 1 if any phase of the compiler returns a non-success return code. If you specify -pass-exit-codes, the gcc program will instead return with numerically highest error produced by any phase that returned an error indication.
🌐
Nongnu
nongnu.org › avr-libc › user-manual › using_tools.html
Options for the C compiler avr-gcc
The table matches them against the corresponding avr-gcc architecture name, and shows the preprocessor symbol declared by the -mmcu option.
Find elsewhere
🌐
Nongnu
nongnu.org › avr-libc › user-manual › cpufunc_8h_source.html
avr-libc: cpufunc.h Source File
51 \ingroup avr_cpufunc · 52 \def _NOP · 53 · 54 Execute a <i>no operation</i> (NOP) CPU instruction. This · 55 should not be used to implement delays, better use the functions · 56 from <util/delay_basic.h> or <util/delay.h> for this. For · 57 debugging purposes, a NOP can be useful ...
🌐
Mcselec
avrhelp.mcselec.com › nop.htm
NOP - BASCOM-AVR - MCS Electronics
This statement does noting · The NOP statement will create 1 NOP assembly instruction. A NOP takes 1 machine cycle and can be used to create a small delay
🌐
Stack Overflow
stackoverflow.com › questions › 62866116 › how-to-define-a-subroutine-macro-in-sperate-asm-file
c - How to define a subroutine/macro in sperate .asm file? - Stack Overflow
0000000a <here>: a: ff cf rjmp .-2 ; 0xa <here> 0000000c <fun>: c: 00 00 nop e: 00 00 nop 10: 08 95 ret · assembly language is specific to the assembler, not the target, so you need to use the language for the assembler you are using, the above ...
🌐
Nongnu
nongnu.org › avr-libc › user-manual › inline_asm.html
Inline Assembler Cookbook
The assembler instruction, "clr r3", will clear the variable counter. AVR-GCC will not completely reserve the specified register. If the optimizer recognizes that the variable will not be referenced any longer, the register may be re-used. But the compiler is not able to check wether this register ...
🌐
Microchip
ww1.microchip.com › downloads › en › Appnotes › doc32074.pdf pdf
32-bit Microcontrollers Application Note Rev. 32074A-AVR-12/07
The AVR32 architecture has three possible shadowing modes: full, half or none2. Specifying no argument to the attribute defaults to none. Writing an · interrupt handler function for an interrupt with half shadow mode can then be done ... GCC provides two built-in functions for byte- swapping.
🌐
Nongnu
nongnu.org › avr-libc › user-manual › FAQ.html
Frequently Asked Questions
While this waste of space applies to virtually any platform C is implemented on, it's usually not noticeable on larger machines like PCs, while the waste of flash ROM storage can be very painful on a small microcontroller like the AVR. So in general, variables should only be explicitly initialized if the initial value is non-zero. ... Recent versions of GCC are now smart enough to detect this situation, and revert variables that are explicitly initialized to 0 to the .bss section.
🌐
GNU
lists.gnu.org › archive › html › avr-gcc-list › 2009-02 › msg00148.html
[avr-gcc-list] How to force GCC to not to remove "nop" statements ?
February 19, 2009 - So I did that.. and the LCD doesn't work reliably. Suspecting the problem, I went straight to the generated assembly, and horror, my 4 nop statements have disappeared ! I made a few trials. It appears that up to and including 3 nop statements, GCC leaves them alone.