Micrium

Support F.A.Q.


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.

Back to top

 

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;
        }
        .
        .
    }
    .
    .
}

Back to top

 

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.

Back to top

 

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.

Back to top
 

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.

Back to top

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

Back to top