OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4686|回复: 2

关于cortex-A7的9种CPU模式

[复制链接]

2

主题

3

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2017-8-21
在线时间
3 小时
发表于 2020-7-3 11:06:02 | 显示全部楼层 |阅读模式
1金钱
9中CPU模式中关于寄存器的图示,正点原子的指南和 官方文档的不太一样

来自 ARM Cortex-A(armV7)编程手册V4.0

来自正点原子的开发指南
官方的寄存器里面SVC模式和IRQ模式是共用SP和LR寄存器的,正点原子给的图示分开的,是这两个图对应的芯片不同吗?
我用的开发板是ALIENTEK   I.MX6U   ALPHA   V2.2
这里好像有点影响IRQ中断的编写
  1. IRQ_Handler:
  2.         push {lr}                                        /* 保存lr地址 */
  3.         push {r0-r3, r12}                        /* 保存r0-r3,r12寄存器 */

  4.         mrs r0, spsr                                /* 读取spsr寄存器 */
  5.         push {r0}                                        /* 保存spsr寄存器 */

  6.         mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中
  7.                                                                 * 参考文档ARM Cortex-A(armV7)编程手册V4.0.pdf P49
  8.                                                                 * Cortex-A7 Technical ReferenceManua.pdf P68 P138
  9.                                                                 */                                                       
  10.         add r1, r1, #0X2000                        /* GIC基地址加0X2000,也就是GIC的CPU接口端基地址 */
  11.         ldr r0, [r1, #0XC]                        /* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器,
  12.                                                                  * GICC_IAR寄存器保存这当前发生中断的中断号,我们要根据
  13.                                                                  * 这个中断号来绝对调用哪个中断服务函数
  14.                                                                  */
  15.         push {r0, r1}                                /* 保存r0,r1 */
  16.        
  17.         cps #0x13                                        /* 进入SVC模式,允许其他中断再次进去 */
  18.        
  19.         push {lr}                                        /* 保存SVC模式的lr寄存器 */
  20.         ldr r2, =system_irqhandler        /* 加载C语言中断处理函数到r2寄存器中*/
  21.         blx r2                                                /* 运行C语言中断处理函数,带有一个参数,保存在R0寄存器中 */

  22.         pop {lr}                                        /* 执行完C语言中断服务函数,lr出栈 */
  23.         cps #0x12                                        /* 进入IRQ模式 */
  24.         pop {r0, r1}                               
  25.         str r0, [r1, #0X10]                        /* 中断执行完成,写EOIR */

  26.         pop {r0}                                               
  27.         msr spsr_cxsf, r0                        /* 恢复spsr */

  28.         pop {r0-r3, r12}                        /* r0-r3,r12出栈 */
  29.         pop {lr}                                        /* lr出栈 */
  30.         subs pc, lr, #4                                /* 将lr-4赋给pc */
复制代码
cps #0x13                                        /* 进入SVC模式,允许其他中断再次进去 */               
push {lr}                                        /* 保存SVC模式的lr寄存器 */

影响这两句代码:
如果SVC和IRQ共用lr寄存器,那如果cps #0x13执行之后,立马来了个IRQ中断,那么lr寄存器肯定会被破坏,然后中断返回之后我们再push{lr}就保存的是错误的数据。
当然如果SVC和IRQ共用lr寄存器也就没必要在这里保存lr寄存器了。
还有sp指针也是,如果共用的话:
  1. /* 复位中断 */       
  2. Reset_Handler:

  3.         cpsid i                                                /* 关闭全局中断 */

  4.         /* 关闭I,DCache和MMU
  5.          * 采取读-改-写的方式。
  6.          */
  7.         mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中                                       */
  8.     bic     r0,  r0, #(0x1 << 12)     /* 清除C1寄存器的bit12位(I位),关闭I Cache                    */
  9.     bic     r0,  r0, #(0x1 <<  2)     /* 清除C1寄存器的bit2(C位),关闭D Cache                                    */
  10.     bic     r0,  r0, #0x2             /* 清除C1寄存器的bit1(A位),关闭对齐                                                */
  11.     bic     r0,  r0, #(0x1 << 11)     /* 清除C1寄存器的bit11(Z位),关闭分支预测                                        */
  12.     bic     r0,  r0, #0x1             /* 清除C1寄存器的bit0(M位),关闭MMU                                               */
  13.     mcr     p15, 0, r0, c1, c0, 0     /* 将r0寄存器中的值写入到CP15的C1寄存器中                                         */

  14.        
  15. #if 0
  16.         /* 汇编版本设置中断向量表偏移 */
  17.         ldr r0, =0X87800000

  18.         dsb
  19.         isb
  20.         mcr p15, 0, r0, c12, c0, 0
  21.         dsb
  22.         isb
  23. #endif
  24.    
  25.         /* 设置各个模式下的栈指针,
  26.          * 注意:IMX6UL的堆栈是向下增长的!
  27.          * 堆栈指针地址一定要是4字节地址对齐的!!!
  28.          * DDR范围:0X80000000~0X9FFFFFFF
  29.          */
  30.         /* 进入IRQ模式 */
  31.         mrs r0, cpsr
  32.         bic r0, r0, #0x1f         /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4         */
  33.         orr r0, r0, #0x12         /* r0或上0x13,表示使用IRQ模式                                        */
  34.         msr cpsr, r0                /* 将r0 的数据写入到cpsr_c中                                         */
  35.         ldr sp, =0x80600000        /* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */

  36.         /* 进入SYS模式 */
  37.         mrs r0, cpsr
  38.         bic r0, r0, #0x1f         /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4         */
  39.         orr r0, r0, #0x1f         /* r0或上0x13,表示使用SYS模式                                        */
  40.         msr cpsr, r0                /* 将r0 的数据写入到cpsr_c中                                         */
  41.         ldr sp, =0x80400000        /* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */

  42.         /* 进入SVC模式 */
  43.         mrs r0, cpsr
  44.         bic r0, r0, #0x1f         /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4         */
  45.         orr r0, r0, #0x13         /* r0或上0x13,表示使用SVC模式                                        */
  46.         msr cpsr, r0                /* 将r0 的数据写入到cpsr_c中                                         */
  47.         ldr sp, =0X80200000        /* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */

  48.         cpsie i                                /* 打开全局中断 */
  49. #if 0
  50.         /* 使能IRQ中断 */
  51.         mrs r0, cpsr                /* 读取cpsr寄存器值到r0中                         */
  52.         bic r0, r0, #0x80        /* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */
  53.         msr cpsr, r0                /* 将r0重新写入到cpsr中                         */
  54. #endif

  55.         b main                                /* 跳转到main函数                                  */
复制代码
这里初始化SVC模式的SP和初始化IRQ模式的SP不是就重复了吗?

最佳答案

查看完整内容[请看2#楼]

应该是官方文档里面写错了,你仔细阅读这一章节,并没有提过SVC和IRQ的R13和R14共用,相反,官方文档里面还有下面一句话: 这里明确的写出了R14_svc和R14_irq。 另外,我又看了一下杜春雷写的《ARM体系结构与编程》这本书,虽然讲的是ARM9,但是在寄存器模式这一块基本和Cortex-A7是一样的,相关描述见下图:
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2020-7-3 11:06:03 | 显示全部楼层
本帖最后由 zuozhongkai 于 2020-7-3 15:39 编辑

应该是官方文档里面写错了,你仔细阅读这一章节,并没有提过SVC和IRQ的R13和R14共用,相反,官方文档里面还有下面一句话:
@XV%$O7RK93SBK)}JVCVH%K.png
这里明确的写出了R14_svc和R14_irq。

另外,我又看了一下杜春雷写的《ARM体系结构与编程》这本书,虽然讲的是ARM9,但是在寄存器模式这一块基本和Cortex-A7是一样的,相关描述见下图:
QQ截图20200703153805.png




回复

使用道具 举报

2

主题

3

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2017-8-21
在线时间
3 小时
 楼主| 发表于 2020-7-3 18:37:34 | 显示全部楼层
zuozhongkai 发表于 2020-7-3 15:32
应该是官方文档里面写错了,你仔细阅读这一章节,并没有提过SVC和IRQ的R13和R14共用,相反,官方文档里面还 ...

谢谢回复,如果SVC和IRQ共用的话,确实对用户编写程序非常不友好,官方的错了我就放心了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 14:43

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表