Real-Time Operating System for AVR Microcontroller v3-0
=======================================================

The RTOS uses one PIN of a port to trigger an interrupt via software. For this
the PIN is configured as output and the pin change interrupt is configured for
this PIN to be activated when the PIN is cleared.

In the main program you need to include the following definitions and code:

1. Define the PIN usinge #define statements, here we use pin 7 of port C.

.equ    RTOS    = 7                     ; Software Interrupt Port for RTOS

#define d_RTOS VPORTC_DIR, RTOS
#define b_RTOS VPORTC_OUT, RTOS
#define f_RTOS VPORTC_INTFLAGS, RTOS
#define c_RTOS PORTC_PIN7CTRL
#define v_RTOS PORTC_PORT_vect

2. Include the following code to jump to the real-time entry routine

        .org    v_RTOS                  ; Software interrupt RTOS
        jmp     rtos_

3. Setup the pin and the pin change interrupt

        sbi     d_RTOS                  ; RT-OS Soft Interrupt
        sbi     b_RTOS                  ; Set Level = High 
        sbi     f_RTOS                  ; Acknowledge any pending interrupt
        ldi     r18, PORT_ISC_LEVEL_gc  ; Level Sense Interrupt
        ori     r18, PORT_PULLUPEN_bm   ; Enable Pull-Up
        sts     c_RTOS, r18             ; Pin Control


Note that the RTOS pin on this port must be the only active pin change interrupt.
The real-time entry routine does only check that it is the RTOS pin but there is no
further processing of other pins from this port. The AVR processor has only one 
dedicated vector for all pins of the same port. 

The interrupt service routine (ISR) is in fact very simple

rtos_:
	sbic	b_RTOS			; Is it an oscall software interrupt
	rjmp	rtos_010		; aaahhh...
	nop
	nop
	nop
	sbi	b_RTOS			; Set the interrupt pin again high
	nop
	nop
	nop
	nop
	sbi	f_RTOS			; Acknowledge Pin Change Interrupt
	ret				; stay in interrupt level0, return to caller

rtos_010:
	ldi	r16, crash_spurious	; 
	jmp	crash			; crashdump (at the moment simple crash)

It checks that the RTOS pin is low and in case this is the case it sets the RTOS
pin high and executes a return instruction. As a result the ISR just returns to 
the program that set the RTOS pin low. 

The RTOS is just a collection of subroutines which use the RTOS pin, which is used
to enter the OS state. Other subroutines may use the RTOS pin as well to avoid that
the execution is interrupted by an interrupt. You could achieve the same by using
CLI and SEI instructions, however these instructions block all interrupts. But we
want to be able to maintain the abilitiy of the level1 interrupt to interrupt the
level0 interrupt level for tasks that may not wait as long as the execution of such
a subroutine takes, e.g. the RTOS sub-routines or the sub-routines malloc() and
free() in the dynamic memory module. Even so the OS and memory sub-routines take
20usec or even less for some very time critical tasks this may be too long. E.g.
the Q-Bus interface requires a reaction time of less than 10usec.

After the sub-routine as set the RTOS pin to low, the ISR will just return to the
instruction after the instruction which set the RTOS pin to low. But as you can
see it uses the ret and not the reti instruction, hence maintains the interrupt
state. 


malloc:
	cbi	b_RTOS		; Trigger software interrupt
	push	r16		; save registers
	push	r17		;;
	push	xl		;;; here we will be already in interrupt
	push	xh		;;; level0 mode
	push	yl
	push	yh
	push	zl
	push	zh
	...			; normal sub-routine execution
	...
	...
	...
	...
	reti			; return to caller and end interrupt state

After setting the RTOS pin to low it may take another instruction to be executed
before the ISR is executed. Therefore you should first execute some instructions,
e.g. save registers you need to save in any case as a sub-routine, which do not
require exclusive use to resources or memory locations.

After this the sub-routine may proceed with the normal execution. Note that there
is no need to save CPU_SREG for such sub-routines. Only sub-routines that might
cause a task switch must save CPU_SREG, i.e. only the RTOS sub-routines will have
to save the status register which will also be restored after the execution of the
OS routine. OS routines may cause a task switch and some OS routines may be called
by ISRs itself.

Of course the sub-routine must use reti and not ret when returning to the caller
to end the interrupt state. From a callers perspective there is no difference in
normal, RTOS or interrupt save sub-routines. They just call the functions with the
appropriate parameters.
