ucosIII移植测试

引用:内容比较 - 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);
          }

断点测试

  1. OSStartHighRdy()os_cpu_a.asm在"从中断/异常返回"指令处设置断点。执行宏后,你应该查看CPU寄存器,确认它们都有期望值(对于、为、等)。如果没有,那说明宏系统中任何一方都不对劲。基本上就是根据堆栈中的内容搭建栈和寄存器。

  2. 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(); 
                       }
                   }
               }
           }
  3. 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().

  1. 验证栈(SP)是否包含OS_CTX_SAVE与OSTaskStkInit() 中相同顺序保存的 CPU 寄存器值

  2. 确认已将SP保存到OSTickTaskTCB.StkPtr

任务调度顺序应该是:

OSCtxSw()

OS_IdleTask()

OSCtxSw()

OS_TickTask()

OSCtxSw()

OS_IdleTask()

OSCtxSw()

etc.

6. 中断部分调试:

  • OSTickISR()

  • OSIntCtxSw()

  • OS_TickTask()

  • BSP_OS_TickISR()

  • OSIntCtxSw()

  • 等等。