引用:内容比较 - Testing a Port (v.5 vs v.6) - µC/OS-III Documentation - Confluence
创建一个简单的测试项目
(1) 是将包含项目源文件的目录名称。MyTest
(2) 是包含且应如下所示的测试文件。app.c ``main()
\Micrium
\Software
\EvalBoards
\MyBoardManufacturer
\MyBoardName
\MyToolsName
\MyBSP
bsp.c
bsp.h
bsp_os.c <- See the section µC/OS-III port
bsp_os_a.asm (optional) <- See the section µC/OS-III port
bsp_os.h <- See the section µC/OS-III port
cpu_bsp.c
cpu_bsp.h
\MyTest (1)
app.c (2)
app_cfg.h (3)
cpu_cfg.h (4) <- Copied from \Micrium\Software\uC-CPU\Cfg\Template
lib_cfg.h <- Copied from \Micrium\Software\uC-LIB\Cfg\Template
os_app_hooks.c <- Copied from \Micrium\Software\uCOS-III\Cfg\Template
os_app_hooks.h <- Copied from \Micrium\Software\uCOS-III\Cfg\Template
os_cfg.h (5) <- Copied from \Micrium\Software\uCOS-III\Cfg\Template
os_cfg_app.h <- Copied from \Micrium\Software\uCOS-III\Cfg\Template
os_type.h <- Copied from \Micrium\Software\uCOS-III\Source
\Micrium
\Software
\uC-CPU
cpu_core.c
cpu_core.h
cpu_def.h
\MyCPUName
\MyToolsName
cpu.h <- See the section µC/CPU
cpu_a.asm <- See the section µC/CPU
\Micrium
\Software
\uC-LIB
lib_ascii.c
lib_ascii.h
lib_def.h
lib_math.c
lib_math.h
lib_mem.c
lib_mem.h
lib_str.c
lib_str.h
\Micrium
\Software
\uC/OS-III
\Cfg
os_app_hooks.c
os_app_hooks.h
os_cfg.h
os_cfg_app.h
\Ports
\MyCPUName
\MyToolsName
os_cpu.h <- See the section µC/OS-III port
os_cpu_a.asm <- See the section µC/OS-III port
os_cpu_a.inc <- See the section µC/OS-III port
os_cpu_c.c <- See the section µC/OS-III port
\Source
os.h
os_cfg_app.c
os_core.c
os_dbg.c
os_flag.c
os_mem.c
os_msg.c
os_mutex.c
os_prio.c
os_q.c
os_sem.c
os_stat.c
os_task.c
os_tick.c
os_time.c
os_tmr.c
os_trace.c
os_type.h
os_var.c
项目配置
(3) h 应具有以下定义:app_cfg.
APP_CFG_TASK_START_PRIO 2U
APP_CFG_TASK_START_STK_SIZE 256u
(4)剩余文件是从本页顶部列表中显示的目录复制的,目前不应更改。
(5)您需要编辑并将以下 s 设置为如下所示的值:os_cfg.h``#define
OS_CFG_PRIO_MAX 32u
OS_CFG_STAT_TASK_EN DEF_DISABLED
OS_CFG_TMR_EN DEF_DISABLED
OS_CFG_SCHED_ROUNDROBIN_EN DEF_DISABLED
这样做是为了确保测试应用中只有两个任务,和。OS_IdleTask()``OS_TickTask()
在这个测试中,你需要添加一 行代码,如下所示。一旦我们验证了 OSIdleTaskHook()、OSInit() 、OSTaskStkInit() 和OSCtxSw(),OS_CTX_SAVE,OS_CTX_RESTORE我们将移除以下代码:
使用 OSIdleTaskHook() 测试应用程序
void OSIdleTaskHook (void)
{
OSTimeTick();
#if OS_CFG_APP_HOOKS_EN > 0u
if (OS_AppIdleTaskHookPtr != (OS_APP_HOOK_VOID)0) {
(*OS_AppIdleTaskHookPtr)();
}
#endif
}
验证任务上下文切换
在本节中,我们将验证以下函数/宏的正确操作:
OSInit() (os_core.c)
OSStartHighRdy() (os_cpu_a.asm)
OSTaskStkInit() (os_cpu_c.c)
OSCtxSw() (os_cpu_a.asm)
OS_CTX_SAVE (os_cpu_a.inc)
OS_CTX_RESTORE (os_cpu_a.inc)
CPU_SR_Save() (cpu_a.asm)
CPU_SR_Restore() (cpu_a.asm)
我们的第一个测试是验证μC/OS-III是否正确初始化,以及代码是否正确初始化任务栈。OSTaskStkInit()
请记住,我们的应用程序包含以下代码:app.c
/* app.c */
#include "os.h"
#include "app_cfg.h"
static OS_TCB App_TaskStartTCB;
static CPU_STK_SIZE App_TaskStartStk[APP_CFG_TASK_START_STK_SIZE];
static void App_TaskStart(void *p_arg);
void main (void)
{
OS_ERR err;
OSInit(&err);
OSTaskCreate(&App_TaskStartTCB,
"App Task Start",
App_TaskStart,
0,
APP_CFG_TASK_START_PRIO,
&App_TaskStartStk[0],
(APP_CFG_TASK_START_STK_SIZE / 10u),
APP_CFG_TASK_START_STK_SIZE,
0,
0,
0,
(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
&err);
OSStart(&err);
}
static void App_TaskStart (void *p_arg)
{
OS_ERR err;
OSTaskSuspend(0, &err);
}
断点测试
-
OSStartHighRdy()os_cpu_a.asm在"从中断/异常返回"指令处设置断点。执行宏后,你应该查看CPU寄存器,确认它们都有期望值(对于、为、等)。如果没有,那说明宏系统中任何一方都不对劲。基本上就是根据堆栈中的内容搭建栈和寄存器。 -
OS_TickTask
void OS_TickTask (void *p_arg) { OS_ERR err; CPU_TS ts; p_arg = p_arg; while (DEF_ON) { (void)OSTaskSemPend((OS_TICK )0, (OS_OPT )OS_OPT_PEND_BLOCKING, (CPU_TS *)&ts, (OS_ERR *)&err); if (err == OS_ERR_NONE) { <- Set a BREAKPOINT here! if (OSRunning == OS_STATE_OS_RUNNING) { OS_TickListUpdate(); } } } } -
OSCtxSw()
OSCtxSw: <- Set a BREAKPOINT here! OS_CTX_SAVE OSTCBCurPtr->StkPtr = SP; OSTaskSwHook(); OSPrioCur = OSPrioHighRdy; OSTCBCurPtr = OSTCBHighRdyPtr; SP = OSTCBCurPtr->StkPtr; OS_CTX_RESTORE Return from Interrupt/Exception;
Basically, what's happening here is that OS_TickTask() will be waiting for the tick ISR to signal the task that a tick has expired. Since we haven't setup the tick interrupt (not yet anyway), OS_TickTask() would never get to execute. However, I had you modify the idle task hook to simulate signaling the tick task so µC/OS-III will eventually switch back to this code. In the meantime, µC/OS-III will switch to the next task that's ready-to-run. This happens to be the idle task. We'll be following the code until we get to OS_IdleTask().
-
验证栈(SP)是否包含OS_CTX_SAVE与OSTaskStkInit() 中相同顺序保存的 CPU 寄存器值
-
确认已将SP保存到
OSTickTaskTCB.StkPtr
任务调度顺序应该是:
OSCtxSw()
OS_IdleTask()
OSCtxSw()
OS_TickTask()
OSCtxSw()
OS_IdleTask()
OSCtxSw()
etc.
6. 中断部分调试:
-
OSTickISR() -
OSIntCtxSw() -
OS_TickTask() -
BSP_OS_TickISR() -
OSIntCtxSw() -
等等。