CH32V307 例程问题

1、对于Freertos例程,启动文件里面修改了使用八级嵌套,但是主函数里面还是采用的NVIC_PriorityGroup_2(还发现了别的青稞内核处理器这个地方的问题,建议更新下例程)image.png

2、对于INT例程种的Interrupt_Nest八级中断嵌套例程,手动修改代码为全使用硬件压栈,并把触发放在while死循环种,任然可以一直触发所有的八级中断,和手册描述不符,这里希望作出解释。image.pngimage.png

您好,感谢你的反馈建议,后续会对EVT例程进行修改。关于配置中断系统控制寄存器(INTSYSCR)为0x1f,即配置使能硬件压栈和中断嵌套功能,中断嵌套深度配置为8级, 注意该寄存器位4的介绍:硬件压栈深度为 3 级,当配置嵌套等级大于 3 级,若该位设置 1,需要将低优先级的三级中断配置为硬件压栈,高优先级配置为软件压栈,如下图。但你的程序中全部配置成了硬件压栈,因此是有问题的,建议你可以直接参考我们EVT例程,那个是没问题的。

image.png

 


您好,我的意思是八级嵌套,我全部用硬件压栈,但是程序能够正常运行,按道理只支持三级硬件压栈,这样没有问题吗


你好,根据我的测试结果,如果您同时触发的中断大于三个会hard fault

比如你有4个中断ABCD

如果你按照 A进入 A退出 B进入 B退出 C进入 C退出 D进入 D退出

是不会有问题的

如果你按照 A进入 B进入 C进入 C退出 D进入 D退出 B退出?A退出

也不会有问题,因为栈里最多只有ABC或者ABD,一共有三层

但是你如果A进入 B进入 C进入 D进入,那在D进入的时候会有HARDFAULT


向您的这个测试只出发一个wwdg是不会出问题的


您好,您用的是CH32V307吗,我这边只是更改了八级嵌套中断例程,全部改成了硬件中断,但是测试时正常运行,不知道为什么。



您好,您说的“但是你如果A进入 B进入 C进入 D进入,那在D进入的时候会有HARDFAULT”,我这边并不会进入HARDFAULT,而是八级嵌套中断正常按照顺序执行。


你好

1.开启了硬件压栈之后,所有中断都会使用硬件压栈,如果3级嵌套,硬件压栈满了,则不会继续硬件压栈,此时如果要继续中断嵌套,则需要高优先级的中断,使用软件压栈,防止数据丢失。

2.__attribute__((interrupt("WCH-Interrupt-fast")));这个声明是告诉编译器,这个中断不需要软件压栈。

3.例程都改为硬件压栈的声明,可以正常运行,原因是例程的中断函数比较简单,没有用到太多通用寄存器,即使没有保存上下文,也可以正常运行,如果代码复杂一点,就会运行混乱。


也就是说,我测试出来的hard fault不是因为压栈压不进去触发的,而是压栈没压进去,然后恢复现场的时候恢复了一坨不知道是什么东西的东西到寄存器组里,然后因为这一坨异常的数据触发的hardfault




image.png

V307 八级中断全硬件压栈,逐个分析了进中断前的寄存器值和退出中断后的寄存器值,不知道是不是使用的官方里程简单,从上图分析出,返回寄存器ra的值,在第八级中断退出的前5次中,一直没有更新,始终是第八级中断退出的地方,但是sp和fp还是会正常更新,逐步返回到前一级的硬件压栈值,个人这里有两种猜测:

第一种:可能是中断嵌套例程太简单,没有干涉到sp和fp寄存器,但是个人觉得这种猜测不合理;

第二种:就是硬件压栈的时候,超过硬件压栈三级后,对于ra寄存器,在最后一级中断退出时,每退一次,重复赋值自身ra值,直到退到嵌套次数小于等于三次后,再次退出时,就开始赋值第二级嵌套的ra值,第二级嵌套退出时,赋值第一级嵌套的ra值,这样退出下去。个人感觉有点不是很合理,就是为什么sp和fp寄存器的值能够保存,但是ra寄存器的值,却没有,这个地方是内核设计的时候,就设计成超过最大压栈次数后,最后一级中断退出的时候重复更新自身ra值,直到嵌套深度小于等于三级压栈。

上述也只是个人的一个猜测,本人不是IC设计行业的,也只能根据现象来反推和猜测了,如有错误,您指出并回复即可。


以下是V307 四级中断全硬件压栈的进出栈寄存器分析,确实能过够得出第二种结论,再第四级中断退出时,由于超过了最大三级硬件压栈次数,因此更新自身ra值,但是sp和fp还是属于正常更新,之后由于嵌套深度为三级,因此再次退出时,可以正常更新ra值,之后就是顺利的退出过程。

image.png


你好

代码里会操作这些寄存器,需要配合汇编指令去分析,mret指令是中断退出的指令,寄存器mepc存放着mret的下一条指令地址。

如果想研究压栈出栈时的变化,可以在反汇编的窗口,在mret和mepc的位置打上断点,在执行mret前,修改通用寄存器的值,然后执行到下一条指令的时候,查看通用寄存器的变化,从而反推硬件压栈和软件压栈的不同之处。


您说的这个,我看了反汇编,懂您说的意思。

但是,我上面那个问题,您可以再仔细回答下么。


你好,我暂时看不懂你的问题,只能谈谈我的理解。

sp是堆栈的指针,在不断的加加减减,自己就在不断更新,这里就一个堆栈,所以不需要保存。

fp不大了解,看汇编中的行为,像是对变量寻址用的,也在频繁的使用,并且有和堆栈交互的痕迹。

ra是函数调用的返回地址,在调用函数的时候之前会修改,所以需要在压栈出栈的时候进行操作,否则就丢失了。


您好,这个问题,可能需要设计这个内核的来回答一下,也很感谢您的耐心解答。

这个问题关键点在于,硬件压栈到出栈,为什么溢出后,在逐级退出的时候,对于溢出的那几级,从现象上看是重复最后那级的ra值,而退到三级(包含三级)以内后,又能够正确的出栈ra值,这个可能需要设计这个内核的人来解释下。


额外说明:

对于说程序进hardfault,这里个人给出一种猜测,如果配置了大于三级的硬件压栈,在这种情况下,介于最高级和三级中间那几级里面的程序并没有正常执行完,因此,可能导致最后退回到主程序里面时,出现问题,从而进入hardfault。


只有登录才能回复,可以选择微信账号登录