Hello,
I'm trying to display a menu on my device, with str710 mcu. To do that, I create use structs to hold the variables and display them later. My structs look like this:
typedef const struct mMenu_s { int type; char text[3][20]; struct command { int command; int argument; } commands; struct specialline { int een; int twee; int drie; } speciallines; } menutype; typedef struct sMenuTemp { menutype *mCurmenu[20]; int iCurmenu; int iCurmenupos; int iOldmenu; int iOldmenupos; int menuactive; } cmdMenu; extern cmdMenu sMenu;
And to place data in it I use:
cmdMenu sMenu; menutype Backlightmenu[] = { { 1, {"Rood", "Red", "Rot"}, {SET_BACKLIGHT,RED}, {NULL,NULL,NULL} }, { 2, {"Groen", "Green", "Grun"}, {SET_BACKLIGHT,GREEN}, {NULL,NULL,NULL} }, { 3, {"Wit", "White", "Weiss"}, {SET_BACKLIGHT,WHITE}, {NULL,NULL,NULL} }, { NULL } }; sMenu->mCurmenu[BACKLIGHTMENU] = Backlightmenu;
With this method I can let (other) programmers create/delete/edit a menu very easy. So far so good.. All the text, commands, arguments and the rest of variables are stored in the memory OK (checked the memory watch, all OK!). But then.. I wan't to display the texts. Selecting the menu, the menuline, the language and the text is no problem. But, with the displaying, the last line of my struct is getting destroyed.
I've debugged my program, and it seems that the LCD-library caused the problem. It does an integer division, and the assembly calls "__aeabi_idivmod", which is an divide-function. On the first instruction, which is: PUSH {R4-R6,LR}, the data of my struct get destroyed, and it very, very weird values on the place of the struct..
And, the stupid thing.. When I remove the graphic-function, it's all normal. And, it doesn't matter on what memory-location my struct is placed, it happens every time.. It looks like the divide haunts my struct =S.
I'm working with the MDK-Arm 3.70 toolchain, in uVision3. Does anybody have an idea why this happens? Or, even better, the solution? I've tried a lot of other things, but it would be so d*mn easy to build and display my menu like that...
Thank you so very much.
Jay.
First are your menu's supposed to be unmodifiable? If so they should be written to be in ROM space only. Second if the division function is modifying your data, then it is likely pointing to your data and your data pointers are getting messed up.
You should always know WHAT you are pointing at. That is what you should check in the debugger. Find out what points to your structure (IE register) and find out what the parameters to your division function are (registers).
You may need to examine your LCD drivers or if someone else wrote them, you should contact them and ask what the LCD drivers are expecting and how to avoid conflict.
Since I normally write my LCD drivers I talk to myself (it's quite humorous but short). Erstwhile be sure the data you are using needs to be modified and if something is modifying it, THAT is a VERY serious bug. Always look at your pointers in the debugging MAKE notes also. If you don't have documentation make it, this will save you time debugging. IE what function is causing corruption where it's located what it's doing what you expect it to do etc.
Stephen
Hi!
Thnx for your fast reply..
First; the data in the struct does not have to be modifiable.. It could be handy (to show a setting-from-flash in the menu for example) but it's not necessary. I've found something about the ROM-thing. Something with a "const"-definition. I tried, still same effect (on the divide-instruction).
I've already tripple-checked my pointers.. They look OK. When I search the memory-window with the adresses the variable-watch says, it shows me the data as it should be. But, when I keep an eye on the memory-watch, and I step trough the program (in the disassembler), the PUSH-instruction, with the registers I mentioned (the registers DOES hold data, but not from my struct) does mess up my struct..
But I don't get it.. I've tried to modify my struct and my code in many ways.. And whatever I tried, on what address my struct is stored.. It always get messed up by the PUSH-instruction.....
Maby I can try the ROM-thing again? Did I missed something? Do you have other suggestions? Thank you for your time!!
You don't really give us much to go on there. What is that LCD library code actually doing at the point of the corruption? Is it, by any chance, working on some of the data contained in that struct? Why would it be performing a division in the first place? And what do you mean when you say:
the last line of my struct is getting destroyed
What gets written where?
Without answers to those questions, I can only offer some general comments.
*) Please don't write NULL when you mean integer zero. NULL should be used for data pointers only.
*) It may not be too wise to put your menu texts directly into the struct, as arrays insetad of pointers to string literals. That's a waste of memory, and likely to create nasty effects if anybody ever configures a string longer than 19 characters.
*) Have you checked for possible stack overrun?
Thank you for your replie(s). I've changed my code/struct a little bit. I've removed the two structs in the sMenuField-struct. I've also changed the array into a multi-dimensional pointer-array. Now it's like this:
typedef struct sMenuField { int type; char *text[3]; int commands[2]; int speciallines[4]; } MenuFieldtype; typedef struct sMenu { MenuFieldtype *mCurmenu[20]; int iCurmenu; int iCurmenupos; int iOldmenu; int iOldmenupos; int menuactive; } cmdMenu;
But still.. Same problem.. The struct that's holding the pointers gets changed by the graphic library. Not on the divide-part now, but just on a variable-assignment in C. The disassembly says:
0x20002D58 B4FF PUSH {R0-R7}
Register R0 and R7 both holds 0x00000000.
I've created two screenshots to clear up the effect of the instruction.. The first one is a screenie of the memorywatch, after creating the struct and place my data in it. I've marked the part that holds the last line of the menu. The second one is the screenie right after the PUSH-instruction. Again I've marked the part that it's all about. As you can see, there is nothing (recognizable) left.
img406.imageshack.us/.../memorybeforepush.jpg img294.imageshack.us/.../memoryafterpush.jpg
*) I've checked for a stack-overrun; not possible. The're just a few things on the stack.. The MCU must be capable of handling this..
*) I've changed to NULL to integer zero (or another logical integer.)
*) As you can see, the text is stored in a pointer. That is working very well. The text is not getting touched by the instructions. It's just the struct that holds it all together..
It's so weird.. It's always the last line.. -.-. And it's also always a PUSH-instruction that destroyes the last line.. Does anybody have any idea?
Thank you very, very much!!
you can instruct the debugger to stop when a specific memory location is read/written. maybe this can help you detect what modifies your struct.
Thank you for you reply..
But.. Euh.. I already know where my struct gets modified.. And by what instruction.. It's getting modified by the PUSH-instruction..
But, i'm curious. How can I do that, what you suggested?
Thanks!
Debug->Breakpoints->Access
Don't forget to specify the size and bytes/objects, and of course the expression to be evaluated. that can also be a memory address, of course.
*) I've checked for a stack-overrun; not possible.
I'm afraid your word isn't quite good enough to back up this statement, especially since it rather strongly contradicts the evidence you showed. A PUSH instruction writes to data to exactly one place: the stack. That write is hitting data that's not supposed to be part of the stack. The only way that can happen is if the stack pointer register no longer points into the area allocated for the stack. That leaves two possibilities:
1) this PUSH is a stack-overrun in action
2) the stack pointer itself has been corrupted by a previous bug
You'll have to look at your memory map, register and call stack displays to tell these two apart. If the call stack still looks sane, and the stack pointer points near the allocated stack area, case 1) is more likely than 2).
Yes, you're right. It must be stack overrun.. When I disable a few things from my graphic-library (so, the library can skip a lot of functions), the struct stays intact.
I also found this document: infocenter.arm.com/.../index.jsp
It says that structs are always located on the stack. And the stack graphic library places also things on the stack. And because there is no more space, my data (from the struct) gets overwritten by other data.. I think I get it..
But.. With earlier versions of my software I also used a multi-dimensional struct with like 20 fields or something. But that struct was filled in another (very ugly) way. This way to fill my struct is much easier and looks very nice, but here it seems responsible for a stack overrun. Why? Why not with a very, very large struct and all of the functions of the library enabled? Is it because of the pointers? Because it's a pointer-struct? I don't know.... Anybody any idea how to solve it?
Thanks for your help everyone!
It says that structs are always located on the stack.
You're reading too much into that statement. That document talks about variables with automatic storage duration. In less technical terms, that means variables local to some function or other block, which are not marked "static". Your struct is supposedly of static storage duration (it hardly ever makes sense to have a 'const' variable that isn't), so this doesn't apply.
This way to fill my struct is much easier and looks very nice, but here it seems responsible for a stack overrun.
It's not. Whatever the reason for that stack overrun is, the definition of a variable is not it.
Hi! I've the same problem with overwriting variables (simple variables or structures). I work with two device: LPC2478 and STM32F103 (both based on ARM core) and both have the same problem. In my opinion it could be problem with compiler. I use uVision3 v3.85. The reason that I thing it could be fault of compiler is really simple. When I compile project on previous version of uVison everything is ok and when I compile the same project on v3.85 program doesn't work correctly. What do You thing? Which version of uVision do you use? Foregive me mistakes in English.
That is really rather unlikely!
Far more likely is that your code is flawed with some "latent" bug that just happened not to manifest in the earlier compiler.
See: http://www.keil.com/forum/docs/thread15735.asp - is that also you?
Perhaps you were relying on a default that has changed?
"When I compile project on previous version of uVison everything is ok and when I compile the same project on v3.85 program doesn't work correctly."
So, have you compared the two to see where they differ?
The LPC2478 is an ARM7; the STM32 is a Cortex-M3
"both have the same problem"
If your code has the same effect on two different cores I think that rather suggests that the bug lies in your code...?
Hi! Of course STM32 is a Cortex, my mistake, sorry. I have different aplication on my devices. LPC2478 works as a LCD driver and STM32 sent to LPC via SPI some information to display. In LPC I have problem with local variable in function but only when the function calls other function with other function calls (just like in post http://www.keil.com/support/docs/2989.htm). And on STM32 I have problem with big structures for graph library. For LPC I track the problem step by step (in debug mode) and I am sure that instruction STMDB cause the problem - variable are overwritten.
"PUSH and POP are synonyms for STMDB and LDM (or LDMIA), with the base register sp (r13), and the adjusted address written back to the base register. PUSH and POP are the preferred mnemonic in these cases."
http://www.keil.com/support/man/docs/armasm/armasm_babefbce.htm
So your problem is stack corruption - as described earlier in this thread?