将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常
Posted
技术标签:
【中文标题】将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常【英文标题】:STM32 Hardfault exception when writing globally declared buffer to FLASH 【发布时间】:2017-06-13 00:49:30 【问题描述】:我正在尝试为 STM32F030x8 编写引导加载程序应用程序。我通过UART将bin文件写入控制器。当 UART RDR 寄存器上存在数据时,我将其放入全局声明的 1Kb 缓冲区中。每次缓冲区已满时,我都会尝试将其写入 FLASH。写入 FLASH 后,应用程序向 PC 软件发出确认,并准备好接受新的 1Kb 块。因此,在访问写入 FLASH 时不会写入缓冲区。当我尝试将全局缓冲区写入 FLASH 时,应用程序进入 Hardfault 处理程序。
但是当我使用 memcpy() 将缓冲区复制到本地声明的 1Kb 缓冲区中,并尝试将该缓冲区写入 FLASH 时,它没有任何问题。
为什么我不能只将全局声明的缓冲区权限写入 FLASH?为什么本地声明的缓冲区写入FLASH没有问题?
提前致谢!
编辑:
uint32_t FLASH_If_Write(__IO uint32_t* FlashAddress, uint32_t* Data ,uint16_t DataLength)
uint32_t i = 0;
for (i = 0; (i < DataLength) && (*FlashAddress <= (USER_FLASH_END_ADDRESS-4)); i++)
/* the operation will be done by word */
if (FLASH_Program(FLASH_TYPEPROGRAM_WORD, *FlashAddress, *(uint32_t*)(Data+i)) == 1)
/* Check the written value */
if (*(uint32_t*)*FlashAddress != *(uint32_t*)(Data+i))
/* Flash content doesn't match SRAM content */
return(2);
/* Increment FLASH destination address */
*FlashAddress += 4;
else
/* Error occurred while writing data in Flash memory */
return (1);
return (0);
这个函数进入for循环时似乎发生了Hardfault。
当发生硬故障异常时,LR 寄存器为 0xFFFFFFF9,SP = 0x200011E8
奇怪的是,在 for 循环中,没有对缓冲区的任何引用,因此实际上从未访问过它。但是当缓冲区被复制到本地时它确实有效。我在这里错过了什么?
编辑 2:
全局声明的缓冲区:
in globals.c:
uint8_t rec_buffer_uart1[REC_BUFFER_SIZE] = 0;
uint8_t send_buffer_uart1[SEND_BUFFER_SIZE] = 0;
in globals.h:
#define REC_BUFFER_SIZE 1029
extern uint8_t rec_buffer_uart1[REC_BUFFER_SIZE];
#define SEND_BUFFER_SIZE 1031
extern uint8_t send_buffer_uart1[SEND_BUFFER_SIZE];
缓冲区收到事件:
uint32_t flashdestination = APPLICATION_ADDRESS;
uint8_t *buf_ptr = &buf; // buf is locally declared buffer
// every time buffer is full:
memcpy(buf_ptr, &rec_buffer_uart1[3], 1024);
// works:
ramsource = (uint32_t)&buf;
// generates Hardfault:
ramsource = (uint32_t)&rec_buffer_uart1[3];
/* Write received data in Flash */
if (FLASH_If_Write(&flashdestination, (uint32_t*) ramsource , (uint16_t) 1024/4) == 0)
// send acknowledge
【问题讨论】:
您是否将硬故障作为复制操作的直接结果?或者是否可能有一个调度程序(即操作系统)作为您的 SW 的一部分,它可能切换到其他线程,然后导致硬故障?事实上,即使没有操作系统,硬故障是否可能发生在您的一个硬件中断处理程序 (ISR) 中?我建议您在硬故障中断处理程序中放置一个断点,并检查 PC 和 LR 的值,以确保这一点。此外,您可能需要检查其他寄存器的 STM 规范,这可能会为您提供有关问题根源的更多信息。 显示完整代码 - 如何声明缓冲区、如何将其传递给函数、如何使用它。 顺便说一句-您显示的功能的代码完全是一派胡言。如果这段代码来自 ST 也不足为奇,因为整个 HAL/SPL 表明他们对正确的软件开发一无所知。 感谢您的回复。添加代码。 另外,你能解释一下为什么这段代码是废话吗?这是我从 HAL 库复制到我自己的库中的函数。 【参考方案1】:请注意,该函数在uint32_t
上运行,而您将uint8_t
缓冲区传递给它。 ARM Cortex-M0 内核(在 STM32F0 中找到)确实不支持非对齐访问,任何尝试这样做都会导致错误。
它只是巧合地适用于本地缓冲区 - 它与 4 字节边界对齐,而全局缓冲区则不是。如果它正确对齐,它也可以与全局缓冲区一起使用 - 再次纯属巧合。
【讨论】:
所以如果我理解正确的话,我必须声明一个包含 256 个条目的 uint32_t 缓冲区,编写一些代码将 uint8_t 缓冲区复制到其中,然后传递 uint32_t 缓冲区? @BertVano 这是一种可能性,是的。或者你可以在你的 UART 中断中使用这个 uint32_t 缓冲区来避免复制。 感谢您的帮助! 嘿。修复了我在 SMT32F765(M7 内核)上的问题以上是关于将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常的主要内容,如果未能解决你的问题,请参考以下文章