尝试读取STM32F4上未对齐的DMA寄存器地址时的硬错误

时间:2017-11-22 16:21:09

标签: c arm stm32 dma

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

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

当我尝试将其与4字节单词对齐时,它可以正常工作。

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

1 个答案:

答案 0 :(得分:1)

我的猜测是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.2 DMA主要功能中,它清楚地写着“仅支持32位访问的AHB从编程接口”。相反,例如, DMA2D支持8位,16位和32位访问,因此可以逐字节访问,不会导致总线故障。