Closed avrs-admin closed 7 months ago
Anatoly Sokolov
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:
Contra:
Anatoly.
Carlos Lamas
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...
- In future add support of "far" pointer in avr-gcc.
This sounds a bit optimistic but... who knows?
Moritz 'morty' Strübe
Hi there
I'd suggest using '"p" (var) ' instead of '"p" (&var)' This allows to define:
typedef uint_farptr_t PGM_PF;
which again makes it easy to create new functions like printf_PF.
Just my two cent.
Cheers
Eric Weddington
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
Jan Waclawek
Adding one more function, memcmp_PF().
Jan Waclawek
Jan Waclawek
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+).
Jan Waclawek
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.
Georg-Johann Lay
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.
Jan Waclawek
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
As far as I can see, all these issues have been resolved:
ELPM
is used when it is avalable.RAMPZ
is initialized ans updated as needed when ELPM
is used / available, i.e. LPM_R0_ZPLUS_*
macros from common/macros.inc
work as expected (974e621902a5523550c755d55231f4b92c4eb683).RAMPZ
is restored when required (issue #476).
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