Implementing the transplantation of μC/OS-II on the development board based on the C8051F015 chip

Publisher:清新微笑Latest update time:2023-08-02 Source: elecfans Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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:

Implementing the transplantation of μC/OS-II on the development board based on the C8051F015 chip

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.


Reference address:Implementing the transplantation of μC/OS-II on the development board based on the C8051F015 chip

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

Latest Microcontroller Articles
  • 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)
    Since development under LINUX is still quite troublesome, is there a more convenient and simple development method under WINDOWS? The answer is yes. Of course, it is not a development tool like ADS, because it ...
  • Learn ARM development(15)
    When using GCC to develop ARM, you will definitely encounter compiler problems. For example, you will encounter various warnings and errors when compiling C code. For example, I encountered several warnings yesterday, so let's take a look at what these warnings are ...
  • Learn ARM development(16)
  • Learn ARM development(17)
  • Learn ARM development(18)
  • Embedded system debugging simulation tool
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号