?? kernel.doc
字號:
The 8052 Real-Time Multi-Tasking Executive(0) INTRODUCTION An interrupt-driven multi-processing architecture has been designed for theIntel 8051-family of processors, complete with a small library of routines toimplement its basic operations. Interrupts are generally reserved forprocess-switching and are dynamically enabled or disabled by the routines inthis package. Initially, the only process running is "main". When the 8051-processorstarts up from reset, a short initialization sequence will initialize themultiprocessing architecture and then send control to "main", which it isassumed the programmer will define (the same as in C). New processes are created by using "Spawn", which has the effect of callingthe process, but also initializing a new stack segment for that process. Thenew process will continue until either it returns, or until it calls "Pause".A "Pause" will stop it, and freeze its stack. It will remain frozen until thecorresponding "Resume" is called, at which point it resumes right at where itleft off AS IF NOTHING HAPPENED IN BETWEEN. It is assumed that each interrupt active will call its own "Resume".This provides a way to have processes go into the background and wait for ahardware interrupt while other processes can resume.(1) ARCHITECTURE Each process "Spawn"-ed will have its own segment on the 8051 stack, which itcan use as its calling stack. Generally, the global stack will occupy registers128 to 255 in the current version of the library, and the address 128 is set tobe the base address of the "main" process. It is up to the programmer to define the stack segments used for eachprocess. Further, there is no error-checking for overlapping stack segments,so the programmer is responsible for assuring that large enough stack segmentsare allocated to each process to prevent conflicts. The library, though it contains code for interrupt handlers, is notcompletely self-contained. The programmer must make modifications to theinterrupt handlers pushing and popping any registers that two or more processesmake concurrent use of. If the programmer is using more than one prioritylevel of interrupts, then at the very least, the registers R0, R1 should besaved. It is also assumed that the register bank is permanently switched tobank 0. The key to this multi-processing model is the Priority Stack. Initiallyempty, each time a Spawn or Resume takes effect it will save the currentstack pointer in order to allow the stack pointer for the new process to beloaded. When this new process either returns or Pauses, the old stack pointeris popped off the stack and is restored as the current stack pointer. This allows stack segments to be switched very quickly and in a way that isconsistent with the priority structure of the 8051 interrupts, so thatprocesses Resumed with higher priority interrupts can preempt processescurrently running. There will generally be registers for each interrupt source used to savestack pointers on Pauses and Resumes. In addition, there will be more registersto effectively enable software interrupts. This means that every processcurrently active will have its stack pointer saved either on the PriorityStack, in a stack pointer register, or will be currently running in theforeground with the current stack pointer. This library provides the following registers for saving stack pointers: SP_IE0, SP_IE1: For external interrupts 0, and 1. SP_TF0, SP_TF1, SP_TF2: For timer 0, 1, and 2 overflow interrupts. SP_RI, SP_TI: For serial receive and transmit interrupts. SP_EXF2: For the timer 2 external capture interrupt. SP_SW0, SP_SW1, SP_SW2, SP_SW3: For "software interrupts" 0, 1, 2, and 3.The first 8 are tied to the hardware interrupts, so that for instance, whenexternal interrupt 0 is active, its interrupt-handler will call Resume withregister SP_IE0.(2) INITIALIZATION Initialization consists of the following actions: (1) The Priority Stack is cleared. (2) The first stack segment, for main, is set up and the calling address for "_Die" is pushed onto it. Thus when main returns, it will jump to the routine _Die, which is an infinite loop. (3) Just under this stack, the calling address Exit will be inserted. This provides a convenient place to initialize unused stack pointer registers.(3) SPAWNING A NEW PROCESS A new process is Spawned by loading its address into the DPTR register,and the base address of its stack segment (which is up to the programmerto provide) in register R0 and then calling Spawn. Spawn will then performthe following actions: (1) Push the current stack pointer onto the Priority Stack. (2) Set the stack pointer to R0 (3) Initialize the stack segment by pushing Exit onto it. (4) Jump to the address indicated by DPTR to begin the process.By pushing the routine Exit onto the bottom of the stack, this providesa clean way for the process to finish. For when the process returns, theroutine Exit will be called, which will reload the current stack pointer bypopping the Priority Stack and thus effectively carrying out a return thateliminates the current process. Spawning a new process that returns without ever calling "Pause" willtherefore be the same as just calling that process and executing a normalreturn.(4) SWITCHING PROCESSSES WITH Pause AND Resume The routines Pause and Resume are called after loading register R0 withthe address of the stack pointer register that will be used to load or savethe stack pointer. Pause carries out the following actions: (1) The current stack pointer is saved in the location indicated by R0. (2) An address is popped off the Priority Stack into the current stack pointer.Resume carries out the currespondingly opposite actions: (1) The current stack pointer is pushed onto the Priority Stack. (2) The current stack pointer is loaded with the value saved in the location indicated by register R0. This location is "cleared" by setting it to the portion of the global stack just under the "main" stack segment, where Exit is located.A Resume will thus reactivate the process frozen by the last call to thecorresponding Pause at exactly the place this Pause was called. Both of these routines are, what is known as, critical regions. Under noconditions can they be interrupted, because to do so would destroy the integrityof the Priority Stack architecture. Therefore, interrupts would need to betemporarily turned off in these routines if there is than one interrupt levelin your application.(5) EXAMPLE Suppose we want to echo the keys pressed on a keyboard or keypad toa screen, while simultaneously listening on the serial communications linefor new commands. Suppose that the keypad or keyboard is flagged using theexternal 0 interrupt. We would have a process, Echo, to carry out the echoingaction and a process, Interpreter, for reading and interpreting commandsobtained from the communications line. Then main could probably be written as follows:main: ... INITIALIZE INTERRUPTS AND REGISTERS ... ;;; Spawn the "Echo" routine, giving it the stack segment 90 to a0 (hex). mov R0, #90h mov DPTR, #Echo call Spawn;;; Spawn the "Interpreter" routine, giving it the stack segment a0 to b0 (hex). mov R0, #0a0h mov DPTR, #Interpreter call Spawn;;; Kill the main process ... it's no longer needed.retThe Echo process will repeatedly obtain a key and then display it. Itmight be written as follows:Echo: call GetKey call DisplayKeyjmp EchoGetKey will actually carry out the keyboard entry routine. It will pauseuntil the keyboard has been flagged, and then read the key pressed and return:GetKey: mov R0, #SP_IE0 call Pause ;;; Pause on external interrupt 0. ... READ THE KEY ...retThe Interpreter program will read commands from the serial line and theninterpret and carry them out. It, too, will be an infinite loop:Interpreter: call Receive call ExecuteretReceive will wait for the serial line to flag a reception and then read thecommand received:Receive: mov R0, #SP_RI call Pause ;;; Pause on serial receive interrupt. ... GET THE COMMAND ...ret This illustrates how the programmer can write routines to carry out morethan one action at a time asynchronously without having to destroy theintegrity of each process by breaking them up and merging them together intoone large Finite State Machine as is often done in these kinds of applications.Consequently, modularity is greatly enhanced.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -