打印
[Kinetis]

【经验分享】Kinetis L系列中断优先级设置问题的解决方案

[复制链接]
5593|36
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 FSL_TICS_A 于 2014-3-25 17:06 编辑

关于Kinetis L系列中断优先级设置问题的解决方案
最近在调试Kinties L系列的时候,使用官方例程中arm_cm0.c,使用其中的void set_irq_priority (int irq, int prio)函数设置了中断优先级,然后仿真的时候,在寄存器窗口发现NVIC_IPRx寄存器的值并没有改变,然后查看寄存器具体的地址的内存发现也没有改变, 后来将NVIC_IPRx寄存器地址的值赋给一个变量,然后使用printf将该变量打印出来,发现第一次能够打印正确的值,但是连续第二次打印,值又变为了0.当时感觉很奇怪,然后仔细阅读了下ARM Cortex-M0的内核文档:The Definitive Guide to the ARM cortex M0.pdf.
发现对于中断优先级的操作,和ARM Cortex-M4还是有区别的:主要在于对于M0+内核的NVIC_IPRx寄存器,每次操作都是一组32位操作,若要改变寄存器的值,首先先要读出相应的值,然后改变一个字节,再将值写回到原来的地址上。
M0内核文档是这么讲的:
1
M4内核就不一样,是可以字节操作的,这点在M4的内核文档上也可以找到。
所以,我认为,原来arm_cm0.cset_irq_priority (int irq, int prio)函数不能实现优先级正确设置的原因之一,是由于采用了8位操作的方式如下:
uint8 *prio_reg;
prio_reg = (uint8 *)((uint32)&NVIC_IP(div));
*prio_reg = ( (prio&0x3) << (8 - ARM_INTERRUPT_LEVEL_BITS) );  
定义需要修改为:
uint32 *prio_reg;
prio_reg = (unsigned long *)((uint32)&NVIC_IP(div));//div
第二,从原来的代码可以看出,并不能准确的实现具体irq的定位与值的修改。
假设我们需要设置:  set_irq_priority(17, 3);
可以看出,上面错误的代码只能实现irq=16值的修改,原因其只是定位到了NVIC_IPR4中的低字节,而没有在IPR44个字节做偏移,所以只能修改irq=16的优先级
根据我们的reference manual可以知道,在每组IPR中,具体定位IRQ,可以通过8*(IRQ mod 4)+6的方法,注意mod是取余数,程序中是“%”,不要理解为“/”.
综合上面两点,我将set_irq_priority函数修改如下:
void set_irq_priority (int irq, int prio)
{   
    /*irq priority pointer*/
    uint8 *prio_reg;
    uint8 err = 0;
    uint8 div = 0;
    uint32 temp=0;
    uint32 *prio_reg1;
    /* Make sure that the IRQ is an allowable number. Right now up to 32 is
     * used.
     *
     * NOTE: If you are using the interrupt definitions from the header
     * file, you MUST SUBTRACT 16!!!
     */
    if (irq > 32)
    {
        printf("\nERR! Invalid IRQ value passed to priority irq function!\n");
        err = 1;
    }
    if (prio > 3)
    {
        printf("\nERR! Invalid priority value passed to priority irq function!\n");
        err = 1;
    }

    if (err != 1)
    {
        /* Determine which of the NVICIPx corresponds to the irq */
        div = irq / 4;
        prio_reg1 = (unsigned long *)((uint32)&NVIC_IP(div));//div
        *prio_reg1 = ( (prio&0x3) << ((8 - ARM_INTERRUPT_LEVEL_BITS) + 8*(irq%4)));
    }
}
同样以set_irq_priority(17, 3);为例,使用CW测试的结果如下:

图 2

图3
可以看到,结果已经成功改变。
希望该经验能够帮到大家。
附件为修改后的arm_cm0.c
游客,如果您要查看本帖隐藏内容请回复

相关帖子

沙发
FSL_TICS_ZJJ|  楼主 | 2014-3-20 10:55 | 只看该作者
不足之处,欢迎大家指正。

使用特权

评论回复
板凳
FSL_TICS_Robin| | 2014-3-20 10:59 | 只看该作者
感谢ZJJ分享的相关经验!
如果大家的程序涉及到中断优先级设置,可以参考着操作一下。

使用特权

评论回复
地板
朝阳之光| | 2014-3-20 11:53 | 只看该作者
好东西

使用特权

评论回复
5
xinyinxing| | 2014-4-15 14:48 | 只看该作者
感谢楼主的经验分享!支持!

使用特权

评论回复
6
870205766| | 2014-5-11 14:13 | 只看该作者

使用特权

评论回复
7
fyzhuhui| | 2014-6-8 20:47 | 只看该作者
这个有点小复杂。

使用特权

评论回复
8
FSL_TICS_Robin| | 2014-6-9 10:19 | 只看该作者
fyzhuhui 发表于 2014-6-8 20:47
这个有点小复杂。

修改中断优先级是程序复杂后都会遇到的,所以如果各位使用L系列可以学习一下。

使用特权

评论回复
9
chenjinst| | 2014-8-8 11:10 | 只看该作者
看看。。。。。。。。。。。。。。。。。。。。

使用特权

评论回复
10
蓝水天下| | 2014-8-11 13:32 | 只看该作者
谢谢,下载下来留着备用

使用特权

评论回复
11
luofeng2g| | 2014-9-10 11:05 | 只看该作者
好东西,正愁怎么配置!!

使用特权

评论回复
12
FSL_5353| | 2014-10-11 14:15 | 只看该作者
谢谢分享呀

使用特权

评论回复
13
zhangjinxi| | 2014-12-31 13:42 | 只看该作者
是开发商李开复老师开发拉绍克法律

使用特权

评论回复
14
KSCS_KSCS| | 2015-1-20 15:38 | 只看该作者
学习一下

使用特权

评论回复
15
缘梦流星| | 2015-1-24 21:21 | 只看该作者
大神啊,多亏你

使用特权

评论回复
16
justperky| | 2015-1-25 19:58 | 只看该作者
多谢楼主分享

使用特权

评论回复
17
yang1zhao| | 2015-4-28 21:32 | 只看该作者
谢谢楼主大神的分享

使用特权

评论回复
18
sblpp| | 2015-5-4 07:45 | 只看该作者
谢谢分享!

使用特权

评论回复
19
Michael19941004| | 2015-6-13 22:49 | 只看该作者
很不错哦,,,

使用特权

评论回复
20
芙蓉洞| | 2015-6-15 09:26 | 只看该作者
下载下来认真学习一下

使用特权

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

本版积分规则

165

主题

5069

帖子

88

粉丝