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的代码:

        

  1. kernelScheduler:  
  2. /* 
  3. @ --------------------------------------------------- 
  4. @ Round Robin Scheduler 
  5. @ --------------------------------------------------- 
  6. */  
  7. CurrentTask:  
  8.   
  9.      ldr     r3,=PCB_CurrentTask  
  10.      ldr     r0,[r3]        
  11.      ldr     r1,=PCB_Table  
  12.      ldr     r1,[r1,r0,LSL#2]      
  13.      ldr     r2,=PCB_PtrCurrentTask  
  14.      str     r1,[r2]      
  15. /* 
  16. @ ** PCB_PtrCurrentTask - updated with the new address 
  17. */  
  18. NextTask:  
  19.      add     r0,r0,#1    
  20.      cmp     r0,#3  
  21.      moveq   r0,#0          
  22.      str     r0,[r3]        
  23.      ldr     r1,=PCB_Table  
  24.      ldr     r1,[r1,r0,LSL#2]      
  25.      ldr     r0,=PCB_PtrNextTask  
  26.      str     r1,[r0]       
  27. /* 
  28. @ ** PCB_PtrCurrentTask   = current PCB 
  29. @ ** PCB_PtrNextTask      = next PCB 
  30. @ ** PCB_CurrentTask      = new TASK_ID 
  31.  
  32. @ ------------------------------------------------------ 
  33. @ Context Switch 
  34. @ ------------------------------------------------------ 
  35. */  
  36.   
  37. handler_contextswitch:  
  38.   
  39.      ldmfd   sp!,{r0-r12,r14}      
  40.      ldr     r13,=PCB_PtrCurrentTask  
  41.      ldr     r13,[r13]  
  42.      sub     r13,r13,#60      
  43.      stmia   r13,{r0-r14}^    
  44.      mrs     r0, SPSR  
  45.      stmdb   r13,{r0,r14}      
  46.      ldr     r13,=PCB_PtrNextTask  
  47.      ldr     r13,[r13]  
  48.      sub     r13,r13,#60    
  49.      ldmdb   r13,{r0,r14}  
  50.      msr     spsr_cxsf, r0  
  51.      ldmia   r13,{r0-r14}^           
  52.      ldr     r13,=PCB_TopOfIRQStack  
  53.      ldr     r13,[r13]                
  54.      movs    pc,r14                   
  55.      .end  

 

 

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

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

 

  1. .text  
  2. .global EntryTask3  
  3.   
  4. Feq_Table:  
  5.     .word     20  
  6.     .word     40  
  7.     .word     60  
  8.     .word     80  
  9.     .word     100  
  10.     .word     120  
  11.     .word     140  
  12.     .word     160     
  13.     .word     180  
  14.     .word     200  
  15.     .word     220  
  16.     .word     240  
  17.   
  18. CurrentFeq:  
  19.     .word 0x0  
  20.   
  21. task3_delay:  
  22.       
  23.     ldr r3,=0xffffff  
  24.   
  25. task3_delay1:  
  26.     sub r3,r3,#1  
  27.   
  28.     cmp r3,#0x0  
  29.   
  30.     bne task3_delay1  
  31.   
  32.     mov pc,lr  
  33.   
  34. EntryTask3:  
  35.   
  36. loopfeq:  
  37.   
  38.   
  39.     ldr r1,=TCON  
  40.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (stop<<0)  
  41.     str r2, [r1]  
  42.   
  43.   
  44.     ldr r2, =GPBCON  
  45.     ldr r1,[r2]  
  46.   
  47.     //ldr   r1, =0x15400  
  48.     bic r1,r1,#0x3  
  49.     orr r1,r1,#0x2  
  50.     str r1,[r2]  
  51.   
  52.     ldr r1,=TCFG0  
  53.     ldr r2,=(Prescaler0<<0)  
  54.     str r2, [r1]  
  55.   
  56.     ldr r1,=TCFG1  
  57.     ldr r2,=(DMA_MODE<<20) | (MUX0<<0)  
  58.     str r2, [r1]  
  59.   
  60.     ldr     r3,=CurrentFeq  
  61.     ldr     r0,[r3]        
  62.     ldr     r4,=Feq_Table  
  63.     ldr     r4,[r4,r0,LSL#2]       @用r4存放table中的值   
  64.     add     r0,r0,#1    
  65.     cmp     r0,#12  
  66.     moveq   r0,#0          
  67.     str     r0,[r3]        
  68.   
  69.   
  70.   
  71.     ldr r1,=TCNTB0  
  72.     //ldr r4,=100  
  73.     str r4, [r1]          
  74.       
  75.     mov  r4,r4,LSR #2  
  76.   
  77.     ldr r1,=TCMPB0  
  78.     //ldr r4,=25  
  79.     str r4, [r1]  
  80.   
  81.   
  82.   
  83.     ldr r1,=TCON  
  84.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (man_update<<1) | (start<<0)  
  85.     str r2, [r1]  
  86.   
  87.     ldr r1,=TCON  
  88.     ldr r2,=(DZ_eable<<4) | (auto_reload<<3) | (inverter<<2) | (clear_man_update<<1) | (start<<0)  
  89.     str r2, [r1]  
  90.   
  91.   
  92.     bl task3_delay  
  93.     b loopfeq     

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

 

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

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

 

                                                                                                                           转载于:blog.csdn.net/dndxhej

posted on 2012-10-15 22:27  Daniel.G  阅读(512)  评论(0编辑  收藏  举报