Passing pointers to __flash strings in IAR C

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

If I save some RAM by declaring strings in flash eg:

__flash unsigned char String1[] = "String1";
__flash unsigned char String2[] = "String2";
__flash unsigned char String3[] = "String3";

and then try to pass the string locations to a function eg:

void PrintString(unsigned char * StringToPrint)

or

void PrintString(__flash unsigned char * StringToPrint)

I find neither will work. In the first instance the compiler tells me __flash unsigned char * is incompatible with unsigned char *, and in the second case, the compiler tells me a I can't use a memory attribute (__flash) with autos or parameters.

Anyone know how to pass the base address of strings stored in flash?

Regards,

Colin

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

cstocks wrote:
If I save some RAM by declaring strings in flash eg:

__flash unsigned char String1[] = "String1";
__flash unsigned char String2[] = "String2";
__flash unsigned char String3[] = "String3";

and then try to pass the string locations to a function eg:

void PrintString(unsigned char * StringToPrint)

or

void PrintString(__flash unsigned char * StringToPrint)

I find neither will work. In the first instance the compiler tells me __flash unsigned char * is incompatible with unsigned char *, and in the second case, the compiler tells me a I can't use a memory attribute (__flash) with autos or parameters.

Anyone know how to pass the base address of strings stored in flash?

Regards,

Colin

try
void PrintString(unsigned char __flash * StringToPrint)

or

void PrintString(__flash unsigned char StringToPrint[])

it's the difference of a pointer stored in flash to a string, and a pointer to a string stored in flash.

You may also want to include pgmspace.h, as they have defined a set of flash pointers there you can use.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

Hi Glitch,

void PrintString(__flash unsigned char PrintPointer[])

does the trick, but this still begs the question why:

void PrintString(__flash unsigned char * PrintPointer)

won't work. In both cases, the compiler should be looking for a pointer to data stored in flash (it shouldn't care, at compile time, where in flash the pointer is aimed at, so it should be happy to receive either an array reference or a pointer), but in the second case, the compiler rejects the __flash memory attribute.

Thanks for the reply (and for any further insights you may have!).

Regards,

Colin

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

It's the position of the flash modifier (order is important), to make it a pointer into flash, you need to place the flash modifier just before the *, not before the type. Otherwise you are making a pointer IN flash, and not a pointer TO flash.

__flash char *myVar; // <-- this pointer is stored in FLASH, and points to RAM
char __flash *myVar; // <-- this pointer is stored in RAM, and points to FLASH
__flash char __flash *myVar; // <-- this pointer is stored in FLASH, and points to FLASH

I have just re-compiled one of my applications (to verify), I only changed the function, and not the header. the program re-compiled and linked fine.

in header:

void fprint(__flash char line[]);

in C file: (original)

void fprint(__flash char line[]) {
  while(*line!=0){
    lcd_x+=write_char_nm(*line,lcd_x,lcd_y);
    line++;
    if(lcd_x>122) {
      lcd_x=0;
      lcd_y+=12;
    }
  }
}

in C file: (substitution)

void fprint(char __flash * line) {
  while(*line!=0){
    lcd_x+=write_char_nm(*line,lcd_x,lcd_y);
    line++;
    if(lcd_x>122) {
      lcd_x=0;
      lcd_y+=12;
    }
  }
}

in C file: (the wrong way, does not compile or link, had to modify the header to match here as well)

void fprint(__flash char * line) {
  while(*line!=0){
    lcd_x+=write_char_nm(*line,lcd_x,lcd_y);
    line++;
    if(lcd_x>122) {
      lcd_x=0;
      lcd_y+=12;
    }
  }
}

so __flash char var[] is interchangeable with char __flash *var but not with __flash char *var. In fact if you use the latter, not only will you get the incomputable pointer type error, if you try to do any operations on the pointer you will get another error about memory attributes not allowed on auto variables or parameters.

This behaviour is not inconsistent with normal C declaration, consider, for example, declaring a far pointer. You would declare it as.

char __far *var;

not
__far char *var;

the far keyword is used to modify only the type of the pointer, not where it is stored.

The compiler parses the line as follows:
[storage class modifier] [data class] [address class modifier] * [label]

Writing code is like having sex.... make one little mistake, and you're supporting it for life.