首页 文章

配置优先级位分配后如何诊断不精确的总线故障,Cortex M3 STM32F10x w uC / OS-III

提问于
浏览
1

我在为ST Microelectronics STM32F103(ARM Cortex-M3 r1p1)编写的应用程序中遇到了问题 . RTOS是uC / OS-III;开发环境是IAR EWARM v.6.44;它还使用ST标准外设库v.1.0.1 .

该应用程序不是新的;它已经在开发和现场至少一年 . 它使用两个UART,I2C和一个或两个定时器 . 最近我决定审查中断优先级分配,并重新安排优先级作为审查的一部分(事情似乎工作得很好) .

我发现在初始化代码中没有显式分配组和子优先级位,包括RTOS,因此为了使应用程序与另一个应用程序(相同的产品,不同的处理器)和新的优先级方案保持一致,我添加了调用NVIC_PriorityGroupConfig(),传入NVIC_PriorityGroup_2 . 这将应用程序中断和复位控制寄存器(AIRCR)中的PRIGROUP值设置为5,为组(抢占)优先级分配2位,为子优先级分配2位 .

执行此操作后,我在执行时得到一个不精确的总线故障异常,不是立即,而是很快 . (更多关于我怀疑它何时发生的地方 . )因为它在BFAR中没有任何用处(BFSR.BFARVALID清除) .

STM32F系列组实现4位优先级 . 虽然我没有在任何地方明确提到这一点,但它显然是优先考虑的最重要的游戏 . 这个假设似乎通过文档中给出的PRIGROUP表进行了验证(第134页,STM32F10xxx / 20xxx / 21xxx / L1xxx Cortex-M3编程手册(Doc 15491,Rev 5),第4.4.5节,应用程序中断和控制寄存器( SCB_AIRCR),表45,优先级分组,第134页) .

在ARM方案中,优先级值包括一定数量的组或抢占优先级位和一些子优先级位 . 组优先级位是高位;次优先级较低 . 3位AIRCR.PRIGROUP值控制如何定义每个位的分配 . PRIGROUP = 0配置7位组优先级和1位子优先级; PRIGROUP = 7配置0位组优先级和8位子优先级(因此优先级都是子优先级,并且对于具有可设置优先级的异常不会发生抢占) .

AIRCR.PRIGROUP的重置值定义为0 .

对于STM32F10x,由于只实现了高4位,因此看起来PRIGROUP = 0,1,2,3应该都是等价的,因为它们都对应于> = 4位的组优先级 .

鉴于该假设,我还尝试使用值NVIC_PriorityGroup_4调用NVIC_PriorityGroupConfig(),其对应于PRIGROUP值3(4位组优先级,无子优先级) .

此更改还会导致总线故障异常 .

不幸的是,我相信STM32F103是r1p1,因此没有实现辅助控制寄存器(ACTLR;在r2p0中引入),因此我无法尝试DISDEFWBUF位(在默认存储器映射访问期间禁止使用写缓冲区) ,以降低性能为代价,使所有总线故障变得精确) .

我几乎可以肯定,ISR中发生了总线故障,很可能是在UART ISR中 . 我在代码中的某个特定位置设置了一个断点,启动了应用程序,并在执行到达断点之前发生了总线故障;但是,如果我在调试器中单步执行代码,我可以到达并超过该断点的位置,如果我允许它从那里执行,我会在继续之后看到总线故障一段时间 .

下一步将尝试确定ISR产生总线故障的原因,以便我可以检测它和/或尝试捕获它的调用并逐步完成它 .

所以我的问题是:

1) Anyone have any suggestions as to how to go about identifying the origin of imprecise bus fault exceptions more intelligently?

2) Why would setting PRIGROUP = 3 change the behavior of the system when PRIGROUP = 0 is the reset default? (PRIGROUP = 0表示7位组,1位子优先级; PRIGROUP = 3表示4位组,4位子优先级; STM32F10x仅实现高4位优先级 . )

很多,非常感谢所有人提前获得任何见解或非空指针!

(当然,如果我事先弄明白的话,我会用任何可能对其他人遇到相同情况的信息更新这篇文章 . )

1 回答

  • 1

    Even if BFAR is not valid, you can still read other related registers within your bus-fault ISR:

    void HardFault_Handler_C(unsigned int* hardfault_args)
    {
        printf("R0    = 0x%.8X\r\n",hardfault_args[0]);         
        printf("R1    = 0x%.8X\r\n",hardfault_args[1]);         
        printf("R2    = 0x%.8X\r\n",hardfault_args[2]);         
        printf("R3    = 0x%.8X\r\n",hardfault_args[3]);         
        printf("R12   = 0x%.8X\r\n",hardfault_args[4]);         
        printf("LR    = 0x%.8X\r\n",hardfault_args[5]);         
        printf("PC    = 0x%.8X\r\n",hardfault_args[6]);         
        printf("PSR   = 0x%.8X\r\n",hardfault_args[7]);         
        printf("BFAR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED38);
        printf("CFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED28);
        printf("HFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED2C);
        printf("DFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED30);
        printf("AFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED3C);
        printf("SHCSR = 0x%.8X\r\n",SCB->SHCSR);                
        while (1);
    }
    

    如果在执行此特定硬故障中断时无法在执行时使用 printf ,则将所有上述数据保存在全局缓冲区中,以便在到达 while (1) 后查看 .

    以下是如何连接它的完整说明ISR到中断向量(虽然我从你的问题中了解到,你已经实现了它):

    Jumping from one firmware to another in MCU internal FLASH

    您可以在以下内容的基础上找到更多信息:

    http://www.keil.com/appnotes/files/apnt209.pdf

相关问题