Forum : 8051
Post Information | Post |
---|---|
April 18, 2011 - 6:58pm
|
Hi, The flash programming interface we use allows us to place a serial number at a certain memory address at the time of programming, and automatically increment this. I can work out how to read from this address at run time to discover the serial number, however I wish to be able to store a predetermined marker at this address incase one of the developers programming the device fails to input a serial number. Aditionally I have a number of other constants I wish to save in the same area of codespace as this bank is one that cannot be modified by the bootloader so is useful for operating characteristics specific to one device or another. My question is what method should I be using in order to locate the constants at a fixed address. TIA Andy |
in C:
- all variables and constants that you would like to have at fixed addresses MUST be global
- then with the 'at' prefix you can tell the linker where to store your data
e.g.
code at 0x1234 unsigned char Numbers[10]={0,1,2,3,4,5,6,7,8,9}; // this Array will be placed from 0x1234 to 0x123B
xdata at 0x0100 int Calibration_value; // Variable in the XRAM-Area or in the (internal) EEPROM-Area of some devices.
idata at 0x80 unsigned char Value;
and quite handy:
bdata at 0x20 char bitfield; // at 0x20 in the internal RAM - equals bit-addressable bits 0 to 7
bit at 0 bit0, bit1, bit2,bit3,bit4, bit5, bit6, bit7; // same byte in the RAM
this saves many shift-operations when de-/serializing data.
And also possible (generates a compiler warning, obviousely): overlap 2 bytes with one integer-value. This is very useful when dealing with variable reload-values of the timers. Just write the 16-bit value and read 2 8bit-values:
data at 0x30 unsigned int timer_reload; // stored high-byte first
data at 0x30 unsigned char timer_reloadH, timer_reload_L; // hich-byte at 0x30,low-byte at 0x31
for variable timer-reload you can then use the following:
timer_reload = 65536 - time_to_set;
TL0 = timer_reloadL;
TH0 = timer_reloadH;
regards
Bernhard
the array Numbers[] will be at the place, where your serial-number gets stored. So if you read 0123456789, then the number is not initialized.
Other possibility, use pointers. declare a pointer-variable to the code-area, then set the pointer to the known address and read from tha address.
code char *address_of_serial_numer;
address_of_serial_numer = 0x8000; // location of the first byte of your number
byte0 = &address_of_serial_numer; // read from address
address_of_serial_numer++; // next address => 0x8001
....
Our users are so experts in using our tools that they answer each other's support requests.
This is sooo cool :cool:
Thank you for your help with this.
Though I have to say we struggled somewhat with the at keyword. It seems to work fine for xdata but not for code.
However we did manage to find a solution which works fine for us, so I'm posting it below incase anyone else comes across the same problem.
The solution we found to work in the end was as follows:
create a separate c file and header to contain the necessary constants.
rom_data.c
int code rom_data_flag_a = 23;
int code rom_data_flag_b = 42;
int code rom_data_flag_c = 19;
rom_data.h
extern int code rom_data_flag_a;
extern int code rom_data_flag_b;
extern int code rom_data_flag_c;
In order to force the code to be located at the required address the following command line flag needs to be passed to the linker.
CODE(?PR?ROM_DATA(0xF800))
Hi Andy,
Why not just:
Or even:
Looks simpler to me.
Concerning the code address if you properly choose the device it should not be necessary to add a CODE directive for the linker.
Best Regards,