diff --git a/cpu/avr8_common/Makefile.include b/cpu/avr8_common/Makefile.include index ce73116c97..295bdea2aa 100644 --- a/cpu/avr8_common/Makefile.include +++ b/cpu/avr8_common/Makefile.include @@ -7,4 +7,8 @@ ifneq (,$(filter printf_float,$(USEMODULE))) LINKFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm endif +# Add aliases for flash_printf, flash_fprintf, flash_snprintf: +LINKFLAGS += -Wl,--defsym=flash_printf=printf_P +LINKFLAGS += -Wl,--defsym=flash_fprintf=fprintf_P +LINKFLAGS += -Wl,--defsym=flash_snprintf=snprintf_P include $(RIOTMAKE)/arch/avr8.inc.mk diff --git a/cpu/avr8_common/include/flash_utils_arch.h b/cpu/avr8_common/include/flash_utils_arch.h index 9663da8b89..43127e65e4 100644 --- a/cpu/avr8_common/include/flash_utils_arch.h +++ b/cpu/avr8_common/include/flash_utils_arch.h @@ -21,7 +21,7 @@ #define FLASH_UTILS_ARCH_H #include -#include +#include #include #ifdef __cplusplus @@ -35,20 +35,68 @@ extern "C" { #define FLASH_ATTR __flash #define PRIsflash "S" #define TO_FLASH(x) __extension__({static FLASH_ATTR const char __c[] = (x); &__c[0];}) -#define flash_strcmp strcmp_P -#define flash_strncmp strncmp_P -#define flash_strlen strlen_P -#define flash_strcpy strcpy_P -#define flash_strncpy strncpy_P -#define flash_printf printf_P -/* avrlibc seemingly forgot to provide vprintf_P(), but vfprintf_P() is there */ -#define flash_vprintf(fmt, arglist) vfprintf_P(stdout, fmt, arglist) -#define flash_fprintf fprintf_P -#define flash_vfprintf vfprintf_P -#define flash_snprintf snprintf_P -#define flash_vsnprintf vsnprintf_P -#define flash_puts puts_P -#define flash_memcpy memcpy_P + +static inline int flash_strcmp(const char *ram, FLASH_ATTR const char *flash) +{ + return strcmp_P(ram, (const char *)flash); +} + +static inline int flash_strncmp(const char *ram, FLASH_ATTR const char *flash, size_t n) +{ + return strncmp_P(ram, (const char *)flash, n); +} + +static inline size_t flash_strlen(FLASH_ATTR const char *flash) +{ + return strlen_P((const char *)flash); +} + +static inline char * flash_strcpy(char *ram, FLASH_ATTR const char *flash) +{ + return strcpy_P(ram, (const char *)flash); +} + +static inline char * flash_strncpy(char *ram, FLASH_ATTR const char *flash, size_t n) +{ + return strncpy_P(ram, (const char *)flash, n); +} + + +static inline int flash_vprintf(FLASH_ATTR const char *flash, va_list args) +{ + /* vprintf_P() is not provided by avr-libc. But vfprintf_P() with + * stdout as stream can be used to implement it */ + return vfprintf_P(stdout, (const char *)flash, args); +} + +static inline int flash_vfprintf(FILE *stream, FLASH_ATTR const char *flash, + va_list args) +{ + return vfprintf_P(stream, (const char *)flash, args); +} + +static inline int flash_vsnprintf(char *buf, size_t buf_len, + FLASH_ATTR const char *flash, va_list args) +{ + return vsnprintf_P(buf, buf_len, (const char *)flash, args); +} + +static inline void flash_puts(FLASH_ATTR const char *flash) +{ + puts_P((const char *)flash); +} + +static inline void * flash_memcpy(void *dest, FLASH_ATTR const void *src, + size_t n) +{ + return memcpy_P(dest, (const void *)src, n); +} + +/* aliases need to be provided by the linker, as passing through va-args is + * not possible */ +int flash_printf(FLASH_ATTR const char *flash, ...); +int flash_fprintf(FILE *stream, FLASH_ATTR const char *flash, ...); +int flash_snprintf(char *buf, size_t buf_len, FLASH_ATTR const char *flash, ...); #endif /* Doxygen */ diff --git a/cpu/avr8_common/work_around_for_shitty_ubuntu_toolchain.c b/cpu/avr8_common/work_around_for_shitty_ubuntu_toolchain.c new file mode 100644 index 0000000000..dfe4535ffc --- /dev/null +++ b/cpu/avr8_common/work_around_for_shitty_ubuntu_toolchain.c @@ -0,0 +1,15 @@ +#include +#include + +/* The outdated linker from Ubuntu's toolchain contains a bug in which it will + * garbage collect symbols referenced only by --defsym= command line options, + * and subsequently complain that the symbols are not defined. Adding other + * references to those symbols from an unused function makes that buggy linker + * happy. Since this function is never used, it will be garbage collected and + * not impact the ROM size. */ +void work_around_for_shitty_ubuntu_toolchain_and_not_expected_to_be_called(void) +{ + printf_P(NULL); + fprintf_P(stdout, NULL); + snprintf_P(NULL, 0, NULL); +}