Accessing a struct from flash without a copy to sram

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have been going at this for a couple of days and my head is hurting from banging it against the wall...

I have a program that is using all of the available RAM and I need to free up some space (if possible).

 

One area that has a big hit on the RAM usage is a struct that is used to store some compile-time information as well as specific info regarding the build configuration that may be accessed by a host system. I need to be able to create the struct in flash and access its various parts without it being copied to RAM. I have done so many iterations of trying to accomplish this that have been close (all data was accessed from the flash) but the startup __do_copy_data still copied the struct to RAM even if not accessed there. crying

 

(I am compiling for an ATmega328P on AtmelStudio. AND I must use PROGMEM, not __flash!)

 

What follows gives an indication of what I am doing as briefly as I can, but it does access the RAM copy of the struct instead of directly accessing the flash:

// FlashStruct_Demo.c

#include <avr/io.h>
#include <avr/pgmspace.h>

// Define a struct to hold the relevant build information
typedef struct Build_Info {
    const char *buildDate;
    const char *buildTime;
} Build_Info_t;

// Create an instance of the struct in flash
const Build_Info_t BuildInfo[] PROGMEM = {
    {   __DATE__,
        __TIME__
    }
};

// Access the struct (this actually is reading from the RAM copy)
void port_puts(const char *str) {
    while(*str) {       // Output till first 0
        PORTB = (*str++);
    }
}

int main(void) {
    DDRB = 0xFF;

    port_puts((const char *)BuildInfo->buildDate);
    port_puts((const char *)BuildInfo->buildTime);

    while(1) {
        PORTB = 0x00;
    }
}

And, yes I know there are some obvious issues here in this code example; however, I am hoping someone can point toan effective solution...

 

 

Thanks...

This topic has a solution.

David

Last Edited: Fri. Oct 30, 2020 - 02:35 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

frog_jr wrote:

// Create an instance of the struct in flash
const Build_Info_t BuildInfo[] PROGMEM = {
    {   __DATE__,
        __TIME__
    }
};

So would this not be global, and so copied to ram, try putting this after:

void main()
{
// Create an instance of the struct in flash
const Build_Info_t BuildInfo[] PROGMEM = {
    {   __DATE__,
        __TIME__
    }
};

....
}//end of main()

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I don't think you can get those date/time initialized as flash vars unless you create them as flash arrays of chars. Then the struct becomes pretty much pointless.

 

#include <avr/io.h>
#include <avr/pgmspace.h>

typedef __flash const char* fccp_t;
typedef __flash const char  fcc_t;

 

//2 strings in flash
fcc_t BuildTime[] = __TIME__;
fcc_t BuildDate[] = __DATE__;

 

//probably pointless to do this

typedef struct { fccp_t date; fccp_t time; } BuildInfo_t;
__flash BuildInfo_t const BuildInfo = { BuildTime, BuildDate };

void port_puts(__flash const char *str) {
    while(*str) PORTB = (*str++);
}

int main(void) {
    port_puts(BuildInfo.date);
    port_puts(BuildInfo.time);

    port_puts(BuildTime);
    port_puts(BuildDate);
    while(1) {}
}

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

avr-gcc is incapable of initialising flash based arrays or flash based structs containing string members with string literals.

NB: __DATE__ is a string literal.

 

You need a level of indirection to get both the strings AND also the struct in flash.

 

This should work:

// Define a struct to hold the relevant build information
typedef struct Build_Info {
    const char *buildDate;
    const char *buildTime;
} Build_Info_t;

// Create an instances of the strings in flash
const char fl_buildDate[] PROGMEM = __DATE__;
const char fl_buildTime[] PROGMEM = __TIME__;

// Create an instance of the struct in flash
const Build_Info_t BuildInfo PROGMEM = {
    fl_buildDate,
    fl_buildTime
};
Last Edited: Thu. Oct 29, 2020 - 10:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And then you just need:

void port_puts_P(const char *str) {
    while(pgm_read_byte(str)) {       // Output till first 0
        PORTB = pgm_read_byte(str++);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Thanks to all!

All of these have helped me solve my RAM usage problem; however, since I must select only one answer as the solution, I have chosen Winterbottom's post #4.

 

I have reduced the RAM usage by nearly 250 bytes in my actual application!

 

Again, THANKSsmiley

 

David