flash helper macros from AVR, when within ARM code

Status
Not open for further replies.

stevech

Well-known member
For the Teensy 3, for example, does prog_char type and PROGMEM macros cause, say, C strings to be stored in the ARM flash rather than in RAM at run time, copied from flash by the crt?

I have a program I wrote which has many such instances, and use of the F() macro for C strings in flash. That large program compiles and runs fine on both AVR and Teensy's ARM. Nice.
Just curious about how those macros/types work for ARM.

I have to have those else the AVR's RAM is too small for the program's buffers and string constants.
 
I believe on the Arm, anything that is static/global and declared as const, it will be placed in the flash memory, and not SRAM.
 
so
static char text[] = { "hello" };
would not go in flash on the Teensy3?

What about the types used on AVRs as below, but same code compiled for Teensy 3 as the target?
prog_char text[] PROGMEM = { "hello" };

(the GCC versions and command line options for Arduino/AVR and Teensy 3 differ, if that matters).
 
If you look at: hardware/teensy/cores/teensy3/avr/pgmspace.h, you will see:

Code:
#include <inttypes.h>

#define PROGMEM
#define PGM_P  const char *
#define PSTR(str) (str)

#define _SFR_BYTE(n) (n)

typedef void prog_void;
typedef char prog_char;
typedef unsigned char prog_uchar;
typedef int8_t prog_int8_t;
typedef uint8_t prog_uint8_t;
typedef int16_t prog_int16_t;
typedef uint16_t prog_uint16_t;
typedef int32_t prog_int32_t;
typedef uint32_t prog_uint32_t;

So if you want it to be in flash in both cases, you will need to add const. If the Arduino team ever decides to update the compiler past the 4.3.2 version that they have used for a long time, and moves to more modern compilers, you will need to add const there as well. The reason is in GCC 4.5, the AVR compiler switched to use the infrastructure that I added for the SPU/cell port for PROGMEM, and it will issue a warning if the array is not declared const.

Code:
static const char text[] = { "hello" };
prog_char const text[] PROGMEM = { "hello" };

Here is an old thread that touches on some of the issues: http://forum.pjrc.com/threads/24038-Teensy3-PROGMEM-compatibilty-issues
 
sounds like today the issues prevail.
I have to re-re-re-read as I still don't get it regarding using const in C or C++. I ASSUME that the .ino file is copied to a cpp file. Don't know.
On top of that is how const is handled vs. version of GCC.

I/we need it distilled to 3 or so terse sentence/rules to follow.
 
The IDE does some amount of post processing of the .ino/.pde file to make a C++ file. Mostly this is to add the standard Arduino include files, and to find functions in the .ino/.pde file and add forward references before the use so that Arduino users don't have to worry about declaring functions. It then looks through all of the #include files to find the libraries. It copies each of these libraries into separate sub-directories, and then compiles every thing, making an executable file, and converts the executable file into a format (Intel ihex?) for uploading to the board.

What changed is around the GCC 4.5 version, the AVR compiler rewrote the PROGMEM handling, and it is a bit stricter than it was previously. I don't know all of the details (other than it now uses the named address extension I put into the GCC for a different embedded processor). As I understand it, the original implementation was something of a hack, and when they changed it, it generally made things better, but as with any change, some things got broken.

I haven't bothered updating the AVR compiler to something newer than what the Arduino team released. For both ARM and AVR projects I stick with the compilers provided, even though it raises my hackels that the AVR compiler is so old. Sure, I could do the build latest from trunk, etc. but frankly this is a hobby for me. I do enough of building and debugging GCC for my day job..

For the nonce, you probably don't have to worry about newer AVR compilers if you stick with the compilers provided by the Arduino team (which Teensy does use). You probably should pick up a C++ text to learn about const (it is slightly different from C). Until you get newer AVR compilers, you don't need to worry about changes in that compiler (there are people who've done it, do a google search for AVR PROGMEM), so you just need to get ARM and AVR to use a common syntax.
 
Thanks. I really want to focus on my subject matter expertise and interests and not on the nuances of the languages. I procrastinated using C++ for years because I think it's way to obtuse for embedded systems where 99.9% of all objects are static, so why bother with classes and C++ versus structs in C. But now I think I know about 80% of C++. I resist templates and operator overloading. What Paul did with operator overloading, e.g., to emulate the AVR SPI I/O with Teensy 3- is brilliant, but..

This all leads to unmaintainable code in my opinion. I like code that's super well commented and is blatantly obvious - to me now, to others, and to me a year from now! Guess it's my development team background.

-===
The impetus for this thread is that this huge amount of C/C++ code I have, combined with Mike's RadioHead - is amazing in that it all compiles/runs on AVR and ARM. No changes. Almost no #ifdefs sprinkled in the code. But I can't tell if my attempts at RAM-conservation are working for the AVR. My program becomes unstable as I add a few things - just a dozen bytes. I did try to use the elf parser but its reports aren't specific. I'd really like to leave the AVR behind entirely. Too much wasted time in software coding hacks to cope with 2.5K of RAM and the (expletive) Harvard address architecture. But not there yet.
 
Last edited:
Arduino is planning to move to avr-gcc 4.8 sometime "soon".

Yes, having to use pgm_read_byte() on AVR is ugly. If you can drop AVR support, it really simplifies things. If not, at least be sure you use "const PROGMEM" in the variable definition, which ought to be reasonably compatible.
 
Fortunately, with the F() macro and others, I haven't had to use pgm_read_byte() to work with C strings on code that targets both AVR and ARM.
Doing Serial.print(F("hello")) and strcpy_P() and so on which thankfully have Teensy3 macros that more or less ignore these.
I need to go back to the code and put in "const" in C strings that could be in the ARM's flash and not duplicated into RAM at startup. I think that's how it would work.
I hope that doing so stays AVR / Arduino compatible.
 
Last edited:
Well if it does prove problematical, you could always do:

Code:
#ifdef __arm__
#define ARM_CONST const
#else
#define ARM_CONST
#endif

and use ARM_CONST.
 
Arduino/AVR has some flash helpers that can't don't work as far as I can find. Such as
sprintf_P(arg1, arg2, arg3)

with arg2 as the address of a flash resident C string and arg3 (and more) as flash-resident C string pointers.
I have one of those in my program, but so far I have to use RAM and and sprintf() without the _P.
This sprintf() is putting out a 10 column table with heading titles and each column containing numbers.
Also, AVR doesn't have Serial.printf() though I know how to add it, I didn't want to for sake of simplicity for others. Hence sprintf() then Serial.print()

Without the Harvard degree (i.e., the Teensy 3) it's not an issue.
 
Last edited:
Status
Not open for further replies.
Back
Top