#include
#define MAX_STK_SIZE 64
void TaskStartyya(void *yydata) reentrant;
void TaskStartyyb(void *yydata) reentrant;
void TaskStartyyc(void *yydata) reentrant;
OS_STK TaskStartStkyya[MAX_STK_SIZE+1];//Note: I set the STACK space to 40H in the ASM file, which is 64. Do not exceed the range.
OS_STK TaskStartStkyyb[MAX_STK_SIZE+1];//One more byte for the user stack to store the length
OS_STK TaskStartStkyyc[MAX_STK_SIZE+1];
void main(void)
{
OSInit();
InitTimer0();
InitSerial();
InitSerialBuffer();
OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],2);
OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3);
OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0] ,4);
OSStart();
}
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
clrscr();
PrintStr("\n\t\t************************ *******\n");
PrintStr("\t\t* Hello! The world. *\n");
PrintStr("\t\t************ *******************\n\n\n");
for(;;){
PrintStr("\tAAAAAA111111 is active.\n");
OSTimeDly(OS_TICKS_PER_SEC);
}
}
void TaskStartyyb(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\tBBBBBB333333 is active.\n");
OSTimeDly(3*OS_TICKS_PER_SEC);
}
}
void TaskStartyyc(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\tCCCCCC666666 is active.\n");
OSTimeDly(6*OS_TICKS_PER_SEC);
}
}
Solution to the reentrant problem:
If the reentrant keyword is used in a task function with formal parameters and local variables, reentrant operation will occur. From the content of C51.PDF pages 129-131, we know that in order to reenter the function, formal parameters and local variables must be saved in the stack. Since the 51 hardware stack is too small, KEIL will simulate the stack in the corresponding memory space according to the memory mode (the growth direction is from top to bottom, opposite to the hardware stack). For large-mode compilation, the function return address is saved in the hardware stack, and the formal parameters and local variables are placed in the simulation stack. The stack pointer is ?C_XBP. When XBPSTACK=1, the starting value is initialized to FFFFH+1 in startup.a51. The simulation stack is inefficient, and KEIL recommends that it should not be used as much as possible, but it must be used for reentrant operations. KEIL can mix and match 3 types of simulation stacks (large, medium, and small modes). In order to improve efficiency, it is recommended to use large-mode compilation for 51.
In order to support reentrant operation, the stack structure is redesigned (as shown below). A data structure for saving the simulation stack pointer ?C_XBP and stack content is added. The files that have been changed accordingly are: OS_CPU_A.ASM, OS_CPU_C.C, OS_CPU.H, YY.C. As can be seen from the figure, the simulation stack and the hardware stack saved in the user stack grow in opposite directions, with an idle interval in between. Obviously, the stack detection function of uCOSII is invalid. The preservation and recovery of the hardware stack are detailed in the previous section. The preservation of the simulation stack is the same as that in the 8086 transplantation. The OS only provides stack space and only operates the stack pointer, and does not copy memory, which is relatively efficient.
It is recommended to use a unified fixed-size stack space. Although the original author of uCOSII regards the use of different spaces for different tasks as an advantage, in order to effectively implement task reentry on 51, the author still insists on not using this advantage for 51.
The size of the user stack space can be accurately calculated. User stack space = hardware stack space + simulation stack space. The hardware stack occupies internal RAM, and the internal RAM has high execution efficiency. If the stack space is too large, it will affect the performance of the KEIL compiled program. If the stack space is small, it will cause the system to crash during interrupt nesting and program calls. After comprehensive consideration, I set the hardware stack space size to 64 bytes, and users can set it according to actual conditions. The simulation stack size depends on the type and number of formal parameters and local variables, and can be accurately calculated. Because all user stacks use the same space size, the space size of the task function that occupies the largest space is taken as the simulation stack space size. In this way, the user stack space size is uniquely determined. I defined the user stack space size in the OS_CFG.H file with a macro named MaxStkSize.
The SP of 51 is only 8 bits and cannot be moved freely in the 64K space, so I have to use the clumsy method of copying all the hardware stack contents. 51 is weak to begin with, and this makes its shortcomings more obvious. In fact, there is a price to pay for introducing OS. Generally, OS takes up 10%-20% of the CPU's load capacity. Please weigh the pros and cons and decide. The switching frequency determines the CPU consumption. The higher the frequency, the greater the consumption. When it reaches a certain level, it is time to replace a stronger CPU. I chose a switching frequency of 50Hz, which is neither high nor low. Users can decide according to their needs. In the case where consumption cannot be avoided, I took several measures to improve efficiency: 1. 1. Mix ret and reti to reduce code; 2. IE and SP are not put in and out of the stack, and are solved by other methods; 3. Use the IDATA keyword to declare global variables used in assembly, and change DPTR operation to Ri operation; 4. Design stack structure and simplify algorithm; 5. Let the serial port input and output work in system state, do not occupy task TCB and priority, increase elastic buffer and reduce waiting.
Instructions for hardware simulation of uCOS51 on 51 MCU:
On November 22, 2002, a zyware netizen wrote to inquire about the hardware simulation of uCOS51 on MCU. The specific situation is "Using uCOS51 core and some components on 51, the simulation passed on keilc, but the program ran wildly when connected to the hardware simulation with wave, and there was no problem with the program before wave simulation. I don't know why."
Since my OS program has been tested on KEIL software simulation and hardware, it cannot be the program's fault. The possible reason can only be the hardware simulation software setting problem. I use Medwin software, debug on Insight, and use uCOS51 to compile and test the program, and it still runs wild. Even if the modified startup.a51 is added (see "Instructions for Solidifying uCOS51 on 51 MCU"), it is not normal. I found that Medwin does not seem to compile startup.a51, because it adds the file to the other Files directory instead of the source Files directory, so I guess only the files placed in the source Files directory are compiled. From observation, we know that files with .c and .asm suffixes are placed in this directory and compiled. So I immediately changed startup.a51 to startup.asm and added it to the project compilation. The test result was normal. There is no need to worry about conflicts caused by the startup name change. KEIL will automatically handle the same name segment when linking the target file, and the files in this directory have a higher priority (this is my understanding, the specific principle is not clear, this is just a conclusion based on practice, I hope friends who understand this process can tell me, I will be grateful.).
The specific steps are as follows:
1. Modify startup.a51 according to the article "Instructions for Fixing uCOS51 on 51 MCU" and rename it to startup.asm.
2. Add the five files startup.asm, yy1.c, os_cpu_c.c, ucos_ii.c, and os_cpu_a.asm to the project compilation.
3. Run
Instructions for fixing uCOS51 on 51 MCU:
Recently, we have received many letters from netizens asking about the fixing problem of uCOS51 on 51 MCU. The focus is: Why can OS run normally on KeilC51 simulation, but it cannot work when burned on CPU? In theory, after the program passes the test in software simulation, it is burned on hardware, and hardware debugging should be successful at one time. Many netizens have this experience, but why does it fail when debugging uCOS51? Is operating system debugging very special?
In fact, the problem lies in the introduction of reentrant function. It turns out that KEILC51 software simulation uses 64K external RAM without modifying the startup.a51 file. It simulates all 0000H-FFFFH as readable and writable RAM, while the user's hardware system may not use such a large RAM space, such as only using 8K/16K/32K, etc., or the user maps some address space to other devices, such as 8019AS, etc. Before calling OSTaskCreate, the function defined as reentrant will use FFE0H as the top pointer of the simulation stack, which is not RAM in the user's system, causing the program to run away. For example, on my user board, part of the FE00H-FFFFH space is allocated to 8019AS. If the demo program is compiled and burned directly to 51, it will not run. The solution is to modify the startup.a51 file according to the system RAM configuration and add it to the project compilation, as shown below:
XBPSTACK EQU 1; set to 1 if large reentrant is used.
XBPSTACKTOP EQU 07FFFH+1; set top of stack to highest location+1.
After this modification, it can run normally on a system with 32K external RAM. Users can modify the startup.a51 related parameters according to their actual XRAM configuration and add it to the project for compilation. Ignore the file with the same name in the KEIL/C51/LIB directory. The startup.a51 here has a higher priority, and KEIL will compile the project according to the configuration of this file.
This also explains the question asked by some netizens, "Why is it correct when adding the reentrant keyword in software simulation, but crashes when burning on the chip, and both are normal after removing reentrant?" Since most people rarely use reentrant functions, they often don't understand this detail, so I would like to draw your attention to it.
The reason why uCOS51 cannot work properly may also be due to incorrect settings of the serial port baud rate, OS_TICKS_PER_SEC, TH0, and TL0. The demo program uses a 22.1184MHz crystal, 19200 baud rate, and a switching frequency of 50Hz by default. To this end, 1. Set "TL1=0xFD;TH1=0xFD;" in SERIAL.C to make the baud rate 19200; 2. Set "TH0=0x70;TL0=0x00;" in OS_CPU_C.C and OS_CPU_A.ASM to make the clock tick = 50 times/second; 3. Set OS_TICKS_PER_SEC to 50Hz in OS_CFG.H. Users should modify these parameters accordingly according to actual conditions, otherwise it will not run correctly.
Timer initial value setting:
Timer 0 is used for the clock beat generator
/
} wt[MaxLenWordTable];
} WORDTABLE;
Get word
bit GetWord(unsigned char *ComBuf, WORDTABLE *WordTable)
{
int i=0;
int j=0;
int k=-1;
int StrFlag=0;
int SentenceEndFlag=0;
char ch;
WordTable->Num=0;
WordTable->LeftCurveNum=0;
WordTable->RightCurveNum=0;
ch=ComBuf[0];
while(!SentenceEndFlag&&i if((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>=' A'&&ch<='Z')||(ch=='.')){
if(StrFlag==0){
StrFlag=1;k=k+1;j=0;
if(k>=MaxLenWordTable) return 0;
WordTable->wt[k].Str[j]=ch;
WordTable->Num=k+1;
}
else{
j=j+1;
if(j>=MaxLenWord) return 0;
WordTable->wt [k].Str[j]=ch;
}
}
else if(ch==' '||ch==','||ch=='('||ch==')'||ch== '\0'){
if(ch=='(') WordTable->LeftCurveNum++;
if(ch==')') WordTable->RightCurveNum++;
if(StrFlag==1){
StrFlag=0;j=j+1;
WordTable->wt [k].Str[j]='\0';
WordTable->wt[k].Length=j;
}
if(ch=='\0') SentenceEndFlag=1;
}
else{
return 0;
}
i= i+1;
ch=ComBuf[i];
}
if(i if(WordTable->LeftCurveNum==WordTable->RightCurveNum) return 1;
else return 0;
}
else{
return 0;
}
}
Input echo and command interpretation and execution
void yyshell(void *yydata) reentrant
{
yydata=yydata;
clrscr();
PrintStr("\t\t***********************************************\n");
PrintStr("\t\t* Welcom to use this program *\n");
PrintStr("\t\t* Author:YangYi 20020715 *\n");
PrintStr("\t\t***********************************************\n\n\n");
PrintStr("% ");
while(!ShellEnd){
switch(State){
case StatInputCom:{
if(yygetch(&ch)){
if(ch==13)
{
PrintStr("\n");
ComBuf[i+1]='\0';
if(i+1 ==0) PrintStr("% ");
else
State=StatExeCom;
}
else{
i=i+1;
if((i>=MaxLenComBuf)&&(ch!=8)){
PrintChar(7);
i=MaxLenComBuf -1;
}
else{
if(ch==8){
i=i-2;
if(i<-1) {i=-1;PrintChar(7);}
else{
PrintChar(8);
PrintChar(' ' );
PrintChar(8);
}
}
else{
PrintChar(ch);
ComBuf[i]=ch;
}
}
}
break;
}
else{
//OSTimeDly(10);
break;
}
}
case StatExeCom:{
if(GetWord(ComBuf,&WordTable)==1&&WordTable.Num!=0){
yystrlwr(WordTable.wt[0].Str);
for(tem=0;tem if(yystrcmp(WordTable.wt[0].Str, ComTable[tem])==0) ComMatchFlag=1;
if(ComMatchFlag){
tem--;
switch(tem){
case 0:{DisplayTask(&WordTable);break;}
case 1:{Kill(&WordTable);break; }
case 2:{PingCommand(&WordTable);break;}
case 3:{UDPCommand(&WordTable);break;}
case 4:{CfgHost(&WordTable);break;}
case 5:{CfgMask(&WordTable);break;}
case 6:{CfgGateway(&WordTable);break;}
case 7:{
//ShellEnd=1;
PrintStr("\n\tThis Command is limited!\n\n");
break;
}
case 8:{PrintConfig(&WordTable);break;}
case 9:{clrscr();break;}
case 10:{DisplayHelpMenu( &WordTable);break;}
}
}
else
PrintStr(" Bad command!\n\n");
}
else{
if(WordTable.Num) PrintStr(" Bad command!\n\n");
}
ComMatchFlag=0;
State=StatInputCom;
if(ShellEnd) {PrintStr("\n\n");}
else PrintStr("% ");
i=-1;
break;
}
default:{
//ShellEnd=1;
PrintStr ("System fatal error!\n");
PrintChar(7);PrintChar(7);PrintChar(7);
}
}
}
}
The above is my experience of porting uCOS51. I wrote it down just to help my colleagues who are going to run the operating system on 51 avoid detours and enhance their confidence. I strongly recommend that you use uCOS, a simple and practical operating system, in your own 51 system. Its size should not be a problem, but the performance improvement is significant. I hope this article can be helpful to my friends. Mistakes are inevitable, and I hope readers will correct them.
Previous article:Serial communication between Delphi and 51 single chip microcomputer
Next article:uC/OS-II transplantation on 51 single chip microcomputer
Recommended ReadingLatest update time:2024-11-16 16:52
- Popular Resources
- Popular amplifiers
- MCU C language programming and Proteus simulation technology (Xu Aijun)
- 100 Examples of Microcontroller C Language Applications (with CD-ROM, 3rd Edition) (Wang Huiliang, Wang Dongfeng, Dong Guanqiang)
- Fundamentals and Applications of Single Chip Microcomputers (Edited by Zhang Liguang and Chen Zhongxiao)
- Single chip microcomputer control technology (Li Shuping, Wang Yan, Zhu Yu, Zhang Xiaoyun)
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
- 【Chuanglong TL570x-EVM】Review 01 - Unboxing
- Power Factor Correction
- Ultra-low standby power consumption < 90mW non-auxiliary AC/DC power supply reference design
- 3D Printer Project—STM32F7508-DK Environment Creation (I)
- Looking for the movie download website of "Miracle"!
- mosfet discrete devices
- MSP430 MCU Development Record (21)
- 【PLC based on the Internet of Things】---Purely handmade PLC controller
- stm32 PWM triggers adc delay acquisition problem
- Those wiring skills required for high-frequency circuit design