uC/OS-II transplantation on 51 single chip microcomputer 2

Publisher:科技创造者Latest update time:2016-03-25 Source: eefocusKeywords:uCOS-II Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
File name: YY.C

#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.

Keywords:uCOS-II Reference address:uC/OS-II transplantation on 51 single chip microcomputer 2

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

51 MCU 232 serial port implementation
Requirements Fosc is 6MHz, timer T1 is working mode 2, serial port working mode 1, baud rate is 4800. 1. Calculate the initial value of the time constant of timer T1 according to the baud rate. 2. Write a sending program for machine A, which works in query or interrupt mode and transmits the sixteen bytes from 30H to
[Microcontroller]
Motor speed measurement control program based on 8051 single chip microcomputer
With the single-chip microcomputer 8031 ​​as the core, the 8279 chip is used to realize key input and the digital tube is used to display the measured speed. The input voltage analog quantity is converted into digital quantity by ADC0809 (the relevant interface has been connected inside the experimental box) to cont
[Microcontroller]
Bicycle odometer based on 51 single chip microcomputer
1. Hardware Solution The hardware of this design mainly consists of 51 single-chip microcomputer + minimum system + LCD1602 liquid crystal display module + Hall speed measurement module + motor module + potentiometer speed control module + buzzer module + LED indicator module + button module + clock module + AT24C02 s
[Microcontroller]
Bicycle odometer based on 51 single chip microcomputer
Temperature collection and wireless transmission based on 8051 single chip microcomputer
Abstract: In order to remotely monitor real-time temperature data, the characteristics of the temperature sensor DS18B20 are used to form a real-time temperature detection system with the AT89C51 single-chip microcomputer, and the temperature is displayed through an LED digital tube. The characteristics of the wirel
[Microcontroller]
Temperature collection and wireless transmission based on 8051 single chip microcomputer
Design of Wireless ECG Monitoring System Based on C8051 Single Chip Microcomputer
1 Introduction With the rapid development of economy and the continuous improvement of people's living standards, health has become the focus of people's attention. Heart disease is a major killer that endangers human health. Its accidental and sudden characteristics make ECG monitoring system have importan
[Microcontroller]
How to use microcontroller? 51What are the examples of C language programming for single chip microcomputer?
How to use the microcontroller? We need to know where the microcontroller is used? The microcontroller is the core device of many electronic products. It is a chip with certain logical judgment and event processing capabilities. Different programs can be programmed on the microcontroller to achieve different functions
[Microcontroller]
51 MCU LED bit definition
1. Bit definition principle Definition method: sbit bit name = special function register ^ position; sbit LED1 = P2^0; The symbol "^" is preceded by the name of the special function register, and the number behind it defines the position of the addressable bit in the special function register. The value must be 0~7 p2
[Microcontroller]
51 MCU LED bit definition
Temperature Control System Based on PID Algorithm and 51 Single Chip Microcomputer
0 Introduction Temperature control technology plays a very important role in both industrial production and daily life. In industries such as metallurgy, petroleum, chemical industry, electric power and modern agriculture, temperature is one of the most important and common thermal parameters. In ordinary households,
[Microcontroller]
Temperature Control System Based on PID Algorithm and 51 Single Chip Microcomputer
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号