using __flash instead of PROGMEM?

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

Hi,

 

  I realise I'm a decade or so late, but I'm struggling to get things working again.

 

I've started a new, smaller game for my hardware project thing and I'm trying to create a 'blank game' template. So far so good.

 

One of the first things my machine does is initialise the OLED and then blank it by writing lots of 0's to the display SRAM. Because I already have a function for displaying a 'block' to screen, I use that:

 

static const __flash byte BLANK[] = {0, 0, 0, 0, 0, 0, 0, 0};

void clear_display(void)
{
    for (byte row=0 ; row<SCREEN_ROWS ; row++)
    {
        set_display_col_row(0, row);
        
        for (byte col=0 ; col<SCREEN_COLUMNS ; col++)
        {
            shift_out_block(&BLANK[0], FALSE);
        }
    }
}

my shift_out_block function looks a bit like this:

 

void shift_out_block(const byte *block, byte inverted)
{
    byte b;
    for (byte i = 0; i < 8; i++)  
    {
        //b = pgm_read_byte(block+i);
        b = block[i];
        if (inverted)
            b = ~b;
        
        if ( b & (1 << 0) )
        {
            PORTB |= 1 << SDA;
        }
        else
        {
            PORTB &= ~(1 << SDA);
        }
        
        PORTB |= 1 << SCL; 		// HIGH
        PORTB &= ~(1 << SCL); 	// LOW
        
...

as you can see, previously, BLANK was declared using the PROGMEM macro. Changing to using __flash, and then removing the pgm_read_byte call causes my screen to be filled with junk instead of blankness.

 

Obviously the wrong address is being passed at the call for shift_out_block(&BLANK[0]...), but I don't understand why (as per usual).

 

-Mike

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

MalphasWats wrote:
Obviously the wrong address is being passed
Nope.

The address is interpreted incorrectly in the function because you forgot to tell the compiler that it points to Flash.

void shift_out_block(const byte *block, byte inverted)

->

void shift_out_block(const __flash byte *block, byte inverted)

Stefan Ernst

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

sternst wrote:

The address is interpreted incorrectly in the function because you forgot to tell the compiler that it points to Flash.

void shift_out_block(const __flash byte *block, byte inverted)

 

Ah I see! That works, thank you.

 

Is it not possible to have a function such as this that could draw from whatever it was given?

 

For example, I might have a normal set of blocks that I draw that are stored in flash, but then also use the same function to draw a block generated at run-time and therefore stored in SRAM?

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

The AVR has a Harvard architecture - meaning it has separate data (RAM) and code (Flash) address spaces.

 

So you can't tell just from an address whether that's in flash or RAM.

 

Your function would have to take a flag to indicate whether the supplies address was to be interpreted as a RAM address, or a Flash address.

Or something similar.

 

 

EDIT

 

Note that some AVRs, apparently, map the Flash into Data space; eg, https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Jun 27, 2018 - 05:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

So you can't tell just from an address whether that's in flash or RAM.

 

Ah, ok. I knew about the harvard vs von neumann, for some reason I'd gotten it into my head that the addresses were contiguous between the two spaces and the flash ones were just read-only!

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

MalphasWats wrote:
Is it not possible to have a function such as this that could draw from whatever it was given?
It is:

void shift_out_block(const __memx byte *block, byte inverted)

Stefan Ernst

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

And if you use __memx then there's a __builtin you can use to tell if its a RAM or flash pointer.