Support F.A.Q.
You are here : Micrium
:
Support FAQ
FAQ-01: My computer/processor 'hangs'
when I run µC/OS or µC/OS-II!
FAQ-02: Are you allowed to send a NULL-pointer
through a Mailbox or a Queue?
FAQ-03: Where should I enable the 'tick'
interrupt?
FAQ-04: Does µC/OS and µC/OS-II
work with Microsoft C/C++?
FAQ-05: Are there other ports available
for µC/OS and µC/OS-II?
FAQ-06: Is there a better way to implement
OSIntCtxSw() and ISRs?
(Added
2001/01/26)
FAQ-01: My computer/processor
'hangs' when I run µC/OS or µC/OS-II!
DOS executables for µC/OS and µC/OS-II are provided
on the diskette. If µC/OS (or µC/OS-II) still hangs
with the executable provided on the floppy, contact me at Jean.Labrosse@Micrium.com.
If µC/OS (or µC/OS-II) does not hang with the executable
provided on the floppy then there are two possible reasons your
computer could crash:
1) You need to look at OSIntCtxSw (pages
62, 63 and 67 in the µC/OS book or pages 200 and 201 in µC/OS-II)
which is processor and compiler specific. The very first
instruction in OSIntCtxSw() may need
some adjustment, i.e. ADD SP,8. If
you use another processor, compiler or memory model, you may need
to adjust the constant. This section in the book will
explain how to determine the 'magic number' to add to the stack
pointer.
The actual value depends on the compiler used and the compiler options. For
example, on the x86 real-mode small model, the constant can be either 4, 6,
8, 10 ... For the x86 real-mode, large model, the constant can be either
8, 10, 12, 14, 16 ...
2) You may want to try removing ANY (and ALL) floating-point
operation. The sample code in example #1 (µC/OS V1.xx
and µC/OS-II V2.00) has a floating-point operation in the
start task. Comment it out (by putting #if
0 / #endif around the sprintf() statement)
and try compiling and running the code. If the code works,
the crash is due to the fact that:
a) The Borland C/C++ floating-point library is non-reentrant.
b) µC/OS and µC/OS-II's task stacks need to be
initialized to perform floating-point operations in a reentrant way. Refer
to AN-1001 for details (See AppNotes).
3) See FAQ-06.

FAQ-02: Are you allowed
to send a NULL-pointer through a Mailbox or a Queue?
No. By definition, a NULL-pointer is not supposed to point
to any valid data. You could, however, 'fake' µC/OS
(or µC/OS-II) into sending NULL pointers. You will
need to 're-map' a NULL pointer to another 'invalid' pointer. For
example, if you want to send a NULL through a message mailbox,
you can do the following:
void SenderTask (void *pdata)
{
.
.
if (msg == (void *)0) { /*
Do I want to send a NULL pointer ? */
msg = (void *)0xFFFFFFFF; /*
Yes, remap to another 'invalid' pointer */
}
OSMboxPost(Mbox, msg);
.
.
}void ReceiverTask (void *pdata)
{
void *msg;
.
.
msg = OSMboxPend(Mbox, 0, &err);
if (err == OS_NO_ERR) {
if (msg == (void *)0xFFFFFFFF) { /*
Did I receive a NULL pointer ? */
msg = (void
*)0;
}
.
.
}
.
.
}

FAQ-03: Where should I
enable the 'tick' interrupt?
You should enable the tick interrupt AFTER you have started µC/OS
(or µC/OS-II) in a 'startup' task as shown in the example
code provided with the book. This way, the OS is in a state ready
to accept interrupts and can thus process interrupts.

FAQ-04: Does µC/OS
and µC/OS-II work with Microsoft C/C++?
Yes, you will have to adjust the SP offset constant (see item
1)) and disable stack checking. Others have used the Microsoft
compiler without too many problems.
See also FAQ-06.

FAQ-05: Are there other
ports available for µC/OS and µC/OS-II?
There are currently a large number of ports available for µC/OS
and µC/OS-II. I am planning on making a number of ports
available on this WEB site as they become available.
A port to µC/OS can easily be ported to µC/OS-II in about an hour
or so. This assumes that you are familiar with the target processor and
it's compiler. This means that if a port for µC/OS-II is not currently
available but a port for µC/OS exist then you could modify the µC/OS
port to work with µC/OS-II. Chapter 10 in the book (µC/OS-II)
describes the steps.

FAQ-06: Is there a better
way to implement OSIntCtxSw() and ISRs?
As you probably know, µC/OS-II has a function that is dependent
on compiler options (OSIntCtxSw()) and,
the port designer HAS to adjust the Stack Pointer based on the
code generation of the compiler.
On certain processors (e.g. 80x86) you can simply write ISRs so
that you SAVE the Stack Pointer (SS:SP for the 80x86) into the
current task's OS_TCB after incrementing OSIntNesting. This
way, we save the PROPER pointer to the ISR stack frame in case
we don't actually return to the interrupted task. If we DO
return to the interrupted task then, there is no harm and all we
did was waste a little bit of CPU time! Of course, we eliminate
the code at the beginning of OSIntCtxSw() to
adjust the Stack Pointer (SP for the 80x86) and the code to save
the Stack Pointer into the OS_TCB!
The new pseudo code for an ISR and OSIntCtxSw() is
now:
MyISR:
Save ALL registers;
OSIntNesting++;
OSTCBCur->OSTCBStkPtr = SP; <<<< NEW
/* Handle ISR */
OSIntExit();
Restore ALL registers;
Return from Interrupt;
OSIntCtxSw:
OSTaskSwHook();
OSTCBCur = OSTCBHighRdy;
SP = OSTCBHighRdy->OSTCBStkPtr;
Restore ALL registers;
Return from Interrupt;
In assembly language for the 80x86 (Large model), this becomes:
_MyISR PROC FAR
;
PUSHA ;
Save interrupted task's context
PUSH ES
PUSH DS
;
MOV AX, SEG(_OSIntNesting) ; Reload
DS
MOV DS, AX
INC BYTE PTR _OSIntNesting ; Notify
uC/OS-II of ISR
;
LES BX, DWORD PTR DS:_OSTCBCur ; OSTCBCur->OSTCBStkPtr
= SS:SP
MOV ES:[BX+2], SS
MOV ES:[BX+0], SP
CALL FAR PTR _MyISRHandler ; Process
the Interrupt
;
CALL FAR PTR _OSIntExit ;
Notify uC/OS-II of end of ISR
;
POP DS ;
Restore interrupted task's context
POP ES
POPA
;
IRET ;
Return to interrupted task
;
_MyISR ENDP
_OSIntCtxSw PROC FAR
;
CALL FAR PTR _OSTaskSwHook ;
Call user defined task switch hook
;
MOV AX, WORD PTR DS:_OSTCBHighRdy+2 ; OSTCBCur = OSTCBHighRdy
MOV DX, WORD PTR DS:_OSTCBHighRdy
MOV WORD PTR DS:_OSTCBCur+2, AX
MOV WORD PTR DS:_OSTCBCur, DX
;
MOV AL, BYTE PTR DS:_OSPrioHighRdy ; OSPrioCur = OSPrioHighRdy
MOV BYTE PTR DS:_OSPrioCur, AL
;
LES BX, DWORD PTR DS:_OSTCBHighRdy ; SS:SP = OSTCBHighRdy->OSTCBStkPtr
MOV SS, ES:[BX+2]
MOV SP, ES:[BX]
;
POP DS ;
Load new task's context
POP ES
POPA
;
IRET ;
Return to new task
;
_OSIntCtxSw ENDP

|