最近在调试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内核文档是这么讲的:
[size=0.83em]1.jpg (62.66 KB, 下载次数: 0)
下载附件
[color=rgb(153, 153, 153) !important]2014-3-20 10:49 上传
0
|
|
|
|
而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.jpg (59.17 KB, 下载次数: 0)
3.jpg (48.79 KB, 下载次数: 0)
|
|
|
|
|
|
|