(1)自写zrtos,实现多任务,多优先级,支持消息邮箱,信号量等的简易操作系统
来源:互联网 发布:千里马计划软件官方 编辑:程序博客网 时间:2024/05/02 02:19
该系统是我在阅读了ucos后,并且借鉴了其它操作系统后实现的,完成了一些基础的工作,可以拿过来学习,也可以进行简单的应用。
声明:仅供学习!
要自写一个操作系统,我们首先要实现的就是任务切换,再其次是任务调度(高优先级先执行,同优先级时间片分割执行),然后再是消息邮箱,信号量,互斥量等等。
下面我们来看看任务切换的实现,这部分的代码只能由汇编语言来完成,在handler.s中有任务切换的具体代码:
我们的任务板是stm32,stm32是基于cortex-m3内核的,所以在写这个系统的时候很多参照了cortex-m3内核的文档,其中包括了pendsv中断向量,与中断压栈以及堆栈指针等方面。在设计中中断任务我们用的是msp堆栈指针,而我们的任务使用的是psp指针,我们在汇编代码中开启了psp指针的使用以后就,cpu就会自动的进行切换了:
开全局与关全局中断的代码:
enter_intexport enter_intCPSID I ;PRIMASK=1 关中断BX LR ;返回exit_intexport exit_intCPSIE I;开中断BX LR ;返回
第一次启动操作系统,我们往往需要初始化psp指针,设置pendsv中断为最低的优先级,然后开始一次调度:
;开启操作系统start_osprocexport start_osCPSID I ;首先设置pendsv为最低优先级;设置pendsv的中断优先级ldr r0,=0xE000ED22;最低优先级ldr r1,=0xff;设置strb r1,[r0];设置psp为0,用于判断是否第一次任务调度MOVS R0, #0 ;R0 = 0MSR PSP, R0 ;PSP = R0;开启pendsv中断LDR R0, =0xE000ED04 ;R0 = 0xE000ED04LDR R1, =0x10000000 ;R1 = 0x10000000;设置触发STR.w R1, [R0] ;*(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET;打开中断CPSIE I ;;死循环os_start_hang B os_start_hangendp
软件开启pendsv中断的代码:
;出发pendsv中断,以便进行中断调度open_scheduling procexport open_schedulingpush {r0-r4,lr}LDR R0, =0xE000ED04LDR R1, =0x10000000 ;进入pendsv中断STR R1, [R0]pop {r0-r4,pc}endp
最后就死pendsv中断中的代码:
;pendsv中断PendSV_Handler PROC EXPORT PendSV_Handler REQUIRE8 ; 加这两条对齐伪指令防止链接器报错PRESERVE8 ; 8 字对齐;中断调度时不能被打断,这里关闭中断 cpsid I;获得sp指针的值MRS R0, PSP ;R0 = PSP;如果第一次执行,则执行一次中断调度CBZ R0, thread_change ;不是第一次则保护r4-r11SUBS R0, R0, #0x20 ;R0 -= 0x20STM R0, {R4-R11} ;;保存本次的栈顶地址ldr r1,=task_mem_ldr r1,[r1]str R0,[r1]thread_change;任务调度push {lr}ldr.w r0,=task_swblx r0pop {lr}LDM R0, {R4-R11} ;恢复新的r4-r11的值ADDS R0, R0, #0x20 ;R0 += 0x20MSR PSP, R0;切换到用户线程模式;lr 的第2位为1时自动切换ORR LR, LR, #0x04 ;开中断cpsie IBX LR ENDP
下面是最最重要的,任务调度器,任务调度器主要是找到最高优先级的任务,并且轮询调度,还要保存要运行的任务的控制块,在task.c中:
//任务调度函数void *task_sw(void){uint32 i=0;TASK_TCB *max_TASK_TCB=TASK_TCB_LIST[0];static TASK_TCB *back_task_tcb=null;//查找没有通优先级的if(back_task_tcb!=null){uint32 spotted=0;for(i=0;i<TASK_TCB_NUM;i++){if(back_task_tcb==TASK_TCB_LIST[i]){spotted=1;continue;}//确保是没有被调度过的任务if(spotted==1){if(TASK_TCB_LIST[i]!=null&&back_task_tcb->level==TASK_TCB_LIST[i]->level){max_TASK_TCB=TASK_TCB_LIST[i];goto step;}}}}for(i=0;i<TASK_TCB_NUM;i++){if(TASK_TCB_LIST[i]!=null){if(TASK_TCB_LIST[i]->status==true&&//任务没有被延时TASK_TCB_LIST[i]->delay_count==0){if(max_TASK_TCB==null){max_TASK_TCB=TASK_TCB_LIST[i];continue;}//获取优先级最高的if(max_TASK_TCB->level > TASK_TCB_LIST[i]->level){max_TASK_TCB=TASK_TCB_LIST[i];}}}}step://运行时间+1max_TASK_TCB->run_count++;//当前的堆栈task_mem_=&max_TASK_TCB->mem_task;//保存当前运行的tcbTCBIng=max_TASK_TCB;//保存上次获得的最大优先级back_task_tcb=max_TASK_TCB;//返回堆栈的地址return max_TASK_TCB->mem_task;}这就是zrtos的任务切换的核心部分,看了这些对rtos也算有一定的了解。请期待下一节,zrtos中API函数的使用。
0 0
- (1)自写zrtos,实现多任务,多优先级,支持消息邮箱,信号量等的简易操作系统
- (2)自写zrtos API详细解释
- vxworks中任务间的通信支持信号量、消息队列、管道、信号、事件、共享内存等
- vxworks中任务间的通信支持信号量、消息队列、管道、信号、事件、共享内存等
- vxworks中任务间的通信支持信号量、消息队列、管道、信号、事件、共享内存等
- 嵌入式操作系统之信号量,消息队列,邮箱的区别
- 操作系统算法:如何利用信号量实现优先级(从读者写者问题引发的联想)
- UCOS-II任务间通信(信号量、邮箱、消息队列)
- (转)ucos的事件 任务的通讯和同步 信号量 互斥量 消息邮箱 消息队列
- ucos2 事件 任务的通讯和同步 信号量 互斥量 消息邮箱 消息队列
- 自编STM32轻量级操作系统(四)------信号量的实现
- 自己写的简易多任务系统---基于pic18fxxx
- 自己写的简易多任务系统---基于pic18fxxx
- 双链表实现的消息队列,可支持优先级读取
- 用redis实现支持优先级的消息队列
- 用redis实现支持优先级的消息队列
- 用redis实现支持优先级的消息队列
- 用redis实现支持优先级的消息队列
- mybatis动态sql查询语法
- #181 Flip Bits
- 上海韬源信息技术有限公司怎么样
- 数据测试手札--------------------(3)
- 【9107】Hanoi双塔问题(NOIP2007)
- (1)自写zrtos,实现多任务,多优先级,支持消息邮箱,信号量等的简易操作系统
- 二维码的扫描
- 定制自己的Windows CE 5.0 ARM中文模拟器
- 在listview 与ScrollVIew 冲突
- 4443: [Scoi2015]小凸玩矩阵
- python中内建函数isinstance的用法
- jQuery的makeArray方法源码分析
- mybatis动态sql删除语法
- Java读取文件MD5的两种方案