alager
(Tester - PRO for PSoC)
Thu May 15 2008 04:23 PM
flash routine / linker overwritting code

The linker is moving my code around based on this variable:
const BYTE EEPowerUp @ 0x0080;//0x0fc0;

Consequently I can not place my flash variables in "unused" areas of flash because no matter where I put them, other code is placed into the same block. Then when I call flash_writeBlock(), my chip gets corrupted.

The expected behavior is to find a block of flash that is not being used, and then place up to 64 bytes of storage there, and the code stays where it was.

Aaron


alager
(Tester - PRO for PSoC)
Thu May 15 2008 04:45 PM
Re: flash routine / linker overwritting code

A temporary work around I found is to declare the variable as an array of 64 bytes.
const BYTE EEPowerUp[64] @ 0x0080;//0x0fc0;

However this is a pain because now I, not the computer, have to think about where code is, and how much space it's taking up ect.

Aaron


clydeAdministrator
(HI-TECH team member)
Thu May 15 2008 04:51 PM
Re: flash routine / linker overwritting code

Aaron, can you explain a little more? I'm not sure what you mean by "based on this variable". The address you've chosen for it is quite low - it's just above the vector table. It's also only one byte in size, so the flash locations around it (i.e. 0x7F and below, and 0x81 and above) are still up for grabs.


If you want to reserve a block of flash so the compiler doesn't use it, you can either use the --ROM option to the compiler or you can place an array on a constant address, e.g.
Code:

const unsigned char _reserved[64] @ 0x7FC0;


would reserve 64 bytes of flash at the given address. There is also a macro in <psoc.h> that will reserve a specified number of blocks at the top of flash:
Code:

#include <psoc.h>
EEPROM_RESERVE_BLOCKS(1)


will reserve 1 block (64 bytes for most PSoC chips) of flash at the very end of the flash memory. The size of a block, and the total size of the flash, are already known by the compiler based on the chip selected.

Clyde


clydeAdministrator
(HI-TECH team member)
Thu May 15 2008 04:57 PM
Re: flash routine / linker overwritting code

Aaron, why don't you explain exactly what it is you are trying to achieve? The compiler is quite happy to manage the memory for you, so if you don't want to do that, why are you reserving flash bytes in the first place?

Clyde


alager
(Tester - PRO for PSoC)
Thu May 15 2008 06:04 PM
Re: flash routine / linker overwritting code

I have to apologize a little on this one. I evidently did use the ROM command in an old project to work around this problem. But I couldn't find anything related in the search of this forum.

I'm just trying to store a value that I can read on power up.
Instead of using the flash read function, I took the advice of the header file and defined a variable directly to the address where my variable will be stored.

I just tried the macro EEPROM_RESERVE_BLOCKS(1), and it behaves similar to my work around. It does work, but the code is relocated to the end of flash (0xba2). I guess this isn't a big deal, but it sure wasn't expected in either case.

Aaron


clydeAdministrator
(HI-TECH team member)
Fri May 16 2008 01:09 AM
Re: flash routine / linker overwritting code

Aaron,

You said "I'm just trying to store a value that I can read on power up." How and when are you storing the value?


alager
(Tester - PRO for PSoC)
Fri May 16 2008 11:09 AM
Re: flash routine / linker overwritting code

Clyde,

Below is the code that I'm trying to run. It's a simple routine to cycle through a few different states each time power is applied. It's called once from main() after the user modules are initialized.

Aaron

Code:

BYTE PowerUp;
const BYTE EEPowerUp @ 0x0fc0;

void ReadSettings(void) {
PowerUp = EEPowerUp;

}

void SaveSettings(void) {
BYTE value;
_flash_temp = 25;
_flash_delay = (((24*100L-80)/13));
value=flash_writeBlock((void *) &PowerUp, BLOCK_ID);
}

void PowerUpState() {
//read and toggle the PowerUp byte to allow normal
//operation or color cycling

ReadSettings();
if (PowerUp == 0) {
//color cycle
PowerUp++;
} else if (PowerUp == 1) {
//just be on
PowerUp++;
}else if (PowerUp == 2) {
//cycle with pause
PowerUp=0;
} else {
PowerUp=0;
}
SaveSettings();
}





clydeAdministrator
(HI-TECH team member)
Fri May 16 2008 05:31 PM
Attachment
Re: flash routine / linker overwritting code

Aaron,

that is pretty much what I thought. The bottom line is that since the PSoC flash can only be written in blocks of 64 bytes (or 128 for some new chips) you have to reserve at least one whole block if you want to use it as EEPROM.

If you want to hide the details of this you can use the eeprom_read and eeprom_write functions, e.g. here is a little test program I wrote for these functions:

Code:

#include <psoc.h>
#include "lcd.h"
#include <string.h>
#include <stdio.h>

#define OFFSET 0x30
#define VALIDVAL 0xAA23
EEPROM_RESERVE_BLOCKS(2); // reserve 2 blocks of FLASH for EEPROM emulation
struct
{
int var1;
long var2;
char var3[10];
int valid;
int seq;
} evars;

void
main(void)
{
lcd_init();
lcd_puts("start");
lcd_goto(0x0);
if(!eeprom_read(OFFSET, &evars, sizeof evars)) {
lcd_puts("read fail");
for(;;);
}
if(evars.valid != VALIDVAL) {
printf("invalid %X", evars.valid);
memset(&evars, 0, sizeof evars);
evars.var1 = 0x1234;
strcpy(evars.var3, "hello wor");
evars.var2 = 0xABCDEF99;
} else {
lcd_goto(0);
printf("Read %X", evars.var1);
}
lcd_goto(0x40)
evars.seq++;
evars.valid = VALIDVAL;
if(!eeprom_write(OFFSET, &evars, sizeof evars)) {
lcd_puts("write failed");
for(;;);
}
printf("FlASH seq %X", evars.seq);
}



This is writing a whole structure to the eeprom, and also using an offset into the eeprom (this is just for test purposes).

When this board is powered on, it displays a number on the LCD that is one more than the last time it was powered up. Note the use of a magic number to detect the first time it was powered up after flashing.

I've attached a zip file with a complete project using this code.

You could use the same approach for your application.

Clyde


alager
(Tester - PRO for PSoC)
Mon May 19 2008 11:53 AM
Re: flash routine / linker overwritting code

Thanks Clyde!

The macro: EEPROM_RESERVE_BLOCKS(1); Does the trick. As you state, it reserves the block, so that no code is placed in that block, and therefore not over written.

I guess what threw me off in the beginning, was that when I declared the constant variable at a specific address, the linker would move the code around so that there was code always in the same block as my constant variable.
I presume this is happening so that LJMP can be avoided within the compiler generated code.

Aaron



Contact Us | Privacy statement HI-TECH Software

Powered by UBB.threads™ 6.5.5