完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
STM8S移植μC/OS-II 广东海洋大学 科创 刘平山 2011/12 μC/OS-II相信大家都很熟悉了,是由美国嵌入式系统专家JeanJ.Labrosse 一种可移植的,可植入ROM的,可裁剪的,抢占式的,实时多任务操作系统内核。它被广泛应用于微处理器、微控制器和数字信号处理器。包含了任务调度,任务管理,时间管理,内存管理和任务间的通信和同步等基本功能。μC/OS-II可移植到几乎所有微处理器上面允许,既有执行效率高、实时性强、任务切换快的特点,版本从2.00到2.85,下面就以移植2.85为例,在STVD编译环境下移植到最新的ST意法半导体公司生产的STM8SMCU。 STM8S基本特点:8位CPU内核,3级流水线的哈佛结构,内核有6个寄存器,并拥有16位指令,指令执行速率可达0.8Mips/Mhz以上,24位的PC寻址空间可达16M,16位的SP寻址空间可达64KB,拥有不可屏蔽的软中断,由于这些特点使得移值操作系统成为了可能。 缺点是CPU内核没有通用寄存器,使得很多运算都要暂存在RAM里边,RAM的划分变得复杂,在STVD编译环境下,采用的方法是利用堆栈来处理临时性变量,全局变量放在RAM的最低处,这种方法很巧妙,但会使得RAM的使用无规则,在IAR环境下,采用的是在RAM划分一个区域来充当通用寄存器使用。为了在STVD下移植μC/OS-II,不仅要清楚CPU的内部原理,还要认识STVD的编译原理。 一、移植步骤如下:第一步:OS数据类型定义typedef unsignedchar OS_STK; typedef unsignedchar BOOLEAN; typedef unsignedchar INT8U; typedef signed char INT8S; typedef unsignedint INT16U; typedef signed int INT16S; typedef unsignedlong INT32U; typedef signed long INT32S; typedef float FP32; typedef double FP64; #defineBYTE INT8S #defineUBYTE INT8U #defineWORD INT16S #defineUWORD INT16U #defineLONG INT32S #defineULONG INT32U 第二步:定义与处理器有关的声明#define OS_CRItiCAL_METHOD 2 #if OS_CRITICAL_METHOD==1 #define OS_ENTER_CRITICAL() _asm("SIM"); #define OS_EXIT_CRITICAL() _asm("RIM"); #endif #if OS_CRITICAL_METHOD==2 #define OS_ENTER_CRITICAL() save_cpusr(); #define OS_EXIT_CRITICAL() restore_cpusr(); #endif #define OS_STK_GROWTH 1 #define OS_TASK_SW() _asm("TRAP"); 第三步:编写底层函数之一【系统开始运行最高优先级的任务】voidOSStartHighRdy(void) { OSTaskSwHook(); #asm LDWX,[_OSTCBCur.W] //获取最高优先级的SP指针值 LDWSP,X #endasm OSRunning=TRUE; EN_OS_CLK; //开定时器 #asm IRET #endasm } 第四步:编写底层函数之二【上下文任务切换函数】.TRAP中断服务函数@far@interruptvoidOSCtxSw(void) { #asm LDWX,SP ADDWX,#6 LDWSP,X POPA ANDA,#0XF7 PUSHA //堆栈指针调整 LDW[_OSTCBCur.W],X //保存堆栈指针 #endasm OSTaskSwHook(); OSTCBCur=OSTCBHighRdy; OSPrioCur=OSPrioHighRdy; #asm POPWX //堆栈调整 LDW0X07,X POP0X0009 POPWX LDW0X04,X POP0X0006 LDWX,[_OSTCBCur.W] //获取堆栈指针 LDWSP,X IRET #endasm } 第五步:编程底层函数之三【中断级任务切换函数】voidOSIntCtxSw(void) { #asm ADDWSP,#10 POPA ANDA,#0XF7 PUSHA LDWX,SP LDW[_OSTCBCur.W],X //堆栈指针调整和保存 #endasm OSTaskSwHook(); OSTCBCur=OSTCBHighRdy; OSPrioCur=OSPrioHighRdy; #asm POPWX LDW0X07,X POP0X0009 POPWX LDW0X04,X POP0X0006 LDWX,[_OSTCBCur.W] //堆栈调整和或者堆栈指针 LDWSP,X IRET #endasm } 第六步:编写底层函数之四【系统时钟函数】.使用定时器中断服务@far@interruptvoidOSTickISR(void) { TIM2->SR1=0X00; //清除定时器标志位 OSIntEnter(); OSTimeTick(); OSIntExit(); } 第七步:编写底层函数之五【堆栈初始化函数】OS_STK*OSTaskStkInit(void(*task)(void*p_arg),void*p_arg,OS_STK*ptos, INT16U opt) { OS_STK*stk; (void)opt; stk =ptos; *(stk) =(INT8U)((INT16U)task); //PCL *(--stk)=(INT8U)((INT16U)task>>8); //PCH *(--stk)=(INT8U)((INT32U)task>>16); //PCE *(--stk)=0X07; //YL *(--stk)=0X04; //YH *(--stk)=0X03; //XL *(--stk)=0X02; //XH *(--stk)=0X01; //A *(--stk)=0X20; //CC (--stk); return(stk); } 第八步:编写临界保护函数【其中MY_CPUSR要在μC/OS-II.H中声明的全局变量】voidsave_cpusr(void) { (INT8U)MY_CPUSR; _asm("PUSHCCnSIMnPOPAn"); _asm("LD_MY_CPUSR,A"); } voidrestore_cpusr(void) { _asm("LDA,_MY_CPUSRnPUSHAnPOPCC"); } 第九步:编写钩子函数(略)二、移植后文件结构图三、主函数char main(void) { System_Init();/*硬件系统初始化,特别提醒:不能开用于系统时钟的定时器*/ OSInit();/*调用OS初始化函数*/ …………/*任务创建等*/ rim();/*开中断*/ OSStart();/*开始调度*/ return (0); } 四、中断函数格式@far @Interrupt void ISR(void) { OSIntEnter(); use_sub();/*用户函数*/ OSIntExit(); } 由于STM8S的内核结构和STVD环境下的变量处理方式,在移植μC/OS-II难免会有点复杂,需要调整和计算好堆栈指针,临界保护函数也正因为STVD处理临时变量使用的是堆栈所以没有使用μC/OS-II中定义的临时cpu_sr,而使用了全局变量。经过试验在用多路高频外部中断触发下可以很稳定的运行,也证明了系统的稳定性和安全性。 限于篇幅,移植源文件不再详解,读者可以直接移植这些与处理器有关的函数,并在μC/OS-II.h内声明外部函数便可。支持STM8S、STM8L、STM8A的各种序列(推荐RAM>=2KB,flash>8KB)。 |
|
相关推荐
3 个讨论
|
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 21:59 , Processed in 0.663643 second(s), Total 60, Slave 46 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号