Readme for ARM U/COS II port v1.0 (3rd November 1999)
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
by Niall Douglas

Herein contained are the files to port U/COS II to a generic ARM.
There is no code specific to any particular ARM other than it must
run in a 32 bit mode (ie; ARM2 and ARM3 processors won't run this).

However, there are a number of assumptions made. The first is that
there are both SWI and IRQ handlers provided. The IRQ handler must
call OSIntEnter(), OSTimeTick() and OSIntExit() for timer interrupts
as the U/COS II book says. The SWI handler must at least provide
SWI OS_EnterOS (0x16) and optionally SWI's OS_IntOn (0x13) and
OS_IntOff (0x14). These work as the *RISC-OS* ones used to, not as
some RTOS's broken implementations do. Demon I believe implements
these fine, Angel does not.

To be specific here:
 * OS_EnterOS: Must exit with processor mode now SVC32, interrupt &
flag state *unchanged*. Also, and it's here where many RTOS's are
broken, SPSR_svc on exit must contain the *correct* prior PSR before
the call to OS_EnterOS.
 * OS_IntOff: Must exit with merely interrupts disabled, nothing
else changed. If you change OS_CRITICAL_METHOD to 2, you don't
need this call.
 * OS_IntOn: Must exit with merely interrupts enabled, nothing else
changed. If you change OS_CRITICAL_METHOD to 2, you don't need this
call.

Other notes: If you are using OS_CRITICAL_METHOD 2, you must be
careful in writing code protected by OS_ENTER_CRITICAL and
OS_EXIT_CRITICAL. The problem is that the current interrupt state
is saved on the SVC stack. This poses no problems to C code
running in USR mode, but C code running in SVC mode may have
stack problems as the calls OSStackAndDisableInts() (called by
OS_ENTER_CRITICAL) and OSRestoreStackedIntState() (called by
OS_EXIT_CRITICAL) are not APCS compliant as they don't leave the
stack in the same state as they received it. This normally isn't
a problem unless the compiler is using the stack for temporary
workspace whose allocation and deallocation isn't nested within
the calls.

There are two work-arounds for this problem. First is to change
OSStackAndDisableInts() and OSRestoreStackedIntState() to stack
the saved interrupt state on the FIQ stack instead of the SVC
one. This causes increased overhead.

The second option is to *always* encapsulate code between the
OS_ENTER_CRITICAL and OS_EXIT_CRITICAL in a scope declaration eg;

OS_ENTER_CRITICAL();
{
	char temp[256];
	// Do stuff
}
OS_EXIT_CRITICAL();

This forces the compiler to deallocate temporary stack usage
before calling OS_EXIT_CRITICAL. Remember this problem ONLY
affects C code which may run in SVC mode. If it's IRQ mode (eg;
IRQ handlers written in C) or any other mode then it is NOT a
problem.

Other small notes: If you enable OS_TASK_DEL_EN, tasks will
auto-call OSTaskDel(OS_PRIO_SELF) if they ever try returning. If
not, the reset vector is called. This behaviour can be changed
in os_cpu_c.c.

The C code correctly handles OS_STK_GROWTH although it assumes
a full descending stack for 1 and an empty ascending stack for
2. The assembler code always assumes a full descending stack as
the relevent ARM instructions embody how stacks move and hence
lots of conditional code would be needed to use a different
stack type. Processor stacks on the ARM haven't been anything
other than full descending for at least a decade now, so I'd
imagine this limitation won't be a problem. 

Finally, the references to NedHAL (including calls to DbgIO_Write0)
refers to my final year project onto which I've ported U/COS II. If
you're at all bothered, it lives at http://www.nedprod.com/NedHAL.

All the best,
Niall Douglas
3rd November 1999

(Email: NedHAL@nedprod.com)
