Stack pointer processing in Keil C51

Publisher:EternalSmileLatest update time:2016-09-25 Source: eefocusKeywords:Keil Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
Keil C is a very good C51 compiler, probably the best C51 compiler, providing various optimization modes, and doing a very good job of optimizing variables and arranging addresses. This is one of the benefits of writing code in C language. If you write in assembly language, you have to spend a lot of time to arrange the physical memory addresses for each variable, and you have to always remember which memory units of which addresses have been allocated. Newly added variables cannot occupy those allocated units to avoid memory overlap conflicts and overflows. I have always trusted the compilation results of Keil C51. In my impression, its memory allocation is perfect. As long as the code does not report any warnings and errors when it is compiled with it, there will be no memory conflicts or overflows when the code is running.
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.
Keywords:Keil Reference address:Stack pointer processing in 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

51 MCU C language learning notes 8: MCU C51 programming specifications
I found this single-chip C51 programming specification on the Internet and found it very useful. I decided to use it when I write C51 programs myself in the future.   1 Single-chip C51 programming specification - Preface  In order to improve the quality and maintainability of the source program, and ultimately i
[Microcontroller]
C51 key recognition, waiting for release
#include reg51.h unsigned char val; unsigned char i,j,k; sbit k1=P3^4; void delayms(int ms) // 1ms {  unsigned char i,j;  for(;ms 0;ms--)   for(i=6;i 0;i--)    for(j=82;j 0;j--); } void main() {  val=0xff;  while(1)  {   if(k1==0)   {    delayms(10);    if(k1==0)    {     P0=val;     val--;    }    while(k1==0); //Wai
[Microcontroller]
KEIL/MDK generates BIN files
Generated using relative paths, no modification required $KARMARMCCbinfromelf.exe --bin --output=@L.bin !L  After compiling, you can see the following in the Build Out box:  After Build - User command #1: D:Program FilesMDK516ARMARMCCbinfromelf.exe --bin --output=test1.bin .objtest1.axf After the above operation,
[Microcontroller]
STM32 transplantation based on keil contiki system
1. File status of all codes Second, the file inclusion situation in keil 3. Modification of source files 1. Contiki-2.5 (based on this version of the kernel), modify the function in the clock.c file under the cpu/arm/stm32f103 folder void clock_init() { if (SysTick_Config(SystemCoreClock /CLOCK_SECOND))  {     
[Microcontroller]
How to realize communication between C51 microcontroller and PLC
1. HMI (Human Machine Interface) is increasingly used in industrial automation systems and equipment due to its small size, high performance, and strong real-time characteristics. It has different displays such as letters, Chinese characters, graphics and pictures, and the interface is simple and friendly. Equipped
[Microcontroller]
How to create 51 microcontroller KEIL project steps
1. What is Keil software Keil software is an integrated development environment (IDE) specially designed for embedded system development. It is commonly used as programming software for 51 and STM32 microcontroller software development. Keil programming software not only supports a variety of tools and extension progr
[Microcontroller]
How to create 51 microcontroller KEIL project steps
Warning error in Keil: WARNING L15
I encountered this problem when debugging today. I didn't pay attention to these warning errors before. Now it seems that I should strive to achieve: 0 errors, 0 warnings. The same serial port printing function was called both in the interrupt and outside the interrupt. The above alarm has been issued, but I didn't
[Microcontroller]
Common Problems of C51 Microcontroller in Electronic Circuit Design
I have used 51 MCUs such as AT89C2051, AT89C51, AT89C52, etc. in my work. Later, I used 51 MCUs from Taiwan Xinmao, Winbond and other manufacturers. I encountered many problems in practice, which were not in the books. I remember that the knowledge in the books only had one page of illustrations, which was the timin
[Microcontroller]
Common Problems of C51 Microcontroller in Electronic Circuit Design
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号