Keil C51 in the processing on the stack pointer

Keil C is very good C51 compiler, probably the best C51 compiler, providing a variety of optimization models, optimization variables and addresses arrangements done very well. This is one of the benefits of writing code in C language, if written in assembly, have to charge a big fan of each variable effort to arrange physical memory address, the variables have to always remember that the newly added memory unit which addresses are already allocated, those who can not occupy the unit has been assigned, in order to avoid conflicts and overlapping memory overflow. I have been very trust Keil C51 compiler the result, in my mind, it allocated memory is perfect, do not report any warning and error codes as long as it is used when compiling code to run when the phenomenon can not be a memory conflict or overflow.
But, what happened today prove me wrong.
There are codes of products on hand, a large amount of code. Programs run up effect is not good, and therefore intends to look at code optimization. The larger the amount of codes, where usually the more optimized. 8051, the access to the chip inside the data area (0 ~ 7FH) is the fastest memory, direct access, an instruction can read and write, and idata region (80H ~ FFH) memory area, though still, but the address allocation coincides with the special register SFR, only an indirect address access, read and write to two instructions, slower points, and external memory xdata area (0 ~ 7FFFH) must be used to access the pointer DPTR, speed is the slowest. Obviously, the principle of optimization is to try to read and write frequently variable priority in the data area, and then idata area, and finally xdata area.
When I finished variable manual optimization, the compiler mode is set to SMALL, C51 compiler automatically so that I do not have to manually specify the storage area of variable data into priority areas, out of effective range of addresses, it will complain, so I can rest assured. After pressing the button rebuild all, compiler hints:
Program Size: Data = 236.2 XDATA = 19321 = 43372 code
"ipphone_main" - 0 Error (S), 0Warning (S).
The compiler hints data area includes a idata included, according to past experience, data area 256 byte, the program was used 236.2, leaving 19, no overflow, while xdata have 32k, only use now the 19k, far from overflow, compile the results of all normal.
After the code programmed into the chip run, an unexpected result, the phenomenon, from about 1 second after the power-on automatic reboot, restart and 1 second, very regular restart.
I have no doubt that is the reason the compiler was first thought was suspected to be the watchdog, after the power-on code open watchdog, some subroutine code execution time may be too long, watchdog reset, so where there is doubt feed the dog inserted into the code, recompile and test again, still automatically restart. So they simply put the watchdog's code comments, do not use the watchdog, thinking that this time it is no problem, unexpected results, or restart.
I carefully thought for a moment, not many reasons can cause the restart of 8051, one caused by the watchdog restart, this can be ruled out; the second is some 8051 to support restart command, I use this on hand, while supporting, but I have not used that command, this can also be ruled out; Third, 8051 is strong interference, the fetch PC register contents changed into 0, then on the restart, this can also be ruled out, because if there is a strong site interference will not restart before the fishes optimization.
Because thought out what is the reason, began to toss, to optimize the recovery of one variable to optimize the recovery of non-state, every recovery step to make another test. When recovery finally found a 16-byte array normal procedure, carefully looked at, and that the array is defined when the program xdata area is completely normal, defined in idata area when the program is reset, although the strange thing is, idata zone defined when the compiler does not report memory overflow. Track assembly instructions have not found an exception, regardless of the definition for array allocation in idata or xdata, the compiler proof of address are indeed valid address, does not overflow, the compiler of the arrangement is still correct.
Although not found the root cause, but the problem since it is present in the memory, I decided to see if the array is specified memory allocation when idata type. Keil C51 compiled M51 will output a file, the file contains a lot of memory allocation information, very detailed, including the compiler which variables are assigned to which memory address, the number of bytes occupied, what variables are local, can be repeated use ...... this document M51 has a detailed list.
Assign an address from the list of variables to see all the way down, all right, but also the side watching stunning compiler allocates a variable arrangement very accurate, but when you see the final arrangements for a stack pointer, finally found the problem, and it is so arrangements:

  the TYPE LENGTH the RELOCATION BASE SEGMENT NAME
  ----------------------------------------- -------------------------------------------------- ---
  IDATA 0080H 0034H UNIT _IDATA_GROUP_
  IDATA 00B4H 0022H UNIT? ID? IPPHONE_MAIN
  IDATA 00D6H 001Fh UNIT? ID? DNS_NICRCV? IPPHONE_DNS
  IDATA 00F5H 0004H UNIT? ID? the DISP
  IDATA 00F9H 0001H UNIT? STACK
This marked with section STACK is a stack allocation, the above data shows, SP stack pointer scheduled F9H this address, stack space is a byte! On the surface there is no overflow, but I use the program in the interrupt service, enter the interrupt service, you need at least eight bytes of stack space (save R0 ~ R7 register) to protect the site, 8051 using the incremental push design , the stack pointer is often arranged in the back portion of the available memory space, a push each byte, SP pointer is incremented by one up, into the interrupt service, push at least 8 bytes, F9H + 8, exceeds FFH, the stack pointer can not exceed FFH, that is a stack overflow! So this is the cause of the restart of the program constantly, not a variable memory overflow, but a stack overflow!
And when I put that array type is specified as xdata because the array is no longer occupied idata zone, then all of a sudden IDATA more than 16 bytes of free space, M51 after recompilation this arrangement:
  IDATA 0080H 0024H UNIT _IDATA_GROUP_
  IDATA 00A4H UNIT 0022H? ID? IPPHONE_MAIN
  IDATA 00C6H A 001Fh UNIT? ID? DNS_NICRCV? IPPHONE_DNS
  IDATA 00E5H 0004H UNIT? ID? the DISP
  IDATA 00E9H 0001H UNIT? STACK
From this set of data,, SP pointer arranged in E9H to this address, the stack space FFH-E9H + 1 = 23 bytes have been enough for the program, so the program runs properly.
Several adjustments variable type of compiling results show, C51 for the size of stack space requirements without calculation, any code just by only one byte stack space needs to allocate (in my eyes it seems that this is obviously a mess, slightly complicated point subroutine call is impossible as long as one byte can be done on-site protection), since the stack can only be allocated in the data area and idata area, so when a program for optimization data area taking up too much, although the compiler can compile successfully, but often the final surface SP stack pointer is allocated in the data area, it is easy to cause a stack overflow space is not enough. For insurance purposes, the best guarantee of SP value after compiling them before F0H, as there are at least 16 bytes of stack space, in order to ensure maximum program does not run fly.
It looks not too sure Keil C51, after compiling finished, have a look at M51 in order to ensure the quality of the program, do not know the count Keil C51 of the bug.

 

Forwarded From: http://bbs.21ic.com/icview-147240-1-1.html

 

notes:

1, compile the results is static, not dynamic analysis process (interrupt, dynamic memory allocation, function calls, etc.).

2, interrupt push-site protection needs, needs some stack space.

Guess you like

Origin www.cnblogs.com/WayneKhouTech/p/12045710.html