星空网 > 软件开发 > 操作系统

嵌入式:UCOSIII的使用

0、一些移植、系统相关 

OS_CFG_APP.H

                              /* --------------------- MISCELLANEOUS ------------------ */#define OS_CFG_MSG_POOL_SIZE      100u        /* 消息池 大小                         */#define OS_CFG_ISR_STK_SIZE       128u        /* Stack size of ISR stack (number of CPU_STK elements)  */#define OS_CFG_TASK_STK_LIMIT_PCT_EMPTY 10u        /* Stack limit position in percentage to empty      */                              /* ---------------------- IDLE TASK --------------------- */#define OS_CFG_IDLE_TASK_STK_SIZE    128u        /* 空闲任务 堆栈空间大小   (一般不做修改)          */                              /* ------------------ ISR HANDLER TASK ------------------ */#define OS_CFG_INT_Q_SIZE        10u        /* 中断服务队列 大小                      */#define OS_CFG_INT_Q_TASK_STK_SIZE   128u        /* 中断服务队列 堆栈空间大小(一般不做修改)           */                              /* ------------------- STATISTIC TASK ------------------- */#define OS_CFG_STAT_TASK_PRIO   (OS_CFG_PRIO_MAX-2u)   /* 统计任务 优先级     (一般不做修改)           */#define OS_CFG_STAT_TASK_RATE_HZ     10u        /* 统计任务频率 (1 to 10 Hz)                 */#define OS_CFG_STAT_TASK_STK_SIZE    128u        /* 统计任务 堆栈空间大小  (一般不做修改)           */                              /* ------------------------ TICKS ----------------------- */#define OS_CFG_TICK_RATE_HZ      200u        /* 时钟节拍频率 200HZ = 5ms (10 to 1000 Hz)        */#define OS_CFG_TICK_TASK_PRIO       1u        /* 时钟节拍优先级,一般设置一个相对较高的优先级          */#define OS_CFG_TICK_TASK_STK_SIZE    128u        /* 时钟节拍堆栈空间大小   (一般不做修改)           */#define OS_CFG_TICK_WHEEL_SIZE      17u        /* Number of 'spokes' in tick wheel; SHOULD be prime   */                              /* ----------------------- TIMERS ----------------------- */#define OS_CFG_TMR_TASK_PRIO       2u        /* 软件定时器优先级				        */#define OS_CFG_TMR_TASK_RATE_HZ     100u        /* 软件定时器频率 100HZ = 10ms,不能小于心跳时钟节拍      */#define OS_CFG_TMR_TASK_STK_SIZE    128u        /* 软件定时器堆栈空间大小  (一般不做修改)          */#define OS_CFG_TMR_WHEEL_SIZE      17u        /* Number of 'spokes' in timer wheel; SHOULD be prime   */

 

OS_CFG.H:功能性裁剪

OS_APP_HOOKS.C:钩子函数

OS_CPU_A.ASM:PendSV中断、任务切换

OS_CPU_C.C: OSTaskStkInit函数,任务创建时,对堆栈初始化,寄存器地址要参照手册

 

 

1、框架写法(个人习惯相关)

1-1、main 函数里创建一个开始任务

int main(void){	OS_ERR err;	CPU_SR_ALLOC();		初始化外设		OSInit(&err);	      //初始化UCOSIII	OS_CRITICAL_ENTER();    //进入临界区	OSTaskCreate();       //创建开始任务 	OS_CRITICAL_EXIT();    //退出临界区 	OSStart(&err);       //开启UCOSIII    while(1);}  

1-2、开始任务里,创建我们要运行的多个任务

void start_task(void *p_arg){	OS_ERR err;	CPU_SR_ALLOC();	p_arg = p_arg;	CPU_Init();	#if OS_CFG_STAT_TASK_EN > 0u      //统计任务  OSStatTaskCPUUsageInit(&err);             #endif	#ifdef CPU_CFG_INT_DIS_MEAS_EN	    //测量中断关闭时间  CPU_IntDisMeasMaxCurReset();	#endif	#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //时间片轮转	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);    //时间片长度为1个系统时钟节拍,既1*5=5ms#endif				OS_CRITICAL_ENTER();	    //进入临界区		OSTaskCreate(); 	    //创建任务	1			OSTaskCreate(); 	    //创建任务	2		 	OSTaskCreate(); 	    //创建任务	3	 	OS_CRITICAL_EXIT();	    //进入临界区		OSTaskDel((OS_TCB*)0,&err);  //删除start_task任务自身}  

  

2、任务创建、挂起、删除

2-1、任务创建

//==================任务创建宏定义,便于修改==================#define START_TASK_PRIO		3		//任务优先级#define START_STK_SIZE 		128		//任务堆栈大小OS_TCB StartTaskTCB;				//任务控制块CPU_STK START_TASK_STK[START_STK_SIZE];	     //任务堆栈	void start_task(void *p_arg);			//任务函数//==================任务创建函数==================OSTaskCreate((OS_TCB 	* )&StartTaskTCB,	//任务 控制块	   (CPU_CHAR	* )"start task", 	//任务 名字	   (OS_TASK_PTR )start_task, 		//任务 函数	   (void	* )0,			//任务 任务函数的参数	   (OS_PRIO	 )START_TASK_PRIO,   //任务 优先级	   (CPU_STK  * )&START_TASK_STK[0],	//任务 堆栈基地址	   (CPU_STK_SIZE)START_STK_SIZE/10,	//任务 堆栈深度限位	   (CPU_STK_SIZE)START_STK_SIZE,	//任务 堆栈大小	   (OS_MSG_QTY )0,			//任务 内部消息队列能够接收的最大消息数目,为0时禁止接收消息	   (OS_TICK	 )0,			//任务 使用时间片轮转,时间片长度,为0时为默认长度,	   (void  	*)0,			//任务 用户补充的存储区	   (OS_OPT   )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,   //任务 选项	   (OS_ERR 	*)&err);		//任务 创建成功与否

2-2、任务挂起

OSTaskSuspend((OS_TCB*)&Task1TaskTCB,&err);		//挂起开始任务

2-3、任务解挂

OSTaskResume((OS_TCB*)&Task1TaskTCB,&err);  //任务解挂

2-4、任务删除

OSTaskDel((OS_TCB*)0,&err);	//删除start_task任务自身

 

3、时间片轮转

3-1、两个任务优先级相等

#define Task0_Task_Prio		4        //优先级4#define Task0_Stk_Size		128OS_TCB Task0TaskTCB;CPU_STK Task0_Task_Stk[Task0_Stk_Size];void Task0Task(void *p_arg);#define Task1_Task_Prio		4        //优先级4#define Task1_Stk_Size		128OS_TCB Task1TaskTCB;CPU_STK Task1_Task_Stk[Task1_Stk_Size];void Task1Task(void *p_arg); 

3-2、使能轮转调度,调用API,设置单位时间

#if	OS_CFG_SCHED_ROUND_ROBIN_EN   //使用时间片轮转	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); //时间片长度为1个系统时钟节拍,既1*5=5ms	#endif	

3-3、创建任务时,设置任务的时间片大小

OSTaskCreate((OS_TCB 	* )&Task1TaskTCB,					 (CPU_CHAR	* )"Task1 task", 					 (OS_TASK_PTR )Task1Task, 						 (void		* )0,								 (OS_PRIO	 )Task1_Task_Prio,   				 (CPU_STK  * )&Task1_Task_Stk[0],				 (CPU_STK_SIZE)Task1_Stk_Size/10,				 (CPU_STK_SIZE)Task1_Stk_Size,					 (OS_MSG_QTY )0,								 (OS_TICK	 )2,						//时间片长度为2*5=10ms								 (void  	* )0,							 (OS_OPT   )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 			 (OS_ERR 	* )&err);	

 

4、钩子函数。函数指针,UCOS不希望我们去修改他的文件,弄了钩子函数,比如 App_OS_IdleTaskHook ,在空闲时运行这个函数,功能自己填写。

4-1、使能钩子函数功能,并设置所有函数指针

#if OS_CFG_APP_HOOKS_EN > 0u	  //使能钩子函数	App_OS_SetAllHooks();			#endif

4-2、在 os_app_hooks.c 里的 App_OS_*Hook,里面填写你要的功能。

void App_OS_IdleTaskHook (void){	static int num ;	num++;        //计算运行了多少次空闲任务}

 

5、软件定时器

5-1、软件定时器创建

//==============定时器结构体、函数声明==============OS_TMR Timer0;void timer0CallBack(void *p_tmr, void *p_arg);//==============定时器创建==============//创建定时器0任务OSTmrCreate (  (OS_TMR			*)&Timer0,		//定时器 结构体		(CPU_CHAR		*)"time0",		//定时器 名字		(OS_TICK		 )10,			//定时器 初次延时节拍 10*10 = 100ms		(OS_TICK		 )100,			//定时器 以后延时节拍 100*10 = 1000ms = 1s		(OS_OPT			 )OS_OPT_TMR_PERIODIC,	//定时器 选项 : 单次 或 周期。		(OS_TMR_CALLBACK_PTR	 )timer0CallBack,	//定时器 回调函数,伪中断服务函数		(void			*)0,			//定时器 中断服务函数的参数		(OS_ERR			*)&err);		//定时器 创建成功与否

5-2、定时器“中断服务函数”,回调函数

void timer0CallBack(void *p_tmr, void *p_arg){	//do something}

 

6、信号量

6-1、信号量创建

OSSemCreate (  (OS_SEM   *)&mySem,		//信号量 结构体		(CPU_CHAR  *)"semtest",	//信号量 名字		(OS_SEM_CTR  )1,		//信号量 初始值,		(OS_ERR   *)&err);		//信号量 创建成功是否

6-2、信号量等待

OSSemPend ((OS_SEM  *)&mySem,			//信号量 结构体	  (OS_TICK  )0,			//信号量 等待超时时间	  (OS_OPT  )OS_OPT_PEND_BLOCKING,	//信号量 阻塞 或 不阻塞	  (CPU_TS  *)0,			//信号量 时间戳	  (OS_ERR  *)&err);			//信号量 等待错误

6-3、信号量发送

OSSemPost ((OS_SEM *)&mySem,		//信号量 结构体	  (OS_OPT  )OS_OPT_POST_1,	//信号量 给就绪最高优先级	  (OS_ERR *)&err);		//信号量 等待错误

 

用途:   1、访问共享资源。

    2、中断发送信号,让处理在任务。

 

7、任务内建信号量

7-1、等待自身的信号量

OSTaskSemPend ( (OS_TICK  )0,				//内建信号量 超时时间		(OS_OPT  )OS_OPT_PEND_BLOCKING,	//内建信号量 阻塞 或 不阻塞			(CPU_TS  *)0,				//内建信号量 时间戳		(OS_ERR  *)&err);			//内建信号量 等待错误

7-2、其他任务,给等待内建信号量的任务发送信号量

OSTaskSemPost ( (OS_TCB *)&Task0TaskTCB,	//内建信号量 等待的任务		(OS_OPT  )OS_OPT_POST_NONE,	//内建信号量 调度 或 不调度		(OS_ERR *)&err);		//内建信号量 等待错误

 

8、互斥信号量

8-1、互斥信号量创建

OSMutexCreate ( (OS_MUTEX 	*)&myMutex,	//互斥信号量 结构体		(CPU_CHAR	*)"Mutextest",	//互斥信号量 名字		(OS_ERR   *)err);		//互斥信号量 创建错误

8-2、互斥信号量等待

OSMutexPend (  (OS_MUTEX	*)&myMutex,		//互斥信号量 结构体		(OS_TICK  )0,				//互斥信号量 等待超时时间		(OS_OPT   )OS_OPT_PEND_BLOCKING,	//互斥信号量 阻塞 或 不阻塞		(CPU_TS  	*)0,			//互斥信号量 时间戳		(OS_ERR  	*)&err);		//互斥信号量 等待错误

8-3、互斥信号量发送

OSMutexPost ( (OS_MUTEX *)&myMutex,		//互斥信号量 结构体	    (OS_OPT  )OS_OPT_POST_NONE,	//互斥信号量 调度 或 不调度	    (OS_ERR *)&err);		//互斥信号量 发送错误

  

用途:防止优先级反转,如:2个任务共享一个资源,而,两者的优先级,中间隔着多个优先级(任务)。高优先级 等待 低优先级 释放,而,低优先级 此时又被 中等优先级 打断,变成 高优先级 要等 中等优先级。

用互斥信号的话,此时 低优先级 ,会暂时提高到共享资源的 高优先级 级别。不会被中等优先级打算。处理完,降回 低优先级 ,高优先级接着访问。再 中等优先级。

 

发现:1、高优先级 等待时, 低优先级用OSSched(); 此时达到预计效果,不会被 中等优先级抢占。

     2、高优先级 等待时,低优先级用OSTimeDlyHMSM();延时指令,此时,会被中等优先级抢占。

 

9、消息队列

9-1、消息队列创建

//================消息队列宏定义================OS_Q my_MSG_Q;#define my_MSG_QTY	(OS_MSG_QTY)5//================消息队列创建================OSQCreate ( (OS_Q    *)&my_MSG_Q,	     //消息队列 结构体	  (CPU_CHAR  *)"MSG_Q_Test",  	//消息队列 名字	  (OS_MSG_QTY  )my_MSG_QTY,		//消息队列 大小	  (OS_ERR   *)&err);		//消息队列 创建错误

9-2、消息发送

u8 *MSG = (u8 *)"testtet";	OSQPost (  (OS_Q     *)&my_MSG_Q,		//消息队列 结构体	  (void     *)MSG,			//消息队列 发送的消息	  (OS_MSG_SIZE  )8,			//消息队列 发送的消息大小	  (OS_OPT    )OS_OPT_POST_FIFO,	//消息队列 发送方式,普通FIFO,紧急LIFO,及发送给所有等待该消息、发送调度与否	  (OS_ERR    *)&err);		//消息队列 发送错误

9-3、消息接收

u8 *MSG;	u8 Q_size;			MSG = OSQPend ( (OS_Q     *)&my_MSG_Q,		//消息队列 结构体		(OS_TICK    )0,			//消息队列 等待超时		(OS_OPT    )OS_OPT_PEND_BLOCKING,	//消息队列 阻塞 或 不阻塞		(OS_MSG_SIZE *)&Q_size,		//消息队列 收到的大小		(CPU_TS    *)0,			//消息队列 时间戳		(OS_ERR    *)&err);			//消息队列 接收错误

 

10、任务内建消息队列

10-1、内建消息队列发送

u8 *MSG = (u8 *)"testtet";OSTaskQPost (  (OS_TCB    *)&MSG_Q_TaskTCB,	  //内建消息队列 接收的任务						(void     *)MSG,		  //内建消息队列 发送的消息		(OS_MSG_SIZE  )8,		  //内建消息队列 发送的消息大小		(OS_OPT    )OS_OPT_POST_FIFO,  //内建消息队列 发送方式,普通FIFO,紧急LIFO,及发送给所有等待该消息、发送调度与否		(OS_ERR    *)&err);		  //内建消息队列 发送错误

10-2、内建消息队列接收

u8 *MSG;u8 Q_size;		MSG = OSTaskQPend (	(OS_TICK		)0,		//内建消息队列 等待超时			(OS_OPT    )OS_OPT_PEND_BLOCKING,	//内建消息队列 阻塞 或 不阻塞			(OS_MSG_SIZE *)&Q_size,		//内建消息队列 收到的大小			(CPU_TS    *)0,			//内建消息队列 时间戳			(OS_ERR    *)&err);			//内建消息队列 接收错误	

  

11、标记位组

11-1、标记位组创建

OS_FLAG_GRP my_FLAG;#define FLAG_INIT	0x00#define FLAG_BIT0	0x01#define FLAG_BIT1	0x02OSFlagCreate (	(OS_FLAG_GRP *)&my_FLAG,	//标记位组 结构体		(CPU_CHAR   *)"Flag test",	//标记位组 名字		(OS_FLAGS   )FLAG_INIT,	//标记位组 标记初始值		(OS_ERR    *)&err);		//标记位组 创建成功与否

11-2、标记位组发送

OSFlagPost ((OS_FLAG_GRP *)&my_FLAG,			//标记位组 结构体	   (OS_FLAGS   )FLAG_BIT0,			//标记位组 bit0	   (OS_OPT    )OS_OPT_POST_FLAG_SET,	//标记位组 置1	   (OS_ERR    *)&err);			//标记位组 bit0 置 1 成功与否

11-3、标记为组等待

OS_FLAGS index;		index = OSFlagPend ((OS_FLAG_GRP *)&my_FLAG,		  //标记位组 结构体		  (OS_FLAGS   )FLAG_BIT0 | FLAG_BIT1, //标记位组 等待的BIT位		  (OS_TICK    )0,			  //标记位组 等待超时时间		  (OS_OPT    )OS_OPT_PEND_FLAG_SET_ANY | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING,	  //标记位组 任意1个Bit置1,接收后清0,阻塞		  (CPU_TS    *)0,			  //标记位组 时间戳		  (OS_ERR    *)&err);		  //标记位组 等待错误

  

12、多个内核对象

12-1、多个内核对象 创建

//=================多个内核对象 结构体=================OS_SEM my_Sem1;OS_SEM my_Sem2;OS_Q my_Q1;#define my_Q1_SIZE	5	//=================多个内核对象 创建=================OSSemCreate (	(OS_SEM   *)&my_Sem1,		(CPU_CHAR  *)"sem1 test",		(OS_SEM_CTR  )0,		(OS_ERR   *)&err);OSSemCreate (	(OS_SEM   *)&my_Sem2,		(CPU_CHAR  *)"sem2 test",		(OS_SEM_CTR  )0,		(OS_ERR   *)&err);								OSQCreate (	(OS_Q    *)&my_Q1,        (CPU_CHAR  *)"my_Q1",        (OS_MSG_QTY  )my_Q1_SIZE,        (OS_ERR   *)&err);

12-2、等待多个内核对象

//===============多个内核对象 宏定义===============#define MY_OBJ_NUM 3					//多个内核对象 等待数量	//===============多个内核对象 等待===============OS_PEND_DATA my_OBJ_data[MY_OBJ_NUM];	//多个内核对象 数组	my_OBJ_data[0].PendObjPtr = (OS_PEND_OBJ *)&my_Sem1;	//多个内核对象 对象0my_OBJ_data[1].PendObjPtr = (OS_PEND_OBJ *)&my_Sem2;	//多个内核对象 对象1my_OBJ_data[2].PendObjPtr = (OS_PEND_OBJ *)&my_Q1;	//多个内核对象 对象2	my_return_data = OSPendMulti (	(OS_PEND_DATA *)my_OBJ_data,	    //多个内核对象 对象数组				(OS_OBJ_QTY   )MY_OBJ_NUM,	    //多个内核对象 对象数量				(OS_TICK    )0,		    //多个内核对象 等待超时时间				(OS_OPT     )OS_OPT_PEND_BLOCKING,	//多个内核对象 阻塞 或 不阻塞				(OS_ERR    *)&err);			//多个内核对象 等待错误

 

12-3、多个内核对象 发送

任意对象 post ,都会结束等待

 

13、内存管理

13-1、内存创建

//==================内存 宏定义==================OS_MEM IN_MEM;#define IN_MEM_Block	5			//必须大于2#define IN_MEM_Zone		25 * 4		//必须大于4,且为4的倍数,存放下一块的地址内容,4字节CPU_INT08U IN_MEM_DATA[IN_MEM_Block][IN_MEM_Zone];//==================内存 创建==================OSMemCreate ( (OS_MEM    *)&IN_MEM,			//内存 结构体        (CPU_CHAR   *)"IN_MEM",		//内存 名字        (void     *)&IN_MEM_DATA[0][0],	//内存 基地址        (OS_MEM_QTY  )IN_MEM_Block,		//内存 几个块,一维数组        (OS_MEM_SIZE  )IN_MEM_Zone,		//内存 每个块大小,二维数组        (OS_ERR    *)&error);			//内存 创建成功与否

13-2、内存申请

u8 *p;p = OSMemGet (	(OS_MEM *)&IN_MEM,	//内存 结构体		(OS_ERR *)&err);	//内存 申请成功与否

13-3、内存释放

OSMemPut ( (OS_MEM *)&IN_MEM,	  //内存 结构体	  (void  *)p,	  //内存 要释放的地址	  (OS_ERR *)&err);	  //内存 释放成功与否

 

备注:内存有申请,必释放,如果申请后,不释放,再申请,那之前申请的地址就找不到了,因为你的指针地址变了。

    所以,如果要多次申请的话,1、还要弄个指针数组,2、或者普通数组来存放当前申请的地址,3、或者知道UCOS的内存管理机制,直接去内存数组里找到地址。

 

 

暂时就这样,以后再检查修改,手酸。

 




原标题:嵌入式:UCOSIII的使用

关键词:

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。

3步让你快速找到小红书蓝海词:https://www.kjdsnews.com/a/1431060.html
一键解锁ChatGPT原理与应用:https://www.kjdsnews.com/a/1431061.html
如何搭建电商复购数据模型?:https://www.kjdsnews.com/a/1431062.html
抖音脚本怎么写?抖音脚本写作技巧:https://www.kjdsnews.com/a/1431063.html
TIKTOK跨境MCN怎么提现?:https://www.kjdsnews.com/a/1431064.html
青瓜早报:网信部门工作组进驻斗鱼;淄博第一季度GDP超1000亿元…:https://www.kjdsnews.com/a/1431065.html
深圳到西安自驾路线攻略 深圳到西安自驾最佳路线:https://www.vstour.cn/a/411228.html
松花蛋是哪里的特产松花蛋的产地:https://www.vstour.cn/a/411229.html
相关文章
我的浏览记录
最新相关资讯
海外公司注册 | 跨境电商服务平台 | 深圳旅行社 | 东南亚物流