繁体   English   中英

尝试读取STM32F4上未对齐的DMA寄存器地址时发生硬故障

[英]Hardfault when attempting to read unaligned DMA register address on STM32F4

我正在STM32F4上实现外设转储。 我正在读取大多数外设寄存器,并逐字节读取并通过UART接口对其进行刷新。 它几乎适用于所有外围设备。

当我尝试逐字节读取DMA1(0x40026000 ...)或DMA2(0x40026400 ...)寄存器时它在0x40026401处出现精确的总线错误而失败。

当我尝试将其读取为4字节字对齐时,它可以正常工作。

我的问题是:为什么它不能在DMA上失败,而所有其他外设(如SCB,RCC,SPI,UART,TIM等)都允许我这样做? 有什么具体原因吗?

我的猜测是CPU和DMA控制器之间的总线仅允许32位访问操作。

您可以从硬故障中断内部进行打印(或转储到内存)。

您需要打印(或转储)的是CPU寄存器,尤其是那些可以更好地指示问题原因的寄存器。

例如:

void HardFault_Handler(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);
}

或者,您可以仅在硬故障中断中停止,然后在IDE中查看这些寄存器...

从STM32F4数据表中:

The MPU attributes don't affect DMA data accesses to the memory/peripherals address
spaces. therefore, in order to protect the memory areas against inadvertent DMA accesses,
the MPU must control the SW/CPU access to the DMA registers.

因此,似乎在访问DMA寄存器方面存在一些限制。


根据PaulR的评论,OP扩展了答案:

文档挖掘证实了原因是DMA AHB从站编程接口的限制。

在DM00031020的第10.2DMA主要功能中,它被清楚地写成“仅支持32位访问的AHB从站编程接口”。 相反,例如DMA2D支持8位,16位和32位访问,因此可以逐字节访问并且不会引起总线故障。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM