将全局声明的缓冲区写入 FLASH 时出现 STM32 Hardfault 异常
STM32 Hardfault exception when writing globally declared buffer to FLASH
我正在尝试为 STM32F030x8 编写引导加载程序应用程序。我通过 UART 将 bin 文件写入控制器。当 UART RDR 寄存器上存在数据时,我将其放入全局声明的 1Kb 缓冲区中。每次缓冲区满时,我都试图将其写入 FLASH。写入 FLASH 后,应用程序向 PC 软件发出确认,准备接受新的 1Kb 块。因此,在访问以写入 FLASH 时不会写入缓冲区。当我尝试将全局缓冲区写入闪存时,应用程序进入 Hardfault 处理程序。
但是当我使用 memcpy() 将缓冲区复制到本地声明的 1Kb 缓冲区,并尝试将该缓冲区写入 FLASH 时,它没有任何问题。
为什么不能将全局声明的缓冲区直接写入FLASH?为什么本地声明的buffer写入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
}
}
请注意,该函数在 uint32_t
上运行,而您将其传递给 uint8_t
缓冲区。 ARM Cortex-M0 内核(在 STM32F0 中找到)不 支持未对齐访问,任何尝试这样做都会导致错误。
它只是巧合地适用于本地缓冲区 - 它与 4 字节边界对齐,而全局缓冲区则不然。如果对齐正确,它也可以与全局缓冲区一起使用 - 再次纯属巧合。
我正在尝试为 STM32F030x8 编写引导加载程序应用程序。我通过 UART 将 bin 文件写入控制器。当 UART RDR 寄存器上存在数据时,我将其放入全局声明的 1Kb 缓冲区中。每次缓冲区满时,我都试图将其写入 FLASH。写入 FLASH 后,应用程序向 PC 软件发出确认,准备接受新的 1Kb 块。因此,在访问以写入 FLASH 时不会写入缓冲区。当我尝试将全局缓冲区写入闪存时,应用程序进入 Hardfault 处理程序。
但是当我使用 memcpy() 将缓冲区复制到本地声明的 1Kb 缓冲区,并尝试将该缓冲区写入 FLASH 时,它没有任何问题。
为什么不能将全局声明的缓冲区直接写入FLASH?为什么本地声明的buffer写入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
}
}
请注意,该函数在 uint32_t
上运行,而您将其传递给 uint8_t
缓冲区。 ARM Cortex-M0 内核(在 STM32F0 中找到)不 支持未对齐访问,任何尝试这样做都会导致错误。
它只是巧合地适用于本地缓冲区 - 它与 4 字节边界对齐,而全局缓冲区则不然。如果对齐正确,它也可以与全局缓冲区一起使用 - 再次纯属巧合。