typedef struct os_tcb {
OS_STK *OSTCBStkPtr; /* Pointer to current top of stack */
#if OS_TASK_CREATE_EXT_EN > 0
void *OSTCBExtPtr; /* Pointer to user definable data for TCB extension */
OS_STK *OSTCBStkBottom; /* Pointer to bottom of stack */
INT32U OSTCBStkSize; /* Size of task stack (in number of stack elements) */
INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */
INT16U OSTCBId; /* Task ID (0..65535) */
#endif
struct os_tcb *OSTCBNext; /* Pointer to next TCB in the TCB list */
struct os_tcb *OSTCBPrev; /* Pointer to previous TCB in the TCB list */
#if (OS_EVENT_EN) || (OS_FLAG_EN > 0)
OS_EVENT *OSTCBEventPtr; /* Pointer to event control block */
#endif
#if (OS_EVENT_EN) && (OS_EVENT_MULTI_EN > 0)
OS_EVENT **OSTCBEventMultiPtr; /* Pointer to multiple event control blocks */
#endif
#if ((OS_Q_EN > 0) && (OS_MAX_QS > 0)) || (OS_MBOX_EN > 0)
void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */
#endif
#if (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
#if OS_TASK_DEL_EN > 0
OS_FLAG_NODE *OSTCBFlagNode; /* Pointer to event flag node */
#endif
OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run */
#endif
INT16U OSTCBDly; /* Nbr ticks to delay task or, timeout waiting for event */
INT8U OSTCBStat; /* Task status */
INT8U OSTCBStatPend; /* Task PEND status */
INT8U OSTCBPrio; /* Task priority (0 == highest) */
INT8U OSTCBX; /* Bit position in group corresponding to task priority */
INT8U OSTCBY; /* Index into ready table corresponding to task priority */
#if OS_LOWEST_PRIO <= 63
INT8U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */
#else
INT16U OSTCBBitX; /* Bit mask to access bit position in ready table */
INT16U OSTCBBitY; /* Bit mask to access bit position in ready group */
#endif
#if OS_TASK_DEL_EN > 0
INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
#endif
#if OS_TASK_PROFILE_EN > 0
INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */
INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */
INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */
OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */
INT32U OSTCBStkUsed; /* Number of bytes used from the stack */
#endif
d.完成以上工作后进行一次编译,我们可以发现出现错误提示
.Source\os_core.c(26): error: #5: cannot open source input file " os_ii.h": No s h file or directory
该问题是包含文件路径引起的, os_ii.h文件实际上存在于Micrium\Software\ OS-II\Source目录下。因此我们需要在工程设置中的C/C++选项卡手动增加头文件路径,针对以上错误我们应该增加的头文件路径未.\Source
e.再次编译发生错误
.\Source\ os_ii.h(44): error: #5: cannot open source input file "app_cfg.h": No s h file or directory
这个问题应该不是原生 OS导致的,是micrium移植系统的时候修改了源文件,在其中增加了一些配置选项,这个配置选项保存在app_cfg.h中,但是micrium发布移植文件包的时候该文件又没有包含在内,因此需要我们自己写一个配置文件。本文为了方便就不细致研究文件内容,直接从micrium的开发板STM3210B-EVAL源码包中拷贝该文件放置于工程目录下的APP文件夹中,并设置相应的包含路径。
f.再次编译发生错误
.\Source\ os_ii.h(45): error: #5: cannot open source input file "os_cfg.h": No s h file or directory
在micrium的移植文件包中也没有这个文件,但是在目录Micrium\Software\ OS-II\Source下存在一个文件名为os_cfg_r.h的文件,将该文件名后的r去掉解决。
g.再次编译发生错误
.\Source\ os_ii.h(46): error: #5: cannot open source input file "os_cpu.h": No s h file or directory
该文件实际上存在于Micrium\Software\ OS-II\Ports\ARM-Cortex-M3\Generic\RealView目录下,因此可以通过修改文件包含路径解决。
h.再次编译发生错误
.\OUTPUT\ OSII.sct(7): error: L6236E: No section matches selector - no section to be FIRST/LAST.
点击该错误提示出现以下内容:
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
k.再次编译发生错误:
.\OUTPUT\ OSII.axf: Error: L6218E: Undefined symbol OS_CPU_SysTickClkFreq (referred from os_cpu_c.o).
这个错误时系统找不到OS_CPU_SysTickClkFreq这个函数实体。查阅相关资料发现micrium增加这个函数的目的是获取系统当前的时钟频率,于是我们在工程中的BSP组增加一个bsp.c文件,同时实现这个OS_CPU_SysTickClkFreq函数即可。未测试需要,本函数简单写为
INT32U OS_CPU_SysTickClkFreq(void)
{
return 8000000;
}
l.再次编译已经没有错误发生,只有一个警告信息
.\OUTPUT\ OSII.axf: Warning: L6305W: Image does not have an entry point. (Not specified or not set d to multiple choices.)
通过查阅资料,大致意思就是说keil不知道整个代码的入口在哪儿,根据init.s中的代码
ENTRY
ResetHndlr
;******************************************************************************
; MOVE TO MAIN
;******************************************************************************
ldr r0, =__main
bx r0 ; Save this in register for possible long jump ;
1.关于AREA--AREA是arm汇编中的段标志,它代表一个段的开始。所谓段是指一个独立的,被命名的,不可分割一组代码或者数据,一个单独的代码段是一个应用功能的最小单元。原文如下“sections are independent, named, indivisible seqnces of code or data. A single code section is the minimum required to prod? an application”。
2.关于ENTRY--ENDTRY英文原意是入口的意思,在汇编语言中它代表了一个代码段中被执行的第一条指令的位置。如果代码中有C语言代码,C的初始化库就已经包含了entry,一般这个entry就是main函数的入口,转换为标识符就是__main所在的位置。在一个文件中如果包含了多个ENTRY连接过程将报错。这也就解释了学习笔记4中编译报错的问题。知道原因我们可以直接去掉init.s中的ENTRY,再编译就直接OK了。
RW_IRAM1 0x20000000 0x00004C00
{
* (+RW,+ZI)
} ;; The following declarations select the "two region model" ;
;; A default __user_initial_stackheap() will be used ;
ARM_LIB_HEAP 0x20004700 EMPTY 0x00000200 {}
ARM_LIB_STACK 0x20004B00 EMPTY -0x00000200 {}
}