[英]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.2章DMA主要功能中,它被清楚地写成“仅支持32位访问的AHB从站编程接口”。 相反,例如DMA2D支持8位,16位和32位访问,因此可以逐字节访问并且不会引起总线故障。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.