But what happened today proved me wrong.
I have a product code on hand, and the code volume is very large. The program does not run well, so I plan to optimize the code. The larger the code volume, the more areas that can be optimized. For 8051, the memory access speed of the data area (0~7FH) inside the chip is the fastest. Direct access can be read and written with one instruction. Although the idata area (80H~FFH) is still a memory area, it can only be accessed indirectly due to the overlap of the address allocation with the special register SFR. It can only be read and written with two instructions, and the speed is slightly slower. The external memory xdata area (0~7FFFH) must be accessed using the DPTR pointer, and the speed is the slowest. Obviously, the principle of optimization is to prioritize the frequently read and written variables in the data area, then the idata area, and finally the xdata area.
After I finished the manual optimization of the variables, I set the compilation mode to SMALL, so that the C51 compiler will automatically prioritize the variables that I did not manually specify the storage area into the data area. If it exceeds the valid address range, it will report an error, so I can rest assured. After pressing the rebuild all button, the compiler prompts:
Program Size: data=236.2 xdata=19321 code=43372
"ipphone_main" - 0 Error(s), 0Warning(s).
The data area prompted by the compiler includes idata. According to past experience, the data area has 256 bytes, and the program only uses 236.2 bytes, leaving 19 bytes, without overflow. The xdata area has 32k, and only 19k is used now, far from overflow. The compilation results are all normal. After
burning the code into the chip and running it, the result is unexpected. From the phenomenon, it automatically restarts about 1 second after power-on, and restarts again after 1 second after restarting. It restarts very regularly.
I did not suspect that it was the compiler. At that time, the first thought was to suspect that it was the watchdog. The watchdog was turned on in the code after power-on. Maybe some subroutine code execution time was too long, and the watchdog was reset. So I inserted the dog feeding code in the suspected place, recompiled and tested it again, and it still restarted automatically. So I simply commented out the watchdog code and didn't use the watchdog, thinking that this time there would be no problem, but surprisingly, it still restarted.
I thought about it carefully, and there are not many reasons that can cause the 8051 to restart. First, the restart caused by the watchdog can be ruled out; second, some 8051s support the restart instruction. Although the one I use supports it, I have never used that instruction, which can also be ruled out; third, the 8051 is strongly interfered with, and the content of the instruction register PC is changed to 0, so it restarts. This can also be ruled out, because if there is strong interference on site, it should restart before optimization.
Since I couldn't figure out what the reason was, I started to toss and turn, restoring the optimized variables one by one to the unoptimized state, and retesting each step of restoration. Finally, when restoring a 16-byte array, I found that the program was normal. After a careful look, the program was completely normal when the array was defined in the xdata area, and the program was reset when it was defined in the idata area. Although it is strange that the compiler did not report a memory overflow when it was defined in the idata area. Tracing the assembly instructions did not find any abnormalities. Regardless of whether it was defined in idata or xdata, the addresses assigned by the compiler to the array proved to be valid addresses. There was indeed no overflow, and the compiler's arrangement was correct.
Although the root cause has not been found, since the problem occurred in the memory, I decided to check the memory allocation when the array was specified as idata type. Keil C51 will output an M51 file during compilation. The file contains a lot of memory allocation information, which is very detailed, including which variable is assigned to which memory address by the compiler, how many bytes it occupies, which variables are local variables, and which variables can be reused... This M51 file has a detailed list.
0001H UNIT ?STACK The segment marked with STACK is the stack allocation. The above data shows that the SP stack pointer
is arranged at the address F9H and the stack space is 1 byte
! On the surface, there is no overflow, but my program uses interrupt service. When entering the interrupt service, at least 8 bytes of stack space (to save R0~R7 registers) are required to protect the scene. 8051 uses an incremental stack design. The stack pointer is often arranged in the available part of the memory space at the back. Every time a byte is pushed, the SP pointer is increased by 1. When entering the interrupt service, at least 8 bytes are pushed, F9H+8, which exceeds FFH. The stack pointer cannot exceed FFH, which means the stack overflows! It turns out that this is the reason why the program keeps restarting. It is not the variable memory overflow, but the stack overflow! When I specified the array as xdata type, because the array no longer occupies the idata area, IDATA suddenly has 16 bytes of available space. The recompiled M51 is arranged like this: IDATA 0080H 0024H UNIT _IDATA_GROUP_ IDATA 00A4H 0022H UNIT ?ID?IPPHONE_MAIN
IDATA 00C6H 001FH UNIT ?ID?DNS_NICRCV?IPPHONE_DNS
IDATA 00E5H 0004H UNIT ?ID?DISP
IDATA 00E9H 0001H UNIT ?STACK
From this set of data, the SP pointer is arranged at the address E9H, and the stack space has FFH-E9H+1=23 bytes, which is enough for the program, so the program runs normally. The
compilation results of adjusting the variable type many times show that C51 does not calculate the required size of the stack space, and any code is only allocated according to the requirement of only 1 byte of stack space (in my opinion, this is obviously nonsense, and it is impossible for a slightly more complex subroutine call to complete the field protection with only 1 byte). Since the stack can only be allocated in the data area and the idata area, when a program occupies too much data area for optimization, although the compiler can compile successfully, the SP stack pointer is often allocated at the end of the data area, which can easily cause the stack space to overflow due to insufficient space. To be on the safe side, it is best to ensure that the compiled SP value is arranged before F0H, so that there is at least 16 bytes of stack space to maximize the guarantee that the program will not run away.
It seems that we cannot trust Keil C51 too much. After compiling, we have to check M51 to ensure the quality of the program. I don’t know if this is a bug of Keil C51.
Previous article:51 Common Programs
Next article:A 51 single chip microcomputer realizes a digital clock (1602 display)
Recommended ReadingLatest update time:2024-11-16 21:26
- Popular Resources
- Popular amplifiers
- 西门子S7-12001500 PLC SCL语言编程从入门到精通 (北岛李工)
- Siemens Motion Control Technology and Engineering Applications (Tongxue, edited by Wu Xiaojun)
- How to read electrical control circuit diagrams (Classic best-selling books on electronics and electrical engineering) (Zheng Fengyi)
- MCU C language programming and Proteus simulation technology (Xu Aijun)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- There are Bluetooth modules and Wi-Fi modules on the PCB board.
- Thirty-three MCU (microcontroller) input/output interface circuits
- EEWORLD University Hall----Using JTAG with UCD3138
- AltiumDesigner integrated library design based on Access database
- EEWORLD University Hall----Live Replay: TE explains the design trends of smart antennas and sensor application cases in the Internet of Things
- Solution to EPLAN software freeze
- PDIUSBD12 Send mode command, soft connection does not work
- Can the same timer realize two independent PWM pulses?
- Today's live broadcast: ADI inertial MEMS applications
- .DSN file is garbled when opened.