Introduce support for Atmel toolchain in-flash strings

Atmel toolchain AVR compiler provides a transparent in-flash object support using __flash and __memx symbols. The former indicates to compiler that this is a flash-based object.  The later used with pointer indicates that the referenced object may reside either in flash or in RAM. The compiler automatically makes 32-bit pointer with flag indicating whether referenced object is in flash or RAM and generates code to access either in run-time. Thus, any function that accepts __memx object can transparently work with RAM and flash objects.

For platforms with a Harvard architecture and a very small RAM like AVR this allows to move all constant strings used in trace messages to flash in the instruction address space, releasing resources for other things.

This change introduces IOBJ and IPTR type qualifiers.  The 'I' indicates that the object may like in instruction space on a Harvard architecture machine.

For platforms that do not have __flash and __memx or similar symbols IOBJ and IPTR are empty, making the types equivalent to, for example, 'const char' and 'const char*'.  For Atmel compiler these will become 'const __flash char' and 'const __memx char*'.  All printf() functions and syslog() functions are changed so that the qualifier is used with the format parameter.

From: Dimitry Kloper <dikloper@cisco.com>
This commit is contained in:
Dimitry Kloper 2016-01-05 10:29:29 -06:00 committed by Gregory Nutt
parent b48ca00cd5
commit 06d83c6261
22 changed files with 128 additions and 62 deletions

View file

@ -11263,4 +11263,25 @@
struct sigevent. This initial implementation will only work in the
FLAT build. See the top-level TODO file for additional details
(2015-12-30).
* include/nuttx/compiler.h, include/nuttx/streams.h include/stdio.h
include/syslog.h libc/stdio/, and libc/syslog: ntroduce support for
Atmel toolchain in-flash strings. Atmel toolchain AVR compiler
provides a transparent in-flash object support using __flash and
__memx symbols. The former indicates to compiler that this is a flash-
based object. The later used with pointer indicates that the referenced
object may reside either in flash or in RAM. The compiler automatically
makes 32-bit pointer with flag indicating whether referenced object is
in flash or RAM and generates code to access either in run-time. Thus,
any function that accepts __memx object can transparently work with RAM
and flash objects.
For platforms with a Harvard architecture and a very small RAM like AVR
this allows to move all constant strings used in trace messages to flash
in the instruction address space, releasing resources for other things.
This change introduces IOBJ and IPTR type qualifiers. The 'I' indicates
that the object may lie in instruction space on a Harvard architecture
machine. For platforms that do not have __flash and __memx or similar
symbols IOBJ and IPTR are empty, making the types equivalent to, for
example, 'const char' and 'const char*'. For Atmel compiler these will
become 'const __flash char' and 'const __memx char*'. All printf()
functions and syslog() functions are changed so that the qualifier is
used with the format parameter. From Dimitry Kloper.

2
arch

@ -1 +1 @@
Subproject commit 3d8815cc4ce2870c2774cc54c6240f7e5c6e33e1
Subproject commit 0761b677efa861b6369cea195968a59e4a6e6860

View file

@ -40,6 +40,8 @@
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@ -127,6 +129,11 @@
*/
#if defined(__m32c__)
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the small, 16-bit addressing model */
# define CONFIG_SMALL_MEMORY 1
@ -140,6 +147,14 @@
# undef CONFIG_PTR_IS_NOT_INT
#elif defined(__AVR__)
/* I-space access qualifiers needed by Harvard architecture */
# if defined(CONFIG_AVR_HAS_MEMX_PTR)
# define IOBJ __flash
# define IPTR __memx
# endif
/* Select the small, 16-bit addressing model */
# define CONFIG_SMALL_MEMORY 1
@ -159,6 +174,11 @@
# define CONFIG_HAVE_FARPOINTER 1
#elif defined(__mc68hc1x__)
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the small, 16-bit addressing model */
# define CONFIG_SMALL_MEMORY 1
@ -173,20 +193,26 @@
# define CONFIG_LONG_IS_NOT_INT 1
/* Pointers and int are the same size (16-bits) */
/* Pointers and int are the same size (16-bits) */
# undef CONFIG_PTR_IS_NOT_INT
#else
# else
/* int and long are both 32-bits */
# undef CONFIG_LONG_IS_NOT_INT
/* Pointers and int are NOT the same size */
/* Pointers and int are NOT the same size */
# define CONFIG_PTR_IS_NOT_INT 1
#endif
# endif
#else
/* No I-space access qualifiers */
# define IOBJ
# define IPTR
/* Select the large, 32-bit addressing model */
# undef CONFIG_SMALL_MEMORY
@ -491,7 +517,6 @@ extern "C"
#define EXTERN extern
#endif
#undef EXTERN
#ifdef __cplusplus
}

View file

@ -1,7 +1,7 @@
/****************************************************************************
* include/nuttx/streams.h
*
* Copyright (C) 2009, 2011-2012, 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2009, 2011-2012, 2014-2015 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -413,9 +413,10 @@ int lib_snoflush(FAR struct lib_sostream_s *this);
*
****************************************************************************/
int lib_sprintf(FAR struct lib_outstream_s *obj, FAR const char *fmt, ...);
int lib_sprintf(FAR struct lib_outstream_s *obj,
FAR const IPTR char *fmt, ...);
int lib_vsprintf(FAR struct lib_outstream_s *obj,
FAR const char *src, va_list ap);
FAR const IPTR char *src, va_list ap);
#undef EXTERN
#if defined(__cplusplus)

View file

@ -143,35 +143,40 @@ int fgetc(FAR FILE *stream);
int fgetpos(FAR FILE *stream, FAR fpos_t *pos);
char *fgets(FAR char *s, int n, FAR FILE *stream);
FAR FILE *fopen(FAR const char *path, FAR const char *type);
int fprintf(FAR FILE *stream, FAR const char *format, ...);
int fprintf(FAR FILE *stream, FAR const IPTR char *format, ...);
int fputc(int c, FAR FILE *stream);
int fputs(FAR const char *s, FAR FILE *stream);
size_t fread(FAR void *ptr, size_t size, size_t n_items, FAR FILE *stream);
FAR FILE *freopen(FAR const char *path, FAR const char *mode, FAR FILE *stream);
FAR FILE *freopen(FAR const char *path, FAR const char *mode,
FAR FILE *stream);
int fseek(FAR FILE *stream, long int offset, int whence);
int fsetpos(FAR FILE *stream, FAR fpos_t *pos);
long ftell(FAR FILE *stream);
size_t fwrite(FAR const void *ptr, size_t size, size_t n_items, FAR FILE *stream);
size_t fwrite(FAR const void *ptr, size_t size, size_t n_items,
FAR FILE *stream);
FAR char *gets(FAR char *s);
FAR char *gets_s(FAR char *s, rsize_t n);
int ungetc(int c, FAR FILE *stream);
/* Operations on the stdout stream, buffers, paths, and the whole printf-family */
int printf(FAR const char *format, ...);
int printf(FAR const IPTR char *format, ...);
int puts(FAR const char *s);
int rename(FAR const char *oldpath, FAR const char *newpath);
int sprintf(FAR char *buf, FAR const char *format, ...);
int asprintf (FAR char **ptr, FAR const char *fmt, ...);
int snprintf(FAR char *buf, size_t size, FAR const char *format, ...);
int sprintf(FAR char *buf, FAR const IPTR char *format, ...);
int asprintf (FAR char **ptr, FAR const IPTR char *fmt, ...);
int snprintf(FAR char *buf, size_t size,
FAR const IPTR char *format, ...);
int sscanf(FAR const char *buf, FAR const char *fmt, ...);
void perror(FAR const char *s);
int vprintf(FAR const char *format, va_list ap);
int vfprintf(FAR FILE *stream, const char *format, va_list ap);
int vsprintf(FAR char *buf, const char *format, va_list ap);
int vasprintf(FAR char **ptr, const char *fmt, va_list ap);
int vsnprintf(FAR char *buf, size_t size, const char *format, va_list ap);
int vprintf(FAR const IPTR FAR char *format, va_list ap);
int vfprintf(FAR FILE *stream, FAR const IPTR char *format,
va_list ap);
int vsprintf(FAR char *buf, FAR const IPTR char *format, va_list ap);
int vasprintf(FAR char **ptr, FAR const IPTR char *fmt, va_list ap);
int vsnprintf(FAR char *buf, size_t size, FAR const IPTR char *format,
va_list ap);
int vsscanf(FAR const char *buf, FAR const char *s, va_list ap);
/* Operations on file descriptors including:
@ -182,8 +187,8 @@ int vsscanf(FAR const char *buf, FAR const char *s, va_list ap);
*/
FAR FILE *fdopen(int fd, FAR const char *type);
int dprintf(int fd, FAR const char *fmt, ...);
int vdprintf(int fd, FAR const char *fmt, va_list ap);
int dprintf(int fd, FAR const IPTR char *fmt, ...);
int vdprintf(int fd, FAR const IPTR char *fmt, va_list ap);
/* Operations on paths */

View file

@ -41,6 +41,7 @@
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/compiler.h>
#include <stdint.h>
#include <stdarg.h>
@ -167,8 +168,8 @@ void closelog(void);
*
****************************************************************************/
int syslog(int priority, FAR const char *format, ...);
int vsyslog(int priority, FAR const char *src, va_list ap);
int syslog(int priority, FAR const IPTR char *format, ...);
int vsyslog(int priority, FAR const IPTR char *src, va_list ap);
/****************************************************************************
* Name: lowsyslog and lowvsyslog
@ -198,8 +199,8 @@ int vsyslog(int priority, FAR const char *src, va_list ap);
#ifdef CONFIG_ARCH_LOWPUTC
int lowsyslog(int priority, FAR const char *format, ...);
int lowvsyslog(int priority, FAR const char *format, va_list ap);
int lowsyslog(int priority, FAR const IPTR char *format, ...);
int lowvsyslog(int priority, FAR const IPTR char *format, va_list ap);
#else

View file

@ -92,7 +92,7 @@
*
****************************************************************************/
int asprintf (FAR char **ptr, const char *fmt, ...)
int asprintf (FAR char **ptr, FAR const IPTR char *fmt, ...)
{
va_list ap;
int ret;

View file

@ -47,7 +47,7 @@
* Name: dprintf
****************************************************************************/
int dprintf(int fd, FAR const char *fmt, ...)
int dprintf(int fd, FAR const IPTR char *fmt, ...)
{
va_list ap;
int ret;

View file

@ -79,7 +79,7 @@
* Name: fprintf
****************************************************************************/
int fprintf(FAR FILE *stream, FAR const char *fmt, ...)
int fprintf(FAR FILE *stream, FAR const IPTR char *fmt, ...)
{
va_list ap;
int n;

View file

@ -76,7 +76,8 @@
* Name: lib_sprintf
****************************************************************************/
int lib_sprintf(FAR struct lib_outstream_s *obj, const char *fmt, ...)
int lib_sprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *fmt,
...)
{
va_list ap;
int n;

View file

@ -145,7 +145,8 @@ enum
/* Pointer to ASCII conversion */
#ifdef CONFIG_PTR_IS_NOT_INT
static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p);
static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags,
FAR void *p);
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
static int getsizesize(uint8_t fmt, uint8_t flags, FAR void *p)
#endif /* CONFIG_NOPRINTF_FIELDWIDTH */
@ -154,7 +155,8 @@ static int getsizesize(uint8_t fmt, uint8_t flags, FAR void *p)
/* Unsigned int to ASCII conversion */
static void utodec(FAR struct lib_outstream_s *obj, unsigned int n);
static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a);
static void utohex(FAR struct lib_outstream_s *obj, unsigned int n,
uint8_t a);
static void utooct(FAR struct lib_outstream_s *obj, unsigned int n);
static void utobin(FAR struct lib_outstream_s *obj, unsigned int n);
static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
@ -169,7 +171,8 @@ static int getusize(uint8_t fmt, uint8_t flags, unsigned int lln);
#ifdef CONFIG_LONG_IS_NOT_INT
static void lutodec(FAR struct lib_outstream_s *obj, unsigned long ln);
static void lutohex(FAR struct lib_outstream_s *obj, unsigned long ln, uint8_t a);
static void lutohex(FAR struct lib_outstream_s *obj, unsigned long ln,
uint8_t a);
static void lutooct(FAR struct lib_outstream_s *obj, unsigned long ln);
static void lutobin(FAR struct lib_outstream_s *obj, unsigned long ln);
static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
@ -184,14 +187,16 @@ static int getlusize(uint8_t fmt, FAR uint8_t flags, unsigned long ln);
#if defined(CONFIG_HAVE_LONG_LONG) && defined(CONFIG_LIBC_LONG_LONG)
static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long lln);
static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long lln, uint8_t a);
static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long lln,
uint8_t a);
static void llutooct(FAR struct lib_outstream_s *obj, unsigned long long lln);
static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long lln);
static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, unsigned long long lln);
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
static void llfixup(uint8_t fmt, FAR uint8_t *flags, FAR long long *lln);
static int getllusize(uint8_t fmt, FAR uint8_t flags, FAR unsigned long long lln);
static int getllusize(uint8_t fmt, FAR uint8_t flags,
FAR unsigned long long lln);
#endif
#endif
@ -235,7 +240,8 @@ static const char g_nullstring[] = "(null)";
****************************************************************************/
#ifdef CONFIG_PTR_IS_NOT_INT
static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags, FAR void *p)
static void ptohex(FAR struct lib_outstream_s *obj, uint8_t flags,
FAR void *p)
{
union
{
@ -309,7 +315,8 @@ static void utodec(FAR struct lib_outstream_s *obj, unsigned int n)
* Name: utohex
****************************************************************************/
static void utohex(FAR struct lib_outstream_s *obj, unsigned int n, uint8_t a)
static void utohex(FAR struct lib_outstream_s *obj, unsigned int n,
uint8_t a)
{
bool nonzero = false;
uint8_t bits;
@ -376,7 +383,8 @@ static void utobin(FAR struct lib_outstream_s *obj, unsigned int n)
* Name: utoascii
****************************************************************************/
static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned int n)
static void utoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, unsigned int n)
{
/* Perform the integer conversion according to the format specifier */
@ -577,7 +585,8 @@ static void lutodec(FAR struct lib_outstream_s *obj, unsigned long n)
* Name: lutohex
****************************************************************************/
static void lutohex(FAR struct lib_outstream_s *obj, unsigned long n, uint8_t a)
static void lutohex(FAR struct lib_outstream_s *obj, unsigned long n,
uint8_t a)
{
bool nonzero = false;
uint8_t bits;
@ -644,7 +653,8 @@ static void lutobin(FAR struct lib_outstream_s *obj, unsigned long n)
* Name: lutoascii
****************************************************************************/
static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long ln)
static void lutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, unsigned long ln)
{
/* Perform the integer conversion according to the format specifier */
@ -827,7 +837,8 @@ static void llutodec(FAR struct lib_outstream_s *obj, unsigned long long n)
* Name: llutohex
****************************************************************************/
static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long n, uint8_t a)
static void llutohex(FAR struct lib_outstream_s *obj, unsigned long long n,
uint8_t a)
{
bool nonzero = false;
uint8_t bits;
@ -894,7 +905,8 @@ static void llutobin(FAR struct lib_outstream_s *obj, unsigned long long n)
* Name: llutoascii
****************************************************************************/
static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt, uint8_t flags, unsigned long long lln)
static void llutoascii(FAR struct lib_outstream_s *obj, uint8_t fmt,
uint8_t flags, unsigned long long lln)
{
/* Perform the integer conversion according to the format specifier */
@ -1164,7 +1176,8 @@ static void postjustify(FAR struct lib_outstream_s *obj, uint8_t fmt,
* libc/stdio/lib_vsprintf
****************************************************************************/
int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list ap)
int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src,
va_list ap)
{
FAR char *ptmp;
#ifndef CONFIG_NOPRINTF_FIELDWIDTH
@ -1616,5 +1629,3 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
return obj->nput;
}

View file

@ -86,7 +86,7 @@
* Name: printf
****************************************************************************/
int printf(FAR const char *fmt, ...)
int printf(FAR const IPTR char *fmt, ...)
{
va_list ap;
int ret;

View file

@ -80,7 +80,7 @@
* sprintf
****************************************************************************/
int snprintf(FAR char *buf, size_t size, const char *format, ...)
int snprintf(FAR char *buf, size_t size, FAR const IPTR char *format, ...)
{
union
{

View file

@ -76,7 +76,7 @@
* sprintf
****************************************************************************/
int sprintf (FAR char *buf, const char *fmt, ...)
int sprintf (FAR char *buf, FAR const IPTR char *fmt, ...)
{
struct lib_memoutstream_s memoutstream;
va_list ap;

View file

@ -112,7 +112,7 @@
*
****************************************************************************/
int vasprintf(FAR char **ptr, FAR const char *fmt, va_list ap)
int vasprintf(FAR char **ptr, FAR const IPTR char *fmt, va_list ap)
{
struct lib_outstream_s nulloutstream;
struct lib_memoutstream_s memoutstream;

View file

@ -48,7 +48,7 @@
* Public Functions
****************************************************************************/
int vdprintf(int fd, FAR const char *fmt, va_list ap)
int vdprintf(int fd, FAR const IPTR char *fmt, va_list ap)
{
struct lib_rawoutstream_s rawoutstream;

View file

@ -76,7 +76,7 @@
* Public Functions
****************************************************************************/
int vfprintf(FAR FILE *stream, FAR const char *fmt, va_list ap)
int vfprintf(FAR FILE *stream, FAR const IPTR char *fmt, va_list ap)
{
struct lib_stdoutstream_s stdoutstream;
int n = ERROR;

View file

@ -83,7 +83,7 @@
* Name: vprintf
****************************************************************************/
int vprintf(FAR const char *fmt, va_list ap)
int vprintf(FAR const IPTR char *fmt, va_list ap)
{
/* vfprintf into stdout */

View file

@ -80,7 +80,8 @@
* Name: vsnprintf
****************************************************************************/
int vsnprintf(FAR char *buf, size_t size, const char *format, va_list ap)
int vsnprintf(FAR char *buf, size_t size, FAR const IPTR char *format,
va_list ap)
{
struct lib_memoutstream_s memoutstream;
int n;

View file

@ -79,7 +79,7 @@
* Name: vsprintf
****************************************************************************/
int vsprintf(FAR char *dest, const char *src, va_list ap)
int vsprintf(FAR char *dest, FAR const IPTR char *src, va_list ap)
{
struct lib_memoutstream_s memoutstream;

View file

@ -93,7 +93,7 @@
*
****************************************************************************/
static inline int lowvsyslog_internal(FAR const char *fmt, va_list ap)
static inline int lowvsyslog_internal(FAR const IPTR char *fmt, va_list ap)
{
struct lib_outstream_s stream;
@ -121,7 +121,7 @@ static inline int lowvsyslog_internal(FAR const char *fmt, va_list ap)
*
****************************************************************************/
int lowvsyslog(int priority, FAR const char *fmt, va_list ap)
int lowvsyslog(int priority, FAR const IPTR char *fmt, va_list ap)
{
int ret = 0;
@ -154,7 +154,7 @@ int lowvsyslog(int priority, FAR const char *fmt, va_list ap)
*
****************************************************************************/
int lowsyslog(int priority, FAR const char *fmt, ...)
int lowsyslog(int priority, FAR const IPTR char *fmt, ...)
{
va_list ap;
int ret;

View file

@ -92,7 +92,7 @@
*
****************************************************************************/
static inline int vsyslog_internal(FAR const char *fmt, va_list ap)
static inline int vsyslog_internal(FAR const IPTR char *fmt, va_list ap)
{
#if defined(CONFIG_SYSLOG)
struct lib_outstream_s stream;
@ -190,7 +190,7 @@ static inline int vsyslog_internal(FAR const char *fmt, va_list ap)
*
****************************************************************************/
int vsyslog(int priority, FAR const char *fmt, va_list ap)
int vsyslog(int priority, FAR const IPTR char *fmt, va_list ap)
{
int ret = 0;
@ -220,7 +220,7 @@ int vsyslog(int priority, FAR const char *fmt, va_list ap)
*
****************************************************************************/
int syslog(int priority, FAR const char *fmt, ...)
int syslog(int priority, FAR const IPTR char *fmt, ...)
{
va_list ap;
int ret;