[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-libc-dev] Far addresses in flash
From: |
Carlos Lamas |
Subject: |
[avr-libc-dev] Far addresses in flash |
Date: |
Wed, 01 Jun 2005 22:24:58 -0000 |
Hello,
This is a proposal to include a mechanism to access the true address of
data in Flash ROM (23 bits for the AVR specification) from C code. The
"address-of" operator '&' does not suffice with its 16 bit limited
precision to 16 bit to read data beyond the low 64K of memory.
There are, for instance, many users programming bootloaders for the
ATmega128 asking for a way to cleanly access data in flash from C code
without knowing absolute data addresses at compile time.
The following macro is the proposed solution:
#ifndef __STRINGIFY
#define __STRINGIFY(str) #str
#endif
#define GET_FAR_ADDRESS(var) \
({ \
uint32_t tmp; \
\
__asm__ __volatile__( \
"ldi %C0, hh8(" __STRINGIFY(var) ")" "\n\t" \
"clr %D0" "\n\t" \
: \
"=d" (tmp) \
: \
"0" (&var) \
); \
tmp; \
})
This is a simple example of use. To test the code with true FAR (>64K)
addresses .text section must be moved to a higher place in memory in
the linker command.
#include <stdint.h>
#include <avr/pgmspace.h>
static uint8_t st[] PROGMEM = "This is a flash memory string";
int main (void)
{
uint32_t address;
uint8_t c;
address = GET_FAR_ADDRESS(st);
address += 4 * sizeof (uint8_t);
while ((c = pgm_read_byte_far(address++))) {
foo(c);
}
for(;;)
;
return 0;
}
COMMENTS
- The overhead is minimal and it's mainly due to the 32 bit size
operation.
- 24 bit sizes guarantees the code compatibility for use in future
devices.
- hh8() is an undocumented feature but seems to give the third
significant byte of a 32 bit data and accepts symbols, complementing
the functionality of hi8() and lo8().
- __STRINGIFY(var) could be replaced by #var and the __STRINGIFY()
macro removed, but the nested macro sequence allows the preprocessor to
replace the identifier 'var' when itself is also a macro.
- 'var' has to be resolved at linking time as an existing symbol, i.e,
a simple type variable name (not a constant), an array name (not an
indexed element of the array), a struct name (not a field of the
struct), a function identifier, a linker defined identifier,...
- The input and output operands in the asm instruction are different
sizes and both share the same storage. Particularly the output operand
'tmp' is bigger than the input operand '&var'. I haven't extensively
tested this.
- The & operator passes part of the job to the compiler and is valid
for every identifier, even for array and function identifiers.
- The input operand informs the compiler that the data is in use, to
avoid used static data removal. The stringifying conversion in the
middle of the instruction doesn't notify of the use.
- The natural place for this macro should be the header pgmspace.h and
the name... pgm_get_far_address?
Regards
--
Carlos Lamas
- [avr-libc-dev] Far addresses in flash,
Carlos Lamas <=