PFSTR and printf_PF

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

I'm a far space noob! I'm using an m2561 and need to move my flash strings up and out of the low 64K.

I'd like to replace every occurrence of

printf_P(PSTR("hello"));

with equivalent "far space" functions such as:

printf_PF(PFSTR("hello"))

Is this a reasonable approach?
If so, has someone done it already?

I found various posts about Carlos Lamas' morepgmspace.h stuff and have experimented. Alas I'm still struggling to find a simple example to use as a model to build what I need.

If there's nothing out there, where should I start reading please?

Cheers,
Mike

Mike

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

You do know that GCC places .progmem down at the bottom just after the vectors so that it's only if there's more than ~64K of data that you need to worry about far pointers don't you? Or are you saying you have more than 64K of PROGMEM data?

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

Hi, thanks for the swift response. Yes I did know that. I was anticipating overflowing string and other fixed data space.

Mike

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

I fear you will have to wait for Carlos' morepgmspace.h to be integrated into AVR-LibC but I doubt that there'll ever be a printf_PF() so you'll probably have to roll your own.

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

clawson wrote:
I fear you will have to wait for Carlos' morepgmspace.h to be integrated into AVR-LibC

Why? It *can* be used without the blessing of the avr-libc mob.
Cliff wrote:
but I doubt that there'll ever be a printf_PF() so you'll probably have to roll your own.

Real embedded programmers don't use printf() and kin anyway. It's not THAT hard to write all the printf_PF() family - look at how printf_P() family looks like, it all boils down to one or two occurences of LPM which would need to be replaced by ELPM, but the whole shebang must've been rewritten for more flags in the "FILE" struct and 32-bit quasi-pointers (a lot of work for little credit). And it would inflate a bit - not that it counts when one is determined to go for the printf() stuff anyway.

But if someone really desires it, I'd fake it out in the following way:

# define PFSTR(s) (__extension__({static char __c[] PROGMEM_FAR = (s); GET_FAR_ADDRESS(__c[0]);}))

#define localPFSTR(s) (({char __c[strlen(s) + 1]; strcpy_PF(__c, PFSTR(s)); &__c[0];})) 

int main(void) {
  printf(localPFSTR("bbb"));
}

The PROGMEM_FAR macro is... now that's for a longer discussion I'll get to soon, for now one can replace it simply with PROGMEM just to try, or some absolutely placed FLASH linker segment.

JW

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

Search for Carlos Lamas' original posting for morepgmspace.h - in it he also includes routines for sprintf, printf, strcmp, and so on, using the "far pointer" ProgMem stuff he came up with. Downside is that they are in assembly (.S files), so you'll need to compile them as a library. Also, Carlos' post is now about 2 or 3 years old so I'm not sure what changes may be needed with the latest WinAVR (probably nothing, but you never know).

I also use the ATmega2560. While I use the macros the Carlos came up with to handle strings for my bootloader, I wrapped my own procedures similar to what Jan did above.

One other thing - Carlos' work has been available for some time and has been submitted to the Avr-libc folks, but IIRC there are some problems (documentation? cannot remember) that have prevented the work from being integrated into the official library. As this question comes up about once every month, perhaps the kindly avr-libc folks can give us a quick status update. (Eric? Jorg? Are you there? :wink:)

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

As a follow-up to my other post, here's my bootloader stuff.

#include 
#include "morepgmspace.h"

#define BOOTSTRING_SECTION   __attribute__ ((section (".bootstring")))

const char boot_Version   [] BOOTSTRING_SECTION = "1.1";
const char boot_Monitor   [] BOOTSTRING_SECTION = "DPHIMON ";
const char boot_Prompt    [] BOOTSTRING_SECTION = "* ";

void sendstring_P(uint32_t str_P);

void sendPrompt()
{
	sendstring_P( (uint32_t) GET_FAR_ADDRESS( boot_Prompt ) );
}

. . .

void sendstring_P(uint32_t str_P)
{
	char c;

	do
	{
		c = pgm_read_byte_far( str_P );
		if ( c )
		{
			sendchar( c );
			str_P++;
		}
	} while ( c );
}

and in the Makefile (originally from the MFile template in WinAVR, naturally)

LDFLAGS += -Wl,--section-start=.bootstring=0x3FA00

Hope this is useful to you!

Stu

PS: I use a very simple-minded character I/O in the bootloader, so printf et al are not needed.

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

Surely you are systematically requiring PRINTF() calls and DEBUG_PRINTF() calls of some description.

It gets very messy typing all those PSTR's and 'far's etc.

So write a P() macro for regular printfs
And a D() macro for your conditional output.

You will be expanding P(fmt, args...) to printf_P(PSTR(fmt), args...)
And D(fmt, args...) to either an empty string or P(fmt, args...)

So when you have mastered the necessary avr-gcc gobbledygook, you just have to edit your single P() macro. Job done!

On the other hand, avr-gcc users seem to enjoy all the complications.

Untested. I always have to check the syntax of variadic macros etc. But I have done exactly this in the past. And it removes all your beloved GCC non-portability in a stroke.

David.

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

Wo! Jackpot!! Thanks for the comments, and code fragments.

JW: Thanks for the macros. That's the kind of er.. hack I had in mind. I'm most grateful.

Stu: Thanks for your boot loader print example. That's an excellent and clear example, and a great way for me to start over when I'm less wet behind the ears! BTW., I saw everything but printf in all the versions of Carlos' stuff I found. But never mind, I'm good to go now anyway.

Again, thanks everyone.
Mike

Mike