|
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
|