GNU ARM汇编--(十四)GNU ARM汇编下做任务调度

        以前工作中用过arm7,没有MMU,也没有用任何OS.现在回忆当时的代码结构,我觉得可以叫无限循环的有限状态机.arm7不跑OS,就相当于单片机,单片机跑的肯定是无限死循环.有限状态机是因为整个代码要处理很多外部的事情,那就是大的循环里面来套小循环,以轮询的方式来检查外界的变化,然后系统作出变化,系统在有限的状态中切换.

        OS的一个标识就是支持多任务的并发.比方说linux,我们看起来是多个进程在同时运行,实际上还是cpu运行一下这个进程,再运行一下其他进程.这个就涉及到上下文切换以及进程调度的算法.当然我这里说的是单核的情况,如果是SMP的话,可能有些区别.暂时也没研究linux下的进程调度,但是通过自己写个最简单的任务调度可以理解任务调度是个什么回事.其实说到底任务调度就是那么回事.据说linux的最初版本,就是两个任务在不停的打印AB...

        硬件平台是s3c2440:

        利用RTC的Tick中断,在中断处理中进行任务的调度,调度算法采用最简单的轮循.

        其中核心就是中断的写法,PCB的建立和任务调度中任务堆栈的保存和恢复:

        调度的代码参考《ARM System Developer's Guide》一书.

        给出scheduler.S的代码:

        

kernelScheduler:
/*
@ ---------------------------------------------------
@ Round Robin Scheduler
@ ---------------------------------------------------
*/
CurrentTask:

     ldr     r3,=PCB_CurrentTask
     ldr     r0,[r3]      
     ldr     r1,=PCB_Table
     ldr     r1,[r1,r0,LSL#2]    
     ldr     r2,=PCB_PtrCurrentTask
     str     r1,[r2]    
/*
@ ** PCB_PtrCurrentTask - updated with the new address
*/
NextTask:
     add     r0,r0,#1  
     cmp     r0,#3
     moveq   r0,#0        
     str     r0,[r3]      
     ldr     r1,=PCB_Table
     ldr     r1,[r1,r0,LSL#2]    
     ldr     r0,=PCB_PtrNextTask
     str     r1,[r0]     
/*
@ ** PCB_PtrCurrentTask   = current PCB
@ ** PCB_PtrNextTask	  = next PCB
@ ** PCB_CurrentTask	  = new TASK_ID

@ ------------------------------------------------------
@ Context Switch
@ ------------------------------------------------------
*/

handler_contextswitch:

     ldmfd   sp!,{r0-r12,r14}    
     ldr     r13,=PCB_PtrCurrentTask
     ldr     r13,[r13]
     sub     r13,r13,#60    
     stmia   r13,{r0-r14}^  
     mrs     r0, SPSR
     stmdb   r13,{r0,r14}    
     ldr     r13,=PCB_PtrNextTask
     ldr     r13,[r13]
     sub     r13,r13,#60  
     ldmdb   r13,{r0,r14}
     msr     spsr_cxsf, r0
     ldmia   r13,{r0-r14}^         
     ldr     r13,=PCB_TopOfIRQStack
     ldr     r13,[r13]              
     movs    pc,r14                 
     .end

        一共写了3个静态任务,第一个任务做一个简单的算术运算,第二个任务是一个流水灯,而第三个任务是利用蜂鸣器来产生旋律.

        仅贴出第三个任务的代码:

 

.text
.global EntryTask3

Feq_Table:
	.word     20
	.word     40
	.word     60
	.word     80
	.word     100
	.word     120
	.word     140
	.word     160   
	.word     180
	.word     200
	.word     220
	.word     240

CurrentFeq:
	.word 0x0

task3_delay:
	
	ldr r3,=0xffffff

task3_delay1:
	sub r3,r3,#1

	cmp r3,#0x0

	bne task3_delay1

	mov pc,lr

EntryTask3:

loopfeq:


	ldr r1,=TCON
	ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)
	str r2, [r1]


	ldr	r2, =GPBCON
	ldr	r1,[r2]

	//ldr	r1, =0x15400
	bic	r1,r1,#0x3
	orr	r1,r1,#0x2
	str	r1,[r2]

	ldr r1,=TCFG0
	ldr r2,=(Prescaler0<<0)
	str r2, [r1]

	ldr r1,=TCFG1
	ldr r2,=(DMA_MODE<<20) | (MUX0<<0)
	str r2, [r1]

	ldr     r3,=CurrentFeq
	ldr     r0,[r3]      
	ldr     r4,=Feq_Table
	ldr     r4,[r4,r0,LSL#2]       @用r4存放table中的值 
	add     r0,r0,#1  
	cmp     r0,#12
	moveq   r0,#0        
	str     r0,[r3]      



	ldr r1,=TCNTB0
	//ldr r4,=100
	str r4, [r1]        
	
	mov  r4,r4,LSR #2

	ldr r1,=TCMPB0
	//ldr r4,=25
	str r4, [r1]



	ldr r1,=TCON
	ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)
	str r2, [r1]

	ldr r1,=TCON
	ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)
	str r2, [r1]


	bl task3_delay
	b loopfeq	
        第三个任务就是每隔一段时间就有新的频率产生.

        整个编译出来不到2K,直接在4K的sram中跑.看到的就是led在流水,蜂鸣器在各种频率.忽然想到了“落霞与孤鹜齐飞”.有了任务调度,看起来还是很美的.

        下一步,利用MMU的MPU功能,改进这个任务调度,并且任务是单独编译的.总大小应该不会超过4K,这样我就暂时不用看Nandflash的datasheet了.不过迟早是要看的.......


评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值