搜索
bottom↓
回复: 13

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

[复制链接]

出0入0汤圆

发表于 2014-3-20 10:57:02 | 显示全部楼层 |阅读模式
本帖最后由 FSL_TICS_Robin 于 2014-7-18 13:54 编辑

关于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.c中set_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中的低字节,而没有在IPR4中4个字节做偏移,所以只能修改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





PS:本帖可从飞思卡尔版块置顶帖:飞思卡尔Kinetis资料大本营飞思卡尔论坛支持小组【经验分享】帖汇总链接进入。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2014-3-20 10:59:24 | 显示全部楼层
不足之处,欢迎大家指正。

出0入0汤圆

发表于 2014-3-20 12:20:10 来自手机 | 显示全部楼层
KL系列总共有四个优先级,0-3,0为最高优先级,在ARM CMSIS里面提供了设置中断优先级的接口函数。

出0入0汤圆

发表于 2014-3-20 12:23:54 来自手机 | 显示全部楼层
函数名为NVIC_SetPriority,比如设置PORTD外部中断为最高优先级,NVIC_SetPriority(PORTD_IRQn, 0);

出0入0汤圆

发表于 2014-3-20 14:03:17 | 显示全部楼层
这个到时没有注意!感谢经验分享。

出0入0汤圆

发表于 2014-3-26 15:18:26 | 显示全部楼层
这是arm捣鬼?

出0入0汤圆

发表于 2014-3-26 20:35:42 | 显示全部楼层
谢谢分享,希望早点出Kinetis SDK.

出0入0汤圆

发表于 2014-3-26 20:38:05 | 显示全部楼层
不是为操作,就只能读修改写了

出0入0汤圆

发表于 2014-3-26 21:06:54 | 显示全部楼层
能否贴一个关于L系列的外部中断的示例来分享,谢谢

出0入0汤圆

发表于 2014-3-27 16:47:16 | 显示全部楼层
支持中断嵌套吗

出0入4汤圆

发表于 2014-4-22 22:53:23 | 显示全部楼层
学习下中断   

出0入0汤圆

发表于 2014-6-3 16:30:28 | 显示全部楼层
asdad sasa

出0入0汤圆

发表于 2014-6-11 10:35:35 | 显示全部楼层
支持中断嵌套吗

出0入0汤圆

发表于 2014-12-5 14:16:12 | 显示全部楼层
谢谢楼主分享!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 05:25

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表