Hi,
The following code gives different values (val1 and val2) for the same data after the ROM write operation. Any reason why and what is the solution? My CPU is K60.
//-------
const int a = 10; //Constant variable in ROM
void get_value_a (void) //Function to get the value a
{
return a;
}
void main (void) //main program
{
int val1, val2;
val1 = a;
val2 = get_value_a();
//!Problem: val1 gives actual value after I update the ROM with different value, but val2 gives me the old value.
}
Thanks.
Solved! Go to Solution.
Hi everyone,
Adding "volatile" solved the problem. Thanks @bobpaddock for the suggestion.
@myke_predko, I use the "const" to store configuration data of a device. For example, I use the value of a to display "English", "French", "Japanese" etc, on the LCD. I have developed an application that allows users to connect the device using USB and reconfigure the LCD display. During the reconfiguration, I rewrite the flash (value of "a"). This will allow the device to display the configured language even when the device restarts after power off.
I will explore other Flash write operations as suggested by @myke_predko. Any suggestions where I should look for?
Thanks.
If I undestand you correctly, you're looking for a way to store configuration information (language specified) in a way that it can be changed and the last value is accessible upon boot.
Personally, I would select a free block of Flash memory and use it to store a configuration information. I recommend using the second to last block in Sector 1 - the last block of each sector is reserved for sector swap data (if this feature is used - but it's still good to not use it just as a rule of thumb in case you want to implement sector swapping for in field updates).
The configuration information would defined in a structure and look something like:
struct NVconfigStruct {
uint32_t checkWord;
uint32_t language;
// You can add more data items to the configuration structure
};
to point to the configuration information, you'll use the pointer "configPtr" (with setup code):
uint32_t sectorSize;
FLASH_GetProperty(&s_flashDriver
, kFLASH_PropertyPflash0SectorSize
, §orSize);
struct NVconfigStruct* configPtr = (struct NVconfigStruct*)((sectorSize * 2) - (FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE * 2));
In ram, you'll need to set up an NVconfigStruct Buffer:
struct NVconfigStruct configBuffer = { 0xA5A55A5A
, 2 // "language" = English (2)
};
In your start up code, you'll check to see if configPtr->checkWord == 0xFFFFFFFF; if the value is all Foxes, then this is the first time executing the application and you'll write configBuffer at configPtr to get an initial configuration:
if (0xFFFFFFFF == configPtr->checkWord) {
flashWrite(configPtr
, configBuffer
, FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE);
}
After this if statement executes, you'll know that the configuration is set and you can use configPtr->language as the user specified language value.
When you want to change the language, set the appropriate value to configBuffer.langauge and then write configBuffer into the sector of Flash at configPtr.
This approach is fairly easy to understand and does not rely on compiler idieosyncracies or esoteric type definitions and uses standard Flash writing methods which you already have working.
I am thinking that your intention to use the const prefix for a variable is just to tell the compiler that you wish the variable to be placed in flash/ROM. I believe that there are other procedures to achieve the desired functionality that we could evaluate.
You could look at the Pflash example in the SDK of the TWR-K60 , which erase several pages of the top of the flash memory and then writes the contents of an array into a certain flash page. However, I am not aware how many times your application will intend to update a variable, to recommend this with certainty.
Other option is to use the Kinetis FlexRAM. This lets you use the Flash as an EEPROM, which has several advantages. Some Kinetis Like the MK60FX512VLQ12 does have this feature, you could check if your part is does.
Regards,
Diego.
I think, as @bobpaddock indicated, you have to provide more information.
I just tried:
void testCMD(void);
int i = testCMD();
:
void testCMD(void) {
return 4;
}
and I got the error "void value not ignored as it ought to be" and the warning (in the method) "'return' with a valud, in function returnting void [-Wreturn-type]". Normally, when you specify "void" as a return value for a method, it means that nothing is to be returned and you should get the error that I got.
If you change the code to:
int testCMD(void);
int i = testCMD();
:
int testCMD(void) {
return 4;
}
Things build and run fine.
I'm curious to find out how you got this built so that it can be executed.
How does this code even compile?
get_value_a() returns a void, not an int.
What compiler are you using?
Make sure all error and warning messages are enabled.
Thank you for the reply.
I made a typing mistake in my earlier post.
The function is actually,
int get_value_a (void) //NOT: void get_value_a (void)
{
return a;
}
I use CodeWarrior Development Studio 10.6. The only reason I can think of is compiler fixes the constant values directly in the code.
What value are the values in val1 & val2 when you reach the comment in your code and can you exactly what you're doing in your application?
In your original post, you put in: "Problem: val1 gives actual value after I update the ROM with different value, but val2 gives me the old value."
What do you mean "update the ROM"? Are you rewriting Flash or writing to "a"?
myke
Hi mykepredkomimet,
Yes, I am rewriting the flash.
Initially I assign a value, "a = 2". During the runtime, I rewrite the flash to make "a = 4".
When I see the values in val1 and val2 after the flash write operation,
val1 shows 4
val2 shows 2.
I could verify that the data in the flash memory has changed to 4. So, I assume compiler assigns the value directly in the code (optimization!!??), therefore even after the flash write, val2 is still 2.
How are you "rewriting" the Flash? This is not a trivial exercise - you're going to have to identify the location of "a" and the block it's in, erase it and then rewrite it, all while ensuring that excution does not take place in that block. That's not a trivial amount of work.
Going back to your original code, if I understand the situation correctory I would update it to:
const int a = 2; //Constant variable in ROM
void get_value_a (void) //Function to get the value a
{
return a;
}
void main (void) //main program
{
int val1, val2;
flashIntUpdate(&a, 4); // Method to change Flash location used to store integer "a" to 4
val1 = a;
val2 = get_value_a();
}
If, as you presume, the optimizer is replacing the value for "a" with its initial value (2) rather than actually reading the contents of the variable (whcih is 4 after "flashIntUpdate") then both val1 & val2 would be 2 and neither one 4.
I'm curious to understand why you're doing this (if I understand it correctly) as if you are defining a variable as "const", I would assume that you want that variable to be always the same value.
myke
You got it almost right, except the function to get the value "a" is as follows.
const int a = 2; //Constant variable in ROM
int get_value_a (void) //Function to get the value a
{
return a;
}
void main (void) //main program
{
int val1, val2;
flashIntUpdate(&a, 4); // Method to change Flash location used to store integer "a" to 4
val1 = a;
val2 = get_value_a();
}
I separate the data and the program sections in the ROM. And update the data using Flash write operation.
Do the results change if 'const' is replaced with 'volatile const'?
If I remember correctly, you only use "const volatile" to create a read only variable at a specific address (like a hardware register that you NEVER want an application engineer to write to but may need to be able to read). I've seen it used in operating systems to force a compile error if the coder is trying to access something beyond their permission level - you get a build error early rather than a confusing run time access violation later on.
I'd like @santoshwagle to explain what he's trying to do because he isn't specifying a specific address for "a" (other than placing it in a set data segment) and, depending on what the goal is, there is probably a lot easier and less esoteric method of coding the required functionality.
The reason I asked was to determine if the compiler in use was doing something odd.
We still don't know what compiler is being used. GCC is likely to inline the get_value_a() function, for example, at normal optimization levels without further attributes.
The C-Abstraction Machine could very well read 'a' only once, as the compiler has no reason to believe that 'a' changed since its first assignment to the global data segment. Adding the 'volatile' would force 'a' to be reread. The C-AM will have no knowledge of a write to flash.
Changing to optimization level of zero/none would also be interesting, and that would also indicate a 'volatile' issue.
I'm sure we all agree there are better/safer ways to modify flash and get the results of least surprise.
Hey @bobpaddock
@santoshwagle indicated that he is using CodeWarrior which doesn't use a standard version of GCC - it's an ARM build that I don't believe has any C99 features, which means that the concept of "inline" isn't in there.
I just did a test build on CW with an "inline static" method and it doesn't generate errors/warnings for "inline" but it also doesn't generate inline code - the assembler code generated is a normal method call.
I think we're heading into the weeds here in terms of how 5+ year old ARM GCC vs today's GCC generates non-standard code and I agree with your conclusion and HIGHLY RECOMMEND that @santoshwagle look at a more traditional way of coding this functionality so that he doesn't end up with something that is build tool dependent, especially when it involves CodeWarrior which is no longer supported.
Sorry, you're right - I forgot to make the change when I copied the code from your original post.
But, the question still stands - why are you defining variables "const" if you are goiing to change them later? If you're looking to have updatable values in Flash, there are more traditional ways of doing it and avoid figuring out what the compiler is going to do.
myke