将全局声明的缓冲区写入FLASH时出现STM32 Hardfault异常

Ber*_*ano 1 c stm32 flash-memory bootloader stm32f0

我正在尝试为STM32F030x8编写一个bootloader应用程序.我通过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);
}
Run Code Online (Sandbox Code Playgroud)

当此函数进入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];
Run Code Online (Sandbox Code Playgroud)

在缓冲区收到事件:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

Fre*_*pin 6

请注意uint32_t,当您向其传递uint8_t缓冲区时,该函数会运行.ARM的Cortex-M0内核(如STM32F0发现)不支持未对齐访问的任何企图这样做会导致故障.

它仅适用于局部缓冲区 - 它与4字节边界对齐,而全局缓冲区则没有.如果它正确对齐,它也可以与全局缓冲区一起使用 - 再次纯粹的巧合.