We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hi,
I am using Phytec LPC3250 board for my design and I have a very important problem that I have been spending time on for days.
I want to modify my bootloader_NOR code so that I can send my application code image from the serial port.
However, when I define a global variable and use this variable in a function it gets wierd values. My code can be simplified as below:
#include "LPC318x.H" int m = 0; void MyFunction(int value) // do nothing function { } int main(void) { for(;;) { m++; // <- Breakpoint MyFunction(m); } }
When I debug the code, I see "m = 0xE0000420" at the breakpoint where I expect to see 0x00.
This ruins all my intention and I cannot proceed to modify the code.
I think the data in the RAM region is corrupted but I dont know why and I have no sensible solution for this.
Thanks for your helps in advance.
Are you using the 'standard as supplied' bootstrap code as your example?
Have you tried disabling ALL optimizations?
Have you tried making your 'm' variable volatile?
I have previously modified the 2nd level boot loader by putting serial debug facilities in. The one thing I had to do for it to work successfully was to increase the size of the USR stack.
This is a variable scope problem I think, not a hardware problem
Errr.. you haven't declared the variable again in main, have you?
This problem is most likely caused by making the assumption that the static initialization of the variable is working. Just because you write something like:
unsigned long MyVar = 0
does not mean that this initialization automatically happens. There is normally special code included in the startup / initialization code that takes care of copying the static initialized variables out of a code flash block into the DATA and XDATA variables. In your case with a boot loader you may not even have setup to use the standard startup code!!
Personally I do not ever write embedded C code that uses static initializers for RAM based variables. For these I write code lines in the beginning of main() or in an initialization subroutine that sets the desired initial values of the variables. Static initializers for variables that are in the CODE space flash make a lot of sense and do not require special handing in the startup code.
Michael Karas
Thanks for your reply.
Yes, I am using the standard bootstrap code. I have no optimization in the project options. And yes, I tried volatile for m.
The problem is that the memory region is corrupted as soon as the bootloader program starts running. For example, the value at address 0x08000004 immediately becomes "0xE000032F". If my variable is located at that address then my variable is gone forever.
The more important thing is that, I cannot get serial data. because in order to get the serial data I have to read memory. And as it is corrupted, I get nonsense values. I send 10 from the PC and get 85 at the mcu.
The memory regions should be changed maybe I dont know. I terribly need help.
Thanks.
Hi Michael, thanks for your reply.
I am pretty sure that the problem is not assigning the variable value. The problem is that the RAM region I am using is changed by the program. As soon as the program starts the value at the memory address 0x08000004 becomes "0xE000032F". So, if my variable is located at that address, I cannot ever reach my variable value.
Also, if my variable is not located at an address that changes automatically, then there is no problem. However, no one can assure that.
Also, the problem is not only the variables, when I try to read the serial receive buffer (from address 0x40090000) I get nonsense values. So, I cannot make the serial communication work either.
Thanks for your replies.
"...does not mean that this initialization automatically happens."
Even with the (sample) bootstrap code, initialisation of variables occurs - Unless steps are explicitly taken to exclude it. It is carried out automagically by the scatter load routines immediately prior to entry of main.
"Personally I do not ever write embedded C code that uses static initializers for RAM based variables."
Nor do I, but that is mainly for reasons of code efficiency.
What I suggest you do is single step through the startup code, watching the memory location of the variable becoming corrupt and see where that corruption occurs.
In the standard startup code, it jumps to main with the sequence:
LDR R0, =__main BX R0
Select the dis-assembly window and single step there. Then I would expect you to enter the scatter load code.
It's a while since I modified my bootstrap, but I seem to remember that doing this brought me to the conclusion that the stack was originally only just sufficient for the unmodified bootstrap code. My first small additions took it over the edge.
That's bad reasoning. The whole feature of initializing static variables exists because the compiler and linker can do it much more efficiently than self-written code ever can. The linker can split zero-initialized variables from those with explicit non-zero ones, and do the entire job with as little as the equivalent of one memset() and one memcpy() before entry to main.
What exactly did you expect to happen? The bootloader, once called, owns the entire CPU, including all the RAM. It has to. And yes, that means you can not rely on any RAM contents being untouched after the bootloader has run unless the documentation of the bootloader explicitly stated that it's going to leave certain locations unmodified. Does this bootloader make that kind of promise about that particular memory region?
I have assumed the OP is talking about the 2-nd level bootloader and he is modifying that.
If those assumptions are correct then he can rely on the contents of RAM since his application is the bootloader - So long as they are within the bounds and knowledge of his modified bootloader.
"The whole feature of initializing static variables exists because the compiler and linker can do it much more efficiently than self-written code ever can."
No. It has to provide the feature because the C standards require it.
Optimization can refer to both speed and size. A memcpy() has to copy from somewhere and that somewhere can take up space. If a platform has limited code space then this can be taken into account.
When using something other than ARM (such as C51) it is very easy to beat the efficiency of the compiler by writing portions in assembler - So I prefer not to subscribe to the theory of 'compiler knows best'.
A misunderstanding. I was talking about why the feature exists in the C standard, actually.
A memcpy() has to copy from somewhere and that somewhere can take up space.
So does the initial value any other method writes into the variable. The problem is that the method you outlined (explicit initialization by C code called at some appropriate moment) inevitably uses more space than just that data. It requires code to do the copy. There's simply no way that this extra code, for all such initializations combined, can be smaller than that of a memcpy()-like loop.
If a platform has limited code space then this can be taken into account.
It's especially in that case that you can't afford the overhead of having hundreds of copies of the "initialize this object" code fragment. That's why your idea reduces efficiency, instead of helping with it.
it is very easy to beat the efficiency of the compiler by writing portions in assembler
There may be portions like that in most programs. Static variable intialization is most decidedly not one of them.
"That's why your idea reduces efficiency, instead of helping with it."
You're talking in too simplistic a manner.
Quite frequently (at least in many of my projects), modules need to be initialised, disabled and then re-initialised. The re-initialisation (normally) requires variables to be given a known value - Through code. If it has to be done in that way once, then it might also be done that way when first initialised. Then there can be an overall saving in both code space and data space.
I do this because I have checked results and found it does give me what I need; i.e., a reduction in overall code space - In various projects on various platforms over a reasonably long career.
I'm not saying this would always be the best solution, but one worth considering with an open mind.
As with much programming, there is no absolute right or wrong way - Just a good choice for the problem in hand.
Is that possible, the OP's 2nd boot-loader uses the IAP functionality, and the IAP functionality needs some RAM space, so some RAM region is modified?