Micrium

Bug Fixes / Improvements

Version 2.52 is currently included with the µC/OS-II book

µC/OS-II Second Edition

Special Notes

µC/OS-II: Alignments of Memory Partitions

Some processors have problems with non word-aligned memory locations for memory partitions. To prevent problems when creating memory partitions, it is recommended that:

1) You allocate the memory blocks as INT32U arrays:

INT32U MemPart1Tbl[MEM_BLKS_1][MEM_BLK_SIZE_1/sizeof(INT32U)];

2) MEM_BLK_SIZE_1 in the example above can still specify the number of BYTEs in the block BUT, it should be a MULTIPLE of sizeof(INT32U).


Bugs corrected

ESBB, Comm Module: COMM_PCA.ASM (V2.00-001)

COMM_PCA.ASM needs to be changed if you use µC/OS-II V2.52 and higher. You can download the new code RIGHT-MOUSE clicking HERE.


µC/OS-View: OS_View.C (V1.10-003)

OSView_TxStart() in OS_View.C is missing the following statements (in Red):

static void OSView_TxStart (void)
{
#if OS_CRITICAL_METHOD == 3
    OS_CPU_SR cpu_sr;
#endif


    OS_ENTER_CRITICAL();
    if (OSView_TxActiveFlag == FALSE) {
        OSView_TxHandler();
        OSView_TxIntEn();
    }
    OS_EXIT_CRITICAL();
}

µC/OS-View: OS_View.C (V1.10-002)

The following case in OSView_RxHandler() should be changed because some compilers/processors do not support 8-bit data types and, the checksum test would fail when the sum exceeds 255. The code thus needs to be changed from:

case OS_VIEW_RX_STATE_CHKSUM: /* waiting for checksum */
    OSView_RxChkSum += data;
    if (OSView_RxChkSum == 0x00) {
        OSView_RxState = OS_VIEW_RX_STATE_ED;
    } else {
        OSView_RxState = OS_VIEW_RX_STATE_SD0;
    }
    break;

To:

case OS_VIEW_RX_STATE_CHKSUM: /* waiting for checksum */
    OSView_RxChkSum += data;
    if ((OSView_RxChkSum & 0xFF) == 0x00)     {
        OSView_RxState = OS_VIEW_RX_STATE_ED;
    } else {
        OSView_RxState = OS_VIEW_RX_STATE_SD0;
    }
    break;

 

µC/OS-View: OS_View.C (V1.10-001)

OSView_Init() is missing THREE initializers:

OSView_TxLen = 0;
OSView_TxStrLen = 0;
OSView_TxActiveFlag = FALSE;


µC/OS-II: OS_TASK.C (V2.70-007)

In OSTaskQuery() we need to check to see if the TCB is assigned to a Mutex. The code is RED is added after the check for 'ptcb' being a NULL pointer.

if (ptcb == (OS_TCB *)0) { /* Task to query must exist */
  OS_EXIT_CRITICAL();
  return (OS_PRIO_ERR);
}
if (ptcb == (OS_TCB *)1) { /* Task to query must not be assigned to a Mutex */
  OS_EXIT_CRITICAL();
  return (OS_PRIO_ERR);
}

µC/OS-II: OS_TASK.C (V2.70-006)

In OSFlagPend() the returned 'flags_rdy' was not set correctly if you didn't specify OS_FLAG_CONSUME. The new code for this function can be downloaded here: OSFlagPend.c.

µC/OS-II: OS_TASK.C (V2.70-005)

In OSTaskNameGet() and OSTaskNameSet(), we were missing an OS_EXIT_CRITICAL() before the exit of the first test. The code has been corrected and the new OSTaskNameGet() and OSTaskNameSet() can be downloaded here: OSTaskNameXXX.c.

µC/OS-II: OS_Q.C (V2.70-004)

In OSQDel(), the first test should return 'pevent' instead of a NULL pointer upon failure. The following code:

if (OSIntNesting > 0) { /* See if called from ISR ... */
  *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  return ((OS_EVENT *)0);
}

Should NOW be:

if (OSIntNesting > 0) { /* See if called from ISR ... */
  *err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  return (pevent);
}

µC/OS-II: OS_MEM.C (V2.70-003)

In OSQPostOpt(), the test for 'msg' being NULL must be DELETED. That's because, as of V2.62, it's now possible to post NULL pointer messages to a message queue. The following code:

#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  return (OS_ERR_PEVENT_NULL);
}
if (msg == (void *)0) { /* Make sure we are not posting a NULL pointer */
  return (OS_ERR_POST_NULL_PTR);
}

#endif

Should NOW be:

#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  return (OS_ERR_PEVENT_NULL);
}
#endif

µC/OS-II: OS_MEM.C (V2.70-002)

In OSMemNameSet(), a return statement is missing for the case when pmem is NULL:

if (pmem == (OS_MEM *)0) { /* Is 'pmem' a NULL pointer? */
  OS_EXIT_CRITICAL(); /* Yes */
  *err = OS_MEM_INVALID_PMEM;
  return;
}

µC/OS-II: OS_TASK.C (V2.70-001)

OSTaskResume() and OSTimeTick() were previously corrected thinking that there were problems with them. It turns out that these functions were correct in V2.70. This correct code can be found in the following files:

OSTaskResume-V271.c
OSTimeTick-V271.c



µC/OS-II: OS_TASK.C (V2.62-001)

In OSTaskDel(), we added a statement to clear the stack pointer of the task being deleted. This statement appears on line 428 and should be REMOVED. The code was added originally to show that the stack of a task that has been deleted is no longer valid. This was to support Kernel Awareness but was found to cause side effects. The line to delete is:

    ptcb->OSTCBStkPtr = (OS_STK *)0;  /* Show that TCB is 'unused' */

µC/OS-II: OS_CORE.C (V2.61-004)

OS_TaskStatStkChk() has an error computing the stack bottom. The new code for this function can be downloaded by clicking HERE! This code also contains the fix for Bug V2.61-003.

µC/OS-II: OS_CORE.C (V2.61-003)

OS_TaskStatStkChk() didn't check for a task that was assigned to a MUTEX and thus attempted to compute the stack size of an invalid task. The following code corrects this problem:

if (ptcb != (OS_TCB *)0) {
  if (ptcb != (OS_TCB *)1) {
#if OS_TASK_CREATE_EXT_EN > 0
    stk_size = ptcb->OSTCBStkSize * sizeof(OS_STK);
#endif
#if OS_TASK_PROFILE_EN > 0
#if OS_STK_GROWTH == 1
    ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom + stk_size;
#else
    ptcb->OSTCBStkBase = ptcb->OSTCBStkBottom - stk_size;
#endif
    ptcb->OSTCBStkUsed = (INT32U)stk_data.OSUsed;
#endif
  }
}

µC/OS-II: OS_MEM.C (V2.61-002)

Line #242 is:

if (len > (OS_EVENT_NAME_SIZE - 1)) {

and should be:

if (len > (OS_MEM_NAME_SIZE - 1)) {

µC/OS-II: OS_FLAG.C (V2.61-001)

The second OS_ENTER_CRITICAL() in OSFlagPendGetFlagsRdy() needs to be changed to OS_EXIT_CRITICAL()
The BAD code is:

OS_FLAGS OSFlagPendGetFlagsRdy (void)
{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_FLAGS flags;


OS_ENTER_CRITICAL();
flags = OSTCBCur->OSTCBFlagsRdy;
OS_ENTER_CRITICAL();
return (flags);

}

and should be:

OS_FLAGS OSFlagPendGetFlagsRdy (void)
{

#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_FLAGS flags;


OS_ENTER_CRITICAL();
flags = OSTCBCur->OSTCBFlagsRdy;
OS_EXIT_CRITICAL();
return (flags);

}


µC/OS-II: uCOS_II.H (V2.51-003)

Line 889

#ifndef OS_FLAG_QUERY_EN
#error "OS_CFG.H, Missing OS_FLAG_DEL_EN: Include code for OSFlagQuery()"

needs to be:

#ifndef OS_FLAG_QUERY_EN
#error "OS_CFG.H, Missing OS_FLAG_QUERY_EN: Include code for OSFlagQuery()"

µC/OS-II: OS_Q.C (V2.51-002)

The function OSQQuery() contains a BUG in the following code which is towards the end of the function.

pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0) {
  pdata->OSMsg = pq->OSQOut; /* Get next message to return if available */
} else {
  pdata->OSMsg = (void *)0;
}

The CORRECT code is shown below. Note that pq->OSQOut was missing the *.

pq = (OS_Q *)pevent->OSEventPtr;
if (pq->OSQEntries > 0) {
  pdata->OSMsg =
*pq->OSQOut; /* Get next message to return if available */
} else {
  pdata->OSMsg = (void *)0;
}

µC/OS-II: uCOS_II.H (V2.51-001)

The function prototype for OSSchedLock() was changed by mistake to OS_SchedLock(). Simply REMOVE the underscore since the CORRECT name is OSSchedLock().


µC/OS-II: OS_CPU_A.ASM (V2.05-001) (For both Ix86L and Ix86L-FP)

The NEW ISRs MUST check to see if OSIntNesting == 1 BEFORE you save the SP in the current task's OS_TCB. The incorrect 'pseudo' code is:

OSTCBCur->OSTCBStkPtr = SP /* Save SP onto current task's stack */

and should be:

if (OSIntNesting == 1) {
  OSTCBCur->OSTCBStkPtr = SP /* Save SP onto current task's stack */
}

The reason we need this change is that we don't want to save the current value of SP if the ISR is for a nested ISR!

IMPORTANT: If you have the release notes version V2.05a then you have the CORRECT code.


µC/OS-II: OS_CORE.C (V2.04-001)

The wrong argument is being passed to the call to OSTaskCreateHook() in OSTCBInit().
The BAD code is:

OSTaskCreateHook(OSTCBPrioTbl[prio]); /* Call user defined hook */

and should be:

OSTaskCreateHook(ptcb); /* Call user defined hook */

µC/OS-II: OS_MUTEX.C (V2.04-002)

The test in OSMutexPost() to see if the posting task owns the MUTEX is incorrect. The correct test needs to have && instead of || as follows:

if (OSTCBCur->OSTCBPrio != pip &&
  OSTCBCur->OSTCBPrio != prio) { /* See if posting task owns the MUTEX */
  OS_EXIT_CRITICAL();
  return (OS_ERR_NOT_MUTEX_OWNER);
}

µC/OS-II: OS_MUTEX.C (V2.04-003)

The function OSMutexDel() needs to release the priority of the PIP. The correct code for OSMutexDel() can be downloaded from:
Download new OSMutexDel().

µC/OS-II: uCOS_II.H (V2.04-004)

The function OSMutexDel() needs to be added in the prototype list for MUTEXes as follows:

#if OS_MUTEX_EN
INT8U OSMutexAccept(OS_EVENT *pevent, INT8U *err);
OS_EVENT *OSMutexCreate(INT8U prio, INT8U *err);
OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err);
void OSMutexPend(OS_EVENT *pevent, INT16U timeout, INT8U *err);
INT8U OSMutexPost(OS_EVENT *pevent);
INT8U OSMutexQuery(OS_EVENT *pevent, OS_MUTEX_DATA *pdata);
#endif


Improvements

µC/OS-II: OS_CPU_A.ASM 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