ST意法半导体
直播中

王超

7年用户 1305经验值
私信 关注
[问答]

为什么我的STM32H742在DCMI使用DMA接收后运行在HardFault中?

对于我的硕士论文,我正在尝试使用 STM32H742 通过 DCMI 接收数据。作为图像传感器,我使用的是 NOIV2SN1300A。它通过 10 条数据线发送数据,这些数据不同(因此并不总是 `0xA603A603`)。为了减少数据大小,我激活了分箱和子采样。
我正在使用 DMA 将 DCMI 接收到的数据传输到地址为“0x24000000”的内部 SRAM 中。在我收到全部数据后,即我设置的整个数据长度(“0xA603A603”数据),uC 进入硬故障和无限循环。我不确定为什么会出现此错误。这是我的 DMA 和 DCMI 配置:
```
hdcmi.Instance = DCMI;
hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_RISING;
hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH;
hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_HIGH;
hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_10B;
hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
hdcmi.Init.ByteSelectMode = DCMI_BSM_ALL;
hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD;
hdcmi.Init.LineSelectMode = DCMI_LSM_ALL;
hdcmi.Init.LineSelectStart = DCMI_OELS_ODD;
如果(HAL_DCMI_Init(&hdcmi)!= HAL_OK)
{
   错误处理程序();
}
/*
  * 为 DCMI 启用所有中断
  */
HAL_NVIC_SetPriority(DCMI_IT_OVR, 1, 0);
HAL_NVIC_EnableIRQ(DCMI_IT_OVR);
HAL_NVIC_SetPriority(DCMI_IT_VSYNC, 1, 0);
HAL_NVIC_EnableIRQ(DCMI_IT_VSYNC);
HAL_NVIC_SetPriority(DCMI_IT_LINE, 1, 0);
HAL_NVIC_EnableIRQ(DCMI_IT_LINE);
HAL_NVIC_SetPriority(DCMI_IT_FRAME, 1, 0);
HAL_NVIC_EnableIRQ(DCMI_IT_FRAME);
HAL_NVIC_SetPriority(DCMI_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DCMI_IRQn);
/*
  * 为 DMA1_Stream0 启用中断
  */
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn);
```
```
hdcmi.Instance = DCMI;
hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;
hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_FALLING; //去做:???
hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_HIGH;
hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_HIGH;
hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_10B;
hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
hdcmi.Init.ByteSelectMode = DCMI_BSM_OTHER;//DCMI_BSM_ALL;
hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD;
hdcmi.Init.LineSelectMode = DCMI_LSM_ALL;
hdcmi.Init.LineSelectStart = DCMI_OELS_ODD;
如果(HAL_DCMI_Init(&hdcmi)!= HAL_OK)
{
  错误处理程序();
}
```
```
uint32_t DataSizeImageSensor = 0xB160;
```
```
DMA_BUFFER uint32_t AddressFrameBuffer[0x1620C];
```
```
HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t)AddressFrameBuffer, DataSizeImageSensor);
```
```
void MPU_Config (void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* 禁用 MPU */
HAL_MPU_Disable();
/* 配置 SDRAM 的 MPU 属性 */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE; //Cache 与 CPU 的 DMA 使用不一致
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCtiON_ACCESS_DISABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* 启用 MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
```
知道为什么会发生此错误吗?就像我说的,我收到数据,我确信传感器发送了可行的数据(所以还有其他东西然后是“0xA603A603”),但我在硬故障之前只通过 DCMI 获得了相同的数据。在此当前设置中,我收到了所有数据,并且数据按预期位于缓冲区中。但是在最后一次写入缓冲区之后,硬故障就发生了。
此外,我禁用了 SRAM1 的缓存,因为缓存/DMA/CPU 一致性存在问题。我不太确定如何继续,因为在我看来这是一个设置错误。可能被 DCMI 超限了?
注意:上面的代码实际上并没有按此顺序出现。那只是相关部分(至少从我期望的相关部分来看)。
我找到了关于这个问题的其他帖子,错误是系统时钟慢。由于我的系统时钟是 475 MHz,而 HCLK3 时钟(DCMI 用于采样)是 237.5 MHz,我可以排除时钟问题。数据表说 HCLK 时钟必须比 DCMI 时钟快 2.5 倍(由 62 Mhz 的图像传感器设置)。
此外,我实施了一个硬故障处理程序,它提供了有关错误的更多信息。按照这个https://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/。问题是,没有设置任何寄存器(因此没有 BusFault 寄存器或类似的东西)。STMCubeIDE 的故障分析器也表示未检测到故障。
此外,我的 DCMI 或 DMA 中断都没有被调用。至少我的断点都没有被输入那里。这对我来说有点奇怪。









回帖(1)

余少虹

2023-1-29 10:56:32
找到了解决方案。这是我为 DCMI 激活的中断,但是我使用 DCMI 的模式不允许中断
举报

更多回帖

发帖
×
20
完善资料,
赚取积分