微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > GNU ARM汇编--(十四)GNU ARM汇编下做任务调度

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

  1. kernelScheduler:
  2. /*
  3. @---------------------------------------------------
  4. @RoundRobinScheduler
  5. @---------------------------------------------------
  6. */
  7. CurrentTask:
  8. ldrr3,=PCB_CurrentTask
  9. ldrr0,[r3]
  10. ldrr1,=PCB_Table
  11. ldrr1,[r1,r0,LSL#2]
  12. ldrr2,=PCB_PtrCurrentTask
  13. strr1,[r2]
  14. /*
  15. @**PCB_PtrCurrentTask-updatedwiththenewaddress
  16. */
  17. NextTask:
  18. addr0,r0,#1
  19. cmpr0,#3
  20. moveqr0,#0
  21. strr0,[r3]
  22. ldrr1,=PCB_Table
  23. ldrr1,[r1,r0,LSL#2]
  24. ldrr0,=PCB_PtrNextTask
  25. strr1,[r0]
  26. /*
  27. @**PCB_PtrCurrentTask=currentPCB
  28. @**PCB_PtrNextTask=nextPCB
  29. @**PCB_CurrentTask=newTASK_ID
  30. @------------------------------------------------------
  31. @ContextSwitch
  32. @------------------------------------------------------
  33. */
  34. handler_contextswitch:
  35. ldmfdsp!,{r0-r12,r14}
  36. ldrr13,=PCB_PtrCurrentTask
  37. ldrr13,[r13]
  38. subr13,r13,#60
  39. stmiar13,{r0-r14}^
  40. mrsr0,SPSR
  41. stmdbr13,{r0,r14}
  42. ldrr13,=PCB_PtrNextTask
  43. ldrr13,[r13]
  44. subr13,r13,#60
  45. ldmdbr13,{r0,r14}
  46. msrspsr_cxsf,r0
  47. ldmiar13,{r0-r14}^
  48. ldrr13,=PCB_TopOfIRQStack
  49. ldrr13,[r13]
  50. movspc,r14
  51. .end


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

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

[cpp]view plaincopy

  1. .text
  2. .globalEntryTask3
  3. Feq_Table:
  4. .word20
  5. .word40
  6. .word60
  7. .word80
  8. .word100
  9. .word120
  10. .word140
  11. .word160
  12. .word180
  13. .word200
  14. .word220
  15. .word240
  16. CurrentFeq:
  17. .word0x0
  18. task3_delay:
  19. ldrr3,=0xffffff
  20. task3_delay1:
  21. subr3,r3,#1
  22. cmpr3,#0x0
  23. bnetask3_delay1
  24. movpc,lr
  25. EntryTask3:
  26. loopfeq:
  27. ldrr1,=TCON
  28. ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(man_update<1)|(stop<0)
  29. strr2,[r1]
  30. ldrr2,=GPBCON
  31. ldrr1,[r2]
  32. //ldrr1,=0x15400
  33. bicr1,r1,#0x3
  34. orrr1,r1,#0x2
  35. strr1,[r2]
  36. ldrr1,=TCFG0
  37. ldrr2,=(Prescaler0<0)
  38. strr2,[r1]
  39. ldrr1,=TCFG1
  40. ldrr2,=(DMA_MODE<20)|(MUX0<0)
  41. strr2,[r1]
  42. ldrr3,=CurrentFeq
  43. ldrr0,[r3]
  44. ldrr4,=Feq_Table
  45. ldrr4,[r4,r0,LSL#2]@用r4存放table中的值
  46. addr0,r0,#1
  47. cmpr0,#12
  48. moveqr0,#0
  49. strr0,[r3]
  50. ldrr1,=TCNTB0
  51. //ldrr4,=100
  52. strr4,[r1]
  53. movr4,r4,LSR#2
  54. ldrr1,=TCMPB0
  55. //ldrr4,=25
  56. strr4,[r1]
  57. ldrr1,=TCON
  58. ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(man_update<1)|(start<0)
  59. strr2,[r1]
  60. ldrr1,=TCON
  61. ldrr2,=(DZ_eable<4)|(auto_reload<3)|(inverter<2)|(clear_man_update<1)|(start<0)
  62. strr2,[r1]
  63. bltask3_delay
  64. bloopfeq

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

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

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

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top