I've been trying to troubleshoot a mysterious problem for a few days now, and I hope someone here can give me some ideas. We are using UV3 and C51 (ver 7.50) to develop an application for Cypress FX2 LP which is a 8051 variant with 16KB RAM (which may be shared for code and data). For applications of up to about 11KB in code size, everything works fine. When the program exceeds 11KB, strange problems pop up. Calling some (valid!) functions trigger a system reset. Adding a line to a function that no one ever calls, and the system goes into infinite reboot loop. Adding a dummy file with some uncalled functions, same thing happens. Adding a redundant function call that does nothing and everything goes back no normal, until the next time some other line changes. To make a long story short - total chaos! I can't understand the logic of any of this, and it happens only beyond a certain program size. The program compiles and links with no errors (except "uncalled segment" warning if 'dummy' uncalled functions are inserted). The problem is very distrurbing and very chaotic - the program may run fine up to a certain point, then reboots with no apparent cause at all. Comment out an unused function and all goes well. Another thing I noticed - if I tell the linker to move the program in memory, the fault point shifts randomly to someplace else. We've ruled out a H/W problem or a defective CPU. Has anyone ever encountered something so odd, and can you give me any ideas on how to troubleshoot? Thanks in advance, Ran Shalgi Siano Mobile Silicon
One thing I'd look into would be stack overflow -- don't forget to account for interrupts.
Thanks, I checked that and it doesn't seem to be the case. I narrowed the problem to a test case. The test case is a 11.5KB program that runs fine. I then add one more large function to the code that nobody calls. It is just there to take up space. This function causes things to move around in the memory map, as the linker accomodates for the change. When that function is present, the program crashes during the init sequence. One function call, a simple function call causes a system reset without ever getting to the first line of the called function. I don't understand why the simple presence of one more function should cause a crash elsewhere in an otherwise working code. If anyone is interested I can post map files, listing files or even the complete application source (but you'll probably need a 16KB Cypress FX2LP to run it). Ran
This function causes things to move around in the memory map ... the program crashes during the init sequence 1) sounds like an atomicity problem 2) "crashes during the init sequence" should be easy to debug since, at least, you have a solid crash. Erik
1. Could you please explain what you mean by "Atmoicity problem"? The crash happens simply when function A calls function B. B never gets called and the CPU restarts. Strangely, if I remove code from other areas of the program (which don't get called at all in this scenario), cutting down on program and data size, the problem disappears. 2. The sequence is easily reproducible, but I don't know how to debug it. The application is too big to fit with the back-end monitor of the debugger, and if I trim my application to be small enough, the problem disappears. It does not reproduce on the simulator under any conditions.
Could you please explain what you mean by "Atomicity problem"? If a variable of more than one byte is used at more than one level. the classic example is the global SerialPointer used both in the main and the ISR. Cypress FX2 LP I have never used this chip, but for example for the Philips LPC932 the upper 512 bytes are reserved, are you running into a similar problem? Erik
1. At the crash point, I only have "main" running. All ISRs are disabled. 2. My understanding is that the chip has 256 bytes of internal memory. The lower 128 are directly accessible and the higher 128 are indirectly accessible. Internal data in my application consumes almost all of the lower 128 with the stack immediately following.
Have you found any solutions? I'm seeing the same kind of problems. I just upgraded to the 7.50 compiler. Now things are acting strangely. I'm seeing the program act differently when I add or remove code that isn't even called. There should be plenty of stack space, yet I've seen a call to a function end up with incorrect values getting passed to the function. Value is correct before the call, incorrect when it gets to the function.
Update: only the first parameter is getting corrupted. I believe that one is actually passed using R7 (that's what the assembly indicates). When I disable interrupts, everything works ok, so somehow R7 is getting corrupted.
i have the exactly same problem! this problem has been bother me for almost a month now! however, i am using uvision 2.20a anyone? help
Ok, found my problem. I did have a warning: "MULTIPLE CALL TO SEGMENT...". This was a function that is called by an ISR, and also called at startup. There would not be a case of it being called in both contexts simultaneously. According to http://www.keil.com/support/docs/805.htm, one resolution is this: "If you are 100% sure that two copies of the function will never execute at the same time (if the function is called from the main code and interrupts are disabled) and that there is no memory used by the function (only registers are used), then you may simply choose to ignore this warning." Apparently, with version 7.5 of the compiler, this is no longer true. Even though the two weren't called at the same time, and no memory was used by the function, somehow the generated code messed up register R7 on other function calls that are unrelated. Adding the "reentrant" keyword to the function got rid of the warning and all the problems.
Thanks for all the ideas and suggestions. My problem is still unresolved and seems to be different than what you describe: 1. I have no "multiple call" warnings. 2. The problem happens even when only a single process ("main") calls the function, with all ISRs disabled. 3. The system reboots when the function is called. It's not that I'm getting into the function and getting erronous values - the first line of the function never gets executed.
just a question: since no one states it, are you all using the Cypress chip? Please repost and indicate the derivative you use Erik
16KB RAM (which may be shared for code and data). "May be" is worrying? Are you actually doing that? Do you actually use von-Neumann mapped memory? Adding a line to a function that no one ever calls, and the system goes into infinite reboot loop Bad idea. There should almost never be functions that no one ever calls in a C51 project. There's good reason for linker warning L16 to exist. That said, I suspect the reason for these strange errors is that you have a call through a rogue function pointer somewhere (or equivalently, a write to code through a rogue data pointer). By nothing but a stroke of bad luck, this might happen not to cause serious harm in those builds that appear to work correctly. I.e. you're not really affecting the root cause of the problem by moving code around --- you're just changing the symptoms from benign to desastrous. You'll need a full instruction trace to find out what's going on.
Hans-Bernhard Broeker - you were absolutely right! Problem solved. Here's the explanation: Cypress initialization code copies the USB descriptors to RAM address 0x80. Why 0x80 is an unexplained mystery. HOWEVER, in project settings (copied from a Cypress example!) address 0x80 is part of a valid code memory area and the linker is free to place code there. Whatever code is stored there gets overwritten during runtime by the USB initialization code. When the program is small enough, the linker may elect not to place any code at 0x80. As the program grows larger, random parts of code may be stored there. Changing bits and pieces of code changes linker placement and therefore moves the problem around - it is a different function each time that gets trashed. The solution: change linker settings to start code placement at 0x200 and onwards. I would like to thank everyone for their help, ideas and suggestions! Ran Shalgi
It's been a while since I looked at these chips (my USB now is also a master) but something just dawned on me. Her is an extract from the datasheet:
Individual FIFO/GPIF Interrupt Sources Priority INT4VEC Value Source Notes 1 80 EP2PF Endpoint 2 Programmable Flag 2 84 EP4PF Endpoint 4 Programmable Flag 3 88 EP6PF Endpoint 6 Programmable Flag 4 8C EP8PF Endpoint 8 Programmable Flag 5 90 EP2EF Endpoint 2 Empty Flag 6 94 EP4EF Endpoint 4 Empty Flag 7 98 EP6EF Endpoint 6 Empty Flag 8 9C EP8EF Endpoint 8 Empty Flag 9 A0 EP2FF Endpoint 2 Full Flag 10 A4 EP4FF Endpoint 4 Full Flag 11 A8 EP6FF Endpoint 6 Full Flag 12 AC EP8FF Endpoint 8 Full Flag 13 B0 GPIFDONE GPIF Operation Complete 14 B4 GPIFWF GPIF Waveform