打印
[应用方案]

Cortex-M内核知识点总结

[复制链接]
楼主: 米多0036
手机看帖
扫描二维码
随时随地手机跟帖
41
米多0036|  楼主 | 2023-9-15 14:26 | 只看该作者 |只看大图 回帖奖励 |倒序浏览

最终定位到发生问题的函数: shell_version_cmd --> unti_strcmp --> LDRB r2 ,[r1,#0] 。 进一步分析原因可继续追溯栈的内容,查出 until_strcmp 参数输入内容,最终发现为until_strcmp 的第二个参数在出异常是为非法地址,访问非法地址导致HardFault

使用特权

评论回复
42
米多0036|  楼主 | 2023-9-15 14:28 | 只看该作者
深入理解中断
中断输入和悬起行为

使用特权

评论回复
43
米多0036|  楼主 | 2023-9-15 14:29 | 只看该作者
我们使用外部中断的高电平触发方式来解释中断的过程 , 如上图中断请求表示外部输入引脚高电平持续的时间 ,内核检测到中断请求后,将悬起对应的中断(中断标志置位) , 中断悬起后,可能不是立马执行服务程序 , 比如当前在临界区,退出临界区后,处理器模式切换成Handler 模式,并开始执行中断服务程序,清除中断标志,执行完成后 ,退出服务,处理器模式切换成线程模式。若中断请求不是期望中的只请求一次能,比如一直存在请求 , 多次间断请求等又会是怎样的情况呢

使用特权

评论回复
44
米多0036|  楼主 | 2023-9-15 14:30 | 只看该作者
请求信号一直保持
首先中断悬起后,只会在服务程序中清除 , 因此在清除了悬起后,等待中断返回 , 由于请求信号一直有 ,中断会再次被悬起,然后再次执行中断服务程序。

使用特权

评论回复
45
米多0036|  楼主 | 2023-9-15 14:30 | 只看该作者

使用特权

评论回复
46
米多0036|  楼主 | 2023-9-15 14:30 | 只看该作者
执行服务前多次请求
因为在第一次请求时中断就被悬起,且在下次请求前没有进入服务程序清除悬起,因此只会执行一次中断服务。

使用特权

评论回复
47
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者

使用特权

评论回复
48
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者
执行服务后再次请求
在下图中,进入中断服务程序后,悬起状态便被清除,但是还未退出中断后,中断请求再次到来,此时中断被再次悬起,且在服务程序退出后,立即又执行中断服务程序,这里内核会取消退出服务程序的出栈,以及进入服务程序的入栈(后面会具体介绍),这种中断情况称为:中断咬尾

使用特权

评论回复
49
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者

使用特权

评论回复
50
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者
中断优先级分组
在配置中断前 ,我们首先需要设置的就是优先级分组 , 然后设置抢占优先级和从优先级 , 数值越小优先级越高 , 类似下面的配置:

使用特权

评论回复
51
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者
//选择使用优先级分组第1组
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

// 使能EXTI0中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; // 指定抢占式优先级别1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; // 指定响应优先级别0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

// 使能EXTI9_5中断
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 指定抢占式优先级别0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; // 指定响应优先级别1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

使用特权

评论回复
52
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者

使用特权

评论回复
53
米多0036|  楼主 | 2023-9-15 14:32 | 只看该作者
首先是分组 , 如上表,分组决定了抢占优先级和从优先级 (响应优先级)的取值范围 。抢占优先级好理解,抢占优先级高的中断可以打断抢占优先级低的中断,响应优先级呢? 在两个中断的抢占优先级相同时 , 它们不具备抢占功能。这时若两个中断同时到达 , 则按照从优先级的高低决定先执行哪个。 中断的同时到达很容易产生误解,同时触发?网上很少有详细解释这一点的 , 同时触发的机率是很小的(如外部中断同时触发),不管误差有多小总有个先来后到 , 如果只是这样,还有必要设计从优先级吗 , 概率极小,多数情况有个先来后到,完全可以像RTOS 线程优先级只一个抢占优先级那样处理。 在了解了中断悬起行为后 , 就能理解,为什么需要从优先级。通过下图理解所谓的中断同时到达。

使用特权

评论回复
54
米多0036|  楼主 | 2023-9-15 14:33 | 只看该作者

使用特权

评论回复
55
米多0036|  楼主 | 2023-9-15 14:33 | 只看该作者
从上图可以看到,在进入临界区后 , 中断1的请求先到达 , 所以中断1先被悬挂 , 但是此时无法执行服务程序,中断2随后到达,也被悬挂,也无法执行。在退出临界区后 , 由于中断2的从优先级高 , 所以先得到执行,因此上面说的两个中断同时到达 ,并不是说中断同时请求 , 而是在执行服务前,存在两个相同抢占优先级的中断同时处于悬挂状态,这时根据从优先级决定先执行谁。
————————————————

使用特权

评论回复
56
米多0036|  楼主 | 2023-9-15 15:44 | 只看该作者
中断咬尾
在上面的相同抢占优先级,不同从优先级中 , IRQ2 服务和 IRQ1 服务 按一般的中断流程,在执行服务程序前需要保护现场(入栈),在退出中断服务程序前要恢复现场(出栈),但是上面的这种情况是可以省略这个过程的 , 因为栈的数据在这个过程中没变化(主程序没来得及执行,之前保存的现场未发生改变,另一个中断服务又开始了),将数据取出来,然后一模一样的又存进去完全没必要 。这样看起来就像是前一个中断的尾巴(出栈)被下一个中断咬住(去尾去头将两个中断连在一起), 咬尾中断有效的减少了中断的延迟。

使用特权

评论回复
57
米多0036|  楼主 | 2023-9-15 15:44 | 只看该作者

使用特权

评论回复
58
米多0036|  楼主 | 2023-9-15 15:44 | 只看该作者

使用特权

评论回复
59
米多0036|  楼主 | 2023-9-15 15:45 | 只看该作者
中断的具体行为
前面我们介绍了中断的请求与悬起 , 中断过程中处理器的模式和特权等级的变化。但是具体过程没有说明,比如中断过程寄存器是如何变化的 , 在中断跳转前,要进行哪些操作 ,中断返回后有需要哪些操作。理解了中断的具体行为,就能解释为何要求不要频繁进入中断。

使用特权

评论回复
60
米多0036|  楼主 | 2023-9-15 15:45 | 只看该作者
入栈
在响应中断前,最先做的就是保护现场 ,比如当前正在计算 c = a + b , 我们已经将 a 的值从内存中加载到 R0 , 将 b 的值加载到 R1 然后进行了求和运算 , 并把结果存在R0中 , 若a , b 特别大,特殊功能寄存器程序状态字中的进位标志会被触发 , 此时还没有将结果从R0 写入到内存中(c在内存的地址),发生了中断,在中断中,可能会有运算,或者函数调用,也会用到R0-R15 以及特殊功能寄存器,但是前面的运算还没有结束 , 不能破坏了现场 ,不然中断返回后,就不能接着执行了 , 这时就需要保存寄存器中的值 , 保存到哪里?保存到栈中 , 栈在哪里?栈在内存中。由于我们做运算或者加载写入数值,函数调用一般只会用到 R0-R3 ,因此,R0-R3 ,R12(内部调用暂时寄存器 ) , R14(连接寄存器LR) , 程序状态字寄存器XPSR , PC 等将会被硬件自动保存到栈中 , 若用到了R4-R11 ,则需要用PUSH 指令手动保存。这些在第二部分会有详细介绍。 还有一点要注意,到底是 入哪个栈 , MSP 还是PSP , 裸机系统我们一般只使用MSP,而RTOS中线程会使用PSP 。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则