微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > GNU ARM汇编--(四)中断汇编之非嵌套中断处理

GNU ARM汇编--(四)中断汇编之非嵌套中断处理

时间:11-26 来源:互联网 点击:

在写这篇blog之前,不得不感慨一句:纸上得来终觉浅,绝知此事要躬行.作为EE出身的,虽然好久好久没用汇编写单片机的中断了,但自我感觉对中断的理解还是比较深入的,本以为在GNU ARM汇编下搞个中断会很容易,谁知道断断续续花了我几周.完全用汇编写中断和用c中的_irq写中断还是有区别的,谁用谁知道.还是那句话:深入细节是必须的,也是值得的.

这一篇blog的理论知识主要来源于:《ARM System Developers Guide》.

ARM的异常和相应的模式之间的对应关系见下表:

当一个异常导致模式的改变时,内核自动地:

1、把cpsr保存到相应模式下的spsr

2、把pc保存到相应模式下的lr

3、设置cpsr为相应异常模式

4、设置pc为相应异常处理程序的入口地址

从异常中断处理程序返回包含下面两个操作:

1、从spsr_mode中恢复内容到cpsr中

2、从lr_mode中恢复内容到pc中,返回到异常中断的指令的下一条政令处执行.

上面刚提到了异常发生时内核的一些动作,那对与IRQ或者FIQ而言,还多一项变化:禁用相关的中断IRQ或FIQ,禁止同类型的其他中断被触发.

对于最简单的非嵌套中断处理的处理流程如下:

下面给出汇编代码:

[cpp]view plaincopy

  1. /*
  2. simpleinterruption
  3. copyleft@dndxhej@gmail.com
  4. */
  5. .equNOINT,0xc0
  6. .equWTCON,0x53000000
  7. .equGPBCON,0x56000010@led
  8. .equGPBDAT,0x56000014@led
  9. .equGPBUP,0x56000018@led
  10. .equGPFCON,0x56000050@interruptconfig
  11. .equEINTMASK,0x560000a4
  12. .equEXTINT0,0x56000088
  13. .equEXTINT1,0x5600008c
  14. .equEXTINT2,0x56000090
  15. .equINTMSK,0x4A000008
  16. .equEINTPEND,0x560000a8
  17. .equINTSUBMSK,0X4A00001C
  18. .equSRCPND,0X4A000000
  19. .equINTPND,0X4A000010
  20. .global_start
  21. _start:breset
  22. ldrpc,_undefined_instruction
  23. ldrpc,_software_interrupt
  24. ldrpc,_prefetch_abort
  25. ldrpc,_data_abort
  26. ldrpc,_not_used
  27. @birq
  28. ldrpc,_irq
  29. ldrpc,_fiq
  30. _undefined_instruction:.wordundefined_instruction
  31. _software_interrupt:.wordsoftware_interrupt
  32. _prefetch_abort:.wordprefetch_abort
  33. _data_abort:.worddata_abort
  34. _not_used:.wordnot_used
  35. _irq:.wordirq
  36. _fiq:.wordfiq
  37. .balignl16,0xdeadbeef
  38. reset:
  39. ldrr3,=WTCON
  40. movr4,#0x0
  41. strr4,[r3]@disablewatchdog
  42. ldrr0,=GPBCON
  43. ldrr1,=0x15400
  44. strr1,[r0]
  45. ldrr2,=GPBDAT
  46. ldrr1,=0x160
  47. strr1,[r2]
  48. bldelay
  49. msrcpsr_c,#0xd2@进入中断模式
  50. ldrsp,=3072@中断模式的栈指针定义
  51. msrcpsr_c,#0xdf@进入系统模式
  52. ldrsp,=4096@设置系统模式的栈指针
  53. @--------------------------------------------
  54. ldrr0,=GPBUP
  55. ldrr1,=0x03f0
  56. strr1,[r0]
  57. ldrr0,=GPFCON
  58. ldrr1,=0x2ea@0x2
  59. strr1,[r0]
  60. ldrr0,=EXTINT0
  61. ldrr1,=0x8f888@0x0@0x8f888@~(7|(7<4)|(7<8)|(7<16))
  62. strr1,[r0]
  63. ldrr0,=EINTPEND
  64. ldrr1,=0xf0@0b10000
  65. strr1,[r0]
  66. ldrr0,=EINTMASK
  67. ldrr1,=0x00@0b00000
  68. strr1,[r0]
  69. ldrr0,=SRCPND
  70. ldrr1,=0xff@0x1@0b11111
  71. strr1,[r0]
  72. ldrr0,=INTPND
  73. ldrr1,=0xff@0x1@0b11111
  74. strr1,[r0]
  75. ldrr0,=INTMSK
  76. ldrr1,=0xffffff00@0b00000
  77. strr1,[r0]
  78. MRSr1,cpsr
  79. BICr1,r1,#0x80
  80. MSRcpsr_c,r1
  81. blmain
  82. irq:
  83. sublr,lr,#4
  84. stmfdsp!,{r0-r12,lr}
  85. blirq_isr
  86. ldmfdsp!,{r0-r12,pc}^
  87. irq_isr:
  88. ldrr2,=GPBDAT
  89. ldrr1,=0x0e0
  90. strr1,[r2]
  91. ldrr0,=EINTPEND
  92. ldrr1,=0xf0
  93. strr1,[r0]
  94. ldrr0,=SRCPND
  95. ldrr1,=0x3f@0b11111
  96. strr1,[r0]
  97. ldrr0,=INTPND
  98. ldrr1,=0x3f@0b11111
  99. strr1,[r0]
  100. movpc,lr
  101. delay:
  102. ldrr3,=0xffff
  103. delay1:
  104. subr3,r3,#1
  105. cmpr3,#0x0
  106. bnedelay1
  107. movpc,lr
  108. main:
  109. ledloop:
  110. ldrr1,=0x1c0
  111. strr1,[r2]
  112. bldelay
  113. ldrr1,=0x1a0
  114. strr1,[r2]
  115. bldelay
  116. ldrr1,=0x160
  117. strr1,[r2]
  118. bldelay
  119. ldrr1,=0x0e0
  120. strr1,[r2]
  121. bldelay
  122. bledloop
  123. undefined_instruction:
  124. nop
  125. software_interrupt:
  126. nop
  127. prefetch_abort:
  128. nop
  129. data_abort:
  130. nop
  131. not_used:
  132. nop
  133. fiq:
  134. nop


lds文件:

[cpp]view plaincopy

  1. OUTPUT_FORMAT("elf32-littlearm","elf32-littlearm","elf32-littlearm")
  2. OUTPUT_ARCH(arm)
  3. ENTRY(_start)
  4. SECTIONS{
  5. .=0x00000000;
  6. .text:{
  7. *(.text)
  8. *(.rodata)
  9. }
  10. .dataALIGN(4):{
  11. *(.data)
  12. }
  13. .bssALIGN(4):{
  14. *(.bss)
  15. }
  16. }


makefile:

[cpp]view plaincopy

  1. CROSS=arm-linux-
  2. CFLAGS=-nostdlib
  3. int.bin:start.S
  4. ${CROSS}gcc$(CFLAGS)-c-ostart.ostart.S
  5. ${CROSS}ld-Tint.ldsstart.o-oint.elf
  6. #${CROSS}ld-Ttext-segment0x30000000start.o-oint.elf
  7. ${CROSS}objcopy-Obinary-Sint.elfint.bin
  8. #rm-f*.o
  9. clean:
  10. rm-f*.elf*.o
  11. rm-fint.bin

该程序实现的流水灯,然后四个按键可以实现外部中断.

代码中值得注意的地方有几点:

1、lds文件中的地址配为0x00000000,因为程序是download到nandflash中运行的.最开始这里写的是0x300

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

网站地图

Top