avrdudes / avr-libc

The AVR-LibC package provides a subset of the standard C library for AVR 8-bit RISC microcontrollers.
https://avrdudes.github.io/avr-libc/
Other
257 stars 56 forks source link

[patch #6352] Far pointer library #752

Closed avrs-admin closed 7 months ago

avrs-admin commented 2 years ago

Fri 21 Dec 2007 03:40:29 PM CET

This code is to intended to access the whole flash memory in devices with flash address space bigger than 64KB.

The macro GET_FAR_ADDRESS() is the best version I've got after testing several ones but is not always a direct replacement of the & operator for getting far pointers. It has not been tested on ATmega2560, not even in simulation.

The string and memory copy functions for far program memory xxxx-PF() are still in beta stage and need more tests (not known bugs but not extensively tested). They had been parked in my hard disk for a long time but the big ROM devices users claim for some standard way to access the data in avr-libc.

Comments are welcomed.

Carlos Lamas.

file #14680: extra pgmspace.zip file #20682: memcmp_PF.zip file #20859: memcpy_PF.zip

This issue was migrated from https://savannah.nongnu.org/patch/?6352

avrs-admin commented 2 years ago

Anatoly Sokolov Wed 02 Jan 2008 05:20:32 PM CET

These functions modify RAMPZ register and is non-reenterable. They cannot be used in interrupt handlers and pre-emptive Real Time OS. It should be written in documentation.

Your comments on such offer:

Add in AVR GCC toolchain architectures for 128KB devices. Define  "AVR_HAVE_RAMPZ" macro and save RAMPZ register in interrupt handlers for these devices.

Pro:

  1. Safely use more 64KB data stored in FLASH.
  2. Add xxxx_PF string functions in avr-libc.
  3. In future add support of "far" pointer in avr-gcc.

Contra:

  1. Longer prologue/epologue code in interrupt handlers (4 instructions + 1 byte stored in stack).

Anatoly.

avrs-admin commented 2 years ago

Carlos Lamas Thu 03 Jan 2008 01:54:07 AM CET

This is a good point. I've considered this at the time of writing the functions but then I've discarded it considering that the code for pgm_read_xxxx_far() macros in avr/pgmspace.h has also the same problems and EEPROM routines are also affected. RAMPZ modification is documented but I agree that the side effects could be explained more clearly.

Making these functions reentrant secured imposes a small penalty (just to save and restore RAMPZ in any of the free call-used registers, 2 instructions, 2 machine cycles) for each function, probably small enough to avoid having two different versions, one reentrant and the other not. pgm_read_xxxx_far() macros probably could live in two flavors, reentrant and not reentrant. These macros will suffer more (relative to their small size) overhead costs adding RAMPZ preserving code.

This is all referred to interrupt handlers only. Preemptive task execution will require to save and restore RAMPZ as part of the task state for each context swap unless interrupts were disabled in the whole function (absurd)

Maybe it's time to debate the creation of a reentrant avr-libc version...

  1. In future add support of "far" pointer in avr-gcc.

This sounds a bit optimistic but... who knows?

avrs-admin commented 2 years ago

Moritz 'morty' Strübe Thu 07 Aug 2008 04:20:25 PM CEST

Hi there

I'd suggest using '"p"  (var) '  instead of '"p"  (&var)' This allows to define:

typedef uint_farptr_t PGM_PF;

define PFSTR(str) ((PGM_PF)GET_FAR_ADDRESS(PSTR(str)))

which again makes it easy to create new functions like printf_PF.

Just my two cent.

Cheers

avrs-admin commented 2 years ago

Eric Weddington Wed 22 Oct 2008 06:50:15 AM CEST

Carlos,

Could you create a patch to avr-libc? Otherwise we will have to manually merge your separate files and it will take longer to commit this.

Thanks, Eric

avrs-admin commented 2 years ago

Jan Waclawek Thu 03 Jun 2010 05:23:06 PM CEST

Adding one more function, memcmp_PF().

Jan Waclawek

(file #20682)

avrs-admin commented 2 years ago

Jan Waclawek Wed 30 Jun 2010 02:50:06 PM CEST

The xxx_PF() functions modify the RAMPZ register, but on XMegas with EBI, RAMPZ influences also LD/LDD/ST/STD, making code after using xxx_PF() to access unintended data memory "pages".

In the attached file, in macros.inc, macro LPM_R0_ZPLUS_INIT is modified and macro LPM_R0_ZPLUS_FINI added, storing and restoring RAMPZ, for targets with __AVR_HAVE_RAMPD__ defined (which IMHO is unique indication of presence of EBI). Only LPM_R0_ZPLUS_FINI needs to be added to xxx_PF() functions (and documentation modified accordingly), as shown in the attached memcpy_PF(). All the xxx_PF() functions are affected and should be modified accordingly after consensus happens.

As a cheaper alternative, RAMPZ could be simply zeroed as all "standard" RAM access in current avr-gcc is restricted to 16-bit addresses; whether this is a better option I leave to decide for the more experienced developers on this forum.

This resolves https://savannah.nongnu.org/bugs/?func=detailitem&item_id=25120 which thus could be closed as duplicate (the issue with RAMPZ mods being non-interrupt safe is resolved by saving RAMPZ in the standard interrupt prologue/epilogue as of avr-gcc version 4.3+).

(file #20859)

avrs-admin commented 2 years ago

Jan Waclawek Wed 03 Aug 2011 11:06:02 PM CEST

The _PF functions in the respective binary libraries are broken, and they ever were, since the've been added to avr-libc in 1.7.0.

They don't use the ELPM instruction rather, incorrectly, the LPM instruction.

The reason is, that these functions rely on LPM_R0_ZPLUS_NEXT macro in common/macros.inc, which uses the BIG_CODE macro defined in the same file to determine whether LPM or ELPM is appropriate.

BIG_CODE is defined according to FLASHEND macro which comes from the individual files' headers (additionally, the RAMPZ register's address might be needed for some of the files). However, these files are compiled with the "generic" -mavrN switch, so the FLASHEND macro is unavailable thus considered zero by preprocessor.

avrs-admin commented 2 years ago

Georg-Johann Lay Mon 26 Sep 2011 10:43:32 PM CEST

They don't use the ELPM instruction rather, incorrectly, the LPM instruction.

The very problem is that AVR with > 64k flash is a segmented architecture and it's not easy to handle them correctly.

For example, ELPM Z+ might change RAMPZ so that this instruction is not of much use.

The root problem is the ABI and that it does not disallow crossing section boundaries, i.e. 64k boundaries.  No data must cross such boundaries and if ELPM Z+ shall be used to get efficient code (users like small/fast/low-ISR-overhead code) the last byte of each segment must be kept free.

Any other approach will lead to very inefficent code and/or strage artifacts.

The alternative is to take away RAMPZ from the compiler altogether and let the user set it appropriately, but the fact that crossing section boundaries does not work smooth won't go away with it, either.

avrs-admin commented 2 years ago

Jan Waclawek Mon 26 Sep 2011 11:29:49 PM CEST

You seem to have misunderstood my comment.

Carlos's library is fully adequate for its purpose and has been used for that purpose by several users months or even years before it has been accepted in 1.7.0; the problem is that it is incorrectly compiled within avr-libc.

My comment thus describes an identical problem to https://savannah.nongnu.org/bugs/?32945 (I wasn't aware of at the time when this problem was brought to my attention in the linked avrfreaks thread).

JW

sprintersb commented 7 months ago

As far as I can see, all these issues have been resolved: