当前位置: 首页 > article >正文

uc/os-II 原理及应用(八) 系统裁减以及移植到51单片机上

两个习题

在这里插入图片描述

  1. 先了解下CPU上函数调用的过程:

    • 一个程序取得函数地址,先保护现场将局部变量及参数压栈,再将调用函数的参数压栈,然后跳转到函数位置,将参数出栈,执行代码,结束后返回到调用位置,再恢复现场。但在MCU中,为了效率与其通常的业务场景可能并不这么做,对于局部变量不会专门保存与恢复。
    • 在多任务系统中,如果多个任务并发的调用一个函数,可能会产生干扰,简单的说是线程不安全。
      如果一个函数被多个任务并发的调用而不产生干扰(线程安全),就是可重入函数。
    • 参考窥探Keil4 C51的函数调用
  2. 各个任务用来存储各自任务堆栈内容的空间是任务堆栈;各个任务在运行时使用的堆栈是系统堆栈。
    在任务切换时,系统堆栈的内容要到重新保存到被中止任务的堆栈空间,要运行的任务的堆栈内存复制到系统堆栈上来。
    任务没有在运行时任务堆栈空间的内容只是备份,所以是那些内容是任务堆栈映像。

移植记录

先使用Keil4 建立一个工程 ucosii_c51,建立两组User与uCOS-II,在User中加入main.c,在uCOS-II中加入uCOS-II的源码

在这里插入图片描述
在这里插入图片描述


的uCOS-II的目录下新建 os_cfg.h,os_cpu.h,app_cfg.h 三个头文件,把os_cfg_r.h的内容先复制到os_cfg.h中来
然后修改os_cfg.h来对uCOS-II系统进行裁减,先做到最小配置

#ifndef __OS_CFG_H__
#define __OS_CFG_H__


                                       /* ---------------------- MISCELLANEOUS ----------------------- */
#define OS_APP_HOOKS_EN           0u   /* Application-defined hooks are called from the uC/OS-II hooks */
#define OS_ARG_CHK_EN             0u   /* Enable (1) or Disable (0) argument checking                  */
#define OS_CPU_HOOKS_EN           0u   /* uC/OS-II hooks are found in the processor port files         */

#define OS_DEBUG_EN               0u   /* Enable(1) debug variables                                    */

#define OS_EVENT_MULTI_EN         1u   /* Include code for OSEventPendMulti()                          */
#define OS_EVENT_NAME_EN          0u   /* Enable names for Sem, Mutex, Mbox and Q                      */

#define OS_LOWEST_PRIO           20u   /* Defines the lowest priority that can be assigned ...         */
                                       /* ... MUST NEVER be higher than 254!                           */

#define OS_MAX_EVENTS            10u   /* Max. number of event control blocks in your application      */
#define OS_MAX_FLAGS              5u   /* Max. number of Event Flag Groups    in your application      */
#define OS_MAX_MEM_PART           5u   /* Max. number of memory partitions                             */
#define OS_MAX_QS                 4u   /* Max. number of queue control blocks in your application      */
#define OS_MAX_TASKS             20u   /* Max. number of tasks in your application, MUST be >= 2       */

#define OS_SCHED_LOCK_EN          1u   /* Include code for OSSchedLock() and OSSchedUnlock()           */

#define OS_TICK_STEP_EN           1u   /* Enable tick stepping feature for uC/OS-View                  */
#define OS_TICKS_PER_SEC        100u   /* Set the number of ticks in one second                        */


                                       /* --------------------- TASK STACK SIZE ---------------------- */
#define OS_TASK_TMR_STK_SIZE    128u   /* Timer      task stack size (# of OS_STK wide entries)        */
#define OS_TASK_STAT_STK_SIZE   128u   /* Statistics task stack size (# of OS_STK wide entries)        */
#define OS_TASK_IDLE_STK_SIZE   128u   /* Idle       task stack size (# of OS_STK wide entries)        */


                                       /* --------------------- TASK MANAGEMENT ---------------------- */
#define OS_TASK_CHANGE_PRIO_EN    0u   /*     Include code for OSTaskChangePrio()                      */
#define OS_TASK_CREATE_EN         1u   /*     Include code for OSTaskCreate()                          */
#define OS_TASK_CREATE_EXT_EN     0u   /*     Include code for OSTaskCreateExt()                       */
#define OS_TASK_DEL_EN            1u   /*     Include code for OSTaskDel()                             */
#define OS_TASK_NAME_EN           0u   /*     Enable task names                                        */
#define OS_TASK_PROFILE_EN        1u   /*     Include variables in OS_TCB for profiling                */
#define OS_TASK_QUERY_EN          1u   /*     Include code for OSTaskQuery()                           */
#define OS_TASK_REG_TBL_SIZE      1u   /*     Size of task variables array (#of INT32U entries)        */
#define OS_TASK_STAT_EN           0u   /*     Enable (1) or Disable(0) the statistics task             */
#define OS_TASK_STAT_STK_CHK_EN   1u   /*     Check task stacks from statistic task                    */
#define OS_TASK_SUSPEND_EN        1u   /*     Include code for OSTaskSuspend() and OSTaskResume()      */
#define OS_TASK_SW_HOOK_EN        0u   /*     Include code for OSTaskSwHook()                          */


                                       /* ----------------------- EVENT FLAGS ------------------------ */
#define OS_FLAG_EN                0u   /* Enable (1) or Disable (0) code generation for EVENT FLAGS    */
#define OS_FLAG_ACCEPT_EN         1u   /*     Include code for OSFlagAccept()                          */
#define OS_FLAG_DEL_EN            1u   /*     Include code for OSFlagDel()                             */
#define OS_FLAG_NAME_EN           1u   /*     Enable names for event flag group                        */
#define OS_FLAG_QUERY_EN          1u   /*     Include code for OSFlagQuery()                           */
#define OS_FLAG_WAIT_CLR_EN       1u   /* Include code for Wait on Clear EVENT FLAGS                   */
#define OS_FLAGS_NBITS           16u   /* Size in #bits of OS_FLAGS data type (8, 16 or 32)            */


                                       /* -------------------- MESSAGE MAILBOXES --------------------- */
#define OS_MBOX_EN                0u   /* Enable (1) or Disable (0) code generation for MAILBOXES      */
#define OS_MBOX_ACCEPT_EN         1u   /*     Include code for OSMboxAccept()                          */
#define OS_MBOX_DEL_EN            1u   /*     Include code for OSMboxDel()                             */
#define OS_MBOX_PEND_ABORT_EN     1u   /*     Include code for OSMboxPendAbort()                       */
#define OS_MBOX_POST_EN           1u   /*     Include code for OSMboxPost()                            */
#define OS_MBOX_POST_OPT_EN       1u   /*     Include code for OSMboxPostOpt()                         */
#define OS_MBOX_QUERY_EN          1u   /*     Include code for OSMboxQuery()                           */


                                       /* --------------------- MEMORY MANAGEMENT -------------------- */
#define OS_MEM_EN                 0u   /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
#define OS_MEM_NAME_EN            1u   /*     Enable memory partition names                            */
#define OS_MEM_QUERY_EN           1u   /*     Include code for OSMemQuery()                            */


                                       /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */
#define OS_MUTEX_EN               0u   /* Enable (1) or Disable (0) code generation for MUTEX          */
#define OS_MUTEX_ACCEPT_EN        1u   /*     Include code for OSMutexAccept()                         */
#define OS_MUTEX_DEL_EN           1u   /*     Include code for OSMutexDel()                            */
#define OS_MUTEX_QUERY_EN         1u   /*     Include code for OSMutexQuery()                          */


                                       /* ---------------------- MESSAGE QUEUES ---------------------- */
#define OS_Q_EN                   0u   /* Enable (1) or Disable (0) code generation for QUEUES         */
#define OS_Q_ACCEPT_EN            1u   /*     Include code for OSQAccept()                             */
#define OS_Q_DEL_EN               1u   /*     Include code for OSQDel()                                */
#define OS_Q_FLUSH_EN             1u   /*     Include code for OSQFlush()                              */
#define OS_Q_PEND_ABORT_EN        1u   /*     Include code for OSQPendAbort()                          */
#define OS_Q_POST_EN              1u   /*     Include code for OSQPost()                               */
#define OS_Q_POST_FRONT_EN        1u   /*     Include code for OSQPostFront()                          */
#define OS_Q_POST_OPT_EN          1u   /*     Include code for OSQPostOpt()                            */
#define OS_Q_QUERY_EN             1u   /*     Include code for OSQQuery()                              */


                                       /* ------------------------ SEMAPHORES ------------------------ */
#define OS_SEM_EN                 0u   /* Enable (1) or Disable (0) code generation for SEMAPHORES     */
#define OS_SEM_ACCEPT_EN          1u   /*    Include code for OSSemAccept()                            */
#define OS_SEM_DEL_EN             1u   /*    Include code for OSSemDel()                               */
#define OS_SEM_PEND_ABORT_EN      1u   /*    Include code for OSSemPendAbort()                         */
#define OS_SEM_QUERY_EN           1u   /*    Include code for OSSemQuery()                             */
#define OS_SEM_SET_EN             1u   /*    Include code for OSSemSet()                               */


                                       /* --------------------- TIME MANAGEMENT ---------------------- */
#define OS_TIME_DLY_HMSM_EN       1u   /*     Include code for OSTimeDlyHMSM()                         */
#define OS_TIME_DLY_RESUME_EN     1u   /*     Include code for OSTimeDlyResume()                       */
#define OS_TIME_GET_SET_EN        1u   /*     Include code for OSTimeGet() and OSTimeSet()             */
#define OS_TIME_TICK_HOOK_EN      1u   /*     Include code for OSTimeTickHook()                        */


                                       /* --------------------- TIMER MANAGEMENT --------------------- */
#define OS_TMR_EN                 0u   /* Enable (1) or Disable (0) code generation for TIMERS         */
#define OS_TMR_CFG_MAX           16u   /*     Maximum number of timers                                 */
#define OS_TMR_CFG_NAME_EN        1u   /*     Determine timer names                                    */
#define OS_TMR_CFG_WHEEL_SIZE     8u   /*     Size of timer wheel (#Spokes)                            */
#define OS_TMR_CFG_TICKS_PER_SEC 10u   /*     Rate at which timer management task runs (Hz)            */

#endif
	 	   	  		 			 	    		   		 		 	 	 			 	    		   	 			 	  	 		 				 		  			 		 					 	  	  		      		  	   		      		  	 		 	      		   		 		  	 		 	      		  		  		  
 		 			 	    		   		 		 	 	 			 	    		   	 			 	  	 		 				 		  			 		 					 	  	  		      		  	   		      		  	 		 	      		   		 		  	 		 	      		  		  		  

在os_cpu.h 中定义一些必要的数据类型及CPU相关配置

#ifndef __OS_CPU_H__
#define __OS_CPU_H__

#include <REGX52.H>


#define OS_STK_GROWTH	    1u				   // 栈增长方向

#define OS_CRITICAL_METHOD  0u				   // 不安全模式下

#define OS_ENTER_CRITICAL() EA=0			   // 关中断
#define OS_EXIT_CRITICAL()  EA=1			   // 开中断

#define OS_TASK_SW()        OSCtxSw()


typedef unsigned char     BOOLEAN;
typedef unsigned char     INT8U;
typedef signed char       INT8S;
typedef unsigned int      INT16U;
typedef signed int        INT16S;
typedef unsigned long int INT32U;
typedef signed long int   INT32S;
typedef float 			  FP32;
typedef double            FP64;

typedef INT8U             OS_STK;


#endif

添加一个源文件os_cpu_c.c
在里面实现任务堆栈初始化函数OSTaskStkInit,以及一些系统必须的钩子。

#ifndef OS_MASTER_FILE
#include <ucos_ii.h>
#endif

OS_STK *OSTaskStkInit(void (*task)(void *p_arg),
                      void *p_arg,
                      OS_STK *ptos,
                      INT16U opt)
{
    OS_STK *stk = ptos;
    (void)(task);
    (void)(p_arg);
    (void)(opt);
    *stk++ = 16;                     // context length of task stack
    *stk++ = ((INT16U)task) & 0xff;  // low(task)
    *stk++ = ((INT16U)task) >> 8;    // HIGH(task)
    *stk++ = 0;                      // for push PSW
    *stk++ = 0;                      // for push ACC
    *stk++ = 0;                      // for push B
    *stk++ = 0;                      // for push DPL
    *stk++ = 0;                      // for push DPH
    *stk++ = 0;                      // for push R0
    *stk++ = ((INT16U)p_arg) & 0xff; // for push R1  LOW(p_arg)
    *stk++ = ((INT16U)p_arg) >> 8;   // for push R2  , HIGH(p_arg)
    *stk++ = 0x1;                    // for push R3   , type of ptr
    *stk++ = 0;                      // for push R4
    *stk++ = 0;                      // for push R5
    *stk++ = 0;                      // for push R6
    *stk++ = 0;                      // for push R7

    return ptos;
}

void OSInitHookBegin(void) {}
void OSInitHookEnd(void) {}

void OSTaskCreateHook(OS_TCB *ptcb) { (void)ptcb; }
void OSTaskDelHook(OS_TCB *ptcb) { (void)ptcb; }

void OSTaskIdleHook(void) {}

void OSTaskReturnHook(OS_TCB *ptcb) { (void)ptcb; }

void OSTaskStatHook(void) {}

void OSTCBInitHook(OS_TCB *ptcb) { (void)ptcb; }
void OSTimeTickHook(void) {}

添加四个源文件 os_cpu_asm_OSCtxSw.c,os_cpu_asm_OSIntCtxSw.c,os_cpu_asm_OSStartHighRdy.c,os_cpu_asm_OSTimerISR.c分别来实现OSCtxSw,OSIntCtxSw,OSStartHighRdy,OSTimerISR; 并且均配置生成RSC文件
在这里插入图片描述
到时个在生成的SRC文件上修改,要更加方便一点


在os_core.c 中可以看到以下代码

/*$PAGE*/
/*
*********************************************************************************************************
*                                          START MULTITASKING
*
* Description: This function is used to start the multitasking process which lets uC/OS-II manages the
*              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
*              and you MUST have created at least one task.
*
* Arguments  : none
*
* Returns    : none
*
* Note       : OSStartHighRdy() MUST:
*                 a) Call OSTaskSwHook() then,
*                 b) Set OSRunning to OS_TRUE.
*                 c) Load the context of the task pointed to by OSTCBHighRdy.
*                 d_ Execute the task.
*********************************************************************************************************
*/

void  OSStart (void)
{
    if (OSRunning == OS_FALSE) {
        OS_SchedNew();                               /* Find highest priority's task priority number   */
        OSPrioCur     = OSPrioHighRdy;
        OSTCBHighRdy  = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run    */
        OSTCBCur      = OSTCBHighRdy;
        OSStartHighRdy();                            /* Execute target specific code to start task     */
    }
}

大致明白OSStartHighRdy 应该要实现什么
在os_cpu_asm_OSStartHighRdy.c写下

#include <REGX52.H>
#ifndef  OS_MASTER_FILE
#include <ucos_ii.h>
#endif

void OSStartHighRdy(void){
	INT8U* stkptr;
	INT8U len;
	INT8U idx;
	INT8U dat;
#if OS_TASK_SW_HOOK_EN > 0u
	OSTaskSwHook();  
#endif
	OSRunning = OS_TRUE;
	stkptr = (INT8U*)(OSTCBHighRdy->OSTCBStkPtr);
	len = *(INT8U*)stkptr;
	for(idx = 0u + sizeof(len);idx < len; ++idx)
	{
		dat = stkptr[idx];
	}
}

在keil里开启输出汇编
在这里插入图片描述
然后再SRC文件改一下,加入到工程中来
在这里插入图片描述

把任务堆栈映像到系统堆栈来,然后popall把系统堆栈里的内容恢复到CPU里面去,利用RETI指令跳转到任务函数中去。



现在编译一下,出现了 error C249: 'DATA': SEGMENT TOO LARGE,可以试着把编译内存模式改为大型
在这里插入图片描述


to be continue …


http://www.kler.cn/a/502419.html

相关文章:

  • Linux下部署Redis(本地部署超详细)
  • Vue2+OpenLayers调用WMTS服务初始化天地图示例(提供Gitee源码)
  • ElasticSearch在Windows环境搭建测试
  • 嵌入式系统中的 OpenCV 与 OpenGLES 协同应用
  • 网络应用技术 实验七:实现无线局域网
  • js前序遍历等
  • 掌握 Ubuntu 终端 mv 与 rename 命令的高效重命名使用方法
  • STM32-笔记42-实时时钟项目
  • uniapp 抖音小程序 getUserProfile:fail must be invoked by user tap gesture
  • CMake学习笔记(1)
  • 开源免费的下载工具AB Download Manager
  • 中等难度——python实现电子宠物和截图工具
  • 概率输出和独热分割掩码的主要区别:
  • 每日学习30分轻松掌握CursorAI:Cursor基础设置与配置
  • 商用服务器密码机的加密技术与优势
  • Win32汇编学习笔记11.游戏辅助的实现
  • fft分析数据求bode图原理
  • 【SQL】进阶知识 -- 删除表的几种方法(包含表内单个字段的删除方法)
  • html5各行各业官网模板源码下载 (4)
  • 初识@ffmpeg/ffmpeg库
  • Docker启动失败 - 解决方案
  • JavaScript 学习总结
  • linux设置http,https代理
  • 系统看门狗配置--以ubuntu为例
  • 数据分析-使用Excel透视图/表分析禅道数据
  • linux网络 | 深度理解https加密过程 | 模拟设计方案