In embedded applications, the main reason for using RTOS is to improve system reliability, followed by improving development efficiency and shortening the development cycle. μC/OS-II is a priority-based preemptive real-time kernel that supports 56 user tasks. 90% of the code is written in standard ANSI C language. The program is highly readable, has good portability, and the code can be solidified and cut. , very flexible. C8051F is a microcontroller compatible with the 51 series produced by the American Cygnal Company. The execution time of 70% of the instructions in the pipeline instruction structure is 1 or 2 system clock cycles. When the clock frequency is 25MHz, the speed can reach 25MIPS, which is a good system-on-chip.
1 Development tools and operating environment
To realize the transplantation of μC/OS-II, the C compiler used needs to support hybrid programming. KEIL C51 can program numerous 8051 derivatives. We chose the KEIL7.02 integrated development environment, and the simulation board is based on the C8051F015 chip.
2 Files that need to be modified during migration
There are three main files related to the CPU, namely the assembly file OS_CPU_A.ASM, the C language file OS_CPU_C.C and the header file OS_CPU.H.
2.1 OS_CPU.H file
The OS_CPU.H file defines data types and basic information related to hardware. The changes are as follows:
In C8051F, the stack operates on a byte basis, so the data type OS_STK is declared as 8-bit. The direction increases from low address to high address, so OS_STK_GROWTH is set to 0. μC/OS-II should turn off interrupts before entering the critical code area of the system, and then turn them on after exiting the critical area to protect core data from being damaged by other tasks or interrupts in a multi-tasking environment. Turning interrupts on and off can be achieved by setting the interrupt mask bit in SFR. When turning off interrupts, first save the contents of IE in the global variable IE_ SHADOW, and then turn off the interrupt; when exiting the critical section, restore the value of IE_SHADOW.
OS_TASK_SW() is used to implement task switching. The stack initialization of the ready task should simulate what it will look like after an interrupt occurs, and the registers in the stack should be set in the order they are pushed into the stack. The OS_TASK_SW() function simulates an interrupt process and performs task switching when the interrupt returns. Since C8051F015 does not have a soft interrupt, the macro OS_TASK_SW() is directly defined as the function OSCtxSw().
2.2 OS_CPU_A.ASM file
The compiler treats each file as a module. The compiled module is named after the main name, which is called the compiled module name and is declared with NAME. Therefore, NAME OS_CPU_A should be declared in the file header.
A function has a program part and a local variable part, which are placed in separate sections. In large mode, what is the fixed format of section name declaration? PR? Function name? Module name SEGMENT CODE. Therefore, OSStartHighRdy(), OSCtxSw(), OSIntCtxSw() and OSTickISR() need to be declared one by one in the above format. like? PR? OSStartHighRdy? OS_CPU_A SEGMENT CODE, the functions implemented by this module need to be declared with PUBLIC, such as PUBLIC OSStartHighRdy, etc.
C51 converts all defined data identifiers into uppercase characters, and renames functions based on whether there is register parameter transfer and whether the function is reentrant, such as: void OSIntEnter (void) Replace the name of the reentrant function OSIntEnter with _? OSIntEnter. These rules can be seen in the compiled LST file. The five global variables declared and referenced in the program are OSTCBCur, OSTCBHighRdy, OSRunning, OSPrioCur, OSPrioHighRdy, and the declaration format is EXTRN IDATA (OSTCBCur), etc. Call four external subroutines OSTaskSwHook(), OSIntEnter(), OSIntExit(), OSTimeTick(), the fixed format is: EXTRN CODE (_? OSTaskSwHook), etc.
Since the stack pointer of C8051F is only 8 bits and can only point to 256 bytes of the internal data area, the stack of the currently running task is in the IDATA area, the stack size is 40H (64 bytes), and the starting point of the stack is determined by KEIL. The SP starting point assigned by KEIL can be obtained through the label. The code is as follows:
? STACK SEGMENT IDATA
RSEG? STACK
OSStack:
DS40H
OSStkStart IDATA OSStack-1
To simplify the subroutine, the push and pop macros are specially defined. The order of pushing onto the stack is PSW, ACC, B, DPL, DPH, R0~R7, and the order of popping from the stack is opposite to that of pushing into the stack.
PUSHALL MACRO
IRP REG, "SW, ACC, B, DPL, DPH, 0, 1, 2, 3, 4, 5, 6, 7"
PUSH REG
ENDM
POPALL MACRO
IRP REG, "7, 6, 5, 4, 3, 2, 1, 0, DPH, DPL, B, ACC, PSW"
POP REG
ENDM
For modifications to specific functions, see the online supplementary version of this journal (http://www.dpj.com.cn).
2.3 OS_CPU_C.C file
To transplant μC/OS-II, six functions need to be defined in OS_CPU_C.C, but in fact only one function, OSTaskStkInit(), needs to be defined. This function is used to initialize the task's stack. The initial state stack only needs to be initialized? C_XBP (emulation stack pointer), task address and stack length. Since there is only the INC DPTR instruction, the lowest address of the stack is returned, and the length of the stack is stored at the lowest address, which facilitates task switching in assembly language. The size of the heap can be determined based on the actual situation of the task, and is determined by the value pointed to by the parameter ppdata.
void *OSTaskStkInit (void (*task) (void *pd), void *ppdata,
void *ptos, INT16U opt) reentrant
{
OS_STK *stk;
INT8UHeapSize;
HeapSize=*(INT8U *)ppdata;
opt = opt;
stk = (OS_STK *)ptos+HeapSize+2;
*stk++ = 15;
*stk++ = (INT16U)task & 0xFF;
*stk++ = (INT16U)task 》》 8;
stk = (OS_STK *)ptos+HeapSize+2;
*--stk = (INT16U) (ptos+HeapSize-1) 》》 8;
*--stk = (INT16U) (ptos+HeapSize-1) & 0xFF;
return ((void *)stk);
}
3 Reentrant functions
Because of the stack space limitations of the 51 series, the KEIL compiler does not use the call stack like large systems. Generally, during a C language call, the parameters of the process and the local variables used are pushed onto the stack. In order to improve efficiency, the compiler does not provide such a stack, but provides a compressed stack, and each process is given a space to store local variables. Each variable in the procedure is placed at a fixed location in this space, and when the procedure is called recursively, the variables will be overwritten. The compiler allows functions to be defined as reentrant functions, specified by the reentrant keyword, and reentrant functions can be saved separately. Because these stacks are simulated, reentrant functions are generally larger and slower to run. The simulation stack does not allow passing bit type variables, nor can it define local bit scalars. In porting, it is best to define functions that may be used by multiple tasks as reentrant functions.
Previous article:How to design a control circuit for a shearing machine with AT89C51 microcontroller as the core?
Next article:Design of remote control of household appliances by telephone based on AT89C51 microcontroller and DTMF communication
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Learn ARM development(21)
- Learn ARM development(20)
- Learn ARM development(19)
- Learn ARM development(14)
- Learn ARM development(15)
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Free application: DCM product evaluation samples are waiting for you!
- I want a switching power supply chip model with silk screen printing
- No GD32? Replace STM32 with domestic MM32
- 【CC1352P Review】Summary
- Single TL431 constant current improved circuit
- Wifi6 video explanation
- Looking for: 3.7V lithium battery charging, boost, power, switch, SOP8 chip
- FPGA_100 Days Tour_ROM-based Arbitrary Waveform Generator
- Merry Christmas Eve
- MicroPython upgraded to v1.11