r0 - temporary register, can be clobbered by any C code (except interrupt handlers which save it), \e may be used to remember something for a while within one piece of assembler code
r1 - assumed to be always zero in any C code, \e may be used to remember something for a while within one piece of assembler code, but \e must then be cleared after use (clr r1). This includes any use of the [f]mul[s[u]] instructions, which return their result in r1:r0. Interrupt handlers save and clear r1 on entry, and restore r1 on exit (in case it was non-zero).
- Function call conventions:If too many, those that don't fit are passed on the stack.
Return values: 8-bit in r24 (not r25!), 16-bit in r25:r24, up to 32 bits in r22-r25, up to 64 bits in r18-r25. 8-bit return values are zero/sign-extended to 16 bits by the called function (unsigned char is more efficient than signed char - just clr r25). Arguments to functions with variable argument lists (printf etc.) are all passed on stack, and \c char is extended to \c int.
\warning There was no such alignment before 2000-07-01, including the old patches for gcc-2.95.2. Check your old assembler subroutines, and adjust them accordingly. Back to \ref faq_index. \section faq_rom_array How do I put an array of strings completely in ROM? There are times when you may need an array of strings which will never be modified. In this case, you don't want to waste ram storing the constant strings. The most obvious (and incorrect) thing to do is this: \code #include| Optimization flags | Size of .text | Time for test \#1 | Time for test \#2 |
| -O3 | 6898 | 903 µs | 19.7 ms |
| -O2 | 6666 | 972 µs | 20.1 ms |
| -Os | 6618 | 955 µs | 20.1 ms |
| -Os -mcall-prologues | 6474 | 972 µs | 20.1 ms |
| Library call | Reentrant Issue | Workaround/Alternative |
| rand(), random() | Uses global variables to keep state information. | Use special reentrant versions: rand_r(), random_r(). |
| strtod(), strtol(), strtoul() | Uses the global variable \c errno to return success/failure. | Ignore \c errno, or protect calls with cli()/sei() or ATOMIC_BLOCK() if the application can tolerate it. Or use sccanf() or sccanf_P() if possible. |
| malloc(), realloc(), calloc(), free() | Uses the stack pointer and global variables to allocate and free memory. | Protect calls with cli()/sei() or ATOMIC_BLOCK() if the application can tolerate it. If using an OS, use the OS provided memory allocator since the OS is likely modifying the stack pointer anyway. |
| fdevopen(), fclose() | Uses calloc() and free(). | Protect calls with cli()/sei() or ATOMIC_BLOCK() if the application
can tolerate it. Or use fdev_setup_stream() or FDEV_SETUP_STREAM().
Note: fclose() will only call free() if the stream has been opened with fdevopen(). |
| eeprom_*(), boot_*() | Accesses I/O registers. | Protect calls with cli()/sei(), ATOMIC_BLOCK(), or use OS locking. |
| pgm_*_far() | Accesses I/O register RAMPZ. | Starting with GCC 4.3, RAMPZ is automatically saved for ISRs, so
nothing further is needed if only using interrupts.
Some OSes may automatically preserve RAMPZ during context switching. Check the OS documentation before assuming it does. Otherwise, protect calls with cli()/sei(), ATOMIC_BLOCK(), or use explicit OS locking. |
| printf(), printf_P(), vprintf(), vprintf_P(), puts(), puts_P() | Alters flags and character count in global FILE \c stdout. | Use only in one thread. Or if returned character count is unimportant,
do not use the *_P versions.
Note: Formatting to a string output, e.g. sprintf(), sprintf_P(), snprintf(), snprintf_P(), vsprintf(), vsprintf_P(), vsnprintf(), vsnprintf_P(), is thread safe. The formatted string could then be followed by an fwrite() which simply calls the lower layer to send the string. |
| fprintf(), fprintf_P(), vfprintf(), vfprintf_P(), fputs(), fputs_P() | Alters flags and character count in the FILE argument. Problems can occur if a global FILE is used from multiple threads. | Assign each thread its own FILE for output. Or if returned character count is unimportant, do not use the *_P versions. |
| assert() | Contains an embedded fprintf(). See above for fprintf(). | See above for fprintf(). |
| clearerr() | Alters flags in the FILE argument. | Assign each thread its own FILE for output. |
| getchar(), gets() | Alters flags, character count, and unget buffer in global FILE \c stdin. | Use only in one thread. *** |
| fgetc(), ungetc(), fgets(), scanf(), scanf_P(), fscanf(), fscanf_P(), vscanf(), vfscanf(), vfscanf_P(), fread() | Alters flags, character count, and unget buffer in the FILE argument. | Assign each thread its own FILE for input. ***
Note: Scanning from a string, e.g. sscanf() and sscanf_P(), are thread safe. |