前言回顾
回顾 《程序如何在cpu中运行的》 举例了几个例子 我们回顾一下
1 顺序执行时 pc指针存放在函数里 PC指针存放的是下一个地址的指令,pc指针寄存器这样的功能
会让程序有序执行.
2 条件分支:当前的 和存放的下一个地址指令 比较 如果 小于或者等于 就会发生跳转 所以 PC指针的下一个地址 应该是 下一个的下一个地址。
3 一级调用函数 : 当发生函数调用时 并不会发生压栈的行为,而是把 地址直接存入了 R14 寄存器 当函数返回时 在把地址取出 执行完函数之后 PC指针又会 指向下一个
4 二级调用 :因为R14寄存器 只能存入 一个地址 所以要引入 堆栈的部分机制 “先进后出 ”
当第一次会让两个地址分别进栈 过程会发生跳转。到了第二次 第一次后进的元素 现在就变成了先进了 所以会先指向他函数存放PC指针的地址 最后才会指向 第一次元素 并且PC指针会继续指向下一次 为了 程序有序运行。
下面 引入中断思想 更深一步理解
地址存放, 调用,返回,三者 的 关系
很精彩 , 哞哞弟带你乱飞, 坐好了窝 开始冲!!!!!!!!!!!
一 中断
当cpu 在执行某个事时,外部发生事件对CPU发起请求处理,于是cpu停止了当前工作,
去处理了请求事件,处理完了 再回到原先的事件继续处理。
那么这里提到的请求事件 就可以成为中断事件.
1 中断响应以及处理过程
在前言我们回顾了一级函数调用的原理 和下面讲到的就息息相关。
不太了解的 回头看看 在看下面的知识点.
首先 我们先看一张图
重点提及
保护现场: 进入中断线 保护当前的数据
恢复现场: 恢复中断前原先的数据
因为在一级调用 并没 把 地址存入地址 当cpu发生中断请求 他就会直接把 存在R14的地址 取出
返回中断函数 执行 执行完之后 因为PC指针存放的是下一个地址的指针 又因为中断函数 存放了 PC指针 所以下一次就是 返回 原来的状态了。
2 中断堆栈的占用
cpu 在执行中断函数之前 需要保护现场,那么是如何保护现场了 现在就用到我们的堆栈了 拿M3 举例 进入中断前 他会自动把XPSR PC LR R12 R3_RO 存入堆栈当中,注意 在对应的汇编代码是看不到的,对于M3来说 有两个堆栈 ,一个是主堆栈指针用于系统内核和中断服务程序的 一个是 线程指针 用于处理用户应用程序的。响应中断时 当前用了线程堆栈指针 那么地址应该是存入线程堆栈指针 要不就是主堆栈指针。
在保护现场时 堆栈就会想应增加 恢复时 因为处理完了中断 所以会减少。
很明显 保护现场 进入中断后 增加了 OXOO-OX10 的堆栈
在处理 逻辑更加复杂的 中断函数时 我们就需要更多的寄存器 就会用到R4-R11了
这部分的寄存器是不能自动加载的 需要我们手动 进行存入堆栈 ,这部分汇编就可以看到了。
3 中断向量表
我们在思考 我们中断源狠多 比如 按键可以触发中断 或者是串口标志位 等等 而他们相应的中断服务子函数是什么
也就是 我们怎么知道在cpu 触发 中断请求 它会怎么对应 相应中断的地址呢
下面介绍一个名词
中断向量表 它有3个层意思
1 是一段连续的存储地在
2 复位后有起始地址
3 每个中断在向量表 都有表项 表项就是中断源对应的子函数
说了 中断向量表复位后有个起始地址 也就是下面的 0X0000 0000
结合回顾 知识看
当然这只是一部分,并不是全部的表项。有了中断向量表之后,
那么当 CPU 接收到中断请求的时候,就会根据这个中断请求的信号去查这个表,
从而查找到其所对应的中断服务子程序的地址,
然后将这个地址赋值给 PC 指针寄存器,那么 CPU 就可以完成中断服务子程序的执行了
4 中断服务函数
void EXTI0_IRQHandler(void)
{
/* 确保是否产生了中断 */
if(EXTI_GetITStatus(EXTI_Line0) != RESET)
{
/*用户代码*/
/*清除中断标志位*/
EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);
}
}
因为函数类型和形参都是void 所以没有返回值 这也就印证了他的地址是存放到R14寄存器的
发生返回时才会取出 又因为 函数存放了 PC指针 也就保证了 他可以 恢复现场 返回执行 原先函数。
5 (#4==#5) 其实和这个函数是一样的
为什么花 3 呢 因为 aa函数 存放的是pc指针 pc指针存放的是下一个地址的指针
因为aa 后面没有函数了 所以看得不明显而已。 这里的3 相当于中断的恢复现场
请多多指点 说的不好 欢迎 留言。哞哞!!!!!!!!!!!!!!!