GNU ARM汇编--(十四)GNU ARM汇编下做任务调度
时间:11-26
来源:互联网
点击:
以前工作中用过arm7,没有MMU,也没有用任何OS.现在回忆当时的代码结构,我觉得可以叫无限循环的有限状态机.arm7不跑OS,就相当于单片机,单片机跑的肯定是无限死循环.有限状态机是因为整个代码要处理很多外部的事情,那就是大的循环里面来套小循环,以轮询的方式来检查外界的变化,然后系统作出变化,系统在有限的状态中切换.
OS的一个标识就是支持多任务的并发.比方说linux,我们看起来是多个进程在同时运行,实际上还是cpu运行一下这个进程,再运行一下其他进程.这个就涉及到上下文切换以及进程调度的算法.当然我这里说的是单核的情况,如果是SMP的话,可能有些区别.暂时也没研究linux下的进程调度,但是通过自己写个最简单的任务调度可以理解任务调度是个什么回事.其实说到底任务调度就是那么回事.据说linux的最初版本,就是两个任务在不停的打印AB...
硬件平台是s3c2440:
利用RTC的Tick中断,在中断处理中进行任务的调度,调度算法采用最简单的轮循.
其中核心就是中断的写法,PCB的建立和任务调度中任务堆栈的保存和恢复:
调度的代码参考《ARM System Developers Guide》一书.
给出scheduler.S的代码:
[cpp]view plaincopy
- kernelScheduler:
- /*
- @---------------------------------------------------
- @RoundRobinScheduler
- @---------------------------------------------------
- */
- CurrentTask:
- ldrr3,=PCB_CurrentTask
- ldrr0,[r3]
- ldrr1,=PCB_Table
- ldrr1,[r1,r0,LSL#2]
- ldrr2,=PCB_PtrCurrentTask
- strr1,[r2]
- /*
- @**PCB_PtrCurrentTask-updatedwiththenewaddress
- */
- NextTask:
- addr0,r0,#1
- cmpr0,#3
- moveqr0,#0
- strr0,[r3]
- ldrr1,=PCB_Table
- ldrr1,[r1,r0,LSL#2]
- ldrr0,=PCB_PtrNextTask
- strr1,[r0]
- /*
- @**PCB_PtrCurrentTask=currentPCB
- @**PCB_PtrNextTask=nextPCB
- @**PCB_CurrentTask=newTASK_ID
- @------------------------------------------------------
- @ContextSwitch
- @------------------------------------------------------
- */
- handler_contextswitch:
- ldmfdsp!,{r0-r12,r14}
- ldrr13,=PCB_PtrCurrentTask
- ldrr13,[r13]
- subr13,r13,#60
- stmiar13,{r0-r14}^
- mrsr0,SPSR
- stmdbr13,{r0,r14}
- ldrr13,=PCB_PtrNextTask
- ldrr13,[r13]
- subr13,r13,#60
- ldmdbr13,{r0,r14}
- msrspsr_cxsf,r0
- ldmiar13,{r0-r14}^
- ldrr13,=PCB_TopOfIRQStack
- ldrr13,[r13]
- movspc,r14
- .end
一共写了3个静态任务,第一个任务做一个简单的算术运算,第二个任务是一个流水灯,而第三个任务是利用蜂鸣器来产生旋律.
仅贴出第三个任务的代码:
[cpp]view plaincopy
- .text
- .globalEntryTask3
- Feq_Table:
- .word20
- .word40
- .word60
- .word80
- .word100
- .word120
- .word140
- .word160
- .word180
- .word200
- .word220
- .word240
- CurrentFeq:
- .word0x0
- task3_delay:
- ldrr3,=0xffffff
- task3_delay1:
- subr3,r3,#1
- cmpr3,#0x0
- bnetask3_delay1
- movpc,lr
- EntryTask3:
- loopfeq:
- ldrr1,=TCON
- ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(man_update<1)|(stop<0)
- strr2,[r1]
- ldrr2,=GPBCON
- ldrr1,[r2]
- //ldrr1,=0x15400
- bicr1,r1,#0x3
- orrr1,r1,#0x2
- strr1,[r2]
- ldrr1,=TCFG0
- ldrr2,=(Prescaler0<0)
- strr2,[r1]
- ldrr1,=TCFG1
- ldrr2,=(DMA_MODE<20)|(MUX0<0)
- strr2,[r1]
- ldrr3,=CurrentFeq
- ldrr0,[r3]
- ldrr4,=Feq_Table
- ldrr4,[r4,r0,LSL#2]@用r4存放table中的值
- addr0,r0,#1
- cmpr0,#12
- moveqr0,#0
- strr0,[r3]
- ldrr1,=TCNTB0
- //ldrr4,=100
- strr4,[r1]
- movr4,r4,LSR#2
- ldrr1,=TCMPB0
- //ldrr4,=25
- strr4,[r1]
- ldrr1,=TCON
- ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(man_update<1)|(start<0)
- strr2,[r1]
- ldrr1,=TCON
- ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(clear_man_update<1)|(start<0)
- strr2,[r1]
- bltask3_delay
- bloopfeq
整个编译出来不到2K,直接在4K的sram中跑.看到的就是led在流水,蜂鸣器在各种频率.忽然想到了“落霞与孤鹜齐飞”.有了任务调度,看起来还是很美的.
下一步,利用MMU的MPU功能,改进这个任务调度,并且任务是单独编译的.总大小应该不会超过4K,这样我就暂时不用看Nandflash的datasheet了.不过迟早是要看的.......
ARM汇编任务调 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)