[原创] MSP430中断的流程

lr2131   2013-1-9 18:34 楼主
在写自己的简单OS时遇到了一些中断处理流程的问题。中断能正常进入和处理,但是一出了中断就马上又进来了,感觉就像是没清除中断标记一样。

一般的MCU在处理中断时都有清除中断标记的操作,例如看到的ARM7的中断代码中,中断的清除一般有两句话,一句是清除VIC中的中断地址,一句是清除产生中断模块位的标记。这些需要用户显式的操作,编译器和硬件是不会智能的去做的。

但是为什么在MSP430中没有类似的显式的操作呢,在哪个资料上看到,说是单个的中断源会由CPU自动清除,但是如果是多个中断源需要用户自己清除。
这句话看起来很简单,但我还是不懂,不知道具体是怎么做的,是在哪做的,想要看到直接的汇编代码,但是试着用了简单的定时器代码来看,中断处理的汇编代码极其简单,压根就没见到这样的操作,可能是因为只有一个中断源吧,让CPU做了。但是如果想自己做了,我想如果CPU先做了,我在代码里面显式的做应该没有问题吧,或者我先显式的做,然后CPU再做也该没有问题吧。那到底要怎么做了?

现在就卡在这个中断的问题上了,任务级的调度已经都完成了,就差中断级的调度,调度器就差不多完成了。不想在这个问题上再拖下去了。

回复评论 (5)

关于中断的处理,我曾经写过一个小帖子
https://home.eeworld.com.cn/my/space-uid-241610-blogid-42042.html
对理解中断会有些帮助
点赞  2013-1-10 10:27
MSP430的中断标志位,有的可以自动清除,有的需要软件清除。
点赞  2013-1-10 10:28
引用: 原帖由 wstt 于 2013-1-10 10:28 发表
MSP430的中断标志位,有的可以自动清除,有的需要软件清除。
硬件平台:MSP430F149 (因为MCU内部资源比较丰富,作为学习板是最合适的,现在似乎学习板最流行的也是这个型号)
软件平台:IAR 5.3 (启动代码中很多地方呗编译器做了限制和保护,想说爱你不容易啊)
调试器:MSP430FET430UIF

简单的分析一下启动代码:(做了截图,但是不知道怎上传,而且最近上传速度忒慢,就不传了算了)

中断向量表存放在0xFFFF处到0xFFE0,共32个字节,每相邻2个字节为一个中断向量,0xFFFE-0xFFFF处存储的是复位向量。这个16位的数据,0xFFFE存放的是低8位数据,0xFFFF存放的是高8位地址,也就是小端模式。这里应该存放的是程序的首地址,我跟踪到的是0x1102(不知道0x1100是什么地址,看到过几次,不记得了,麻烦知道的指点一下)。

CPU上电复位后,PC指向0xFFFE,CPU从中断向量表中取得程序首地址的地址后,马上跳转到0x1102处。在0x1102处,存放的是MOV,#0x0A00,SP  也就是初始化栈寄存器,因为后面马上就会用到了,不尽快初始化会出问题的。之后可能有关闭看门狗或者是没有这个操作,这个要看用户是怎么弄的吧。

F149的RAM是2K的,从0x0200到0xA00,因为MSP430是满递减堆栈的,所以初始化堆栈寄存器给出的是0xA00,不是0x200。

然后接下来,如果程序中使用了静态变量(包括全局的和局部的),那么有静态变量的初始化,将静态变量在RAM中创建或初始化。地址从0x200开始,所以在跟踪一些静态变量时会发现它们的地址基本都在0x200以后。也就是RW的搬运和ZI断的创建,linux下表述方式为data段和bss段。具体的我也没有分析过。


然后才call #main,调用用户的main函数,进入用户程序的流程。

所以综上,启动代码一般要做的4件事的流程是:
1.初始化栈寄存器SP
2.初始化某些硬件外设,例如看门狗。(可选,依具体硬件和需求决定)
3.初始化RW段        (可选,看用户中是否有初始化值的静态变量)
4.创建ZI段       (可选,看用户中是否有未初始化值的静态变量,默认初始化为0)
5.调用用户main函数,进入用户程序流程。

有问题的地方欢迎指出和纠正。
点赞  2013-1-10 11:11
调试了一整天,还发现了一些其他的问题,不过调度器已经完成了。这几天整理一下,把调试的过程和解决方法与大家共享一下,也有一些东西不明白,欢迎大家讨论。
点赞  2013-1-10 17:14
大致列一下这个解决问题的流程:

1.我先想确认如果中断整个的是正常的进出的话,用户线程是否能正常运行,至少被打断的线程调度没有问题。但是这个定时器A的中断一出去就马上进来了,通过加断点单步调试能看到,几乎是一出去就又进中断了,我就先在中断用汇编的方式把压栈的SR中清0了GIE,所以出了中断就不再进来了,发现被打断的线程果然可以正常继续运行。只是以后就不能在进中断了,这样做只是想验证代码上其他地方的逻辑性是否正确,验证完了。

2.接下来,查找了TImerA的中断标记寄存器,在中断中用汇编的方式把TACCTL0和TACTL的中断标记位都清0,在调试模式下却发现居然没有效果,怀疑是汇编代码写得有问题(刚接触MSP430不久,汇编也只是入门了),反反复复的改还是一样不行,算了,在中断服务子程序中用C的代码来写,依然不行。这下大跌眼镜。不知道该怎么搞了。

3.先想了下,至少现在用代码是不能清除这个中断标记了,只能放弃代码的方式来清除了,还是让系统自己来做清除吧。然后接下来用代码的最小系统来做,发现似乎是我的时钟设置和定时器设置有问题,最小系统也出现了一模一样的现象,也是一出中断就进来了,改了几个地方,已经不记得是改了哪个就好了,没有做备份和记录。

4.把这个没有问题的设置放回到原来简单OS代码汇中,预想是没有大问题了,稍稍改了点东西,再改回去,编译后全速运行,果然都好了。

任务级和中断级的调度都好了,剩下的要做一下稳定性的检查。
到最后还是没有查到根本原因。当时以为是BCSCTL2 |= SELM_2 + SELS + DIVS_3;中应该去掉SELS的,但今天又加上这个也是好的,就不记得当时是怎么搞的。
SELS只是选着SMCLK的源,我是想选XT2做时钟源的,因为这个是OS的时钟源,当然稳定一些好啊。但这个怎么选也不应该影响到中断的问题呀,所以当时解决了问题,却觉得很奇怪,没有马上贴出来,现在却发现又不是这个原因。很遗憾没有查出这个原因,以后有时间再来查这个原因吧,不过中断的流程是越来越清楚了。
点赞  2013-1-12 11:18
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复