写入非易失性内存而不会破坏UART中断STM32F4XX上的执行



我在uart外围有几个超支错误,因为我一直在接收uart数据,而我的代码处于失速状态,因为我在flash 上执行写入操作。p>我正在使用UART中断,并在应用程序注释AN3969上进行了解释:

eeprom仿真固件从内部闪光灯运行,从而访问 闪光灯将在需要闪光擦除或 编程(EEPROM初始化,可变更新或页面擦除)。作为 结果,未执行应用程序代码,并且中断 无法服务。

对于许多应用程序,这种行为可能是可以接受的,但是 具有实时约束的应用程序,您需要运行关键 内部RAM的过程。

在这种情况下:

  1. 在内部RAM中重新放置向量表。
  2. 从内部RAM执行所有关键过程并中断服务例程。编译器提供了声明功能的关键字 作为RAM功能;该功能从闪光灯复制到RAM 系统启动就像任何初始化变量一样。重要的是要 请注意,对于RAM函数,所有使用的变量都称为 功能应在RAM内。

因此,我在互联网上搜索并找到了AN4808,该AN4808提供了有关如何在Flash操作时保持中断运行的示例。

我继续修改了我的代码:

链接脚本将向量表添加到SRAM并定义A .RAMFUNC Section

/* stm32f417.dld */
ENTRY(Reset_Handler)
MEMORY
{
    ccmram(xrw)       : ORIGIN = 0x10000000, LENGTH = 64k
    sram              : ORIGIN = 0x20000000, LENGTH = 112k
    eeprom_default    : ORIGIN = 0x08004008, LENGTH = 16376
    eeprom_s1         : ORIGIN = 0x08008000, LENGTH = 16k
    eeprom_s2         : ORIGIN = 0x0800C000, LENGTH = 16k
    flash_unused      : ORIGIN = 0x08010000, LENGTH = 64k
    flash             : ORIGIN = 0x08020000, LENGTH = 896k
}
_end_stack = 0x2001BFF0;
SECTIONS 
{
  . = ORIGIN(eeprom_default);
  .eeprom_data :
  {
    *(.eeprom_data)
  } >eeprom_default
  . = ORIGIN(flash);
  .vectors :
    {
        _load_vector = LOADADDR(.vectors);
        _start_vector = .;
        *(.vectors)
        _end_vector = .;
    } >sram AT >flash
    .text :
    {
        *(.text)
        *(.rodata)
        *(.rodata*)
        _end_text = .;
    } >flash
    .data : 
    {
        _load_data = LOADADDR(.data);
        . = ALIGN(4);
        _start_data = .;
        *(.data)
    } >sram AT >flash

    .ramfunc :
    {
        . = ALIGN(4);
        *(.ramfunc)
        *(.ramfunc.*)
        . = ALIGN(4);
        _end_data = .;
    } >sram AT >flash
    .ccmram :
    {
        _load_ccmram = LOADADDR(.ccmram);
        . = ALIGN(4);
        _start_ccmram = .;
        *(.ccmram)
        *(.ccmram*)
        . = ALIGN(4);
        _end_ccmram = .;
    } > ccmram AT >flash
    .bss :
    {
        _start_bss = .;
        *(.bss)
        _end_bss = .;
    } >sram
    . = ALIGN(4);
    _start_stack = .;

}
_end = .;
PROVIDE(end = .);

重置处理程序添加了矢量表复制SRAM并定义A .RAMFUNC SERCEMT

void Reset_Handler(void)
{
  unsigned int *src, *dst;
  /* Copy vector table from flash to RAM */
  src = &_load_vector;
  dst = &_start_vector;
  while (dst < &_end_vector)
    *dst++ = *src++;
  /* Copy data section from flash to RAM */
  src = &_load_data;
  dst = &_start_data;
  while (dst < &_end_data)
    *dst++ = *src++;
  /* Copy data section from flash to CCRAM */
  src = &_load_ccmram;
  dst = &_start_ccmram;
  while (dst < &_end_ccmram)
    *dst++ = *src++;
  /* Clear the bss section */
  dst = &_start_bss;
  while (dst < &_end_bss)
    *dst++ = 0;
  SystemInit();
  SystemCoreClockUpdate();
  RCC->AHB1ENR = 0xFFFFFFFF;
  RCC->AHB2ENR = 0xFFFFFFFF;
  RCC->AHB3ENR = 0xFFFFFFFF;
  RCC->APB1ENR = 0xFFFFFFFF;
  RCC->APB2ENR = 0xFFFFFFFF;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOFEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOIEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN;
  main();
  while(1);
}

system_stm32f4xxx.c: tocnected vect_tab_sram define

/*!< Uncomment the following line if you need to relocate your vector Table in
     Internal SRAM. */
#define VECT_TAB_SRAM
#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field. 
                                   This value must be a multiple of 0x200. */

添加了ramfunc的定义以设置部分属性:

#define RAMFUNC __attribute__ ((section (".ramfunc")))

在UART相关功能和原型之前添加ramfunc,因此它可以从RAM运行。

RAMFUNC void USART1_IRQHandler(void)
{
  uint32_t sr = USART1->SR;
  USART1->SR & USART_SR_ORE ? GPIO_SET(LED_ERROR_PORT, LED_ERROR_PIN_bp):GPIO_CLR(LED_ERROR_PORT, LED_ERROR_PIN_bp);
  if(sr & USART_SR_TXE)
  {
    if(uart_1_send_write_pos != uart_1_send_read_pos)
    {
      USART1->DR = uart_1_send_buffer[uart_1_send_read_pos];
      uart_1_send_read_pos = (uart_1_send_read_pos + 1) % USART_1_SEND_BUF_SIZE;
    }
    else
    {
      USART1->CR1 &= ~USART_CR1_TXEIE;
    }
  }
  if(sr & (USART_SR_RXNE | USART_SR_ORE)) 
  {
    USART1->SR &= ~(USART_SR_RXNE | USART_SR_ORE);
    uint8_t byte = USART1->DR;
    uart_1_recv_buffer[uart_1_recv_write_pos] = byte;
    uart_1_recv_write_pos = (uart_1_recv_write_pos + 1) % USART_1_RECV_BUF_SIZE;
  }
}

我的目标在RAM中使用矢量表和UART功能正确运行,但我仍然在USART上占据了超支。执行Flash Write操作时,我也不会破坏中断。

我还尝试从CCM RAM而不是SRAM运行代码,但是我在此邮政编码上看到的是在STMF32F4XX上的CCM RAM上执行的代码...

有什么想法吗?谢谢。

任何试图从闪存中读取时,在写操作正在进行时会导致公共汽车停滞不前。

为了不被Flash Writes阻止,我认为不仅是中断代码,而且中断功能也必须从RAM运行,否则核心将在可能的中断时无法进入状态。

>

尝试将闪存处理代码重新定位到RAM。

如果可能的话,我建议切换到具有两个独立的闪存库的MCU,例如PIN-和软件兼容的427/429/437/439系列。您可以将一家银行专用于程序代码,而将另一个银行专用于EEPROM状的数据存储,然后编写第二个银行不会打扰从第一银行运行的代码。

如建议,可能有必要从RAM执行代码;或者,请确保在进行写入时没有执行闪光读取操作。

要测试,您可能需要编译RAM的整个可执行文件,而不是闪存(即将所有内容都放入RAM而不是使用闪光灯)。

然后,您可以使用GDB加载二进制并开始执行...测试您的UART,并确保其正常工作。至少这样,您可以确定闪光灯未使用。

一些micros在编写部分同时执行多个操作时读取的部分。

相关内容

  • 没有找到相关文章

最新更新