代码之家  ›  专栏  ›  技术社区  ›  jedzej

试图读取STM32F4上未对齐的DMA寄存器地址时出现硬故障

  •  0
  • jedzej  · 技术社区  · 7 年前

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

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

    当我试着按照4字节的单词来读的时候,它很好用。

    我的问题是:为什么它在DMA上失败,而所有其他外围设备,如SCB、RCC、SPI、UART、TIM和其他允许我这么做?有什么具体原因吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   jedzej    7 年前

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

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

    例如:

    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位访问,因此可以逐字节访问,不会导致总线故障。