![]() |
|
| << Previous | Index | Next >> | |
| | |
RabbitSys is an operating system in the sense that it provides system-level services with a reliable interface. RabbitSys supports two basic tasking models: cooperative multitasking and preemptive multitasking. In addition, RabbitSys provides the ability to hook in a tasker.
This chapter briefly describes the support for cooperative and preemptive multitasking. Most of the chapter is used to explain how to hook in a tasker.
6.1 Cooperative Multitasking
There are no changes to the application when using the Dynamic C costate and cofunction constructs in the RabbitSys execution environment. This holds true unless you have partially disabled the system tick function, in which case, you will have to call
_sys_tickexplicitly in your application.The system tick function takes one parameter. Passing in zero partially disables the system tick, meaning that it will only hit the primary watchdog and will not run RabbitSys components. This can be useful if you want RabbitSys out of the way when your application is running correctly. Of course, RabbitSys will be available over the Internet if your application should fail. If you pass anything other than zero to
_sys_tickboth the primary and secondary watchdogs will be hit and the RabbitSys components will run.You can also partially disable the system tick through the Console command.
setup tick 06.2 Preemptive Multitasking
There are no code changes that must be made in the application when using the Dynamic C µC/OS-II module in the RabbitSys execution environment, unless you have defined stacks that are too small for the RabbitSys TCP/IP stack. A safe stack size is 4K.
Slice statements are not compatible with the use of RabbitSys.
6.3 Hooking a Tasker to the Periodic Interrupt
In addition to providing tasking support as described above, RabbitSys provides services to enable the use of your own tasker. Using the same method employed to provide services to the real-time operating system µC/OS-II, any tasker can be run on top of RabbitSys. This section describes the system services provided to the tasker and the code changes that need to be made to the tasker to set up everything.
RabbitSys provides the ability for the tasks running under the tasker to keep track of the interrupt nesting level, as well as calling the tasker's tick function on each periodic interrupt.
The function _sys_init_userosdata() must be called from the tasker to hook itself into RabbitSys.
_sys_init_userosdata( &bios_intnesting, bios_intexit,
sys_useros_tick);The first parameter, the address of
bios_intnesting, is a global interrupt nesting counter provided in the Dynamic C libraries specifically for tracking the interrupt nesting level. It is defined in the Virtual Driver interface library for RabbitSys,sysvdriver.lib. This global counter is incremented and decremented in ISRs that must be tasking aware. How do you know if your ISR must be tasking aware? If other interrupts can occur before an ISR has completed, then the ISR must be tasking aware. Also, an ISR must also be tasking aware even if it does not reenable interrupts if it signals a task to the ready state.The second parameter,
bios_intexit, is a pointer to the function that will be called when an interrupt occurs; it is called when a task must be switched to at the end of an ISR.bios_intexitis defined insysvdriver.liband must be modified to satisfy the requirements of your tasker. Below is the code frombios_intexitthat would run if the Dynamic C µC/OS-II module was active. We will use it as a template for explaining what needs to happen in your tasker-specific code.#ifdef MCOS
ld IX,(OSTCBCur) ; task being switched out
bool HL
ld L,H
add HL,SP
ld (IX+0),HLcall OSTaskSwHookld A,(OSPrioHighRdy) ; OSPrioCur = OSPrioHighRdy
ld (OSPrioCur),A
ld HL,(OSTCBHighRdy) ; task being switched in (preempted task)
ld (OSTCBCur),HLld HL,(HL+os_tcb+OSTCBStkSeg) ; Get STACKSEG of task to resume
ld A,L
ld HL,(OSTCBHighRdy) ; Get stack pointer of task to resume
ld HL,(HL+0)ex DE,HL
ld B,0
ld C,A
push BC
push DE
call _sys_stack_switch
add SP,4
#endifTypically, code that interacts with interrupts is written in assembly for speed. The above code is preparing to call the RabbitSys function
_sys_stack_switch. This system call expects a segmented address in the form XX:NYYY, where N is a logical address in the stack segment, and the associated physical address is in User space. If the logical address is not of this form an error will be generated.The last parameter of _sys_init_userosdata is
sys_useros_tick, a pointer to a user-defined tick function. RabbitSys will call this function at every occurrence of the periodic interrupt so that your tasker has a sense of time passing and can perform preemptive multitasking.
| RabbitSys | << Previous | Index | Next>> | rabbit.com |